diff --git a/Userland/Libraries/LibUnicode/Locale.cpp b/Userland/Libraries/LibUnicode/Locale.cpp index e1714299ae7..b1ef307aed4 100644 --- a/Userland/Libraries/LibUnicode/Locale.cpp +++ b/Userland/Libraries/LibUnicode/Locale.cpp @@ -843,6 +843,52 @@ Optional add_likely_subtags([[maybe_unused]] LanguageID const& langu #endif } +Optional 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 language, Optional script, Optional region) -> Optional { + 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(' '); diff --git a/Userland/Libraries/LibUnicode/Locale.h b/Userland/Libraries/LibUnicode/Locale.h index 08498026aec..c1ad4588074 100644 --- a/Userland/Libraries/LibUnicode/Locale.h +++ b/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 language {}; @@ -131,6 +132,7 @@ Optional resolve_variant_alias(StringView variant); Optional resolve_subdivision_alias(StringView subdivision); Optional add_likely_subtags(LanguageID const& language_id); +Optional remove_likely_subtags(LanguageID const& language_id); String resolve_most_likely_territory(LanguageID const& language_id, StringView territory_alias); }