diff --git a/frameworks/intl/include/locale_config.h b/frameworks/intl/include/locale_config.h index 6a1bdf03a62380b41f0377c17f341995a3a36ee7..ec53a85a055f9e2a5884e5d9af5e9c78b0d3feec 100644 --- a/frameworks/intl/include/locale_config.h +++ b/frameworks/intl/include/locale_config.h @@ -60,19 +60,26 @@ private: static constexpr int CONFIG_LEN = 128; static const char *SUPPORTED_LOCALES_NAME; static const char *SUPPORTED_REGIONS_NAME; - static const char *WHITE_LANGUAGE_NAME; - static const char *WHILTE_LANGUAGES_PATH; + static const char *WHITE_LANGUAGES_NAME; + static const char *WHITE_LANGUAGES_PATH; + static const char *FORBIDDEN_REGIONS_PATH; + static const char *FORBIDDEN_REGIONS_NAME; + static const char *FORBIDDEN_LANGUAGES_PATH; + static const char *FORBIDDEN_LANGUAGES_NAME; static const std::unordered_set& GetSupportedLocales(); static const std::unordered_set& GetForbiddenRegions(); static const std::unordered_set& GetSupportedRegions(); static void GetCountriesFromSim(std::vector &simCountries); - static void GetRelatedLocales(std::unordered_set &relatedLocales); + static void GetRelatedLocales(std::unordered_set &relatedLocales, + const std::vector countries); static std::string GetRegionChangeLocale(const std::string &languageTag, const std::string ®ion); static void GetListFromFile(const char *path, const char *resourceName, std::unordered_set &ret); + static void Expunge(std::unordered_set &src, const std::unordered_set &another); + static std::string GetMainLanguage(const std::string &language); static std::unordered_set supportedLocales; - static std::unordered_set forbiddenRegions; static std::unordered_set supportedRegions; static std::unordered_set whiteLanguages; + static std::unordered_map dialectMap; static bool listsInitialized; static bool InitializeLists(); }; diff --git a/frameworks/intl/src/locale_config.cpp b/frameworks/intl/src/locale_config.cpp index 5c024ea943b9a44562fb8dfdea9180e045e68f85..bafa32c59a1ffa8dd0d370796c356c16d23d00ab 100644 --- a/frameworks/intl/src/locale_config.cpp +++ b/frameworks/intl/src/locale_config.cpp @@ -16,7 +16,6 @@ #include #include #include "locale_config.h" -#include "core_manager.h" #include "libxml/parser.h" #include "locale_info.h" #include "localebuilder.h" @@ -40,14 +39,43 @@ const char *LocaleConfig::DEFAULT_LANGUAGE = "zh-Hans"; const char *LocaleConfig::DEFAULT_REGION = "CN"; const char *LocaleConfig::SUPPORTED_LOCALES_NAME = "supported_locales"; const char *LocaleConfig::SUPPORTED_REGIONS_NAME = "supported_regions"; -const char *LocaleConfig::WHITE_LANGUAGE_NAME = "white_language"; +const char *LocaleConfig::WHITE_LANGUAGES_NAME = "white_languages"; +const char *LocaleConfig::FORBIDDEN_LANGUAGES_NAME = "forbidden_languages"; +const char *LocaleConfig::FORBIDDEN_REGIONS_NAME = "forbidden_regions"; +const char *LocaleConfig::FORBIDDEN_LANGUAGES_PATH = "/system/usr/ohos_locale_config/forbidden_languages.xml"; +const char *LocaleConfig::FORBIDDEN_REGIONS_PATH = "/system/usr/ohos_locale_config/forbidden_regions.xml"; const char *LocaleConfig::SUPPORTED_LOCALES_PATH = "/system/usr/ohos_locale_config/supported_locales.xml"; const char *LocaleConfig::SUPPORTED_REGIONS_PATH = "/system/usr/ohos_locale_config/supported_regions.xml"; -const char *LocaleConfig::WHILTE_LANGUAGES_PATH = "/system/usr/ohos_locale_config/white_languages.xml"; -unordered_set LocaleConfig::forbiddenRegions; +const char *LocaleConfig::WHITE_LANGUAGES_PATH = "/system/usr/ohos_locale_config/white_languages.xml"; unordered_set LocaleConfig::supportedLocales; unordered_set LocaleConfig::supportedRegions; unordered_set LocaleConfig::whiteLanguages; +unordered_map LocaleConfig::dialectMap { + { "es-Latn-419", "es-Latn-419" }, + { "es-Latn-BO", "es-Latn-419" }, + { "es-Latn-BR", "es-Latn-419" }, + { "es-Latn-BZ", "es-Latn-419" }, + { "es-Latn-CL", "es-Latn-419" }, + { "es-Latn-CO", "es-Latn-419" }, + { "es-Latn-CR", "es-Latn-419" }, + { "es-Latn-CU", "es-Latn-419" }, + { "es-Latn-DO", "es-Latn-419" }, + { "es-Latn-EC", "es-Latn-419" }, + { "es-Latn-GT", "es-Latn-419" }, + { "es-Latn-HN", "es-Latn-419" }, + { "es-Latn-MX", "es-Latn-419" }, + { "es-Latn-NI", "es-Latn-419" }, + { "es-Latn-PA", "es-Latn-419" }, + { "es-Latn-PE", "es-Latn-419" }, + { "es-Latn-PR", "es-Latn-419" }, + { "es-Latn-PY", "es-Latn-419" }, + { "es-Latn-SV", "es-Latn-419" }, + { "es-Latn-US", "es-Latn-419" }, + { "es-Latn-UY", "es-Latn-419" }, + { "es-Latn-VE", "es-Latn-419" }, + { "pt-Latn-PT", "pt-Latn-PT" }, + { "en-Latn-US", "en-Latn-US" } +}; bool LocaleConfig::listsInitialized = LocaleConfig::InitializeLists(); @@ -88,7 +116,7 @@ string LocaleConfig::GetSystemLocale() bool LocaleConfig::SetSystemLanguage(const string &language) { - if ((language != "") && !IsValidTag(language)) { + if (!IsValidTag(language)) { return false; } return SetParameter(LANGUAGE_KEY, language.data()) == 0; @@ -96,14 +124,15 @@ bool LocaleConfig::SetSystemLanguage(const string &language) bool LocaleConfig::SetSystemRegion(const string ®ion) { - if ((region != "") && !IsValidRegion(region)) { + if (!IsValidRegion(region)) { return false; } char value[CONFIG_LEN]; int code = GetParameter(LOCALE_KEY, "", value, CONFIG_LEN); string newLocale; if (code > 0) { - newLocale = GetRegionChangeLocale(value, region); + string tag(value, code); + newLocale = GetRegionChangeLocale(tag, region); if (newLocale == "") { return false; } @@ -124,7 +153,7 @@ bool LocaleConfig::SetSystemRegion(const string ®ion) bool LocaleConfig::SetSystemLocale(const string &locale) { - if ((locale != "") && !IsValidTag(locale)) { + if (!IsValidTag(locale)) { return false; } return SetParameter(LOCALE_KEY, locale.data()) == 0; @@ -198,13 +227,11 @@ void LocaleConfig::Split(const string &src, const string &sep, vector &d } } +// language in white languages should have script. void LocaleConfig::GetSystemLanguages(vector &ret) { - const unordered_set &supported = GetSupportedLocales(); - for (auto item : supported) { - if (supported.find(item) != supported.end()) { - ret.push_back(item); - } + for (auto item : whiteLanguages) { + ret.push_back(item); } } @@ -228,49 +255,62 @@ void LocaleConfig::GetSystemCountries(vector &ret) bool LocaleConfig::IsSuggested(const string &language) { unordered_set relatedLocales; - GetRelatedLocales(relatedLocales); - return relatedLocales.find(language) != relatedLocales.end(); + vector simCountries; + GetCountriesFromSim(simCountries); + GetRelatedLocales(relatedLocales, simCountries); + for (auto iter = relatedLocales.begin(); iter != relatedLocales.end();) { + if (whiteLanguages.find(*iter) == whiteLanguages.end()) { + iter = relatedLocales.erase(iter); + } else { + ++iter; + } + } + string mainLanguage = GetMainLanguage(language); + return relatedLocales.find(mainLanguage) != relatedLocales.end(); } bool LocaleConfig::IsSuggested(const std::string &language, const std::string ®ion) { unordered_set relatedLocales; - GetRelatedLocales(relatedLocales); - if (relatedLocales.find(language) == relatedLocales.end()) { - return false; + vector countries { region }; + GetRelatedLocales(relatedLocales, countries); + for (auto iter = relatedLocales.begin(); iter != relatedLocales.end();) { + if (whiteLanguages.find(*iter) == whiteLanguages.end()) { + iter = relatedLocales.erase(iter); + } else { + ++iter; + } } - string temp = GetRegionChangeLocale(language, region); - return relatedLocales.find(temp) != relatedLocales.end(); + string mainLanguage = GetMainLanguage(language); + return relatedLocales.find(mainLanguage) != relatedLocales.end(); } -void LocaleConfig::GetRelatedLocales(unordered_set &relatedLocales) +void LocaleConfig::GetRelatedLocales(unordered_set &relatedLocales, vector countries) { - vector simCountries; - GetCountriesFromSim(simCountries); + // remove unsupported countries const unordered_set ®ions = GetSupportedRegions(); - for (auto iter = simCountries.begin(); iter != simCountries.end();) { + for (auto iter = countries.begin(); iter != countries.end();) { if (regions.find(*iter) == regions.end()) { - iter = simCountries.erase(iter); + iter = countries.erase(iter); } else { ++iter; } } const unordered_set &locales = GetSupportedLocales(); - for (auto item : locales) { - if (whiteLanguages.find(item) == whiteLanguages.end()) { - continue; - } - UErrorCode status = U_ZERO_ERROR; - icu::Locale locale = icu::Locale::forLanguageTag(item, status); - if (status != U_ZERO_ERROR) { - continue; + for (string locale : locales) { + bool find = false; + for (string country : countries) { + if (locale.find(country) != string::npos) { + find = true; + break; + } } - const char *region = locale.getCountry(); - if (region == nullptr) { + if (!find) { continue; } - if (find(simCountries.begin(), simCountries.end(), region) != simCountries.end()) { - relatedLocales.insert(item); + string mainLanguage = GetMainLanguage(locale); + if (mainLanguage != "") { + relatedLocales.insert(mainLanguage); } } } @@ -295,58 +335,54 @@ void LocaleConfig::GetListFromFile(const char *path, const char *resourceName, u } xmlNodePtr cur = xmlDocGetRootElement(doc); if (cur == nullptr || (xmlStrcmp(cur->name, reinterpret_cast(resourceName))) != 0) { + xmlFreeDoc(doc); return; } cur = cur->xmlChildrenNode; - xmlChar *content; + xmlChar *content = nullptr; while (cur != nullptr) { content = xmlNodeGetContent(cur); - ret.insert(reinterpret_cast(content)); - xmlFree(content); - cur = cur->next; + if (content != nullptr) { + ret.insert(reinterpret_cast(content)); + xmlFree(content); + cur = cur->next; + } else { + break; + } } xmlFreeDoc(doc); } -const unordered_set& LocaleConfig::GetForbiddenRegions() +void LocaleConfig::Expunge(unordered_set &src, const unordered_set &another) { - return forbiddenRegions; + for (auto iter = src.begin(); iter != src.end();) { + if (another.find(*iter) != another.end()) { + iter = src.erase(iter); + } else { + ++iter; + } + } } bool LocaleConfig::InitializeLists() { SetHwIcuDirectory(); - GetListFromFile(SUPPORTED_LOCALES_PATH, SUPPORTED_LOCALES_NAME, supportedLocales); - for (auto iter = supportedLocales.begin(); iter != supportedLocales.end();) { - bool find = false; - for (auto item : forbiddenRegions) { - if (iter->find(item)) { - find = true; - break; - } - } - if (find) { - iter = supportedLocales.erase(iter); - } else { - ++iter; - } - } GetListFromFile(SUPPORTED_REGIONS_PATH, SUPPORTED_REGIONS_NAME, supportedRegions); - for (auto iter = supportedRegions.begin(); iter != supportedRegions.end();) { - if (forbiddenRegions.find(*iter) != forbiddenRegions.end()) { - iter = supportedRegions.erase(iter); - } else { - ++iter; - } - } - GetListFromFile(WHILTE_LANGUAGES_PATH, WHITE_LANGUAGE_NAME, whiteLanguages); + unordered_set forbiddenRegions; + GetListFromFile(FORBIDDEN_REGIONS_PATH, FORBIDDEN_REGIONS_NAME, forbiddenRegions); + Expunge(supportedRegions, forbiddenRegions); + GetListFromFile(WHITE_LANGUAGES_PATH, WHITE_LANGUAGES_NAME, whiteLanguages); + unordered_set forbiddenLanguages; + GetListFromFile(FORBIDDEN_LANGUAGES_PATH, FORBIDDEN_LANGUAGES_NAME, forbiddenLanguages); + Expunge(whiteLanguages, forbiddenLanguages); + GetListFromFile(SUPPORTED_LOCALES_PATH, SUPPORTED_LOCALES_NAME, supportedLocales); return true; } string LocaleConfig::GetRegionChangeLocale(const string &languageTag, const string ®ion) { UErrorCode status = U_ZERO_ERROR; - icu::Locale origin = icu::Locale::forLanguageTag(languageTag, status); + const icu::Locale origin = icu::Locale::forLanguageTag(languageTag, status); if (status != U_ZERO_ERROR) { return ""; } @@ -360,10 +396,41 @@ string LocaleConfig::GetRegionChangeLocale(const string &languageTag, const stri return (status != U_ZERO_ERROR) ? "" : ret; } +string LocaleConfig::GetMainLanguage(const string &language) +{ + UErrorCode status = U_ZERO_ERROR; + icu::Locale origin = icu::Locale::forLanguageTag(language, status); + if (status != U_ZERO_ERROR) { + return ""; + } + origin.addLikelySubtags(status); + if (status != U_ZERO_ERROR) { + return ""; + } + icu::LocaleBuilder builder = icu::LocaleBuilder().setLanguage(origin.getLanguage()). + setScript(origin.getScript()).setRegion(origin.getCountry()); + icu::Locale temp = builder.setExtension('u', "").build(status); + string fullLanguage = temp.toLanguageTag(status); + if (status != U_ZERO_ERROR) { + return ""; + } + if (dialectMap.find(fullLanguage) != dialectMap.end()) { + return dialectMap[fullLanguage]; + } + builder.setRegion(""); + temp = builder.build(status); + fullLanguage = temp.toLanguageTag(status); + if (status != U_ZERO_ERROR) { + return ""; + } + return fullLanguage; +} + string LocaleConfig::GetDisplayLanguage(const string &language, const string &displayLocale, bool sentenceCase) { UErrorCode status = U_ZERO_ERROR; - const icu::Locale originLocale = icu::Locale::forLanguageTag(language, status); + icu::Locale originLocale = icu::Locale::forLanguageTag(language, status); + originLocale.addLikelySubtags(status); if (status != U_ZERO_ERROR) { return ""; } @@ -385,7 +452,8 @@ string LocaleConfig::GetDisplayLanguage(const string &language, const string &di string LocaleConfig::GetDisplayRegion(const string ®ion, const string &displayLocale, bool sentenceCase) { UErrorCode status = U_ZERO_ERROR; - const icu::Locale originLocale = icu::Locale::forLanguageTag(region, status); + icu::LocaleBuilder builder = icu::LocaleBuilder().setRegion(region); + icu::Locale originLocale = builder.build(status); if (status != U_ZERO_ERROR) { return ""; } diff --git a/frameworks/intl/src/supported_locales.xml b/frameworks/intl/src/supported_locales.xml index e538b6f3cf27a85c40a2942c94819b212ee9830e..5bf27cbd400961fb1bf1f1a6ea5fdc692e872142 100644 --- a/frameworks/intl/src/supported_locales.xml +++ b/frameworks/intl/src/supported_locales.xml @@ -13,446 +13,558 @@ limitations under the License. --> - am - am-ET - ar - ar-001 - ar-AE - ar-BH - ar-DJ - ar-DZ - ar-EG - ar-EH - ar-ER - ar-IL - ar-IQ - ar-JO - ar-KM - ar-KW - ar-LB - ar-LY - ar-MA - ar-MR - ar-OM - ar-PS - ar-QA - ar-SA - ar-SD - ar-SO - ar-SS - ar-SY - ar-TD - ar-TN - ar-XB - ar-YE - as - as-IN - az - az-Cyrl + af-Latn-NA + af-Latn-ZA + agq-Latn-CM + ak-Latn-GH + am-Ethi-ET + ar-Arab-001 + ar-Arab-AE + ar-Arab-BH + ar-Arab-DJ + ar-Arab-DZ + ar-Arab-EG + ar-Arab-EH + ar-Arab-ER + ar-Arab-IL + ar-Arab-IQ + ar-Arab-JO + ar-Arab-KM + ar-Arab-KW + ar-Arab-LB + ar-Arab-LY + ar-Arab-MA + ar-Arab-MR + ar-Arab-OM + ar-Arab-PS + ar-Arab-QA + ar-Arab-SA + ar-Arab-SD + ar-Arab-SO + ar-Arab-SS + ar-Arab-SY + ar-Arab-TD + ar-Arab-TN + ar-Arab-XB + ar-Arab-YE + as-Beng-IN + asa-Latn-TZ + ast-Latn-ES az-Cyrl-AZ - az-Latn az-Latn-AZ - be - be-BY - bg - bg-BG - bn - bn-BD - bn-IN - bo - bo-CN - bo-IN - bs - bs-Cyrl + bas-Latn-CM + be-Cyrl-BY + bem-Latn-ZM + bez-Latn-TZ + bg-Cyrl-BG + bm-Latn-ML + bn-Beng-BD + bn-Beng-IN + bo-Tibt-CN + bo-Tibt-IN + br-Latn-FR + brx-Deva-IN bs-Cyrl-BA - bs-Latn bs-Latn-BA - ca - ca-AD - ca-ES - ca-FR - ca-IT - cs - cs-CZ - da - da-DK - da-GL - de - de-AT - de-BE - de-CH - de-DE - de-IT - de-LI - de-LU - el - el-CY - el-GR - en - en-001 - en-150 - en-AE - en-AG - en-AI - en-AS - en-AT - en-AU - en-BB - en-BE - en-BI - en-BM - en-BS - en-BW - en-BZ - en-CA - en-CC - en-CH - en-CK - en-CM - en-CX - en-CY - en-DE - en-DG - en-DK - en-DM - en-ER - en-FI - en-FJ - en-FK - en-FM - en-GB - en-GD - en-GG - en-GH - en-GI - en-GM - en-GU - en-GY - en-HK - en-IE - en-IL - en-IM - en-IN - en-IO - en-JE - en-JM - en-KE - en-KI - en-KN - en-KY - en-LC - en-LR - en-LS - en-MG - en-MH - en-MM - en-MO - en-MP - en-MS - en-MT - en-MU - en-MW - en-MY - en-NA - en-NF - en-NG - en-NL - en-NR - en-NU - en-NZ - en-PG - en-PH - en-PK - en-PN - en-PR - en-PW - en-Qaag + ca-Latn-AD + ca-Latn-ES + ca-Latn-FR + ca-Latn-IT + ccp-Cakm-BD + ccp-Cakm-IN + ce-Cyrl-RU + ceb-Latn-PH + cgg-Latn-UG + chr-Cher-US + ckb-Arab-IQ + ckb-Arab-IR + cs-Latn-CZ + cy-Latn-GB + da-Latn-DK + da-Latn-GL + dav-Latn-KE + de-Latn-AT + de-Latn-BE + de-Latn-CH + de-Latn-DE + de-Latn-IT + de-Latn-LI + de-Latn-LU + dje-Latn-NE + dsb-Latn-DE + dua-Latn-CM + dyo-Latn-SN + dz-Tibt-BT + ebu-Latn-KE + ee-Latn-GH + ee-Latn-TG + el-Grek-CY + el-Grek-GR + en-Latn-001 + en-Latn-150 + en-Latn-AE + en-Latn-AG + en-Latn-AI + en-Latn-AS + en-Latn-AT + en-Latn-AU + en-Latn-BB + en-Latn-BE + en-Latn-BI + en-Latn-BM + en-Latn-BS + en-Latn-BW + en-Latn-BZ + en-Latn-CA + en-Latn-CC + en-Latn-CH + en-Latn-CK + en-Latn-CM + en-Latn-CX + en-Latn-CY + en-Latn-DE + en-Latn-DG + en-Latn-DK + en-Latn-DM + en-Latn-ER + en-Latn-FI + en-Latn-FJ + en-Latn-FK + en-Latn-FM + en-Latn-GB + en-Latn-GD + en-Latn-GG + en-Latn-GH + en-Latn-GI + en-Latn-GM + en-Latn-GU + en-Latn-GY + en-Latn-HK + en-Latn-IE + en-Latn-IL + en-Latn-IM + en-Latn-IN + en-Latn-IO + en-Latn-JE + en-Latn-JM + en-Latn-KE + en-Latn-KI + en-Latn-KN + en-Latn-KY + en-Latn-LC + en-Latn-LR + en-Latn-LS + en-Latn-MG + en-Latn-MH + en-Latn-MM + en-Latn-MO + en-Latn-MP + en-Latn-MS + en-Latn-MT + en-Latn-MU + en-Latn-MW + en-Latn-MY + en-Latn-NA + en-Latn-NF + en-Latn-NG + en-Latn-NL + en-Latn-NR + en-Latn-NU + en-Latn-NZ + en-Latn-PG + en-Latn-PH + en-Latn-PK + en-Latn-PN + en-Latn-PR + en-Latn-PW + en-Latn-RW + en-Latn-SB + en-Latn-SC + en-Latn-SD + en-Latn-SE + en-Latn-SG + en-Latn-SH + en-Latn-SI + en-Latn-SL + en-Latn-SS + en-Latn-SX + en-Latn-SZ + en-Latn-TC + en-Latn-TK + en-Latn-TO + en-Latn-TT + en-Latn-TV + en-Latn-TZ + en-Latn-UG + en-Latn-UM + en-Latn-US + en-Latn-VC + en-Latn-VG + en-Latn-VI + en-Latn-VU + en-Latn-WS + en-Latn-XA + en-Latn-ZA + en-Latn-ZM + en-Latn-ZW en-Qaag-MM - en-RW - en-SB - en-SC - en-SD - en-SE - en-SG - en-SH - en-SI - en-SL - en-SS - en-SX - en-SZ - en-TC - en-TK - en-TO - en-TT - en-TV - en-TZ - en-UG - en-UM - en-US - en-US-u-va-posix - en-VC - en-VG - en-VI - en-VU - en-WS - en-XA - en-ZA - en-ZM - en-ZW - es - es-419 - es-AR - es-BO - es-BR - es-BZ - es-CL - es-CO - es-CR - es-CU - es-DO - es-EA - es-EC - es-ES - es-GQ - es-GT - es-HN - es-IC - es-MX - es-NI - es-PA - es-PE - es-PH - es-PR - es-PY - es-SV - es-US - es-UY - es-VE - et - et-EE - eu - eu-ES - fa - fa-AF - fa-IR - fi - fi-FI - fr - fr-BE - fr-BF - fr-BI - fr-BJ - fr-BL - fr-CA - fr-CD - fr-CF - fr-CG - fr-CH - fr-CI - fr-CM - fr-DJ - fr-DZ - fr-FR - fr-GA - fr-GF - fr-GN - fr-GP - fr-GQ - fr-HT - fr-KM - fr-LU - fr-MA - fr-MC - fr-MF - fr-MG - fr-ML - fr-MQ - fr-MR - fr-MU - fr-NC - fr-NE - fr-PF - fr-PM - fr-RE - fr-RW - fr-SC - fr-SN - fr-SY - fr-TD - fr-TG - fr-TN - fr-VU - fr-WF - fr-YT - gl - gl-ES - gu - gu-IN - hi - hi-IN - hr - hr-BA - hr-HR - hu - hu-HU - it - it-CH - it-IT - it-SM - it-VA - ja - ja-JP - jv - jv-ID - ka - ka-GE - kk - kk-KZ - km - km-KH - kn - kn-IN - ko - ko-KP - ko-KR - lo - lo-LA - lt - lt-LT - lv - lv-LV - mai - mai-Deva + en-Qaag-US + eo-Latn-001 + es-Latn-419 + es-Latn-AR + es-Latn-BO + es-Latn-BR + es-Latn-BZ + es-Latn-CL + es-Latn-CO + es-Latn-CR + es-Latn-CU + es-Latn-DO + es-Latn-EA + es-Latn-EC + es-Latn-ES + es-Latn-GQ + es-Latn-GT + es-Latn-HN + es-Latn-IC + es-Latn-MX + es-Latn-NI + es-Latn-PA + es-Latn-PE + es-Latn-PH + es-Latn-PR + es-Latn-PY + es-Latn-SV + es-Latn-US + es-Latn-UY + es-Latn-VE + et-Latn-EE + eu-Latn-ES + ewo-Latn-CM + fa-Arab-AF + fa-Arab-IR + ff-Adlm-BF + ff-Adlm-CM + ff-Adlm-GH + ff-Adlm-GM + ff-Adlm-GN + ff-Adlm-GW + ff-Adlm-LR + ff-Adlm-MR + ff-Adlm-NE + ff-Adlm-NG + ff-Adlm-SL + ff-Adlm-SN + ff-Latn-BF + ff-Latn-CM + ff-Latn-GH + ff-Latn-GM + ff-Latn-GN + ff-Latn-GW + ff-Latn-LR + ff-Latn-MR + ff-Latn-NE + ff-Latn-NG + ff-Latn-SL + ff-Latn-SN + fi-Latn-FI + fil-Latn-PH + fo-Latn-DK + fo-Latn-FO + fr-Latn-BE + fr-Latn-BF + fr-Latn-BI + fr-Latn-BJ + fr-Latn-BL + fr-Latn-CA + fr-Latn-CD + fr-Latn-CF + fr-Latn-CG + fr-Latn-CH + fr-Latn-CI + fr-Latn-CM + fr-Latn-DJ + fr-Latn-DZ + fr-Latn-FR + fr-Latn-GA + fr-Latn-GF + fr-Latn-GN + fr-Latn-GP + fr-Latn-GQ + fr-Latn-HT + fr-Latn-KM + fr-Latn-LU + fr-Latn-MA + fr-Latn-MC + fr-Latn-MF + fr-Latn-MG + fr-Latn-ML + fr-Latn-MQ + fr-Latn-MR + fr-Latn-MU + fr-Latn-NC + fr-Latn-NE + fr-Latn-PF + fr-Latn-PM + fr-Latn-RE + fr-Latn-RW + fr-Latn-SC + fr-Latn-SN + fr-Latn-SY + fr-Latn-TD + fr-Latn-TG + fr-Latn-TN + fr-Latn-VU + fr-Latn-WF + fr-Latn-YT + fur-Latn-IT + fy-Latn-NL + ga-Latn-GB + ga-Latn-IE + gd-Latn-GB + gl-Latn-ES + gsw-Latn-CH + gsw-Latn-FR + gsw-Latn-LI + gu-Gujr-IN + guz-Latn-KE + gv-Latn-IM + ha-Latn-GH + ha-Latn-NE + ha-Latn-NG + haw-Latn-US + he-Hebr-IL + hi-Deva-IN + hr-Latn-BA + hr-Latn-HR + hsb-Latn-DE + hu-Latn-HU + hy-Armn-AM + ia-Latn-001 + id-Latn-ID + ig-Latn-NG + ii-Yiii-CN + is-Latn-IS + it-Latn-CH + it-Latn-IT + it-Latn-SM + it-Latn-VA + ja-Jpan-JP + jgo-Latn-CM + jmc-Latn-TZ + jv-Latn-ID + ka-Geor-GE + kab-Latn-DZ + kam-Latn-KE + kde-Latn-TZ + kea-Latn-CV + khq-Latn-ML + ki-Latn-KE + kk-Cyrl-KZ + kkj-Latn-CM + kl-Latn-GL + kln-Latn-KE + km-Khmr-KH + kn-Knda-IN + ko-Kore-KP + ko-Kore-KR + kok-Deva-IN + ks-Arab-IN + ksb-Latn-TZ + ksf-Latn-CM + ksh-Latn-DE + ku-Latn-TR + kw-Latn-GB + ky-Cyrl-KG + lag-Latn-TZ + lb-Latn-LU + lg-Latn-UG + lkt-Latn-US + ln-Latn-AO + ln-Latn-CD + ln-Latn-CF + ln-Latn-CG + lo-Laoo-LA + lrc-Arab-IQ + lrc-Arab-IR + lt-Latn-LT + lu-Latn-CD + luo-Latn-KE + luy-Latn-KE + lv-Latn-LV mai-Deva-IN - mai-IN - mi - mi-NZ - mk - mk-MK - ml - ml-IN - mn - mn-MN - mr - mr-IN - ms - ms-BN - ms-ID - ms-MY - ms-SG - my - my-MM - my-Qaag + mas-Latn-KE + mas-Latn-TZ + mer-Latn-KE + mfe-Latn-MU + mg-Latn-MG + mgh-Latn-MZ + mgo-Latn-CM + mi-Latn-NZ + mk-Cyrl-MK + ml-Mlym-IN + mn-Cyrl-MN + mni-Beng-IN + mr-Deva-IN + ms-Arab-ID + ms-Latn-BN + ms-Latn-MY + ms-Latn-SG + mt-Latn-MT + mua-Latn-CM + my-Mymr-MM + my-Mymr-ZG my-Qaag-MM - my-ZG - nb - nb-NO - nb-SJ - ne - ne-IN - ne-NP - nl - nl-AW - nl-BE - nl-BQ - nl-CW - nl-NL - nl-SR - nl-SX - or - or-IN - pa - pa-Arab + mzn-Arab-IR + naq-Latn-NA + nb-Latn-NO + nb-Latn-SJ + nd-Latn-ZW + nds-Latn-DE + nds-Latn-NL + ne-Deva-IN + ne-Deva-NP + nl-Latn-AW + nl-Latn-BE + nl-Latn-BQ + nl-Latn-CW + nl-Latn-NL + nl-Latn-SR + nl-Latn-SX + nmg-Latn-CM + nn-Latn-NO + nnh-Latn-CM + nus-Latn-SS + nyn-Latn-UG + om-Latn-ET + om-Latn-KE + or-Orya-IN + os-Cyrl-GE + os-Cyrl-RU pa-Arab-PK - pa-Guru pa-Guru-IN - pl - pl-PL - pt - pt-AO - pt-BR - pt-CH - pt-CV - pt-GQ - pt-GW - pt-LU - pt-MO - pt-MZ - pt-PT - pt-ST - pt-TL - ro - ro-MD - ro-RO - ru - ru-BY - ru-KG - ru-KZ - ru-MD - ru-RU - ru-UA - si - si-LK - sk - sk-SK - sl - sl-SI - sr - sr-Cyrl + pcm-Latn-NG + pl-Latn-PL + ps-Arab-AF + ps-Arab-PK + pt-Latn-AO + pt-Latn-BR + pt-Latn-CH + pt-Latn-CV + pt-Latn-GQ + pt-Latn-GW + pt-Latn-LU + pt-Latn-MO + pt-Latn-MZ + pt-Latn-PT + pt-Latn-ST + pt-Latn-TL + qu-Latn-BO + qu-Latn-EC + qu-Latn-PE + rm-Latn-CH + rn-Latn-BI + ro-Latn-MD + ro-Latn-RO + rof-Latn-TZ + ru-Cyrl-BY + ru-Cyrl-KG + ru-Cyrl-KZ + ru-Cyrl-MD + ru-Cyrl-RU + ru-Cyrl-UA + rw-Latn-RW + rwk-Latn-TZ + sah-Cyrl-RU + saq-Latn-KE + sat-Latn-IN + sat-Olck-IN + sbp-Latn-TZ + sd-Arab-PK + sd-Deva-IN + se-Latn-FI + se-Latn-NO + se-Latn-SE + seh-Latn-MZ + ses-Latn-ML + sg-Latn-CF + shi-Latn-MA + shi-Tfng-MA + si-Sinh-LK + sk-Latn-SK + sl-Latn-SI + smn-Latn-FI + sn-Latn-ZW + so-Latn-DJ + so-Latn-ET + so-Latn-KE + so-Latn-SO + sq-Latn-AL + sq-Latn-MK + sq-Latn-XK sr-Cyrl-BA sr-Cyrl-ME sr-Cyrl-RS sr-Cyrl-XK - sr-Latn sr-Latn-BA sr-Latn-ME sr-Latn-RS sr-Latn-XK - sv - sv-AX - sv-FI - sv-SE - sw - sw-CD - sw-KE - sw-TZ - sw-UG - ta - ta-IN - ta-LK - ta-MY - ta-SG - te - te-IN - th - th-TH - tr - tr-CY - tr-TR - ug - ug-CN - uk - uk-UA - ur - ur-IN - ur-PK - uz - uz-Arab + su-Latn-ID + sv-Latn-AX + sv-Latn-FI + sv-Latn-SE + sw-Latn-CD + sw-Latn-KE + sw-Latn-TZ + sw-Latn-UG + ta-Taml-IN + ta-Taml-LK + ta-Taml-MY + ta-Taml-SG + te-Telu-IN + teo-Latn-KE + teo-Latn-UG + tg-Cyrl-TJ + th-Thai-TH + ti-Ethi-ER + ti-Ethi-ET + tk-Latn-TM + to-Latn-TO + tr-Latn-CY + tr-Latn-TR + tt-Cyrl-RU + twq-Latn-NE + tzm-Latn-MA + ug-Arab-CN + uk-Cyrl-UA + ur-Arab-IN + ur-Arab-PK uz-Arab-AF - uz-Cyrl uz-Cyrl-UZ - uz-Latn uz-Latn-UZ - vi - vi-VN - zh - zh-Hans + vai-Latn-LR + vai-Vaii-LR + vi-Latn-VN + vun-Latn-TZ + wae-Latn-CH + wo-Latn-SN + xh-Latn-ZA + xog-Latn-UG + yav-Latn-CM + yi-Hebr-001 + yo-Latn-BJ + yo-Latn-NG + yue-Hans-CN + yue-Hant-HK + zgh-Tfng-MA zh-Hans-CN zh-Hans-HK zh-Hans-MO zh-Hans-SG - zh-Hant zh-Hant-HK zh-Hant-MO zh-Hant-TW + zu-Latn-ZA + zz-Latn-ZX \ No newline at end of file