From ffc449de6243b17857b5d67854bdec723bf06f21 Mon Sep 17 00:00:00 2001 From: Frank Tang Date: Tue, 15 Aug 2023 20:23:28 -0700 Subject: [PATCH] ICU-20777 Merge the likelySubtags implemention Change testdata/likelySubtags.txt to consider FAIL line ICU-20777 Fix Java Tests ICU-20777 Fix all issues ICU-20777 Incase timeout ICU-20777 ICU-20777 Skip Data Driven test --- icu4c/source/common/BUILD.bazel | 2 + icu4c/source/common/localematcher.cpp | 2 +- icu4c/source/common/locid.cpp | 6 +- icu4c/source/common/loclikely.cpp | 672 +------ icu4c/source/common/loclikelysubtags.cpp | 311 +++- icu4c/source/common/loclikelysubtags.h | 28 +- icu4c/source/common/lsr.cpp | 20 + icu4c/source/common/lsr.h | 3 + icu4c/source/common/ulocimp.h | 2 + icu4c/source/common/unicode/locid.h | 9 + icu4c/source/test/cintltst/cloctst.c | 8 +- icu4c/source/test/depstest/dependencies.txt | 11 +- icu4c/source/test/intltest/loctest.cpp | 194 +- icu4c/source/test/intltest/loctest.h | 1 + icu4c/source/test/testdata/likelySubtags.txt | 1607 +++++++++++++++++ .../ibm/icu/impl/locale/LocaleDistance.java | 4 +- .../ibm/icu/impl/locale/XLikelySubtags.java | 148 +- .../src/com/ibm/icu/util/LocaleMatcher.java | 2 +- .../core/src/com/ibm/icu/util/ULocale.java | 363 +--- .../com/ibm/icu/dev/data/likelySubtags.txt | 1607 +++++++++++++++++ .../icu/dev/test/util/LocaleMatcherTest.java | 10 +- .../ibm/icu/dev/test/util/ULocaleTest.java | 116 +- .../dev/tool/locale/LikelySubtagsBuilder.java | 317 ---- .../tool/locale/LocaleDistanceBuilder.java | 4 +- 24 files changed, 3956 insertions(+), 1491 deletions(-) create mode 100644 icu4c/source/test/testdata/likelySubtags.txt create mode 100644 icu4j/main/tests/core/src/com/ibm/icu/dev/data/likelySubtags.txt delete mode 100644 icu4j/main/tests/core/src/com/ibm/icu/dev/tool/locale/LikelySubtagsBuilder.java diff --git a/icu4c/source/common/BUILD.bazel b/icu4c/source/common/BUILD.bazel index 30f49425c742..3ecae30c437f 100644 --- a/icu4c/source/common/BUILD.bazel +++ b/icu4c/source/common/BUILD.bazel @@ -603,7 +603,9 @@ cc_library( "locbased.cpp", "locid.cpp", "loclikely.cpp", + "loclikelysubtags.cpp", "locmap.cpp", + "lsr.cpp", "resbund.cpp", "resource.cpp", "uloc.cpp", diff --git a/icu4c/source/common/localematcher.cpp b/icu4c/source/common/localematcher.cpp index 5f8c703df713..6fc578af118b 100644 --- a/icu4c/source/common/localematcher.cpp +++ b/icu4c/source/common/localematcher.cpp @@ -307,7 +307,7 @@ LSR getMaximalLsrOrUnd(const XLikelySubtags &likelySubtags, const Locale &locale if (U_FAILURE(errorCode) || locale.isBogus() || *locale.getName() == 0 /* "und" */) { return UND_LSR; } else { - return likelySubtags.makeMaximizedLsrFrom(locale, errorCode); + return likelySubtags.makeMaximizedLsrFrom(locale, false, errorCode); } } diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp index 057e68d9d640..ee35f106f3f3 100644 --- a/icu4c/source/common/locid.cpp +++ b/icu4c/source/common/locid.cpp @@ -2080,6 +2080,10 @@ Locale::addLikelySubtags(UErrorCode& status) { void Locale::minimizeSubtags(UErrorCode& status) { + Locale::minimizeSubtags(false, status); +} +void +Locale::minimizeSubtags(bool favorScript, UErrorCode& status) { if (U_FAILURE(status)) { return; } @@ -2087,7 +2091,7 @@ Locale::minimizeSubtags(UErrorCode& status) { CharString minimizedLocaleID; { CharStringByteSink sink(&minimizedLocaleID); - ulocimp_minimizeSubtags(fullName, sink, &status); + ulocimp_minimizeSubtags(fullName, sink, favorScript, &status); } if (U_FAILURE(status)) { diff --git a/icu4c/source/common/loclikely.cpp b/icu4c/source/common/loclikely.cpp index d2a05c636440..5235daaf59df 100644 --- a/icu4c/source/common/loclikely.cpp +++ b/icu4c/source/common/loclikely.cpp @@ -31,82 +31,10 @@ #include "charstr.h" #include "cmemory.h" #include "cstring.h" +#include "loclikelysubtags.h" #include "ulocimp.h" #include "ustr_imp.h" -/** - * These are the canonical strings for unknown languages, scripts and regions. - **/ -static const char* const unknownLanguage = "und"; -static const char* const unknownScript = "Zzzz"; -static const char* const unknownRegion = "ZZ"; - -/** - * This function looks for the localeID in the likelySubtags resource. - * - * @param localeID The tag to find. - * @param buffer A buffer to hold the matching entry - * @param bufferLength The length of the output buffer - * @return A pointer to "buffer" if found, or a null pointer if not. - */ -static const char* U_CALLCONV -findLikelySubtags(const char* localeID, - char* buffer, - int32_t bufferLength, - UErrorCode* err) { - const char* result = nullptr; - - if (!U_FAILURE(*err)) { - int32_t resLen = 0; - const char16_t* s = nullptr; - UErrorCode tmpErr = U_ZERO_ERROR; - icu::LocalUResourceBundlePointer subtags(ures_openDirect(nullptr, "likelySubtags", &tmpErr)); - if (U_SUCCESS(tmpErr)) { - icu::CharString und; - if (localeID != nullptr) { - if (*localeID == '\0') { - localeID = unknownLanguage; - } else if (*localeID == '_') { - und.append(unknownLanguage, *err); - und.append(localeID, *err); - if (U_FAILURE(*err)) { - return nullptr; - } - localeID = und.data(); - } - } - s = ures_getStringByKey(subtags.getAlias(), localeID, &resLen, &tmpErr); - - if (U_FAILURE(tmpErr)) { - /* - * If a resource is missing, it's not really an error, it's - * just that we don't have any data for that particular locale ID. - */ - if (tmpErr != U_MISSING_RESOURCE_ERROR) { - *err = tmpErr; - } - } - else if (resLen >= bufferLength) { - /* The buffer should never overflow. */ - *err = U_INTERNAL_PROGRAM_ERROR; - } - else { - u_UCharsToChars(s, buffer, resLen + 1); - if (resLen >= 3 && - uprv_strnicmp(buffer, unknownLanguage, 3) == 0 && - (resLen == 3 || buffer[3] == '_')) { - uprv_memmove(buffer, buffer + 3, resLen - 3 + 1); - } - result = buffer; - } - } else { - *err = tmpErr; - } - } - - return result; -} - /** * Append a tag to a buffer, adding the separator if necessary. The buffer * must be large enough to contain the resulting tag plus any separator @@ -360,57 +288,6 @@ createTagStringWithAlternates( } } -/** - * Create a tag string from the supplied parameters. The lang, script and region - * parameters may be nullptr pointers. If they are, their corresponding length parameters - * must be less than or equal to 0. If the lang parameter is an empty string, the - * default value for an unknown language is written to the output buffer. - * - * If the length of the new string exceeds the capacity of the output buffer, - * the function copies as many bytes to the output buffer as it can, and returns - * the error U_BUFFER_OVERFLOW_ERROR. - * - * If an illegal argument is provided, the function returns the error - * U_ILLEGAL_ARGUMENT_ERROR. - * - * @param lang The language tag to use. - * @param langLength The length of the language tag. - * @param script The script tag to use. - * @param scriptLength The length of the script tag. - * @param region The region tag to use. - * @param regionLength The length of the region tag. - * @param trailing Any trailing data to append to the new tag. - * @param trailingLength The length of the trailing data. - * @param sink The output sink receiving the tag string. - * @param err A pointer to a UErrorCode for error reporting. - **/ -static void U_CALLCONV -createTagString( - const char* lang, - int32_t langLength, - const char* script, - int32_t scriptLength, - const char* region, - int32_t regionLength, - const char* trailing, - int32_t trailingLength, - icu::ByteSink& sink, - UErrorCode* err) -{ - createTagStringWithAlternates( - lang, - langLength, - script, - scriptLength, - region, - regionLength, - trailing, - trailingLength, - nullptr, - sink, - err); -} - /** * Parse the language, script, and region subtags from a tag string, and copy the * results into the corresponding output parameters. The buffers are null-terminated, @@ -494,13 +371,6 @@ parseTagString( *scriptLength = subtagLength; if (*scriptLength > 0) { - if (uprv_strnicmp(script, unknownScript, *scriptLength) == 0) { - /** - * If the script part is the "unknown" script, then don't return it. - **/ - *scriptLength = 0; - } - /* * Move past any separator. */ @@ -517,14 +387,7 @@ parseTagString( *regionLength = subtagLength; - if (*regionLength > 0) { - if (uprv_strnicmp(region, unknownRegion, *regionLength) == 0) { - /** - * If the region part is the "unknown" region, then don't return it. - **/ - *regionLength = 0; - } - } else if (*position != 0 && *position != '@') { + if (*regionLength <= 0 && *position != 0 && *position != '@') { /* back up over consumed trailing separator */ --position; } @@ -546,264 +409,6 @@ parseTagString( goto exit; } -static UBool U_CALLCONV -createLikelySubtagsString( - const char* lang, - int32_t langLength, - const char* script, - int32_t scriptLength, - const char* region, - int32_t regionLength, - const char* variants, - int32_t variantsLength, - icu::ByteSink& sink, - UErrorCode* err) { - /** - * ULOC_FULLNAME_CAPACITY will provide enough capacity - * that we can build a string that contains the language, - * script and region code without worrying about overrunning - * the user-supplied buffer. - **/ - char likelySubtagsBuffer[ULOC_FULLNAME_CAPACITY]; - - if(U_FAILURE(*err)) { - goto error; - } - - /** - * Try the language with the script and region first. - **/ - if (scriptLength > 0 && regionLength > 0) { - - const char* likelySubtags = nullptr; - - icu::CharString tagBuffer; - { - icu::CharStringByteSink sink(&tagBuffer); - createTagString( - lang, - langLength, - script, - scriptLength, - region, - regionLength, - nullptr, - 0, - sink, - err); - } - if(U_FAILURE(*err)) { - goto error; - } - - likelySubtags = - findLikelySubtags( - tagBuffer.data(), - likelySubtagsBuffer, - sizeof(likelySubtagsBuffer), - err); - if(U_FAILURE(*err)) { - goto error; - } - - if (likelySubtags != nullptr) { - /* Always use the language tag from the - maximal string, since it may be more - specific than the one provided. */ - createTagStringWithAlternates( - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - variants, - variantsLength, - likelySubtags, - sink, - err); - return true; - } - } - - /** - * Try the language with just the script. - **/ - if (scriptLength > 0) { - - const char* likelySubtags = nullptr; - - icu::CharString tagBuffer; - { - icu::CharStringByteSink sink(&tagBuffer); - createTagString( - lang, - langLength, - script, - scriptLength, - nullptr, - 0, - nullptr, - 0, - sink, - err); - } - if(U_FAILURE(*err)) { - goto error; - } - - likelySubtags = - findLikelySubtags( - tagBuffer.data(), - likelySubtagsBuffer, - sizeof(likelySubtagsBuffer), - err); - if(U_FAILURE(*err)) { - goto error; - } - - if (likelySubtags != nullptr) { - /* Always use the language tag from the - maximal string, since it may be more - specific than the one provided. */ - createTagStringWithAlternates( - nullptr, - 0, - nullptr, - 0, - region, - regionLength, - variants, - variantsLength, - likelySubtags, - sink, - err); - return true; - } - } - - /** - * Try the language with just the region. - **/ - if (regionLength > 0) { - - const char* likelySubtags = nullptr; - - icu::CharString tagBuffer; - { - icu::CharStringByteSink sink(&tagBuffer); - createTagString( - lang, - langLength, - nullptr, - 0, - region, - regionLength, - nullptr, - 0, - sink, - err); - } - if(U_FAILURE(*err)) { - goto error; - } - - likelySubtags = - findLikelySubtags( - tagBuffer.data(), - likelySubtagsBuffer, - sizeof(likelySubtagsBuffer), - err); - if(U_FAILURE(*err)) { - goto error; - } - - if (likelySubtags != nullptr) { - /* Always use the language tag from the - maximal string, since it may be more - specific than the one provided. */ - createTagStringWithAlternates( - nullptr, - 0, - script, - scriptLength, - nullptr, - 0, - variants, - variantsLength, - likelySubtags, - sink, - err); - return true; - } - } - - /** - * Finally, try just the language. - **/ - { - const char* likelySubtags = nullptr; - - icu::CharString tagBuffer; - { - icu::CharStringByteSink sink(&tagBuffer); - createTagString( - lang, - langLength, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - sink, - err); - } - if(U_FAILURE(*err)) { - goto error; - } - - likelySubtags = - findLikelySubtags( - tagBuffer.data(), - likelySubtagsBuffer, - sizeof(likelySubtagsBuffer), - err); - if(U_FAILURE(*err)) { - goto error; - } - - if (likelySubtags != nullptr) { - /* Always use the language tag from the - maximal string, since it may be more - specific than the one provided. */ - createTagStringWithAlternates( - nullptr, - 0, - script, - scriptLength, - region, - regionLength, - variants, - variantsLength, - likelySubtags, - sink, - err); - return true; - } - } - - return false; - -error: - - if (!U_FAILURE(*err)) { - *err = U_ILLEGAL_ARGUMENT_ERROR; - } - - return false; -} - #define CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength) UPRV_BLOCK_MACRO_BEGIN { \ int32_t count = 0; \ int32_t i; \ @@ -836,7 +441,6 @@ _uloc_addLikelySubtags(const char* localeID, const char* trailing = ""; int32_t trailingLength = 0; int32_t trailingIndex = 0; - UBool success = false; if(U_FAILURE(*err)) { goto error; @@ -862,6 +466,9 @@ _uloc_addLikelySubtags(const char* localeID, goto error; } + if (langLength > 3) { + goto error; + } /* Find the length of the trailing portion. */ while (_isIDSeparator(localeID[trailingIndex])) { @@ -871,30 +478,33 @@ _uloc_addLikelySubtags(const char* localeID, trailingLength = (int32_t)uprv_strlen(trailing); CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength); - - success = - createLikelySubtagsString( - lang, - langLength, - script, - scriptLength, - region, - regionLength, + { + const icu::XLikelySubtags* likelySubtags = icu::XLikelySubtags::getSingleton(*err); + if(U_FAILURE(*err)) { + goto error; + } + icu::LSR lsr = likelySubtags->makeMaximizedLsrFrom(icu::Locale::createFromName(localeID), true, *err); + const char* language = lsr.language; + if (uprv_strcmp(language, "und") == 0) { + language = ""; + } + createTagStringWithAlternates( + language, + (int32_t)uprv_strlen(language), + lsr.script, + (int32_t)uprv_strlen(lsr.script), + lsr.region, + (int32_t)uprv_strlen(lsr.region), trailing, trailingLength, + nullptr, sink, err); - - if (!success) { - const int32_t localIDLength = (int32_t)uprv_strlen(localeID); - - /* - * If we get here, we need to return localeID. - */ - sink.Append(localeID, localIDLength); + if(U_FAILURE(*err)) { + goto error; + } } - - return success; + return true; error: @@ -913,6 +523,7 @@ static UBool _ulocimp_addLikelySubtags(const char*, icu::ByteSink&, UErrorCode*) static void _uloc_minimizeSubtags(const char* localeID, icu::ByteSink& sink, + bool favorScript, UErrorCode* err) { icu::CharString maximizedTagBuffer; @@ -925,7 +536,6 @@ _uloc_minimizeSubtags(const char* localeID, const char* trailing = ""; int32_t trailingLength = 0; int32_t trailingIndex = 0; - UBool successGetMax = false; if(U_FAILURE(*err)) { goto error; @@ -964,213 +574,38 @@ _uloc_minimizeSubtags(const char* localeID, CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength); { - icu::CharString base; - { - icu::CharStringByteSink baseSink(&base); - createTagString( - lang, - langLength, - script, - scriptLength, - region, - regionLength, - nullptr, - 0, - baseSink, - err); - } - - /** - * First, we need to first get the maximization - * from AddLikelySubtags. - **/ - { - icu::CharStringByteSink maxSink(&maximizedTagBuffer); - successGetMax = _ulocimp_addLikelySubtags(base.data(), maxSink, err); - } - } - - if(U_FAILURE(*err)) { - goto error; - } - - if (!successGetMax) { - /** - * If we got here, return the locale ID parameter unchanged. - **/ - const int32_t localeIDLength = (int32_t)uprv_strlen(localeID); - sink.Append(localeID, localeIDLength); - return; - } - - // In the following, the lang, script, region are referring to those in - // the maximizedTagBuffer, not the one in the localeID. - langLength = sizeof(lang); - scriptLength = sizeof(script); - regionLength = sizeof(region); - parseTagString( - maximizedTagBuffer.data(), - lang, - &langLength, - script, - &scriptLength, - region, - ®ionLength, - err); - if(U_FAILURE(*err)) { - goto error; - } - - /** - * Start first with just the language. - **/ - { - icu::CharString tagBuffer; - { - icu::CharStringByteSink tagSink(&tagBuffer); - createLikelySubtagsString( - lang, - langLength, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - tagSink, - err); - } - + const icu::XLikelySubtags* likelySubtags = icu::XLikelySubtags::getSingleton(*err); if(U_FAILURE(*err)) { goto error; } - else if (!tagBuffer.isEmpty() && - uprv_strnicmp( - maximizedTagBuffer.data(), - tagBuffer.data(), - tagBuffer.length()) == 0) { - - createTagString( - lang, - langLength, - nullptr, - 0, - nullptr, - 0, - trailing, - trailingLength, - sink, - err); - return; - } - } - - /** - * Next, try the language and region. - **/ - if (regionLength > 0) { - - icu::CharString tagBuffer; - { - icu::CharStringByteSink tagSink(&tagBuffer); - createLikelySubtagsString( - lang, - langLength, - nullptr, - 0, - region, - regionLength, - nullptr, - 0, - tagSink, - err); - } - + icu::LSR lsr = likelySubtags->minimizeSubtags( + {lang, langLength}, + {script, scriptLength}, + {region, regionLength}, + favorScript, + *err); if(U_FAILURE(*err)) { goto error; } - else if (!tagBuffer.isEmpty() && - uprv_strnicmp( - maximizedTagBuffer.data(), - tagBuffer.data(), - tagBuffer.length()) == 0) { - - createTagString( - lang, - langLength, - nullptr, - 0, - region, - regionLength, - trailing, - trailingLength, - sink, - err); - return; - } - } - - /** - * Finally, try the language and script. This is our last chance, - * since trying with all three subtags would only yield the - * maximal version that we already have. - **/ - if (scriptLength > 0) { - icu::CharString tagBuffer; - { - icu::CharStringByteSink tagSink(&tagBuffer); - createLikelySubtagsString( - lang, - langLength, - script, - scriptLength, - nullptr, - 0, - nullptr, - 0, - tagSink, - err); - } - + const char* language = lsr.language; + if (uprv_strcmp(language, "und") == 0) { + language = ""; + } + createTagStringWithAlternates( + language, + (int32_t)uprv_strlen(language), + lsr.script, + (int32_t)uprv_strlen(lsr.script), + lsr.region, + (int32_t)uprv_strlen(lsr.region), + trailing, + trailingLength, + nullptr, + sink, + err); if(U_FAILURE(*err)) { goto error; } - else if (!tagBuffer.isEmpty() && - uprv_strnicmp( - maximizedTagBuffer.data(), - tagBuffer.data(), - tagBuffer.length()) == 0) { - - createTagString( - lang, - langLength, - script, - scriptLength, - nullptr, - 0, - trailing, - trailingLength, - sink, - err); - return; - } - } - - { - /** - * If we got here, return the max + trail. - **/ - createTagString( - lang, - langLength, - script, - scriptLength, - region, - regionLength, - trailing, - trailingLength, - sink, - err); return; } @@ -1271,7 +706,7 @@ uloc_minimizeSubtags(const char* localeID, icu::CheckedArrayByteSink sink( minimizedLocaleID, minimizedLocaleIDCapacity); - ulocimp_minimizeSubtags(localeID, sink, status); + ulocimp_minimizeSubtags(localeID, sink, false, status); int32_t reslen = sink.NumberOfBytesAppended(); if (U_FAILURE(*status)) { @@ -1291,6 +726,7 @@ uloc_minimizeSubtags(const char* localeID, U_CAPI void U_EXPORT2 ulocimp_minimizeSubtags(const char* localeID, icu::ByteSink& sink, + bool favorScript, UErrorCode* status) { PreflightingLocaleIDBuffer localeBuffer; do { @@ -1298,7 +734,7 @@ ulocimp_minimizeSubtags(const char* localeID, localeBuffer.getCapacity(), status); } while (localeBuffer.needToTryAgain(status)); - _uloc_minimizeSubtags(localeBuffer.getBuffer(), sink, status); + _uloc_minimizeSubtags(localeBuffer.getBuffer(), sink, favorScript, status); } // Pairs of (language subtag, + or -) for finding out fast if common languages diff --git a/icu4c/source/common/loclikelysubtags.cpp b/icu4c/source/common/loclikelysubtags.cpp index 8511955da63d..e81af4191c0d 100644 --- a/icu4c/source/common/loclikelysubtags.cpp +++ b/icu4c/source/common/loclikelysubtags.cpp @@ -24,6 +24,7 @@ #include "uniquecharstr.h" #include "uresdata.h" #include "uresimp.h" +#include "uvector.h" U_NAMESPACE_BEGIN @@ -304,7 +305,7 @@ struct XLikelySubtagsData { encoded %= 27 * 27; if (encoded < 27) { // Selected M49 code index, find the code from "m49" resource. - return m49IndexToCode(m49Array, value, 2, errorCode); + return m49IndexToCode(m49Array, value, encoded, errorCode); } char region[2]; region[0] = 'A' + ((encoded % 27) - 1); @@ -339,15 +340,52 @@ struct XLikelySubtagsData { namespace { XLikelySubtags *gLikelySubtags = nullptr; +UVector *gMacroregions = nullptr; UInitOnce gInitOnce {}; UBool U_CALLCONV cleanup() { delete gLikelySubtags; gLikelySubtags = nullptr; + delete gMacroregions; + gMacroregions = nullptr; gInitOnce.reset(); return true; } +static const char16_t RANGE_MARKER = 0x7E; /* '~' */ +UVector* loadMacroregions(UErrorCode &status) { + LocalPointer newMacroRegions(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); + + LocalUResourceBundlePointer supplementalData(ures_openDirect(nullptr,"supplementalData",&status)); + LocalUResourceBundlePointer idValidity(ures_getByKey(supplementalData.getAlias(),"idValidity",nullptr,&status)); + LocalUResourceBundlePointer regionList(ures_getByKey(idValidity.getAlias(),"region",nullptr,&status)); + LocalUResourceBundlePointer regionMacro(ures_getByKey(regionList.getAlias(),"macroregion",nullptr,&status)); + + if (U_FAILURE(status)) { + return nullptr; + } + + while (U_SUCCESS(status) && ures_hasNext(regionMacro.getAlias())) { + UnicodeString regionName = ures_getNextUnicodeString(regionMacro.getAlias(),nullptr,&status); + int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER); + char16_t buf[6]; + regionName.extract(buf,6,status); + if ( rangeMarkerLocation > 0 ) { + char16_t endRange = regionName.charAt(rangeMarkerLocation+1); + buf[rangeMarkerLocation] = 0; + while ( buf[rangeMarkerLocation-1] <= endRange && U_SUCCESS(status)) { + LocalPointer newRegion(new UnicodeString(buf), status); + newMacroRegions->adoptElement(newRegion.orphan(),status); + buf[rangeMarkerLocation-1]++; + } + } else { + LocalPointer newRegion(new UnicodeString(regionName), status); + newMacroRegions->adoptElement(newRegion.orphan(),status); + } + } + return newMacroRegions.orphan(); +} + } // namespace void U_CALLCONV XLikelySubtags::initLikelySubtags(UErrorCode &errorCode) { @@ -357,10 +395,14 @@ void U_CALLCONV XLikelySubtags::initLikelySubtags(UErrorCode &errorCode) { data.load(errorCode); if (U_FAILURE(errorCode)) { return; } gLikelySubtags = new XLikelySubtags(data); - if (gLikelySubtags == nullptr) { + gMacroregions = loadMacroregions(errorCode); + if (U_FAILURE(errorCode) || gLikelySubtags == nullptr || gMacroregions == nullptr) { + delete gLikelySubtags; + delete gMacroregions; errorCode = U_MEMORY_ALLOCATION_ERROR; return; } + ucln_common_registerCleanup(UCLN_COMMON_LIKELY_SUBTAGS, cleanup); } @@ -411,15 +453,28 @@ XLikelySubtags::~XLikelySubtags() { delete[] lsrs; } -LSR XLikelySubtags::makeMaximizedLsrFrom(const Locale &locale, UErrorCode &errorCode) const { +LSR XLikelySubtags::makeMaximizedLsrFrom(const Locale &locale, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const { const char *name = locale.getName(); if (uprv_isAtSign(name[0]) && name[1] == 'x' && name[2] == '=') { // name.startsWith("@x=") // Private use language tag x-subtag-subtag... which CLDR changes to // und-x-subtag-subtag... return LSR(name, "", "", LSR::EXPLICIT_LSR); } - return makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), - locale.getVariant(), errorCode); + LSR max = makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), + locale.getVariant(), returnInputIfUnmatch, errorCode); + + if (uprv_strlen(max.language) == 0 && + uprv_strlen(max.script) == 0 && + uprv_strlen(max.region) == 0) { + // No match. ICU API mandate us to + // If the provided ULocale instance is already in the maximal form, or + // there is no data available available for maximization, it will be + // returned. + return LSR(locale.getLanguage(), locale.getScript(), locale.getCountry(), LSR::EXPLICIT_LSR, errorCode); + } + return max; } namespace { @@ -432,7 +487,9 @@ const char *getCanonical(const CharStringMap &aliases, const char *alias) { } // namespace LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, const char *region, - const char *variant, UErrorCode &errorCode) const { + const char *variant, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const { // Handle pseudolocales like en-XA, ar-XB, fr-PSCRACK. // They should match only themselves, // not other locales with what looks like the same language and script subtags. @@ -472,64 +529,91 @@ LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, c language = getCanonical(languageAliases, language); // (We have no script mappings.) region = getCanonical(regionAliases, region); - return maximize(language, script, region); + return maximize(language, script, region, returnInputIfUnmatch, errorCode); } -LSR XLikelySubtags::maximize(const char *language, const char *script, const char *region) const { - if (uprv_strcmp(language, "und") == 0) { +LSR XLikelySubtags::maximize(const char *language, const char *script, const char *region, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const { + return maximize({language, (int32_t)uprv_strlen(language)}, + {script, (int32_t)uprv_strlen(script)}, + {region, (int32_t)uprv_strlen(region)}, + returnInputIfUnmatch, + errorCode); +} + +bool XLikelySubtags::isMacroregion(StringPiece& region, UErrorCode& errorCode) const { + // In Java, we use Region class. In C++, since Region is under i18n, + // we read the same data used by Region into gMacroregions avoid dependency + // from common to i18n/region.cpp + if (U_FAILURE(errorCode)) { return false; } + umtx_initOnce(gInitOnce, &XLikelySubtags::initLikelySubtags, errorCode); + if (U_FAILURE(errorCode)) { return false; } + UnicodeString str(UnicodeString::fromUTF8(region)); + return gMacroregions->contains((void *)&str); +} + +LSR XLikelySubtags::maximize(StringPiece language, StringPiece script, StringPiece region, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { + return LSR(language, script, region, LSR::EXPLICIT_LSR, errorCode); + } + if (language.compare("und") == 0) { language = ""; } - if (uprv_strcmp(script, "Zzzz") == 0) { + if (script.compare("Zzzz") == 0) { script = ""; } - if (uprv_strcmp(region, "ZZ") == 0) { + if (region.compare("ZZ") == 0) { region = ""; } - if (*script != 0 && *region != 0 && *language != 0) { - return LSR(language, script, region, LSR::EXPLICIT_LSR); // already maximized + if (!script.empty() && !region.empty() && !language.empty()) { + return LSR(language, script, region, LSR::EXPLICIT_LSR, errorCode); // already maximized } + bool retainLanguage = false; + bool retainScript = false; + bool retainRegion = false; - uint32_t retainOldMask = 0; BytesTrie iter(trie); uint64_t state; int32_t value; // Small optimization: Array lookup for first language letter. int32_t c0; - if (0 <= (c0 = uprv_lowerOrdinal(language[0])) && c0 <= 25 && - language[1] != 0 && // language.length() >= 2 + if (0 <= (c0 = uprv_lowerOrdinal(language.data()[0])) && c0 <= 25 && + language.length() >= 2 && (state = trieFirstLetterStates[c0]) != 0) { value = trieNext(iter.resetToState64(state), language, 1); } else { value = trieNext(iter, language, 0); } + bool matchLanguage = (value >= 0); + bool matchScript = false; if (value >= 0) { - if (*language != 0) { - retainOldMask |= 4; - } + retainLanguage = !language.empty(); state = iter.getState64(); } else { - retainOldMask |= 4; + retainLanguage = true; iter.resetToState64(trieUndState); // "und" ("*") state = 0; } + if (value >= 0 && !script.empty()) { + matchScript = true; + } if (value > 0) { // Intermediate or final value from just language. if (value == SKIP_SCRIPT) { value = 0; } - if (*script != 0) { - retainOldMask |= 2; - } + retainScript = !script.empty(); } else { value = trieNext(iter, script, 0); if (value >= 0) { - if (*script != 0) { - retainOldMask |= 2; - } + retainScript = !script.empty(); state = iter.getState64(); } else { - retainOldMask |= 2; + retainScript = true; if (state == 0) { iter.resetToState64(trieUndZzzzState); // "und-Zzzz" ("**") } else { @@ -541,19 +625,19 @@ LSR XLikelySubtags::maximize(const char *language, const char *script, const cha } } + bool matchRegion = false; if (value > 0) { // Final value from just language or language+script. - if (*region != 0) { - retainOldMask |= 1; - } + retainRegion = !region.empty(); } else { value = trieNext(iter, region, 0); if (value >= 0) { - if (*region != 0) { - retainOldMask |= 1; + if (!region.empty() && !isMacroregion(region, errorCode)) { + retainRegion = true; + matchRegion = true; } } else { - retainOldMask |= 1; + retainRegion = true; if (state == 0) { value = defaultLsrIndex; } else { @@ -564,28 +648,33 @@ LSR XLikelySubtags::maximize(const char *language, const char *script, const cha } } U_ASSERT(value < lsrsLength); - const LSR &result = lsrs[value]; + const LSR &matched = lsrs[value]; - if (*language == 0) { - language = "und"; + if (returnInputIfUnmatch && + (!(matchLanguage || matchScript || (matchRegion && language.empty())))) { + return LSR("", "", "", LSR::EXPLICIT_LSR, errorCode); // no matching. + } + if (language.empty()) { + language = StringPiece("und"); } - if (retainOldMask == 0) { + if (!(retainLanguage || retainScript || retainRegion)) { // Quickly return a copy of the lookup-result LSR // without new allocation of the subtags. - return LSR(result.language, result.script, result.region, result.flags); + return LSR(matched.language, matched.script, matched.region, matched.flags); } - if ((retainOldMask & 4) == 0) { - language = result.language; + if (!retainLanguage) { + language = matched.language; } - if ((retainOldMask & 2) == 0) { - script = result.script; + if (!retainScript) { + script = matched.script; } - if ((retainOldMask & 1) == 0) { - region = result.region; + if (!retainRegion) { + region = matched.region; } + int32_t retainMask = (retainLanguage ? 4 : 0) + (retainScript ? 2 : 0) + (retainRegion ? 1 : 0); // retainOldMask flags = LSR explicit-subtag flags - return LSR(language, script, region, retainOldMask); + return LSR(language, script, region, retainMask, errorCode); } int32_t XLikelySubtags::compareLikely(const LSR &lsr, const LSR &other, int32_t likelyInfo) const { @@ -721,57 +810,97 @@ int32_t XLikelySubtags::trieNext(BytesTrie &iter, const char *s, int32_t i) { default: return -1; } } +int32_t XLikelySubtags::trieNext(BytesTrie &iter, StringPiece s, int32_t i) { + UStringTrieResult result; + uint8_t c; + if (s.length() == i) { + result = iter.next(u'*'); + } else { + c = s.data()[i]; + for (;;) { + c = uprv_invCharToAscii(c); + // EBCDIC: If s[i] is not an invariant character, + // then c is now 0 and will simply not match anything, which is harmless. + if (i+1 != s.length()) { + if (!USTRINGTRIE_HAS_NEXT(iter.next(c))) { + return -1; + } + c = s.data()[++i]; + } else { + // last character of this subtag + result = iter.next(c | 0x80); + break; + } + } + } + switch (result) { + case USTRINGTRIE_NO_MATCH: return -1; + case USTRINGTRIE_NO_VALUE: return 0; + case USTRINGTRIE_INTERMEDIATE_VALUE: + U_ASSERT(iter.getValue() == SKIP_SCRIPT); + return SKIP_SCRIPT; + case USTRINGTRIE_FINAL_VALUE: return iter.getValue(); + default: return -1; + } +} -// TODO(ICU-20777): Switch Locale/uloc_ likely-subtags API from the old code -// in loclikely.cpp to this new code, including activating this -// minimizeSubtags() function. The LocaleMatcher does not minimize. -#if 0 -LSR XLikelySubtags::minimizeSubtags(const char *languageIn, const char *scriptIn, - const char *regionIn, ULocale.Minimize fieldToFavor, +LSR XLikelySubtags::minimizeSubtags(StringPiece language, StringPiece script, + StringPiece region, + bool favorScript, UErrorCode &errorCode) const { - LSR result = maximize(languageIn, scriptIn, regionIn); - - // We could try just a series of checks, like: - // LSR result2 = addLikelySubtags(languageIn, "", ""); - // if result.equals(result2) return result2; - // However, we can optimize 2 of the cases: - // (languageIn, "", "") - // (languageIn, "", regionIn) - - // value00 = lookup(result.language, "", "") - BytesTrie iter = new BytesTrie(trie); - int value = trieNext(iter, result.language, 0); - U_ASSERT(value >= 0); - if (value == 0) { - value = trieNext(iter, "", 0); - U_ASSERT(value >= 0); - if (value == 0) { - value = trieNext(iter, "", 0); - } - } - U_ASSERT(value > 0); - LSR value00 = lsrs[value]; - boolean favorRegionOk = false; - if (result.script.equals(value00.script)) { //script is default - if (result.region.equals(value00.region)) { - return new LSR(result.language, "", "", LSR.DONT_CARE_FLAGS); - } else if (fieldToFavor == ULocale.Minimize.FAVOR_REGION) { - return new LSR(result.language, "", result.region, LSR.DONT_CARE_FLAGS); - } else { - favorRegionOk = true; + LSR max = maximize(language, script, region, true, errorCode); + if (U_FAILURE(errorCode)) { + return max; + } + // If no match, return it. + if (uprv_strlen(max.language) == 0 && + uprv_strlen(max.script) == 0 && + uprv_strlen(max.region) == 0) { + // No match. ICU API mandate us to + // "If this Locale is already in the minimal form, or not valid, or + // there is no data available for minimization, the Locale will be + // unchanged." + return LSR(language, script, region, LSR::EXPLICIT_LSR, errorCode); + } + // try language + LSR test = maximize(max.language, "", "", true, errorCode); + if (U_FAILURE(errorCode)) { + return max; + } + if (test.isEquivalentTo(max)) { + return LSR(max.language, "", "", LSR::DONT_CARE_FLAGS, errorCode); + } + + if (!favorScript) { + // favor Region + // try language and region + test = maximize(max.language, "", max.region, true, errorCode); + if (U_FAILURE(errorCode)) { + return max; + } + if (test.isEquivalentTo(max)) { + return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode); } } - - // The last case is not as easy to optimize. - // Maybe do later, but for now use the straightforward code. - LSR result2 = maximize(languageIn, scriptIn, ""); - if (result2.equals(result)) { - return new LSR(result.language, result.script, "", LSR.DONT_CARE_FLAGS); - } else if (favorRegionOk) { - return new LSR(result.language, "", result.region, LSR.DONT_CARE_FLAGS); + // try language and script + test = maximize(max.language, max.script, "", true, errorCode); + if (U_FAILURE(errorCode)) { + return max; + } + if (test.isEquivalentTo(max)) { + return LSR(max.language, max.script, "", LSR::DONT_CARE_FLAGS, errorCode); + } + if (favorScript) { + // try language and region + test = maximize(max.language, "", max.region, true, errorCode); + if (U_FAILURE(errorCode)) { + return max; + } + if (test.isEquivalentTo(max)) { + return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode); + } } - return result; + return LSR(max.language, max.script, max.region, LSR::DONT_CARE_FLAGS, errorCode); } -#endif U_NAMESPACE_END diff --git a/icu4c/source/common/loclikelysubtags.h b/icu4c/source/common/loclikelysubtags.h index 14a01a5eac7e..ebd9c153068e 100644 --- a/icu4c/source/common/loclikelysubtags.h +++ b/icu4c/source/common/loclikelysubtags.h @@ -11,6 +11,7 @@ #include "unicode/utypes.h" #include "unicode/bytestrie.h" #include "unicode/locid.h" +#include "unicode/stringpiece.h" #include "unicode/uobject.h" #include "unicode/ures.h" #include "charstrmap.h" @@ -47,7 +48,9 @@ class XLikelySubtags final : public UMemory { static const XLikelySubtags *getSingleton(UErrorCode &errorCode); // VisibleForTesting - LSR makeMaximizedLsrFrom(const Locale &locale, UErrorCode &errorCode) const; + LSR makeMaximizedLsrFrom(const Locale &locale, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const; /** * Tests whether lsr is "more likely" than other. @@ -61,13 +64,9 @@ class XLikelySubtags final : public UMemory { */ int32_t compareLikely(const LSR &lsr, const LSR &other, int32_t likelyInfo) const; - // TODO(ICU-20777): Switch Locale/uloc_ likely-subtags API from the old code - // in loclikely.cpp to this new code, including activating this - // minimizeSubtags() function. The LocaleMatcher does not minimize. -#if 0 - LSR minimizeSubtags(const char *languageIn, const char *scriptIn, const char *regionIn, - ULocale.Minimize fieldToFavor, UErrorCode &errorCode) const; -#endif + LSR minimizeSubtags(StringPiece language, StringPiece script, StringPiece region, + bool favorScript, + UErrorCode &errorCode) const; // visible for LocaleDistance const LocaleDistanceData &getDistanceData() const { return distanceData; } @@ -80,16 +79,25 @@ class XLikelySubtags final : public UMemory { static void initLikelySubtags(UErrorCode &errorCode); LSR makeMaximizedLsr(const char *language, const char *script, const char *region, - const char *variant, UErrorCode &errorCode) const; + const char *variant, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const; /** * Raw access to addLikelySubtags. Input must be in canonical format, eg "en", not "eng" or "EN". */ - LSR maximize(const char *language, const char *script, const char *region) const; + LSR maximize(const char *language, const char *script, const char *region, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const; + LSR maximize(StringPiece language, StringPiece script, StringPiece region, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const; int32_t getLikelyIndex(const char *language, const char *script) const; + bool isMacroregion(StringPiece& region, UErrorCode &errorCode) const; static int32_t trieNext(BytesTrie &iter, const char *s, int32_t i); + static int32_t trieNext(BytesTrie &iter, StringPiece s, int32_t i); UResourceBundle *langInfoBundle; // We could store the strings by value, except that if there were few enough strings, diff --git a/icu4c/source/common/lsr.cpp b/icu4c/source/common/lsr.cpp index 39eb46df27d0..bd231ecdb5e3 100644 --- a/icu4c/source/common/lsr.cpp +++ b/icu4c/source/common/lsr.cpp @@ -31,6 +31,26 @@ LSR::LSR(char prefix, const char *lang, const char *scr, const char *r, int32_t } } +LSR::LSR(StringPiece lang, StringPiece scr, StringPiece r, int32_t f, + UErrorCode &errorCode) : + language(nullptr), script(nullptr), region(nullptr), + regionIndex(indexForRegion(r.data())), flags(f) { + if (U_SUCCESS(errorCode)) { + CharString data; + data.append(lang, errorCode).append('\0', errorCode); + int32_t scriptOffset = data.length(); + data.append(scr, errorCode).append('\0', errorCode); + int32_t regionOffset = data.length(); + data.append(r, errorCode); + owned = data.cloneData(errorCode); + if (U_SUCCESS(errorCode)) { + language = owned; + script = owned + scriptOffset; + region = owned + regionOffset; + } + } +} + LSR::LSR(LSR &&other) noexcept : language(other.language), script(other.script), region(other.region), owned(other.owned), regionIndex(other.regionIndex), flags(other.flags), diff --git a/icu4c/source/common/lsr.h b/icu4c/source/common/lsr.h index a2f7c8bb155b..313286e93d85 100644 --- a/icu4c/source/common/lsr.h +++ b/icu4c/source/common/lsr.h @@ -7,6 +7,7 @@ #ifndef __LSR_H__ #define __LSR_H__ +#include "unicode/stringpiece.h" #include "unicode/utypes.h" #include "unicode/uobject.h" #include "cstring.h" @@ -45,6 +46,8 @@ struct LSR final : public UMemory { */ LSR(char prefix, const char *lang, const char *scr, const char *r, int32_t f, UErrorCode &errorCode); + LSR(StringPiece lang, StringPiece scr, StringPiece r, int32_t f, + UErrorCode &errorCode); LSR(LSR &&other) noexcept; LSR(const LSR &other) = delete; inline ~LSR() { diff --git a/icu4c/source/common/ulocimp.h b/icu4c/source/common/ulocimp.h index 48341054e31c..91f4d87072f1 100644 --- a/icu4c/source/common/ulocimp.h +++ b/icu4c/source/common/ulocimp.h @@ -237,6 +237,7 @@ ulocimp_addLikelySubtags(const char* localeID, * * @param localeID The locale to minimize * @param sink The output sink receiving the maximized locale + * @param favorScript favor to keep script if true, region if false. * @param err Error information if minimizing the locale failed. If the length * of the localeID and the null-terminator is greater than the maximum allowed size, * or the localeId is not well-formed, the error code is U_ILLEGAL_ARGUMENT_ERROR. @@ -245,6 +246,7 @@ ulocimp_addLikelySubtags(const char* localeID, U_CAPI void U_EXPORT2 ulocimp_minimizeSubtags(const char* localeID, icu::ByteSink& sink, + bool favorScript, UErrorCode* err); U_CAPI const char * U_EXPORT2 diff --git a/icu4c/source/common/unicode/locid.h b/icu4c/source/common/unicode/locid.h index 36575f13f2ce..f0bdc7ca5141 100644 --- a/icu4c/source/common/unicode/locid.h +++ b/icu4c/source/common/unicode/locid.h @@ -1113,6 +1113,15 @@ class U_COMMON_API Locale : public UObject { * @internal */ void setFromPOSIXID(const char *posixID); + /** + * Minimize the subtags for this Locale, per the algorithm described + * @param favorScript favor to keep script if true, to keep region if false. + * @param status error information if maximizing this Locale failed. + * If this Locale is not well-formed, the error code is + * U_ILLEGAL_ARGUMENT_ERROR. + * @internal + */ + void minimizeSubtags(bool favorScript, UErrorCode& status); #endif /* U_HIDE_INTERNAL_API */ private: diff --git a/icu4c/source/test/cintltst/cloctst.c b/icu4c/source/test/cintltst/cloctst.c index 3edd878513b0..f28cdd108e14 100644 --- a/icu4c/source/test/cintltst/cloctst.c +++ b/icu4c/source/test/cintltst/cloctst.c @@ -4605,8 +4605,8 @@ const char* const full_data[][3] = { "am" }, { "und_Ethi_ER", - "am_Ethi_ER", - "am_ER" + "ti_Ethi_ER", + "ti_ER" }, { "und_FI", "fi_Latn_FI", @@ -5381,8 +5381,8 @@ const char* const full_data[][3] = { "trv" }, { "und_Latn_HK", - "zh_Latn_HK", - "zh_Latn_HK" + "en_Latn_HK", + "en_HK" }, { "und_Latn_AQ", "_Latn_AQ", diff --git a/icu4c/source/test/depstest/dependencies.txt b/icu4c/source/test/depstest/dependencies.txt index ca5027ed5cb6..e458961c582b 100644 --- a/icu4c/source/test/depstest/dependencies.txt +++ b/icu4c/source/test/depstest/dependencies.txt @@ -655,17 +655,19 @@ group: resourcebundle localebuilder.o ulocale.o ulocbuilder.o + loclikelysubtags.o deps udata ucol_swp sort stringenumeration uhash uvector uscript_props propname bytesinkutil errorcode + lsr group: localematcher localematcher.o deps - resourcebundle localeprioritylist loclikelysubtags locdistance lsr + resourcebundle localeprioritylist locdistance group: localeprioritylist localeprioritylist.o @@ -675,12 +677,7 @@ group: localeprioritylist group: locdistance locdistance.o deps - loclikelysubtags - -group: loclikelysubtags - loclikelysubtags.o - deps - lsr resourcebundle + resourcebundle group: lsr lsr.o diff --git a/icu4c/source/test/intltest/loctest.cpp b/icu4c/source/test/intltest/loctest.cpp index 23dda8bc2633..ca5184ecc50b 100644 --- a/icu4c/source/test/intltest/loctest.cpp +++ b/icu4c/source/test/intltest/loctest.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "loctest.h" #include "unicode/localebuilder.h" @@ -234,6 +235,7 @@ void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, c TESTCASE_AUTO(TestAddLikelySubtags); TESTCASE_AUTO(TestMinimizeSubtags); TESTCASE_AUTO(TestAddLikelyAndMinimizeSubtags); + TESTCASE_AUTO(TestDataDrivenLikelySubtags); TESTCASE_AUTO(TestKeywordVariants); TESTCASE_AUTO(TestCreateUnicodeKeywords); TESTCASE_AUTO(TestKeywordVariantParsing); @@ -1711,6 +1713,11 @@ LocaleTest::TestAddLikelyAndMinimizeSubtags() { const char* const add; const char* const remove; } full_data[] = { + { + "und", + "en_Latn_US", + "en" + }, { "und_AQ", "_Latn_AQ", @@ -2517,8 +2524,8 @@ LocaleTest::TestAddLikelyAndMinimizeSubtags() { "am" }, { "und_Ethi_ER", - "am_Ethi_ER", - "am_ER" + "ti_Ethi_ER", + "ti_ER" }, { "und_FI", "fi_Latn_FI", @@ -3293,8 +3300,8 @@ LocaleTest::TestAddLikelyAndMinimizeSubtags() { "trv" }, { "und_Latn_HK", - "zh_Latn_HK", - "zh_Latn_HK" + "en_Latn_HK", + "en_HK" }, { "und_Latn_AQ", "_Latn_AQ", @@ -3865,7 +3872,6 @@ LocaleTest::TestAddLikelyAndMinimizeSubtags() { } } - void LocaleTest::TestKeywordVariants() { static const struct { @@ -5546,6 +5552,184 @@ void LocaleTest::TestLocaleCanonicalizationFromFile() } } +std::string trim(const std::string &s) { + auto start = s.begin(); + while (start != s.end() && std::isspace(*start)) { + start++; + } + + auto end = s.end(); + do { + end--; + } while (std::distance(start, end) > 0 && std::isspace(*end)); + + return std::string(start, end + 1); +} + +// A testing helper class which favorScript when minimizeSubtags. +class FavorScriptLocale : public Locale { +public: + FavorScriptLocale(const Locale& l) :Locale(l) { } + void minimizeSubtags(UErrorCode& status) { + Locale::minimizeSubtags(true, status); + } +}; + + +bool isKnownSourceFor20777(const std::string& s) { + return s == "und-001" || + s == "und-AQ" || + s == "und-CC" || + s == "und-SL" || + s == "und-SS" || + s == "und-ZM" || + s.find("und-Latn-") == 0; +} + +void U_CALLCONV +testLikelySubtagsLineFn(void *context, + char *fields[][2], int32_t fieldCount, + UErrorCode *pErrorCode) { + (void)fieldCount; + LocaleTest* THIS = (LocaleTest*)context; + std::string source(trim(std::string(fields[0][0], fields[0][1]-fields[0][0]))); + std::string addLikely(trim(std::string(fields[1][0], fields[1][1]-fields[1][0]))); + std::string removeFavorScript(trim(std::string(fields[2][0], fields[2][1]-fields[2][0]))); + if (removeFavorScript.length() == 0) { + removeFavorScript = addLikely; + } + std::string removeFavorRegion(trim(std::string(fields[3][0], fields[3][1]-fields[3][0]))); + + if (removeFavorRegion.length() == 0) { + removeFavorRegion = removeFavorScript; + } + Locale l = Locale::forLanguageTag(source, *pErrorCode); + if (U_FAILURE(*pErrorCode)) { + THIS->errln("forLanguageTag(%s) return error %x %s", source.c_str(), + *pErrorCode, u_errorName(*pErrorCode)); + *pErrorCode = U_ZERO_ERROR; + return; + } + + Locale actualMax(l); + actualMax.addLikelySubtags(*pErrorCode); + if (addLikely == "FAIL") { + if (uprv_strcmp(l.getName(), actualMax.getName()) != 0) { + THIS->errln("addLikelySubtags('%s') return should return the same but return '%s'", + l.getName(), actualMax.getName()); + } + } else { + std::string max = actualMax.toLanguageTag(*pErrorCode); + if (U_FAILURE(*pErrorCode)) { + THIS->errln("toLanguageTag(%s) return error %x %s", actualMax.getName(), + *pErrorCode, u_errorName(*pErrorCode)); + *pErrorCode = U_ZERO_ERROR; + } else { + if (max != addLikely) { + if (isKnownSourceFor20777(source)) { + THIS->logKnownIssue( + "ICU-20777", "addLikelySubtags('%s') should return '%s' but got '%s'", + source.c_str(), addLikely.c_str(), max.c_str()); + } else { + THIS->errln("addLikelySubtags('%s') should return '%s' but got '%s'", + source.c_str(), addLikely.c_str(), max.c_str()); + } + } + } + } + + Locale actualMin(l); + actualMin.minimizeSubtags(*pErrorCode); + if (removeFavorRegion == "FAIL") { + if (uprv_strcmp(l.getName(), actualMin.getName()) != 0) { + THIS->errln("minimizeSubtags('%s') return should return the same but return '%s'", + l.getName(), actualMin.getName()); + } + } else { + std::string min = actualMin.toLanguageTag(*pErrorCode); + if (U_FAILURE(*pErrorCode)) { + THIS->errln("toLanguageTag(%s) return error %x %s", actualMin.getName(), + *pErrorCode, u_errorName(*pErrorCode)); + *pErrorCode = U_ZERO_ERROR; + } else { + if (min != removeFavorRegion) { + if (isKnownSourceFor20777(source)) { + THIS->logKnownIssue( + "ICU-20777", "minimizeSubtags('%s') should return '%s' but got '%s'", + source.c_str(), removeFavorRegion.c_str(), min.c_str()); + } else { + THIS->errln("minimizeSubtags('%s') should return '%s' but got '%s'", + source.c_str(), removeFavorRegion.c_str(), min.c_str()); + } + } + } + } + + FavorScriptLocale actualMinFavorScript(l); + actualMinFavorScript.minimizeSubtags(*pErrorCode); + if (removeFavorScript == "FAIL") { + if (uprv_strcmp(l.getName(), actualMinFavorScript.getName()) != 0) { + THIS->errln("minimizeSubtags('%s') return should return the same but return '%s'", + l.getName(), actualMinFavorScript.getName()); + } + } else { + std::string min = actualMinFavorScript.toLanguageTag(*pErrorCode); + if (U_FAILURE(*pErrorCode)) { + THIS->errln("toLanguageTag(%s) favor script return error %x %s", actualMinFavorScript.getName(), + *pErrorCode, u_errorName(*pErrorCode)); + *pErrorCode = U_ZERO_ERROR; + } else { + if (min != removeFavorScript) { + if (isKnownSourceFor20777(source)) { + THIS->logKnownIssue( + "ICU-20777", + "minimizeSubtags('%s') favor script should return '%s' but got '%s'", + source.c_str(), removeFavorScript.c_str(), min.c_str()); + } else { + THIS->errln("minimizeSubtags('%s') favor script should return '%s' but got '%s'", + source.c_str(), removeFavorScript.c_str(), min.c_str()); + } + } + } + } +} + +void +LocaleTest::TestDataDrivenLikelySubtags() { + if (quick) { + // This test is too slow to run. Only run in -e mode. + return; + } + IcuTestErrorCode errorCode(*this, "TestDataDrivenLikelySubtags()"); + const char* name = "likelySubtags.txt"; + const char *sourceTestDataPath = getSourceTestData(errorCode); + if (errorCode.errIfFailureAndReset("unable to find the source/test/testdata " + "folder (getSourceTestData())")) { + return; + } + CharString path(sourceTestDataPath, errorCode); + path.appendPathPart(name, errorCode); + LocalStdioFilePointer testFile(fopen(path.data(), "r")); + if (testFile.isNull()) { + errln("unable to open %s", path.data()); + return; + } + + // Columns (c1, c2,...) are separated by semicolons. + // Leading and trailing spaces and tabs in each column are ignored. + // Comments are indicated with hash marks. + const int32_t kNumFields = 4; + char *fields[kNumFields][2]; + + u_parseDelimitedFile(path.data(), ';', fields, kNumFields, testLikelySubtagsLineFn, + this, errorCode); + if (errorCode.errIfFailureAndReset("error parsing %s", name)) { + return; + } +} + + + void LocaleTest::TestKnownCanonicalizedListCorrect() { IcuTestErrorCode status(*this, "TestKnownCanonicalizedListCorrect"); diff --git a/icu4c/source/test/intltest/loctest.h b/icu4c/source/test/intltest/loctest.h index 7d1af3cd6158..80e03e959838 100644 --- a/icu4c/source/test/intltest/loctest.h +++ b/icu4c/source/test/intltest/loctest.h @@ -131,6 +131,7 @@ class LocaleTest: public IntlTest { void TestAddLikelySubtags(); void TestMinimizeSubtags(); void TestAddLikelyAndMinimizeSubtags(); + void TestDataDrivenLikelySubtags(); void TestForLanguageTag(); void TestForLanguageTagLegacyTagBug21676(); diff --git a/icu4c/source/test/testdata/likelySubtags.txt b/icu4c/source/test/testdata/likelySubtags.txt new file mode 100644 index 000000000000..4482b13397ba --- /dev/null +++ b/icu4c/source/test/testdata/likelySubtags.txt @@ -0,0 +1,1607 @@ +# Test data for Likely Subtags +# Copyright © 1991-2023 Unicode, Inc. +# For terms of use, see http://www.unicode.org/copyright.html +# SPDX-License-Identifier: Unicode-DFS-2016 +# CLDR data files are interpreted according to the LDML specification (http://unicode.org/reports/tr35/) +# +# Test data for https://www.unicode.org/reports/tr35/tr35.html#Likely_Subtags +# +# Format: + +# Source ; AddLikely ; RemoveFavorScript ; RemoveFavorRegion +# Source: a locale to which the following operations are applied. +# AddLikely: the result of the Add Likely Subtags. +# If Add Likely Subtags fails, then “FAIL”. +# RemoveFavorScript: Remove Likely Subtags, when the script is favored. +# Only included when different than AddLikely. +# RemoveFavorRegion: Remove Likely Subtags, when the region is favored. +# Only included when different than RemoveFavorScript. +# +# Generation: GenerateLikelyTestData.java + +af ; af-Latn-ZA ; af ; +af-AQ ; af-Latn-AQ ; af-AQ ; +af-Egyp ; af-Egyp-ZA ; af-Egyp ; +af-Latn ; af-Latn-ZA ; af ; +af-NA ; af-Latn-NA ; af-NA ; +af-ZA ; af-Latn-ZA ; af ; +am ; am-Ethi-ET ; am ; +am-AQ ; am-Ethi-AQ ; am-AQ ; +am-ET ; am-Ethi-ET ; am ; +am-Egyp ; am-Egyp-ET ; am-Egyp ; +am-Ethi ; am-Ethi-ET ; am ; +ar ; ar-Arab-EG ; ar ; +ar-001 ; ar-Arab-001 ; ar-001 ; +ar-AE ; ar-Arab-AE ; ar-AE ; +ar-AQ ; ar-Arab-AQ ; ar-AQ ; +ar-Arab ; ar-Arab-EG ; ar ; +ar-BH ; ar-Arab-BH ; ar-BH ; +ar-DJ ; ar-Arab-DJ ; ar-DJ ; +ar-DZ ; ar-Arab-DZ ; ar-DZ ; +ar-EG ; ar-Arab-EG ; ar ; +ar-EH ; ar-Arab-EH ; ar-EH ; +ar-ER ; ar-Arab-ER ; ar-ER ; +ar-Egyp ; ar-Egyp-EG ; ar-Egyp ; +ar-IL ; ar-Arab-IL ; ar-IL ; +ar-IQ ; ar-Arab-IQ ; ar-IQ ; +ar-JO ; ar-Arab-JO ; ar-JO ; +ar-KM ; ar-Arab-KM ; ar-KM ; +ar-KW ; ar-Arab-KW ; ar-KW ; +ar-LB ; ar-Arab-LB ; ar-LB ; +ar-LY ; ar-Arab-LY ; ar-LY ; +ar-MA ; ar-Arab-MA ; ar-MA ; +ar-MR ; ar-Arab-MR ; ar-MR ; +ar-OM ; ar-Arab-OM ; ar-OM ; +ar-PS ; ar-Arab-PS ; ar-PS ; +ar-QA ; ar-Arab-QA ; ar-QA ; +ar-SA ; ar-Arab-SA ; ar-SA ; +ar-SD ; ar-Arab-SD ; ar-SD ; +ar-SO ; ar-Arab-SO ; ar-SO ; +ar-SS ; ar-Arab-SS ; ar-SS ; +ar-SY ; ar-Arab-SY ; ar-SY ; +ar-TD ; ar-Arab-TD ; ar-TD ; +ar-TN ; ar-Arab-TN ; ar-TN ; +ar-YE ; ar-Arab-YE ; ar-YE ; +as ; as-Beng-IN ; as ; +as-AQ ; as-Beng-AQ ; as-AQ ; +as-Beng ; as-Beng-IN ; as ; +as-Egyp ; as-Egyp-IN ; as-Egyp ; +as-IN ; as-Beng-IN ; as ; +ast ; ast-Latn-ES ; ast ; +ast-AQ ; ast-Latn-AQ ; ast-AQ ; +ast-ES ; ast-Latn-ES ; ast ; +ast-Egyp ; ast-Egyp-ES ; ast-Egyp ; +ast-Latn ; ast-Latn-ES ; ast ; +az ; az-Latn-AZ ; az ; +az-AQ ; az-Latn-AQ ; az-AQ ; +az-AZ ; az-Latn-AZ ; az ; +az-Egyp ; az-Egyp-AZ ; az-Egyp ; +az-Latn ; az-Latn-AZ ; az ; +be ; be-Cyrl-BY ; be ; +be-AQ ; be-Cyrl-AQ ; be-AQ ; +be-BY ; be-Cyrl-BY ; be ; +be-Cyrl ; be-Cyrl-BY ; be ; +be-Egyp ; be-Egyp-BY ; be-Egyp ; +bg ; bg-Cyrl-BG ; bg ; +bg-AQ ; bg-Cyrl-AQ ; bg-AQ ; +bg-BG ; bg-Cyrl-BG ; bg ; +bg-Cyrl ; bg-Cyrl-BG ; bg ; +bg-Egyp ; bg-Egyp-BG ; bg-Egyp ; +bgc ; bgc-Deva-IN ; bgc ; +bgc-AQ ; bgc-Deva-AQ ; bgc-AQ ; +bgc-Deva ; bgc-Deva-IN ; bgc ; +bgc-Egyp ; bgc-Egyp-IN ; bgc-Egyp ; +bgc-IN ; bgc-Deva-IN ; bgc ; +bho ; bho-Deva-IN ; bho ; +bho-AQ ; bho-Deva-AQ ; bho-AQ ; +bho-Deva ; bho-Deva-IN ; bho ; +bho-Egyp ; bho-Egyp-IN ; bho-Egyp ; +bho-IN ; bho-Deva-IN ; bho ; +blo ; blo-Latn-BJ ; blo ; +blo-AQ ; blo-Latn-AQ ; blo-AQ ; +blo-BJ ; blo-Latn-BJ ; blo ; +blo-Egyp ; blo-Egyp-BJ ; blo-Egyp ; +blo-Latn ; blo-Latn-BJ ; blo ; +bn ; bn-Beng-BD ; bn ; +bn-AQ ; bn-Beng-AQ ; bn-AQ ; +bn-BD ; bn-Beng-BD ; bn ; +bn-Beng ; bn-Beng-BD ; bn ; +bn-Egyp ; bn-Egyp-BD ; bn-Egyp ; +bn-IN ; bn-Beng-IN ; bn-IN ; +br ; br-Latn-FR ; br ; +br-AQ ; br-Latn-AQ ; br-AQ ; +br-Egyp ; br-Egyp-FR ; br-Egyp ; +br-FR ; br-Latn-FR ; br ; +br-Latn ; br-Latn-FR ; br ; +brx ; brx-Deva-IN ; brx ; +brx-AQ ; brx-Deva-AQ ; brx-AQ ; +brx-Deva ; brx-Deva-IN ; brx ; +brx-Egyp ; brx-Egyp-IN ; brx-Egyp ; +brx-IN ; brx-Deva-IN ; brx ; +bs ; bs-Latn-BA ; bs ; +bs-AQ ; bs-Latn-AQ ; bs-AQ ; +bs-BA ; bs-Latn-BA ; bs ; +bs-Cyrl ; bs-Cyrl-BA ; bs-Cyrl ; +bs-Egyp ; bs-Egyp-BA ; bs-Egyp ; +bs-Latn ; bs-Latn-BA ; bs ; +ca ; ca-Latn-ES ; ca ; +ca-AD ; ca-Latn-AD ; ca-AD ; +ca-AQ ; ca-Latn-AQ ; ca-AQ ; +ca-ES ; ca-Latn-ES ; ca ; +ca-Egyp ; ca-Egyp-ES ; ca-Egyp ; +ca-FR ; ca-Latn-FR ; ca-FR ; +ca-IT ; ca-Latn-IT ; ca-IT ; +ca-Latn ; ca-Latn-ES ; ca ; +ceb ; ceb-Latn-PH ; ceb ; +ceb-AQ ; ceb-Latn-AQ ; ceb-AQ ; +ceb-Egyp ; ceb-Egyp-PH ; ceb-Egyp ; +ceb-Latn ; ceb-Latn-PH ; ceb ; +ceb-PH ; ceb-Latn-PH ; ceb ; +chr ; chr-Cher-US ; chr ; +chr-AQ ; chr-Cher-AQ ; chr-AQ ; +chr-Cher ; chr-Cher-US ; chr ; +chr-Egyp ; chr-Egyp-US ; chr-Egyp ; +chr-US ; chr-Cher-US ; chr ; +cs ; cs-Latn-CZ ; cs ; +cs-AQ ; cs-Latn-AQ ; cs-AQ ; +cs-CZ ; cs-Latn-CZ ; cs ; +cs-Egyp ; cs-Egyp-CZ ; cs-Egyp ; +cs-Latn ; cs-Latn-CZ ; cs ; +csw ; csw-Cans-CA ; csw ; +csw-AQ ; csw-Cans-AQ ; csw-AQ ; +csw-CA ; csw-Cans-CA ; csw ; +csw-Cans ; csw-Cans-CA ; csw ; +csw-Egyp ; csw-Egyp-CA ; csw-Egyp ; +cv ; cv-Cyrl-RU ; cv ; +cv-AQ ; cv-Cyrl-AQ ; cv-AQ ; +cv-Cyrl ; cv-Cyrl-RU ; cv ; +cv-Egyp ; cv-Egyp-RU ; cv-Egyp ; +cv-RU ; cv-Cyrl-RU ; cv ; +cy ; cy-Latn-GB ; cy ; +cy-AQ ; cy-Latn-AQ ; cy-AQ ; +cy-Egyp ; cy-Egyp-GB ; cy-Egyp ; +cy-GB ; cy-Latn-GB ; cy ; +cy-Latn ; cy-Latn-GB ; cy ; +da ; da-Latn-DK ; da ; +da-AQ ; da-Latn-AQ ; da-AQ ; +da-DK ; da-Latn-DK ; da ; +da-Egyp ; da-Egyp-DK ; da-Egyp ; +da-GL ; da-Latn-GL ; da-GL ; +da-Latn ; da-Latn-DK ; da ; +de ; de-Latn-DE ; de ; +de-AQ ; de-Latn-AQ ; de-AQ ; +de-AT ; de-Latn-AT ; de-AT ; +de-BE ; de-Latn-BE ; de-BE ; +de-CH ; de-Latn-CH ; de-CH ; +de-DE ; de-Latn-DE ; de ; +de-Egyp ; de-Egyp-DE ; de-Egyp ; +de-IT ; de-Latn-IT ; de-IT ; +de-LI ; de-Latn-LI ; de-LI ; +de-LU ; de-Latn-LU ; de-LU ; +de-Latn ; de-Latn-DE ; de ; +doi ; doi-Deva-IN ; doi ; +doi-AQ ; doi-Deva-AQ ; doi-AQ ; +doi-Deva ; doi-Deva-IN ; doi ; +doi-Egyp ; doi-Egyp-IN ; doi-Egyp ; +doi-IN ; doi-Deva-IN ; doi ; +dsb ; dsb-Latn-DE ; dsb ; +dsb-AQ ; dsb-Latn-AQ ; dsb-AQ ; +dsb-DE ; dsb-Latn-DE ; dsb ; +dsb-Egyp ; dsb-Egyp-DE ; dsb-Egyp ; +dsb-Latn ; dsb-Latn-DE ; dsb ; +el ; el-Grek-GR ; el ; +el-AQ ; el-Grek-AQ ; el-AQ ; +el-CY ; el-Grek-CY ; el-CY ; +el-Egyp ; el-Egyp-GR ; el-Egyp ; +el-GR ; el-Grek-GR ; el ; +el-Grek ; el-Grek-GR ; el ; +en ; en-Latn-US ; en ; +en-001 ; en-Latn-001 ; en-001 ; +en-150 ; en-Latn-150 ; en-150 ; +en-AE ; en-Latn-AE ; en-AE ; +en-AG ; en-Latn-AG ; en-AG ; +en-AI ; en-Latn-AI ; en-AI ; +en-AQ ; en-Latn-AQ ; en-AQ ; +en-AS ; en-Latn-AS ; en-AS ; +en-AT ; en-Latn-AT ; en-AT ; +en-AU ; en-Latn-AU ; en-AU ; +en-BB ; en-Latn-BB ; en-BB ; +en-BE ; en-Latn-BE ; en-BE ; +en-BI ; en-Latn-BI ; en-BI ; +en-BM ; en-Latn-BM ; en-BM ; +en-BS ; en-Latn-BS ; en-BS ; +en-BW ; en-Latn-BW ; en-BW ; +en-BZ ; en-Latn-BZ ; en-BZ ; +en-CA ; en-Latn-CA ; en-CA ; +en-CC ; en-Latn-CC ; en-CC ; +en-CH ; en-Latn-CH ; en-CH ; +en-CK ; en-Latn-CK ; en-CK ; +en-CM ; en-Latn-CM ; en-CM ; +en-CX ; en-Latn-CX ; en-CX ; +en-CY ; en-Latn-CY ; en-CY ; +en-DE ; en-Latn-DE ; en-DE ; +en-DG ; en-Latn-DG ; en-DG ; +en-DK ; en-Latn-DK ; en-DK ; +en-DM ; en-Latn-DM ; en-DM ; +en-ER ; en-Latn-ER ; en-ER ; +en-Egyp ; en-Egyp-US ; en-Egyp ; +en-FI ; en-Latn-FI ; en-FI ; +en-FJ ; en-Latn-FJ ; en-FJ ; +en-FK ; en-Latn-FK ; en-FK ; +en-FM ; en-Latn-FM ; en-FM ; +en-GB ; en-Latn-GB ; en-GB ; +en-GD ; en-Latn-GD ; en-GD ; +en-GG ; en-Latn-GG ; en-GG ; +en-GH ; en-Latn-GH ; en-GH ; +en-GI ; en-Latn-GI ; en-GI ; +en-GM ; en-Latn-GM ; en-GM ; +en-GU ; en-Latn-GU ; en-GU ; +en-GY ; en-Latn-GY ; en-GY ; +en-HK ; en-Latn-HK ; en-HK ; +en-IE ; en-Latn-IE ; en-IE ; +en-IL ; en-Latn-IL ; en-IL ; +en-IM ; en-Latn-IM ; en-IM ; +en-IN ; en-Latn-IN ; en-IN ; +en-IO ; en-Latn-IO ; en-IO ; +en-JE ; en-Latn-JE ; en-JE ; +en-JM ; en-Latn-JM ; en-JM ; +en-KE ; en-Latn-KE ; en-KE ; +en-KI ; en-Latn-KI ; en-KI ; +en-KN ; en-Latn-KN ; en-KN ; +en-KY ; en-Latn-KY ; en-KY ; +en-LC ; en-Latn-LC ; en-LC ; +en-LR ; en-Latn-LR ; en-LR ; +en-LS ; en-Latn-LS ; en-LS ; +en-Latn ; en-Latn-US ; en ; +en-MG ; en-Latn-MG ; en-MG ; +en-MH ; en-Latn-MH ; en-MH ; +en-MO ; en-Latn-MO ; en-MO ; +en-MP ; en-Latn-MP ; en-MP ; +en-MS ; en-Latn-MS ; en-MS ; +en-MT ; en-Latn-MT ; en-MT ; +en-MU ; en-Latn-MU ; en-MU ; +en-MV ; en-Latn-MV ; en-MV ; +en-MW ; en-Latn-MW ; en-MW ; +en-MY ; en-Latn-MY ; en-MY ; +en-NA ; en-Latn-NA ; en-NA ; +en-NF ; en-Latn-NF ; en-NF ; +en-NG ; en-Latn-NG ; en-NG ; +en-NL ; en-Latn-NL ; en-NL ; +en-NR ; en-Latn-NR ; en-NR ; +en-NU ; en-Latn-NU ; en-NU ; +en-NZ ; en-Latn-NZ ; en-NZ ; +en-PG ; en-Latn-PG ; en-PG ; +en-PH ; en-Latn-PH ; en-PH ; +en-PK ; en-Latn-PK ; en-PK ; +en-PN ; en-Latn-PN ; en-PN ; +en-PR ; en-Latn-PR ; en-PR ; +en-PW ; en-Latn-PW ; en-PW ; +en-RW ; en-Latn-RW ; en-RW ; +en-SB ; en-Latn-SB ; en-SB ; +en-SC ; en-Latn-SC ; en-SC ; +en-SD ; en-Latn-SD ; en-SD ; +en-SE ; en-Latn-SE ; en-SE ; +en-SG ; en-Latn-SG ; en-SG ; +en-SH ; en-Latn-SH ; en-SH ; +en-SI ; en-Latn-SI ; en-SI ; +en-SL ; en-Latn-SL ; en-SL ; +en-SS ; en-Latn-SS ; en-SS ; +en-SX ; en-Latn-SX ; en-SX ; +en-SZ ; en-Latn-SZ ; en-SZ ; +en-TC ; en-Latn-TC ; en-TC ; +en-TK ; en-Latn-TK ; en-TK ; +en-TO ; en-Latn-TO ; en-TO ; +en-TT ; en-Latn-TT ; en-TT ; +en-TV ; en-Latn-TV ; en-TV ; +en-TZ ; en-Latn-TZ ; en-TZ ; +en-UG ; en-Latn-UG ; en-UG ; +en-UM ; en-Latn-UM ; en-UM ; +en-US ; en-Latn-US ; en ; +en-VC ; en-Latn-VC ; en-VC ; +en-VG ; en-Latn-VG ; en-VG ; +en-VI ; en-Latn-VI ; en-VI ; +en-VU ; en-Latn-VU ; en-VU ; +en-WS ; en-Latn-WS ; en-WS ; +en-ZA ; en-Latn-ZA ; en-ZA ; +en-ZM ; en-Latn-ZM ; en-ZM ; +en-ZW ; en-Latn-ZW ; en-ZW ; +es ; es-Latn-ES ; es ; +es-419 ; es-Latn-419 ; es-419 ; +es-AQ ; es-Latn-AQ ; es-AQ ; +es-AR ; es-Latn-AR ; es-AR ; +es-BO ; es-Latn-BO ; es-BO ; +es-BR ; es-Latn-BR ; es-BR ; +es-BZ ; es-Latn-BZ ; es-BZ ; +es-CL ; es-Latn-CL ; es-CL ; +es-CO ; es-Latn-CO ; es-CO ; +es-CR ; es-Latn-CR ; es-CR ; +es-CU ; es-Latn-CU ; es-CU ; +es-DO ; es-Latn-DO ; es-DO ; +es-EA ; es-Latn-EA ; es-EA ; +es-EC ; es-Latn-EC ; es-EC ; +es-ES ; es-Latn-ES ; es ; +es-Egyp ; es-Egyp-ES ; es-Egyp ; +es-GQ ; es-Latn-GQ ; es-GQ ; +es-GT ; es-Latn-GT ; es-GT ; +es-HN ; es-Latn-HN ; es-HN ; +es-IC ; es-Latn-IC ; es-IC ; +es-Latn ; es-Latn-ES ; es ; +es-MX ; es-Latn-MX ; es-MX ; +es-NI ; es-Latn-NI ; es-NI ; +es-PA ; es-Latn-PA ; es-PA ; +es-PE ; es-Latn-PE ; es-PE ; +es-PH ; es-Latn-PH ; es-PH ; +es-PR ; es-Latn-PR ; es-PR ; +es-PY ; es-Latn-PY ; es-PY ; +es-SV ; es-Latn-SV ; es-SV ; +es-US ; es-Latn-US ; es-US ; +es-UY ; es-Latn-UY ; es-UY ; +es-VE ; es-Latn-VE ; es-VE ; +et ; et-Latn-EE ; et ; +et-AQ ; et-Latn-AQ ; et-AQ ; +et-EE ; et-Latn-EE ; et ; +et-Egyp ; et-Egyp-EE ; et-Egyp ; +et-Latn ; et-Latn-EE ; et ; +eu ; eu-Latn-ES ; eu ; +eu-AQ ; eu-Latn-AQ ; eu-AQ ; +eu-ES ; eu-Latn-ES ; eu ; +eu-Egyp ; eu-Egyp-ES ; eu-Egyp ; +eu-Latn ; eu-Latn-ES ; eu ; +fa ; fa-Arab-IR ; fa ; +fa-AF ; fa-Arab-AF ; fa-AF ; +fa-AQ ; fa-Arab-AQ ; fa-AQ ; +fa-Arab ; fa-Arab-IR ; fa ; +fa-Egyp ; fa-Egyp-IR ; fa-Egyp ; +fa-IR ; fa-Arab-IR ; fa ; +ff ; ff-Latn-SN ; ff ; +ff-AQ ; ff-Latn-AQ ; ff-AQ ; +ff-Adlm ; ff-Adlm-GN ; ff-Adlm ; +ff-BF ; ff-Latn-BF ; ff-BF ; +ff-CM ; ff-Latn-CM ; ff-CM ; +ff-Egyp ; ff-Egyp-SN ; ff-Egyp ; +ff-GH ; ff-Latn-GH ; ff-GH ; +ff-GM ; ff-Latn-GM ; ff-GM ; +ff-GN ; ff-Latn-GN ; ff-GN ; +ff-GW ; ff-Latn-GW ; ff-GW ; +ff-LR ; ff-Latn-LR ; ff-LR ; +ff-MR ; ff-Latn-MR ; ff-MR ; +ff-NE ; ff-Latn-NE ; ff-NE ; +ff-NG ; ff-Latn-NG ; ff-NG ; +ff-SL ; ff-Latn-SL ; ff-SL ; +ff-SN ; ff-Latn-SN ; ff ; +fi ; fi-Latn-FI ; fi ; +fi-AQ ; fi-Latn-AQ ; fi-AQ ; +fi-Egyp ; fi-Egyp-FI ; fi-Egyp ; +fi-FI ; fi-Latn-FI ; fi ; +fi-Latn ; fi-Latn-FI ; fi ; +fil ; fil-Latn-PH ; fil ; +fil-AQ ; fil-Latn-AQ ; fil-AQ ; +fil-Egyp ; fil-Egyp-PH ; fil-Egyp ; +fil-Latn ; fil-Latn-PH ; fil ; +fil-PH ; fil-Latn-PH ; fil ; +fo ; fo-Latn-FO ; fo ; +fo-AQ ; fo-Latn-AQ ; fo-AQ ; +fo-DK ; fo-Latn-DK ; fo-DK ; +fo-Egyp ; fo-Egyp-FO ; fo-Egyp ; +fo-FO ; fo-Latn-FO ; fo ; +fo-Latn ; fo-Latn-FO ; fo ; +fr ; fr-Latn-FR ; fr ; +fr-AQ ; fr-Latn-AQ ; fr-AQ ; +fr-BE ; fr-Latn-BE ; fr-BE ; +fr-BF ; fr-Latn-BF ; fr-BF ; +fr-BI ; fr-Latn-BI ; fr-BI ; +fr-BJ ; fr-Latn-BJ ; fr-BJ ; +fr-BL ; fr-Latn-BL ; fr-BL ; +fr-CA ; fr-Latn-CA ; fr-CA ; +fr-CD ; fr-Latn-CD ; fr-CD ; +fr-CF ; fr-Latn-CF ; fr-CF ; +fr-CG ; fr-Latn-CG ; fr-CG ; +fr-CH ; fr-Latn-CH ; fr-CH ; +fr-CI ; fr-Latn-CI ; fr-CI ; +fr-CM ; fr-Latn-CM ; fr-CM ; +fr-DJ ; fr-Latn-DJ ; fr-DJ ; +fr-DZ ; fr-Latn-DZ ; fr-DZ ; +fr-Egyp ; fr-Egyp-FR ; fr-Egyp ; +fr-FR ; fr-Latn-FR ; fr ; +fr-GA ; fr-Latn-GA ; fr-GA ; +fr-GF ; fr-Latn-GF ; fr-GF ; +fr-GN ; fr-Latn-GN ; fr-GN ; +fr-GP ; fr-Latn-GP ; fr-GP ; +fr-GQ ; fr-Latn-GQ ; fr-GQ ; +fr-HT ; fr-Latn-HT ; fr-HT ; +fr-KM ; fr-Latn-KM ; fr-KM ; +fr-LU ; fr-Latn-LU ; fr-LU ; +fr-Latn ; fr-Latn-FR ; fr ; +fr-MA ; fr-Latn-MA ; fr-MA ; +fr-MC ; fr-Latn-MC ; fr-MC ; +fr-MF ; fr-Latn-MF ; fr-MF ; +fr-MG ; fr-Latn-MG ; fr-MG ; +fr-ML ; fr-Latn-ML ; fr-ML ; +fr-MQ ; fr-Latn-MQ ; fr-MQ ; +fr-MR ; fr-Latn-MR ; fr-MR ; +fr-MU ; fr-Latn-MU ; fr-MU ; +fr-NC ; fr-Latn-NC ; fr-NC ; +fr-NE ; fr-Latn-NE ; fr-NE ; +fr-PF ; fr-Latn-PF ; fr-PF ; +fr-PM ; fr-Latn-PM ; fr-PM ; +fr-RE ; fr-Latn-RE ; fr-RE ; +fr-RW ; fr-Latn-RW ; fr-RW ; +fr-SC ; fr-Latn-SC ; fr-SC ; +fr-SN ; fr-Latn-SN ; fr-SN ; +fr-SY ; fr-Latn-SY ; fr-SY ; +fr-TD ; fr-Latn-TD ; fr-TD ; +fr-TG ; fr-Latn-TG ; fr-TG ; +fr-TN ; fr-Latn-TN ; fr-TN ; +fr-VU ; fr-Latn-VU ; fr-VU ; +fr-WF ; fr-Latn-WF ; fr-WF ; +fr-YT ; fr-Latn-YT ; fr-YT ; +ga ; ga-Latn-IE ; ga ; +ga-AQ ; ga-Latn-AQ ; ga-AQ ; +ga-Egyp ; ga-Egyp-IE ; ga-Egyp ; +ga-GB ; ga-Latn-GB ; ga-GB ; +ga-IE ; ga-Latn-IE ; ga ; +ga-Latn ; ga-Latn-IE ; ga ; +gd ; gd-Latn-GB ; gd ; +gd-AQ ; gd-Latn-AQ ; gd-AQ ; +gd-Egyp ; gd-Egyp-GB ; gd-Egyp ; +gd-GB ; gd-Latn-GB ; gd ; +gd-Latn ; gd-Latn-GB ; gd ; +gl ; gl-Latn-ES ; gl ; +gl-AQ ; gl-Latn-AQ ; gl-AQ ; +gl-ES ; gl-Latn-ES ; gl ; +gl-Egyp ; gl-Egyp-ES ; gl-Egyp ; +gl-Latn ; gl-Latn-ES ; gl ; +gu ; gu-Gujr-IN ; gu ; +gu-AQ ; gu-Gujr-AQ ; gu-AQ ; +gu-Egyp ; gu-Egyp-IN ; gu-Egyp ; +gu-Gujr ; gu-Gujr-IN ; gu ; +gu-IN ; gu-Gujr-IN ; gu ; +ha ; ha-Latn-NG ; ha ; +ha-AQ ; ha-Latn-AQ ; ha-AQ ; +ha-Egyp ; ha-Egyp-NG ; ha-Egyp ; +ha-GH ; ha-Latn-GH ; ha-GH ; +ha-Latn ; ha-Latn-NG ; ha ; +ha-NE ; ha-Latn-NE ; ha-NE ; +ha-NG ; ha-Latn-NG ; ha ; +he ; he-Hebr-IL ; he ; +he-AQ ; he-Hebr-AQ ; he-AQ ; +he-Egyp ; he-Egyp-IL ; he-Egyp ; +he-Hebr ; he-Hebr-IL ; he ; +he-IL ; he-Hebr-IL ; he ; +hi ; hi-Deva-IN ; hi ; +hi-AQ ; hi-Deva-AQ ; hi-AQ ; +hi-Deva ; hi-Deva-IN ; hi ; +hi-Egyp ; hi-Egyp-IN ; hi-Egyp ; +hi-IN ; hi-Deva-IN ; hi ; +hi-Latn ; hi-Latn-IN ; hi-Latn ; +hr ; hr-Latn-HR ; hr ; +hr-AQ ; hr-Latn-AQ ; hr-AQ ; +hr-BA ; hr-Latn-BA ; hr-BA ; +hr-Egyp ; hr-Egyp-HR ; hr-Egyp ; +hr-HR ; hr-Latn-HR ; hr ; +hr-Latn ; hr-Latn-HR ; hr ; +hsb ; hsb-Latn-DE ; hsb ; +hsb-AQ ; hsb-Latn-AQ ; hsb-AQ ; +hsb-DE ; hsb-Latn-DE ; hsb ; +hsb-Egyp ; hsb-Egyp-DE ; hsb-Egyp ; +hsb-Latn ; hsb-Latn-DE ; hsb ; +hu ; hu-Latn-HU ; hu ; +hu-AQ ; hu-Latn-AQ ; hu-AQ ; +hu-Egyp ; hu-Egyp-HU ; hu-Egyp ; +hu-HU ; hu-Latn-HU ; hu ; +hu-Latn ; hu-Latn-HU ; hu ; +hy ; hy-Armn-AM ; hy ; +hy-AM ; hy-Armn-AM ; hy ; +hy-AQ ; hy-Armn-AQ ; hy-AQ ; +hy-Armn ; hy-Armn-AM ; hy ; +hy-Egyp ; hy-Egyp-AM ; hy-Egyp ; +id ; id-Latn-ID ; id ; +id-AQ ; id-Latn-AQ ; id-AQ ; +id-Egyp ; id-Egyp-ID ; id-Egyp ; +id-ID ; id-Latn-ID ; id ; +id-Latn ; id-Latn-ID ; id ; +ig ; ig-Latn-NG ; ig ; +ig-AQ ; ig-Latn-AQ ; ig-AQ ; +ig-Egyp ; ig-Egyp-NG ; ig-Egyp ; +ig-Latn ; ig-Latn-NG ; ig ; +ig-NG ; ig-Latn-NG ; ig ; +is ; is-Latn-IS ; is ; +is-AQ ; is-Latn-AQ ; is-AQ ; +is-Egyp ; is-Egyp-IS ; is-Egyp ; +is-IS ; is-Latn-IS ; is ; +is-Latn ; is-Latn-IS ; is ; +it ; it-Latn-IT ; it ; +it-AQ ; it-Latn-AQ ; it-AQ ; +it-CH ; it-Latn-CH ; it-CH ; +it-Egyp ; it-Egyp-IT ; it-Egyp ; +it-IT ; it-Latn-IT ; it ; +it-Latn ; it-Latn-IT ; it ; +it-SM ; it-Latn-SM ; it-SM ; +it-VA ; it-Latn-VA ; it-VA ; +ja ; ja-Jpan-JP ; ja ; +ja-AQ ; ja-Jpan-AQ ; ja-AQ ; +ja-Egyp ; ja-Egyp-JP ; ja-Egyp ; +ja-JP ; ja-Jpan-JP ; ja ; +ja-Jpan ; ja-Jpan-JP ; ja ; +jv ; jv-Latn-ID ; jv ; +jv-AQ ; jv-Latn-AQ ; jv-AQ ; +jv-Egyp ; jv-Egyp-ID ; jv-Egyp ; +jv-ID ; jv-Latn-ID ; jv ; +jv-Latn ; jv-Latn-ID ; jv ; +ka ; ka-Geor-GE ; ka ; +ka-AQ ; ka-Geor-AQ ; ka-AQ ; +ka-Egyp ; ka-Egyp-GE ; ka-Egyp ; +ka-GE ; ka-Geor-GE ; ka ; +ka-Geor ; ka-Geor-GE ; ka ; +kea ; kea-Latn-CV ; kea ; +kea-AQ ; kea-Latn-AQ ; kea-AQ ; +kea-CV ; kea-Latn-CV ; kea ; +kea-Egyp ; kea-Egyp-CV ; kea-Egyp ; +kea-Latn ; kea-Latn-CV ; kea ; +kgp ; kgp-Latn-BR ; kgp ; +kgp-AQ ; kgp-Latn-AQ ; kgp-AQ ; +kgp-BR ; kgp-Latn-BR ; kgp ; +kgp-Egyp ; kgp-Egyp-BR ; kgp-Egyp ; +kgp-Latn ; kgp-Latn-BR ; kgp ; +kk ; kk-Cyrl-KZ ; kk ; +kk-AQ ; kk-Cyrl-AQ ; kk-AQ ; +kk-Cyrl ; kk-Cyrl-KZ ; kk ; +kk-Egyp ; kk-Egyp-KZ ; kk-Egyp ; +kk-KZ ; kk-Cyrl-KZ ; kk ; +km ; km-Khmr-KH ; km ; +km-AQ ; km-Khmr-AQ ; km-AQ ; +km-Egyp ; km-Egyp-KH ; km-Egyp ; +km-KH ; km-Khmr-KH ; km ; +km-Khmr ; km-Khmr-KH ; km ; +kn ; kn-Knda-IN ; kn ; +kn-AQ ; kn-Knda-AQ ; kn-AQ ; +kn-Egyp ; kn-Egyp-IN ; kn-Egyp ; +kn-IN ; kn-Knda-IN ; kn ; +kn-Knda ; kn-Knda-IN ; kn ; +ko ; ko-Kore-KR ; ko ; +ko-AQ ; ko-Kore-AQ ; ko-AQ ; +ko-CN ; ko-Kore-CN ; ko-CN ; +ko-Egyp ; ko-Egyp-KR ; ko-Egyp ; +ko-KP ; ko-Kore-KP ; ko-KP ; +ko-KR ; ko-Kore-KR ; ko ; +ko-Kore ; ko-Kore-KR ; ko ; +kok ; kok-Deva-IN ; kok ; +kok-AQ ; kok-Deva-AQ ; kok-AQ ; +kok-Deva ; kok-Deva-IN ; kok ; +kok-Egyp ; kok-Egyp-IN ; kok-Egyp ; +kok-IN ; kok-Deva-IN ; kok ; +ks ; ks-Arab-IN ; ks ; +ks-AQ ; ks-Arab-AQ ; ks-AQ ; +ks-Arab ; ks-Arab-IN ; ks ; +ks-Deva ; ks-Deva-IN ; ks-Deva ; +ks-Egyp ; ks-Egyp-IN ; ks-Egyp ; +ks-IN ; ks-Arab-IN ; ks ; +ku ; ku-Latn-TR ; ku ; +ku-AQ ; ku-Latn-AQ ; ku-AQ ; +ku-Egyp ; ku-Egyp-TR ; ku-Egyp ; +ku-Latn ; ku-Latn-TR ; ku ; +ku-TR ; ku-Latn-TR ; ku ; +kxv ; kxv-Latn-IN ; kxv ; +kxv-AQ ; kxv-Latn-AQ ; kxv-AQ ; +kxv-Deva ; kxv-Deva-IN ; kxv-Deva ; +kxv-Egyp ; kxv-Egyp-IN ; kxv-Egyp ; +kxv-IN ; kxv-Latn-IN ; kxv ; +kxv-Latn ; kxv-Latn-IN ; kxv ; +kxv-Orya ; kxv-Orya-IN ; kxv-Orya ; +kxv-Telu ; kxv-Telu-IN ; kxv-Telu ; +ky ; ky-Cyrl-KG ; ky ; +ky-AQ ; ky-Cyrl-AQ ; ky-AQ ; +ky-Cyrl ; ky-Cyrl-KG ; ky ; +ky-Egyp ; ky-Egyp-KG ; ky-Egyp ; +ky-KG ; ky-Cyrl-KG ; ky ; +lo ; lo-Laoo-LA ; lo ; +lo-AQ ; lo-Laoo-AQ ; lo-AQ ; +lo-Egyp ; lo-Egyp-LA ; lo-Egyp ; +lo-LA ; lo-Laoo-LA ; lo ; +lo-Laoo ; lo-Laoo-LA ; lo ; +lt ; lt-Latn-LT ; lt ; +lt-AQ ; lt-Latn-AQ ; lt-AQ ; +lt-Egyp ; lt-Egyp-LT ; lt-Egyp ; +lt-LT ; lt-Latn-LT ; lt ; +lt-Latn ; lt-Latn-LT ; lt ; +lv ; lv-Latn-LV ; lv ; +lv-AQ ; lv-Latn-AQ ; lv-AQ ; +lv-Egyp ; lv-Egyp-LV ; lv-Egyp ; +lv-LV ; lv-Latn-LV ; lv ; +lv-Latn ; lv-Latn-LV ; lv ; +mai ; mai-Deva-IN ; mai ; +mai-AQ ; mai-Deva-AQ ; mai-AQ ; +mai-Deva ; mai-Deva-IN ; mai ; +mai-Egyp ; mai-Egyp-IN ; mai-Egyp ; +mai-IN ; mai-Deva-IN ; mai ; +mi ; mi-Latn-NZ ; mi ; +mi-AQ ; mi-Latn-AQ ; mi-AQ ; +mi-Egyp ; mi-Egyp-NZ ; mi-Egyp ; +mi-Latn ; mi-Latn-NZ ; mi ; +mi-NZ ; mi-Latn-NZ ; mi ; +mk ; mk-Cyrl-MK ; mk ; +mk-AQ ; mk-Cyrl-AQ ; mk-AQ ; +mk-Cyrl ; mk-Cyrl-MK ; mk ; +mk-Egyp ; mk-Egyp-MK ; mk-Egyp ; +mk-MK ; mk-Cyrl-MK ; mk ; +ml ; ml-Mlym-IN ; ml ; +ml-AQ ; ml-Mlym-AQ ; ml-AQ ; +ml-Egyp ; ml-Egyp-IN ; ml-Egyp ; +ml-IN ; ml-Mlym-IN ; ml ; +ml-Mlym ; ml-Mlym-IN ; ml ; +mn ; mn-Cyrl-MN ; mn ; +mn-AQ ; mn-Cyrl-AQ ; mn-AQ ; +mn-Cyrl ; mn-Cyrl-MN ; mn ; +mn-Egyp ; mn-Egyp-MN ; mn-Egyp ; +mn-MN ; mn-Cyrl-MN ; mn ; +mni ; mni-Beng-IN ; mni ; +mni-AQ ; mni-Beng-AQ ; mni-AQ ; +mni-Beng ; mni-Beng-IN ; mni ; +mni-Egyp ; mni-Egyp-IN ; mni-Egyp ; +mni-IN ; mni-Beng-IN ; mni ; +mr ; mr-Deva-IN ; mr ; +mr-AQ ; mr-Deva-AQ ; mr-AQ ; +mr-Deva ; mr-Deva-IN ; mr ; +mr-Egyp ; mr-Egyp-IN ; mr-Egyp ; +mr-IN ; mr-Deva-IN ; mr ; +ms ; ms-Latn-MY ; ms ; +ms-AQ ; ms-Latn-AQ ; ms-AQ ; +ms-BN ; ms-Latn-BN ; ms-BN ; +ms-Egyp ; ms-Egyp-MY ; ms-Egyp ; +ms-ID ; ms-Latn-ID ; ms-ID ; +ms-Latn ; ms-Latn-MY ; ms ; +ms-MY ; ms-Latn-MY ; ms ; +ms-SG ; ms-Latn-SG ; ms-SG ; +my ; my-Mymr-MM ; my ; +my-AQ ; my-Mymr-AQ ; my-AQ ; +my-Egyp ; my-Egyp-MM ; my-Egyp ; +my-MM ; my-Mymr-MM ; my ; +my-Mymr ; my-Mymr-MM ; my ; +nb ; nb-Latn-NO ; nb ; +nb-AQ ; nb-Latn-AQ ; nb-AQ ; +nb-Egyp ; nb-Egyp-NO ; nb-Egyp ; +nb-Latn ; nb-Latn-NO ; nb ; +nb-NO ; nb-Latn-NO ; nb ; +nb-SJ ; nb-Latn-SJ ; nb-SJ ; +ne ; ne-Deva-NP ; ne ; +ne-AQ ; ne-Deva-AQ ; ne-AQ ; +ne-Deva ; ne-Deva-NP ; ne ; +ne-Egyp ; ne-Egyp-NP ; ne-Egyp ; +ne-IN ; ne-Deva-IN ; ne-IN ; +ne-NP ; ne-Deva-NP ; ne ; +nl ; nl-Latn-NL ; nl ; +nl-AQ ; nl-Latn-AQ ; nl-AQ ; +nl-AW ; nl-Latn-AW ; nl-AW ; +nl-BE ; nl-Latn-BE ; nl-BE ; +nl-BQ ; nl-Latn-BQ ; nl-BQ ; +nl-CW ; nl-Latn-CW ; nl-CW ; +nl-Egyp ; nl-Egyp-NL ; nl-Egyp ; +nl-Latn ; nl-Latn-NL ; nl ; +nl-NL ; nl-Latn-NL ; nl ; +nl-SR ; nl-Latn-SR ; nl-SR ; +nl-SX ; nl-Latn-SX ; nl-SX ; +nn ; nn-Latn-NO ; nn ; +nn-AQ ; nn-Latn-AQ ; nn-AQ ; +nn-Egyp ; nn-Egyp-NO ; nn-Egyp ; +nn-Latn ; nn-Latn-NO ; nn ; +nn-NO ; nn-Latn-NO ; nn ; +no ; no-Latn-NO ; no ; +no-AQ ; no-Latn-AQ ; no-AQ ; +no-Egyp ; no-Egyp-NO ; no-Egyp ; +no-Latn ; no-Latn-NO ; no ; +no-NO ; no-Latn-NO ; no ; +or ; or-Orya-IN ; or ; +or-AQ ; or-Orya-AQ ; or-AQ ; +or-Egyp ; or-Egyp-IN ; or-Egyp ; +or-IN ; or-Orya-IN ; or ; +or-Orya ; or-Orya-IN ; or ; +pa ; pa-Guru-IN ; pa ; +pa-AQ ; pa-Guru-AQ ; pa-AQ ; +pa-Egyp ; pa-Egyp-IN ; pa-Egyp ; +pa-Guru ; pa-Guru-IN ; pa ; +pa-IN ; pa-Guru-IN ; pa ; +pcm ; pcm-Latn-NG ; pcm ; +pcm-AQ ; pcm-Latn-AQ ; pcm-AQ ; +pcm-Egyp ; pcm-Egyp-NG ; pcm-Egyp ; +pcm-Latn ; pcm-Latn-NG ; pcm ; +pcm-NG ; pcm-Latn-NG ; pcm ; +pl ; pl-Latn-PL ; pl ; +pl-AQ ; pl-Latn-AQ ; pl-AQ ; +pl-Egyp ; pl-Egyp-PL ; pl-Egyp ; +pl-Latn ; pl-Latn-PL ; pl ; +pl-PL ; pl-Latn-PL ; pl ; +ps ; ps-Arab-AF ; ps ; +ps-AF ; ps-Arab-AF ; ps ; +ps-AQ ; ps-Arab-AQ ; ps-AQ ; +ps-Arab ; ps-Arab-AF ; ps ; +ps-Egyp ; ps-Egyp-AF ; ps-Egyp ; +ps-PK ; ps-Arab-PK ; ps-PK ; +pt ; pt-Latn-BR ; pt ; +pt-AO ; pt-Latn-AO ; pt-AO ; +pt-AQ ; pt-Latn-AQ ; pt-AQ ; +pt-BR ; pt-Latn-BR ; pt ; +pt-CH ; pt-Latn-CH ; pt-CH ; +pt-CV ; pt-Latn-CV ; pt-CV ; +pt-Egyp ; pt-Egyp-BR ; pt-Egyp ; +pt-GQ ; pt-Latn-GQ ; pt-GQ ; +pt-GW ; pt-Latn-GW ; pt-GW ; +pt-LU ; pt-Latn-LU ; pt-LU ; +pt-Latn ; pt-Latn-BR ; pt ; +pt-MO ; pt-Latn-MO ; pt-MO ; +pt-MZ ; pt-Latn-MZ ; pt-MZ ; +pt-PT ; pt-Latn-PT ; pt-PT ; +pt-ST ; pt-Latn-ST ; pt-ST ; +pt-TL ; pt-Latn-TL ; pt-TL ; +qaa ; FAIL ; ; +qaa-CH ; FAIL ; ; +qaa-Cyrl ; FAIL ; ; +qaa-Cyrl-CH ; FAIL ; ; +qu ; qu-Latn-PE ; qu ; +qu-AQ ; qu-Latn-AQ ; qu-AQ ; +qu-BO ; qu-Latn-BO ; qu-BO ; +qu-EC ; qu-Latn-EC ; qu-EC ; +qu-Egyp ; qu-Egyp-PE ; qu-Egyp ; +qu-Latn ; qu-Latn-PE ; qu ; +qu-PE ; qu-Latn-PE ; qu ; +raj ; raj-Deva-IN ; raj ; +raj-AQ ; raj-Deva-AQ ; raj-AQ ; +raj-Deva ; raj-Deva-IN ; raj ; +raj-Egyp ; raj-Egyp-IN ; raj-Egyp ; +raj-IN ; raj-Deva-IN ; raj ; +rm ; rm-Latn-CH ; rm ; +rm-AQ ; rm-Latn-AQ ; rm-AQ ; +rm-CH ; rm-Latn-CH ; rm ; +rm-Egyp ; rm-Egyp-CH ; rm-Egyp ; +rm-Latn ; rm-Latn-CH ; rm ; +ro ; ro-Latn-RO ; ro ; +ro-AQ ; ro-Latn-AQ ; ro-AQ ; +ro-Egyp ; ro-Egyp-RO ; ro-Egyp ; +ro-Latn ; ro-Latn-RO ; ro ; +ro-MD ; ro-Latn-MD ; ro-MD ; +ro-RO ; ro-Latn-RO ; ro ; +ru ; ru-Cyrl-RU ; ru ; +ru-AQ ; ru-Cyrl-AQ ; ru-AQ ; +ru-BY ; ru-Cyrl-BY ; ru-BY ; +ru-Cyrl ; ru-Cyrl-RU ; ru ; +ru-Egyp ; ru-Egyp-RU ; ru-Egyp ; +ru-KG ; ru-Cyrl-KG ; ru-KG ; +ru-KZ ; ru-Cyrl-KZ ; ru-KZ ; +ru-MD ; ru-Cyrl-MD ; ru-MD ; +ru-RU ; ru-Cyrl-RU ; ru ; +ru-UA ; ru-Cyrl-UA ; ru-UA ; +sa ; sa-Deva-IN ; sa ; +sa-AQ ; sa-Deva-AQ ; sa-AQ ; +sa-Deva ; sa-Deva-IN ; sa ; +sa-Egyp ; sa-Egyp-IN ; sa-Egyp ; +sa-IN ; sa-Deva-IN ; sa ; +sat ; sat-Olck-IN ; sat ; +sat-AQ ; sat-Olck-AQ ; sat-AQ ; +sat-Egyp ; sat-Egyp-IN ; sat-Egyp ; +sat-IN ; sat-Olck-IN ; sat ; +sat-Olck ; sat-Olck-IN ; sat ; +sc ; sc-Latn-IT ; sc ; +sc-AQ ; sc-Latn-AQ ; sc-AQ ; +sc-Egyp ; sc-Egyp-IT ; sc-Egyp ; +sc-IT ; sc-Latn-IT ; sc ; +sc-Latn ; sc-Latn-IT ; sc ; +sd ; sd-Arab-PK ; sd ; +sd-AQ ; sd-Arab-AQ ; sd-AQ ; +sd-Arab ; sd-Arab-PK ; sd ; +sd-Deva ; sd-Deva-IN ; sd-Deva ; sd-IN +sd-Egyp ; sd-Egyp-PK ; sd-Egyp ; +sd-IN ; sd-Deva-IN ; sd-Deva ; sd-IN +sd-PK ; sd-Arab-PK ; sd ; +si ; si-Sinh-LK ; si ; +si-AQ ; si-Sinh-AQ ; si-AQ ; +si-Egyp ; si-Egyp-LK ; si-Egyp ; +si-LK ; si-Sinh-LK ; si ; +si-Sinh ; si-Sinh-LK ; si ; +sk ; sk-Latn-SK ; sk ; +sk-AQ ; sk-Latn-AQ ; sk-AQ ; +sk-Egyp ; sk-Egyp-SK ; sk-Egyp ; +sk-Latn ; sk-Latn-SK ; sk ; +sk-SK ; sk-Latn-SK ; sk ; +sl ; sl-Latn-SI ; sl ; +sl-AQ ; sl-Latn-AQ ; sl-AQ ; +sl-Egyp ; sl-Egyp-SI ; sl-Egyp ; +sl-Latn ; sl-Latn-SI ; sl ; +sl-SI ; sl-Latn-SI ; sl ; +so ; so-Latn-SO ; so ; +so-AQ ; so-Latn-AQ ; so-AQ ; +so-DJ ; so-Latn-DJ ; so-DJ ; +so-ET ; so-Latn-ET ; so-ET ; +so-Egyp ; so-Egyp-SO ; so-Egyp ; +so-KE ; so-Latn-KE ; so-KE ; +so-Latn ; so-Latn-SO ; so ; +so-SO ; so-Latn-SO ; so ; +sq ; sq-Latn-AL ; sq ; +sq-AL ; sq-Latn-AL ; sq ; +sq-AQ ; sq-Latn-AQ ; sq-AQ ; +sq-Egyp ; sq-Egyp-AL ; sq-Egyp ; +sq-Latn ; sq-Latn-AL ; sq ; +sq-MK ; sq-Latn-MK ; sq-MK ; +sq-XK ; sq-Latn-XK ; sq-XK ; +sr ; sr-Cyrl-RS ; sr ; +sr-AQ ; sr-Cyrl-AQ ; sr-AQ ; +sr-BA ; sr-Cyrl-BA ; sr-BA ; +sr-Cyrl ; sr-Cyrl-RS ; sr ; +sr-Egyp ; sr-Egyp-RS ; sr-Egyp ; +sr-Latn ; sr-Latn-RS ; sr-Latn ; +sr-ME ; sr-Latn-ME ; sr-ME ; +sr-RS ; sr-Cyrl-RS ; sr ; +sr-XK ; sr-Cyrl-XK ; sr-XK ; +su ; su-Latn-ID ; su ; +su-AQ ; su-Latn-AQ ; su-AQ ; +su-Egyp ; su-Egyp-ID ; su-Egyp ; +su-ID ; su-Latn-ID ; su ; +su-Latn ; su-Latn-ID ; su ; +sv ; sv-Latn-SE ; sv ; +sv-AQ ; sv-Latn-AQ ; sv-AQ ; +sv-AX ; sv-Latn-AX ; sv-AX ; +sv-Egyp ; sv-Egyp-SE ; sv-Egyp ; +sv-FI ; sv-Latn-FI ; sv-FI ; +sv-Latn ; sv-Latn-SE ; sv ; +sv-SE ; sv-Latn-SE ; sv ; +sw ; sw-Latn-TZ ; sw ; +sw-AQ ; sw-Latn-AQ ; sw-AQ ; +sw-CD ; sw-Latn-CD ; sw-CD ; +sw-Egyp ; sw-Egyp-TZ ; sw-Egyp ; +sw-KE ; sw-Latn-KE ; sw-KE ; +sw-Latn ; sw-Latn-TZ ; sw ; +sw-TZ ; sw-Latn-TZ ; sw ; +sw-UG ; sw-Latn-UG ; sw-UG ; +ta ; ta-Taml-IN ; ta ; +ta-AQ ; ta-Taml-AQ ; ta-AQ ; +ta-Egyp ; ta-Egyp-IN ; ta-Egyp ; +ta-IN ; ta-Taml-IN ; ta ; +ta-LK ; ta-Taml-LK ; ta-LK ; +ta-MY ; ta-Taml-MY ; ta-MY ; +ta-SG ; ta-Taml-SG ; ta-SG ; +ta-Taml ; ta-Taml-IN ; ta ; +te ; te-Telu-IN ; te ; +te-AQ ; te-Telu-AQ ; te-AQ ; +te-Egyp ; te-Egyp-IN ; te-Egyp ; +te-IN ; te-Telu-IN ; te ; +te-Telu ; te-Telu-IN ; te ; +tg ; tg-Cyrl-TJ ; tg ; +tg-AQ ; tg-Cyrl-AQ ; tg-AQ ; +tg-Cyrl ; tg-Cyrl-TJ ; tg ; +tg-Egyp ; tg-Egyp-TJ ; tg-Egyp ; +tg-TJ ; tg-Cyrl-TJ ; tg ; +th ; th-Thai-TH ; th ; +th-AQ ; th-Thai-AQ ; th-AQ ; +th-Egyp ; th-Egyp-TH ; th-Egyp ; +th-TH ; th-Thai-TH ; th ; +th-Thai ; th-Thai-TH ; th ; +ti ; ti-Ethi-ET ; ti ; +ti-AQ ; ti-Ethi-AQ ; ti-AQ ; +ti-ER ; ti-Ethi-ER ; ti-ER ; +ti-ET ; ti-Ethi-ET ; ti ; +ti-Egyp ; ti-Egyp-ET ; ti-Egyp ; +ti-Ethi ; ti-Ethi-ET ; ti ; +tk ; tk-Latn-TM ; tk ; +tk-AQ ; tk-Latn-AQ ; tk-AQ ; +tk-Egyp ; tk-Egyp-TM ; tk-Egyp ; +tk-Latn ; tk-Latn-TM ; tk ; +tk-TM ; tk-Latn-TM ; tk ; +to ; to-Latn-TO ; to ; +to-AQ ; to-Latn-AQ ; to-AQ ; +to-Egyp ; to-Egyp-TO ; to-Egyp ; +to-Latn ; to-Latn-TO ; to ; +to-TO ; to-Latn-TO ; to ; +tr ; tr-Latn-TR ; tr ; +tr-AQ ; tr-Latn-AQ ; tr-AQ ; +tr-CY ; tr-Latn-CY ; tr-CY ; +tr-Egyp ; tr-Egyp-TR ; tr-Egyp ; +tr-Latn ; tr-Latn-TR ; tr ; +tr-TR ; tr-Latn-TR ; tr ; +tt ; tt-Cyrl-RU ; tt ; +tt-AQ ; tt-Cyrl-AQ ; tt-AQ ; +tt-Cyrl ; tt-Cyrl-RU ; tt ; +tt-Egyp ; tt-Egyp-RU ; tt-Egyp ; +tt-RU ; tt-Cyrl-RU ; tt ; +uk ; uk-Cyrl-UA ; uk ; +uk-AQ ; uk-Cyrl-AQ ; uk-AQ ; +uk-Cyrl ; uk-Cyrl-UA ; uk ; +uk-Egyp ; uk-Egyp-UA ; uk-Egyp ; +uk-UA ; uk-Cyrl-UA ; uk ; +und ; en-Latn-US ; en ; +und-001 ; en-Latn-001 ; en-001 ; +und-150 ; ru-Cyrl-RU ; ru ; +und-419 ; es-Latn-419 ; es-419 ; +und-AD ; ca-Latn-AD ; ca-AD ; +und-AE ; ar-Arab-AE ; ar-AE ; +und-AF ; fa-Arab-AF ; fa-AF ; +und-AG ; en-Latn-AG ; en-AG ; +und-AI ; en-Latn-AI ; en-AI ; +und-AL ; sq-Latn-AL ; sq ; +und-AM ; hy-Armn-AM ; hy ; +und-AO ; pt-Latn-AO ; pt-AO ; +und-AQ ; en-Latn-AQ ; en-AQ ; +und-AR ; es-Latn-AR ; es-AR ; +und-AS ; sm-Latn-AS ; sm-AS ; +und-AT ; de-Latn-AT ; de-AT ; +und-AU ; en-Latn-AU ; en-AU ; +und-AW ; nl-Latn-AW ; nl-AW ; +und-AX ; sv-Latn-AX ; sv-AX ; +und-AZ ; az-Latn-AZ ; az ; +und-Adlm ; ff-Adlm-GN ; ff-Adlm ; +und-Adlm-AQ ; ff-Adlm-AQ ; ; +und-Adlm-BF ; ff-Adlm-BF ; ; +und-Adlm-CM ; ff-Adlm-CM ; ; +und-Adlm-GH ; ff-Adlm-GH ; ; +und-Adlm-GM ; ff-Adlm-GM ; ; +und-Adlm-GN ; ff-Adlm-GN ; ff-Adlm ; +und-Adlm-GW ; ff-Adlm-GW ; ; +und-Adlm-LR ; ff-Adlm-LR ; ; +und-Adlm-MR ; ff-Adlm-MR ; ; +und-Adlm-NE ; ff-Adlm-NE ; ; +und-Adlm-NG ; ff-Adlm-NG ; ; +und-Adlm-SL ; ff-Adlm-SL ; ; +und-Adlm-SN ; ff-Adlm-SN ; ; +und-Arab ; ar-Arab-EG ; ar ; +und-Arab-001 ; ar-Arab-001 ; ar-001 ; +und-Arab-AE ; ar-Arab-AE ; ar-AE ; +und-Arab-AF ; fa-Arab-AF ; fa-AF ; +und-Arab-AQ ; ar-Arab-AQ ; ar-AQ ; +und-Arab-BH ; ar-Arab-BH ; ar-BH ; +und-Arab-DJ ; ar-Arab-DJ ; ar-DJ ; +und-Arab-DZ ; ar-Arab-DZ ; ar-DZ ; +und-Arab-EG ; ar-Arab-EG ; ar ; +und-Arab-EH ; ar-Arab-EH ; ar-EH ; +und-Arab-ER ; ar-Arab-ER ; ar-ER ; +und-Arab-IL ; ar-Arab-IL ; ar-IL ; +und-Arab-IN ; ur-Arab-IN ; ur-IN ; +und-Arab-IQ ; ar-Arab-IQ ; ar-IQ ; +und-Arab-IR ; fa-Arab-IR ; fa ; +und-Arab-JO ; ar-Arab-JO ; ar-JO ; +und-Arab-KM ; ar-Arab-KM ; ar-KM ; +und-Arab-KW ; ar-Arab-KW ; ar-KW ; +und-Arab-LB ; ar-Arab-LB ; ar-LB ; +und-Arab-LY ; ar-Arab-LY ; ar-LY ; +und-Arab-MA ; ar-Arab-MA ; ar-MA ; +und-Arab-MR ; ar-Arab-MR ; ar-MR ; +und-Arab-OM ; ar-Arab-OM ; ar-OM ; +und-Arab-PK ; ur-Arab-PK ; ur ; +und-Arab-PS ; ar-Arab-PS ; ar-PS ; +und-Arab-QA ; ar-Arab-QA ; ar-QA ; +und-Arab-SA ; ar-Arab-SA ; ar-SA ; +und-Arab-SD ; ar-Arab-SD ; ar-SD ; +und-Arab-SO ; ar-Arab-SO ; ar-SO ; +und-Arab-SS ; ar-Arab-SS ; ar-SS ; +und-Arab-SY ; ar-Arab-SY ; ar-SY ; +und-Arab-TD ; ar-Arab-TD ; ar-TD ; +und-Arab-TN ; ar-Arab-TN ; ar-TN ; +und-Arab-YE ; ar-Arab-YE ; ar-YE ; +und-Armn ; hy-Armn-AM ; hy ; +und-Armn-AM ; hy-Armn-AM ; hy ; +und-Armn-AQ ; hy-Armn-AQ ; hy-AQ ; +und-BA ; bs-Latn-BA ; bs ; +und-BB ; en-Latn-BB ; en-BB ; +und-BD ; bn-Beng-BD ; bn ; +und-BE ; nl-Latn-BE ; nl-BE ; +und-BF ; fr-Latn-BF ; fr-BF ; +und-BG ; bg-Cyrl-BG ; bg ; +und-BH ; ar-Arab-BH ; ar-BH ; +und-BI ; rn-Latn-BI ; rn ; +und-BJ ; fr-Latn-BJ ; fr-BJ ; +und-BL ; fr-Latn-BL ; fr-BL ; +und-BM ; en-Latn-BM ; en-BM ; +und-BN ; ms-Latn-BN ; ms-BN ; +und-BO ; es-Latn-BO ; es-BO ; +und-BQ ; pap-Latn-BQ ; pap-BQ ; +und-BR ; pt-Latn-BR ; pt ; +und-BS ; en-Latn-BS ; en-BS ; +und-BW ; en-Latn-BW ; en-BW ; +und-BY ; be-Cyrl-BY ; be ; +und-BZ ; en-Latn-BZ ; en-BZ ; +und-Beng ; bn-Beng-BD ; bn ; +und-Beng-AQ ; bn-Beng-AQ ; bn-AQ ; +und-Beng-BD ; bn-Beng-BD ; bn ; +und-Beng-IN ; bn-Beng-IN ; bn-IN ; +und-CA ; en-Latn-CA ; en-CA ; +und-CC ; ms-Arab-CC ; ms-CC ; +und-CD ; sw-Latn-CD ; sw-CD ; +und-CF ; fr-Latn-CF ; fr-CF ; +und-CG ; fr-Latn-CG ; fr-CG ; +und-CH ; de-Latn-CH ; de-CH ; +und-CI ; fr-Latn-CI ; fr-CI ; +und-CK ; en-Latn-CK ; en-CK ; +und-CL ; es-Latn-CL ; es-CL ; +und-CM ; fr-Latn-CM ; fr-CM ; +und-CN ; zh-Hans-CN ; zh ; +und-CO ; es-Latn-CO ; es-CO ; +und-CR ; es-Latn-CR ; es-CR ; +und-CU ; es-Latn-CU ; es-CU ; +und-CV ; pt-Latn-CV ; pt-CV ; +und-CW ; pap-Latn-CW ; pap ; +und-CX ; en-Latn-CX ; en-CX ; +und-CY ; el-Grek-CY ; el-CY ; +und-CZ ; cs-Latn-CZ ; cs ; +und-Cans ; iu-Cans-CA ; iu ; +und-Cans-AQ ; iu-Cans-AQ ; iu-AQ ; +und-Cans-CA ; iu-Cans-CA ; iu ; +und-Cher ; chr-Cher-US ; chr ; +und-Cher-AQ ; chr-Cher-AQ ; chr-AQ ; +und-Cher-US ; chr-Cher-US ; chr ; +und-Cyrl ; ru-Cyrl-RU ; ru ; +und-Cyrl-AQ ; ru-Cyrl-AQ ; ru-AQ ; +und-Cyrl-BA ; sr-Cyrl-BA ; sr-BA ; +und-Cyrl-BG ; bg-Cyrl-BG ; bg ; +und-Cyrl-BY ; be-Cyrl-BY ; be ; +und-Cyrl-KG ; ky-Cyrl-KG ; ky ; +und-Cyrl-KZ ; ru-Cyrl-KZ ; ru-KZ ; +und-Cyrl-MD ; uk-Cyrl-MD ; uk-MD ; +und-Cyrl-ME ; ru-Cyrl-ME ; ru-ME ; +und-Cyrl-MK ; mk-Cyrl-MK ; mk ; +und-Cyrl-MN ; mn-Cyrl-MN ; mn ; +und-Cyrl-RS ; sr-Cyrl-RS ; sr ; +und-Cyrl-RU ; ru-Cyrl-RU ; ru ; +und-Cyrl-TJ ; tg-Cyrl-TJ ; tg ; +und-Cyrl-UA ; uk-Cyrl-UA ; uk ; +und-Cyrl-UZ ; ru-Cyrl-UZ ; ru-UZ ; +und-Cyrl-XK ; sr-Cyrl-XK ; sr-XK ; +und-DE ; de-Latn-DE ; de ; +und-DG ; en-Latn-DG ; en-DG ; +und-DJ ; aa-Latn-DJ ; aa-DJ ; +und-DK ; da-Latn-DK ; da ; +und-DM ; en-Latn-DM ; en-DM ; +und-DO ; es-Latn-DO ; es-DO ; +und-DZ ; ar-Arab-DZ ; ar-DZ ; +und-Deva ; hi-Deva-IN ; hi ; +und-Deva-AQ ; hi-Deva-AQ ; hi-AQ ; +und-Deva-IN ; hi-Deva-IN ; hi ; +und-Deva-NP ; ne-Deva-NP ; ne ; +und-Deva-PK ; btv-Deva-PK ; btv ; +und-EA ; es-Latn-EA ; es-EA ; +und-EC ; es-Latn-EC ; es-EC ; +und-EE ; et-Latn-EE ; et ; +und-EG ; ar-Arab-EG ; ar ; +und-EH ; ar-Arab-EH ; ar-EH ; +und-ER ; ti-Ethi-ER ; ti-ER ; +und-ES ; es-Latn-ES ; es ; +und-ET ; am-Ethi-ET ; am ; +und-Egyp ; egy-Egyp-EG ; egy ; +und-Ethi ; am-Ethi-ET ; am ; +und-Ethi-AQ ; am-Ethi-AQ ; am-AQ ; +und-Ethi-ER ; ti-Ethi-ER ; ti-ER ; +und-Ethi-ET ; am-Ethi-ET ; am ; +und-FI ; fi-Latn-FI ; fi ; +und-FJ ; en-Latn-FJ ; en-FJ ; +und-FK ; en-Latn-FK ; en-FK ; +und-FM ; en-Latn-FM ; en-FM ; +und-FO ; fo-Latn-FO ; fo ; +und-FR ; fr-Latn-FR ; fr ; +und-GA ; fr-Latn-GA ; fr-GA ; +und-GB ; en-Latn-GB ; en-GB ; +und-GD ; en-Latn-GD ; en-GD ; +und-GE ; ka-Geor-GE ; ka ; +und-GF ; fr-Latn-GF ; fr-GF ; +und-GG ; en-Latn-GG ; en-GG ; +und-GH ; ak-Latn-GH ; ak ; +und-GI ; en-Latn-GI ; en-GI ; +und-GL ; kl-Latn-GL ; kl ; +und-GM ; en-Latn-GM ; en-GM ; +und-GN ; fr-Latn-GN ; fr-GN ; +und-GP ; fr-Latn-GP ; fr-GP ; +und-GQ ; es-Latn-GQ ; es-GQ ; +und-GR ; el-Grek-GR ; el ; +und-GT ; es-Latn-GT ; es-GT ; +und-GU ; en-Latn-GU ; en-GU ; +und-GW ; pt-Latn-GW ; pt-GW ; +und-GY ; en-Latn-GY ; en-GY ; +und-Geor ; ka-Geor-GE ; ka ; +und-Geor-AQ ; ka-Geor-AQ ; ka-AQ ; +und-Geor-GE ; ka-Geor-GE ; ka ; +und-Grek ; el-Grek-GR ; el ; +und-Grek-AQ ; el-Grek-AQ ; el-AQ ; +und-Grek-CY ; el-Grek-CY ; el-CY ; +und-Grek-GR ; el-Grek-GR ; el ; +und-Gujr ; gu-Gujr-IN ; gu ; +und-Gujr-AQ ; gu-Gujr-AQ ; gu-AQ ; +und-Gujr-IN ; gu-Gujr-IN ; gu ; +und-Guru ; pa-Guru-IN ; pa ; +und-Guru-AQ ; pa-Guru-AQ ; pa-AQ ; +und-Guru-IN ; pa-Guru-IN ; pa ; +und-HK ; zh-Hant-HK ; zh-HK ; +und-HN ; es-Latn-HN ; es-HN ; +und-HR ; hr-Latn-HR ; hr ; +und-HT ; ht-Latn-HT ; ht ; +und-HU ; hu-Latn-HU ; hu ; +und-Hans ; zh-Hans-CN ; zh ; +und-Hans-AQ ; zh-Hans-AQ ; zh-AQ ; +und-Hans-CN ; zh-Hans-CN ; zh ; +und-Hans-HK ; zh-Hans-HK ; ; +und-Hans-MO ; zh-Hans-MO ; ; +und-Hans-SG ; zh-Hans-SG ; zh-SG ; +und-Hans-TW ; zh-Hans-TW ; ; +und-Hant ; zh-Hant-TW ; zh-Hant ; zh-TW +und-Hant-AQ ; zh-Hant-AQ ; ; +und-Hant-CN ; zh-Hant-CN ; ; +und-Hant-HK ; zh-Hant-HK ; zh-HK ; +und-Hant-MO ; zh-Hant-MO ; zh-MO ; +und-Hant-SG ; zh-Hant-SG ; ; +und-Hant-TW ; zh-Hant-TW ; zh-Hant ; zh-TW +und-Hebr ; he-Hebr-IL ; he ; +und-Hebr-AQ ; he-Hebr-AQ ; he-AQ ; +und-Hebr-IL ; he-Hebr-IL ; he ; +und-IC ; es-Latn-IC ; es-IC ; +und-ID ; id-Latn-ID ; id ; +und-IE ; en-Latn-IE ; en-IE ; +und-IL ; he-Hebr-IL ; he ; +und-IM ; en-Latn-IM ; en-IM ; +und-IN ; hi-Deva-IN ; hi ; +und-IO ; en-Latn-IO ; en-IO ; +und-IQ ; ar-Arab-IQ ; ar-IQ ; +und-IR ; fa-Arab-IR ; fa ; +und-IS ; is-Latn-IS ; is ; +und-IT ; it-Latn-IT ; it ; +und-JE ; en-Latn-JE ; en-JE ; +und-JM ; en-Latn-JM ; en-JM ; +und-JO ; ar-Arab-JO ; ar-JO ; +und-JP ; ja-Jpan-JP ; ja ; +und-Jpan ; ja-Jpan-JP ; ja ; +und-Jpan-AQ ; ja-Jpan-AQ ; ja-AQ ; +und-Jpan-JP ; ja-Jpan-JP ; ja ; +und-KE ; sw-Latn-KE ; sw-KE ; +und-KG ; ky-Cyrl-KG ; ky ; +und-KH ; km-Khmr-KH ; km ; +und-KI ; en-Latn-KI ; en-KI ; +und-KM ; ar-Arab-KM ; ar-KM ; +und-KN ; en-Latn-KN ; en-KN ; +und-KP ; ko-Kore-KP ; ko-KP ; +und-KR ; ko-Kore-KR ; ko ; +und-KW ; ar-Arab-KW ; ar-KW ; +und-KY ; en-Latn-KY ; en-KY ; +und-KZ ; ru-Cyrl-KZ ; ru-KZ ; +und-Khmr ; km-Khmr-KH ; km ; +und-Khmr-AQ ; km-Khmr-AQ ; km-AQ ; +und-Khmr-KH ; km-Khmr-KH ; km ; +und-Knda ; kn-Knda-IN ; kn ; +und-Knda-AQ ; kn-Knda-AQ ; kn-AQ ; +und-Knda-IN ; kn-Knda-IN ; kn ; +und-Kore ; ko-Kore-KR ; ko ; +und-Kore-AQ ; ko-Kore-AQ ; ko-AQ ; +und-Kore-CN ; ko-Kore-CN ; ko-CN ; +und-Kore-KP ; ko-Kore-KP ; ko-KP ; +und-Kore-KR ; ko-Kore-KR ; ko ; +und-LA ; lo-Laoo-LA ; lo ; +und-LB ; ar-Arab-LB ; ar-LB ; +und-LC ; en-Latn-LC ; en-LC ; +und-LI ; de-Latn-LI ; de-LI ; +und-LK ; si-Sinh-LK ; si ; +und-LR ; en-Latn-LR ; en-LR ; +und-LS ; st-Latn-LS ; st-LS ; +und-LT ; lt-Latn-LT ; lt ; +und-LU ; fr-Latn-LU ; fr-LU ; +und-LV ; lv-Latn-LV ; lv ; +und-LY ; ar-Arab-LY ; ar-LY ; +und-Laoo ; lo-Laoo-LA ; lo ; +und-Laoo-AQ ; lo-Laoo-AQ ; lo-AQ ; +und-Laoo-LA ; lo-Laoo-LA ; lo ; +und-Latn ; en-Latn-US ; en ; +und-Latn-001 ; en-Latn-001 ; en-001 ; +und-Latn-150 ; ru-Latn-150 ; ; +und-Latn-419 ; es-Latn-419 ; es-419 ; +und-Latn-AD ; ca-Latn-AD ; ca-AD ; +und-Latn-AE ; ar-Latn-AE ; ; +und-Latn-AG ; en-Latn-AG ; en-AG ; +und-Latn-AI ; en-Latn-AI ; en-AI ; +und-Latn-AL ; sq-Latn-AL ; sq ; +und-Latn-AO ; pt-Latn-AO ; pt-AO ; +und-Latn-AQ ; en-Latn-AQ ; en-AQ ; +und-Latn-AR ; es-Latn-AR ; es-AR ; +und-Latn-AS ; sm-Latn-AS ; sm-AS ; +und-Latn-AT ; de-Latn-AT ; de-AT ; +und-Latn-AU ; en-Latn-AU ; en-AU ; +und-Latn-AW ; nl-Latn-AW ; nl-AW ; +und-Latn-AX ; sv-Latn-AX ; sv-AX ; +und-Latn-AZ ; az-Latn-AZ ; az ; +und-Latn-BA ; bs-Latn-BA ; bs ; +und-Latn-BB ; en-Latn-BB ; en-BB ; +und-Latn-BE ; nl-Latn-BE ; nl-BE ; +und-Latn-BF ; fr-Latn-BF ; fr-BF ; +und-Latn-BI ; rn-Latn-BI ; rn ; +und-Latn-BJ ; fr-Latn-BJ ; fr-BJ ; +und-Latn-BL ; fr-Latn-BL ; fr-BL ; +und-Latn-BM ; en-Latn-BM ; en-BM ; +und-Latn-BN ; ms-Latn-BN ; ms-BN ; +und-Latn-BO ; es-Latn-BO ; es-BO ; +und-Latn-BQ ; pap-Latn-BQ ; pap-BQ ; +und-Latn-BR ; pt-Latn-BR ; pt ; +und-Latn-BS ; en-Latn-BS ; en-BS ; +und-Latn-BW ; en-Latn-BW ; en-BW ; +und-Latn-BZ ; en-Latn-BZ ; en-BZ ; +und-Latn-CA ; en-Latn-CA ; en-CA ; +und-Latn-CC ; ms-Latn-CC ; ; +und-Latn-CD ; sw-Latn-CD ; sw-CD ; +und-Latn-CF ; fr-Latn-CF ; fr-CF ; +und-Latn-CG ; fr-Latn-CG ; fr-CG ; +und-Latn-CH ; de-Latn-CH ; de-CH ; +und-Latn-CI ; fr-Latn-CI ; fr-CI ; +und-Latn-CK ; en-Latn-CK ; en-CK ; +und-Latn-CL ; es-Latn-CL ; es-CL ; +und-Latn-CM ; fr-Latn-CM ; fr-CM ; +und-Latn-CO ; es-Latn-CO ; es-CO ; +und-Latn-CR ; es-Latn-CR ; es-CR ; +und-Latn-CU ; es-Latn-CU ; es-CU ; +und-Latn-CV ; pt-Latn-CV ; pt-CV ; +und-Latn-CW ; pap-Latn-CW ; pap ; +und-Latn-CX ; en-Latn-CX ; en-CX ; +und-Latn-CY ; tr-Latn-CY ; tr-CY ; +und-Latn-CZ ; cs-Latn-CZ ; cs ; +und-Latn-DE ; de-Latn-DE ; de ; +und-Latn-DG ; en-Latn-DG ; en-DG ; +und-Latn-DJ ; aa-Latn-DJ ; aa-DJ ; +und-Latn-DK ; da-Latn-DK ; da ; +und-Latn-DM ; en-Latn-DM ; en-DM ; +und-Latn-DO ; es-Latn-DO ; es-DO ; +und-Latn-DZ ; fr-Latn-DZ ; fr-DZ ; +und-Latn-EA ; es-Latn-EA ; es-EA ; +und-Latn-EC ; es-Latn-EC ; es-EC ; +und-Latn-EE ; et-Latn-EE ; et ; +und-Latn-ER ; ti-Latn-ER ; ; +und-Latn-ES ; es-Latn-ES ; es ; +und-Latn-ET ; en-Latn-ET ; en-ET ; +und-Latn-FI ; fi-Latn-FI ; fi ; +und-Latn-FJ ; en-Latn-FJ ; en-FJ ; +und-Latn-FK ; en-Latn-FK ; en-FK ; +und-Latn-FM ; en-Latn-FM ; en-FM ; +und-Latn-FO ; fo-Latn-FO ; fo ; +und-Latn-FR ; fr-Latn-FR ; fr ; +und-Latn-GA ; fr-Latn-GA ; fr-GA ; +und-Latn-GB ; en-Latn-GB ; en-GB ; +und-Latn-GD ; en-Latn-GD ; en-GD ; +und-Latn-GF ; fr-Latn-GF ; fr-GF ; +und-Latn-GG ; en-Latn-GG ; en-GG ; +und-Latn-GH ; ak-Latn-GH ; ak ; +und-Latn-GI ; en-Latn-GI ; en-GI ; +und-Latn-GL ; kl-Latn-GL ; kl ; +und-Latn-GM ; en-Latn-GM ; en-GM ; +und-Latn-GN ; fr-Latn-GN ; fr-GN ; +und-Latn-GP ; fr-Latn-GP ; fr-GP ; +und-Latn-GQ ; es-Latn-GQ ; es-GQ ; +und-Latn-GT ; es-Latn-GT ; es-GT ; +und-Latn-GU ; en-Latn-GU ; en-GU ; +und-Latn-GW ; pt-Latn-GW ; pt-GW ; +und-Latn-GY ; en-Latn-GY ; en-GY ; +und-Latn-HK ; zh-Latn-HK ; ; +und-Latn-HN ; es-Latn-HN ; es-HN ; +und-Latn-HR ; hr-Latn-HR ; hr ; +und-Latn-HT ; ht-Latn-HT ; ht ; +und-Latn-HU ; hu-Latn-HU ; hu ; +und-Latn-IC ; es-Latn-IC ; es-IC ; +und-Latn-ID ; id-Latn-ID ; id ; +und-Latn-IE ; en-Latn-IE ; en-IE ; +und-Latn-IL ; he-Latn-IL ; he-Latn ; +und-Latn-IM ; en-Latn-IM ; en-IM ; +und-Latn-IN ; hi-Latn-IN ; hi-Latn ; +und-Latn-IO ; en-Latn-IO ; en-IO ; +und-Latn-IS ; is-Latn-IS ; is ; +und-Latn-IT ; it-Latn-IT ; it ; +und-Latn-JE ; en-Latn-JE ; en-JE ; +und-Latn-JM ; en-Latn-JM ; en-JM ; +und-Latn-KE ; sw-Latn-KE ; sw-KE ; +und-Latn-KI ; en-Latn-KI ; en-KI ; +und-Latn-KM ; fr-Latn-KM ; fr-KM ; +und-Latn-KN ; en-Latn-KN ; en-KN ; +und-Latn-KY ; en-Latn-KY ; en-KY ; +und-Latn-LC ; en-Latn-LC ; en-LC ; +und-Latn-LI ; de-Latn-LI ; de-LI ; +und-Latn-LR ; en-Latn-LR ; en-LR ; +und-Latn-LS ; st-Latn-LS ; st-LS ; +und-Latn-LT ; lt-Latn-LT ; lt ; +und-Latn-LU ; fr-Latn-LU ; fr-LU ; +und-Latn-LV ; lv-Latn-LV ; lv ; +und-Latn-MA ; fr-Latn-MA ; fr-MA ; +und-Latn-MC ; fr-Latn-MC ; fr-MC ; +und-Latn-MD ; ro-Latn-MD ; ro-MD ; +und-Latn-ME ; sr-Latn-ME ; sr-ME ; +und-Latn-MF ; fr-Latn-MF ; fr-MF ; +und-Latn-MG ; mg-Latn-MG ; mg ; +und-Latn-MH ; en-Latn-MH ; en-MH ; +und-Latn-MK ; sq-Latn-MK ; sq-MK ; +und-Latn-ML ; bm-Latn-ML ; bm ; +und-Latn-MO ; pt-Latn-MO ; pt-MO ; +und-Latn-MP ; en-Latn-MP ; en-MP ; +und-Latn-MQ ; fr-Latn-MQ ; fr-MQ ; +und-Latn-MR ; fr-Latn-MR ; fr-MR ; +und-Latn-MS ; en-Latn-MS ; en-MS ; +und-Latn-MT ; mt-Latn-MT ; mt ; +und-Latn-MU ; mfe-Latn-MU ; mfe ; +und-Latn-MV ; dv-Latn-MV ; dv-Latn ; +und-Latn-MW ; en-Latn-MW ; en-MW ; +und-Latn-MX ; es-Latn-MX ; es-MX ; +und-Latn-MY ; ms-Latn-MY ; ms ; +und-Latn-MZ ; pt-Latn-MZ ; pt-MZ ; +und-Latn-NA ; af-Latn-NA ; af-NA ; +und-Latn-NC ; fr-Latn-NC ; fr-NC ; +und-Latn-NE ; ha-Latn-NE ; ha-NE ; +und-Latn-NF ; en-Latn-NF ; en-NF ; +und-Latn-NG ; en-Latn-NG ; en-NG ; +und-Latn-NI ; es-Latn-NI ; es-NI ; +und-Latn-NL ; nl-Latn-NL ; nl ; +und-Latn-NO ; nb-Latn-NO ; nb ; +und-Latn-NR ; en-Latn-NR ; en-NR ; +und-Latn-NU ; en-Latn-NU ; en-NU ; +und-Latn-NZ ; en-Latn-NZ ; en-NZ ; +und-Latn-PA ; es-Latn-PA ; es-PA ; +und-Latn-PE ; es-Latn-PE ; es-PE ; +und-Latn-PF ; fr-Latn-PF ; fr-PF ; +und-Latn-PG ; tpi-Latn-PG ; tpi ; +und-Latn-PH ; fil-Latn-PH ; fil ; +und-Latn-PK ; ur-Latn-PK ; ur-Latn ; +und-Latn-PL ; pl-Latn-PL ; pl ; +und-Latn-PM ; fr-Latn-PM ; fr-PM ; +und-Latn-PN ; en-Latn-PN ; en-PN ; +und-Latn-PR ; es-Latn-PR ; es-PR ; +und-Latn-PT ; pt-Latn-PT ; pt-PT ; +und-Latn-PW ; pau-Latn-PW ; pau ; +und-Latn-PY ; gn-Latn-PY ; gn ; +und-Latn-RE ; fr-Latn-RE ; fr-RE ; +und-Latn-RO ; ro-Latn-RO ; ro ; +und-Latn-RS ; sr-Latn-RS ; sr-Latn ; +und-Latn-RW ; rw-Latn-RW ; rw ; +und-Latn-SB ; en-Latn-SB ; en-SB ; +und-Latn-SC ; fr-Latn-SC ; fr-SC ; +und-Latn-SD ; ar-Latn-SD ; ; +und-Latn-SE ; sv-Latn-SE ; sv ; +und-Latn-SG ; en-Latn-SG ; en-SG ; +und-Latn-SH ; en-Latn-SH ; en-SH ; +und-Latn-SI ; sl-Latn-SI ; sl ; +und-Latn-SJ ; nb-Latn-SJ ; nb-SJ ; +und-Latn-SK ; sk-Latn-SK ; sk ; +und-Latn-SL ; kri-Latn-SL ; kri ; +und-Latn-SM ; it-Latn-SM ; it-SM ; +und-Latn-SN ; fr-Latn-SN ; fr-SN ; +und-Latn-SO ; so-Latn-SO ; so ; +und-Latn-SR ; nl-Latn-SR ; nl-SR ; +und-Latn-SS ; ar-Latn-SS ; ; +und-Latn-ST ; pt-Latn-ST ; pt-ST ; +und-Latn-SV ; es-Latn-SV ; es-SV ; +und-Latn-SX ; en-Latn-SX ; en-SX ; +und-Latn-SY ; fr-Latn-SY ; fr-SY ; +und-Latn-SZ ; en-Latn-SZ ; en-SZ ; +und-Latn-TC ; en-Latn-TC ; en-TC ; +und-Latn-TD ; fr-Latn-TD ; fr-TD ; +und-Latn-TG ; fr-Latn-TG ; fr-TG ; +und-Latn-TK ; tkl-Latn-TK ; tkl ; +und-Latn-TL ; pt-Latn-TL ; pt-TL ; +und-Latn-TM ; tk-Latn-TM ; tk ; +und-Latn-TN ; fr-Latn-TN ; fr-TN ; +und-Latn-TO ; to-Latn-TO ; to ; +und-Latn-TR ; tr-Latn-TR ; tr ; +und-Latn-TT ; en-Latn-TT ; en-TT ; +und-Latn-TV ; tvl-Latn-TV ; tvl ; +und-Latn-TZ ; sw-Latn-TZ ; sw ; +und-Latn-UG ; sw-Latn-UG ; sw-UG ; +und-Latn-UM ; en-Latn-UM ; en-UM ; +und-Latn-US ; en-Latn-US ; en ; +und-Latn-UY ; es-Latn-UY ; es-UY ; +und-Latn-UZ ; uz-Latn-UZ ; uz ; +und-Latn-VA ; it-Latn-VA ; it-VA ; +und-Latn-VC ; en-Latn-VC ; en-VC ; +und-Latn-VE ; es-Latn-VE ; es-VE ; +und-Latn-VG ; en-Latn-VG ; en-VG ; +und-Latn-VI ; en-Latn-VI ; en-VI ; +und-Latn-VN ; vi-Latn-VN ; vi ; +und-Latn-VU ; bi-Latn-VU ; bi ; +und-Latn-WF ; fr-Latn-WF ; fr-WF ; +und-Latn-WS ; sm-Latn-WS ; sm ; +und-Latn-XK ; sq-Latn-XK ; sq-XK ; +und-Latn-YT ; fr-Latn-YT ; fr-YT ; +und-Latn-ZA ; en-Latn-ZA ; en-ZA ; +und-Latn-ZM ; bem-Latn-ZM ; bem ; +und-Latn-ZW ; sn-Latn-ZW ; sn ; +und-MA ; ar-Arab-MA ; ar-MA ; +und-MC ; fr-Latn-MC ; fr-MC ; +und-MD ; ro-Latn-MD ; ro-MD ; +und-ME ; sr-Latn-ME ; sr-ME ; +und-MF ; fr-Latn-MF ; fr-MF ; +und-MG ; mg-Latn-MG ; mg ; +und-MH ; en-Latn-MH ; en-MH ; +und-MK ; mk-Cyrl-MK ; mk ; +und-ML ; bm-Latn-ML ; bm ; +und-MM ; my-Mymr-MM ; my ; +und-MN ; mn-Cyrl-MN ; mn ; +und-MO ; zh-Hant-MO ; zh-MO ; +und-MP ; en-Latn-MP ; en-MP ; +und-MQ ; fr-Latn-MQ ; fr-MQ ; +und-MR ; ar-Arab-MR ; ar-MR ; +und-MS ; en-Latn-MS ; en-MS ; +und-MT ; mt-Latn-MT ; mt ; +und-MU ; mfe-Latn-MU ; mfe ; +und-MV ; dv-Thaa-MV ; dv ; +und-MW ; en-Latn-MW ; en-MW ; +und-MX ; es-Latn-MX ; es-MX ; +und-MY ; ms-Latn-MY ; ms ; +und-MZ ; pt-Latn-MZ ; pt-MZ ; +und-Mlym ; ml-Mlym-IN ; ml ; +und-Mlym-AQ ; ml-Mlym-AQ ; ml-AQ ; +und-Mlym-IN ; ml-Mlym-IN ; ml ; +und-Mymr ; my-Mymr-MM ; my ; +und-Mymr-AQ ; my-Mymr-AQ ; my-AQ ; +und-Mymr-MM ; my-Mymr-MM ; my ; +und-NA ; af-Latn-NA ; af-NA ; +und-NC ; fr-Latn-NC ; fr-NC ; +und-NE ; ha-Latn-NE ; ha-NE ; +und-NF ; en-Latn-NF ; en-NF ; +und-NG ; en-Latn-NG ; en-NG ; +und-NI ; es-Latn-NI ; es-NI ; +und-NL ; nl-Latn-NL ; nl ; +und-NO ; nb-Latn-NO ; nb ; +und-NP ; ne-Deva-NP ; ne ; +und-NR ; en-Latn-NR ; en-NR ; +und-NU ; en-Latn-NU ; en-NU ; +und-NZ ; en-Latn-NZ ; en-NZ ; +und-OM ; ar-Arab-OM ; ar-OM ; +und-Olck ; sat-Olck-IN ; sat ; +und-Olck-AQ ; sat-Olck-AQ ; sat-AQ ; +und-Olck-IN ; sat-Olck-IN ; sat ; +und-Orya ; or-Orya-IN ; or ; +und-Orya-AQ ; or-Orya-AQ ; or-AQ ; +und-Orya-IN ; or-Orya-IN ; or ; +und-PA ; es-Latn-PA ; es-PA ; +und-PE ; es-Latn-PE ; es-PE ; +und-PF ; fr-Latn-PF ; fr-PF ; +und-PG ; tpi-Latn-PG ; tpi ; +und-PH ; fil-Latn-PH ; fil ; +und-PK ; ur-Arab-PK ; ur ; +und-PL ; pl-Latn-PL ; pl ; +und-PM ; fr-Latn-PM ; fr-PM ; +und-PN ; en-Latn-PN ; en-PN ; +und-PR ; es-Latn-PR ; es-PR ; +und-PS ; ar-Arab-PS ; ar-PS ; +und-PT ; pt-Latn-PT ; pt-PT ; +und-PW ; pau-Latn-PW ; pau ; +und-PY ; gn-Latn-PY ; gn ; +und-QA ; ar-Arab-QA ; ar-QA ; +und-RE ; fr-Latn-RE ; fr-RE ; +und-RO ; ro-Latn-RO ; ro ; +und-RS ; sr-Cyrl-RS ; sr ; +und-RU ; ru-Cyrl-RU ; ru ; +und-RW ; rw-Latn-RW ; rw ; +und-SA ; ar-Arab-SA ; ar-SA ; +und-SB ; en-Latn-SB ; en-SB ; +und-SC ; fr-Latn-SC ; fr-SC ; +und-SD ; ar-Arab-SD ; ar-SD ; +und-SE ; sv-Latn-SE ; sv ; +und-SG ; en-Latn-SG ; en-SG ; +und-SH ; en-Latn-SH ; en-SH ; +und-SI ; sl-Latn-SI ; sl ; +und-SJ ; nb-Latn-SJ ; nb-SJ ; +und-SK ; sk-Latn-SK ; sk ; +und-SL ; kri-Latn-SL ; kri ; +und-SM ; it-Latn-SM ; it-SM ; +und-SN ; fr-Latn-SN ; fr-SN ; +und-SO ; so-Latn-SO ; so ; +und-SR ; nl-Latn-SR ; nl-SR ; +und-SS ; ar-Arab-SS ; ar-SS ; +und-ST ; pt-Latn-ST ; pt-ST ; +und-SV ; es-Latn-SV ; es-SV ; +und-SX ; en-Latn-SX ; en-SX ; +und-SY ; ar-Arab-SY ; ar-SY ; +und-SZ ; en-Latn-SZ ; en-SZ ; +und-Sinh ; si-Sinh-LK ; si ; +und-Sinh-AQ ; si-Sinh-AQ ; si-AQ ; +und-Sinh-LK ; si-Sinh-LK ; si ; +und-TC ; en-Latn-TC ; en-TC ; +und-TD ; fr-Latn-TD ; fr-TD ; +und-TG ; fr-Latn-TG ; fr-TG ; +und-TH ; th-Thai-TH ; th ; +und-TJ ; tg-Cyrl-TJ ; tg ; +und-TK ; tkl-Latn-TK ; tkl ; +und-TL ; pt-Latn-TL ; pt-TL ; +und-TM ; tk-Latn-TM ; tk ; +und-TN ; ar-Arab-TN ; ar-TN ; +und-TO ; to-Latn-TO ; to ; +und-TR ; tr-Latn-TR ; tr ; +und-TT ; en-Latn-TT ; en-TT ; +und-TV ; tvl-Latn-TV ; tvl ; +und-TW ; zh-Hant-TW ; zh-Hant ; zh-TW +und-TZ ; sw-Latn-TZ ; sw ; +und-Taml ; ta-Taml-IN ; ta ; +und-Taml-AQ ; ta-Taml-AQ ; ta-AQ ; +und-Taml-IN ; ta-Taml-IN ; ta ; +und-Taml-LK ; ta-Taml-LK ; ta-LK ; +und-Taml-MY ; ta-Taml-MY ; ta-MY ; +und-Taml-SG ; ta-Taml-SG ; ta-SG ; +und-Telu ; te-Telu-IN ; te ; +und-Telu-AQ ; te-Telu-AQ ; te-AQ ; +und-Telu-IN ; te-Telu-IN ; te ; +und-Thai ; th-Thai-TH ; th ; +und-Thai-AQ ; th-Thai-AQ ; th-AQ ; +und-Thai-TH ; th-Thai-TH ; th ; +und-UA ; uk-Cyrl-UA ; uk ; +und-UG ; sw-Latn-UG ; sw-UG ; +und-UM ; en-Latn-UM ; en-UM ; +und-US ; en-Latn-US ; en ; +und-UY ; es-Latn-UY ; es-UY ; +und-UZ ; uz-Latn-UZ ; uz ; +und-VA ; it-Latn-VA ; it-VA ; +und-VC ; en-Latn-VC ; en-VC ; +und-VE ; es-Latn-VE ; es-VE ; +und-VG ; en-Latn-VG ; en-VG ; +und-VI ; en-Latn-VI ; en-VI ; +und-VN ; vi-Latn-VN ; vi ; +und-VU ; bi-Latn-VU ; bi ; +und-WF ; fr-Latn-WF ; fr-WF ; +und-WS ; sm-Latn-WS ; sm ; +und-XK ; sq-Latn-XK ; sq-XK ; +und-YE ; ar-Arab-YE ; ar-YE ; +und-YT ; fr-Latn-YT ; fr-YT ; +und-ZA ; en-Latn-ZA ; en-ZA ; +und-ZM ; bem-Latn-ZM ; bem ; +und-ZW ; sn-Latn-ZW ; sn ; +ur ; ur-Arab-PK ; ur ; +ur-AQ ; ur-Arab-AQ ; ur-AQ ; +ur-Arab ; ur-Arab-PK ; ur ; +ur-Egyp ; ur-Egyp-PK ; ur-Egyp ; +ur-IN ; ur-Arab-IN ; ur-IN ; +ur-PK ; ur-Arab-PK ; ur ; +uz ; uz-Latn-UZ ; uz ; +uz-AQ ; uz-Latn-AQ ; uz-AQ ; +uz-Cyrl ; uz-Cyrl-UZ ; uz-Cyrl ; +uz-Egyp ; uz-Egyp-UZ ; uz-Egyp ; +uz-Latn ; uz-Latn-UZ ; uz ; +uz-UZ ; uz-Latn-UZ ; uz ; +vec ; vec-Latn-IT ; vec ; +vec-AQ ; vec-Latn-AQ ; vec-AQ ; +vec-Egyp ; vec-Egyp-IT ; vec-Egyp ; +vec-IT ; vec-Latn-IT ; vec ; +vec-Latn ; vec-Latn-IT ; vec ; +vi ; vi-Latn-VN ; vi ; +vi-AQ ; vi-Latn-AQ ; vi-AQ ; +vi-Egyp ; vi-Egyp-VN ; vi-Egyp ; +vi-Latn ; vi-Latn-VN ; vi ; +vi-VN ; vi-Latn-VN ; vi ; +wo ; wo-Latn-SN ; wo ; +wo-AQ ; wo-Latn-AQ ; wo-AQ ; +wo-Egyp ; wo-Egyp-SN ; wo-Egyp ; +wo-Latn ; wo-Latn-SN ; wo ; +wo-SN ; wo-Latn-SN ; wo ; +xh ; xh-Latn-ZA ; xh ; +xh-AQ ; xh-Latn-AQ ; xh-AQ ; +xh-Egyp ; xh-Egyp-ZA ; xh-Egyp ; +xh-Latn ; xh-Latn-ZA ; xh ; +xh-ZA ; xh-Latn-ZA ; xh ; +xnr ; xnr-Deva-IN ; xnr ; +xnr-AQ ; xnr-Deva-AQ ; xnr-AQ ; +xnr-Deva ; xnr-Deva-IN ; xnr ; +xnr-Egyp ; xnr-Egyp-IN ; xnr-Egyp ; +xnr-IN ; xnr-Deva-IN ; xnr ; +yo ; yo-Latn-NG ; yo ; +yo-AQ ; yo-Latn-AQ ; yo-AQ ; +yo-BJ ; yo-Latn-BJ ; yo-BJ ; +yo-Egyp ; yo-Egyp-NG ; yo-Egyp ; +yo-Latn ; yo-Latn-NG ; yo ; +yo-NG ; yo-Latn-NG ; yo ; +yrl ; yrl-Latn-BR ; yrl ; +yrl-AQ ; yrl-Latn-AQ ; yrl-AQ ; +yrl-BR ; yrl-Latn-BR ; yrl ; +yrl-CO ; yrl-Latn-CO ; yrl-CO ; +yrl-Egyp ; yrl-Egyp-BR ; yrl-Egyp ; +yrl-Latn ; yrl-Latn-BR ; yrl ; +yrl-VE ; yrl-Latn-VE ; yrl-VE ; +yue ; yue-Hant-HK ; yue ; +yue-AQ ; yue-Hant-AQ ; yue-AQ ; +yue-CN ; yue-Hans-CN ; yue-Hans ; yue-CN +yue-Egyp ; yue-Egyp-HK ; yue-Egyp ; +yue-HK ; yue-Hant-HK ; yue ; +yue-Hans ; yue-Hans-CN ; yue-Hans ; yue-CN +yue-Hant ; yue-Hant-HK ; yue ; +zh ; zh-Hans-CN ; zh ; +zh-AQ ; zh-Hans-AQ ; zh-AQ ; +zh-CN ; zh-Hans-CN ; zh ; +zh-Egyp ; zh-Egyp-CN ; zh-Egyp ; +zh-HK ; zh-Hant-HK ; zh-HK ; +zh-Hans ; zh-Hans-CN ; zh ; +zh-Hant ; zh-Hant-TW ; zh-Hant ; zh-TW +zh-MO ; zh-Hant-MO ; zh-MO ; +zh-SG ; zh-Hans-SG ; zh-SG ; +zh-TW ; zh-Hant-TW ; zh-Hant ; zh-TW +zu ; zu-Latn-ZA ; zu ; +zu-AQ ; zu-Latn-AQ ; zu-AQ ; +zu-Egyp ; zu-Egyp-ZA ; zu-Egyp ; +zu-Latn ; zu-Latn-ZA ; zu ; +zu-ZA ; zu-Latn-ZA ; zu ; diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/LocaleDistance.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/LocaleDistance.java index 44fbe80fc4a1..3d4d540a3fef 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/LocaleDistance.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/LocaleDistance.java @@ -225,8 +225,8 @@ private LocaleDistance(Data data) { // VisibleForTesting public int testOnlyDistance(ULocale desired, ULocale supported, int threshold, FavorSubtag favorSubtag) { - LSR supportedLSR = XLikelySubtags.INSTANCE.makeMaximizedLsrFrom(supported); - LSR desiredLSR = XLikelySubtags.INSTANCE.makeMaximizedLsrFrom(desired); + LSR supportedLSR = XLikelySubtags.INSTANCE.makeMaximizedLsrFrom(supported, false); + LSR desiredLSR = XLikelySubtags.INSTANCE.makeMaximizedLsrFrom(desired, false); int indexAndDistance = getBestIndexAndDistance(desiredLSR, new LSR[] { supportedLSR }, 1, shiftDistance(threshold), favorSubtag, LocaleMatcher.Direction.WITH_ONE_WAY); return getDistanceFloor(indexAndDistance); diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/XLikelySubtags.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/XLikelySubtags.java index f23e98a90240..01adcc0ca60b 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/XLikelySubtags.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/XLikelySubtags.java @@ -15,6 +15,7 @@ import com.ibm.icu.impl.ICUResourceBundle; import com.ibm.icu.impl.UResource; import com.ibm.icu.util.BytesTrie; +import com.ibm.icu.util.Region; import com.ibm.icu.util.ULocale; public final class XLikelySubtags { @@ -180,7 +181,7 @@ private static String getCanonical(Map aliases, String alias) { } // VisibleForTesting - public LSR makeMaximizedLsrFrom(ULocale locale) { + public LSR makeMaximizedLsrFrom(ULocale locale, boolean returnInputIfUnmatch) { String name = locale.getName(); // Faster than .toLanguageTag(). if (name.startsWith("@x=")) { String tag = locale.toLanguageTag(); @@ -189,8 +190,12 @@ public LSR makeMaximizedLsrFrom(ULocale locale) { // und-x-subtag-subtag... return new LSR(tag, "", "", LSR.EXPLICIT_LSR); } - return makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), - locale.getVariant()); + LSR max = makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), + locale.getVariant(), returnInputIfUnmatch); + if (max.language.isEmpty() && max.script.isEmpty() && max.region.isEmpty()) { + return new LSR(locale.getLanguage(), locale.getScript(), locale.getCountry(), LSR.EXPLICIT_LSR); + } + return max; } public LSR makeMaximizedLsrFrom(Locale locale) { @@ -201,10 +206,10 @@ public LSR makeMaximizedLsrFrom(Locale locale) { return new LSR(tag, "", "", LSR.EXPLICIT_LSR); } return makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), - locale.getVariant()); + locale.getVariant(), false); } - private LSR makeMaximizedLsr(String language, String script, String region, String variant) { + private LSR makeMaximizedLsr(String language, String script, String region, String variant, boolean returnInputIfUnmatch) { // Handle pseudolocales like en-XA, ar-XB, fr-PSCRACK. // They should match only themselves, // not other locales with what looks like the same language and script subtags. @@ -248,13 +253,23 @@ private LSR makeMaximizedLsr(String language, String script, String region, Stri language = getCanonical(languageAliases, language); // (We have no script mappings.) region = getCanonical(regionAliases, region); - return maximize(language, script, region); + return maximize(language, script, region, returnInputIfUnmatch); + } + + /** + * Helper method to find out a region is a macroregion + */ + private boolean isMacroregion(String region) { + Region.RegionType type = Region.getInstance(region).getType(); + return type == Region.RegionType.WORLD || + type == Region.RegionType.CONTINENT || + type == Region.RegionType.SUBCONTINENT ; } /** * Raw access to addLikelySubtags. Input must be in canonical format, eg "en", not "eng" or "EN". */ - private LSR maximize(String language, String script, String region) { + private LSR maximize(String language, String script, String region, boolean returnInputIfUnmatch) { if (language.equals("und")) { language = ""; } @@ -268,7 +283,9 @@ private LSR maximize(String language, String script, String region) { return new LSR(language, script, region, LSR.EXPLICIT_LSR); // already maximized } - int retainOldMask = 0; + boolean retainLanguage = false; + boolean retainScript = false; + boolean retainRegion = false; BytesTrie iter = new BytesTrie(trie); long state; int value; @@ -280,34 +297,33 @@ private LSR maximize(String language, String script, String region) { } else { value = trieNext(iter, language, 0); } + boolean matchLanguage = (value >= 0); + boolean matchScript = false; if (value >= 0) { - if (!language.isEmpty()) { - retainOldMask |= 4; - } + retainLanguage = ! language.isEmpty(); state = iter.getState64(); } else { - retainOldMask |= 4; + retainLanguage = true; iter.resetToState64(trieUndState); // "und" ("*") state = 0; } + if (value >= 0 && !script.isEmpty()) { + matchScript = true; + } if (value > 0) { // Intermediate or final value from just language. if (value == SKIP_SCRIPT) { value = 0; } - if (!script.isEmpty()) { - retainOldMask |= 2; - } + retainScript = ! script.isEmpty(); } else { value = trieNext(iter, script, 0); if (value >= 0) { - if (!script.isEmpty()) { - retainOldMask |= 2; - } + retainScript = ! script.isEmpty(); state = iter.getState64(); } else { - retainOldMask |= 2; + retainScript = true; if (state == 0) { iter.resetToState64(trieUndZzzzState); // "und-Zzzz" ("**") } else { @@ -319,19 +335,19 @@ private LSR maximize(String language, String script, String region) { } } + boolean matchRegion = false; if (value > 0) { // Final value from just language or language+script. - if (!region.isEmpty()) { - retainOldMask |= 1; - } + retainRegion = ! region.isEmpty(); } else { value = trieNext(iter, region, 0); if (value >= 0) { - if (!region.isEmpty()) { - retainOldMask |= 1; + if (!region.isEmpty() && !isMacroregion(region)) { + retainRegion = true; + matchRegion = true; } } else { - retainOldMask |= 1; + retainRegion = true; if (state == 0) { value = defaultLsrIndex; } else { @@ -343,25 +359,30 @@ private LSR maximize(String language, String script, String region) { } LSR result = lsrs[value]; + if (returnInputIfUnmatch && + (!(matchLanguage || matchScript || (matchRegion && language.isEmpty())))) { + return new LSR("", "", "", LSR.EXPLICIT_LSR); // no matching. + } if (language.isEmpty()) { language = "und"; } - if (retainOldMask == 0) { + if (! (retainLanguage || retainScript || retainRegion)) { assert result.flags == LSR.IMPLICIT_LSR; return result; } - if ((retainOldMask & 4) == 0) { + if (!retainLanguage) { language = result.language; } - if ((retainOldMask & 2) == 0) { + if (!retainScript) { script = result.script; } - if ((retainOldMask & 1) == 0) { + if (!retainRegion) { region = result.region; } + int retainMask = (retainLanguage ? 4 : 0) + (retainScript ? 2 : 0) + (retainRegion ? 1 : 0); // retainOldMask flags = LSR explicit-subtag flags - return new LSR(language, script, region, retainOldMask); + return new LSR(language, script, region, retainMask); } /** @@ -502,50 +523,37 @@ private static final int trieNext(BytesTrie iter, String s, int i) { } } - LSR minimizeSubtags(String languageIn, String scriptIn, String regionIn, + public LSR minimizeSubtags(String languageIn, String scriptIn, String regionIn, ULocale.Minimize fieldToFavor) { - LSR result = maximize(languageIn, scriptIn, regionIn); - - // We could try just a series of checks, like: - // LSR result2 = addLikelySubtags(languageIn, "", ""); - // if result.equals(result2) return result2; - // However, we can optimize 2 of the cases: - // (languageIn, "", "") - // (languageIn, "", regionIn) - - // value00 = lookup(result.language, "", "") - BytesTrie iter = new BytesTrie(trie); - int value = trieNext(iter, result.language, 0); - assert value >= 0; - if (value == 0) { - value = trieNext(iter, "", 0); - assert value >= 0; - if (value == 0) { - value = trieNext(iter, "", 0); + LSR max = maximize(languageIn, scriptIn, regionIn, true); + if (max.language.isEmpty() && max.region.isEmpty() && max.script.isEmpty()) { + // Cannot match, return as is + return new LSR(languageIn, scriptIn, regionIn, LSR.EXPLICIT_LSR); + } + LSR test = maximize(max.language, "", "", true); + if (test.isEquivalentTo(max)) { + return new LSR(max.language, "", "", LSR.DONT_CARE_FLAGS); + } + if (ULocale.Minimize.FAVOR_REGION == fieldToFavor) { + test = maximize(max.language, "", max.region, true); + if (test.isEquivalentTo(max)) { + return new LSR(max.language, "", max.region, LSR.DONT_CARE_FLAGS); } - } - assert value > 0; - LSR value00 = lsrs[value]; - boolean favorRegionOk = false; - if (result.script.equals(value00.script)) { //script is default - if (result.region.equals(value00.region)) { - return new LSR(result.language, "", "", LSR.DONT_CARE_FLAGS); - } else if (fieldToFavor == ULocale.Minimize.FAVOR_REGION) { - return new LSR(result.language, "", result.region, LSR.DONT_CARE_FLAGS); - } else { - favorRegionOk = true; + test = maximize(max.language, max.script, "", true); + if (test.isEquivalentTo(max)) { + return new LSR(max.language, max.script, "", LSR.DONT_CARE_FLAGS); + } + } else { + test = maximize(max.language, max.script, "", true); + if (test.isEquivalentTo(max)) { + return new LSR(max.language, max.script, "", LSR.DONT_CARE_FLAGS); + } + test = maximize(max.language, "", max.region, true); + if (test.isEquivalentTo(max)) { + return new LSR(max.language, "", max.region, LSR.DONT_CARE_FLAGS); } } - - // The last case is not as easy to optimize. - // Maybe do later, but for now use the straightforward code. - LSR result2 = maximize(languageIn, scriptIn, ""); - if (result2.equals(result)) { - return new LSR(result.language, result.script, "", LSR.DONT_CARE_FLAGS); - } else if (favorRegionOk) { - return new LSR(result.language, "", result.region, LSR.DONT_CARE_FLAGS); - } - return result; + return new LSR(max.language, max.script, max.region, LSR.DONT_CARE_FLAGS); } private Map getTable() { diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/LocaleMatcher.java b/icu4j/main/classes/core/src/com/ibm/icu/util/LocaleMatcher.java index 35061f000f48..074ee0a4f1ec 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/util/LocaleMatcher.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/util/LocaleMatcher.java @@ -796,7 +796,7 @@ private static final LSR getMaximalLsrOrUnd(ULocale locale) { if (locale.equals(UND_ULOCALE)) { return UND_LSR; } else { - return XLikelySubtags.INSTANCE.makeMaximizedLsrFrom(locale); + return XLikelySubtags.INSTANCE.makeMaximizedLsrFrom(locale, false); } } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/ULocale.java b/icu4j/main/classes/core/src/com/ibm/icu/util/ULocale.java index 0f3591c98b99..50241cf0926d 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/util/ULocale.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/util/ULocale.java @@ -42,15 +42,16 @@ import com.ibm.icu.impl.locale.Extension; import com.ibm.icu.impl.locale.InternalLocaleBuilder; import com.ibm.icu.impl.locale.KeyTypeData; +import com.ibm.icu.impl.locale.LSR; import com.ibm.icu.impl.locale.LanguageTag; import com.ibm.icu.impl.locale.LocaleExtensions; import com.ibm.icu.impl.locale.LocaleSyntaxException; import com.ibm.icu.impl.locale.ParseStatus; import com.ibm.icu.impl.locale.UnicodeLocaleExtension; +import com.ibm.icu.impl.locale.XLikelySubtags; import com.ibm.icu.lang.UScript; import com.ibm.icu.text.LocaleDisplayNames; import com.ibm.icu.text.LocaleDisplayNames.DialectHandling; - /** * {@icuenhanced java.util.Locale}.{@icu _usage_} * @@ -2722,12 +2723,10 @@ public static ULocale addLikelySubtags(ULocale loc) { trailing = loc.localeID.substring(trailingIndex); } - String newLocaleID = - createLikelySubtagsString( - tags[0], - tags[1], - tags[2], - trailing); + LSR max = XLikelySubtags.INSTANCE.makeMaximizedLsrFrom( + new ULocale(loc.getLanguage(), loc.getScript(), loc.getCountry()), true); + String newLocaleID = createTagString(max.language, max.script, max.region, + trailing); return newLocaleID == null ? loc : new ULocale(newLocaleID); } @@ -2819,148 +2818,22 @@ public enum Minimize { @Deprecated public static ULocale minimizeSubtags(ULocale loc, Minimize fieldToFavor) { String[] tags = new String[3]; + String trailing = null; int trailingIndex = parseTagString( loc.localeID, tags); - String originalLang = tags[0]; - String originalScript = tags[1]; - String originalRegion = tags[2]; - String originalTrailing = null; - if (trailingIndex < loc.localeID.length()) { - /* - * Create a String that contains everything - * after the language, script, and region. - */ - originalTrailing = loc.localeID.substring(trailingIndex); + trailing = loc.localeID.substring(trailingIndex); } - /** - * First, we need to first get the maximization - * by adding any likely subtags. - **/ - String maximizedLocaleID = - createLikelySubtagsString( - originalLang, - originalScript, - originalRegion, - null); - - /** - * If maximization fails, there's nothing - * we can do. - **/ - if (isEmptyString(maximizedLocaleID)) { - return loc; - } - else { - /** - * Start first with just the language. - **/ - String tag = - createLikelySubtagsString( - originalLang, - null, - null, - null); - - if (tag.equals(maximizedLocaleID)) { - String newLocaleID = - createTagString( - originalLang, - null, - null, - originalTrailing); - - return new ULocale(newLocaleID); - } - } + LSR lsr = XLikelySubtags.INSTANCE.minimizeSubtags( + loc.getLanguage(), loc.getScript(), loc.getCountry(), fieldToFavor); + String newLocaleID = createTagString(lsr.language, lsr.script, lsr.region, + trailing); - /** - * Next, try the language and region. - **/ - if (fieldToFavor == Minimize.FAVOR_REGION) { - if (originalRegion.length() != 0) { - String tag = - createLikelySubtagsString( - originalLang, - null, - originalRegion, - null); - - if (tag.equals(maximizedLocaleID)) { - String newLocaleID = - createTagString( - originalLang, - null, - originalRegion, - originalTrailing); - - return new ULocale(newLocaleID); - } - } - if (originalScript.length() != 0){ - String tag = - createLikelySubtagsString( - originalLang, - originalScript, - null, - null); - - if (tag.equals(maximizedLocaleID)) { - String newLocaleID = - createTagString( - originalLang, - originalScript, - null, - originalTrailing); - - return new ULocale(newLocaleID); - } - } - } else { // FAVOR_SCRIPT, so - if (originalScript.length() != 0){ - String tag = - createLikelySubtagsString( - originalLang, - originalScript, - null, - null); - - if (tag.equals(maximizedLocaleID)) { - String newLocaleID = - createTagString( - originalLang, - originalScript, - null, - originalTrailing); - - return new ULocale(newLocaleID); - } - } - if (originalRegion.length() != 0) { - String tag = - createLikelySubtagsString( - originalLang, - null, - originalRegion, - null); - - if (tag.equals(maximizedLocaleID)) { - String newLocaleID = - createTagString( - originalLang, - null, - originalRegion, - originalTrailing); - - return new ULocale(newLocaleID); - } - } - } - return loc; + return newLocaleID == null ? loc : new ULocale(newLocaleID); } /** @@ -3007,10 +2880,9 @@ private static void appendTag(String tag, StringBuilder buffer) { * @return The new tag string. **/ private static String createTagString(String lang, String script, String region, - String trailing, String alternateTags) { + String trailing) { LocaleIDParser parser = null; - boolean regionAppended = false; StringBuilder tag = new StringBuilder(); @@ -3018,8 +2890,7 @@ private static String createTagString(String lang, String script, String region, appendTag( lang, tag); - } - else if (isEmptyString(alternateTags)) { + } else { /* * Append the value for an unknown language, if * we found no language. @@ -3028,66 +2899,17 @@ else if (isEmptyString(alternateTags)) { UNDEFINED_LANGUAGE, tag); } - else { - parser = new LocaleIDParser(alternateTags); - - String alternateLang = parser.getLanguage(); - - /* - * Append the value for an unknown language, if - * we found no language. - */ - appendTag( - !isEmptyString(alternateLang) ? alternateLang : UNDEFINED_LANGUAGE, - tag); - } if (!isEmptyString(script)) { appendTag( script, tag); } - else if (!isEmptyString(alternateTags)) { - /* - * Parse the alternateTags string for the script. - */ - if (parser == null) { - parser = new LocaleIDParser(alternateTags); - } - - String alternateScript = parser.getScript(); - - if (!isEmptyString(alternateScript)) { - appendTag( - alternateScript, - tag); - } - } if (!isEmptyString(region)) { appendTag( region, tag); - - regionAppended = true; - } - else if (!isEmptyString(alternateTags)) { - /* - * Parse the alternateTags string for the region. - */ - if (parser == null) { - parser = new LocaleIDParser(alternateTags); - } - - String alternateRegion = parser.getCountry(); - - if (!isEmptyString(alternateRegion)) { - appendTag( - alternateRegion, - tag); - - regionAppended = true; - } } if (trailing != null && trailing.length() > 1) { @@ -3107,7 +2929,7 @@ else if (!isEmptyString(alternateTags)) { separators = 1; } - if (regionAppended) { + if (!isEmptyString(region)) { /* * If we appended a region, we may need to strip * the extra separator from the variant portion. @@ -3134,21 +2956,6 @@ else if (!isEmptyString(alternateTags)) { return tag.toString(); } - /** - * Create a tag string from the supplied parameters. The lang, script and region - * parameters may be null references.If the lang parameter is an empty string, the - * default value for an unknown language is written to the output buffer. - * - * @param lang The language tag to use. - * @param script The script tag to use. - * @param region The region tag to use. - * @param trailing Any trailing data to append to the new tag. - * @return The new String. - **/ - static String createTagString(String lang, String script, String region, String trailing) { - return createTagString(lang, script, region, trailing, null); - } - /** * Parse the language, script, and region subtags from a tag string, and return the results. * @@ -3214,144 +3021,6 @@ private static int parseTagString(String localeID, String tags[]) { } } - private static String lookupLikelySubtags(String localeId) { - UResourceBundle bundle = - UResourceBundle.getBundleInstance( - ICUData.ICU_BASE_NAME, "likelySubtags"); - try { - return bundle.getString(localeId); - } - catch(MissingResourceException e) { - return null; - } - } - - private static String createLikelySubtagsString(String lang, String script, String region, - String variants) { - - /** - * Try the language with the script and region first. - */ - if (!isEmptyString(script) && !isEmptyString(region)) { - - String searchTag = - createTagString( - lang, - script, - region, - null); - - String likelySubtags = lookupLikelySubtags(searchTag); - - /* - if (likelySubtags == null) { - if (likelySubtags2 != null) { - System.err.println("Tag mismatch: \"(null)\" \"" + likelySubtags2 + "\""); - } - } - else if (likelySubtags2 == null) { - System.err.println("Tag mismatch: \"" + likelySubtags + "\" \"(null)\""); - } - else if (!likelySubtags.equals(likelySubtags2)) { - System.err.println("Tag mismatch: \"" + likelySubtags + "\" \"" + likelySubtags2 - + "\""); - } - */ - if (likelySubtags != null) { - // Always use the language tag from the - // maximal string, since it may be more - // specific than the one provided. - return createTagString( - null, - null, - null, - variants, - likelySubtags); - } - } - - /** - * Try the language with just the script. - **/ - if (!isEmptyString(script)) { - - String searchTag = - createTagString( - lang, - script, - null, - null); - - String likelySubtags = lookupLikelySubtags(searchTag); - if (likelySubtags != null) { - // Always use the language tag from the - // maximal string, since it may be more - // specific than the one provided. - return createTagString( - null, - null, - region, - variants, - likelySubtags); - } - } - - /** - * Try the language with just the region. - **/ - if (!isEmptyString(region)) { - - String searchTag = - createTagString( - lang, - null, - region, - null); - - String likelySubtags = lookupLikelySubtags(searchTag); - - if (likelySubtags != null) { - // Always use the language tag from the - // maximal string, since it may be more - // specific than the one provided. - return createTagString( - null, - script, - null, - variants, - likelySubtags); - } - } - - /** - * Finally, try just the language. - **/ - { - String searchTag = - createTagString( - lang, - null, - null, - null); - - String likelySubtags = lookupLikelySubtags(searchTag); - - if (likelySubtags != null) { - // Always use the language tag from the - // maximal string, since it may be more - // specific than the one provided. - return createTagString( - null, - script, - region, - variants, - likelySubtags); - } - } - - return null; - } - // -------------------------------- // BCP47/OpenJDK APIs // -------------------------------- diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/data/likelySubtags.txt b/icu4j/main/tests/core/src/com/ibm/icu/dev/data/likelySubtags.txt new file mode 100644 index 000000000000..4482b13397ba --- /dev/null +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/data/likelySubtags.txt @@ -0,0 +1,1607 @@ +# Test data for Likely Subtags +# Copyright © 1991-2023 Unicode, Inc. +# For terms of use, see http://www.unicode.org/copyright.html +# SPDX-License-Identifier: Unicode-DFS-2016 +# CLDR data files are interpreted according to the LDML specification (http://unicode.org/reports/tr35/) +# +# Test data for https://www.unicode.org/reports/tr35/tr35.html#Likely_Subtags +# +# Format: + +# Source ; AddLikely ; RemoveFavorScript ; RemoveFavorRegion +# Source: a locale to which the following operations are applied. +# AddLikely: the result of the Add Likely Subtags. +# If Add Likely Subtags fails, then “FAIL”. +# RemoveFavorScript: Remove Likely Subtags, when the script is favored. +# Only included when different than AddLikely. +# RemoveFavorRegion: Remove Likely Subtags, when the region is favored. +# Only included when different than RemoveFavorScript. +# +# Generation: GenerateLikelyTestData.java + +af ; af-Latn-ZA ; af ; +af-AQ ; af-Latn-AQ ; af-AQ ; +af-Egyp ; af-Egyp-ZA ; af-Egyp ; +af-Latn ; af-Latn-ZA ; af ; +af-NA ; af-Latn-NA ; af-NA ; +af-ZA ; af-Latn-ZA ; af ; +am ; am-Ethi-ET ; am ; +am-AQ ; am-Ethi-AQ ; am-AQ ; +am-ET ; am-Ethi-ET ; am ; +am-Egyp ; am-Egyp-ET ; am-Egyp ; +am-Ethi ; am-Ethi-ET ; am ; +ar ; ar-Arab-EG ; ar ; +ar-001 ; ar-Arab-001 ; ar-001 ; +ar-AE ; ar-Arab-AE ; ar-AE ; +ar-AQ ; ar-Arab-AQ ; ar-AQ ; +ar-Arab ; ar-Arab-EG ; ar ; +ar-BH ; ar-Arab-BH ; ar-BH ; +ar-DJ ; ar-Arab-DJ ; ar-DJ ; +ar-DZ ; ar-Arab-DZ ; ar-DZ ; +ar-EG ; ar-Arab-EG ; ar ; +ar-EH ; ar-Arab-EH ; ar-EH ; +ar-ER ; ar-Arab-ER ; ar-ER ; +ar-Egyp ; ar-Egyp-EG ; ar-Egyp ; +ar-IL ; ar-Arab-IL ; ar-IL ; +ar-IQ ; ar-Arab-IQ ; ar-IQ ; +ar-JO ; ar-Arab-JO ; ar-JO ; +ar-KM ; ar-Arab-KM ; ar-KM ; +ar-KW ; ar-Arab-KW ; ar-KW ; +ar-LB ; ar-Arab-LB ; ar-LB ; +ar-LY ; ar-Arab-LY ; ar-LY ; +ar-MA ; ar-Arab-MA ; ar-MA ; +ar-MR ; ar-Arab-MR ; ar-MR ; +ar-OM ; ar-Arab-OM ; ar-OM ; +ar-PS ; ar-Arab-PS ; ar-PS ; +ar-QA ; ar-Arab-QA ; ar-QA ; +ar-SA ; ar-Arab-SA ; ar-SA ; +ar-SD ; ar-Arab-SD ; ar-SD ; +ar-SO ; ar-Arab-SO ; ar-SO ; +ar-SS ; ar-Arab-SS ; ar-SS ; +ar-SY ; ar-Arab-SY ; ar-SY ; +ar-TD ; ar-Arab-TD ; ar-TD ; +ar-TN ; ar-Arab-TN ; ar-TN ; +ar-YE ; ar-Arab-YE ; ar-YE ; +as ; as-Beng-IN ; as ; +as-AQ ; as-Beng-AQ ; as-AQ ; +as-Beng ; as-Beng-IN ; as ; +as-Egyp ; as-Egyp-IN ; as-Egyp ; +as-IN ; as-Beng-IN ; as ; +ast ; ast-Latn-ES ; ast ; +ast-AQ ; ast-Latn-AQ ; ast-AQ ; +ast-ES ; ast-Latn-ES ; ast ; +ast-Egyp ; ast-Egyp-ES ; ast-Egyp ; +ast-Latn ; ast-Latn-ES ; ast ; +az ; az-Latn-AZ ; az ; +az-AQ ; az-Latn-AQ ; az-AQ ; +az-AZ ; az-Latn-AZ ; az ; +az-Egyp ; az-Egyp-AZ ; az-Egyp ; +az-Latn ; az-Latn-AZ ; az ; +be ; be-Cyrl-BY ; be ; +be-AQ ; be-Cyrl-AQ ; be-AQ ; +be-BY ; be-Cyrl-BY ; be ; +be-Cyrl ; be-Cyrl-BY ; be ; +be-Egyp ; be-Egyp-BY ; be-Egyp ; +bg ; bg-Cyrl-BG ; bg ; +bg-AQ ; bg-Cyrl-AQ ; bg-AQ ; +bg-BG ; bg-Cyrl-BG ; bg ; +bg-Cyrl ; bg-Cyrl-BG ; bg ; +bg-Egyp ; bg-Egyp-BG ; bg-Egyp ; +bgc ; bgc-Deva-IN ; bgc ; +bgc-AQ ; bgc-Deva-AQ ; bgc-AQ ; +bgc-Deva ; bgc-Deva-IN ; bgc ; +bgc-Egyp ; bgc-Egyp-IN ; bgc-Egyp ; +bgc-IN ; bgc-Deva-IN ; bgc ; +bho ; bho-Deva-IN ; bho ; +bho-AQ ; bho-Deva-AQ ; bho-AQ ; +bho-Deva ; bho-Deva-IN ; bho ; +bho-Egyp ; bho-Egyp-IN ; bho-Egyp ; +bho-IN ; bho-Deva-IN ; bho ; +blo ; blo-Latn-BJ ; blo ; +blo-AQ ; blo-Latn-AQ ; blo-AQ ; +blo-BJ ; blo-Latn-BJ ; blo ; +blo-Egyp ; blo-Egyp-BJ ; blo-Egyp ; +blo-Latn ; blo-Latn-BJ ; blo ; +bn ; bn-Beng-BD ; bn ; +bn-AQ ; bn-Beng-AQ ; bn-AQ ; +bn-BD ; bn-Beng-BD ; bn ; +bn-Beng ; bn-Beng-BD ; bn ; +bn-Egyp ; bn-Egyp-BD ; bn-Egyp ; +bn-IN ; bn-Beng-IN ; bn-IN ; +br ; br-Latn-FR ; br ; +br-AQ ; br-Latn-AQ ; br-AQ ; +br-Egyp ; br-Egyp-FR ; br-Egyp ; +br-FR ; br-Latn-FR ; br ; +br-Latn ; br-Latn-FR ; br ; +brx ; brx-Deva-IN ; brx ; +brx-AQ ; brx-Deva-AQ ; brx-AQ ; +brx-Deva ; brx-Deva-IN ; brx ; +brx-Egyp ; brx-Egyp-IN ; brx-Egyp ; +brx-IN ; brx-Deva-IN ; brx ; +bs ; bs-Latn-BA ; bs ; +bs-AQ ; bs-Latn-AQ ; bs-AQ ; +bs-BA ; bs-Latn-BA ; bs ; +bs-Cyrl ; bs-Cyrl-BA ; bs-Cyrl ; +bs-Egyp ; bs-Egyp-BA ; bs-Egyp ; +bs-Latn ; bs-Latn-BA ; bs ; +ca ; ca-Latn-ES ; ca ; +ca-AD ; ca-Latn-AD ; ca-AD ; +ca-AQ ; ca-Latn-AQ ; ca-AQ ; +ca-ES ; ca-Latn-ES ; ca ; +ca-Egyp ; ca-Egyp-ES ; ca-Egyp ; +ca-FR ; ca-Latn-FR ; ca-FR ; +ca-IT ; ca-Latn-IT ; ca-IT ; +ca-Latn ; ca-Latn-ES ; ca ; +ceb ; ceb-Latn-PH ; ceb ; +ceb-AQ ; ceb-Latn-AQ ; ceb-AQ ; +ceb-Egyp ; ceb-Egyp-PH ; ceb-Egyp ; +ceb-Latn ; ceb-Latn-PH ; ceb ; +ceb-PH ; ceb-Latn-PH ; ceb ; +chr ; chr-Cher-US ; chr ; +chr-AQ ; chr-Cher-AQ ; chr-AQ ; +chr-Cher ; chr-Cher-US ; chr ; +chr-Egyp ; chr-Egyp-US ; chr-Egyp ; +chr-US ; chr-Cher-US ; chr ; +cs ; cs-Latn-CZ ; cs ; +cs-AQ ; cs-Latn-AQ ; cs-AQ ; +cs-CZ ; cs-Latn-CZ ; cs ; +cs-Egyp ; cs-Egyp-CZ ; cs-Egyp ; +cs-Latn ; cs-Latn-CZ ; cs ; +csw ; csw-Cans-CA ; csw ; +csw-AQ ; csw-Cans-AQ ; csw-AQ ; +csw-CA ; csw-Cans-CA ; csw ; +csw-Cans ; csw-Cans-CA ; csw ; +csw-Egyp ; csw-Egyp-CA ; csw-Egyp ; +cv ; cv-Cyrl-RU ; cv ; +cv-AQ ; cv-Cyrl-AQ ; cv-AQ ; +cv-Cyrl ; cv-Cyrl-RU ; cv ; +cv-Egyp ; cv-Egyp-RU ; cv-Egyp ; +cv-RU ; cv-Cyrl-RU ; cv ; +cy ; cy-Latn-GB ; cy ; +cy-AQ ; cy-Latn-AQ ; cy-AQ ; +cy-Egyp ; cy-Egyp-GB ; cy-Egyp ; +cy-GB ; cy-Latn-GB ; cy ; +cy-Latn ; cy-Latn-GB ; cy ; +da ; da-Latn-DK ; da ; +da-AQ ; da-Latn-AQ ; da-AQ ; +da-DK ; da-Latn-DK ; da ; +da-Egyp ; da-Egyp-DK ; da-Egyp ; +da-GL ; da-Latn-GL ; da-GL ; +da-Latn ; da-Latn-DK ; da ; +de ; de-Latn-DE ; de ; +de-AQ ; de-Latn-AQ ; de-AQ ; +de-AT ; de-Latn-AT ; de-AT ; +de-BE ; de-Latn-BE ; de-BE ; +de-CH ; de-Latn-CH ; de-CH ; +de-DE ; de-Latn-DE ; de ; +de-Egyp ; de-Egyp-DE ; de-Egyp ; +de-IT ; de-Latn-IT ; de-IT ; +de-LI ; de-Latn-LI ; de-LI ; +de-LU ; de-Latn-LU ; de-LU ; +de-Latn ; de-Latn-DE ; de ; +doi ; doi-Deva-IN ; doi ; +doi-AQ ; doi-Deva-AQ ; doi-AQ ; +doi-Deva ; doi-Deva-IN ; doi ; +doi-Egyp ; doi-Egyp-IN ; doi-Egyp ; +doi-IN ; doi-Deva-IN ; doi ; +dsb ; dsb-Latn-DE ; dsb ; +dsb-AQ ; dsb-Latn-AQ ; dsb-AQ ; +dsb-DE ; dsb-Latn-DE ; dsb ; +dsb-Egyp ; dsb-Egyp-DE ; dsb-Egyp ; +dsb-Latn ; dsb-Latn-DE ; dsb ; +el ; el-Grek-GR ; el ; +el-AQ ; el-Grek-AQ ; el-AQ ; +el-CY ; el-Grek-CY ; el-CY ; +el-Egyp ; el-Egyp-GR ; el-Egyp ; +el-GR ; el-Grek-GR ; el ; +el-Grek ; el-Grek-GR ; el ; +en ; en-Latn-US ; en ; +en-001 ; en-Latn-001 ; en-001 ; +en-150 ; en-Latn-150 ; en-150 ; +en-AE ; en-Latn-AE ; en-AE ; +en-AG ; en-Latn-AG ; en-AG ; +en-AI ; en-Latn-AI ; en-AI ; +en-AQ ; en-Latn-AQ ; en-AQ ; +en-AS ; en-Latn-AS ; en-AS ; +en-AT ; en-Latn-AT ; en-AT ; +en-AU ; en-Latn-AU ; en-AU ; +en-BB ; en-Latn-BB ; en-BB ; +en-BE ; en-Latn-BE ; en-BE ; +en-BI ; en-Latn-BI ; en-BI ; +en-BM ; en-Latn-BM ; en-BM ; +en-BS ; en-Latn-BS ; en-BS ; +en-BW ; en-Latn-BW ; en-BW ; +en-BZ ; en-Latn-BZ ; en-BZ ; +en-CA ; en-Latn-CA ; en-CA ; +en-CC ; en-Latn-CC ; en-CC ; +en-CH ; en-Latn-CH ; en-CH ; +en-CK ; en-Latn-CK ; en-CK ; +en-CM ; en-Latn-CM ; en-CM ; +en-CX ; en-Latn-CX ; en-CX ; +en-CY ; en-Latn-CY ; en-CY ; +en-DE ; en-Latn-DE ; en-DE ; +en-DG ; en-Latn-DG ; en-DG ; +en-DK ; en-Latn-DK ; en-DK ; +en-DM ; en-Latn-DM ; en-DM ; +en-ER ; en-Latn-ER ; en-ER ; +en-Egyp ; en-Egyp-US ; en-Egyp ; +en-FI ; en-Latn-FI ; en-FI ; +en-FJ ; en-Latn-FJ ; en-FJ ; +en-FK ; en-Latn-FK ; en-FK ; +en-FM ; en-Latn-FM ; en-FM ; +en-GB ; en-Latn-GB ; en-GB ; +en-GD ; en-Latn-GD ; en-GD ; +en-GG ; en-Latn-GG ; en-GG ; +en-GH ; en-Latn-GH ; en-GH ; +en-GI ; en-Latn-GI ; en-GI ; +en-GM ; en-Latn-GM ; en-GM ; +en-GU ; en-Latn-GU ; en-GU ; +en-GY ; en-Latn-GY ; en-GY ; +en-HK ; en-Latn-HK ; en-HK ; +en-IE ; en-Latn-IE ; en-IE ; +en-IL ; en-Latn-IL ; en-IL ; +en-IM ; en-Latn-IM ; en-IM ; +en-IN ; en-Latn-IN ; en-IN ; +en-IO ; en-Latn-IO ; en-IO ; +en-JE ; en-Latn-JE ; en-JE ; +en-JM ; en-Latn-JM ; en-JM ; +en-KE ; en-Latn-KE ; en-KE ; +en-KI ; en-Latn-KI ; en-KI ; +en-KN ; en-Latn-KN ; en-KN ; +en-KY ; en-Latn-KY ; en-KY ; +en-LC ; en-Latn-LC ; en-LC ; +en-LR ; en-Latn-LR ; en-LR ; +en-LS ; en-Latn-LS ; en-LS ; +en-Latn ; en-Latn-US ; en ; +en-MG ; en-Latn-MG ; en-MG ; +en-MH ; en-Latn-MH ; en-MH ; +en-MO ; en-Latn-MO ; en-MO ; +en-MP ; en-Latn-MP ; en-MP ; +en-MS ; en-Latn-MS ; en-MS ; +en-MT ; en-Latn-MT ; en-MT ; +en-MU ; en-Latn-MU ; en-MU ; +en-MV ; en-Latn-MV ; en-MV ; +en-MW ; en-Latn-MW ; en-MW ; +en-MY ; en-Latn-MY ; en-MY ; +en-NA ; en-Latn-NA ; en-NA ; +en-NF ; en-Latn-NF ; en-NF ; +en-NG ; en-Latn-NG ; en-NG ; +en-NL ; en-Latn-NL ; en-NL ; +en-NR ; en-Latn-NR ; en-NR ; +en-NU ; en-Latn-NU ; en-NU ; +en-NZ ; en-Latn-NZ ; en-NZ ; +en-PG ; en-Latn-PG ; en-PG ; +en-PH ; en-Latn-PH ; en-PH ; +en-PK ; en-Latn-PK ; en-PK ; +en-PN ; en-Latn-PN ; en-PN ; +en-PR ; en-Latn-PR ; en-PR ; +en-PW ; en-Latn-PW ; en-PW ; +en-RW ; en-Latn-RW ; en-RW ; +en-SB ; en-Latn-SB ; en-SB ; +en-SC ; en-Latn-SC ; en-SC ; +en-SD ; en-Latn-SD ; en-SD ; +en-SE ; en-Latn-SE ; en-SE ; +en-SG ; en-Latn-SG ; en-SG ; +en-SH ; en-Latn-SH ; en-SH ; +en-SI ; en-Latn-SI ; en-SI ; +en-SL ; en-Latn-SL ; en-SL ; +en-SS ; en-Latn-SS ; en-SS ; +en-SX ; en-Latn-SX ; en-SX ; +en-SZ ; en-Latn-SZ ; en-SZ ; +en-TC ; en-Latn-TC ; en-TC ; +en-TK ; en-Latn-TK ; en-TK ; +en-TO ; en-Latn-TO ; en-TO ; +en-TT ; en-Latn-TT ; en-TT ; +en-TV ; en-Latn-TV ; en-TV ; +en-TZ ; en-Latn-TZ ; en-TZ ; +en-UG ; en-Latn-UG ; en-UG ; +en-UM ; en-Latn-UM ; en-UM ; +en-US ; en-Latn-US ; en ; +en-VC ; en-Latn-VC ; en-VC ; +en-VG ; en-Latn-VG ; en-VG ; +en-VI ; en-Latn-VI ; en-VI ; +en-VU ; en-Latn-VU ; en-VU ; +en-WS ; en-Latn-WS ; en-WS ; +en-ZA ; en-Latn-ZA ; en-ZA ; +en-ZM ; en-Latn-ZM ; en-ZM ; +en-ZW ; en-Latn-ZW ; en-ZW ; +es ; es-Latn-ES ; es ; +es-419 ; es-Latn-419 ; es-419 ; +es-AQ ; es-Latn-AQ ; es-AQ ; +es-AR ; es-Latn-AR ; es-AR ; +es-BO ; es-Latn-BO ; es-BO ; +es-BR ; es-Latn-BR ; es-BR ; +es-BZ ; es-Latn-BZ ; es-BZ ; +es-CL ; es-Latn-CL ; es-CL ; +es-CO ; es-Latn-CO ; es-CO ; +es-CR ; es-Latn-CR ; es-CR ; +es-CU ; es-Latn-CU ; es-CU ; +es-DO ; es-Latn-DO ; es-DO ; +es-EA ; es-Latn-EA ; es-EA ; +es-EC ; es-Latn-EC ; es-EC ; +es-ES ; es-Latn-ES ; es ; +es-Egyp ; es-Egyp-ES ; es-Egyp ; +es-GQ ; es-Latn-GQ ; es-GQ ; +es-GT ; es-Latn-GT ; es-GT ; +es-HN ; es-Latn-HN ; es-HN ; +es-IC ; es-Latn-IC ; es-IC ; +es-Latn ; es-Latn-ES ; es ; +es-MX ; es-Latn-MX ; es-MX ; +es-NI ; es-Latn-NI ; es-NI ; +es-PA ; es-Latn-PA ; es-PA ; +es-PE ; es-Latn-PE ; es-PE ; +es-PH ; es-Latn-PH ; es-PH ; +es-PR ; es-Latn-PR ; es-PR ; +es-PY ; es-Latn-PY ; es-PY ; +es-SV ; es-Latn-SV ; es-SV ; +es-US ; es-Latn-US ; es-US ; +es-UY ; es-Latn-UY ; es-UY ; +es-VE ; es-Latn-VE ; es-VE ; +et ; et-Latn-EE ; et ; +et-AQ ; et-Latn-AQ ; et-AQ ; +et-EE ; et-Latn-EE ; et ; +et-Egyp ; et-Egyp-EE ; et-Egyp ; +et-Latn ; et-Latn-EE ; et ; +eu ; eu-Latn-ES ; eu ; +eu-AQ ; eu-Latn-AQ ; eu-AQ ; +eu-ES ; eu-Latn-ES ; eu ; +eu-Egyp ; eu-Egyp-ES ; eu-Egyp ; +eu-Latn ; eu-Latn-ES ; eu ; +fa ; fa-Arab-IR ; fa ; +fa-AF ; fa-Arab-AF ; fa-AF ; +fa-AQ ; fa-Arab-AQ ; fa-AQ ; +fa-Arab ; fa-Arab-IR ; fa ; +fa-Egyp ; fa-Egyp-IR ; fa-Egyp ; +fa-IR ; fa-Arab-IR ; fa ; +ff ; ff-Latn-SN ; ff ; +ff-AQ ; ff-Latn-AQ ; ff-AQ ; +ff-Adlm ; ff-Adlm-GN ; ff-Adlm ; +ff-BF ; ff-Latn-BF ; ff-BF ; +ff-CM ; ff-Latn-CM ; ff-CM ; +ff-Egyp ; ff-Egyp-SN ; ff-Egyp ; +ff-GH ; ff-Latn-GH ; ff-GH ; +ff-GM ; ff-Latn-GM ; ff-GM ; +ff-GN ; ff-Latn-GN ; ff-GN ; +ff-GW ; ff-Latn-GW ; ff-GW ; +ff-LR ; ff-Latn-LR ; ff-LR ; +ff-MR ; ff-Latn-MR ; ff-MR ; +ff-NE ; ff-Latn-NE ; ff-NE ; +ff-NG ; ff-Latn-NG ; ff-NG ; +ff-SL ; ff-Latn-SL ; ff-SL ; +ff-SN ; ff-Latn-SN ; ff ; +fi ; fi-Latn-FI ; fi ; +fi-AQ ; fi-Latn-AQ ; fi-AQ ; +fi-Egyp ; fi-Egyp-FI ; fi-Egyp ; +fi-FI ; fi-Latn-FI ; fi ; +fi-Latn ; fi-Latn-FI ; fi ; +fil ; fil-Latn-PH ; fil ; +fil-AQ ; fil-Latn-AQ ; fil-AQ ; +fil-Egyp ; fil-Egyp-PH ; fil-Egyp ; +fil-Latn ; fil-Latn-PH ; fil ; +fil-PH ; fil-Latn-PH ; fil ; +fo ; fo-Latn-FO ; fo ; +fo-AQ ; fo-Latn-AQ ; fo-AQ ; +fo-DK ; fo-Latn-DK ; fo-DK ; +fo-Egyp ; fo-Egyp-FO ; fo-Egyp ; +fo-FO ; fo-Latn-FO ; fo ; +fo-Latn ; fo-Latn-FO ; fo ; +fr ; fr-Latn-FR ; fr ; +fr-AQ ; fr-Latn-AQ ; fr-AQ ; +fr-BE ; fr-Latn-BE ; fr-BE ; +fr-BF ; fr-Latn-BF ; fr-BF ; +fr-BI ; fr-Latn-BI ; fr-BI ; +fr-BJ ; fr-Latn-BJ ; fr-BJ ; +fr-BL ; fr-Latn-BL ; fr-BL ; +fr-CA ; fr-Latn-CA ; fr-CA ; +fr-CD ; fr-Latn-CD ; fr-CD ; +fr-CF ; fr-Latn-CF ; fr-CF ; +fr-CG ; fr-Latn-CG ; fr-CG ; +fr-CH ; fr-Latn-CH ; fr-CH ; +fr-CI ; fr-Latn-CI ; fr-CI ; +fr-CM ; fr-Latn-CM ; fr-CM ; +fr-DJ ; fr-Latn-DJ ; fr-DJ ; +fr-DZ ; fr-Latn-DZ ; fr-DZ ; +fr-Egyp ; fr-Egyp-FR ; fr-Egyp ; +fr-FR ; fr-Latn-FR ; fr ; +fr-GA ; fr-Latn-GA ; fr-GA ; +fr-GF ; fr-Latn-GF ; fr-GF ; +fr-GN ; fr-Latn-GN ; fr-GN ; +fr-GP ; fr-Latn-GP ; fr-GP ; +fr-GQ ; fr-Latn-GQ ; fr-GQ ; +fr-HT ; fr-Latn-HT ; fr-HT ; +fr-KM ; fr-Latn-KM ; fr-KM ; +fr-LU ; fr-Latn-LU ; fr-LU ; +fr-Latn ; fr-Latn-FR ; fr ; +fr-MA ; fr-Latn-MA ; fr-MA ; +fr-MC ; fr-Latn-MC ; fr-MC ; +fr-MF ; fr-Latn-MF ; fr-MF ; +fr-MG ; fr-Latn-MG ; fr-MG ; +fr-ML ; fr-Latn-ML ; fr-ML ; +fr-MQ ; fr-Latn-MQ ; fr-MQ ; +fr-MR ; fr-Latn-MR ; fr-MR ; +fr-MU ; fr-Latn-MU ; fr-MU ; +fr-NC ; fr-Latn-NC ; fr-NC ; +fr-NE ; fr-Latn-NE ; fr-NE ; +fr-PF ; fr-Latn-PF ; fr-PF ; +fr-PM ; fr-Latn-PM ; fr-PM ; +fr-RE ; fr-Latn-RE ; fr-RE ; +fr-RW ; fr-Latn-RW ; fr-RW ; +fr-SC ; fr-Latn-SC ; fr-SC ; +fr-SN ; fr-Latn-SN ; fr-SN ; +fr-SY ; fr-Latn-SY ; fr-SY ; +fr-TD ; fr-Latn-TD ; fr-TD ; +fr-TG ; fr-Latn-TG ; fr-TG ; +fr-TN ; fr-Latn-TN ; fr-TN ; +fr-VU ; fr-Latn-VU ; fr-VU ; +fr-WF ; fr-Latn-WF ; fr-WF ; +fr-YT ; fr-Latn-YT ; fr-YT ; +ga ; ga-Latn-IE ; ga ; +ga-AQ ; ga-Latn-AQ ; ga-AQ ; +ga-Egyp ; ga-Egyp-IE ; ga-Egyp ; +ga-GB ; ga-Latn-GB ; ga-GB ; +ga-IE ; ga-Latn-IE ; ga ; +ga-Latn ; ga-Latn-IE ; ga ; +gd ; gd-Latn-GB ; gd ; +gd-AQ ; gd-Latn-AQ ; gd-AQ ; +gd-Egyp ; gd-Egyp-GB ; gd-Egyp ; +gd-GB ; gd-Latn-GB ; gd ; +gd-Latn ; gd-Latn-GB ; gd ; +gl ; gl-Latn-ES ; gl ; +gl-AQ ; gl-Latn-AQ ; gl-AQ ; +gl-ES ; gl-Latn-ES ; gl ; +gl-Egyp ; gl-Egyp-ES ; gl-Egyp ; +gl-Latn ; gl-Latn-ES ; gl ; +gu ; gu-Gujr-IN ; gu ; +gu-AQ ; gu-Gujr-AQ ; gu-AQ ; +gu-Egyp ; gu-Egyp-IN ; gu-Egyp ; +gu-Gujr ; gu-Gujr-IN ; gu ; +gu-IN ; gu-Gujr-IN ; gu ; +ha ; ha-Latn-NG ; ha ; +ha-AQ ; ha-Latn-AQ ; ha-AQ ; +ha-Egyp ; ha-Egyp-NG ; ha-Egyp ; +ha-GH ; ha-Latn-GH ; ha-GH ; +ha-Latn ; ha-Latn-NG ; ha ; +ha-NE ; ha-Latn-NE ; ha-NE ; +ha-NG ; ha-Latn-NG ; ha ; +he ; he-Hebr-IL ; he ; +he-AQ ; he-Hebr-AQ ; he-AQ ; +he-Egyp ; he-Egyp-IL ; he-Egyp ; +he-Hebr ; he-Hebr-IL ; he ; +he-IL ; he-Hebr-IL ; he ; +hi ; hi-Deva-IN ; hi ; +hi-AQ ; hi-Deva-AQ ; hi-AQ ; +hi-Deva ; hi-Deva-IN ; hi ; +hi-Egyp ; hi-Egyp-IN ; hi-Egyp ; +hi-IN ; hi-Deva-IN ; hi ; +hi-Latn ; hi-Latn-IN ; hi-Latn ; +hr ; hr-Latn-HR ; hr ; +hr-AQ ; hr-Latn-AQ ; hr-AQ ; +hr-BA ; hr-Latn-BA ; hr-BA ; +hr-Egyp ; hr-Egyp-HR ; hr-Egyp ; +hr-HR ; hr-Latn-HR ; hr ; +hr-Latn ; hr-Latn-HR ; hr ; +hsb ; hsb-Latn-DE ; hsb ; +hsb-AQ ; hsb-Latn-AQ ; hsb-AQ ; +hsb-DE ; hsb-Latn-DE ; hsb ; +hsb-Egyp ; hsb-Egyp-DE ; hsb-Egyp ; +hsb-Latn ; hsb-Latn-DE ; hsb ; +hu ; hu-Latn-HU ; hu ; +hu-AQ ; hu-Latn-AQ ; hu-AQ ; +hu-Egyp ; hu-Egyp-HU ; hu-Egyp ; +hu-HU ; hu-Latn-HU ; hu ; +hu-Latn ; hu-Latn-HU ; hu ; +hy ; hy-Armn-AM ; hy ; +hy-AM ; hy-Armn-AM ; hy ; +hy-AQ ; hy-Armn-AQ ; hy-AQ ; +hy-Armn ; hy-Armn-AM ; hy ; +hy-Egyp ; hy-Egyp-AM ; hy-Egyp ; +id ; id-Latn-ID ; id ; +id-AQ ; id-Latn-AQ ; id-AQ ; +id-Egyp ; id-Egyp-ID ; id-Egyp ; +id-ID ; id-Latn-ID ; id ; +id-Latn ; id-Latn-ID ; id ; +ig ; ig-Latn-NG ; ig ; +ig-AQ ; ig-Latn-AQ ; ig-AQ ; +ig-Egyp ; ig-Egyp-NG ; ig-Egyp ; +ig-Latn ; ig-Latn-NG ; ig ; +ig-NG ; ig-Latn-NG ; ig ; +is ; is-Latn-IS ; is ; +is-AQ ; is-Latn-AQ ; is-AQ ; +is-Egyp ; is-Egyp-IS ; is-Egyp ; +is-IS ; is-Latn-IS ; is ; +is-Latn ; is-Latn-IS ; is ; +it ; it-Latn-IT ; it ; +it-AQ ; it-Latn-AQ ; it-AQ ; +it-CH ; it-Latn-CH ; it-CH ; +it-Egyp ; it-Egyp-IT ; it-Egyp ; +it-IT ; it-Latn-IT ; it ; +it-Latn ; it-Latn-IT ; it ; +it-SM ; it-Latn-SM ; it-SM ; +it-VA ; it-Latn-VA ; it-VA ; +ja ; ja-Jpan-JP ; ja ; +ja-AQ ; ja-Jpan-AQ ; ja-AQ ; +ja-Egyp ; ja-Egyp-JP ; ja-Egyp ; +ja-JP ; ja-Jpan-JP ; ja ; +ja-Jpan ; ja-Jpan-JP ; ja ; +jv ; jv-Latn-ID ; jv ; +jv-AQ ; jv-Latn-AQ ; jv-AQ ; +jv-Egyp ; jv-Egyp-ID ; jv-Egyp ; +jv-ID ; jv-Latn-ID ; jv ; +jv-Latn ; jv-Latn-ID ; jv ; +ka ; ka-Geor-GE ; ka ; +ka-AQ ; ka-Geor-AQ ; ka-AQ ; +ka-Egyp ; ka-Egyp-GE ; ka-Egyp ; +ka-GE ; ka-Geor-GE ; ka ; +ka-Geor ; ka-Geor-GE ; ka ; +kea ; kea-Latn-CV ; kea ; +kea-AQ ; kea-Latn-AQ ; kea-AQ ; +kea-CV ; kea-Latn-CV ; kea ; +kea-Egyp ; kea-Egyp-CV ; kea-Egyp ; +kea-Latn ; kea-Latn-CV ; kea ; +kgp ; kgp-Latn-BR ; kgp ; +kgp-AQ ; kgp-Latn-AQ ; kgp-AQ ; +kgp-BR ; kgp-Latn-BR ; kgp ; +kgp-Egyp ; kgp-Egyp-BR ; kgp-Egyp ; +kgp-Latn ; kgp-Latn-BR ; kgp ; +kk ; kk-Cyrl-KZ ; kk ; +kk-AQ ; kk-Cyrl-AQ ; kk-AQ ; +kk-Cyrl ; kk-Cyrl-KZ ; kk ; +kk-Egyp ; kk-Egyp-KZ ; kk-Egyp ; +kk-KZ ; kk-Cyrl-KZ ; kk ; +km ; km-Khmr-KH ; km ; +km-AQ ; km-Khmr-AQ ; km-AQ ; +km-Egyp ; km-Egyp-KH ; km-Egyp ; +km-KH ; km-Khmr-KH ; km ; +km-Khmr ; km-Khmr-KH ; km ; +kn ; kn-Knda-IN ; kn ; +kn-AQ ; kn-Knda-AQ ; kn-AQ ; +kn-Egyp ; kn-Egyp-IN ; kn-Egyp ; +kn-IN ; kn-Knda-IN ; kn ; +kn-Knda ; kn-Knda-IN ; kn ; +ko ; ko-Kore-KR ; ko ; +ko-AQ ; ko-Kore-AQ ; ko-AQ ; +ko-CN ; ko-Kore-CN ; ko-CN ; +ko-Egyp ; ko-Egyp-KR ; ko-Egyp ; +ko-KP ; ko-Kore-KP ; ko-KP ; +ko-KR ; ko-Kore-KR ; ko ; +ko-Kore ; ko-Kore-KR ; ko ; +kok ; kok-Deva-IN ; kok ; +kok-AQ ; kok-Deva-AQ ; kok-AQ ; +kok-Deva ; kok-Deva-IN ; kok ; +kok-Egyp ; kok-Egyp-IN ; kok-Egyp ; +kok-IN ; kok-Deva-IN ; kok ; +ks ; ks-Arab-IN ; ks ; +ks-AQ ; ks-Arab-AQ ; ks-AQ ; +ks-Arab ; ks-Arab-IN ; ks ; +ks-Deva ; ks-Deva-IN ; ks-Deva ; +ks-Egyp ; ks-Egyp-IN ; ks-Egyp ; +ks-IN ; ks-Arab-IN ; ks ; +ku ; ku-Latn-TR ; ku ; +ku-AQ ; ku-Latn-AQ ; ku-AQ ; +ku-Egyp ; ku-Egyp-TR ; ku-Egyp ; +ku-Latn ; ku-Latn-TR ; ku ; +ku-TR ; ku-Latn-TR ; ku ; +kxv ; kxv-Latn-IN ; kxv ; +kxv-AQ ; kxv-Latn-AQ ; kxv-AQ ; +kxv-Deva ; kxv-Deva-IN ; kxv-Deva ; +kxv-Egyp ; kxv-Egyp-IN ; kxv-Egyp ; +kxv-IN ; kxv-Latn-IN ; kxv ; +kxv-Latn ; kxv-Latn-IN ; kxv ; +kxv-Orya ; kxv-Orya-IN ; kxv-Orya ; +kxv-Telu ; kxv-Telu-IN ; kxv-Telu ; +ky ; ky-Cyrl-KG ; ky ; +ky-AQ ; ky-Cyrl-AQ ; ky-AQ ; +ky-Cyrl ; ky-Cyrl-KG ; ky ; +ky-Egyp ; ky-Egyp-KG ; ky-Egyp ; +ky-KG ; ky-Cyrl-KG ; ky ; +lo ; lo-Laoo-LA ; lo ; +lo-AQ ; lo-Laoo-AQ ; lo-AQ ; +lo-Egyp ; lo-Egyp-LA ; lo-Egyp ; +lo-LA ; lo-Laoo-LA ; lo ; +lo-Laoo ; lo-Laoo-LA ; lo ; +lt ; lt-Latn-LT ; lt ; +lt-AQ ; lt-Latn-AQ ; lt-AQ ; +lt-Egyp ; lt-Egyp-LT ; lt-Egyp ; +lt-LT ; lt-Latn-LT ; lt ; +lt-Latn ; lt-Latn-LT ; lt ; +lv ; lv-Latn-LV ; lv ; +lv-AQ ; lv-Latn-AQ ; lv-AQ ; +lv-Egyp ; lv-Egyp-LV ; lv-Egyp ; +lv-LV ; lv-Latn-LV ; lv ; +lv-Latn ; lv-Latn-LV ; lv ; +mai ; mai-Deva-IN ; mai ; +mai-AQ ; mai-Deva-AQ ; mai-AQ ; +mai-Deva ; mai-Deva-IN ; mai ; +mai-Egyp ; mai-Egyp-IN ; mai-Egyp ; +mai-IN ; mai-Deva-IN ; mai ; +mi ; mi-Latn-NZ ; mi ; +mi-AQ ; mi-Latn-AQ ; mi-AQ ; +mi-Egyp ; mi-Egyp-NZ ; mi-Egyp ; +mi-Latn ; mi-Latn-NZ ; mi ; +mi-NZ ; mi-Latn-NZ ; mi ; +mk ; mk-Cyrl-MK ; mk ; +mk-AQ ; mk-Cyrl-AQ ; mk-AQ ; +mk-Cyrl ; mk-Cyrl-MK ; mk ; +mk-Egyp ; mk-Egyp-MK ; mk-Egyp ; +mk-MK ; mk-Cyrl-MK ; mk ; +ml ; ml-Mlym-IN ; ml ; +ml-AQ ; ml-Mlym-AQ ; ml-AQ ; +ml-Egyp ; ml-Egyp-IN ; ml-Egyp ; +ml-IN ; ml-Mlym-IN ; ml ; +ml-Mlym ; ml-Mlym-IN ; ml ; +mn ; mn-Cyrl-MN ; mn ; +mn-AQ ; mn-Cyrl-AQ ; mn-AQ ; +mn-Cyrl ; mn-Cyrl-MN ; mn ; +mn-Egyp ; mn-Egyp-MN ; mn-Egyp ; +mn-MN ; mn-Cyrl-MN ; mn ; +mni ; mni-Beng-IN ; mni ; +mni-AQ ; mni-Beng-AQ ; mni-AQ ; +mni-Beng ; mni-Beng-IN ; mni ; +mni-Egyp ; mni-Egyp-IN ; mni-Egyp ; +mni-IN ; mni-Beng-IN ; mni ; +mr ; mr-Deva-IN ; mr ; +mr-AQ ; mr-Deva-AQ ; mr-AQ ; +mr-Deva ; mr-Deva-IN ; mr ; +mr-Egyp ; mr-Egyp-IN ; mr-Egyp ; +mr-IN ; mr-Deva-IN ; mr ; +ms ; ms-Latn-MY ; ms ; +ms-AQ ; ms-Latn-AQ ; ms-AQ ; +ms-BN ; ms-Latn-BN ; ms-BN ; +ms-Egyp ; ms-Egyp-MY ; ms-Egyp ; +ms-ID ; ms-Latn-ID ; ms-ID ; +ms-Latn ; ms-Latn-MY ; ms ; +ms-MY ; ms-Latn-MY ; ms ; +ms-SG ; ms-Latn-SG ; ms-SG ; +my ; my-Mymr-MM ; my ; +my-AQ ; my-Mymr-AQ ; my-AQ ; +my-Egyp ; my-Egyp-MM ; my-Egyp ; +my-MM ; my-Mymr-MM ; my ; +my-Mymr ; my-Mymr-MM ; my ; +nb ; nb-Latn-NO ; nb ; +nb-AQ ; nb-Latn-AQ ; nb-AQ ; +nb-Egyp ; nb-Egyp-NO ; nb-Egyp ; +nb-Latn ; nb-Latn-NO ; nb ; +nb-NO ; nb-Latn-NO ; nb ; +nb-SJ ; nb-Latn-SJ ; nb-SJ ; +ne ; ne-Deva-NP ; ne ; +ne-AQ ; ne-Deva-AQ ; ne-AQ ; +ne-Deva ; ne-Deva-NP ; ne ; +ne-Egyp ; ne-Egyp-NP ; ne-Egyp ; +ne-IN ; ne-Deva-IN ; ne-IN ; +ne-NP ; ne-Deva-NP ; ne ; +nl ; nl-Latn-NL ; nl ; +nl-AQ ; nl-Latn-AQ ; nl-AQ ; +nl-AW ; nl-Latn-AW ; nl-AW ; +nl-BE ; nl-Latn-BE ; nl-BE ; +nl-BQ ; nl-Latn-BQ ; nl-BQ ; +nl-CW ; nl-Latn-CW ; nl-CW ; +nl-Egyp ; nl-Egyp-NL ; nl-Egyp ; +nl-Latn ; nl-Latn-NL ; nl ; +nl-NL ; nl-Latn-NL ; nl ; +nl-SR ; nl-Latn-SR ; nl-SR ; +nl-SX ; nl-Latn-SX ; nl-SX ; +nn ; nn-Latn-NO ; nn ; +nn-AQ ; nn-Latn-AQ ; nn-AQ ; +nn-Egyp ; nn-Egyp-NO ; nn-Egyp ; +nn-Latn ; nn-Latn-NO ; nn ; +nn-NO ; nn-Latn-NO ; nn ; +no ; no-Latn-NO ; no ; +no-AQ ; no-Latn-AQ ; no-AQ ; +no-Egyp ; no-Egyp-NO ; no-Egyp ; +no-Latn ; no-Latn-NO ; no ; +no-NO ; no-Latn-NO ; no ; +or ; or-Orya-IN ; or ; +or-AQ ; or-Orya-AQ ; or-AQ ; +or-Egyp ; or-Egyp-IN ; or-Egyp ; +or-IN ; or-Orya-IN ; or ; +or-Orya ; or-Orya-IN ; or ; +pa ; pa-Guru-IN ; pa ; +pa-AQ ; pa-Guru-AQ ; pa-AQ ; +pa-Egyp ; pa-Egyp-IN ; pa-Egyp ; +pa-Guru ; pa-Guru-IN ; pa ; +pa-IN ; pa-Guru-IN ; pa ; +pcm ; pcm-Latn-NG ; pcm ; +pcm-AQ ; pcm-Latn-AQ ; pcm-AQ ; +pcm-Egyp ; pcm-Egyp-NG ; pcm-Egyp ; +pcm-Latn ; pcm-Latn-NG ; pcm ; +pcm-NG ; pcm-Latn-NG ; pcm ; +pl ; pl-Latn-PL ; pl ; +pl-AQ ; pl-Latn-AQ ; pl-AQ ; +pl-Egyp ; pl-Egyp-PL ; pl-Egyp ; +pl-Latn ; pl-Latn-PL ; pl ; +pl-PL ; pl-Latn-PL ; pl ; +ps ; ps-Arab-AF ; ps ; +ps-AF ; ps-Arab-AF ; ps ; +ps-AQ ; ps-Arab-AQ ; ps-AQ ; +ps-Arab ; ps-Arab-AF ; ps ; +ps-Egyp ; ps-Egyp-AF ; ps-Egyp ; +ps-PK ; ps-Arab-PK ; ps-PK ; +pt ; pt-Latn-BR ; pt ; +pt-AO ; pt-Latn-AO ; pt-AO ; +pt-AQ ; pt-Latn-AQ ; pt-AQ ; +pt-BR ; pt-Latn-BR ; pt ; +pt-CH ; pt-Latn-CH ; pt-CH ; +pt-CV ; pt-Latn-CV ; pt-CV ; +pt-Egyp ; pt-Egyp-BR ; pt-Egyp ; +pt-GQ ; pt-Latn-GQ ; pt-GQ ; +pt-GW ; pt-Latn-GW ; pt-GW ; +pt-LU ; pt-Latn-LU ; pt-LU ; +pt-Latn ; pt-Latn-BR ; pt ; +pt-MO ; pt-Latn-MO ; pt-MO ; +pt-MZ ; pt-Latn-MZ ; pt-MZ ; +pt-PT ; pt-Latn-PT ; pt-PT ; +pt-ST ; pt-Latn-ST ; pt-ST ; +pt-TL ; pt-Latn-TL ; pt-TL ; +qaa ; FAIL ; ; +qaa-CH ; FAIL ; ; +qaa-Cyrl ; FAIL ; ; +qaa-Cyrl-CH ; FAIL ; ; +qu ; qu-Latn-PE ; qu ; +qu-AQ ; qu-Latn-AQ ; qu-AQ ; +qu-BO ; qu-Latn-BO ; qu-BO ; +qu-EC ; qu-Latn-EC ; qu-EC ; +qu-Egyp ; qu-Egyp-PE ; qu-Egyp ; +qu-Latn ; qu-Latn-PE ; qu ; +qu-PE ; qu-Latn-PE ; qu ; +raj ; raj-Deva-IN ; raj ; +raj-AQ ; raj-Deva-AQ ; raj-AQ ; +raj-Deva ; raj-Deva-IN ; raj ; +raj-Egyp ; raj-Egyp-IN ; raj-Egyp ; +raj-IN ; raj-Deva-IN ; raj ; +rm ; rm-Latn-CH ; rm ; +rm-AQ ; rm-Latn-AQ ; rm-AQ ; +rm-CH ; rm-Latn-CH ; rm ; +rm-Egyp ; rm-Egyp-CH ; rm-Egyp ; +rm-Latn ; rm-Latn-CH ; rm ; +ro ; ro-Latn-RO ; ro ; +ro-AQ ; ro-Latn-AQ ; ro-AQ ; +ro-Egyp ; ro-Egyp-RO ; ro-Egyp ; +ro-Latn ; ro-Latn-RO ; ro ; +ro-MD ; ro-Latn-MD ; ro-MD ; +ro-RO ; ro-Latn-RO ; ro ; +ru ; ru-Cyrl-RU ; ru ; +ru-AQ ; ru-Cyrl-AQ ; ru-AQ ; +ru-BY ; ru-Cyrl-BY ; ru-BY ; +ru-Cyrl ; ru-Cyrl-RU ; ru ; +ru-Egyp ; ru-Egyp-RU ; ru-Egyp ; +ru-KG ; ru-Cyrl-KG ; ru-KG ; +ru-KZ ; ru-Cyrl-KZ ; ru-KZ ; +ru-MD ; ru-Cyrl-MD ; ru-MD ; +ru-RU ; ru-Cyrl-RU ; ru ; +ru-UA ; ru-Cyrl-UA ; ru-UA ; +sa ; sa-Deva-IN ; sa ; +sa-AQ ; sa-Deva-AQ ; sa-AQ ; +sa-Deva ; sa-Deva-IN ; sa ; +sa-Egyp ; sa-Egyp-IN ; sa-Egyp ; +sa-IN ; sa-Deva-IN ; sa ; +sat ; sat-Olck-IN ; sat ; +sat-AQ ; sat-Olck-AQ ; sat-AQ ; +sat-Egyp ; sat-Egyp-IN ; sat-Egyp ; +sat-IN ; sat-Olck-IN ; sat ; +sat-Olck ; sat-Olck-IN ; sat ; +sc ; sc-Latn-IT ; sc ; +sc-AQ ; sc-Latn-AQ ; sc-AQ ; +sc-Egyp ; sc-Egyp-IT ; sc-Egyp ; +sc-IT ; sc-Latn-IT ; sc ; +sc-Latn ; sc-Latn-IT ; sc ; +sd ; sd-Arab-PK ; sd ; +sd-AQ ; sd-Arab-AQ ; sd-AQ ; +sd-Arab ; sd-Arab-PK ; sd ; +sd-Deva ; sd-Deva-IN ; sd-Deva ; sd-IN +sd-Egyp ; sd-Egyp-PK ; sd-Egyp ; +sd-IN ; sd-Deva-IN ; sd-Deva ; sd-IN +sd-PK ; sd-Arab-PK ; sd ; +si ; si-Sinh-LK ; si ; +si-AQ ; si-Sinh-AQ ; si-AQ ; +si-Egyp ; si-Egyp-LK ; si-Egyp ; +si-LK ; si-Sinh-LK ; si ; +si-Sinh ; si-Sinh-LK ; si ; +sk ; sk-Latn-SK ; sk ; +sk-AQ ; sk-Latn-AQ ; sk-AQ ; +sk-Egyp ; sk-Egyp-SK ; sk-Egyp ; +sk-Latn ; sk-Latn-SK ; sk ; +sk-SK ; sk-Latn-SK ; sk ; +sl ; sl-Latn-SI ; sl ; +sl-AQ ; sl-Latn-AQ ; sl-AQ ; +sl-Egyp ; sl-Egyp-SI ; sl-Egyp ; +sl-Latn ; sl-Latn-SI ; sl ; +sl-SI ; sl-Latn-SI ; sl ; +so ; so-Latn-SO ; so ; +so-AQ ; so-Latn-AQ ; so-AQ ; +so-DJ ; so-Latn-DJ ; so-DJ ; +so-ET ; so-Latn-ET ; so-ET ; +so-Egyp ; so-Egyp-SO ; so-Egyp ; +so-KE ; so-Latn-KE ; so-KE ; +so-Latn ; so-Latn-SO ; so ; +so-SO ; so-Latn-SO ; so ; +sq ; sq-Latn-AL ; sq ; +sq-AL ; sq-Latn-AL ; sq ; +sq-AQ ; sq-Latn-AQ ; sq-AQ ; +sq-Egyp ; sq-Egyp-AL ; sq-Egyp ; +sq-Latn ; sq-Latn-AL ; sq ; +sq-MK ; sq-Latn-MK ; sq-MK ; +sq-XK ; sq-Latn-XK ; sq-XK ; +sr ; sr-Cyrl-RS ; sr ; +sr-AQ ; sr-Cyrl-AQ ; sr-AQ ; +sr-BA ; sr-Cyrl-BA ; sr-BA ; +sr-Cyrl ; sr-Cyrl-RS ; sr ; +sr-Egyp ; sr-Egyp-RS ; sr-Egyp ; +sr-Latn ; sr-Latn-RS ; sr-Latn ; +sr-ME ; sr-Latn-ME ; sr-ME ; +sr-RS ; sr-Cyrl-RS ; sr ; +sr-XK ; sr-Cyrl-XK ; sr-XK ; +su ; su-Latn-ID ; su ; +su-AQ ; su-Latn-AQ ; su-AQ ; +su-Egyp ; su-Egyp-ID ; su-Egyp ; +su-ID ; su-Latn-ID ; su ; +su-Latn ; su-Latn-ID ; su ; +sv ; sv-Latn-SE ; sv ; +sv-AQ ; sv-Latn-AQ ; sv-AQ ; +sv-AX ; sv-Latn-AX ; sv-AX ; +sv-Egyp ; sv-Egyp-SE ; sv-Egyp ; +sv-FI ; sv-Latn-FI ; sv-FI ; +sv-Latn ; sv-Latn-SE ; sv ; +sv-SE ; sv-Latn-SE ; sv ; +sw ; sw-Latn-TZ ; sw ; +sw-AQ ; sw-Latn-AQ ; sw-AQ ; +sw-CD ; sw-Latn-CD ; sw-CD ; +sw-Egyp ; sw-Egyp-TZ ; sw-Egyp ; +sw-KE ; sw-Latn-KE ; sw-KE ; +sw-Latn ; sw-Latn-TZ ; sw ; +sw-TZ ; sw-Latn-TZ ; sw ; +sw-UG ; sw-Latn-UG ; sw-UG ; +ta ; ta-Taml-IN ; ta ; +ta-AQ ; ta-Taml-AQ ; ta-AQ ; +ta-Egyp ; ta-Egyp-IN ; ta-Egyp ; +ta-IN ; ta-Taml-IN ; ta ; +ta-LK ; ta-Taml-LK ; ta-LK ; +ta-MY ; ta-Taml-MY ; ta-MY ; +ta-SG ; ta-Taml-SG ; ta-SG ; +ta-Taml ; ta-Taml-IN ; ta ; +te ; te-Telu-IN ; te ; +te-AQ ; te-Telu-AQ ; te-AQ ; +te-Egyp ; te-Egyp-IN ; te-Egyp ; +te-IN ; te-Telu-IN ; te ; +te-Telu ; te-Telu-IN ; te ; +tg ; tg-Cyrl-TJ ; tg ; +tg-AQ ; tg-Cyrl-AQ ; tg-AQ ; +tg-Cyrl ; tg-Cyrl-TJ ; tg ; +tg-Egyp ; tg-Egyp-TJ ; tg-Egyp ; +tg-TJ ; tg-Cyrl-TJ ; tg ; +th ; th-Thai-TH ; th ; +th-AQ ; th-Thai-AQ ; th-AQ ; +th-Egyp ; th-Egyp-TH ; th-Egyp ; +th-TH ; th-Thai-TH ; th ; +th-Thai ; th-Thai-TH ; th ; +ti ; ti-Ethi-ET ; ti ; +ti-AQ ; ti-Ethi-AQ ; ti-AQ ; +ti-ER ; ti-Ethi-ER ; ti-ER ; +ti-ET ; ti-Ethi-ET ; ti ; +ti-Egyp ; ti-Egyp-ET ; ti-Egyp ; +ti-Ethi ; ti-Ethi-ET ; ti ; +tk ; tk-Latn-TM ; tk ; +tk-AQ ; tk-Latn-AQ ; tk-AQ ; +tk-Egyp ; tk-Egyp-TM ; tk-Egyp ; +tk-Latn ; tk-Latn-TM ; tk ; +tk-TM ; tk-Latn-TM ; tk ; +to ; to-Latn-TO ; to ; +to-AQ ; to-Latn-AQ ; to-AQ ; +to-Egyp ; to-Egyp-TO ; to-Egyp ; +to-Latn ; to-Latn-TO ; to ; +to-TO ; to-Latn-TO ; to ; +tr ; tr-Latn-TR ; tr ; +tr-AQ ; tr-Latn-AQ ; tr-AQ ; +tr-CY ; tr-Latn-CY ; tr-CY ; +tr-Egyp ; tr-Egyp-TR ; tr-Egyp ; +tr-Latn ; tr-Latn-TR ; tr ; +tr-TR ; tr-Latn-TR ; tr ; +tt ; tt-Cyrl-RU ; tt ; +tt-AQ ; tt-Cyrl-AQ ; tt-AQ ; +tt-Cyrl ; tt-Cyrl-RU ; tt ; +tt-Egyp ; tt-Egyp-RU ; tt-Egyp ; +tt-RU ; tt-Cyrl-RU ; tt ; +uk ; uk-Cyrl-UA ; uk ; +uk-AQ ; uk-Cyrl-AQ ; uk-AQ ; +uk-Cyrl ; uk-Cyrl-UA ; uk ; +uk-Egyp ; uk-Egyp-UA ; uk-Egyp ; +uk-UA ; uk-Cyrl-UA ; uk ; +und ; en-Latn-US ; en ; +und-001 ; en-Latn-001 ; en-001 ; +und-150 ; ru-Cyrl-RU ; ru ; +und-419 ; es-Latn-419 ; es-419 ; +und-AD ; ca-Latn-AD ; ca-AD ; +und-AE ; ar-Arab-AE ; ar-AE ; +und-AF ; fa-Arab-AF ; fa-AF ; +und-AG ; en-Latn-AG ; en-AG ; +und-AI ; en-Latn-AI ; en-AI ; +und-AL ; sq-Latn-AL ; sq ; +und-AM ; hy-Armn-AM ; hy ; +und-AO ; pt-Latn-AO ; pt-AO ; +und-AQ ; en-Latn-AQ ; en-AQ ; +und-AR ; es-Latn-AR ; es-AR ; +und-AS ; sm-Latn-AS ; sm-AS ; +und-AT ; de-Latn-AT ; de-AT ; +und-AU ; en-Latn-AU ; en-AU ; +und-AW ; nl-Latn-AW ; nl-AW ; +und-AX ; sv-Latn-AX ; sv-AX ; +und-AZ ; az-Latn-AZ ; az ; +und-Adlm ; ff-Adlm-GN ; ff-Adlm ; +und-Adlm-AQ ; ff-Adlm-AQ ; ; +und-Adlm-BF ; ff-Adlm-BF ; ; +und-Adlm-CM ; ff-Adlm-CM ; ; +und-Adlm-GH ; ff-Adlm-GH ; ; +und-Adlm-GM ; ff-Adlm-GM ; ; +und-Adlm-GN ; ff-Adlm-GN ; ff-Adlm ; +und-Adlm-GW ; ff-Adlm-GW ; ; +und-Adlm-LR ; ff-Adlm-LR ; ; +und-Adlm-MR ; ff-Adlm-MR ; ; +und-Adlm-NE ; ff-Adlm-NE ; ; +und-Adlm-NG ; ff-Adlm-NG ; ; +und-Adlm-SL ; ff-Adlm-SL ; ; +und-Adlm-SN ; ff-Adlm-SN ; ; +und-Arab ; ar-Arab-EG ; ar ; +und-Arab-001 ; ar-Arab-001 ; ar-001 ; +und-Arab-AE ; ar-Arab-AE ; ar-AE ; +und-Arab-AF ; fa-Arab-AF ; fa-AF ; +und-Arab-AQ ; ar-Arab-AQ ; ar-AQ ; +und-Arab-BH ; ar-Arab-BH ; ar-BH ; +und-Arab-DJ ; ar-Arab-DJ ; ar-DJ ; +und-Arab-DZ ; ar-Arab-DZ ; ar-DZ ; +und-Arab-EG ; ar-Arab-EG ; ar ; +und-Arab-EH ; ar-Arab-EH ; ar-EH ; +und-Arab-ER ; ar-Arab-ER ; ar-ER ; +und-Arab-IL ; ar-Arab-IL ; ar-IL ; +und-Arab-IN ; ur-Arab-IN ; ur-IN ; +und-Arab-IQ ; ar-Arab-IQ ; ar-IQ ; +und-Arab-IR ; fa-Arab-IR ; fa ; +und-Arab-JO ; ar-Arab-JO ; ar-JO ; +und-Arab-KM ; ar-Arab-KM ; ar-KM ; +und-Arab-KW ; ar-Arab-KW ; ar-KW ; +und-Arab-LB ; ar-Arab-LB ; ar-LB ; +und-Arab-LY ; ar-Arab-LY ; ar-LY ; +und-Arab-MA ; ar-Arab-MA ; ar-MA ; +und-Arab-MR ; ar-Arab-MR ; ar-MR ; +und-Arab-OM ; ar-Arab-OM ; ar-OM ; +und-Arab-PK ; ur-Arab-PK ; ur ; +und-Arab-PS ; ar-Arab-PS ; ar-PS ; +und-Arab-QA ; ar-Arab-QA ; ar-QA ; +und-Arab-SA ; ar-Arab-SA ; ar-SA ; +und-Arab-SD ; ar-Arab-SD ; ar-SD ; +und-Arab-SO ; ar-Arab-SO ; ar-SO ; +und-Arab-SS ; ar-Arab-SS ; ar-SS ; +und-Arab-SY ; ar-Arab-SY ; ar-SY ; +und-Arab-TD ; ar-Arab-TD ; ar-TD ; +und-Arab-TN ; ar-Arab-TN ; ar-TN ; +und-Arab-YE ; ar-Arab-YE ; ar-YE ; +und-Armn ; hy-Armn-AM ; hy ; +und-Armn-AM ; hy-Armn-AM ; hy ; +und-Armn-AQ ; hy-Armn-AQ ; hy-AQ ; +und-BA ; bs-Latn-BA ; bs ; +und-BB ; en-Latn-BB ; en-BB ; +und-BD ; bn-Beng-BD ; bn ; +und-BE ; nl-Latn-BE ; nl-BE ; +und-BF ; fr-Latn-BF ; fr-BF ; +und-BG ; bg-Cyrl-BG ; bg ; +und-BH ; ar-Arab-BH ; ar-BH ; +und-BI ; rn-Latn-BI ; rn ; +und-BJ ; fr-Latn-BJ ; fr-BJ ; +und-BL ; fr-Latn-BL ; fr-BL ; +und-BM ; en-Latn-BM ; en-BM ; +und-BN ; ms-Latn-BN ; ms-BN ; +und-BO ; es-Latn-BO ; es-BO ; +und-BQ ; pap-Latn-BQ ; pap-BQ ; +und-BR ; pt-Latn-BR ; pt ; +und-BS ; en-Latn-BS ; en-BS ; +und-BW ; en-Latn-BW ; en-BW ; +und-BY ; be-Cyrl-BY ; be ; +und-BZ ; en-Latn-BZ ; en-BZ ; +und-Beng ; bn-Beng-BD ; bn ; +und-Beng-AQ ; bn-Beng-AQ ; bn-AQ ; +und-Beng-BD ; bn-Beng-BD ; bn ; +und-Beng-IN ; bn-Beng-IN ; bn-IN ; +und-CA ; en-Latn-CA ; en-CA ; +und-CC ; ms-Arab-CC ; ms-CC ; +und-CD ; sw-Latn-CD ; sw-CD ; +und-CF ; fr-Latn-CF ; fr-CF ; +und-CG ; fr-Latn-CG ; fr-CG ; +und-CH ; de-Latn-CH ; de-CH ; +und-CI ; fr-Latn-CI ; fr-CI ; +und-CK ; en-Latn-CK ; en-CK ; +und-CL ; es-Latn-CL ; es-CL ; +und-CM ; fr-Latn-CM ; fr-CM ; +und-CN ; zh-Hans-CN ; zh ; +und-CO ; es-Latn-CO ; es-CO ; +und-CR ; es-Latn-CR ; es-CR ; +und-CU ; es-Latn-CU ; es-CU ; +und-CV ; pt-Latn-CV ; pt-CV ; +und-CW ; pap-Latn-CW ; pap ; +und-CX ; en-Latn-CX ; en-CX ; +und-CY ; el-Grek-CY ; el-CY ; +und-CZ ; cs-Latn-CZ ; cs ; +und-Cans ; iu-Cans-CA ; iu ; +und-Cans-AQ ; iu-Cans-AQ ; iu-AQ ; +und-Cans-CA ; iu-Cans-CA ; iu ; +und-Cher ; chr-Cher-US ; chr ; +und-Cher-AQ ; chr-Cher-AQ ; chr-AQ ; +und-Cher-US ; chr-Cher-US ; chr ; +und-Cyrl ; ru-Cyrl-RU ; ru ; +und-Cyrl-AQ ; ru-Cyrl-AQ ; ru-AQ ; +und-Cyrl-BA ; sr-Cyrl-BA ; sr-BA ; +und-Cyrl-BG ; bg-Cyrl-BG ; bg ; +und-Cyrl-BY ; be-Cyrl-BY ; be ; +und-Cyrl-KG ; ky-Cyrl-KG ; ky ; +und-Cyrl-KZ ; ru-Cyrl-KZ ; ru-KZ ; +und-Cyrl-MD ; uk-Cyrl-MD ; uk-MD ; +und-Cyrl-ME ; ru-Cyrl-ME ; ru-ME ; +und-Cyrl-MK ; mk-Cyrl-MK ; mk ; +und-Cyrl-MN ; mn-Cyrl-MN ; mn ; +und-Cyrl-RS ; sr-Cyrl-RS ; sr ; +und-Cyrl-RU ; ru-Cyrl-RU ; ru ; +und-Cyrl-TJ ; tg-Cyrl-TJ ; tg ; +und-Cyrl-UA ; uk-Cyrl-UA ; uk ; +und-Cyrl-UZ ; ru-Cyrl-UZ ; ru-UZ ; +und-Cyrl-XK ; sr-Cyrl-XK ; sr-XK ; +und-DE ; de-Latn-DE ; de ; +und-DG ; en-Latn-DG ; en-DG ; +und-DJ ; aa-Latn-DJ ; aa-DJ ; +und-DK ; da-Latn-DK ; da ; +und-DM ; en-Latn-DM ; en-DM ; +und-DO ; es-Latn-DO ; es-DO ; +und-DZ ; ar-Arab-DZ ; ar-DZ ; +und-Deva ; hi-Deva-IN ; hi ; +und-Deva-AQ ; hi-Deva-AQ ; hi-AQ ; +und-Deva-IN ; hi-Deva-IN ; hi ; +und-Deva-NP ; ne-Deva-NP ; ne ; +und-Deva-PK ; btv-Deva-PK ; btv ; +und-EA ; es-Latn-EA ; es-EA ; +und-EC ; es-Latn-EC ; es-EC ; +und-EE ; et-Latn-EE ; et ; +und-EG ; ar-Arab-EG ; ar ; +und-EH ; ar-Arab-EH ; ar-EH ; +und-ER ; ti-Ethi-ER ; ti-ER ; +und-ES ; es-Latn-ES ; es ; +und-ET ; am-Ethi-ET ; am ; +und-Egyp ; egy-Egyp-EG ; egy ; +und-Ethi ; am-Ethi-ET ; am ; +und-Ethi-AQ ; am-Ethi-AQ ; am-AQ ; +und-Ethi-ER ; ti-Ethi-ER ; ti-ER ; +und-Ethi-ET ; am-Ethi-ET ; am ; +und-FI ; fi-Latn-FI ; fi ; +und-FJ ; en-Latn-FJ ; en-FJ ; +und-FK ; en-Latn-FK ; en-FK ; +und-FM ; en-Latn-FM ; en-FM ; +und-FO ; fo-Latn-FO ; fo ; +und-FR ; fr-Latn-FR ; fr ; +und-GA ; fr-Latn-GA ; fr-GA ; +und-GB ; en-Latn-GB ; en-GB ; +und-GD ; en-Latn-GD ; en-GD ; +und-GE ; ka-Geor-GE ; ka ; +und-GF ; fr-Latn-GF ; fr-GF ; +und-GG ; en-Latn-GG ; en-GG ; +und-GH ; ak-Latn-GH ; ak ; +und-GI ; en-Latn-GI ; en-GI ; +und-GL ; kl-Latn-GL ; kl ; +und-GM ; en-Latn-GM ; en-GM ; +und-GN ; fr-Latn-GN ; fr-GN ; +und-GP ; fr-Latn-GP ; fr-GP ; +und-GQ ; es-Latn-GQ ; es-GQ ; +und-GR ; el-Grek-GR ; el ; +und-GT ; es-Latn-GT ; es-GT ; +und-GU ; en-Latn-GU ; en-GU ; +und-GW ; pt-Latn-GW ; pt-GW ; +und-GY ; en-Latn-GY ; en-GY ; +und-Geor ; ka-Geor-GE ; ka ; +und-Geor-AQ ; ka-Geor-AQ ; ka-AQ ; +und-Geor-GE ; ka-Geor-GE ; ka ; +und-Grek ; el-Grek-GR ; el ; +und-Grek-AQ ; el-Grek-AQ ; el-AQ ; +und-Grek-CY ; el-Grek-CY ; el-CY ; +und-Grek-GR ; el-Grek-GR ; el ; +und-Gujr ; gu-Gujr-IN ; gu ; +und-Gujr-AQ ; gu-Gujr-AQ ; gu-AQ ; +und-Gujr-IN ; gu-Gujr-IN ; gu ; +und-Guru ; pa-Guru-IN ; pa ; +und-Guru-AQ ; pa-Guru-AQ ; pa-AQ ; +und-Guru-IN ; pa-Guru-IN ; pa ; +und-HK ; zh-Hant-HK ; zh-HK ; +und-HN ; es-Latn-HN ; es-HN ; +und-HR ; hr-Latn-HR ; hr ; +und-HT ; ht-Latn-HT ; ht ; +und-HU ; hu-Latn-HU ; hu ; +und-Hans ; zh-Hans-CN ; zh ; +und-Hans-AQ ; zh-Hans-AQ ; zh-AQ ; +und-Hans-CN ; zh-Hans-CN ; zh ; +und-Hans-HK ; zh-Hans-HK ; ; +und-Hans-MO ; zh-Hans-MO ; ; +und-Hans-SG ; zh-Hans-SG ; zh-SG ; +und-Hans-TW ; zh-Hans-TW ; ; +und-Hant ; zh-Hant-TW ; zh-Hant ; zh-TW +und-Hant-AQ ; zh-Hant-AQ ; ; +und-Hant-CN ; zh-Hant-CN ; ; +und-Hant-HK ; zh-Hant-HK ; zh-HK ; +und-Hant-MO ; zh-Hant-MO ; zh-MO ; +und-Hant-SG ; zh-Hant-SG ; ; +und-Hant-TW ; zh-Hant-TW ; zh-Hant ; zh-TW +und-Hebr ; he-Hebr-IL ; he ; +und-Hebr-AQ ; he-Hebr-AQ ; he-AQ ; +und-Hebr-IL ; he-Hebr-IL ; he ; +und-IC ; es-Latn-IC ; es-IC ; +und-ID ; id-Latn-ID ; id ; +und-IE ; en-Latn-IE ; en-IE ; +und-IL ; he-Hebr-IL ; he ; +und-IM ; en-Latn-IM ; en-IM ; +und-IN ; hi-Deva-IN ; hi ; +und-IO ; en-Latn-IO ; en-IO ; +und-IQ ; ar-Arab-IQ ; ar-IQ ; +und-IR ; fa-Arab-IR ; fa ; +und-IS ; is-Latn-IS ; is ; +und-IT ; it-Latn-IT ; it ; +und-JE ; en-Latn-JE ; en-JE ; +und-JM ; en-Latn-JM ; en-JM ; +und-JO ; ar-Arab-JO ; ar-JO ; +und-JP ; ja-Jpan-JP ; ja ; +und-Jpan ; ja-Jpan-JP ; ja ; +und-Jpan-AQ ; ja-Jpan-AQ ; ja-AQ ; +und-Jpan-JP ; ja-Jpan-JP ; ja ; +und-KE ; sw-Latn-KE ; sw-KE ; +und-KG ; ky-Cyrl-KG ; ky ; +und-KH ; km-Khmr-KH ; km ; +und-KI ; en-Latn-KI ; en-KI ; +und-KM ; ar-Arab-KM ; ar-KM ; +und-KN ; en-Latn-KN ; en-KN ; +und-KP ; ko-Kore-KP ; ko-KP ; +und-KR ; ko-Kore-KR ; ko ; +und-KW ; ar-Arab-KW ; ar-KW ; +und-KY ; en-Latn-KY ; en-KY ; +und-KZ ; ru-Cyrl-KZ ; ru-KZ ; +und-Khmr ; km-Khmr-KH ; km ; +und-Khmr-AQ ; km-Khmr-AQ ; km-AQ ; +und-Khmr-KH ; km-Khmr-KH ; km ; +und-Knda ; kn-Knda-IN ; kn ; +und-Knda-AQ ; kn-Knda-AQ ; kn-AQ ; +und-Knda-IN ; kn-Knda-IN ; kn ; +und-Kore ; ko-Kore-KR ; ko ; +und-Kore-AQ ; ko-Kore-AQ ; ko-AQ ; +und-Kore-CN ; ko-Kore-CN ; ko-CN ; +und-Kore-KP ; ko-Kore-KP ; ko-KP ; +und-Kore-KR ; ko-Kore-KR ; ko ; +und-LA ; lo-Laoo-LA ; lo ; +und-LB ; ar-Arab-LB ; ar-LB ; +und-LC ; en-Latn-LC ; en-LC ; +und-LI ; de-Latn-LI ; de-LI ; +und-LK ; si-Sinh-LK ; si ; +und-LR ; en-Latn-LR ; en-LR ; +und-LS ; st-Latn-LS ; st-LS ; +und-LT ; lt-Latn-LT ; lt ; +und-LU ; fr-Latn-LU ; fr-LU ; +und-LV ; lv-Latn-LV ; lv ; +und-LY ; ar-Arab-LY ; ar-LY ; +und-Laoo ; lo-Laoo-LA ; lo ; +und-Laoo-AQ ; lo-Laoo-AQ ; lo-AQ ; +und-Laoo-LA ; lo-Laoo-LA ; lo ; +und-Latn ; en-Latn-US ; en ; +und-Latn-001 ; en-Latn-001 ; en-001 ; +und-Latn-150 ; ru-Latn-150 ; ; +und-Latn-419 ; es-Latn-419 ; es-419 ; +und-Latn-AD ; ca-Latn-AD ; ca-AD ; +und-Latn-AE ; ar-Latn-AE ; ; +und-Latn-AG ; en-Latn-AG ; en-AG ; +und-Latn-AI ; en-Latn-AI ; en-AI ; +und-Latn-AL ; sq-Latn-AL ; sq ; +und-Latn-AO ; pt-Latn-AO ; pt-AO ; +und-Latn-AQ ; en-Latn-AQ ; en-AQ ; +und-Latn-AR ; es-Latn-AR ; es-AR ; +und-Latn-AS ; sm-Latn-AS ; sm-AS ; +und-Latn-AT ; de-Latn-AT ; de-AT ; +und-Latn-AU ; en-Latn-AU ; en-AU ; +und-Latn-AW ; nl-Latn-AW ; nl-AW ; +und-Latn-AX ; sv-Latn-AX ; sv-AX ; +und-Latn-AZ ; az-Latn-AZ ; az ; +und-Latn-BA ; bs-Latn-BA ; bs ; +und-Latn-BB ; en-Latn-BB ; en-BB ; +und-Latn-BE ; nl-Latn-BE ; nl-BE ; +und-Latn-BF ; fr-Latn-BF ; fr-BF ; +und-Latn-BI ; rn-Latn-BI ; rn ; +und-Latn-BJ ; fr-Latn-BJ ; fr-BJ ; +und-Latn-BL ; fr-Latn-BL ; fr-BL ; +und-Latn-BM ; en-Latn-BM ; en-BM ; +und-Latn-BN ; ms-Latn-BN ; ms-BN ; +und-Latn-BO ; es-Latn-BO ; es-BO ; +und-Latn-BQ ; pap-Latn-BQ ; pap-BQ ; +und-Latn-BR ; pt-Latn-BR ; pt ; +und-Latn-BS ; en-Latn-BS ; en-BS ; +und-Latn-BW ; en-Latn-BW ; en-BW ; +und-Latn-BZ ; en-Latn-BZ ; en-BZ ; +und-Latn-CA ; en-Latn-CA ; en-CA ; +und-Latn-CC ; ms-Latn-CC ; ; +und-Latn-CD ; sw-Latn-CD ; sw-CD ; +und-Latn-CF ; fr-Latn-CF ; fr-CF ; +und-Latn-CG ; fr-Latn-CG ; fr-CG ; +und-Latn-CH ; de-Latn-CH ; de-CH ; +und-Latn-CI ; fr-Latn-CI ; fr-CI ; +und-Latn-CK ; en-Latn-CK ; en-CK ; +und-Latn-CL ; es-Latn-CL ; es-CL ; +und-Latn-CM ; fr-Latn-CM ; fr-CM ; +und-Latn-CO ; es-Latn-CO ; es-CO ; +und-Latn-CR ; es-Latn-CR ; es-CR ; +und-Latn-CU ; es-Latn-CU ; es-CU ; +und-Latn-CV ; pt-Latn-CV ; pt-CV ; +und-Latn-CW ; pap-Latn-CW ; pap ; +und-Latn-CX ; en-Latn-CX ; en-CX ; +und-Latn-CY ; tr-Latn-CY ; tr-CY ; +und-Latn-CZ ; cs-Latn-CZ ; cs ; +und-Latn-DE ; de-Latn-DE ; de ; +und-Latn-DG ; en-Latn-DG ; en-DG ; +und-Latn-DJ ; aa-Latn-DJ ; aa-DJ ; +und-Latn-DK ; da-Latn-DK ; da ; +und-Latn-DM ; en-Latn-DM ; en-DM ; +und-Latn-DO ; es-Latn-DO ; es-DO ; +und-Latn-DZ ; fr-Latn-DZ ; fr-DZ ; +und-Latn-EA ; es-Latn-EA ; es-EA ; +und-Latn-EC ; es-Latn-EC ; es-EC ; +und-Latn-EE ; et-Latn-EE ; et ; +und-Latn-ER ; ti-Latn-ER ; ; +und-Latn-ES ; es-Latn-ES ; es ; +und-Latn-ET ; en-Latn-ET ; en-ET ; +und-Latn-FI ; fi-Latn-FI ; fi ; +und-Latn-FJ ; en-Latn-FJ ; en-FJ ; +und-Latn-FK ; en-Latn-FK ; en-FK ; +und-Latn-FM ; en-Latn-FM ; en-FM ; +und-Latn-FO ; fo-Latn-FO ; fo ; +und-Latn-FR ; fr-Latn-FR ; fr ; +und-Latn-GA ; fr-Latn-GA ; fr-GA ; +und-Latn-GB ; en-Latn-GB ; en-GB ; +und-Latn-GD ; en-Latn-GD ; en-GD ; +und-Latn-GF ; fr-Latn-GF ; fr-GF ; +und-Latn-GG ; en-Latn-GG ; en-GG ; +und-Latn-GH ; ak-Latn-GH ; ak ; +und-Latn-GI ; en-Latn-GI ; en-GI ; +und-Latn-GL ; kl-Latn-GL ; kl ; +und-Latn-GM ; en-Latn-GM ; en-GM ; +und-Latn-GN ; fr-Latn-GN ; fr-GN ; +und-Latn-GP ; fr-Latn-GP ; fr-GP ; +und-Latn-GQ ; es-Latn-GQ ; es-GQ ; +und-Latn-GT ; es-Latn-GT ; es-GT ; +und-Latn-GU ; en-Latn-GU ; en-GU ; +und-Latn-GW ; pt-Latn-GW ; pt-GW ; +und-Latn-GY ; en-Latn-GY ; en-GY ; +und-Latn-HK ; zh-Latn-HK ; ; +und-Latn-HN ; es-Latn-HN ; es-HN ; +und-Latn-HR ; hr-Latn-HR ; hr ; +und-Latn-HT ; ht-Latn-HT ; ht ; +und-Latn-HU ; hu-Latn-HU ; hu ; +und-Latn-IC ; es-Latn-IC ; es-IC ; +und-Latn-ID ; id-Latn-ID ; id ; +und-Latn-IE ; en-Latn-IE ; en-IE ; +und-Latn-IL ; he-Latn-IL ; he-Latn ; +und-Latn-IM ; en-Latn-IM ; en-IM ; +und-Latn-IN ; hi-Latn-IN ; hi-Latn ; +und-Latn-IO ; en-Latn-IO ; en-IO ; +und-Latn-IS ; is-Latn-IS ; is ; +und-Latn-IT ; it-Latn-IT ; it ; +und-Latn-JE ; en-Latn-JE ; en-JE ; +und-Latn-JM ; en-Latn-JM ; en-JM ; +und-Latn-KE ; sw-Latn-KE ; sw-KE ; +und-Latn-KI ; en-Latn-KI ; en-KI ; +und-Latn-KM ; fr-Latn-KM ; fr-KM ; +und-Latn-KN ; en-Latn-KN ; en-KN ; +und-Latn-KY ; en-Latn-KY ; en-KY ; +und-Latn-LC ; en-Latn-LC ; en-LC ; +und-Latn-LI ; de-Latn-LI ; de-LI ; +und-Latn-LR ; en-Latn-LR ; en-LR ; +und-Latn-LS ; st-Latn-LS ; st-LS ; +und-Latn-LT ; lt-Latn-LT ; lt ; +und-Latn-LU ; fr-Latn-LU ; fr-LU ; +und-Latn-LV ; lv-Latn-LV ; lv ; +und-Latn-MA ; fr-Latn-MA ; fr-MA ; +und-Latn-MC ; fr-Latn-MC ; fr-MC ; +und-Latn-MD ; ro-Latn-MD ; ro-MD ; +und-Latn-ME ; sr-Latn-ME ; sr-ME ; +und-Latn-MF ; fr-Latn-MF ; fr-MF ; +und-Latn-MG ; mg-Latn-MG ; mg ; +und-Latn-MH ; en-Latn-MH ; en-MH ; +und-Latn-MK ; sq-Latn-MK ; sq-MK ; +und-Latn-ML ; bm-Latn-ML ; bm ; +und-Latn-MO ; pt-Latn-MO ; pt-MO ; +und-Latn-MP ; en-Latn-MP ; en-MP ; +und-Latn-MQ ; fr-Latn-MQ ; fr-MQ ; +und-Latn-MR ; fr-Latn-MR ; fr-MR ; +und-Latn-MS ; en-Latn-MS ; en-MS ; +und-Latn-MT ; mt-Latn-MT ; mt ; +und-Latn-MU ; mfe-Latn-MU ; mfe ; +und-Latn-MV ; dv-Latn-MV ; dv-Latn ; +und-Latn-MW ; en-Latn-MW ; en-MW ; +und-Latn-MX ; es-Latn-MX ; es-MX ; +und-Latn-MY ; ms-Latn-MY ; ms ; +und-Latn-MZ ; pt-Latn-MZ ; pt-MZ ; +und-Latn-NA ; af-Latn-NA ; af-NA ; +und-Latn-NC ; fr-Latn-NC ; fr-NC ; +und-Latn-NE ; ha-Latn-NE ; ha-NE ; +und-Latn-NF ; en-Latn-NF ; en-NF ; +und-Latn-NG ; en-Latn-NG ; en-NG ; +und-Latn-NI ; es-Latn-NI ; es-NI ; +und-Latn-NL ; nl-Latn-NL ; nl ; +und-Latn-NO ; nb-Latn-NO ; nb ; +und-Latn-NR ; en-Latn-NR ; en-NR ; +und-Latn-NU ; en-Latn-NU ; en-NU ; +und-Latn-NZ ; en-Latn-NZ ; en-NZ ; +und-Latn-PA ; es-Latn-PA ; es-PA ; +und-Latn-PE ; es-Latn-PE ; es-PE ; +und-Latn-PF ; fr-Latn-PF ; fr-PF ; +und-Latn-PG ; tpi-Latn-PG ; tpi ; +und-Latn-PH ; fil-Latn-PH ; fil ; +und-Latn-PK ; ur-Latn-PK ; ur-Latn ; +und-Latn-PL ; pl-Latn-PL ; pl ; +und-Latn-PM ; fr-Latn-PM ; fr-PM ; +und-Latn-PN ; en-Latn-PN ; en-PN ; +und-Latn-PR ; es-Latn-PR ; es-PR ; +und-Latn-PT ; pt-Latn-PT ; pt-PT ; +und-Latn-PW ; pau-Latn-PW ; pau ; +und-Latn-PY ; gn-Latn-PY ; gn ; +und-Latn-RE ; fr-Latn-RE ; fr-RE ; +und-Latn-RO ; ro-Latn-RO ; ro ; +und-Latn-RS ; sr-Latn-RS ; sr-Latn ; +und-Latn-RW ; rw-Latn-RW ; rw ; +und-Latn-SB ; en-Latn-SB ; en-SB ; +und-Latn-SC ; fr-Latn-SC ; fr-SC ; +und-Latn-SD ; ar-Latn-SD ; ; +und-Latn-SE ; sv-Latn-SE ; sv ; +und-Latn-SG ; en-Latn-SG ; en-SG ; +und-Latn-SH ; en-Latn-SH ; en-SH ; +und-Latn-SI ; sl-Latn-SI ; sl ; +und-Latn-SJ ; nb-Latn-SJ ; nb-SJ ; +und-Latn-SK ; sk-Latn-SK ; sk ; +und-Latn-SL ; kri-Latn-SL ; kri ; +und-Latn-SM ; it-Latn-SM ; it-SM ; +und-Latn-SN ; fr-Latn-SN ; fr-SN ; +und-Latn-SO ; so-Latn-SO ; so ; +und-Latn-SR ; nl-Latn-SR ; nl-SR ; +und-Latn-SS ; ar-Latn-SS ; ; +und-Latn-ST ; pt-Latn-ST ; pt-ST ; +und-Latn-SV ; es-Latn-SV ; es-SV ; +und-Latn-SX ; en-Latn-SX ; en-SX ; +und-Latn-SY ; fr-Latn-SY ; fr-SY ; +und-Latn-SZ ; en-Latn-SZ ; en-SZ ; +und-Latn-TC ; en-Latn-TC ; en-TC ; +und-Latn-TD ; fr-Latn-TD ; fr-TD ; +und-Latn-TG ; fr-Latn-TG ; fr-TG ; +und-Latn-TK ; tkl-Latn-TK ; tkl ; +und-Latn-TL ; pt-Latn-TL ; pt-TL ; +und-Latn-TM ; tk-Latn-TM ; tk ; +und-Latn-TN ; fr-Latn-TN ; fr-TN ; +und-Latn-TO ; to-Latn-TO ; to ; +und-Latn-TR ; tr-Latn-TR ; tr ; +und-Latn-TT ; en-Latn-TT ; en-TT ; +und-Latn-TV ; tvl-Latn-TV ; tvl ; +und-Latn-TZ ; sw-Latn-TZ ; sw ; +und-Latn-UG ; sw-Latn-UG ; sw-UG ; +und-Latn-UM ; en-Latn-UM ; en-UM ; +und-Latn-US ; en-Latn-US ; en ; +und-Latn-UY ; es-Latn-UY ; es-UY ; +und-Latn-UZ ; uz-Latn-UZ ; uz ; +und-Latn-VA ; it-Latn-VA ; it-VA ; +und-Latn-VC ; en-Latn-VC ; en-VC ; +und-Latn-VE ; es-Latn-VE ; es-VE ; +und-Latn-VG ; en-Latn-VG ; en-VG ; +und-Latn-VI ; en-Latn-VI ; en-VI ; +und-Latn-VN ; vi-Latn-VN ; vi ; +und-Latn-VU ; bi-Latn-VU ; bi ; +und-Latn-WF ; fr-Latn-WF ; fr-WF ; +und-Latn-WS ; sm-Latn-WS ; sm ; +und-Latn-XK ; sq-Latn-XK ; sq-XK ; +und-Latn-YT ; fr-Latn-YT ; fr-YT ; +und-Latn-ZA ; en-Latn-ZA ; en-ZA ; +und-Latn-ZM ; bem-Latn-ZM ; bem ; +und-Latn-ZW ; sn-Latn-ZW ; sn ; +und-MA ; ar-Arab-MA ; ar-MA ; +und-MC ; fr-Latn-MC ; fr-MC ; +und-MD ; ro-Latn-MD ; ro-MD ; +und-ME ; sr-Latn-ME ; sr-ME ; +und-MF ; fr-Latn-MF ; fr-MF ; +und-MG ; mg-Latn-MG ; mg ; +und-MH ; en-Latn-MH ; en-MH ; +und-MK ; mk-Cyrl-MK ; mk ; +und-ML ; bm-Latn-ML ; bm ; +und-MM ; my-Mymr-MM ; my ; +und-MN ; mn-Cyrl-MN ; mn ; +und-MO ; zh-Hant-MO ; zh-MO ; +und-MP ; en-Latn-MP ; en-MP ; +und-MQ ; fr-Latn-MQ ; fr-MQ ; +und-MR ; ar-Arab-MR ; ar-MR ; +und-MS ; en-Latn-MS ; en-MS ; +und-MT ; mt-Latn-MT ; mt ; +und-MU ; mfe-Latn-MU ; mfe ; +und-MV ; dv-Thaa-MV ; dv ; +und-MW ; en-Latn-MW ; en-MW ; +und-MX ; es-Latn-MX ; es-MX ; +und-MY ; ms-Latn-MY ; ms ; +und-MZ ; pt-Latn-MZ ; pt-MZ ; +und-Mlym ; ml-Mlym-IN ; ml ; +und-Mlym-AQ ; ml-Mlym-AQ ; ml-AQ ; +und-Mlym-IN ; ml-Mlym-IN ; ml ; +und-Mymr ; my-Mymr-MM ; my ; +und-Mymr-AQ ; my-Mymr-AQ ; my-AQ ; +und-Mymr-MM ; my-Mymr-MM ; my ; +und-NA ; af-Latn-NA ; af-NA ; +und-NC ; fr-Latn-NC ; fr-NC ; +und-NE ; ha-Latn-NE ; ha-NE ; +und-NF ; en-Latn-NF ; en-NF ; +und-NG ; en-Latn-NG ; en-NG ; +und-NI ; es-Latn-NI ; es-NI ; +und-NL ; nl-Latn-NL ; nl ; +und-NO ; nb-Latn-NO ; nb ; +und-NP ; ne-Deva-NP ; ne ; +und-NR ; en-Latn-NR ; en-NR ; +und-NU ; en-Latn-NU ; en-NU ; +und-NZ ; en-Latn-NZ ; en-NZ ; +und-OM ; ar-Arab-OM ; ar-OM ; +und-Olck ; sat-Olck-IN ; sat ; +und-Olck-AQ ; sat-Olck-AQ ; sat-AQ ; +und-Olck-IN ; sat-Olck-IN ; sat ; +und-Orya ; or-Orya-IN ; or ; +und-Orya-AQ ; or-Orya-AQ ; or-AQ ; +und-Orya-IN ; or-Orya-IN ; or ; +und-PA ; es-Latn-PA ; es-PA ; +und-PE ; es-Latn-PE ; es-PE ; +und-PF ; fr-Latn-PF ; fr-PF ; +und-PG ; tpi-Latn-PG ; tpi ; +und-PH ; fil-Latn-PH ; fil ; +und-PK ; ur-Arab-PK ; ur ; +und-PL ; pl-Latn-PL ; pl ; +und-PM ; fr-Latn-PM ; fr-PM ; +und-PN ; en-Latn-PN ; en-PN ; +und-PR ; es-Latn-PR ; es-PR ; +und-PS ; ar-Arab-PS ; ar-PS ; +und-PT ; pt-Latn-PT ; pt-PT ; +und-PW ; pau-Latn-PW ; pau ; +und-PY ; gn-Latn-PY ; gn ; +und-QA ; ar-Arab-QA ; ar-QA ; +und-RE ; fr-Latn-RE ; fr-RE ; +und-RO ; ro-Latn-RO ; ro ; +und-RS ; sr-Cyrl-RS ; sr ; +und-RU ; ru-Cyrl-RU ; ru ; +und-RW ; rw-Latn-RW ; rw ; +und-SA ; ar-Arab-SA ; ar-SA ; +und-SB ; en-Latn-SB ; en-SB ; +und-SC ; fr-Latn-SC ; fr-SC ; +und-SD ; ar-Arab-SD ; ar-SD ; +und-SE ; sv-Latn-SE ; sv ; +und-SG ; en-Latn-SG ; en-SG ; +und-SH ; en-Latn-SH ; en-SH ; +und-SI ; sl-Latn-SI ; sl ; +und-SJ ; nb-Latn-SJ ; nb-SJ ; +und-SK ; sk-Latn-SK ; sk ; +und-SL ; kri-Latn-SL ; kri ; +und-SM ; it-Latn-SM ; it-SM ; +und-SN ; fr-Latn-SN ; fr-SN ; +und-SO ; so-Latn-SO ; so ; +und-SR ; nl-Latn-SR ; nl-SR ; +und-SS ; ar-Arab-SS ; ar-SS ; +und-ST ; pt-Latn-ST ; pt-ST ; +und-SV ; es-Latn-SV ; es-SV ; +und-SX ; en-Latn-SX ; en-SX ; +und-SY ; ar-Arab-SY ; ar-SY ; +und-SZ ; en-Latn-SZ ; en-SZ ; +und-Sinh ; si-Sinh-LK ; si ; +und-Sinh-AQ ; si-Sinh-AQ ; si-AQ ; +und-Sinh-LK ; si-Sinh-LK ; si ; +und-TC ; en-Latn-TC ; en-TC ; +und-TD ; fr-Latn-TD ; fr-TD ; +und-TG ; fr-Latn-TG ; fr-TG ; +und-TH ; th-Thai-TH ; th ; +und-TJ ; tg-Cyrl-TJ ; tg ; +und-TK ; tkl-Latn-TK ; tkl ; +und-TL ; pt-Latn-TL ; pt-TL ; +und-TM ; tk-Latn-TM ; tk ; +und-TN ; ar-Arab-TN ; ar-TN ; +und-TO ; to-Latn-TO ; to ; +und-TR ; tr-Latn-TR ; tr ; +und-TT ; en-Latn-TT ; en-TT ; +und-TV ; tvl-Latn-TV ; tvl ; +und-TW ; zh-Hant-TW ; zh-Hant ; zh-TW +und-TZ ; sw-Latn-TZ ; sw ; +und-Taml ; ta-Taml-IN ; ta ; +und-Taml-AQ ; ta-Taml-AQ ; ta-AQ ; +und-Taml-IN ; ta-Taml-IN ; ta ; +und-Taml-LK ; ta-Taml-LK ; ta-LK ; +und-Taml-MY ; ta-Taml-MY ; ta-MY ; +und-Taml-SG ; ta-Taml-SG ; ta-SG ; +und-Telu ; te-Telu-IN ; te ; +und-Telu-AQ ; te-Telu-AQ ; te-AQ ; +und-Telu-IN ; te-Telu-IN ; te ; +und-Thai ; th-Thai-TH ; th ; +und-Thai-AQ ; th-Thai-AQ ; th-AQ ; +und-Thai-TH ; th-Thai-TH ; th ; +und-UA ; uk-Cyrl-UA ; uk ; +und-UG ; sw-Latn-UG ; sw-UG ; +und-UM ; en-Latn-UM ; en-UM ; +und-US ; en-Latn-US ; en ; +und-UY ; es-Latn-UY ; es-UY ; +und-UZ ; uz-Latn-UZ ; uz ; +und-VA ; it-Latn-VA ; it-VA ; +und-VC ; en-Latn-VC ; en-VC ; +und-VE ; es-Latn-VE ; es-VE ; +und-VG ; en-Latn-VG ; en-VG ; +und-VI ; en-Latn-VI ; en-VI ; +und-VN ; vi-Latn-VN ; vi ; +und-VU ; bi-Latn-VU ; bi ; +und-WF ; fr-Latn-WF ; fr-WF ; +und-WS ; sm-Latn-WS ; sm ; +und-XK ; sq-Latn-XK ; sq-XK ; +und-YE ; ar-Arab-YE ; ar-YE ; +und-YT ; fr-Latn-YT ; fr-YT ; +und-ZA ; en-Latn-ZA ; en-ZA ; +und-ZM ; bem-Latn-ZM ; bem ; +und-ZW ; sn-Latn-ZW ; sn ; +ur ; ur-Arab-PK ; ur ; +ur-AQ ; ur-Arab-AQ ; ur-AQ ; +ur-Arab ; ur-Arab-PK ; ur ; +ur-Egyp ; ur-Egyp-PK ; ur-Egyp ; +ur-IN ; ur-Arab-IN ; ur-IN ; +ur-PK ; ur-Arab-PK ; ur ; +uz ; uz-Latn-UZ ; uz ; +uz-AQ ; uz-Latn-AQ ; uz-AQ ; +uz-Cyrl ; uz-Cyrl-UZ ; uz-Cyrl ; +uz-Egyp ; uz-Egyp-UZ ; uz-Egyp ; +uz-Latn ; uz-Latn-UZ ; uz ; +uz-UZ ; uz-Latn-UZ ; uz ; +vec ; vec-Latn-IT ; vec ; +vec-AQ ; vec-Latn-AQ ; vec-AQ ; +vec-Egyp ; vec-Egyp-IT ; vec-Egyp ; +vec-IT ; vec-Latn-IT ; vec ; +vec-Latn ; vec-Latn-IT ; vec ; +vi ; vi-Latn-VN ; vi ; +vi-AQ ; vi-Latn-AQ ; vi-AQ ; +vi-Egyp ; vi-Egyp-VN ; vi-Egyp ; +vi-Latn ; vi-Latn-VN ; vi ; +vi-VN ; vi-Latn-VN ; vi ; +wo ; wo-Latn-SN ; wo ; +wo-AQ ; wo-Latn-AQ ; wo-AQ ; +wo-Egyp ; wo-Egyp-SN ; wo-Egyp ; +wo-Latn ; wo-Latn-SN ; wo ; +wo-SN ; wo-Latn-SN ; wo ; +xh ; xh-Latn-ZA ; xh ; +xh-AQ ; xh-Latn-AQ ; xh-AQ ; +xh-Egyp ; xh-Egyp-ZA ; xh-Egyp ; +xh-Latn ; xh-Latn-ZA ; xh ; +xh-ZA ; xh-Latn-ZA ; xh ; +xnr ; xnr-Deva-IN ; xnr ; +xnr-AQ ; xnr-Deva-AQ ; xnr-AQ ; +xnr-Deva ; xnr-Deva-IN ; xnr ; +xnr-Egyp ; xnr-Egyp-IN ; xnr-Egyp ; +xnr-IN ; xnr-Deva-IN ; xnr ; +yo ; yo-Latn-NG ; yo ; +yo-AQ ; yo-Latn-AQ ; yo-AQ ; +yo-BJ ; yo-Latn-BJ ; yo-BJ ; +yo-Egyp ; yo-Egyp-NG ; yo-Egyp ; +yo-Latn ; yo-Latn-NG ; yo ; +yo-NG ; yo-Latn-NG ; yo ; +yrl ; yrl-Latn-BR ; yrl ; +yrl-AQ ; yrl-Latn-AQ ; yrl-AQ ; +yrl-BR ; yrl-Latn-BR ; yrl ; +yrl-CO ; yrl-Latn-CO ; yrl-CO ; +yrl-Egyp ; yrl-Egyp-BR ; yrl-Egyp ; +yrl-Latn ; yrl-Latn-BR ; yrl ; +yrl-VE ; yrl-Latn-VE ; yrl-VE ; +yue ; yue-Hant-HK ; yue ; +yue-AQ ; yue-Hant-AQ ; yue-AQ ; +yue-CN ; yue-Hans-CN ; yue-Hans ; yue-CN +yue-Egyp ; yue-Egyp-HK ; yue-Egyp ; +yue-HK ; yue-Hant-HK ; yue ; +yue-Hans ; yue-Hans-CN ; yue-Hans ; yue-CN +yue-Hant ; yue-Hant-HK ; yue ; +zh ; zh-Hans-CN ; zh ; +zh-AQ ; zh-Hans-AQ ; zh-AQ ; +zh-CN ; zh-Hans-CN ; zh ; +zh-Egyp ; zh-Egyp-CN ; zh-Egyp ; +zh-HK ; zh-Hant-HK ; zh-HK ; +zh-Hans ; zh-Hans-CN ; zh ; +zh-Hant ; zh-Hant-TW ; zh-Hant ; zh-TW +zh-MO ; zh-Hant-MO ; zh-MO ; +zh-SG ; zh-Hans-SG ; zh-SG ; +zh-TW ; zh-Hant-TW ; zh-Hant ; zh-TW +zu ; zu-Latn-ZA ; zu ; +zu-AQ ; zu-Latn-AQ ; zu-AQ ; +zu-Egyp ; zu-Egyp-ZA ; zu-Egyp ; +zu-Latn ; zu-Latn-ZA ; zu ; +zu-ZA ; zu-Latn-ZA ; zu ; diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/LocaleMatcherTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/LocaleMatcherTest.java index f8bf9fdff75a..b0443f4a40bf 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/LocaleMatcherTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/LocaleMatcherTest.java @@ -24,7 +24,6 @@ import org.junit.runner.RunWith; import com.ibm.icu.dev.test.TestFmwk; -import com.ibm.icu.dev.tool.locale.LikelySubtagsBuilder; import com.ibm.icu.impl.locale.XCldrStub.FileUtilities; import com.ibm.icu.impl.locale.XLikelySubtags; import com.ibm.icu.util.LocaleMatcher; @@ -869,19 +868,12 @@ private static long timeMaximize(Iterable list, int iterations) { long start = System.nanoTime(); for (int i = iterations; i > 0; --i) { for (ULocale locale : list) { - XLikelySubtags.INSTANCE.makeMaximizedLsrFrom(locale); + XLikelySubtags.INSTANCE.makeMaximizedLsrFrom(locale, false); } } return System.nanoTime() - start; } - @Test - public void testLikelySubtagsLoadedDataSameAsBuiltFromScratch() { - XLikelySubtags.Data built = LikelySubtagsBuilder.build(); - XLikelySubtags.Data loaded = XLikelySubtags.Data.load(); - assertEquals("run LocaleDistanceBuilder and update ICU4C langInfo.txt", built, loaded); - } - private static final class TestCase implements Cloneable { private static final String ENDL = System.getProperties().getProperty("line.separator"); diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ULocaleTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ULocaleTest.java index af47414ccab1..a5f99d01d2af 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ULocaleTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ULocaleTest.java @@ -16,11 +16,13 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -54,7 +56,10 @@ import com.ibm.icu.util.UResourceBundle; import com.ibm.icu.util.VersionInfo; -@RunWith(JUnit4.class) +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; + +@RunWith(JUnitParamsRunner.class) public class ULocaleTest extends TestFmwk { // Ticket #8078 and #11674 @@ -1947,7 +1952,7 @@ else if (!res.toString().equals(exp)) { "de__POSIX_1901" }, { "und", - "" + "en" } }; @@ -2760,8 +2765,8 @@ else if (!res.toString().equals(exp)) { "am" }, { "und_Ethi_ER", - "am_Ethi_ER", - "am_ER" + "ti_Ethi_ER", + "ti_ER" }, { "und_FI", "fi_Latn_FI", @@ -3536,8 +3541,8 @@ else if (!res.toString().equals(exp)) { "trv" }, { "und_Latn_HK", - "zh_Latn_HK", - "zh_Latn_HK" + "en_Latn_HK", + "en_HK" }, { "und_Latn_AQ", "_Latn_AQ", @@ -5417,4 +5422,103 @@ public void TestLocaleCanonicalizationFromFile() throws IOException { } } + + boolean isKnownSourceFor20777(String s) { + return s.equals("und-001") || + s.equals("und-AQ") || + s.equals("und-CC") || + s.equals("und-SL") || + s.equals("und-SS") || + s.equals("und-ZM") || + s.startsWith("und-Latn-"); + } + + private static final class TestCase implements Cloneable { + private static final String ENDL = System.getProperties().getProperty("line.separator"); + + int lineNr = 0; + + String source = ""; + String addLikely = ""; + String removeFavorScript = ""; + String removeFavorRegion = ""; + + @Override + public TestCase clone() throws CloneNotSupportedException { + return (TestCase) super.clone(); + } + + @Override + public String toString() { + return (new StringBuilder(source)) + .append(";") + .append(addLikely) + .append(";") + .append(removeFavorScript) + .append(";") + .append(removeFavorRegion) + .toString(); + } + } + static List readLikelySubtagsTestCases() throws Exception { + List tests = new ArrayList<>(); + TestCase test = new TestCase(); + BufferedReader testFile = TestUtil.getDataReader("likelySubtags.txt"); + try { + String line; + while ((line = testFile.readLine()) != null) { + if (line.startsWith("#")) continue; + String [] fields = line.split("[ \t]?;[ \t]?"); + if (fields.length < 2) continue; + test.source = fields[0]; + test.addLikely = fields[1]; + test.removeFavorScript = (fields.length < 3) || fields[2].isEmpty() ? test.addLikely : fields[2]; + test.removeFavorRegion = (fields.length < 4) || fields[3].isEmpty() ? test.removeFavorScript : fields[3]; + tests.add(test.clone()); + } + } finally { + testFile.close(); + } + return tests; + } + + @Test + @Parameters(method = "readLikelySubtagsTestCases") + public void likelySubtagsDataDriven(TestCase test) { + ULocale l = ULocale.forLanguageTag(test.source); + if (isKnownSourceFor20777(test.source)) { + if (test.addLikely.equals(ULocale.addLikelySubtags(l).toLanguageTag())) { + logKnownIssue("ICU-20777", "addLikelySubtags(" + test.source + ")"); + } + if (test.removeFavorRegion.equals(ULocale.minimizeSubtags(l).toLanguageTag())) { + logKnownIssue("ICU-20777", "minimizeSubtags(" + test.source + ")"); + } + if (test.removeFavorScript.equals(ULocale.minimizeSubtags( + l, ULocale.Minimize.FAVOR_SCRIPT).toLanguageTag())) { + logKnownIssue("ICU-20777", "minimizeSubtags(" + test.source + ") - FAVOR_SCRIPT"); + } + } else { + if (test.addLikely.equals("FAIL")) { + assertEquals("addLikelySubtags(" + test.source + ") should be unchanged", + l, ULocale.addLikelySubtags(l)); + } else { + assertEquals("addLikelySubtags(" + test.source + ")", + test.addLikely, ULocale.addLikelySubtags(l).toLanguageTag()); + } + if (test.removeFavorRegion.equals("FAIL")) { + assertEquals("minimizeSubtags(" + test.source + ") should be unchanged", + l, ULocale.minimizeSubtags(l)); + } else { + assertEquals("minimizeSubtags(" + test.source + ")", + test.removeFavorRegion, ULocale.minimizeSubtags(l).toLanguageTag()); + } + if (test.removeFavorScript.equals("FAIL")) { + assertEquals("minimizeSubtags(" + test.source + ") - FAVOR_SCRIPT should be unchanged", + l, ULocale.minimizeSubtags(l, ULocale.Minimize.FAVOR_SCRIPT)); + } else { + assertEquals("minimizeSubtags(" + test.source + ") - FAVOR_SCRIPT", + test.removeFavorScript, ULocale.minimizeSubtags(l, ULocale.Minimize.FAVOR_SCRIPT).toLanguageTag()); + } + } + } } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/tool/locale/LikelySubtagsBuilder.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/tool/locale/LikelySubtagsBuilder.java deleted file mode 100644 index fdba09ba71f0..000000000000 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/tool/locale/LikelySubtagsBuilder.java +++ /dev/null @@ -1,317 +0,0 @@ -// © 2017 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -package com.ibm.icu.dev.tool.locale; - -import java.nio.ByteBuffer; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import com.ibm.icu.impl.ICUData; -import com.ibm.icu.impl.ICUResourceBundle; -import com.ibm.icu.impl.UResource; -import com.ibm.icu.impl.locale.LSR; -import com.ibm.icu.impl.locale.XCldrStub.HashMultimap; -import com.ibm.icu.impl.locale.XCldrStub.Multimap; -import com.ibm.icu.impl.locale.XCldrStub.Multimaps; -import com.ibm.icu.impl.locale.XLikelySubtags; -import com.ibm.icu.util.BytesTrieBuilder; -import com.ibm.icu.util.ICUException; - -/** - * Builds data for XLikelySubtags. - * Reads source data from ICU resource bundles. - */ -public class LikelySubtagsBuilder { - private static final boolean DEBUG_OUTPUT = LSR.DEBUG_OUTPUT; - - private static ICUResourceBundle getSupplementalDataBundle(String name) { - return ICUResourceBundle.getBundleInstance( - ICUData.ICU_BASE_NAME, name, - ICUResourceBundle.ICU_DATA_CLASS_LOADER, ICUResourceBundle.OpenType.DIRECT); - } - - private static final class AliasesBuilder { - final Map toCanonical = new HashMap<>(); - final Multimap toAliases; - - public Set getAliases(String canonical) { - Set aliases = toAliases.get(canonical); - return aliases == null ? Collections.singleton(canonical) : aliases; - } - - public AliasesBuilder(String type) { - ICUResourceBundle metadata = getSupplementalDataBundle("metadata"); - UResource.Value value = metadata.getValueWithFallback("alias/" + type); - UResource.Table aliases = value.getTable(); - UResource.Key key = new UResource.Key(); - for (int i = 0; aliases.getKeyAndValue(i, key, value); ++i) { - String aliasFrom = key.toString(); - if (aliasFrom.contains("_") || aliasFrom.contains("-")) { - continue; // only simple aliasing - } - UResource.Table table = value.getTable(); - if (table.findValue("reason", value) && value.getString().equals("overlong")) { - continue; - } - if (!table.findValue("replacement", value)) { - continue; - } - String aliasTo = value.getString(); - int spacePos = aliasTo.indexOf(' '); - String aliasFirst = spacePos < 0 ? aliasTo : aliasTo.substring(0, spacePos); - if (aliasFirst.contains("_")) { - continue; // only simple aliasing - } - toCanonical.put(aliasFrom, aliasFirst); - } - if (type.equals("language")) { - toCanonical.put("mo", "ro"); // special case - } - toAliases = Multimaps.invertFrom(toCanonical, HashMultimap.create()); - - if (DEBUG_OUTPUT) { - System.out.println("*** " + type + " aliases"); - for (Map.Entry mapping : new TreeMap<>(toCanonical).entrySet()) { - System.out.println(mapping); - } - } - } - } - - private static final class TrieBuilder { - byte[] bytes = new byte[24]; - int length = 0; - BytesTrieBuilder tb = new BytesTrieBuilder(); - - void addValue(int value) { - assert value >= 0; - tb.add(bytes, length, value); - } - - void addStar() { - bytes[length++] = '*'; - } - - void addSubtag(String s) { - assert !s.isEmpty(); - assert !s.equals("*"); - int end = s.length() - 1; - for (int i = 0;; ++i) { - char c = s.charAt(i); - assert c <= 0x7f; - if (i < end) { - bytes[length++] = (byte) c; - } else { - // Mark the last character as a terminator to avoid overlap matches. - bytes[length++] = (byte) (c | 0x80); - break; - } - } - } - - byte[] build() { - ByteBuffer buffer = tb.buildByteBuffer(BytesTrieBuilder.Option.SMALL); - // Allocate an array with just the necessary capacity, - // so that we do not hold on to a larger array for a long time. - byte[] bytes = new byte[buffer.remaining()]; - buffer.get(bytes); - if (DEBUG_OUTPUT) { - System.out.println("likely subtags trie size: " + bytes.length + " bytes"); - } - return bytes; - } - } - - // VisibleForTesting - public static XLikelySubtags.Data build() { - AliasesBuilder languageAliasesBuilder = new AliasesBuilder("language"); - AliasesBuilder regionAliasesBuilder = new AliasesBuilder("territory"); - - Map>> langTable = - makeTable(languageAliasesBuilder, regionAliasesBuilder); - - TrieBuilder trieBuilder = new TrieBuilder(); - Map lsrIndexes = new LinkedHashMap<>(); - // Reserve index 0 as "no value": - // The runtime lookup returns 0 for an intermediate match with no value. - lsrIndexes.put(new LSR("", "", "", LSR.DONT_CARE_FLAGS), 0); // arbitrary LSR - // Reserve index 1 for SKIP_SCRIPT: - // The runtime lookup returns 1 for an intermediate match with a value. - // This LSR looks good when printing the data. - lsrIndexes.put(new LSR("skip", "script", "", LSR.DONT_CARE_FLAGS), 1); - // We could prefill the lsrList with common locales to give them small indexes, - // and see if that improves performance a little. - for (Map.Entry>> ls : langTable.entrySet()) { - trieBuilder.length = 0; - String lang = ls.getKey(); - if (lang.equals("und")) { - trieBuilder.addStar(); - } else { - trieBuilder.addSubtag(lang); - } - Map> scriptTable = ls.getValue(); - boolean skipScript = false; - if (scriptTable.size() == 1) { - Map regionTable = scriptTable.get(""); - if (regionTable.size() == 1) { - // Prune the script and region levels from language with - // only * for scripts and regions. - int i = uniqueIdForLsr(lsrIndexes, regionTable.get("")); - trieBuilder.addValue(i); - continue; - } else { - // Prune the script level from language with only * for scripts - // but with real regions. - // Set an intermediate value as a signal to the lookup code. - trieBuilder.addValue(XLikelySubtags.SKIP_SCRIPT); - skipScript = true; - } - } - int scriptStartLength = trieBuilder.length; - for (Map.Entry> sr : scriptTable.entrySet()) { - trieBuilder.length = scriptStartLength; - if (!skipScript) { - String script = sr.getKey(); - if (script.isEmpty()) { - trieBuilder.addStar(); - } else { - trieBuilder.addSubtag(script); - } - } - Map regionTable = sr.getValue(); - if (regionTable.size() == 1) { - // Prune the region level from language+script with only * for regions. - int i = uniqueIdForLsr(lsrIndexes, regionTable.get("")); - trieBuilder.addValue(i); - continue; - } - int regionStartLength = trieBuilder.length; - for (Map.Entry r2lsr : regionTable.entrySet()) { - trieBuilder.length = regionStartLength; - String region = r2lsr.getKey(); - // Map the whole lang+script+region to a unique, dense index of the LSR. - if (region.isEmpty()) { - trieBuilder.addStar(); - } else { - trieBuilder.addSubtag(region); - } - int i = uniqueIdForLsr(lsrIndexes, r2lsr.getValue()); - trieBuilder.addValue(i); - } - } - } - byte[] trie = trieBuilder.build(); - LSR[] lsrs = lsrIndexes.keySet().toArray(new LSR[lsrIndexes.size()]); - return new XLikelySubtags.Data( - languageAliasesBuilder.toCanonical, regionAliasesBuilder.toCanonical, trie, lsrs); - } - - private static int uniqueIdForLsr(Map lsrIndexes, LSR lsr) { - Integer index = lsrIndexes.get(lsr); - if (index != null) { - return index.intValue(); - } else { - int i = lsrIndexes.size(); - lsrIndexes.put(lsr, i); - return i; - } - } - - private static Map>> makeTable( - AliasesBuilder languageAliasesBuilder, AliasesBuilder regionAliasesBuilder) { - Map>> result = new TreeMap<>(); - // set the base data - ICUResourceBundle likelySubtags = getSupplementalDataBundle("likelySubtags"); - UResource.Value value = likelySubtags.getValueWithFallback(""); - UResource.Table table = value.getTable(); - UResource.Key key = new UResource.Key(); - for (int i = 0; table.getKeyAndValue(i, key, value); ++i) { - LSR ltp = lsrFromLocaleID(key.toString()); // source - final String language = ltp.language; - final String script = ltp.script; - final String region = ltp.region; - - ltp = lsrFromLocaleID(value.getString()); // target - set(result, language, script, region, ltp); - - // now add aliases - Collection languageAliases = languageAliasesBuilder.getAliases(language); - Collection regionAliases = regionAliasesBuilder.getAliases(region); - for (String languageAlias : languageAliases) { - for (String regionAlias : regionAliases) { - if (languageAlias.equals(language) && regionAlias.equals(region)) { - continue; - } - set(result, languageAlias, script, regionAlias, ltp); - } - } - } - // hack - set(result, "und", "Latn", "", new LSR("en", "Latn", "US", LSR.DONT_CARE_FLAGS)); - - // hack, ensure that if und-YY => und-Xxxx-YY, then we add Xxxx=>YY to the table - // - - // so und-Latn-GH => ak-Latn-GH - Map> undScriptMap = result.get("und"); - Map undEmptyRegionMap = undScriptMap.get(""); - for (Map.Entry regionEntry : undEmptyRegionMap.entrySet()) { - final LSR lsr = regionEntry.getValue(); - set(result, "und", lsr.script, lsr.region, lsr); - } - // - // check that every level has "" (or "und") - if (!result.containsKey("und")) { - throw new IllegalArgumentException("failure: base"); - } - for (Map.Entry>> langEntry : result.entrySet()) { - String lang = langEntry.getKey(); - final Map> scriptMap = langEntry.getValue(); - if (!scriptMap.containsKey("")) { - throw new IllegalArgumentException("failure: " + lang); - } - for (Map.Entry> scriptEntry : scriptMap.entrySet()) { - String script = scriptEntry.getKey(); - final Map regionMap = scriptEntry.getValue(); - if (!regionMap.containsKey("")) { - throw new IllegalArgumentException("failure: " + lang + "-" + script); - } - } - } - return result; - } - - // Parses locale IDs in the likelySubtags data, not arbitrary language tags. - private static LSR lsrFromLocaleID(String languageIdentifier) { - String[] parts = languageIdentifier.split("[-_]"); - if (parts.length < 1 || parts.length > 3) { - throw new ICUException("too many subtags"); - } - String lang = parts[0]; - String p2 = parts.length < 2 ? "" : parts[1]; - String p3 = parts.length < 3 ? "" : parts[2]; - return p2.length() < 4 ? - new LSR(lang, "", p2, LSR.DONT_CARE_FLAGS) : - new LSR(lang, p2, p3, LSR.DONT_CARE_FLAGS); - } - - private static void set(Map>> langTable, - final String language, final String script, final String region, LSR newValue) { - Map> scriptTable = getSubtable(langTable, language); - Map regionTable = getSubtable(scriptTable, script); - regionTable.put(region, newValue); - } - - private static Map getSubtable(Map> table, final K subtag) { - Map subTable = table.get(subtag); - if (subTable == null) { - table.put(subtag, subTable = new TreeMap<>()); - } - return subTable; - } -} diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/tool/locale/LocaleDistanceBuilder.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/tool/locale/LocaleDistanceBuilder.java index 0a70709ee987..4a0736a99b6c 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/tool/locale/LocaleDistanceBuilder.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/tool/locale/LocaleDistanceBuilder.java @@ -489,7 +489,7 @@ public static LocaleDistance.Data build() { Set paradigmLSRs = new LinkedHashSet<>(); // could be TreeSet if LSR were Comparable for (String paradigm : paradigms) { ULocale pl = new ULocale(paradigm); - LSR max = XLikelySubtags.INSTANCE.makeMaximizedLsrFrom(pl); + LSR max = XLikelySubtags.INSTANCE.makeMaximizedLsrFrom(pl, false); // Clear the LSR flags to make the data equality test in // LocaleDistanceTest happy. paradigmLSRs.add(new LSR(max.language, max.script, max.region, LSR.DONT_CARE_FLAGS)); @@ -887,7 +887,7 @@ private static void printManyHexBytes(PrintWriter out, byte[] bytes) { } public static final void main(String[] args) throws IOException { - XLikelySubtags.Data likelyData = LikelySubtagsBuilder.build(); + XLikelySubtags.Data likelyData = XLikelySubtags.Data.load(); LocaleDistance.Data distanceData = build(); System.out.println("Writing LocaleDistance.Data to " + TXT_PATH + '/' + TXT_FILE_NAME); try (PrintWriter out = openWriter()) {