Переглянути джерело

LibUnicode: Implement the Remove Likely Subtags method

Unlike Add Likely Subtags, this method doesn't require generated data.
Instead, it is defined in terms of Add Likely Subtags.
Timothy Flynn 3 роки тому
батько
коміт
a77f323dfb

+ 46 - 0
Userland/Libraries/LibUnicode/Locale.cpp

@@ -843,6 +843,52 @@ Optional<LanguageID> add_likely_subtags([[maybe_unused]] LanguageID const& langu
 #endif
 }
 
+Optional<LanguageID> remove_likely_subtags([[maybe_unused]] LanguageID const& language_id)
+{
+#if ENABLE_UNICODE_DATA
+    // https://www.unicode.org/reports/tr35/#Likely_Subtags
+    auto return_language_and_variants = [](auto language, auto variants) {
+        language.variants = move(variants);
+        return language;
+    };
+
+    // 1. First get max = AddLikelySubtags(inputLocale). If an error is signaled, return it.
+    auto maximized = add_likely_subtags(language_id);
+    if (!maximized.has_value())
+        return {};
+
+    // 2. Remove the variants from max.
+    auto variants = move(maximized->variants);
+
+    // 3. Get the components of the max (languagemax, scriptmax, regionmax).
+    auto language_max = maximized->language;
+    auto script_max = maximized->script;
+    auto region_max = maximized->region;
+
+    // 4. Then for trial in {languagemax, languagemax_regionmax, languagemax_scriptmax}:
+    //    If AddLikelySubtags(trial) = max, then return trial + variants.
+    auto run_trial = [&](Optional<String> language, Optional<String> script, Optional<String> region) -> Optional<LanguageID> {
+        LanguageID trial { .language = move(language), .script = move(script), .region = move(region) };
+
+        if (add_likely_subtags(trial) == maximized)
+            return return_language_and_variants(move(trial), move(variants));
+        return {};
+    };
+
+    if (auto trial = run_trial(language_max, {}, {}); trial.has_value())
+        return trial;
+    if (auto trial = run_trial(language_max, {}, region_max); trial.has_value())
+        return trial;
+    if (auto trial = run_trial(language_max, script_max, {}); trial.has_value())
+        return trial;
+
+    // 5. If you do not get a match, return max + variants.
+    return return_language_and_variants(maximized.release_value(), move(variants));
+#else
+    return {};
+#endif
+}
+
 String resolve_most_likely_territory([[maybe_unused]] LanguageID const& language_id, StringView territory_alias)
 {
     auto aliases = territory_alias.split_view(' ');

+ 2 - 0
Userland/Libraries/LibUnicode/Locale.h

@@ -18,6 +18,7 @@ namespace Unicode {
 
 struct LanguageID {
     String to_string() const;
+    bool operator==(LanguageID const&) const = default;
 
     bool is_root { false };
     Optional<String> language {};
@@ -131,6 +132,7 @@ Optional<StringView> resolve_variant_alias(StringView variant);
 Optional<StringView> resolve_subdivision_alias(StringView subdivision);
 
 Optional<LanguageID> add_likely_subtags(LanguageID const& language_id);
+Optional<LanguageID> remove_likely_subtags(LanguageID const& language_id);
 String resolve_most_likely_territory(LanguageID const& language_id, StringView territory_alias);
 
 }