Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 1 | // © 2016 and later: Unicode, Inc. and others. |
| 2 | // License & terms of use: http://www.unicode.org/copyright.html |
| 3 | /******************************************************************** |
| 4 | * COPYRIGHT: |
| 5 | * Copyright (c) 1997-2016, International Business Machines Corporation and |
| 6 | * others. All Rights Reserved. |
| 7 | ********************************************************************/ |
| 8 | |
| 9 | #include <algorithm> |
| 10 | #include <functional> |
| 11 | #include <iterator> |
| 12 | #include <set> |
| 13 | #include <utility> |
| 14 | |
| 15 | #include "loctest.h" |
| 16 | #include "unicode/localebuilder.h" |
| 17 | #include "unicode/localpointer.h" |
| 18 | #include "unicode/decimfmt.h" |
| 19 | #include "unicode/ucurr.h" |
| 20 | #include "unicode/smpdtfmt.h" |
| 21 | #include "unicode/strenum.h" |
| 22 | #include "unicode/dtfmtsym.h" |
| 23 | #include "unicode/brkiter.h" |
| 24 | #include "unicode/coll.h" |
| 25 | #include "unicode/ustring.h" |
| 26 | #include "unicode/std_string.h" |
| 27 | #include "charstr.h" |
| 28 | #include "cmemory.h" |
| 29 | #include "cstring.h" |
| 30 | #include <stdio.h> |
| 31 | #include <string.h> |
| 32 | #include "putilimp.h" |
| 33 | #include "hash.h" |
| 34 | #include "locmap.h" |
| 35 | #include "uparse.h" |
| 36 | #include "ulocimp.h" |
| 37 | |
| 38 | static const char* const rawData[33][8] = { |
| 39 | |
| 40 | // language code |
| 41 | { "en", "fr", "ca", "el", "no", "it", "xx", "zh" }, |
| 42 | // script code |
| 43 | { "", "", "", "", "", "", "", "Hans" }, |
| 44 | // country code |
| 45 | { "US", "FR", "ES", "GR", "NO", "", "YY", "CN" }, |
| 46 | // variant code |
| 47 | { "", "", "", "", "NY", "", "", "" }, |
| 48 | // full name |
| 49 | { "en_US", "fr_FR", "ca_ES", "el_GR", "no_NO_NY", "it", "xx_YY", "zh_Hans_CN" }, |
| 50 | // ISO-3 language |
| 51 | { "eng", "fra", "cat", "ell", "nor", "ita", "", "zho" }, |
| 52 | // ISO-3 country |
| 53 | { "USA", "FRA", "ESP", "GRC", "NOR", "", "", "CHN" }, |
| 54 | // LCID |
| 55 | { "409", "40c", "403", "408", "814", "10", "0", "804" }, |
| 56 | |
| 57 | // display language (English) |
| 58 | { "English", "French", "Catalan", "Greek", "Norwegian", "Italian", "xx", "Chinese" }, |
| 59 | // display script (English) |
| 60 | { "", "", "", "", "", "", "", "Simplified Han" }, |
| 61 | // display country (English) |
| 62 | { "United States", "France", "Spain", "Greece", "Norway", "", "YY", "China" }, |
| 63 | // display variant (English) |
| 64 | { "", "", "", "", "NY", "", "", ""}, |
| 65 | // display name (English) |
| 66 | // Updated no_NO_NY English display name for new pattern-based algorithm |
| 67 | // (part of Euro support). |
| 68 | { "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway, NY)", "Italian", "xx (YY)", "Chinese (Simplified, China)" }, |
| 69 | |
| 70 | // display language (French) |
| 71 | { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "italien", "xx", "chinois" }, |
| 72 | // display script (French) |
| 73 | { "", "", "", "", "", "", "", "sinogrammes simplifi\\u00E9s" }, |
| 74 | // display country (French) |
| 75 | { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "", "YY", "Chine" }, |
| 76 | // display variant (French) |
| 77 | { "", "", "", "", "NY", "", "", "" }, |
| 78 | // display name (French) |
| 79 | //{ "anglais (Etats-Unis)", "francais (France)", "catalan (Espagne)", "grec (Grece)", "norvegien (Norvege,Nynorsk)", "italien", "xx (YY)" }, |
| 80 | { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)", "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "italien", "xx (YY)", "chinois (simplifi\\u00E9, Chine)" }, |
| 81 | |
| 82 | |
| 83 | /* display language (Catalan) */ |
| 84 | { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "itali\\u00E0", "", "xin\\u00E8s" }, |
| 85 | /* display script (Catalan) */ |
| 86 | { "", "", "", "", "", "", "", "han simplificat" }, |
| 87 | /* display country (Catalan) */ |
| 88 | { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "", "", "Xina" }, |
| 89 | /* display variant (Catalan) */ |
| 90 | { "", "", "", "", "NY", "", "" }, |
| 91 | /* display name (Catalan) */ |
| 92 | { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)", "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "itali\\u00E0", "", "xin\\u00E8s (simplificat, Xina)" }, |
| 93 | |
| 94 | // display language (Greek)[actual values listed below] |
| 95 | { "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac", |
| 96 | "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac", |
| 97 | "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac", |
| 98 | "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac", |
| 99 | "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac", |
| 100 | "\\u0399\\u03c4\\u03b1\\u03bb\\u03b9\\u03ba\\u03ac", |
| 101 | "", |
| 102 | "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC" |
| 103 | }, |
| 104 | // display script (Greek) |
| 105 | { "", "", "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd" }, |
| 106 | // display country (Greek)[actual values listed below] |
| 107 | { "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2", |
| 108 | "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1", |
| 109 | "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1", |
| 110 | "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1", |
| 111 | "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1", |
| 112 | "", |
| 113 | "", |
| 114 | "\\u039A\\u03AF\\u03BD\\u03B1" |
| 115 | }, |
| 116 | // display variant (Greek) |
| 117 | { "", "", "", "", "NY", "", "" }, |
| 118 | // display name (Greek)[actual values listed below] |
| 119 | { "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)", |
| 120 | "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)", |
| 121 | "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)", |
| 122 | "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)", |
| 123 | "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)", |
| 124 | "\\u0399\\u03c4\\u03b1\\u03bb\\u03b9\\u03ba\\u03ac", |
| 125 | "", |
| 126 | "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)" |
| 127 | }, |
| 128 | |
| 129 | // display language (<root>) |
| 130 | { "English", "French", "Catalan", "Greek", "Norwegian", "Italian", "xx", "" }, |
| 131 | // display script (<root>) |
| 132 | { "", "", "", "", "", "", "", ""}, |
| 133 | // display country (<root>) |
| 134 | { "United States", "France", "Spain", "Greece", "Norway", "", "YY", "" }, |
| 135 | // display variant (<root>) |
| 136 | { "", "", "", "", "Nynorsk", "", "", ""}, |
| 137 | // display name (<root>) |
| 138 | //{ "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway,Nynorsk)", "Italian", "xx (YY)" }, |
| 139 | { "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway,NY)", "Italian", "xx (YY)", "" } |
| 140 | }; |
| 141 | |
| 142 | |
| 143 | /* |
| 144 | Usage: |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 145 | test_assert( Test (should be true) ) |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 146 | |
| 147 | Example: |
| 148 | test_assert(i==3); |
| 149 | |
| 150 | the macro is ugly but makes the tests pretty. |
| 151 | */ |
| 152 | |
| 153 | #define test_assert(test) UPRV_BLOCK_MACRO_BEGIN { \ |
| 154 | if(!(test)) \ |
| 155 | errln("FAIL: " #test " was not true. In " __FILE__ " on line %d", __LINE__ ); \ |
| 156 | else \ |
| 157 | logln("PASS: asserted " #test); \ |
| 158 | } UPRV_BLOCK_MACRO_END |
| 159 | |
| 160 | /* |
| 161 | Usage: |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 162 | test_assert_print( Test (should be true), printable ) |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 163 | |
| 164 | Example: |
| 165 | test_assert(i==3, toString(i)); |
| 166 | |
| 167 | the macro is ugly but makes the tests pretty. |
| 168 | */ |
| 169 | |
| 170 | #define test_assert_print(test,print) UPRV_BLOCK_MACRO_BEGIN { \ |
| 171 | if(!(test)) \ |
| 172 | errln("FAIL: " #test " was not true. " + UnicodeString(print) ); \ |
| 173 | else \ |
| 174 | logln("PASS: asserted " #test "-> " + UnicodeString(print)); \ |
| 175 | } UPRV_BLOCK_MACRO_END |
| 176 | |
| 177 | |
| 178 | #define test_dumpLocale(l) UPRV_BLOCK_MACRO_BEGIN { \ |
| 179 | logln(#l " = " + UnicodeString(l.getName(), "")); \ |
| 180 | } UPRV_BLOCK_MACRO_END |
| 181 | |
| 182 | LocaleTest::LocaleTest() |
| 183 | : dataTable(NULL) |
| 184 | { |
| 185 | setUpDataTable(); |
| 186 | } |
| 187 | |
| 188 | LocaleTest::~LocaleTest() |
| 189 | { |
| 190 | if (dataTable != 0) { |
| 191 | for (int32_t i = 0; i < 33; i++) { |
| 192 | delete []dataTable[i]; |
| 193 | } |
| 194 | delete []dataTable; |
| 195 | dataTable = 0; |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) |
| 200 | { |
| 201 | TESTCASE_AUTO_BEGIN; |
| 202 | TESTCASE_AUTO(TestBug11421); // Must run early in list to trigger failure. |
| 203 | TESTCASE_AUTO(TestBasicGetters); |
| 204 | TESTCASE_AUTO(TestSimpleResourceInfo); |
| 205 | TESTCASE_AUTO(TestDisplayNames); |
| 206 | TESTCASE_AUTO(TestSimpleObjectStuff); |
| 207 | TESTCASE_AUTO(TestPOSIXParsing); |
| 208 | TESTCASE_AUTO(TestGetAvailableLocales); |
| 209 | TESTCASE_AUTO(TestDataDirectory); |
| 210 | TESTCASE_AUTO(TestISO3Fallback); |
| 211 | TESTCASE_AUTO(TestGetLangsAndCountries); |
| 212 | TESTCASE_AUTO(TestSimpleDisplayNames); |
| 213 | TESTCASE_AUTO(TestUninstalledISO3Names); |
| 214 | TESTCASE_AUTO(TestAtypicalLocales); |
| 215 | #if !UCONFIG_NO_FORMATTING |
| 216 | TESTCASE_AUTO(TestThaiCurrencyFormat); |
| 217 | TESTCASE_AUTO(TestEuroSupport); |
| 218 | #endif |
| 219 | TESTCASE_AUTO(TestToString); |
| 220 | #if !UCONFIG_NO_FORMATTING |
| 221 | TESTCASE_AUTO(Test4139940); |
| 222 | TESTCASE_AUTO(Test4143951); |
| 223 | #endif |
| 224 | TESTCASE_AUTO(Test4147315); |
| 225 | TESTCASE_AUTO(Test4147317); |
| 226 | TESTCASE_AUTO(Test4147552); |
| 227 | TESTCASE_AUTO(TestVariantParsing); |
| 228 | TESTCASE_AUTO(Test20639_DeprecatesISO3Language); |
| 229 | #if !UCONFIG_NO_FORMATTING |
| 230 | TESTCASE_AUTO(Test4105828); |
| 231 | #endif |
| 232 | TESTCASE_AUTO(TestSetIsBogus); |
| 233 | TESTCASE_AUTO(TestParallelAPIValues); |
| 234 | TESTCASE_AUTO(TestAddLikelySubtags); |
| 235 | TESTCASE_AUTO(TestMinimizeSubtags); |
| 236 | TESTCASE_AUTO(TestAddLikelyAndMinimizeSubtags); |
| 237 | TESTCASE_AUTO(TestKeywordVariants); |
| 238 | TESTCASE_AUTO(TestCreateUnicodeKeywords); |
| 239 | TESTCASE_AUTO(TestKeywordVariantParsing); |
| 240 | TESTCASE_AUTO(TestCreateKeywordSet); |
| 241 | TESTCASE_AUTO(TestCreateKeywordSetEmpty); |
| 242 | TESTCASE_AUTO(TestCreateKeywordSetWithPrivateUse); |
| 243 | TESTCASE_AUTO(TestCreateUnicodeKeywordSet); |
| 244 | TESTCASE_AUTO(TestCreateUnicodeKeywordSetEmpty); |
| 245 | TESTCASE_AUTO(TestCreateUnicodeKeywordSetWithPrivateUse); |
| 246 | TESTCASE_AUTO(TestGetKeywordValueStdString); |
| 247 | TESTCASE_AUTO(TestGetUnicodeKeywordValueStdString); |
| 248 | TESTCASE_AUTO(TestSetKeywordValue); |
| 249 | TESTCASE_AUTO(TestSetKeywordValueStringPiece); |
| 250 | TESTCASE_AUTO(TestSetUnicodeKeywordValueStringPiece); |
| 251 | TESTCASE_AUTO(TestGetBaseName); |
| 252 | #if !UCONFIG_NO_FILE_IO |
| 253 | TESTCASE_AUTO(TestGetLocale); |
| 254 | #endif |
| 255 | TESTCASE_AUTO(TestVariantWithOutCountry); |
| 256 | TESTCASE_AUTO(TestCanonicalization); |
| 257 | TESTCASE_AUTO(TestCurrencyByDate); |
| 258 | TESTCASE_AUTO(TestGetVariantWithKeywords); |
| 259 | TESTCASE_AUTO(TestIsRightToLeft); |
| 260 | TESTCASE_AUTO(TestBug13277); |
| 261 | TESTCASE_AUTO(TestBug13554); |
| 262 | TESTCASE_AUTO(TestBug20410); |
| 263 | TESTCASE_AUTO(TestBug20900); |
| 264 | TESTCASE_AUTO(TestLocaleCanonicalizationFromFile); |
| 265 | TESTCASE_AUTO(TestKnownCanonicalizedListCorrect); |
| 266 | TESTCASE_AUTO(TestConstructorAcceptsBCP47); |
| 267 | TESTCASE_AUTO(TestForLanguageTag); |
| 268 | TESTCASE_AUTO(TestForLanguageTagLegacyTagBug21676); |
| 269 | TESTCASE_AUTO(TestToLanguageTag); |
| 270 | TESTCASE_AUTO(TestToLanguageTagOmitTrue); |
| 271 | TESTCASE_AUTO(TestMoveAssign); |
| 272 | TESTCASE_AUTO(TestMoveCtor); |
| 273 | TESTCASE_AUTO(TestBug20407iVariantPreferredValue); |
| 274 | TESTCASE_AUTO(TestBug13417VeryLongLanguageTag); |
| 275 | TESTCASE_AUTO(TestBug11053UnderlineTimeZone); |
| 276 | TESTCASE_AUTO(TestUnd); |
| 277 | TESTCASE_AUTO(TestUndScript); |
| 278 | TESTCASE_AUTO(TestUndRegion); |
| 279 | TESTCASE_AUTO(TestUndCAPI); |
| 280 | TESTCASE_AUTO(TestRangeIterator); |
| 281 | TESTCASE_AUTO(TestPointerConvertingIterator); |
| 282 | TESTCASE_AUTO(TestTagConvertingIterator); |
| 283 | TESTCASE_AUTO(TestCapturingTagConvertingIterator); |
| 284 | TESTCASE_AUTO(TestSetUnicodeKeywordValueInLongLocale); |
| 285 | TESTCASE_AUTO(TestSetUnicodeKeywordValueNullInLongLocale); |
| 286 | TESTCASE_AUTO(TestCanonicalize); |
| 287 | TESTCASE_AUTO(TestLeak21419); |
| 288 | TESTCASE_AUTO(TestNullDereferenceWrite21597); |
| 289 | TESTCASE_AUTO(TestLongLocaleSetKeywordAssign); |
| 290 | TESTCASE_AUTO(TestLongLocaleSetKeywordMoveAssign); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 291 | #if !UCONFIG_NO_FORMATTING |
| 292 | TESTCASE_AUTO(TestSierraLeoneCurrency21997); |
| 293 | #endif |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 294 | TESTCASE_AUTO_END; |
| 295 | } |
| 296 | |
| 297 | void LocaleTest::TestBasicGetters() { |
| 298 | UnicodeString temp; |
| 299 | |
| 300 | int32_t i; |
| 301 | for (i = 0; i <= MAX_LOCALES; i++) { |
| 302 | Locale testLocale(""); |
| 303 | if (rawData[SCRIPT][i] && rawData[SCRIPT][i][0] != 0) { |
| 304 | testLocale = Locale(rawData[LANG][i], rawData[SCRIPT][i], rawData[CTRY][i], rawData[VAR][i]); |
| 305 | } |
| 306 | else { |
| 307 | testLocale = Locale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]); |
| 308 | } |
| 309 | logln("Testing " + (UnicodeString)testLocale.getName() + "..."); |
| 310 | |
| 311 | if ( (temp=testLocale.getLanguage()) != (dataTable[LANG][i])) |
| 312 | errln(" Language code mismatch: " + temp + " versus " |
| 313 | + dataTable[LANG][i]); |
| 314 | if ( (temp=testLocale.getScript()) != (dataTable[SCRIPT][i])) |
| 315 | errln(" Script code mismatch: " + temp + " versus " |
| 316 | + dataTable[SCRIPT][i]); |
| 317 | if ( (temp=testLocale.getCountry()) != (dataTable[CTRY][i])) |
| 318 | errln(" Country code mismatch: " + temp + " versus " |
| 319 | + dataTable[CTRY][i]); |
| 320 | if ( (temp=testLocale.getVariant()) != (dataTable[VAR][i])) |
| 321 | errln(" Variant code mismatch: " + temp + " versus " |
| 322 | + dataTable[VAR][i]); |
| 323 | if ( (temp=testLocale.getName()) != (dataTable[NAME][i])) |
| 324 | errln(" Locale name mismatch: " + temp + " versus " |
| 325 | + dataTable[NAME][i]); |
| 326 | } |
| 327 | |
| 328 | logln("Same thing without variant codes..."); |
| 329 | for (i = 0; i <= MAX_LOCALES; i++) { |
| 330 | Locale testLocale(""); |
| 331 | if (rawData[SCRIPT][i] && rawData[SCRIPT][i][0] != 0) { |
| 332 | testLocale = Locale(rawData[LANG][i], rawData[SCRIPT][i], rawData[CTRY][i]); |
| 333 | } |
| 334 | else { |
| 335 | testLocale = Locale(rawData[LANG][i], rawData[CTRY][i]); |
| 336 | } |
| 337 | logln("Testing " + (temp=testLocale.getName()) + "..."); |
| 338 | |
| 339 | if ( (temp=testLocale.getLanguage()) != (dataTable[LANG][i])) |
| 340 | errln("Language code mismatch: " + temp + " versus " |
| 341 | + dataTable[LANG][i]); |
| 342 | if ( (temp=testLocale.getScript()) != (dataTable[SCRIPT][i])) |
| 343 | errln("Script code mismatch: " + temp + " versus " |
| 344 | + dataTable[SCRIPT][i]); |
| 345 | if ( (temp=testLocale.getCountry()) != (dataTable[CTRY][i])) |
| 346 | errln("Country code mismatch: " + temp + " versus " |
| 347 | + dataTable[CTRY][i]); |
| 348 | if (testLocale.getVariant()[0] != 0) |
| 349 | errln("Variant code mismatch: something versus \"\""); |
| 350 | } |
| 351 | |
| 352 | logln("Testing long language names and getters"); |
| 353 | Locale test8 = Locale::createFromName("x-klingon-latn-zx.utf32be@special"); |
| 354 | |
| 355 | temp = test8.getLanguage(); |
| 356 | if (temp != UnicodeString("x-klingon") ) |
| 357 | errln("Language code mismatch: " + temp + " versus \"x-klingon\""); |
| 358 | |
| 359 | temp = test8.getScript(); |
| 360 | if (temp != UnicodeString("Latn") ) |
| 361 | errln("Script code mismatch: " + temp + " versus \"Latn\""); |
| 362 | |
| 363 | temp = test8.getCountry(); |
| 364 | if (temp != UnicodeString("ZX") ) |
| 365 | errln("Country code mismatch: " + temp + " versus \"ZX\""); |
| 366 | |
| 367 | temp = test8.getVariant(); |
| 368 | //if (temp != UnicodeString("SPECIAL") ) |
| 369 | // errln("Variant code mismatch: " + temp + " versus \"SPECIAL\""); |
| 370 | // As of 3.0, the "@special" will *not* be parsed by uloc_getName() |
| 371 | if (temp != UnicodeString("") ) |
| 372 | errln("Variant code mismatch: " + temp + " versus \"\""); |
| 373 | |
| 374 | if (Locale::getDefault() != Locale::createFromName(NULL)) |
| 375 | errln("Locale::getDefault() == Locale::createFromName(NULL)"); |
| 376 | |
| 377 | /*----------*/ |
| 378 | // NOTE: There used to be a special test for locale names that had language or |
| 379 | // country codes that were longer than two letters. The new version of Locale |
| 380 | // doesn't support anything that isn't an officially recognized language or |
| 381 | // country code, so we no longer support this feature. |
| 382 | |
| 383 | Locale bogusLang("THISISABOGUSLANGUAGE"); // Jitterbug 2864: language code too long |
| 384 | if(!bogusLang.isBogus()) { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 385 | errln("Locale(\"THISISABOGUSLANGUAGE\").isBogus()==false"); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 386 | } |
| 387 | |
| 388 | bogusLang=Locale("eo"); |
| 389 | if( bogusLang.isBogus() || |
| 390 | strcmp(bogusLang.getLanguage(), "eo")!=0 || |
| 391 | *bogusLang.getCountry()!=0 || |
| 392 | *bogusLang.getVariant()!=0 || |
| 393 | strcmp(bogusLang.getName(), "eo")!=0 |
| 394 | ) { |
| 395 | errln("assignment to bogus Locale does not unbogus it or sets bad data"); |
| 396 | } |
| 397 | |
| 398 | Locale a("eo_DE@currency=DEM"); |
| 399 | Locale *pb=a.clone(); |
| 400 | if(pb==&a || *pb!=a) { |
| 401 | errln("Locale.clone() failed"); |
| 402 | } |
| 403 | delete pb; |
| 404 | } |
| 405 | |
| 406 | void LocaleTest::TestParallelAPIValues() { |
| 407 | logln("Test synchronization between C and C++ API"); |
| 408 | if (strcmp(Locale::getChinese().getName(), ULOC_CHINESE) != 0) { |
| 409 | errln("Differences for ULOC_CHINESE Locale"); |
| 410 | } |
| 411 | if (strcmp(Locale::getEnglish().getName(), ULOC_ENGLISH) != 0) { |
| 412 | errln("Differences for ULOC_ENGLISH Locale"); |
| 413 | } |
| 414 | if (strcmp(Locale::getFrench().getName(), ULOC_FRENCH) != 0) { |
| 415 | errln("Differences for ULOC_FRENCH Locale"); |
| 416 | } |
| 417 | if (strcmp(Locale::getGerman().getName(), ULOC_GERMAN) != 0) { |
| 418 | errln("Differences for ULOC_GERMAN Locale"); |
| 419 | } |
| 420 | if (strcmp(Locale::getItalian().getName(), ULOC_ITALIAN) != 0) { |
| 421 | errln("Differences for ULOC_ITALIAN Locale"); |
| 422 | } |
| 423 | if (strcmp(Locale::getJapanese().getName(), ULOC_JAPANESE) != 0) { |
| 424 | errln("Differences for ULOC_JAPANESE Locale"); |
| 425 | } |
| 426 | if (strcmp(Locale::getKorean().getName(), ULOC_KOREAN) != 0) { |
| 427 | errln("Differences for ULOC_KOREAN Locale"); |
| 428 | } |
| 429 | if (strcmp(Locale::getSimplifiedChinese().getName(), ULOC_SIMPLIFIED_CHINESE) != 0) { |
| 430 | errln("Differences for ULOC_SIMPLIFIED_CHINESE Locale"); |
| 431 | } |
| 432 | if (strcmp(Locale::getTraditionalChinese().getName(), ULOC_TRADITIONAL_CHINESE) != 0) { |
| 433 | errln("Differences for ULOC_TRADITIONAL_CHINESE Locale"); |
| 434 | } |
| 435 | |
| 436 | |
| 437 | if (strcmp(Locale::getCanada().getName(), ULOC_CANADA) != 0) { |
| 438 | errln("Differences for ULOC_CANADA Locale"); |
| 439 | } |
| 440 | if (strcmp(Locale::getCanadaFrench().getName(), ULOC_CANADA_FRENCH) != 0) { |
| 441 | errln("Differences for ULOC_CANADA_FRENCH Locale"); |
| 442 | } |
| 443 | if (strcmp(Locale::getChina().getName(), ULOC_CHINA) != 0) { |
| 444 | errln("Differences for ULOC_CHINA Locale"); |
| 445 | } |
| 446 | if (strcmp(Locale::getPRC().getName(), ULOC_PRC) != 0) { |
| 447 | errln("Differences for ULOC_PRC Locale"); |
| 448 | } |
| 449 | if (strcmp(Locale::getFrance().getName(), ULOC_FRANCE) != 0) { |
| 450 | errln("Differences for ULOC_FRANCE Locale"); |
| 451 | } |
| 452 | if (strcmp(Locale::getGermany().getName(), ULOC_GERMANY) != 0) { |
| 453 | errln("Differences for ULOC_GERMANY Locale"); |
| 454 | } |
| 455 | if (strcmp(Locale::getItaly().getName(), ULOC_ITALY) != 0) { |
| 456 | errln("Differences for ULOC_ITALY Locale"); |
| 457 | } |
| 458 | if (strcmp(Locale::getJapan().getName(), ULOC_JAPAN) != 0) { |
| 459 | errln("Differences for ULOC_JAPAN Locale"); |
| 460 | } |
| 461 | if (strcmp(Locale::getKorea().getName(), ULOC_KOREA) != 0) { |
| 462 | errln("Differences for ULOC_KOREA Locale"); |
| 463 | } |
| 464 | if (strcmp(Locale::getTaiwan().getName(), ULOC_TAIWAN) != 0) { |
| 465 | errln("Differences for ULOC_TAIWAN Locale"); |
| 466 | } |
| 467 | if (strcmp(Locale::getUK().getName(), ULOC_UK) != 0) { |
| 468 | errln("Differences for ULOC_UK Locale"); |
| 469 | } |
| 470 | if (strcmp(Locale::getUS().getName(), ULOC_US) != 0) { |
| 471 | errln("Differences for ULOC_US Locale"); |
| 472 | } |
| 473 | } |
| 474 | |
| 475 | |
| 476 | void LocaleTest::TestSimpleResourceInfo() { |
| 477 | UnicodeString temp; |
| 478 | char temp2[20]; |
| 479 | UErrorCode err = U_ZERO_ERROR; |
| 480 | int32_t i = 0; |
| 481 | |
| 482 | for (i = 0; i <= MAX_LOCALES; i++) { |
| 483 | Locale testLocale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]); |
| 484 | logln("Testing " + (temp=testLocale.getName()) + "..."); |
| 485 | |
| 486 | if ( (temp=testLocale.getISO3Language()) != (dataTable[LANG3][i])) |
| 487 | errln(" ISO-3 language code mismatch: " + temp |
| 488 | + " versus " + dataTable[LANG3][i]); |
| 489 | if ( (temp=testLocale.getISO3Country()) != (dataTable[CTRY3][i])) |
| 490 | errln(" ISO-3 country code mismatch: " + temp |
| 491 | + " versus " + dataTable[CTRY3][i]); |
| 492 | |
| 493 | sprintf(temp2, "%x", (int)testLocale.getLCID()); |
| 494 | if (UnicodeString(temp2) != dataTable[LCID][i]) |
| 495 | errln((UnicodeString)" LCID mismatch: " + temp2 + " versus " |
| 496 | + dataTable[LCID][i]); |
| 497 | |
| 498 | if(U_FAILURE(err)) |
| 499 | { |
| 500 | errln((UnicodeString)"Some error on number " + i + u_errorName(err)); |
| 501 | } |
| 502 | err = U_ZERO_ERROR; |
| 503 | } |
| 504 | |
| 505 | Locale locale("en"); |
| 506 | if(strcmp(locale.getName(), "en") != 0|| |
| 507 | strcmp(locale.getLanguage(), "en") != 0) { |
| 508 | errln("construction of Locale(en) failed\n"); |
| 509 | } |
| 510 | /*-----*/ |
| 511 | |
| 512 | } |
| 513 | |
| 514 | /* |
| 515 | * Jitterbug 2439 -- markus 20030425 |
| 516 | * |
| 517 | * The lookup of display names must not fall back through the default |
| 518 | * locale because that yields useless results. |
| 519 | */ |
| 520 | void |
| 521 | LocaleTest::TestDisplayNames() |
| 522 | { |
| 523 | Locale english("en", "US"); |
| 524 | Locale french("fr", "FR"); |
| 525 | Locale croatian("ca", "ES"); |
| 526 | Locale greek("el", "GR"); |
| 527 | |
| 528 | logln(" In locale = en_US..."); |
| 529 | doTestDisplayNames(english, DLANG_EN); |
| 530 | logln(" In locale = fr_FR..."); |
| 531 | doTestDisplayNames(french, DLANG_FR); |
| 532 | logln(" In locale = ca_ES..."); |
| 533 | doTestDisplayNames(croatian, DLANG_CA); |
| 534 | logln(" In locale = el_GR..."); |
| 535 | doTestDisplayNames(greek, DLANG_EL); |
| 536 | |
| 537 | UnicodeString s; |
| 538 | UErrorCode status = U_ZERO_ERROR; |
| 539 | |
| 540 | #if !UCONFIG_NO_FORMATTING |
| 541 | DecimalFormatSymbols symb(status); |
| 542 | /* Check to see if ICU supports this locale */ |
| 543 | if (symb.getLocale(ULOC_VALID_LOCALE, status) != Locale("root")) { |
| 544 | /* test that the default locale has a display name for its own language */ |
| 545 | /* Currently, there is no language information in the "tl" data file so this test will fail if default locale is "tl" */ |
| 546 | if (uprv_strcmp(Locale().getLanguage(), "tl") != 0) { |
| 547 | Locale().getDisplayLanguage(Locale(), s); |
| 548 | if(s.length()<=3 && s.charAt(0)<=0x7f) { |
| 549 | /* check <=3 to reject getting the language code as a display name */ |
| 550 | dataerrln("unable to get a display string for the language of the default locale: " + s); |
| 551 | } |
| 552 | |
| 553 | /* |
| 554 | * API coverage improvements: call |
| 555 | * Locale::getDisplayLanguage(UnicodeString &) and |
| 556 | * Locale::getDisplayCountry(UnicodeString &) |
| 557 | */ |
| 558 | s.remove(); |
| 559 | Locale().getDisplayLanguage(s); |
| 560 | if(s.length()<=3 && s.charAt(0)<=0x7f) { |
| 561 | dataerrln("unable to get a display string for the language of the default locale [2]: " + s); |
| 562 | } |
| 563 | } |
| 564 | } |
| 565 | else { |
| 566 | logln("Default locale %s is unsupported by ICU\n", Locale().getName()); |
| 567 | } |
| 568 | s.remove(); |
| 569 | #endif |
| 570 | |
| 571 | french.getDisplayCountry(s); |
| 572 | if(s.isEmpty()) { |
| 573 | errln("unable to get any default-locale display string for the country of fr_FR\n"); |
| 574 | } |
| 575 | s.remove(); |
| 576 | Locale("zh", "Hant").getDisplayScript(s); |
| 577 | if(s.isEmpty()) { |
| 578 | errln("unable to get any default-locale display string for the country of zh_Hant\n"); |
| 579 | } |
| 580 | } |
| 581 | |
| 582 | void LocaleTest::TestSimpleObjectStuff() { |
| 583 | Locale test1("aa", "AA"); |
| 584 | Locale test2("aa", "AA"); |
| 585 | Locale test3(test1); |
| 586 | Locale test4("zz", "ZZ"); |
| 587 | Locale test5("aa", "AA", ""); |
| 588 | Locale test6("aa", "AA", "ANTARES"); |
| 589 | Locale test7("aa", "AA", "JUPITER"); |
| 590 | Locale test8 = Locale::createFromName("aa-aa-jupiTER"); // was "aa-aa.utf8@jupiter" but in 3.0 getName won't normalize that |
| 591 | |
| 592 | // now list them all for debugging usage. |
| 593 | test_dumpLocale(test1); |
| 594 | test_dumpLocale(test2); |
| 595 | test_dumpLocale(test3); |
| 596 | test_dumpLocale(test4); |
| 597 | test_dumpLocale(test5); |
| 598 | test_dumpLocale(test6); |
| 599 | test_dumpLocale(test7); |
| 600 | test_dumpLocale(test8); |
| 601 | |
| 602 | // Make sure things compare to themselves! |
| 603 | test_assert(test1 == test1); |
| 604 | test_assert(test2 == test2); |
| 605 | test_assert(test3 == test3); |
| 606 | test_assert(test4 == test4); |
| 607 | test_assert(test5 == test5); |
| 608 | test_assert(test6 == test6); |
| 609 | test_assert(test7 == test7); |
| 610 | test_assert(test8 == test8); |
| 611 | |
| 612 | // make sure things are not equal to themselves. |
| 613 | test_assert(!(test1 != test1)); |
| 614 | test_assert(!(test2 != test2)); |
| 615 | test_assert(!(test3 != test3)); |
| 616 | test_assert(!(test4 != test4)); |
| 617 | test_assert(!(test5 != test5)); |
| 618 | test_assert(!(test6 != test6)); |
| 619 | test_assert(!(test7 != test7)); |
| 620 | test_assert(!(test8 != test8)); |
| 621 | |
| 622 | // make sure things that are equal to each other don't show up as unequal. |
| 623 | test_assert(!(test1 != test2)); |
| 624 | test_assert(!(test2 != test1)); |
| 625 | test_assert(!(test1 != test3)); |
| 626 | test_assert(!(test2 != test3)); |
| 627 | test_assert(test5 == test1); |
| 628 | test_assert(test6 != test2); |
| 629 | test_assert(test6 != test5); |
| 630 | |
| 631 | test_assert(test6 != test7); |
| 632 | |
| 633 | // test for things that shouldn't compare equal. |
| 634 | test_assert(!(test1 == test4)); |
| 635 | test_assert(!(test2 == test4)); |
| 636 | test_assert(!(test3 == test4)); |
| 637 | |
| 638 | test_assert(test7 == test8); |
| 639 | |
| 640 | // test for hash codes to be the same. |
| 641 | int32_t hash1 = test1.hashCode(); |
| 642 | int32_t hash2 = test2.hashCode(); |
| 643 | int32_t hash3 = test3.hashCode(); |
| 644 | |
| 645 | test_assert(hash1 == hash2); |
| 646 | test_assert(hash1 == hash3); |
| 647 | test_assert(hash2 == hash3); |
| 648 | |
| 649 | // test that the assignment operator works. |
| 650 | test4 = test1; |
| 651 | logln("test4=test1;"); |
| 652 | test_dumpLocale(test4); |
| 653 | test_assert(test4 == test4); |
| 654 | |
| 655 | test_assert(!(test1 != test4)); |
| 656 | test_assert(!(test2 != test4)); |
| 657 | test_assert(!(test3 != test4)); |
| 658 | test_assert(test1 == test4); |
| 659 | test_assert(test4 == test1); |
| 660 | |
| 661 | // test assignments with a variant |
| 662 | logln("test7 = test6"); |
| 663 | test7 = test6; |
| 664 | test_dumpLocale(test7); |
| 665 | test_assert(test7 == test7); |
| 666 | test_assert(test7 == test6); |
| 667 | test_assert(test7 != test5); |
| 668 | |
| 669 | logln("test6 = test1"); |
| 670 | test6=test1; |
| 671 | test_dumpLocale(test6); |
| 672 | test_assert(test6 != test7); |
| 673 | test_assert(test6 == test1); |
| 674 | test_assert(test6 == test6); |
| 675 | } |
| 676 | |
| 677 | // A class which exposes constructors that are implemented in terms of the POSIX parsing code. |
| 678 | class POSIXLocale : public Locale |
| 679 | { |
| 680 | public: |
| 681 | POSIXLocale(const UnicodeString& l) |
| 682 | :Locale() |
| 683 | { |
| 684 | char *ch; |
| 685 | ch = new char[l.length() + 1]; |
| 686 | ch[l.extract(0, 0x7fffffff, ch, "")] = 0; |
| 687 | setFromPOSIXID(ch); |
| 688 | delete [] ch; |
| 689 | } |
| 690 | POSIXLocale(const char *l) |
| 691 | :Locale() |
| 692 | { |
| 693 | setFromPOSIXID(l); |
| 694 | } |
| 695 | }; |
| 696 | |
| 697 | void LocaleTest::TestPOSIXParsing() |
| 698 | { |
| 699 | POSIXLocale test1("ab_AB"); |
| 700 | POSIXLocale test2(UnicodeString("ab_AB")); |
| 701 | Locale test3("ab","AB"); |
| 702 | |
| 703 | POSIXLocale test4("ab_AB_Antares"); |
| 704 | POSIXLocale test5(UnicodeString("ab_AB_Antares")); |
| 705 | Locale test6("ab", "AB", "Antares"); |
| 706 | |
| 707 | test_dumpLocale(test1); |
| 708 | test_dumpLocale(test2); |
| 709 | test_dumpLocale(test3); |
| 710 | test_dumpLocale(test4); |
| 711 | test_dumpLocale(test5); |
| 712 | test_dumpLocale(test6); |
| 713 | |
| 714 | test_assert(test1 == test1); |
| 715 | |
| 716 | test_assert(test1 == test2); |
| 717 | test_assert(test2 == test3); |
| 718 | test_assert(test3 == test1); |
| 719 | |
| 720 | test_assert(test4 == test5); |
| 721 | test_assert(test5 == test6); |
| 722 | test_assert(test6 == test4); |
| 723 | |
| 724 | test_assert(test1 != test4); |
| 725 | test_assert(test5 != test3); |
| 726 | test_assert(test5 != test2); |
| 727 | |
| 728 | int32_t hash1 = test1.hashCode(); |
| 729 | int32_t hash2 = test2.hashCode(); |
| 730 | int32_t hash3 = test3.hashCode(); |
| 731 | |
| 732 | test_assert(hash1 == hash2); |
| 733 | test_assert(hash2 == hash3); |
| 734 | test_assert(hash3 == hash1); |
| 735 | } |
| 736 | |
| 737 | void LocaleTest::TestGetAvailableLocales() |
| 738 | { |
| 739 | int32_t locCount = 0; |
| 740 | const Locale* locList = Locale::getAvailableLocales(locCount); |
| 741 | |
| 742 | if (locCount == 0) |
| 743 | dataerrln("getAvailableLocales() returned an empty list!"); |
| 744 | else { |
| 745 | logln(UnicodeString("Number of locales returned = ") + locCount); |
| 746 | UnicodeString temp; |
| 747 | for(int32_t i = 0; i < locCount; ++i) |
| 748 | logln(locList[i].getName()); |
| 749 | } |
| 750 | // I have no idea how to test this function... |
| 751 | } |
| 752 | |
| 753 | // This test isn't applicable anymore - getISO3Language is |
| 754 | // independent of the data directory |
| 755 | void LocaleTest::TestDataDirectory() |
| 756 | { |
| 757 | /* |
| 758 | char oldDirectory[80]; |
| 759 | const char* temp; |
| 760 | UErrorCode err = U_ZERO_ERROR; |
| 761 | UnicodeString testValue; |
| 762 | |
| 763 | temp = Locale::getDataDirectory(); |
| 764 | strcpy(oldDirectory, temp); |
| 765 | logln(UnicodeString("oldDirectory = ") + oldDirectory); |
| 766 | |
| 767 | Locale test(Locale::US); |
| 768 | test.getISO3Language(testValue); |
| 769 | logln("first fetch of language retrieved " + testValue); |
| 770 | if (testValue != "eng") |
| 771 | errln("Initial check of ISO3 language failed: expected \"eng\", got \"" + testValue + "\""); |
| 772 | |
| 773 | { |
| 774 | char *path; |
| 775 | path=IntlTest::getTestDirectory(); |
| 776 | Locale::setDataDirectory( path ); |
| 777 | } |
| 778 | |
| 779 | test.getISO3Language(testValue); |
| 780 | logln("second fetch of language retrieved " + testValue); |
| 781 | if (testValue != "xxx") |
| 782 | errln("setDataDirectory() failed: expected \"xxx\", got \"" + testValue + "\""); |
| 783 | |
| 784 | Locale::setDataDirectory(oldDirectory); |
| 785 | test.getISO3Language(testValue); |
| 786 | logln("third fetch of language retrieved " + testValue); |
| 787 | if (testValue != "eng") |
| 788 | errln("get/setDataDirectory() failed: expected \"eng\", got \"" + testValue + "\""); |
| 789 | */ |
| 790 | } |
| 791 | |
| 792 | //=========================================================== |
| 793 | |
| 794 | void LocaleTest::doTestDisplayNames(Locale& displayLocale, int32_t compareIndex) { |
| 795 | UnicodeString temp; |
| 796 | |
| 797 | for (int32_t i = 0; i <= MAX_LOCALES; i++) { |
| 798 | Locale testLocale(""); |
| 799 | if (rawData[SCRIPT][i] && rawData[SCRIPT][i][0] != 0) { |
| 800 | testLocale = Locale(rawData[LANG][i], rawData[SCRIPT][i], rawData[CTRY][i], rawData[VAR][i]); |
| 801 | } |
| 802 | else { |
| 803 | testLocale = Locale(rawData[LANG][i], rawData[CTRY][i], rawData[VAR][i]); |
| 804 | } |
| 805 | logln(" Testing " + (temp=testLocale.getName()) + "..."); |
| 806 | |
| 807 | UnicodeString testLang; |
| 808 | UnicodeString testScript; |
| 809 | UnicodeString testCtry; |
| 810 | UnicodeString testVar; |
| 811 | UnicodeString testName; |
| 812 | |
| 813 | testLocale.getDisplayLanguage(displayLocale, testLang); |
| 814 | testLocale.getDisplayScript(displayLocale, testScript); |
| 815 | testLocale.getDisplayCountry(displayLocale, testCtry); |
| 816 | testLocale.getDisplayVariant(displayLocale, testVar); |
| 817 | testLocale.getDisplayName(displayLocale, testName); |
| 818 | |
| 819 | UnicodeString expectedLang; |
| 820 | UnicodeString expectedScript; |
| 821 | UnicodeString expectedCtry; |
| 822 | UnicodeString expectedVar; |
| 823 | UnicodeString expectedName; |
| 824 | |
| 825 | expectedLang = dataTable[compareIndex][i]; |
| 826 | if (expectedLang.length() == 0) |
| 827 | expectedLang = dataTable[DLANG_EN][i]; |
| 828 | |
| 829 | expectedScript = dataTable[compareIndex + 1][i]; |
| 830 | if (expectedScript.length() == 0) |
| 831 | expectedScript = dataTable[DSCRIPT_EN][i]; |
| 832 | |
| 833 | expectedCtry = dataTable[compareIndex + 2][i]; |
| 834 | if (expectedCtry.length() == 0) |
| 835 | expectedCtry = dataTable[DCTRY_EN][i]; |
| 836 | |
| 837 | expectedVar = dataTable[compareIndex + 3][i]; |
| 838 | if (expectedVar.length() == 0) |
| 839 | expectedVar = dataTable[DVAR_EN][i]; |
| 840 | |
| 841 | expectedName = dataTable[compareIndex + 4][i]; |
| 842 | if (expectedName.length() == 0) |
| 843 | expectedName = dataTable[DNAME_EN][i]; |
| 844 | |
| 845 | if (testLang != expectedLang) |
| 846 | dataerrln("Display language (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testLang + " expected " + expectedLang); |
| 847 | if (testScript != expectedScript) |
| 848 | dataerrln("Display script (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testScript + " expected " + expectedScript); |
| 849 | if (testCtry != expectedCtry) |
| 850 | dataerrln("Display country (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testCtry + " expected " + expectedCtry); |
| 851 | if (testVar != expectedVar) |
| 852 | dataerrln("Display variant (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testVar + " expected " + expectedVar); |
| 853 | if (testName != expectedName) |
| 854 | dataerrln("Display name (" + UnicodeString(displayLocale.getName()) + ") of (" + UnicodeString(testLocale.getName()) + ") got " + testName + " expected " + expectedName); |
| 855 | } |
| 856 | } |
| 857 | |
| 858 | //--------------------------------------------------- |
| 859 | // table of valid data |
| 860 | //--------------------------------------------------- |
| 861 | |
| 862 | |
| 863 | |
| 864 | void LocaleTest::setUpDataTable() |
| 865 | { |
| 866 | if (dataTable == 0) { |
| 867 | dataTable = new UnicodeString*[33]; |
| 868 | |
| 869 | for (int32_t i = 0; i < 33; i++) { |
| 870 | dataTable[i] = new UnicodeString[8]; |
| 871 | for (int32_t j = 0; j < 8; j++) { |
| 872 | dataTable[i][j] = CharsToUnicodeString(rawData[i][j]); |
| 873 | } |
| 874 | } |
| 875 | } |
| 876 | } |
| 877 | |
| 878 | // ==================== |
| 879 | |
| 880 | |
| 881 | /** |
| 882 | * @bug 4011756 4011380 |
| 883 | */ |
| 884 | void |
| 885 | LocaleTest::TestISO3Fallback() |
| 886 | { |
| 887 | Locale test("xx", "YY"); |
| 888 | |
| 889 | const char * result; |
| 890 | |
| 891 | result = test.getISO3Language(); |
| 892 | |
| 893 | // Conform to C API usage |
| 894 | |
| 895 | if (!result || (result[0] != 0)) |
| 896 | errln("getISO3Language() on xx_YY returned " + UnicodeString(result) + " instead of \"\""); |
| 897 | |
| 898 | result = test.getISO3Country(); |
| 899 | |
| 900 | if (!result || (result[0] != 0)) |
| 901 | errln("getISO3Country() on xx_YY returned " + UnicodeString(result) + " instead of \"\""); |
| 902 | } |
| 903 | |
| 904 | /** |
| 905 | * @bug 4106155 4118587 |
| 906 | */ |
| 907 | void |
| 908 | LocaleTest::TestGetLangsAndCountries() |
| 909 | { |
| 910 | // It didn't seem right to just do an exhaustive test of everything here, so I check |
| 911 | // for the following things: |
| 912 | // 1) Does each list have the right total number of entries? |
| 913 | // 2) Does each list contain certain language and country codes we think are important |
| 914 | // (the G7 countries, plus a couple others)? |
| 915 | // 3) Does each list have every entry formatted correctly? (i.e., two characters, |
| 916 | // all lower case for the language codes, all upper case for the country codes) |
| 917 | // 4) Is each list in sorted order? |
| 918 | int32_t testCount = 0; |
| 919 | const char * const * test = Locale::getISOLanguages(); |
| 920 | const char spotCheck1[ ][4] = { "en", "es", "fr", "de", "it", |
| 921 | "ja", "ko", "zh", "th", "he", |
| 922 | "id", "iu", "ug", "yi", "za" }; |
| 923 | |
| 924 | int32_t i; |
| 925 | |
| 926 | for(testCount = 0;test[testCount];testCount++) |
| 927 | ; |
| 928 | |
| 929 | /* TODO: Change this test to be more like the cloctst version? */ |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 930 | if (testCount != 595) |
| 931 | errln("Expected getISOLanguages() to return 595 languages; it returned %d", testCount); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 932 | else { |
| 933 | for (i = 0; i < 15; i++) { |
| 934 | int32_t j; |
| 935 | for (j = 0; j < testCount; j++) |
| 936 | if (uprv_strcmp(test[j],spotCheck1[i])== 0) |
| 937 | break; |
| 938 | if (j == testCount || (uprv_strcmp(test[j],spotCheck1[i])!=0)) |
| 939 | errln("Couldn't find " + (UnicodeString)spotCheck1[i] + " in language list."); |
| 940 | } |
| 941 | } |
| 942 | for (i = 0; i < testCount; i++) { |
| 943 | UnicodeString testee(test[i],""); |
| 944 | UnicodeString lc(test[i],""); |
| 945 | if (testee != lc.toLower()) |
| 946 | errln(lc + " is not all lower case."); |
| 947 | if ( (testee.length() != 2) && (testee.length() != 3)) |
| 948 | errln(testee + " is not two or three characters long."); |
| 949 | if (i > 0 && testee.compare(test[i - 1]) <= 0) |
| 950 | errln(testee + " appears in an out-of-order position in the list."); |
| 951 | } |
| 952 | |
| 953 | test = Locale::getISOCountries(); |
| 954 | UnicodeString spotCheck2 [] = { "US", "CA", "GB", "FR", "DE", |
| 955 | "IT", "JP", "KR", "CN", "TW", |
| 956 | "TH" }; |
| 957 | int32_t spot2Len = 11; |
| 958 | for(testCount=0;test[testCount];testCount++) |
| 959 | ; |
| 960 | |
| 961 | if (testCount != 253){ |
| 962 | errln("Expected getISOCountries to return 253 countries; it returned %d", testCount); |
| 963 | }else { |
| 964 | for (i = 0; i < spot2Len; i++) { |
| 965 | int32_t j; |
| 966 | for (j = 0; j < testCount; j++) |
| 967 | { |
| 968 | UnicodeString testee(test[j],""); |
| 969 | |
| 970 | if (testee == spotCheck2[i]) |
| 971 | break; |
| 972 | } |
| 973 | UnicodeString testee(test[j],""); |
| 974 | if (j == testCount || testee != spotCheck2[i]) |
| 975 | errln("Couldn't find " + spotCheck2[i] + " in country list."); |
| 976 | } |
| 977 | } |
| 978 | for (i = 0; i < testCount; i++) { |
| 979 | UnicodeString testee(test[i],""); |
| 980 | UnicodeString uc(test[i],""); |
| 981 | if (testee != uc.toUpper()) |
| 982 | errln(testee + " is not all upper case."); |
| 983 | if (testee.length() != 2) |
| 984 | errln(testee + " is not two characters long."); |
| 985 | if (i > 0 && testee.compare(test[i - 1]) <= 0) |
| 986 | errln(testee + " appears in an out-of-order position in the list."); |
| 987 | } |
| 988 | |
| 989 | // This getAvailableLocales and getISO3Language |
| 990 | { |
| 991 | int32_t numOfLocales; |
| 992 | Locale enLoc ("en"); |
| 993 | const Locale *pLocales = Locale::getAvailableLocales(numOfLocales); |
| 994 | |
| 995 | for (int i = 0; i < numOfLocales; i++) { |
| 996 | const Locale &loc(pLocales[i]); |
| 997 | UnicodeString name; |
| 998 | char szName[200]; |
| 999 | |
| 1000 | loc.getDisplayName (enLoc, name); |
| 1001 | name.extract (0, 200, szName, sizeof(szName)); |
| 1002 | |
| 1003 | if (strlen(loc.getISO3Language()) == 0) { |
| 1004 | errln("getISO3Language() returned an empty string for: " + name); |
| 1005 | } |
| 1006 | } |
| 1007 | } |
| 1008 | } |
| 1009 | |
| 1010 | /** |
| 1011 | * @bug 4118587 |
| 1012 | */ |
| 1013 | void |
| 1014 | LocaleTest::TestSimpleDisplayNames() |
| 1015 | { |
| 1016 | // This test is different from TestDisplayNames because TestDisplayNames checks |
| 1017 | // fallback behavior, combination of language and country names to form locale |
| 1018 | // names, and other stuff like that. This test just checks specific language |
| 1019 | // and country codes to make sure we have the correct names for them. |
| 1020 | char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za" }; |
| 1021 | UnicodeString languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish", |
| 1022 | "Zhuang" }; |
| 1023 | |
| 1024 | for (int32_t i = 0; i < 6; i++) { |
| 1025 | UnicodeString test; |
| 1026 | Locale l(languageCodes[i], "", ""); |
| 1027 | l.getDisplayLanguage(Locale::getUS(), test); |
| 1028 | if (test != languageNames[i]) |
| 1029 | dataerrln("Got wrong display name for " + UnicodeString(languageCodes[i]) + ": Expected \"" + |
| 1030 | languageNames[i] + "\", got \"" + test + "\"."); |
| 1031 | } |
| 1032 | } |
| 1033 | |
| 1034 | /** |
| 1035 | * @bug 4118595 |
| 1036 | */ |
| 1037 | void |
| 1038 | LocaleTest::TestUninstalledISO3Names() |
| 1039 | { |
| 1040 | // This test checks to make sure getISO3Language and getISO3Country work right |
| 1041 | // even for locales that are not installed. |
| 1042 | const char iso2Languages [][4] = { "am", "ba", "fy", "mr", "rn", |
| 1043 | "ss", "tw", "zu" }; |
| 1044 | const char iso3Languages [][5] = { "amh", "bak", "fry", "mar", "run", |
| 1045 | "ssw", "twi", "zul" }; |
| 1046 | |
| 1047 | int32_t i; |
| 1048 | |
| 1049 | for (i = 0; i < 8; i++) { |
| 1050 | UErrorCode err = U_ZERO_ERROR; |
| 1051 | |
| 1052 | UnicodeString test; |
| 1053 | Locale l(iso2Languages[i], "", ""); |
| 1054 | test = l.getISO3Language(); |
| 1055 | if((test != iso3Languages[i]) || U_FAILURE(err)) |
| 1056 | errln("Got wrong ISO3 code for " + UnicodeString(iso2Languages[i]) + ": Expected \"" + |
| 1057 | iso3Languages[i] + "\", got \"" + test + "\"." + UnicodeString(u_errorName(err))); |
| 1058 | } |
| 1059 | |
| 1060 | char iso2Countries [][4] = { "AF", "BW", "KZ", "MO", "MN", |
| 1061 | "SB", "TC", "ZW" }; |
| 1062 | char iso3Countries [][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG", |
| 1063 | "SLB", "TCA", "ZWE" }; |
| 1064 | |
| 1065 | for (i = 0; i < 8; i++) { |
| 1066 | UErrorCode err = U_ZERO_ERROR; |
| 1067 | Locale l("", iso2Countries[i], ""); |
| 1068 | UnicodeString test(l.getISO3Country(), ""); |
| 1069 | if (test != iso3Countries[i]) |
| 1070 | errln("Got wrong ISO3 code for " + UnicodeString(iso2Countries[i]) + ": Expected \"" + |
| 1071 | UnicodeString(iso3Countries[i]) + "\", got \"" + test + "\"." + u_errorName(err)); |
| 1072 | } |
| 1073 | } |
| 1074 | |
| 1075 | /** |
| 1076 | * @bug 4092475 |
| 1077 | * I could not reproduce this bug. I'm pretty convinced it was fixed with the |
| 1078 | * big locale-data reorg of 10/28/97. The lookup logic for language and country |
| 1079 | * display names was also changed at that time in that check-in. --rtg 3/20/98 |
| 1080 | */ |
| 1081 | void |
| 1082 | LocaleTest::TestAtypicalLocales() |
| 1083 | { |
| 1084 | Locale localesToTest [] = { Locale("de", "CA"), |
| 1085 | Locale("ja", "ZA"), |
| 1086 | Locale("ru", "MX"), |
| 1087 | Locale("en", "FR"), |
| 1088 | Locale("es", "DE"), |
| 1089 | Locale("", "HR"), |
| 1090 | Locale("", "SE"), |
| 1091 | Locale("", "DO"), |
| 1092 | Locale("", "BE") }; |
| 1093 | |
| 1094 | UnicodeString englishDisplayNames [] = { "German (Canada)", |
| 1095 | "Japanese (South Africa)", |
| 1096 | "Russian (Mexico)", |
| 1097 | "English (France)", |
| 1098 | "Spanish (Germany)", |
| 1099 | "Unknown language (Croatia)", |
| 1100 | "Unknown language (Sweden)", |
| 1101 | "Unknown language (Dominican Republic)", |
| 1102 | "Unknown language (Belgium)" }; |
| 1103 | UnicodeString frenchDisplayNames []= { "allemand (Canada)", |
| 1104 | "japonais (Afrique du Sud)", |
| 1105 | "russe (Mexique)", |
| 1106 | "anglais (France)", |
| 1107 | "espagnol (Allemagne)", |
| 1108 | u"langue indéterminée (Croatie)", |
| 1109 | u"langue indéterminée (Suède)", |
| 1110 | u"langue indéterminée (République dominicaine)", |
| 1111 | u"langue indéterminée (Belgique)" }; |
| 1112 | UnicodeString spanishDisplayNames [] = { |
| 1113 | u"alemán (Canadá)", |
| 1114 | u"japonés (Sudáfrica)", |
| 1115 | u"ruso (México)", |
| 1116 | u"inglés (Francia)", |
| 1117 | u"español (Alemania)", |
| 1118 | "lengua desconocida (Croacia)", |
| 1119 | "lengua desconocida (Suecia)", |
| 1120 | u"lengua desconocida (República Dominicana)", |
| 1121 | u"lengua desconocida (Bélgica)" }; |
| 1122 | // De-Anglicizing root required the change from |
| 1123 | // English display names to ISO Codes - ram 2003/09/26 |
| 1124 | UnicodeString invDisplayNames [] = { "German (Canada)", |
| 1125 | "Japanese (South Africa)", |
| 1126 | "Russian (Mexico)", |
| 1127 | "English (France)", |
| 1128 | "Spanish (Germany)", |
| 1129 | "Unknown language (Croatia)", |
| 1130 | "Unknown language (Sweden)", |
| 1131 | "Unknown language (Dominican Republic)", |
| 1132 | "Unknown language (Belgium)" }; |
| 1133 | |
| 1134 | int32_t i; |
| 1135 | UErrorCode status = U_ZERO_ERROR; |
| 1136 | Locale saveLocale; |
| 1137 | Locale::setDefault(Locale::getUS(), status); |
| 1138 | for (i = 0; i < 9; ++i) { |
| 1139 | UnicodeString name; |
| 1140 | localesToTest[i].getDisplayName(Locale::getUS(), name); |
| 1141 | logln(name); |
| 1142 | if (name != englishDisplayNames[i]) |
| 1143 | { |
| 1144 | dataerrln("Lookup in English failed: expected \"" + englishDisplayNames[i] |
| 1145 | + "\", got \"" + name + "\""); |
| 1146 | logln("Locale name was-> " + (name=localesToTest[i].getName())); |
| 1147 | } |
| 1148 | } |
| 1149 | |
| 1150 | for (i = 0; i < 9; i++) { |
| 1151 | UnicodeString name; |
| 1152 | localesToTest[i].getDisplayName(Locale("es", "ES"), name); |
| 1153 | logln(name); |
| 1154 | if (name != spanishDisplayNames[i]) |
| 1155 | dataerrln("Lookup in Spanish failed: expected \"" + spanishDisplayNames[i] |
| 1156 | + "\", got \"" + name + "\""); |
| 1157 | } |
| 1158 | |
| 1159 | for (i = 0; i < 9; i++) { |
| 1160 | UnicodeString name; |
| 1161 | localesToTest[i].getDisplayName(Locale::getFrance(), name); |
| 1162 | logln(name); |
| 1163 | if (name != frenchDisplayNames[i]) |
| 1164 | dataerrln("Lookup in French failed: expected \"" + frenchDisplayNames[i] |
| 1165 | + "\", got \"" + name + "\""); |
| 1166 | } |
| 1167 | |
| 1168 | for (i = 0; i < 9; i++) { |
| 1169 | UnicodeString name; |
| 1170 | localesToTest[i].getDisplayName(Locale("inv", "IN"), name); |
| 1171 | logln(name + " Locale fallback to be, and data fallback to root"); |
| 1172 | if (name != invDisplayNames[i]) |
| 1173 | dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i]) |
| 1174 | + "\", got \"" + prettify(name) + "\""); |
| 1175 | localesToTest[i].getDisplayName(Locale("inv", "BD"), name); |
| 1176 | logln(name + " Data fallback to root"); |
| 1177 | if (name != invDisplayNames[i]) |
| 1178 | dataerrln("Lookup in INV failed: expected \"" + prettify(invDisplayNames[i]) |
| 1179 | + "\", got \"" + prettify(name )+ "\""); |
| 1180 | } |
| 1181 | Locale::setDefault(saveLocale, status); |
| 1182 | } |
| 1183 | |
| 1184 | #if !UCONFIG_NO_FORMATTING |
| 1185 | |
| 1186 | /** |
| 1187 | * @bug 4135752 |
| 1188 | * This would be better tested by the LocaleDataTest. Will move it when I |
| 1189 | * get the LocaleDataTest working again. |
| 1190 | */ |
| 1191 | void |
| 1192 | LocaleTest::TestThaiCurrencyFormat() |
| 1193 | { |
| 1194 | UErrorCode status = U_ZERO_ERROR; |
| 1195 | DecimalFormat *thaiCurrency = (DecimalFormat*)NumberFormat::createCurrencyInstance( |
| 1196 | Locale("th", "TH"), status); |
| 1197 | UnicodeString posPrefix(u"\u0E3F"); |
| 1198 | UnicodeString temp; |
| 1199 | |
| 1200 | if(U_FAILURE(status) || !thaiCurrency) |
| 1201 | { |
| 1202 | dataerrln("Couldn't get th_TH currency -> " + UnicodeString(u_errorName(status))); |
| 1203 | return; |
| 1204 | } |
| 1205 | if (thaiCurrency->getPositivePrefix(temp) != posPrefix) |
| 1206 | errln("Thai currency prefix wrong: expected Baht sign, got \"" + |
| 1207 | thaiCurrency->getPositivePrefix(temp) + "\""); |
| 1208 | if (thaiCurrency->getPositiveSuffix(temp) != "") |
| 1209 | errln("Thai currency suffix wrong: expected \"\", got \"" + |
| 1210 | thaiCurrency->getPositiveSuffix(temp) + "\""); |
| 1211 | |
| 1212 | delete thaiCurrency; |
| 1213 | } |
| 1214 | |
| 1215 | /** |
| 1216 | * @bug 4122371 |
| 1217 | * Confirm that Euro support works. This test is pretty rudimentary; all it does |
| 1218 | * is check that any locales with the EURO variant format a number using the |
| 1219 | * Euro currency symbol. |
| 1220 | * |
| 1221 | * ASSUME: All locales encode the Euro character "\u20AC". |
| 1222 | * If this is changed to use the single-character Euro symbol, this |
| 1223 | * test must be updated. |
| 1224 | * |
| 1225 | */ |
| 1226 | void |
| 1227 | LocaleTest::TestEuroSupport() |
| 1228 | { |
| 1229 | UChar euro = 0x20ac; |
| 1230 | const UnicodeString EURO_CURRENCY(&euro, 1, 1); // Look for this UnicodeString in formatted Euro currency |
| 1231 | const char* localeArr[] = { |
| 1232 | "ca_ES", |
| 1233 | "de_AT", |
| 1234 | "de_DE", |
| 1235 | "de_LU", |
| 1236 | "el_GR", |
| 1237 | "en_BE", |
| 1238 | "en_IE", |
| 1239 | "en_GB@currency=EUR", |
| 1240 | "en_US@currency=EUR", |
| 1241 | "es_ES", |
| 1242 | "eu_ES", |
| 1243 | "fi_FI", |
| 1244 | "fr_BE", |
| 1245 | "fr_FR", |
| 1246 | "fr_LU", |
| 1247 | "ga_IE", |
| 1248 | "gl_ES", |
| 1249 | "it_IT", |
| 1250 | "nl_BE", |
| 1251 | "nl_NL", |
| 1252 | "pt_PT", |
| 1253 | NULL |
| 1254 | }; |
| 1255 | const char** locales = localeArr; |
| 1256 | |
| 1257 | UErrorCode status = U_ZERO_ERROR; |
| 1258 | |
| 1259 | UnicodeString temp; |
| 1260 | |
| 1261 | for (;*locales!=NULL;locales++) { |
| 1262 | Locale loc (*locales); |
| 1263 | UnicodeString temp; |
| 1264 | NumberFormat *nf = NumberFormat::createCurrencyInstance(loc, status); |
| 1265 | UnicodeString pos; |
| 1266 | |
| 1267 | if (U_FAILURE(status)) { |
| 1268 | dataerrln("Error calling NumberFormat::createCurrencyInstance(%s)", *locales); |
| 1269 | continue; |
| 1270 | } |
| 1271 | |
| 1272 | nf->format(271828.182845, pos); |
| 1273 | UnicodeString neg; |
| 1274 | nf->format(-271828.182845, neg); |
| 1275 | if (pos.indexOf(EURO_CURRENCY) >= 0 && |
| 1276 | neg.indexOf(EURO_CURRENCY) >= 0) { |
| 1277 | logln("Ok: " + (temp=loc.getName()) + |
| 1278 | ": " + pos + " / " + neg); |
| 1279 | } |
| 1280 | else { |
| 1281 | errln("Fail: " + (temp=loc.getName()) + |
| 1282 | " formats without " + EURO_CURRENCY + |
| 1283 | ": " + pos + " / " + neg + |
| 1284 | "\n*** THIS FAILURE MAY ONLY MEAN THAT LOCALE DATA HAS CHANGED ***"); |
| 1285 | } |
| 1286 | |
| 1287 | delete nf; |
| 1288 | } |
| 1289 | |
| 1290 | UnicodeString dollarStr("USD", ""), euroStr("EUR", ""), genericStr((UChar)0x00a4), resultStr; |
| 1291 | UChar tmp[4]; |
| 1292 | status = U_ZERO_ERROR; |
| 1293 | |
| 1294 | ucurr_forLocale("en_US", tmp, 4, &status); |
| 1295 | resultStr.setTo(tmp); |
| 1296 | if (dollarStr != resultStr) { |
| 1297 | errcheckln(status, "Fail: en_US didn't return USD - %s", u_errorName(status)); |
| 1298 | } |
| 1299 | ucurr_forLocale("en_US@currency=EUR", tmp, 4, &status); |
| 1300 | resultStr.setTo(tmp); |
| 1301 | if (euroStr != resultStr) { |
| 1302 | errcheckln(status, "Fail: en_US@currency=EUR didn't return EUR - %s", u_errorName(status)); |
| 1303 | } |
| 1304 | ucurr_forLocale("en_GB@currency=EUR", tmp, 4, &status); |
| 1305 | resultStr.setTo(tmp); |
| 1306 | if (euroStr != resultStr) { |
| 1307 | errcheckln(status, "Fail: en_GB@currency=EUR didn't return EUR - %s", u_errorName(status)); |
| 1308 | } |
| 1309 | ucurr_forLocale("en_US_Q", tmp, 4, &status); |
| 1310 | resultStr.setTo(tmp); |
| 1311 | if (dollarStr != resultStr) { |
| 1312 | errcheckln(status, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status)); |
| 1313 | } |
| 1314 | int32_t invalidLen = ucurr_forLocale("en_QQ", tmp, 4, &status); |
| 1315 | if (invalidLen || U_SUCCESS(status)) { |
| 1316 | errln("Fail: en_QQ didn't return NULL"); |
| 1317 | } |
| 1318 | |
| 1319 | // The currency keyword value is as long as the destination buffer. |
| 1320 | // It should detect the overflow internally, and default to the locale's currency. |
| 1321 | tmp[0] = u'¤'; |
| 1322 | status = U_ZERO_ERROR; |
| 1323 | int32_t length = ucurr_forLocale("en_US@currency=euro", tmp, 4, &status); |
| 1324 | if (U_FAILURE(status) || dollarStr != UnicodeString(tmp, length)) { |
| 1325 | if (U_SUCCESS(status) && tmp[0] == u'¤') { |
| 1326 | errln("Fail: ucurr_forLocale(en_US@currency=euro) succeeded without writing output"); |
| 1327 | } else { |
| 1328 | errln("Fail: ucurr_forLocale(en_US@currency=euro) != USD - %s", u_errorName(status)); |
| 1329 | } |
| 1330 | } |
| 1331 | } |
| 1332 | |
| 1333 | #endif |
| 1334 | |
| 1335 | /** |
| 1336 | * @bug 4139504 |
| 1337 | * toString() doesn't work with language_VARIANT. |
| 1338 | */ |
| 1339 | void |
| 1340 | LocaleTest::TestToString() { |
| 1341 | Locale DATA [] = { |
| 1342 | Locale("xx", "", ""), |
| 1343 | Locale("", "YY", ""), |
| 1344 | Locale("", "", "ZZ"), |
| 1345 | Locale("xx", "YY", ""), |
| 1346 | Locale("xx", "", "ZZ"), |
| 1347 | Locale("", "YY", "ZZ"), |
| 1348 | Locale("xx", "YY", "ZZ"), |
| 1349 | }; |
| 1350 | |
| 1351 | const char DATA_S [][20] = { |
| 1352 | "xx", |
| 1353 | "_YY", |
| 1354 | "__ZZ", |
| 1355 | "xx_YY", |
| 1356 | "xx__ZZ", |
| 1357 | "_YY_ZZ", |
| 1358 | "xx_YY_ZZ", |
| 1359 | }; |
| 1360 | |
| 1361 | for (int32_t i=0; i < 7; ++i) { |
| 1362 | const char *name; |
| 1363 | name = DATA[i].getName(); |
| 1364 | |
| 1365 | if (strcmp(name, DATA_S[i]) != 0) |
| 1366 | { |
| 1367 | errln("Fail: Locale.getName(), got:" + UnicodeString(name) + ", expected: " + DATA_S[i]); |
| 1368 | } |
| 1369 | else |
| 1370 | logln("Pass: Locale.getName(), got:" + UnicodeString(name) ); |
| 1371 | } |
| 1372 | } |
| 1373 | |
| 1374 | #if !UCONFIG_NO_FORMATTING |
| 1375 | |
| 1376 | /** |
| 1377 | * @bug 4139940 |
| 1378 | * Couldn't reproduce this bug -- probably was fixed earlier. |
| 1379 | * |
| 1380 | * ORIGINAL BUG REPORT: |
| 1381 | * -- basically, hungarian for monday shouldn't have an \u00f4 |
| 1382 | * (o circumflex)in it instead it should be an o with 2 inclined |
| 1383 | * (right) lines over it.. |
| 1384 | * |
| 1385 | * You may wonder -- why do all this -- why not just add a line to |
| 1386 | * LocaleData? Well, I could see by inspection that the locale file had the |
| 1387 | * right character in it, so I wanted to check the rest of the pipeline -- a |
| 1388 | * very remote possibility, but I wanted to be sure. The other possibility |
| 1389 | * is that something is wrong with the font mapping subsystem, but we can't |
| 1390 | * test that here. |
| 1391 | */ |
| 1392 | void |
| 1393 | LocaleTest::Test4139940() |
| 1394 | { |
| 1395 | Locale mylocale("hu", "", ""); |
| 1396 | UDate mydate = date(98,3,13); // A Monday |
| 1397 | UErrorCode status = U_ZERO_ERROR; |
| 1398 | SimpleDateFormat df_full("EEEE", mylocale, status); |
| 1399 | if(U_FAILURE(status)){ |
| 1400 | dataerrln(UnicodeString("Could not create SimpleDateFormat object for locale hu. Error: ") + UnicodeString(u_errorName(status))); |
| 1401 | return; |
| 1402 | } |
| 1403 | UnicodeString str; |
| 1404 | FieldPosition pos(FieldPosition::DONT_CARE); |
| 1405 | df_full.format(mydate, str, pos); |
| 1406 | // Make sure that o circumflex (\u00F4) is NOT there, and |
| 1407 | // o double acute (\u0151) IS. |
| 1408 | UChar ocf = 0x00f4; |
| 1409 | UChar oda = 0x0151; |
| 1410 | if (str.indexOf(oda) < 0 || str.indexOf(ocf) >= 0) { |
| 1411 | /* If the default locale is "th" this test will fail because of the buddhist calendar. */ |
| 1412 | if (strcmp(Locale::getDefault().getLanguage(), "th") != 0) { |
| 1413 | errln("Fail: Monday in Hungarian is wrong - oda's index is %d and ocf's is %d", |
| 1414 | str.indexOf(oda), str.indexOf(ocf)); |
| 1415 | } else { |
| 1416 | logln(UnicodeString("An error is produce in buddhist calendar.")); |
| 1417 | } |
| 1418 | logln(UnicodeString("String is: ") + str ); |
| 1419 | } |
| 1420 | } |
| 1421 | |
| 1422 | UDate |
| 1423 | LocaleTest::date(int32_t y, int32_t m, int32_t d, int32_t hr, int32_t min, int32_t sec) |
| 1424 | { |
| 1425 | UErrorCode status = U_ZERO_ERROR; |
| 1426 | Calendar *cal = Calendar::createInstance(status); |
| 1427 | if (cal == 0) |
| 1428 | return 0.0; |
| 1429 | cal->clear(); |
| 1430 | cal->set(1900 + y, m, d, hr, min, sec); // Add 1900 to follow java.util.Date protocol |
| 1431 | UDate dt = cal->getTime(status); |
| 1432 | if (U_FAILURE(status)) |
| 1433 | return 0.0; |
| 1434 | |
| 1435 | delete cal; |
| 1436 | return dt; |
| 1437 | } |
| 1438 | |
| 1439 | /** |
| 1440 | * @bug 4143951 |
| 1441 | * Russian first day of week should be Monday. Confirmed. |
| 1442 | */ |
| 1443 | void |
| 1444 | LocaleTest::Test4143951() |
| 1445 | { |
| 1446 | UErrorCode status = U_ZERO_ERROR; |
| 1447 | Calendar *cal = Calendar::createInstance(Locale("ru", "", ""), status); |
| 1448 | if(U_SUCCESS(status)) { |
| 1449 | if (cal->getFirstDayOfWeek(status) != UCAL_MONDAY) { |
| 1450 | dataerrln("Fail: First day of week in Russia should be Monday"); |
| 1451 | } |
| 1452 | } |
| 1453 | delete cal; |
| 1454 | } |
| 1455 | |
| 1456 | #endif |
| 1457 | |
| 1458 | /** |
| 1459 | * @bug 4147315 |
| 1460 | * java.util.Locale.getISO3Country() works wrong for non ISO-3166 codes. |
| 1461 | * Should throw an exception for unknown locales |
| 1462 | */ |
| 1463 | void |
| 1464 | LocaleTest::Test4147315() |
| 1465 | { |
| 1466 | UnicodeString temp; |
| 1467 | // Try with codes that are the wrong length but happen to match text |
| 1468 | // at a valid offset in the mapping table |
| 1469 | Locale locale("xxx", "CCC"); |
| 1470 | |
| 1471 | const char *result = locale.getISO3Country(); |
| 1472 | |
| 1473 | // Change to conform to C api usage |
| 1474 | if((result==NULL)||(result[0] != 0)) |
| 1475 | errln("ERROR: getISO3Country() returns: " + UnicodeString(result,"") + |
| 1476 | " for locale '" + (temp=locale.getName()) + "' rather than exception" ); |
| 1477 | } |
| 1478 | |
| 1479 | /** |
| 1480 | * @bug 4147317 |
| 1481 | * java.util.Locale.getISO3Language() works wrong for non ISO-3166 codes. |
| 1482 | * Should throw an exception for unknown locales |
| 1483 | */ |
| 1484 | void |
| 1485 | LocaleTest::Test4147317() |
| 1486 | { |
| 1487 | UnicodeString temp; |
| 1488 | // Try with codes that are the wrong length but happen to match text |
| 1489 | // at a valid offset in the mapping table |
| 1490 | Locale locale("xxx", "CCC"); |
| 1491 | |
| 1492 | const char *result = locale.getISO3Language(); |
| 1493 | |
| 1494 | // Change to conform to C api usage |
| 1495 | if((result==NULL)||(result[0] != 0)) |
| 1496 | errln("ERROR: getISO3Language() returns: " + UnicodeString(result,"") + |
| 1497 | " for locale '" + (temp=locale.getName()) + "' rather than exception" ); |
| 1498 | } |
| 1499 | |
| 1500 | /* |
| 1501 | * @bug 4147552 |
| 1502 | */ |
| 1503 | void |
| 1504 | LocaleTest::Test4147552() |
| 1505 | { |
| 1506 | Locale locales [] = { Locale("no", "NO"), |
| 1507 | Locale("no", "NO", "B"), |
| 1508 | Locale("no", "NO", "NY") |
| 1509 | }; |
| 1510 | |
| 1511 | UnicodeString edn("Norwegian (Norway, B)"); |
| 1512 | UnicodeString englishDisplayNames [] = { |
| 1513 | "Norwegian (Norway)", |
| 1514 | edn, |
| 1515 | // "Norwegian (Norway,B)", |
| 1516 | //"Norwegian (Norway,NY)" |
| 1517 | "Norwegian (Norway, NY)" |
| 1518 | }; |
| 1519 | UnicodeString ndn("norsk (Norge, B"); |
| 1520 | UnicodeString norwegianDisplayNames [] = { |
| 1521 | "norsk (Norge)", |
| 1522 | "norsk (Norge, B)", |
| 1523 | //ndn, |
| 1524 | "norsk (Noreg, NY)" |
| 1525 | //"Norsk (Noreg, Nynorsk)" |
| 1526 | }; |
| 1527 | UErrorCode status = U_ZERO_ERROR; |
| 1528 | |
| 1529 | Locale saveLocale; |
| 1530 | Locale::setDefault(Locale::getEnglish(), status); |
| 1531 | for (int32_t i = 0; i < 3; ++i) { |
| 1532 | Locale loc = locales[i]; |
| 1533 | UnicodeString temp; |
| 1534 | if (loc.getDisplayName(temp) != englishDisplayNames[i]) |
| 1535 | dataerrln("English display-name mismatch: expected " + |
| 1536 | englishDisplayNames[i] + ", got " + loc.getDisplayName(temp)); |
| 1537 | if (loc.getDisplayName(loc, temp) != norwegianDisplayNames[i]) |
| 1538 | dataerrln("Norwegian display-name mismatch: expected " + |
| 1539 | norwegianDisplayNames[i] + ", got " + |
| 1540 | loc.getDisplayName(loc, temp)); |
| 1541 | } |
| 1542 | Locale::setDefault(saveLocale, status); |
| 1543 | } |
| 1544 | |
| 1545 | void |
| 1546 | LocaleTest::TestVariantParsing() |
| 1547 | { |
| 1548 | Locale en_US_custom("en", "US", "De Anza_Cupertino_California_United States_Earth"); |
| 1549 | |
| 1550 | UnicodeString dispName("English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)"); |
| 1551 | UnicodeString dispVar("DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH"); |
| 1552 | |
| 1553 | UnicodeString got; |
| 1554 | |
| 1555 | en_US_custom.getDisplayVariant(Locale::getUS(), got); |
| 1556 | if(got != dispVar) { |
| 1557 | errln("FAIL: getDisplayVariant()"); |
| 1558 | errln("Wanted: " + dispVar); |
| 1559 | errln("Got : " + got); |
| 1560 | } |
| 1561 | |
| 1562 | en_US_custom.getDisplayName(Locale::getUS(), got); |
| 1563 | if(got != dispName) { |
| 1564 | dataerrln("FAIL: getDisplayName()"); |
| 1565 | dataerrln("Wanted: " + dispName); |
| 1566 | dataerrln("Got : " + got); |
| 1567 | } |
| 1568 | |
| 1569 | Locale shortVariant("fr", "FR", "foo"); |
| 1570 | shortVariant.getDisplayVariant(got); |
| 1571 | |
| 1572 | if(got != "FOO") { |
| 1573 | errln("FAIL: getDisplayVariant()"); |
| 1574 | errln("Wanted: foo"); |
| 1575 | errln("Got : " + got); |
| 1576 | } |
| 1577 | |
| 1578 | Locale bogusVariant("fr", "FR", "_foo"); |
| 1579 | bogusVariant.getDisplayVariant(got); |
| 1580 | |
| 1581 | if(got != "FOO") { |
| 1582 | errln("FAIL: getDisplayVariant()"); |
| 1583 | errln("Wanted: foo"); |
| 1584 | errln("Got : " + got); |
| 1585 | } |
| 1586 | |
| 1587 | Locale bogusVariant2("fr", "FR", "foo_"); |
| 1588 | bogusVariant2.getDisplayVariant(got); |
| 1589 | |
| 1590 | if(got != "FOO") { |
| 1591 | errln("FAIL: getDisplayVariant()"); |
| 1592 | errln("Wanted: foo"); |
| 1593 | errln("Got : " + got); |
| 1594 | } |
| 1595 | |
| 1596 | Locale bogusVariant3("fr", "FR", "_foo_"); |
| 1597 | bogusVariant3.getDisplayVariant(got); |
| 1598 | |
| 1599 | if(got != "FOO") { |
| 1600 | errln("FAIL: getDisplayVariant()"); |
| 1601 | errln("Wanted: foo"); |
| 1602 | errln("Got : " + got); |
| 1603 | } |
| 1604 | } |
| 1605 | |
| 1606 | void LocaleTest::Test20639_DeprecatesISO3Language() { |
| 1607 | IcuTestErrorCode status(*this, "Test20639_DeprecatesISO3Language"); |
| 1608 | |
| 1609 | const struct TestCase { |
| 1610 | const char* localeName; |
| 1611 | const char* expectedISO3Language; |
| 1612 | } cases[] = { |
| 1613 | {"nb", "nob"}, |
| 1614 | {"no", "nor"}, // why not nob? |
| 1615 | {"he", "heb"}, |
| 1616 | {"iw", "heb"}, |
| 1617 | {"ro", "ron"}, |
| 1618 | {"mo", "mol"}, |
| 1619 | }; |
| 1620 | for (auto& cas : cases) { |
| 1621 | Locale loc(cas.localeName); |
| 1622 | const char* actual = loc.getISO3Language(); |
| 1623 | assertEquals(cas.localeName, cas.expectedISO3Language, actual); |
| 1624 | } |
| 1625 | } |
| 1626 | |
| 1627 | #if !UCONFIG_NO_FORMATTING |
| 1628 | |
| 1629 | /** |
| 1630 | * @bug 4105828 |
| 1631 | * Currency symbol in zh is wrong. We will test this at the NumberFormat |
| 1632 | * end to test the whole pipe. |
| 1633 | */ |
| 1634 | void |
| 1635 | LocaleTest::Test4105828() |
| 1636 | { |
| 1637 | Locale LOC [] = { Locale::getChinese(), Locale("zh", "CN", ""), |
| 1638 | Locale("zh", "TW", ""), Locale("zh", "HK", "") }; |
| 1639 | UErrorCode status = U_ZERO_ERROR; |
| 1640 | for (int32_t i = 0; i < 4; ++i) { |
| 1641 | NumberFormat *fmt = NumberFormat::createPercentInstance(LOC[i], status); |
| 1642 | if(U_FAILURE(status)) { |
| 1643 | dataerrln("Couldn't create NumberFormat - %s", u_errorName(status)); |
| 1644 | return; |
| 1645 | } |
| 1646 | UnicodeString result; |
| 1647 | FieldPosition pos(FieldPosition::DONT_CARE); |
| 1648 | fmt->format((int32_t)1, result, pos); |
| 1649 | UnicodeString temp; |
| 1650 | if(result != "100%") { |
| 1651 | errln(UnicodeString("Percent for ") + LOC[i].getDisplayName(temp) + " should be 100%, got " + result); |
| 1652 | } |
| 1653 | delete fmt; |
| 1654 | } |
| 1655 | } |
| 1656 | |
| 1657 | #endif |
| 1658 | |
| 1659 | // Tests setBogus and isBogus APIs for Locale |
| 1660 | // Jitterbug 1735 |
| 1661 | void |
| 1662 | LocaleTest::TestSetIsBogus() { |
| 1663 | Locale l("en_US"); |
| 1664 | l.setToBogus(); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 1665 | if(l.isBogus() != true) { |
| 1666 | errln("After setting bogus, didn't return true"); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 1667 | } |
| 1668 | l = "en_US"; // This should reset bogus |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 1669 | if(l.isBogus() != false) { |
| 1670 | errln("After resetting bogus, didn't return false"); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 1671 | } |
| 1672 | } |
| 1673 | |
| 1674 | |
| 1675 | void |
| 1676 | LocaleTest::TestAddLikelySubtags() { |
| 1677 | IcuTestErrorCode status(*this, "TestAddLikelySubtags()"); |
| 1678 | |
| 1679 | static const Locale min("sv"); |
| 1680 | static const Locale max("sv_Latn_SE"); |
| 1681 | |
| 1682 | Locale result(min); |
| 1683 | result.addLikelySubtags(status); |
| 1684 | status.errIfFailureAndReset("\"%s\"", min.getName()); |
| 1685 | assertEquals("addLikelySubtags", max.getName(), result.getName()); |
| 1686 | } |
| 1687 | |
| 1688 | |
| 1689 | void |
| 1690 | LocaleTest::TestMinimizeSubtags() { |
| 1691 | IcuTestErrorCode status(*this, "TestMinimizeSubtags()"); |
| 1692 | |
| 1693 | static const Locale max("zh_Hant_TW"); |
| 1694 | static const Locale min("zh_TW"); |
| 1695 | |
| 1696 | Locale result(max); |
| 1697 | result.minimizeSubtags(status); |
| 1698 | status.errIfFailureAndReset("\"%s\"", max.getName()); |
| 1699 | assertEquals("minimizeSubtags", min.getName(), result.getName()); |
| 1700 | } |
| 1701 | |
| 1702 | |
| 1703 | void |
| 1704 | LocaleTest::TestAddLikelyAndMinimizeSubtags() { |
| 1705 | IcuTestErrorCode status(*this, "TestAddLikelyAndMinimizeSubtags()"); |
| 1706 | |
| 1707 | static const struct { |
| 1708 | const char* const from; |
| 1709 | const char* const add; |
| 1710 | const char* const remove; |
| 1711 | } full_data[] = { |
| 1712 | { |
| 1713 | "und_AQ", |
| 1714 | "_Latn_AQ", |
| 1715 | "_AQ" |
| 1716 | }, { |
| 1717 | "und_Zzzz_AQ", |
| 1718 | "_Latn_AQ", |
| 1719 | "_AQ" |
| 1720 | }, { |
| 1721 | "und_Latn_AQ", |
| 1722 | "_Latn_AQ", |
| 1723 | "_AQ" |
| 1724 | }, { |
| 1725 | "und_Moon_AQ", |
| 1726 | "_Moon_AQ", |
| 1727 | "_Moon_AQ" |
| 1728 | }, { |
| 1729 | "aa", |
| 1730 | "aa_Latn_ET", |
| 1731 | "aa" |
| 1732 | }, { |
| 1733 | "af", |
| 1734 | "af_Latn_ZA", |
| 1735 | "af" |
| 1736 | }, { |
| 1737 | "ak", |
| 1738 | "ak_Latn_GH", |
| 1739 | "ak" |
| 1740 | }, { |
| 1741 | "am", |
| 1742 | "am_Ethi_ET", |
| 1743 | "am" |
| 1744 | }, { |
| 1745 | "ar", |
| 1746 | "ar_Arab_EG", |
| 1747 | "ar" |
| 1748 | }, { |
| 1749 | "as", |
| 1750 | "as_Beng_IN", |
| 1751 | "as" |
| 1752 | }, { |
| 1753 | "az", |
| 1754 | "az_Latn_AZ", |
| 1755 | "az" |
| 1756 | }, { |
| 1757 | "be", |
| 1758 | "be_Cyrl_BY", |
| 1759 | "be" |
| 1760 | }, { |
| 1761 | "bg", |
| 1762 | "bg_Cyrl_BG", |
| 1763 | "bg" |
| 1764 | }, { |
| 1765 | "bn", |
| 1766 | "bn_Beng_BD", |
| 1767 | "bn" |
| 1768 | }, { |
| 1769 | "bo", |
| 1770 | "bo_Tibt_CN", |
| 1771 | "bo" |
| 1772 | }, { |
| 1773 | "bs", |
| 1774 | "bs_Latn_BA", |
| 1775 | "bs" |
| 1776 | }, { |
| 1777 | "ca", |
| 1778 | "ca_Latn_ES", |
| 1779 | "ca" |
| 1780 | }, { |
| 1781 | "ch", |
| 1782 | "ch_Latn_GU", |
| 1783 | "ch" |
| 1784 | }, { |
| 1785 | "chk", |
| 1786 | "chk_Latn_FM", |
| 1787 | "chk" |
| 1788 | }, { |
| 1789 | "cs", |
| 1790 | "cs_Latn_CZ", |
| 1791 | "cs" |
| 1792 | }, { |
| 1793 | "cy", |
| 1794 | "cy_Latn_GB", |
| 1795 | "cy" |
| 1796 | }, { |
| 1797 | "da", |
| 1798 | "da_Latn_DK", |
| 1799 | "da" |
| 1800 | }, { |
| 1801 | "de", |
| 1802 | "de_Latn_DE", |
| 1803 | "de" |
| 1804 | }, { |
| 1805 | "dv", |
| 1806 | "dv_Thaa_MV", |
| 1807 | "dv" |
| 1808 | }, { |
| 1809 | "dz", |
| 1810 | "dz_Tibt_BT", |
| 1811 | "dz" |
| 1812 | }, { |
| 1813 | "ee", |
| 1814 | "ee_Latn_GH", |
| 1815 | "ee" |
| 1816 | }, { |
| 1817 | "el", |
| 1818 | "el_Grek_GR", |
| 1819 | "el" |
| 1820 | }, { |
| 1821 | "en", |
| 1822 | "en_Latn_US", |
| 1823 | "en" |
| 1824 | }, { |
| 1825 | "es", |
| 1826 | "es_Latn_ES", |
| 1827 | "es" |
| 1828 | }, { |
| 1829 | "et", |
| 1830 | "et_Latn_EE", |
| 1831 | "et" |
| 1832 | }, { |
| 1833 | "eu", |
| 1834 | "eu_Latn_ES", |
| 1835 | "eu" |
| 1836 | }, { |
| 1837 | "fa", |
| 1838 | "fa_Arab_IR", |
| 1839 | "fa" |
| 1840 | }, { |
| 1841 | "fi", |
| 1842 | "fi_Latn_FI", |
| 1843 | "fi" |
| 1844 | }, { |
| 1845 | "fil", |
| 1846 | "fil_Latn_PH", |
| 1847 | "fil" |
| 1848 | }, { |
| 1849 | "fj", |
| 1850 | "fj_Latn_FJ", |
| 1851 | "fj" |
| 1852 | }, { |
| 1853 | "fo", |
| 1854 | "fo_Latn_FO", |
| 1855 | "fo" |
| 1856 | }, { |
| 1857 | "fr", |
| 1858 | "fr_Latn_FR", |
| 1859 | "fr" |
| 1860 | }, { |
| 1861 | "fur", |
| 1862 | "fur_Latn_IT", |
| 1863 | "fur" |
| 1864 | }, { |
| 1865 | "ga", |
| 1866 | "ga_Latn_IE", |
| 1867 | "ga" |
| 1868 | }, { |
| 1869 | "gaa", |
| 1870 | "gaa_Latn_GH", |
| 1871 | "gaa" |
| 1872 | }, { |
| 1873 | "gl", |
| 1874 | "gl_Latn_ES", |
| 1875 | "gl" |
| 1876 | }, { |
| 1877 | "gn", |
| 1878 | "gn_Latn_PY", |
| 1879 | "gn" |
| 1880 | }, { |
| 1881 | "gu", |
| 1882 | "gu_Gujr_IN", |
| 1883 | "gu" |
| 1884 | }, { |
| 1885 | "ha", |
| 1886 | "ha_Latn_NG", |
| 1887 | "ha" |
| 1888 | }, { |
| 1889 | "haw", |
| 1890 | "haw_Latn_US", |
| 1891 | "haw" |
| 1892 | }, { |
| 1893 | "he", |
| 1894 | "he_Hebr_IL", |
| 1895 | "he" |
| 1896 | }, { |
| 1897 | "hi", |
| 1898 | "hi_Deva_IN", |
| 1899 | "hi" |
| 1900 | }, { |
| 1901 | "hr", |
| 1902 | "hr_Latn_HR", |
| 1903 | "hr" |
| 1904 | }, { |
| 1905 | "ht", |
| 1906 | "ht_Latn_HT", |
| 1907 | "ht" |
| 1908 | }, { |
| 1909 | "hu", |
| 1910 | "hu_Latn_HU", |
| 1911 | "hu" |
| 1912 | }, { |
| 1913 | "hy", |
| 1914 | "hy_Armn_AM", |
| 1915 | "hy" |
| 1916 | }, { |
| 1917 | "id", |
| 1918 | "id_Latn_ID", |
| 1919 | "id" |
| 1920 | }, { |
| 1921 | "ig", |
| 1922 | "ig_Latn_NG", |
| 1923 | "ig" |
| 1924 | }, { |
| 1925 | "ii", |
| 1926 | "ii_Yiii_CN", |
| 1927 | "ii" |
| 1928 | }, { |
| 1929 | "is", |
| 1930 | "is_Latn_IS", |
| 1931 | "is" |
| 1932 | }, { |
| 1933 | "it", |
| 1934 | "it_Latn_IT", |
| 1935 | "it" |
| 1936 | }, { |
| 1937 | "ja", |
| 1938 | "ja_Jpan_JP", |
| 1939 | "ja" |
| 1940 | }, { |
| 1941 | "ka", |
| 1942 | "ka_Geor_GE", |
| 1943 | "ka" |
| 1944 | }, { |
| 1945 | "kaj", |
| 1946 | "kaj_Latn_NG", |
| 1947 | "kaj" |
| 1948 | }, { |
| 1949 | "kam", |
| 1950 | "kam_Latn_KE", |
| 1951 | "kam" |
| 1952 | }, { |
| 1953 | "kk", |
| 1954 | "kk_Cyrl_KZ", |
| 1955 | "kk" |
| 1956 | }, { |
| 1957 | "kl", |
| 1958 | "kl_Latn_GL", |
| 1959 | "kl" |
| 1960 | }, { |
| 1961 | "km", |
| 1962 | "km_Khmr_KH", |
| 1963 | "km" |
| 1964 | }, { |
| 1965 | "kn", |
| 1966 | "kn_Knda_IN", |
| 1967 | "kn" |
| 1968 | }, { |
| 1969 | "ko", |
| 1970 | "ko_Kore_KR", |
| 1971 | "ko" |
| 1972 | }, { |
| 1973 | "kok", |
| 1974 | "kok_Deva_IN", |
| 1975 | "kok" |
| 1976 | }, { |
| 1977 | "kpe", |
| 1978 | "kpe_Latn_LR", |
| 1979 | "kpe" |
| 1980 | }, { |
| 1981 | "ku", |
| 1982 | "ku_Latn_TR", |
| 1983 | "ku" |
| 1984 | }, { |
| 1985 | "ky", |
| 1986 | "ky_Cyrl_KG", |
| 1987 | "ky" |
| 1988 | }, { |
| 1989 | "la", |
| 1990 | "la_Latn_VA", |
| 1991 | "la" |
| 1992 | }, { |
| 1993 | "ln", |
| 1994 | "ln_Latn_CD", |
| 1995 | "ln" |
| 1996 | }, { |
| 1997 | "lo", |
| 1998 | "lo_Laoo_LA", |
| 1999 | "lo" |
| 2000 | }, { |
| 2001 | "lt", |
| 2002 | "lt_Latn_LT", |
| 2003 | "lt" |
| 2004 | }, { |
| 2005 | "lv", |
| 2006 | "lv_Latn_LV", |
| 2007 | "lv" |
| 2008 | }, { |
| 2009 | "mg", |
| 2010 | "mg_Latn_MG", |
| 2011 | "mg" |
| 2012 | }, { |
| 2013 | "mh", |
| 2014 | "mh_Latn_MH", |
| 2015 | "mh" |
| 2016 | }, { |
| 2017 | "mk", |
| 2018 | "mk_Cyrl_MK", |
| 2019 | "mk" |
| 2020 | }, { |
| 2021 | "ml", |
| 2022 | "ml_Mlym_IN", |
| 2023 | "ml" |
| 2024 | }, { |
| 2025 | "mn", |
| 2026 | "mn_Cyrl_MN", |
| 2027 | "mn" |
| 2028 | }, { |
| 2029 | "mr", |
| 2030 | "mr_Deva_IN", |
| 2031 | "mr" |
| 2032 | }, { |
| 2033 | "ms", |
| 2034 | "ms_Latn_MY", |
| 2035 | "ms" |
| 2036 | }, { |
| 2037 | "mt", |
| 2038 | "mt_Latn_MT", |
| 2039 | "mt" |
| 2040 | }, { |
| 2041 | "my", |
| 2042 | "my_Mymr_MM", |
| 2043 | "my" |
| 2044 | }, { |
| 2045 | "na", |
| 2046 | "na_Latn_NR", |
| 2047 | "na" |
| 2048 | }, { |
| 2049 | "ne", |
| 2050 | "ne_Deva_NP", |
| 2051 | "ne" |
| 2052 | }, { |
| 2053 | "niu", |
| 2054 | "niu_Latn_NU", |
| 2055 | "niu" |
| 2056 | }, { |
| 2057 | "nl", |
| 2058 | "nl_Latn_NL", |
| 2059 | "nl" |
| 2060 | }, { |
| 2061 | "nn", |
| 2062 | "nn_Latn_NO", |
| 2063 | "nn" |
| 2064 | }, { |
| 2065 | "no", |
| 2066 | "no_Latn_NO", |
| 2067 | "no" |
| 2068 | }, { |
| 2069 | "nr", |
| 2070 | "nr_Latn_ZA", |
| 2071 | "nr" |
| 2072 | }, { |
| 2073 | "nso", |
| 2074 | "nso_Latn_ZA", |
| 2075 | "nso" |
| 2076 | }, { |
| 2077 | "om", |
| 2078 | "om_Latn_ET", |
| 2079 | "om" |
| 2080 | }, { |
| 2081 | "or", |
| 2082 | "or_Orya_IN", |
| 2083 | "or" |
| 2084 | }, { |
| 2085 | "pa", |
| 2086 | "pa_Guru_IN", |
| 2087 | "pa" |
| 2088 | }, { |
| 2089 | "pa_Arab", |
| 2090 | "pa_Arab_PK", |
| 2091 | "pa_PK" |
| 2092 | }, { |
| 2093 | "pa_PK", |
| 2094 | "pa_Arab_PK", |
| 2095 | "pa_PK" |
| 2096 | }, { |
| 2097 | "pap", |
| 2098 | "pap_Latn_AW", |
| 2099 | "pap" |
| 2100 | }, { |
| 2101 | "pau", |
| 2102 | "pau_Latn_PW", |
| 2103 | "pau" |
| 2104 | }, { |
| 2105 | "pl", |
| 2106 | "pl_Latn_PL", |
| 2107 | "pl" |
| 2108 | }, { |
| 2109 | "ps", |
| 2110 | "ps_Arab_AF", |
| 2111 | "ps" |
| 2112 | }, { |
| 2113 | "pt", |
| 2114 | "pt_Latn_BR", |
| 2115 | "pt" |
| 2116 | }, { |
| 2117 | "rn", |
| 2118 | "rn_Latn_BI", |
| 2119 | "rn" |
| 2120 | }, { |
| 2121 | "ro", |
| 2122 | "ro_Latn_RO", |
| 2123 | "ro" |
| 2124 | }, { |
| 2125 | "ru", |
| 2126 | "ru_Cyrl_RU", |
| 2127 | "ru" |
| 2128 | }, { |
| 2129 | "rw", |
| 2130 | "rw_Latn_RW", |
| 2131 | "rw" |
| 2132 | }, { |
| 2133 | "sa", |
| 2134 | "sa_Deva_IN", |
| 2135 | "sa" |
| 2136 | }, { |
| 2137 | "se", |
| 2138 | "se_Latn_NO", |
| 2139 | "se" |
| 2140 | }, { |
| 2141 | "sg", |
| 2142 | "sg_Latn_CF", |
| 2143 | "sg" |
| 2144 | }, { |
| 2145 | "si", |
| 2146 | "si_Sinh_LK", |
| 2147 | "si" |
| 2148 | }, { |
| 2149 | "sid", |
| 2150 | "sid_Latn_ET", |
| 2151 | "sid" |
| 2152 | }, { |
| 2153 | "sk", |
| 2154 | "sk_Latn_SK", |
| 2155 | "sk" |
| 2156 | }, { |
| 2157 | "sl", |
| 2158 | "sl_Latn_SI", |
| 2159 | "sl" |
| 2160 | }, { |
| 2161 | "sm", |
| 2162 | "sm_Latn_WS", |
| 2163 | "sm" |
| 2164 | }, { |
| 2165 | "so", |
| 2166 | "so_Latn_SO", |
| 2167 | "so" |
| 2168 | }, { |
| 2169 | "sq", |
| 2170 | "sq_Latn_AL", |
| 2171 | "sq" |
| 2172 | }, { |
| 2173 | "sr", |
| 2174 | "sr_Cyrl_RS", |
| 2175 | "sr" |
| 2176 | }, { |
| 2177 | "ss", |
| 2178 | "ss_Latn_ZA", |
| 2179 | "ss" |
| 2180 | }, { |
| 2181 | "st", |
| 2182 | "st_Latn_ZA", |
| 2183 | "st" |
| 2184 | }, { |
| 2185 | "sv", |
| 2186 | "sv_Latn_SE", |
| 2187 | "sv" |
| 2188 | }, { |
| 2189 | "sw", |
| 2190 | "sw_Latn_TZ", |
| 2191 | "sw" |
| 2192 | }, { |
| 2193 | "ta", |
| 2194 | "ta_Taml_IN", |
| 2195 | "ta" |
| 2196 | }, { |
| 2197 | "te", |
| 2198 | "te_Telu_IN", |
| 2199 | "te" |
| 2200 | }, { |
| 2201 | "tet", |
| 2202 | "tet_Latn_TL", |
| 2203 | "tet" |
| 2204 | }, { |
| 2205 | "tg", |
| 2206 | "tg_Cyrl_TJ", |
| 2207 | "tg" |
| 2208 | }, { |
| 2209 | "th", |
| 2210 | "th_Thai_TH", |
| 2211 | "th" |
| 2212 | }, { |
| 2213 | "ti", |
| 2214 | "ti_Ethi_ET", |
| 2215 | "ti" |
| 2216 | }, { |
| 2217 | "tig", |
| 2218 | "tig_Ethi_ER", |
| 2219 | "tig" |
| 2220 | }, { |
| 2221 | "tk", |
| 2222 | "tk_Latn_TM", |
| 2223 | "tk" |
| 2224 | }, { |
| 2225 | "tkl", |
| 2226 | "tkl_Latn_TK", |
| 2227 | "tkl" |
| 2228 | }, { |
| 2229 | "tn", |
| 2230 | "tn_Latn_ZA", |
| 2231 | "tn" |
| 2232 | }, { |
| 2233 | "to", |
| 2234 | "to_Latn_TO", |
| 2235 | "to" |
| 2236 | }, { |
| 2237 | "tpi", |
| 2238 | "tpi_Latn_PG", |
| 2239 | "tpi" |
| 2240 | }, { |
| 2241 | "tr", |
| 2242 | "tr_Latn_TR", |
| 2243 | "tr" |
| 2244 | }, { |
| 2245 | "ts", |
| 2246 | "ts_Latn_ZA", |
| 2247 | "ts" |
| 2248 | }, { |
| 2249 | "tt", |
| 2250 | "tt_Cyrl_RU", |
| 2251 | "tt" |
| 2252 | }, { |
| 2253 | "tvl", |
| 2254 | "tvl_Latn_TV", |
| 2255 | "tvl" |
| 2256 | }, { |
| 2257 | "ty", |
| 2258 | "ty_Latn_PF", |
| 2259 | "ty" |
| 2260 | }, { |
| 2261 | "uk", |
| 2262 | "uk_Cyrl_UA", |
| 2263 | "uk" |
| 2264 | }, { |
| 2265 | "und", |
| 2266 | "en_Latn_US", |
| 2267 | "en" |
| 2268 | }, { |
| 2269 | "und_AD", |
| 2270 | "ca_Latn_AD", |
| 2271 | "ca_AD" |
| 2272 | }, { |
| 2273 | "und_AE", |
| 2274 | "ar_Arab_AE", |
| 2275 | "ar_AE" |
| 2276 | }, { |
| 2277 | "und_AF", |
| 2278 | "fa_Arab_AF", |
| 2279 | "fa_AF" |
| 2280 | }, { |
| 2281 | "und_AL", |
| 2282 | "sq_Latn_AL", |
| 2283 | "sq" |
| 2284 | }, { |
| 2285 | "und_AM", |
| 2286 | "hy_Armn_AM", |
| 2287 | "hy" |
| 2288 | }, { |
| 2289 | "und_AO", |
| 2290 | "pt_Latn_AO", |
| 2291 | "pt_AO" |
| 2292 | }, { |
| 2293 | "und_AR", |
| 2294 | "es_Latn_AR", |
| 2295 | "es_AR" |
| 2296 | }, { |
| 2297 | "und_AS", |
| 2298 | "sm_Latn_AS", |
| 2299 | "sm_AS" |
| 2300 | }, { |
| 2301 | "und_AT", |
| 2302 | "de_Latn_AT", |
| 2303 | "de_AT" |
| 2304 | }, { |
| 2305 | "und_AW", |
| 2306 | "nl_Latn_AW", |
| 2307 | "nl_AW" |
| 2308 | }, { |
| 2309 | "und_AX", |
| 2310 | "sv_Latn_AX", |
| 2311 | "sv_AX" |
| 2312 | }, { |
| 2313 | "und_AZ", |
| 2314 | "az_Latn_AZ", |
| 2315 | "az" |
| 2316 | }, { |
| 2317 | "und_Arab", |
| 2318 | "ar_Arab_EG", |
| 2319 | "ar" |
| 2320 | }, { |
| 2321 | "und_Arab_IN", |
| 2322 | "ur_Arab_IN", |
| 2323 | "ur_IN" |
| 2324 | }, { |
| 2325 | "und_Arab_PK", |
| 2326 | "ur_Arab_PK", |
| 2327 | "ur" |
| 2328 | }, { |
| 2329 | "und_Arab_SN", |
| 2330 | "ar_Arab_SN", |
| 2331 | "ar_SN" |
| 2332 | }, { |
| 2333 | "und_Armn", |
| 2334 | "hy_Armn_AM", |
| 2335 | "hy" |
| 2336 | }, { |
| 2337 | "und_BA", |
| 2338 | "bs_Latn_BA", |
| 2339 | "bs" |
| 2340 | }, { |
| 2341 | "und_BD", |
| 2342 | "bn_Beng_BD", |
| 2343 | "bn" |
| 2344 | }, { |
| 2345 | "und_BE", |
| 2346 | "nl_Latn_BE", |
| 2347 | "nl_BE" |
| 2348 | }, { |
| 2349 | "und_BF", |
| 2350 | "fr_Latn_BF", |
| 2351 | "fr_BF" |
| 2352 | }, { |
| 2353 | "und_BG", |
| 2354 | "bg_Cyrl_BG", |
| 2355 | "bg" |
| 2356 | }, { |
| 2357 | "und_BH", |
| 2358 | "ar_Arab_BH", |
| 2359 | "ar_BH" |
| 2360 | }, { |
| 2361 | "und_BI", |
| 2362 | "rn_Latn_BI", |
| 2363 | "rn" |
| 2364 | }, { |
| 2365 | "und_BJ", |
| 2366 | "fr_Latn_BJ", |
| 2367 | "fr_BJ" |
| 2368 | }, { |
| 2369 | "und_BN", |
| 2370 | "ms_Latn_BN", |
| 2371 | "ms_BN" |
| 2372 | }, { |
| 2373 | "und_BO", |
| 2374 | "es_Latn_BO", |
| 2375 | "es_BO" |
| 2376 | }, { |
| 2377 | "und_BR", |
| 2378 | "pt_Latn_BR", |
| 2379 | "pt" |
| 2380 | }, { |
| 2381 | "und_BT", |
| 2382 | "dz_Tibt_BT", |
| 2383 | "dz" |
| 2384 | }, { |
| 2385 | "und_BY", |
| 2386 | "be_Cyrl_BY", |
| 2387 | "be" |
| 2388 | }, { |
| 2389 | "und_Beng", |
| 2390 | "bn_Beng_BD", |
| 2391 | "bn" |
| 2392 | }, { |
| 2393 | "und_Beng_IN", |
| 2394 | "bn_Beng_IN", |
| 2395 | "bn_IN" |
| 2396 | }, { |
| 2397 | "und_CD", |
| 2398 | "sw_Latn_CD", |
| 2399 | "sw_CD" |
| 2400 | }, { |
| 2401 | "und_CF", |
| 2402 | "fr_Latn_CF", |
| 2403 | "fr_CF" |
| 2404 | }, { |
| 2405 | "und_CG", |
| 2406 | "fr_Latn_CG", |
| 2407 | "fr_CG" |
| 2408 | }, { |
| 2409 | "und_CH", |
| 2410 | "de_Latn_CH", |
| 2411 | "de_CH" |
| 2412 | }, { |
| 2413 | "und_CI", |
| 2414 | "fr_Latn_CI", |
| 2415 | "fr_CI" |
| 2416 | }, { |
| 2417 | "und_CL", |
| 2418 | "es_Latn_CL", |
| 2419 | "es_CL" |
| 2420 | }, { |
| 2421 | "und_CM", |
| 2422 | "fr_Latn_CM", |
| 2423 | "fr_CM" |
| 2424 | }, { |
| 2425 | "und_CN", |
| 2426 | "zh_Hans_CN", |
| 2427 | "zh" |
| 2428 | }, { |
| 2429 | "und_CO", |
| 2430 | "es_Latn_CO", |
| 2431 | "es_CO" |
| 2432 | }, { |
| 2433 | "und_CR", |
| 2434 | "es_Latn_CR", |
| 2435 | "es_CR" |
| 2436 | }, { |
| 2437 | "und_CU", |
| 2438 | "es_Latn_CU", |
| 2439 | "es_CU" |
| 2440 | }, { |
| 2441 | "und_CV", |
| 2442 | "pt_Latn_CV", |
| 2443 | "pt_CV" |
| 2444 | }, { |
| 2445 | "und_CY", |
| 2446 | "el_Grek_CY", |
| 2447 | "el_CY" |
| 2448 | }, { |
| 2449 | "und_CZ", |
| 2450 | "cs_Latn_CZ", |
| 2451 | "cs" |
| 2452 | }, { |
| 2453 | "und_Cyrl", |
| 2454 | "ru_Cyrl_RU", |
| 2455 | "ru" |
| 2456 | }, { |
| 2457 | "und_Cyrl_KZ", |
| 2458 | "ru_Cyrl_KZ", |
| 2459 | "ru_KZ" |
| 2460 | }, { |
| 2461 | "und_DE", |
| 2462 | "de_Latn_DE", |
| 2463 | "de" |
| 2464 | }, { |
| 2465 | "und_DJ", |
| 2466 | "aa_Latn_DJ", |
| 2467 | "aa_DJ" |
| 2468 | }, { |
| 2469 | "und_DK", |
| 2470 | "da_Latn_DK", |
| 2471 | "da" |
| 2472 | }, { |
| 2473 | "und_DO", |
| 2474 | "es_Latn_DO", |
| 2475 | "es_DO" |
| 2476 | }, { |
| 2477 | "und_DZ", |
| 2478 | "ar_Arab_DZ", |
| 2479 | "ar_DZ" |
| 2480 | }, { |
| 2481 | "und_Deva", |
| 2482 | "hi_Deva_IN", |
| 2483 | "hi" |
| 2484 | }, { |
| 2485 | "und_EC", |
| 2486 | "es_Latn_EC", |
| 2487 | "es_EC" |
| 2488 | }, { |
| 2489 | "und_EE", |
| 2490 | "et_Latn_EE", |
| 2491 | "et" |
| 2492 | }, { |
| 2493 | "und_EG", |
| 2494 | "ar_Arab_EG", |
| 2495 | "ar" |
| 2496 | }, { |
| 2497 | "und_EH", |
| 2498 | "ar_Arab_EH", |
| 2499 | "ar_EH" |
| 2500 | }, { |
| 2501 | "und_ER", |
| 2502 | "ti_Ethi_ER", |
| 2503 | "ti_ER" |
| 2504 | }, { |
| 2505 | "und_ES", |
| 2506 | "es_Latn_ES", |
| 2507 | "es" |
| 2508 | }, { |
| 2509 | "und_ET", |
| 2510 | "am_Ethi_ET", |
| 2511 | "am" |
| 2512 | }, { |
| 2513 | "und_Ethi", |
| 2514 | "am_Ethi_ET", |
| 2515 | "am" |
| 2516 | }, { |
| 2517 | "und_Ethi_ER", |
| 2518 | "am_Ethi_ER", |
| 2519 | "am_ER" |
| 2520 | }, { |
| 2521 | "und_FI", |
| 2522 | "fi_Latn_FI", |
| 2523 | "fi" |
| 2524 | }, { |
| 2525 | "und_FM", |
| 2526 | "en_Latn_FM", |
| 2527 | "en_FM" |
| 2528 | }, { |
| 2529 | "und_FO", |
| 2530 | "fo_Latn_FO", |
| 2531 | "fo" |
| 2532 | }, { |
| 2533 | "und_FR", |
| 2534 | "fr_Latn_FR", |
| 2535 | "fr" |
| 2536 | }, { |
| 2537 | "und_GA", |
| 2538 | "fr_Latn_GA", |
| 2539 | "fr_GA" |
| 2540 | }, { |
| 2541 | "und_GE", |
| 2542 | "ka_Geor_GE", |
| 2543 | "ka" |
| 2544 | }, { |
| 2545 | "und_GF", |
| 2546 | "fr_Latn_GF", |
| 2547 | "fr_GF" |
| 2548 | }, { |
| 2549 | "und_GL", |
| 2550 | "kl_Latn_GL", |
| 2551 | "kl" |
| 2552 | }, { |
| 2553 | "und_GN", |
| 2554 | "fr_Latn_GN", |
| 2555 | "fr_GN" |
| 2556 | }, { |
| 2557 | "und_GP", |
| 2558 | "fr_Latn_GP", |
| 2559 | "fr_GP" |
| 2560 | }, { |
| 2561 | "und_GQ", |
| 2562 | "es_Latn_GQ", |
| 2563 | "es_GQ" |
| 2564 | }, { |
| 2565 | "und_GR", |
| 2566 | "el_Grek_GR", |
| 2567 | "el" |
| 2568 | }, { |
| 2569 | "und_GT", |
| 2570 | "es_Latn_GT", |
| 2571 | "es_GT" |
| 2572 | }, { |
| 2573 | "und_GU", |
| 2574 | "en_Latn_GU", |
| 2575 | "en_GU" |
| 2576 | }, { |
| 2577 | "und_GW", |
| 2578 | "pt_Latn_GW", |
| 2579 | "pt_GW" |
| 2580 | }, { |
| 2581 | "und_Geor", |
| 2582 | "ka_Geor_GE", |
| 2583 | "ka" |
| 2584 | }, { |
| 2585 | "und_Grek", |
| 2586 | "el_Grek_GR", |
| 2587 | "el" |
| 2588 | }, { |
| 2589 | "und_Gujr", |
| 2590 | "gu_Gujr_IN", |
| 2591 | "gu" |
| 2592 | }, { |
| 2593 | "und_Guru", |
| 2594 | "pa_Guru_IN", |
| 2595 | "pa" |
| 2596 | }, { |
| 2597 | "und_HK", |
| 2598 | "zh_Hant_HK", |
| 2599 | "zh_HK" |
| 2600 | }, { |
| 2601 | "und_HN", |
| 2602 | "es_Latn_HN", |
| 2603 | "es_HN" |
| 2604 | }, { |
| 2605 | "und_HR", |
| 2606 | "hr_Latn_HR", |
| 2607 | "hr" |
| 2608 | }, { |
| 2609 | "und_HT", |
| 2610 | "ht_Latn_HT", |
| 2611 | "ht" |
| 2612 | }, { |
| 2613 | "und_HU", |
| 2614 | "hu_Latn_HU", |
| 2615 | "hu" |
| 2616 | }, { |
| 2617 | "und_Hani", |
| 2618 | "zh_Hani_CN", |
| 2619 | "zh_Hani" |
| 2620 | }, { |
| 2621 | "und_Hans", |
| 2622 | "zh_Hans_CN", |
| 2623 | "zh" |
| 2624 | }, { |
| 2625 | "und_Hant", |
| 2626 | "zh_Hant_TW", |
| 2627 | "zh_TW" |
| 2628 | }, { |
| 2629 | "und_Hebr", |
| 2630 | "he_Hebr_IL", |
| 2631 | "he" |
| 2632 | }, { |
| 2633 | "und_ID", |
| 2634 | "id_Latn_ID", |
| 2635 | "id" |
| 2636 | }, { |
| 2637 | "und_IL", |
| 2638 | "he_Hebr_IL", |
| 2639 | "he" |
| 2640 | }, { |
| 2641 | "und_IN", |
| 2642 | "hi_Deva_IN", |
| 2643 | "hi" |
| 2644 | }, { |
| 2645 | "und_IQ", |
| 2646 | "ar_Arab_IQ", |
| 2647 | "ar_IQ" |
| 2648 | }, { |
| 2649 | "und_IR", |
| 2650 | "fa_Arab_IR", |
| 2651 | "fa" |
| 2652 | }, { |
| 2653 | "und_IS", |
| 2654 | "is_Latn_IS", |
| 2655 | "is" |
| 2656 | }, { |
| 2657 | "und_IT", |
| 2658 | "it_Latn_IT", |
| 2659 | "it" |
| 2660 | }, { |
| 2661 | "und_JO", |
| 2662 | "ar_Arab_JO", |
| 2663 | "ar_JO" |
| 2664 | }, { |
| 2665 | "und_JP", |
| 2666 | "ja_Jpan_JP", |
| 2667 | "ja" |
| 2668 | }, { |
| 2669 | "und_Jpan", |
| 2670 | "ja_Jpan_JP", |
| 2671 | "ja" |
| 2672 | }, { |
| 2673 | "und_KG", |
| 2674 | "ky_Cyrl_KG", |
| 2675 | "ky" |
| 2676 | }, { |
| 2677 | "und_KH", |
| 2678 | "km_Khmr_KH", |
| 2679 | "km" |
| 2680 | }, { |
| 2681 | "und_KM", |
| 2682 | "ar_Arab_KM", |
| 2683 | "ar_KM" |
| 2684 | }, { |
| 2685 | "und_KP", |
| 2686 | "ko_Kore_KP", |
| 2687 | "ko_KP" |
| 2688 | }, { |
| 2689 | "und_KR", |
| 2690 | "ko_Kore_KR", |
| 2691 | "ko" |
| 2692 | }, { |
| 2693 | "und_KW", |
| 2694 | "ar_Arab_KW", |
| 2695 | "ar_KW" |
| 2696 | }, { |
| 2697 | "und_KZ", |
| 2698 | "ru_Cyrl_KZ", |
| 2699 | "ru_KZ" |
| 2700 | }, { |
| 2701 | "und_Khmr", |
| 2702 | "km_Khmr_KH", |
| 2703 | "km" |
| 2704 | }, { |
| 2705 | "und_Knda", |
| 2706 | "kn_Knda_IN", |
| 2707 | "kn" |
| 2708 | }, { |
| 2709 | "und_Kore", |
| 2710 | "ko_Kore_KR", |
| 2711 | "ko" |
| 2712 | }, { |
| 2713 | "und_LA", |
| 2714 | "lo_Laoo_LA", |
| 2715 | "lo" |
| 2716 | }, { |
| 2717 | "und_LB", |
| 2718 | "ar_Arab_LB", |
| 2719 | "ar_LB" |
| 2720 | }, { |
| 2721 | "und_LI", |
| 2722 | "de_Latn_LI", |
| 2723 | "de_LI" |
| 2724 | }, { |
| 2725 | "und_LK", |
| 2726 | "si_Sinh_LK", |
| 2727 | "si" |
| 2728 | }, { |
| 2729 | "und_LS", |
| 2730 | "st_Latn_LS", |
| 2731 | "st_LS" |
| 2732 | }, { |
| 2733 | "und_LT", |
| 2734 | "lt_Latn_LT", |
| 2735 | "lt" |
| 2736 | }, { |
| 2737 | "und_LU", |
| 2738 | "fr_Latn_LU", |
| 2739 | "fr_LU" |
| 2740 | }, { |
| 2741 | "und_LV", |
| 2742 | "lv_Latn_LV", |
| 2743 | "lv" |
| 2744 | }, { |
| 2745 | "und_LY", |
| 2746 | "ar_Arab_LY", |
| 2747 | "ar_LY" |
| 2748 | }, { |
| 2749 | "und_Laoo", |
| 2750 | "lo_Laoo_LA", |
| 2751 | "lo" |
| 2752 | }, { |
| 2753 | "und_Latn_ES", |
| 2754 | "es_Latn_ES", |
| 2755 | "es" |
| 2756 | }, { |
| 2757 | "und_Latn_ET", |
| 2758 | "en_Latn_ET", |
| 2759 | "en_ET" |
| 2760 | }, { |
| 2761 | "und_Latn_GB", |
| 2762 | "en_Latn_GB", |
| 2763 | "en_GB" |
| 2764 | }, { |
| 2765 | "und_Latn_GH", |
| 2766 | "ak_Latn_GH", |
| 2767 | "ak" |
| 2768 | }, { |
| 2769 | "und_Latn_ID", |
| 2770 | "id_Latn_ID", |
| 2771 | "id" |
| 2772 | }, { |
| 2773 | "und_Latn_IT", |
| 2774 | "it_Latn_IT", |
| 2775 | "it" |
| 2776 | }, { |
| 2777 | "und_Latn_NG", |
| 2778 | "en_Latn_NG", |
| 2779 | "en_NG" |
| 2780 | }, { |
| 2781 | "und_Latn_TR", |
| 2782 | "tr_Latn_TR", |
| 2783 | "tr" |
| 2784 | }, { |
| 2785 | "und_Latn_ZA", |
| 2786 | "en_Latn_ZA", |
| 2787 | "en_ZA" |
| 2788 | }, { |
| 2789 | "und_MA", |
| 2790 | "ar_Arab_MA", |
| 2791 | "ar_MA" |
| 2792 | }, { |
| 2793 | "und_MC", |
| 2794 | "fr_Latn_MC", |
| 2795 | "fr_MC" |
| 2796 | }, { |
| 2797 | "und_MD", |
| 2798 | "ro_Latn_MD", |
| 2799 | "ro_MD" |
| 2800 | }, { |
| 2801 | "und_ME", |
| 2802 | "sr_Latn_ME", |
| 2803 | "sr_ME" |
| 2804 | }, { |
| 2805 | "und_MG", |
| 2806 | "mg_Latn_MG", |
| 2807 | "mg" |
| 2808 | }, { |
| 2809 | "und_MK", |
| 2810 | "mk_Cyrl_MK", |
| 2811 | "mk" |
| 2812 | }, { |
| 2813 | "und_ML", |
| 2814 | "bm_Latn_ML", |
| 2815 | "bm" |
| 2816 | }, { |
| 2817 | "und_MM", |
| 2818 | "my_Mymr_MM", |
| 2819 | "my" |
| 2820 | }, { |
| 2821 | "und_MN", |
| 2822 | "mn_Cyrl_MN", |
| 2823 | "mn" |
| 2824 | }, { |
| 2825 | "und_MO", |
| 2826 | "zh_Hant_MO", |
| 2827 | "zh_MO" |
| 2828 | }, { |
| 2829 | "und_MQ", |
| 2830 | "fr_Latn_MQ", |
| 2831 | "fr_MQ" |
| 2832 | }, { |
| 2833 | "und_MR", |
| 2834 | "ar_Arab_MR", |
| 2835 | "ar_MR" |
| 2836 | }, { |
| 2837 | "und_MT", |
| 2838 | "mt_Latn_MT", |
| 2839 | "mt" |
| 2840 | }, { |
| 2841 | "und_MV", |
| 2842 | "dv_Thaa_MV", |
| 2843 | "dv" |
| 2844 | }, { |
| 2845 | "und_MX", |
| 2846 | "es_Latn_MX", |
| 2847 | "es_MX" |
| 2848 | }, { |
| 2849 | "und_MY", |
| 2850 | "ms_Latn_MY", |
| 2851 | "ms" |
| 2852 | }, { |
| 2853 | "und_MZ", |
| 2854 | "pt_Latn_MZ", |
| 2855 | "pt_MZ" |
| 2856 | }, { |
| 2857 | "und_Mlym", |
| 2858 | "ml_Mlym_IN", |
| 2859 | "ml" |
| 2860 | }, { |
| 2861 | "und_Mymr", |
| 2862 | "my_Mymr_MM", |
| 2863 | "my" |
| 2864 | }, { |
| 2865 | "und_NC", |
| 2866 | "fr_Latn_NC", |
| 2867 | "fr_NC" |
| 2868 | }, { |
| 2869 | "und_NE", |
| 2870 | "ha_Latn_NE", |
| 2871 | "ha_NE" |
| 2872 | }, { |
| 2873 | "und_NG", |
| 2874 | "en_Latn_NG", |
| 2875 | "en_NG" |
| 2876 | }, { |
| 2877 | "und_NI", |
| 2878 | "es_Latn_NI", |
| 2879 | "es_NI" |
| 2880 | }, { |
| 2881 | "und_NL", |
| 2882 | "nl_Latn_NL", |
| 2883 | "nl" |
| 2884 | }, { |
| 2885 | "und_NO", |
| 2886 | "nb_Latn_NO", |
| 2887 | "nb" |
| 2888 | }, { |
| 2889 | "und_NP", |
| 2890 | "ne_Deva_NP", |
| 2891 | "ne" |
| 2892 | }, { |
| 2893 | "und_NR", |
| 2894 | "en_Latn_NR", |
| 2895 | "en_NR" |
| 2896 | }, { |
| 2897 | "und_OM", |
| 2898 | "ar_Arab_OM", |
| 2899 | "ar_OM" |
| 2900 | }, { |
| 2901 | "und_Orya", |
| 2902 | "or_Orya_IN", |
| 2903 | "or" |
| 2904 | }, { |
| 2905 | "und_PA", |
| 2906 | "es_Latn_PA", |
| 2907 | "es_PA" |
| 2908 | }, { |
| 2909 | "und_PE", |
| 2910 | "es_Latn_PE", |
| 2911 | "es_PE" |
| 2912 | }, { |
| 2913 | "und_PF", |
| 2914 | "fr_Latn_PF", |
| 2915 | "fr_PF" |
| 2916 | }, { |
| 2917 | "und_PG", |
| 2918 | "tpi_Latn_PG", |
| 2919 | "tpi" |
| 2920 | }, { |
| 2921 | "und_PH", |
| 2922 | "fil_Latn_PH", |
| 2923 | "fil" |
| 2924 | }, { |
| 2925 | "und_PL", |
| 2926 | "pl_Latn_PL", |
| 2927 | "pl" |
| 2928 | }, { |
| 2929 | "und_PM", |
| 2930 | "fr_Latn_PM", |
| 2931 | "fr_PM" |
| 2932 | }, { |
| 2933 | "und_PR", |
| 2934 | "es_Latn_PR", |
| 2935 | "es_PR" |
| 2936 | }, { |
| 2937 | "und_PS", |
| 2938 | "ar_Arab_PS", |
| 2939 | "ar_PS" |
| 2940 | }, { |
| 2941 | "und_PT", |
| 2942 | "pt_Latn_PT", |
| 2943 | "pt_PT" |
| 2944 | }, { |
| 2945 | "und_PW", |
| 2946 | "pau_Latn_PW", |
| 2947 | "pau" |
| 2948 | }, { |
| 2949 | "und_PY", |
| 2950 | "gn_Latn_PY", |
| 2951 | "gn" |
| 2952 | }, { |
| 2953 | "und_QA", |
| 2954 | "ar_Arab_QA", |
| 2955 | "ar_QA" |
| 2956 | }, { |
| 2957 | "und_RE", |
| 2958 | "fr_Latn_RE", |
| 2959 | "fr_RE" |
| 2960 | }, { |
| 2961 | "und_RO", |
| 2962 | "ro_Latn_RO", |
| 2963 | "ro" |
| 2964 | }, { |
| 2965 | "und_RS", |
| 2966 | "sr_Cyrl_RS", |
| 2967 | "sr" |
| 2968 | }, { |
| 2969 | "und_RU", |
| 2970 | "ru_Cyrl_RU", |
| 2971 | "ru" |
| 2972 | }, { |
| 2973 | "und_RW", |
| 2974 | "rw_Latn_RW", |
| 2975 | "rw" |
| 2976 | }, { |
| 2977 | "und_SA", |
| 2978 | "ar_Arab_SA", |
| 2979 | "ar_SA" |
| 2980 | }, { |
| 2981 | "und_SD", |
| 2982 | "ar_Arab_SD", |
| 2983 | "ar_SD" |
| 2984 | }, { |
| 2985 | "und_SE", |
| 2986 | "sv_Latn_SE", |
| 2987 | "sv" |
| 2988 | }, { |
| 2989 | "und_SG", |
| 2990 | "en_Latn_SG", |
| 2991 | "en_SG" |
| 2992 | }, { |
| 2993 | "und_SI", |
| 2994 | "sl_Latn_SI", |
| 2995 | "sl" |
| 2996 | }, { |
| 2997 | "und_SJ", |
| 2998 | "nb_Latn_SJ", |
| 2999 | "nb_SJ" |
| 3000 | }, { |
| 3001 | "und_SK", |
| 3002 | "sk_Latn_SK", |
| 3003 | "sk" |
| 3004 | }, { |
| 3005 | "und_SM", |
| 3006 | "it_Latn_SM", |
| 3007 | "it_SM" |
| 3008 | }, { |
| 3009 | "und_SN", |
| 3010 | "fr_Latn_SN", |
| 3011 | "fr_SN" |
| 3012 | }, { |
| 3013 | "und_SO", |
| 3014 | "so_Latn_SO", |
| 3015 | "so" |
| 3016 | }, { |
| 3017 | "und_SR", |
| 3018 | "nl_Latn_SR", |
| 3019 | "nl_SR" |
| 3020 | }, { |
| 3021 | "und_ST", |
| 3022 | "pt_Latn_ST", |
| 3023 | "pt_ST" |
| 3024 | }, { |
| 3025 | "und_SV", |
| 3026 | "es_Latn_SV", |
| 3027 | "es_SV" |
| 3028 | }, { |
| 3029 | "und_SY", |
| 3030 | "ar_Arab_SY", |
| 3031 | "ar_SY" |
| 3032 | }, { |
| 3033 | "und_Sinh", |
| 3034 | "si_Sinh_LK", |
| 3035 | "si" |
| 3036 | }, { |
| 3037 | "und_Syrc", |
| 3038 | "syr_Syrc_IQ", |
| 3039 | "syr" |
| 3040 | }, { |
| 3041 | "und_TD", |
| 3042 | "fr_Latn_TD", |
| 3043 | "fr_TD" |
| 3044 | }, { |
| 3045 | "und_TG", |
| 3046 | "fr_Latn_TG", |
| 3047 | "fr_TG" |
| 3048 | }, { |
| 3049 | "und_TH", |
| 3050 | "th_Thai_TH", |
| 3051 | "th" |
| 3052 | }, { |
| 3053 | "und_TJ", |
| 3054 | "tg_Cyrl_TJ", |
| 3055 | "tg" |
| 3056 | }, { |
| 3057 | "und_TK", |
| 3058 | "tkl_Latn_TK", |
| 3059 | "tkl" |
| 3060 | }, { |
| 3061 | "und_TL", |
| 3062 | "pt_Latn_TL", |
| 3063 | "pt_TL" |
| 3064 | }, { |
| 3065 | "und_TM", |
| 3066 | "tk_Latn_TM", |
| 3067 | "tk" |
| 3068 | }, { |
| 3069 | "und_TN", |
| 3070 | "ar_Arab_TN", |
| 3071 | "ar_TN" |
| 3072 | }, { |
| 3073 | "und_TO", |
| 3074 | "to_Latn_TO", |
| 3075 | "to" |
| 3076 | }, { |
| 3077 | "und_TR", |
| 3078 | "tr_Latn_TR", |
| 3079 | "tr" |
| 3080 | }, { |
| 3081 | "und_TV", |
| 3082 | "tvl_Latn_TV", |
| 3083 | "tvl" |
| 3084 | }, { |
| 3085 | "und_TW", |
| 3086 | "zh_Hant_TW", |
| 3087 | "zh_TW" |
| 3088 | }, { |
| 3089 | "und_Taml", |
| 3090 | "ta_Taml_IN", |
| 3091 | "ta" |
| 3092 | }, { |
| 3093 | "und_Telu", |
| 3094 | "te_Telu_IN", |
| 3095 | "te" |
| 3096 | }, { |
| 3097 | "und_Thaa", |
| 3098 | "dv_Thaa_MV", |
| 3099 | "dv" |
| 3100 | }, { |
| 3101 | "und_Thai", |
| 3102 | "th_Thai_TH", |
| 3103 | "th" |
| 3104 | }, { |
| 3105 | "und_Tibt", |
| 3106 | "bo_Tibt_CN", |
| 3107 | "bo" |
| 3108 | }, { |
| 3109 | "und_UA", |
| 3110 | "uk_Cyrl_UA", |
| 3111 | "uk" |
| 3112 | }, { |
| 3113 | "und_UY", |
| 3114 | "es_Latn_UY", |
| 3115 | "es_UY" |
| 3116 | }, { |
| 3117 | "und_UZ", |
| 3118 | "uz_Latn_UZ", |
| 3119 | "uz" |
| 3120 | }, { |
| 3121 | "und_VA", |
| 3122 | "it_Latn_VA", |
| 3123 | "it_VA" |
| 3124 | }, { |
| 3125 | "und_VE", |
| 3126 | "es_Latn_VE", |
| 3127 | "es_VE" |
| 3128 | }, { |
| 3129 | "und_VN", |
| 3130 | "vi_Latn_VN", |
| 3131 | "vi" |
| 3132 | }, { |
| 3133 | "und_VU", |
| 3134 | "bi_Latn_VU", |
| 3135 | "bi" |
| 3136 | }, { |
| 3137 | "und_WF", |
| 3138 | "fr_Latn_WF", |
| 3139 | "fr_WF" |
| 3140 | }, { |
| 3141 | "und_WS", |
| 3142 | "sm_Latn_WS", |
| 3143 | "sm" |
| 3144 | }, { |
| 3145 | "und_YE", |
| 3146 | "ar_Arab_YE", |
| 3147 | "ar_YE" |
| 3148 | }, { |
| 3149 | "und_YT", |
| 3150 | "fr_Latn_YT", |
| 3151 | "fr_YT" |
| 3152 | }, { |
| 3153 | "und_Yiii", |
| 3154 | "ii_Yiii_CN", |
| 3155 | "ii" |
| 3156 | }, { |
| 3157 | "ur", |
| 3158 | "ur_Arab_PK", |
| 3159 | "ur" |
| 3160 | }, { |
| 3161 | "uz", |
| 3162 | "uz_Latn_UZ", |
| 3163 | "uz" |
| 3164 | }, { |
| 3165 | "uz_AF", |
| 3166 | "uz_Arab_AF", |
| 3167 | "uz_AF" |
| 3168 | }, { |
| 3169 | "uz_Arab", |
| 3170 | "uz_Arab_AF", |
| 3171 | "uz_AF" |
| 3172 | }, { |
| 3173 | "ve", |
| 3174 | "ve_Latn_ZA", |
| 3175 | "ve" |
| 3176 | }, { |
| 3177 | "vi", |
| 3178 | "vi_Latn_VN", |
| 3179 | "vi" |
| 3180 | }, { |
| 3181 | "wal", |
| 3182 | "wal_Ethi_ET", |
| 3183 | "wal" |
| 3184 | }, { |
| 3185 | "wo", |
| 3186 | "wo_Latn_SN", |
| 3187 | "wo" |
| 3188 | }, { |
| 3189 | "wo_SN", |
| 3190 | "wo_Latn_SN", |
| 3191 | "wo" |
| 3192 | }, { |
| 3193 | "xh", |
| 3194 | "xh_Latn_ZA", |
| 3195 | "xh" |
| 3196 | }, { |
| 3197 | "yo", |
| 3198 | "yo_Latn_NG", |
| 3199 | "yo" |
| 3200 | }, { |
| 3201 | "zh", |
| 3202 | "zh_Hans_CN", |
| 3203 | "zh" |
| 3204 | }, { |
| 3205 | "zh_HK", |
| 3206 | "zh_Hant_HK", |
| 3207 | "zh_HK" |
| 3208 | }, { |
| 3209 | "zh_Hani", |
| 3210 | "zh_Hani_CN", |
| 3211 | "zh_Hani" |
| 3212 | }, { |
| 3213 | "zh_Hant", |
| 3214 | "zh_Hant_TW", |
| 3215 | "zh_TW" |
| 3216 | }, { |
| 3217 | "zh_MO", |
| 3218 | "zh_Hant_MO", |
| 3219 | "zh_MO" |
| 3220 | }, { |
| 3221 | "zh_TW", |
| 3222 | "zh_Hant_TW", |
| 3223 | "zh_TW" |
| 3224 | }, { |
| 3225 | "zu", |
| 3226 | "zu_Latn_ZA", |
| 3227 | "zu" |
| 3228 | }, { |
| 3229 | "und", |
| 3230 | "en_Latn_US", |
| 3231 | "en" |
| 3232 | }, { |
| 3233 | "und_ZZ", |
| 3234 | "en_Latn_US", |
| 3235 | "en" |
| 3236 | }, { |
| 3237 | "und_CN", |
| 3238 | "zh_Hans_CN", |
| 3239 | "zh" |
| 3240 | }, { |
| 3241 | "und_TW", |
| 3242 | "zh_Hant_TW", |
| 3243 | "zh_TW" |
| 3244 | }, { |
| 3245 | "und_HK", |
| 3246 | "zh_Hant_HK", |
| 3247 | "zh_HK" |
| 3248 | }, { |
| 3249 | "und_AQ", |
| 3250 | "_Latn_AQ", |
| 3251 | "_AQ" |
| 3252 | }, { |
| 3253 | "und_Zzzz", |
| 3254 | "en_Latn_US", |
| 3255 | "en" |
| 3256 | }, { |
| 3257 | "und_Zzzz_ZZ", |
| 3258 | "en_Latn_US", |
| 3259 | "en" |
| 3260 | }, { |
| 3261 | "und_Zzzz_CN", |
| 3262 | "zh_Hans_CN", |
| 3263 | "zh" |
| 3264 | }, { |
| 3265 | "und_Zzzz_TW", |
| 3266 | "zh_Hant_TW", |
| 3267 | "zh_TW" |
| 3268 | }, { |
| 3269 | "und_Zzzz_HK", |
| 3270 | "zh_Hant_HK", |
| 3271 | "zh_HK" |
| 3272 | }, { |
| 3273 | "und_Zzzz_AQ", |
| 3274 | "_Latn_AQ", |
| 3275 | "_AQ" |
| 3276 | }, { |
| 3277 | "und_Latn", |
| 3278 | "en_Latn_US", |
| 3279 | "en" |
| 3280 | }, { |
| 3281 | "und_Latn_ZZ", |
| 3282 | "en_Latn_US", |
| 3283 | "en" |
| 3284 | }, { |
| 3285 | "und_Latn_CN", |
| 3286 | "za_Latn_CN", |
| 3287 | "za" |
| 3288 | }, { |
| 3289 | "und_Latn_TW", |
| 3290 | "trv_Latn_TW", |
| 3291 | "trv" |
| 3292 | }, { |
| 3293 | "und_Latn_HK", |
| 3294 | "zh_Latn_HK", |
| 3295 | "zh_Latn_HK" |
| 3296 | }, { |
| 3297 | "und_Latn_AQ", |
| 3298 | "_Latn_AQ", |
| 3299 | "_AQ" |
| 3300 | }, { |
| 3301 | "und_Hans", |
| 3302 | "zh_Hans_CN", |
| 3303 | "zh" |
| 3304 | }, { |
| 3305 | "und_Hans_ZZ", |
| 3306 | "zh_Hans_CN", |
| 3307 | "zh" |
| 3308 | }, { |
| 3309 | "und_Hans_CN", |
| 3310 | "zh_Hans_CN", |
| 3311 | "zh" |
| 3312 | }, { |
| 3313 | "und_Hans_TW", |
| 3314 | "zh_Hans_TW", |
| 3315 | "zh_Hans_TW" |
| 3316 | }, { |
| 3317 | "und_Hans_HK", |
| 3318 | "zh_Hans_HK", |
| 3319 | "zh_Hans_HK" |
| 3320 | }, { |
| 3321 | "und_Hans_AQ", |
| 3322 | "zh_Hans_AQ", |
| 3323 | "zh_AQ" |
| 3324 | }, { |
| 3325 | "und_Hant", |
| 3326 | "zh_Hant_TW", |
| 3327 | "zh_TW" |
| 3328 | }, { |
| 3329 | "und_Hant_ZZ", |
| 3330 | "zh_Hant_TW", |
| 3331 | "zh_TW" |
| 3332 | }, { |
| 3333 | "und_Hant_CN", |
| 3334 | "zh_Hant_CN", |
| 3335 | "zh_Hant_CN" |
| 3336 | }, { |
| 3337 | "und_Hant_TW", |
| 3338 | "zh_Hant_TW", |
| 3339 | "zh_TW" |
| 3340 | }, { |
| 3341 | "und_Hant_HK", |
| 3342 | "zh_Hant_HK", |
| 3343 | "zh_HK" |
| 3344 | }, { |
| 3345 | "und_Hant_AQ", |
| 3346 | "zh_Hant_AQ", |
| 3347 | "zh_Hant_AQ" |
| 3348 | }, { |
| 3349 | "und_Moon", |
| 3350 | "en_Moon_US", |
| 3351 | "en_Moon" |
| 3352 | }, { |
| 3353 | "und_Moon_ZZ", |
| 3354 | "en_Moon_US", |
| 3355 | "en_Moon" |
| 3356 | }, { |
| 3357 | "und_Moon_CN", |
| 3358 | "zh_Moon_CN", |
| 3359 | "zh_Moon" |
| 3360 | }, { |
| 3361 | "und_Moon_TW", |
| 3362 | "zh_Moon_TW", |
| 3363 | "zh_Moon_TW" |
| 3364 | }, { |
| 3365 | "und_Moon_HK", |
| 3366 | "zh_Moon_HK", |
| 3367 | "zh_Moon_HK" |
| 3368 | }, { |
| 3369 | "und_Moon_AQ", |
| 3370 | "_Moon_AQ", |
| 3371 | "_Moon_AQ" |
| 3372 | }, { |
| 3373 | "es", |
| 3374 | "es_Latn_ES", |
| 3375 | "es" |
| 3376 | }, { |
| 3377 | "es_ZZ", |
| 3378 | "es_Latn_ES", |
| 3379 | "es" |
| 3380 | }, { |
| 3381 | "es_CN", |
| 3382 | "es_Latn_CN", |
| 3383 | "es_CN" |
| 3384 | }, { |
| 3385 | "es_TW", |
| 3386 | "es_Latn_TW", |
| 3387 | "es_TW" |
| 3388 | }, { |
| 3389 | "es_HK", |
| 3390 | "es_Latn_HK", |
| 3391 | "es_HK" |
| 3392 | }, { |
| 3393 | "es_AQ", |
| 3394 | "es_Latn_AQ", |
| 3395 | "es_AQ" |
| 3396 | }, { |
| 3397 | "es_Zzzz", |
| 3398 | "es_Latn_ES", |
| 3399 | "es" |
| 3400 | }, { |
| 3401 | "es_Zzzz_ZZ", |
| 3402 | "es_Latn_ES", |
| 3403 | "es" |
| 3404 | }, { |
| 3405 | "es_Zzzz_CN", |
| 3406 | "es_Latn_CN", |
| 3407 | "es_CN" |
| 3408 | }, { |
| 3409 | "es_Zzzz_TW", |
| 3410 | "es_Latn_TW", |
| 3411 | "es_TW" |
| 3412 | }, { |
| 3413 | "es_Zzzz_HK", |
| 3414 | "es_Latn_HK", |
| 3415 | "es_HK" |
| 3416 | }, { |
| 3417 | "es_Zzzz_AQ", |
| 3418 | "es_Latn_AQ", |
| 3419 | "es_AQ" |
| 3420 | }, { |
| 3421 | "es_Latn", |
| 3422 | "es_Latn_ES", |
| 3423 | "es" |
| 3424 | }, { |
| 3425 | "es_Latn_ZZ", |
| 3426 | "es_Latn_ES", |
| 3427 | "es" |
| 3428 | }, { |
| 3429 | "es_Latn_CN", |
| 3430 | "es_Latn_CN", |
| 3431 | "es_CN" |
| 3432 | }, { |
| 3433 | "es_Latn_TW", |
| 3434 | "es_Latn_TW", |
| 3435 | "es_TW" |
| 3436 | }, { |
| 3437 | "es_Latn_HK", |
| 3438 | "es_Latn_HK", |
| 3439 | "es_HK" |
| 3440 | }, { |
| 3441 | "es_Latn_AQ", |
| 3442 | "es_Latn_AQ", |
| 3443 | "es_AQ" |
| 3444 | }, { |
| 3445 | "es_Hans", |
| 3446 | "es_Hans_ES", |
| 3447 | "es_Hans" |
| 3448 | }, { |
| 3449 | "es_Hans_ZZ", |
| 3450 | "es_Hans_ES", |
| 3451 | "es_Hans" |
| 3452 | }, { |
| 3453 | "es_Hans_CN", |
| 3454 | "es_Hans_CN", |
| 3455 | "es_Hans_CN" |
| 3456 | }, { |
| 3457 | "es_Hans_TW", |
| 3458 | "es_Hans_TW", |
| 3459 | "es_Hans_TW" |
| 3460 | }, { |
| 3461 | "es_Hans_HK", |
| 3462 | "es_Hans_HK", |
| 3463 | "es_Hans_HK" |
| 3464 | }, { |
| 3465 | "es_Hans_AQ", |
| 3466 | "es_Hans_AQ", |
| 3467 | "es_Hans_AQ" |
| 3468 | }, { |
| 3469 | "es_Hant", |
| 3470 | "es_Hant_ES", |
| 3471 | "es_Hant" |
| 3472 | }, { |
| 3473 | "es_Hant_ZZ", |
| 3474 | "es_Hant_ES", |
| 3475 | "es_Hant" |
| 3476 | }, { |
| 3477 | "es_Hant_CN", |
| 3478 | "es_Hant_CN", |
| 3479 | "es_Hant_CN" |
| 3480 | }, { |
| 3481 | "es_Hant_TW", |
| 3482 | "es_Hant_TW", |
| 3483 | "es_Hant_TW" |
| 3484 | }, { |
| 3485 | "es_Hant_HK", |
| 3486 | "es_Hant_HK", |
| 3487 | "es_Hant_HK" |
| 3488 | }, { |
| 3489 | "es_Hant_AQ", |
| 3490 | "es_Hant_AQ", |
| 3491 | "es_Hant_AQ" |
| 3492 | }, { |
| 3493 | "es_Moon", |
| 3494 | "es_Moon_ES", |
| 3495 | "es_Moon" |
| 3496 | }, { |
| 3497 | "es_Moon_ZZ", |
| 3498 | "es_Moon_ES", |
| 3499 | "es_Moon" |
| 3500 | }, { |
| 3501 | "es_Moon_CN", |
| 3502 | "es_Moon_CN", |
| 3503 | "es_Moon_CN" |
| 3504 | }, { |
| 3505 | "es_Moon_TW", |
| 3506 | "es_Moon_TW", |
| 3507 | "es_Moon_TW" |
| 3508 | }, { |
| 3509 | "es_Moon_HK", |
| 3510 | "es_Moon_HK", |
| 3511 | "es_Moon_HK" |
| 3512 | }, { |
| 3513 | "es_Moon_AQ", |
| 3514 | "es_Moon_AQ", |
| 3515 | "es_Moon_AQ" |
| 3516 | }, { |
| 3517 | "zh", |
| 3518 | "zh_Hans_CN", |
| 3519 | "zh" |
| 3520 | }, { |
| 3521 | "zh_ZZ", |
| 3522 | "zh_Hans_CN", |
| 3523 | "zh" |
| 3524 | }, { |
| 3525 | "zh_CN", |
| 3526 | "zh_Hans_CN", |
| 3527 | "zh" |
| 3528 | }, { |
| 3529 | "zh_TW", |
| 3530 | "zh_Hant_TW", |
| 3531 | "zh_TW" |
| 3532 | }, { |
| 3533 | "zh_HK", |
| 3534 | "zh_Hant_HK", |
| 3535 | "zh_HK" |
| 3536 | }, { |
| 3537 | "zh_AQ", |
| 3538 | "zh_Hans_AQ", |
| 3539 | "zh_AQ" |
| 3540 | }, { |
| 3541 | "zh_Zzzz", |
| 3542 | "zh_Hans_CN", |
| 3543 | "zh" |
| 3544 | }, { |
| 3545 | "zh_Zzzz_ZZ", |
| 3546 | "zh_Hans_CN", |
| 3547 | "zh" |
| 3548 | }, { |
| 3549 | "zh_Zzzz_CN", |
| 3550 | "zh_Hans_CN", |
| 3551 | "zh" |
| 3552 | }, { |
| 3553 | "zh_Zzzz_TW", |
| 3554 | "zh_Hant_TW", |
| 3555 | "zh_TW" |
| 3556 | }, { |
| 3557 | "zh_Zzzz_HK", |
| 3558 | "zh_Hant_HK", |
| 3559 | "zh_HK" |
| 3560 | }, { |
| 3561 | "zh_Zzzz_AQ", |
| 3562 | "zh_Hans_AQ", |
| 3563 | "zh_AQ" |
| 3564 | }, { |
| 3565 | "zh_Latn", |
| 3566 | "zh_Latn_CN", |
| 3567 | "zh_Latn" |
| 3568 | }, { |
| 3569 | "zh_Latn_ZZ", |
| 3570 | "zh_Latn_CN", |
| 3571 | "zh_Latn" |
| 3572 | }, { |
| 3573 | "zh_Latn_CN", |
| 3574 | "zh_Latn_CN", |
| 3575 | "zh_Latn" |
| 3576 | }, { |
| 3577 | "zh_Latn_TW", |
| 3578 | "zh_Latn_TW", |
| 3579 | "zh_Latn_TW" |
| 3580 | }, { |
| 3581 | "zh_Latn_HK", |
| 3582 | "zh_Latn_HK", |
| 3583 | "zh_Latn_HK" |
| 3584 | }, { |
| 3585 | "zh_Latn_AQ", |
| 3586 | "zh_Latn_AQ", |
| 3587 | "zh_Latn_AQ" |
| 3588 | }, { |
| 3589 | "zh_Hans", |
| 3590 | "zh_Hans_CN", |
| 3591 | "zh" |
| 3592 | }, { |
| 3593 | "zh_Hans_ZZ", |
| 3594 | "zh_Hans_CN", |
| 3595 | "zh" |
| 3596 | }, { |
| 3597 | "zh_Hans_TW", |
| 3598 | "zh_Hans_TW", |
| 3599 | "zh_Hans_TW" |
| 3600 | }, { |
| 3601 | "zh_Hans_HK", |
| 3602 | "zh_Hans_HK", |
| 3603 | "zh_Hans_HK" |
| 3604 | }, { |
| 3605 | "zh_Hans_AQ", |
| 3606 | "zh_Hans_AQ", |
| 3607 | "zh_AQ" |
| 3608 | }, { |
| 3609 | "zh_Hant", |
| 3610 | "zh_Hant_TW", |
| 3611 | "zh_TW" |
| 3612 | }, { |
| 3613 | "zh_Hant_ZZ", |
| 3614 | "zh_Hant_TW", |
| 3615 | "zh_TW" |
| 3616 | }, { |
| 3617 | "zh_Hant_CN", |
| 3618 | "zh_Hant_CN", |
| 3619 | "zh_Hant_CN" |
| 3620 | }, { |
| 3621 | "zh_Hant_AQ", |
| 3622 | "zh_Hant_AQ", |
| 3623 | "zh_Hant_AQ" |
| 3624 | }, { |
| 3625 | "zh_Moon", |
| 3626 | "zh_Moon_CN", |
| 3627 | "zh_Moon" |
| 3628 | }, { |
| 3629 | "zh_Moon_ZZ", |
| 3630 | "zh_Moon_CN", |
| 3631 | "zh_Moon" |
| 3632 | }, { |
| 3633 | "zh_Moon_CN", |
| 3634 | "zh_Moon_CN", |
| 3635 | "zh_Moon" |
| 3636 | }, { |
| 3637 | "zh_Moon_TW", |
| 3638 | "zh_Moon_TW", |
| 3639 | "zh_Moon_TW" |
| 3640 | }, { |
| 3641 | "zh_Moon_HK", |
| 3642 | "zh_Moon_HK", |
| 3643 | "zh_Moon_HK" |
| 3644 | }, { |
| 3645 | "zh_Moon_AQ", |
| 3646 | "zh_Moon_AQ", |
| 3647 | "zh_Moon_AQ" |
| 3648 | }, { |
| 3649 | "art", |
| 3650 | "", |
| 3651 | "" |
| 3652 | }, { |
| 3653 | "art_ZZ", |
| 3654 | "", |
| 3655 | "" |
| 3656 | }, { |
| 3657 | "art_CN", |
| 3658 | "", |
| 3659 | "" |
| 3660 | }, { |
| 3661 | "art_TW", |
| 3662 | "", |
| 3663 | "" |
| 3664 | }, { |
| 3665 | "art_HK", |
| 3666 | "", |
| 3667 | "" |
| 3668 | }, { |
| 3669 | "art_AQ", |
| 3670 | "", |
| 3671 | "" |
| 3672 | }, { |
| 3673 | "art_Zzzz", |
| 3674 | "", |
| 3675 | "" |
| 3676 | }, { |
| 3677 | "art_Zzzz_ZZ", |
| 3678 | "", |
| 3679 | "" |
| 3680 | }, { |
| 3681 | "art_Zzzz_CN", |
| 3682 | "", |
| 3683 | "" |
| 3684 | }, { |
| 3685 | "art_Zzzz_TW", |
| 3686 | "", |
| 3687 | "" |
| 3688 | }, { |
| 3689 | "art_Zzzz_HK", |
| 3690 | "", |
| 3691 | "" |
| 3692 | }, { |
| 3693 | "art_Zzzz_AQ", |
| 3694 | "", |
| 3695 | "" |
| 3696 | }, { |
| 3697 | "art_Latn", |
| 3698 | "", |
| 3699 | "" |
| 3700 | }, { |
| 3701 | "art_Latn_ZZ", |
| 3702 | "", |
| 3703 | "" |
| 3704 | }, { |
| 3705 | "art_Latn_CN", |
| 3706 | "", |
| 3707 | "" |
| 3708 | }, { |
| 3709 | "art_Latn_TW", |
| 3710 | "", |
| 3711 | "" |
| 3712 | }, { |
| 3713 | "art_Latn_HK", |
| 3714 | "", |
| 3715 | "" |
| 3716 | }, { |
| 3717 | "art_Latn_AQ", |
| 3718 | "", |
| 3719 | "" |
| 3720 | }, { |
| 3721 | "art_Hans", |
| 3722 | "", |
| 3723 | "" |
| 3724 | }, { |
| 3725 | "art_Hans_ZZ", |
| 3726 | "", |
| 3727 | "" |
| 3728 | }, { |
| 3729 | "art_Hans_CN", |
| 3730 | "", |
| 3731 | "" |
| 3732 | }, { |
| 3733 | "art_Hans_TW", |
| 3734 | "", |
| 3735 | "" |
| 3736 | }, { |
| 3737 | "art_Hans_HK", |
| 3738 | "", |
| 3739 | "" |
| 3740 | }, { |
| 3741 | "art_Hans_AQ", |
| 3742 | "", |
| 3743 | "" |
| 3744 | }, { |
| 3745 | "art_Hant", |
| 3746 | "", |
| 3747 | "" |
| 3748 | }, { |
| 3749 | "art_Hant_ZZ", |
| 3750 | "", |
| 3751 | "" |
| 3752 | }, { |
| 3753 | "art_Hant_CN", |
| 3754 | "", |
| 3755 | "" |
| 3756 | }, { |
| 3757 | "art_Hant_TW", |
| 3758 | "", |
| 3759 | "" |
| 3760 | }, { |
| 3761 | "art_Hant_HK", |
| 3762 | "", |
| 3763 | "" |
| 3764 | }, { |
| 3765 | "art_Hant_AQ", |
| 3766 | "", |
| 3767 | "" |
| 3768 | }, { |
| 3769 | "art_Moon", |
| 3770 | "", |
| 3771 | "" |
| 3772 | }, { |
| 3773 | "art_Moon_ZZ", |
| 3774 | "", |
| 3775 | "" |
| 3776 | }, { |
| 3777 | "art_Moon_CN", |
| 3778 | "", |
| 3779 | "" |
| 3780 | }, { |
| 3781 | "art_Moon_TW", |
| 3782 | "", |
| 3783 | "" |
| 3784 | }, { |
| 3785 | "art_Moon_HK", |
| 3786 | "", |
| 3787 | "" |
| 3788 | }, { |
| 3789 | "art_Moon_AQ", |
| 3790 | "", |
| 3791 | "" |
| 3792 | }, { |
| 3793 | "aae_Latn_IT", |
| 3794 | "aae_Latn_IT", |
| 3795 | "aae_Latn_IT" |
| 3796 | }, { |
| 3797 | "aae_Thai_CO", |
| 3798 | "aae_Thai_CO", |
| 3799 | "aae_Thai_CO" |
| 3800 | }, { |
| 3801 | "und_CW", |
| 3802 | "pap_Latn_CW", |
| 3803 | "pap_CW" |
| 3804 | }, { |
| 3805 | "zh_Hant", |
| 3806 | "zh_Hant_TW", |
| 3807 | "zh_TW" |
| 3808 | }, { |
| 3809 | "zh_Hani", |
| 3810 | "zh_Hani_CN", |
| 3811 | "zh_Hani" |
| 3812 | }, { |
| 3813 | "und", |
| 3814 | "en_Latn_US", |
| 3815 | "en" |
| 3816 | }, { |
| 3817 | "und_Thai", |
| 3818 | "th_Thai_TH", |
| 3819 | "th" |
| 3820 | }, { |
| 3821 | "und_419", |
| 3822 | "es_Latn_419", |
| 3823 | "es_419" |
| 3824 | }, { |
| 3825 | "und_150", |
| 3826 | "ru_Cyrl_RU", |
| 3827 | "ru" |
| 3828 | }, { |
| 3829 | "und_AT", |
| 3830 | "de_Latn_AT", |
| 3831 | "de_AT" |
| 3832 | }, { |
| 3833 | "und_US", |
| 3834 | "en_Latn_US", |
| 3835 | "en" |
| 3836 | } |
| 3837 | }; |
| 3838 | |
| 3839 | for (const auto& item : full_data) { |
| 3840 | const char* const org = item.from; |
| 3841 | const char* const exp = item.add; |
| 3842 | Locale res(org); |
| 3843 | res.addLikelySubtags(status); |
| 3844 | status.errIfFailureAndReset("\"%s\"", org); |
| 3845 | if (exp[0]) { |
| 3846 | assertEquals("addLikelySubtags", exp, res.getName()); |
| 3847 | } else { |
| 3848 | assertEquals("addLikelySubtags", org, res.getName()); |
| 3849 | } |
| 3850 | } |
| 3851 | |
| 3852 | for (const auto& item : full_data) { |
| 3853 | const char* const org = item.from; |
| 3854 | const char* const exp = item.remove; |
| 3855 | Locale res(org); |
| 3856 | res.minimizeSubtags(status); |
| 3857 | status.errIfFailureAndReset("\"%s\"", org); |
| 3858 | if (exp[0]) { |
| 3859 | assertEquals("minimizeSubtags", exp, res.getName()); |
| 3860 | } else { |
| 3861 | assertEquals("minimizeSubtags", org, res.getName()); |
| 3862 | } |
| 3863 | } |
| 3864 | } |
| 3865 | |
| 3866 | |
| 3867 | void |
| 3868 | LocaleTest::TestKeywordVariants(void) { |
| 3869 | static const struct { |
| 3870 | const char *localeID; |
| 3871 | const char *expectedLocaleID; |
| 3872 | //const char *expectedLocaleIDNoKeywords; |
| 3873 | //const char *expectedCanonicalID; |
| 3874 | const char *expectedKeywords[10]; |
| 3875 | int32_t numKeywords; |
| 3876 | UErrorCode expectedStatus; |
| 3877 | } testCases[] = { |
| 3878 | { |
| 3879 | "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ", |
| 3880 | "de_DE@calendar=buddhist;collation=Phonebook;currency=euro", |
| 3881 | //"de_DE", |
| 3882 | //"de_DE@calendar=buddhist;collation=Phonebook;currency=euro", |
| 3883 | {"calendar", "collation", "currency"}, |
| 3884 | 3, |
| 3885 | U_ZERO_ERROR |
| 3886 | }, |
| 3887 | { |
| 3888 | "de_DE@euro", |
| 3889 | "de_DE@euro", |
| 3890 | //"de_DE", |
| 3891 | //"de_DE@currency=EUR", |
| 3892 | {"","","","","","",""}, |
| 3893 | 0, |
| 3894 | U_INVALID_FORMAT_ERROR /* must have '=' after '@' */ |
| 3895 | } |
| 3896 | }; |
| 3897 | UErrorCode status = U_ZERO_ERROR; |
| 3898 | |
| 3899 | int32_t i = 0, j = 0; |
| 3900 | const char *result = NULL; |
| 3901 | StringEnumeration *keywords; |
| 3902 | int32_t keyCount = 0; |
| 3903 | const char *keyword = NULL; |
| 3904 | const UnicodeString *keywordString; |
| 3905 | int32_t keywordLen = 0; |
| 3906 | |
| 3907 | for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { |
| 3908 | status = U_ZERO_ERROR; |
| 3909 | Locale l(testCases[i].localeID); |
| 3910 | keywords = l.createKeywords(status); |
| 3911 | |
| 3912 | if(status != testCases[i].expectedStatus) { |
| 3913 | err("Expected to get status %s. Got %s instead\n", |
| 3914 | u_errorName(testCases[i].expectedStatus), u_errorName(status)); |
| 3915 | } |
| 3916 | status = U_ZERO_ERROR; |
| 3917 | if(keywords) { |
| 3918 | if((keyCount = keywords->count(status)) != testCases[i].numKeywords) { |
| 3919 | err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount); |
| 3920 | } |
| 3921 | if(keyCount) { |
| 3922 | for(j = 0;;) { |
| 3923 | if((j&1)==0) { |
| 3924 | if((keyword = keywords->next(&keywordLen, status)) == NULL) { |
| 3925 | break; |
| 3926 | } |
| 3927 | if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) { |
| 3928 | err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword); |
| 3929 | } |
| 3930 | } else { |
| 3931 | if((keywordString = keywords->snext(status)) == NULL) { |
| 3932 | break; |
| 3933 | } |
| 3934 | if(*keywordString != UnicodeString(testCases[i].expectedKeywords[j], "")) { |
| 3935 | err("Expected to get keyword UnicodeString %s, got %s\n", testCases[i].expectedKeywords[j], keyword); |
| 3936 | } |
| 3937 | } |
| 3938 | j++; |
| 3939 | |
| 3940 | if(j == keyCount / 2) { |
| 3941 | // replace keywords with a clone of itself |
| 3942 | StringEnumeration *k2 = keywords->clone(); |
| 3943 | if(k2 == NULL || keyCount != k2->count(status)) { |
| 3944 | errln("KeywordEnumeration.clone() failed"); |
| 3945 | } else { |
| 3946 | delete keywords; |
| 3947 | keywords = k2; |
| 3948 | } |
| 3949 | } |
| 3950 | } |
| 3951 | keywords->reset(status); // Make sure that reset works. |
| 3952 | for(j = 0;;) { |
| 3953 | if((keyword = keywords->next(&keywordLen, status)) == NULL) { |
| 3954 | break; |
| 3955 | } |
| 3956 | if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) { |
| 3957 | err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword); |
| 3958 | } |
| 3959 | j++; |
| 3960 | } |
| 3961 | } |
| 3962 | delete keywords; |
| 3963 | } |
| 3964 | result = l.getName(); |
| 3965 | if(uprv_strcmp(testCases[i].expectedLocaleID, result) != 0) { |
| 3966 | err("Expected to get \"%s\" from \"%s\". Got \"%s\" instead\n", |
| 3967 | testCases[i].expectedLocaleID, testCases[i].localeID, result); |
| 3968 | } |
| 3969 | |
| 3970 | } |
| 3971 | |
| 3972 | } |
| 3973 | |
| 3974 | |
| 3975 | void |
| 3976 | LocaleTest::TestCreateUnicodeKeywords(void) { |
| 3977 | IcuTestErrorCode status(*this, "TestCreateUnicodeKeywords()"); |
| 3978 | |
| 3979 | static const Locale l("de@calendar=buddhist;collation=phonebook"); |
| 3980 | |
| 3981 | LocalPointer<StringEnumeration> keys(l.createUnicodeKeywords(status)); |
| 3982 | status.errIfFailureAndReset("\"%s\"", l.getName()); |
| 3983 | |
| 3984 | const char* key; |
| 3985 | int32_t resultLength; |
| 3986 | |
| 3987 | key = keys->next(&resultLength, status); |
| 3988 | status.errIfFailureAndReset("key #1"); |
| 3989 | assertEquals("resultLength", 2, resultLength); |
| 3990 | assertTrue("key != nullptr", key != nullptr); |
| 3991 | if (key != nullptr) { |
| 3992 | assertEquals("calendar", "ca", key); |
| 3993 | } |
| 3994 | |
| 3995 | key = keys->next(&resultLength, status); |
| 3996 | status.errIfFailureAndReset("key #2"); |
| 3997 | assertEquals("resultLength", 2, resultLength); |
| 3998 | assertTrue("key != nullptr", key != nullptr); |
| 3999 | if (key != nullptr) { |
| 4000 | assertEquals("collation", "co", key); |
| 4001 | } |
| 4002 | |
| 4003 | key = keys->next(&resultLength, status); |
| 4004 | status.errIfFailureAndReset("end of keys"); |
| 4005 | assertEquals("resultLength", 0, resultLength); |
| 4006 | assertTrue("key == nullptr", key == nullptr); |
| 4007 | |
| 4008 | const UnicodeString* skey; |
| 4009 | keys->reset(status); // KeywordEnumeration::reset() never touches status. |
| 4010 | |
| 4011 | skey = keys->snext(status); |
| 4012 | status.errIfFailureAndReset("skey #1"); |
| 4013 | assertTrue("skey != nullptr", skey != nullptr); |
| 4014 | if (skey != nullptr) { |
| 4015 | assertEquals("calendar", "ca", *skey); |
| 4016 | } |
| 4017 | |
| 4018 | skey = keys->snext(status); |
| 4019 | status.errIfFailureAndReset("skey #2"); |
| 4020 | assertTrue("skey != nullptr", skey != nullptr); |
| 4021 | if (skey != nullptr) { |
| 4022 | assertEquals("collation", "co", *skey); |
| 4023 | } |
| 4024 | |
| 4025 | skey = keys->snext(status); |
| 4026 | status.errIfFailureAndReset("end of keys"); |
| 4027 | assertTrue("skey == nullptr", skey == nullptr); |
| 4028 | } |
| 4029 | |
| 4030 | |
| 4031 | void |
| 4032 | LocaleTest::TestKeywordVariantParsing(void) { |
| 4033 | static const struct { |
| 4034 | const char *localeID; |
| 4035 | const char *keyword; |
| 4036 | const char *expectedValue; |
| 4037 | } testCases[] = { |
| 4038 | { "de_DE@ C o ll A t i o n = Phonebook ", "collation", "Phonebook" }, |
| 4039 | { "de_DE", "collation", ""}, |
| 4040 | { "de_DE@collation= PHONEBOOK", "collation", "PHONEBOOK" }, |
| 4041 | { "de_DE@ currency = euro ; CoLLaTion = PHONEBOOk ", "collation", "PHONEBOOk" }, |
| 4042 | }; |
| 4043 | |
| 4044 | UErrorCode status = U_ZERO_ERROR; |
| 4045 | |
| 4046 | int32_t i = 0; |
| 4047 | int32_t resultLen = 0; |
| 4048 | char buffer[256]; |
| 4049 | |
| 4050 | for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { |
| 4051 | *buffer = 0; |
| 4052 | Locale l(testCases[i].localeID); |
| 4053 | resultLen = l.getKeywordValue(testCases[i].keyword, buffer, 256, status); |
| 4054 | (void)resultLen; // Suppress unused variable warning. |
| 4055 | if(uprv_strcmp(testCases[i].expectedValue, buffer) != 0) { |
| 4056 | err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n", |
| 4057 | testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer); |
| 4058 | } |
| 4059 | } |
| 4060 | } |
| 4061 | |
| 4062 | void |
| 4063 | LocaleTest::TestCreateKeywordSet(void) { |
| 4064 | IcuTestErrorCode status(*this, "TestCreateKeywordSet()"); |
| 4065 | |
| 4066 | static const Locale l("de@calendar=buddhist;collation=phonebook"); |
| 4067 | |
| 4068 | std::set<std::string> result; |
| 4069 | l.getKeywords<std::string>( |
| 4070 | std::insert_iterator<decltype(result)>(result, result.begin()), |
| 4071 | status); |
| 4072 | status.errIfFailureAndReset("\"%s\"", l.getName()); |
| 4073 | |
| 4074 | assertEquals("set::size()", 2, static_cast<int32_t>(result.size())); |
| 4075 | assertTrue("set::find(\"calendar\")", |
| 4076 | result.find("calendar") != result.end()); |
| 4077 | assertTrue("set::find(\"collation\")", |
| 4078 | result.find("collation") != result.end()); |
| 4079 | } |
| 4080 | |
| 4081 | void |
| 4082 | LocaleTest::TestCreateKeywordSetEmpty(void) { |
| 4083 | IcuTestErrorCode status(*this, "TestCreateKeywordSetEmpty()"); |
| 4084 | |
| 4085 | static const Locale l("de"); |
| 4086 | |
| 4087 | std::set<std::string> result; |
| 4088 | l.getKeywords<std::string>( |
| 4089 | std::insert_iterator<decltype(result)>(result, result.begin()), |
| 4090 | status); |
| 4091 | status.errIfFailureAndReset("\"%s\"", l.getName()); |
| 4092 | |
| 4093 | assertEquals("set::size()", 0, static_cast<int32_t>(result.size())); |
| 4094 | } |
| 4095 | |
| 4096 | void |
| 4097 | LocaleTest::TestCreateKeywordSetWithPrivateUse(void) { |
| 4098 | IcuTestErrorCode status(*this, "TestCreateKeywordSetWithPrivateUse()"); |
| 4099 | |
| 4100 | static const char tag[] = "en-US-u-ca-gregory-x-foo"; |
| 4101 | static const Locale l = Locale::forLanguageTag(tag, status); |
| 4102 | std::set<std::string> result; |
| 4103 | l.getKeywords<std::string>( |
| 4104 | std::insert_iterator<decltype(result)>(result, result.begin()), |
| 4105 | status); |
| 4106 | status.errIfFailureAndReset("getKeywords \"%s\"", l.getName()); |
| 4107 | assertTrue("getKeywords set::find(\"calendar\")", |
| 4108 | result.find("calendar") != result.end()); |
| 4109 | assertTrue("getKeywords set::find(\"ca\")", |
| 4110 | result.find("ca") == result.end()); |
| 4111 | assertTrue("getKeywords set::find(\"x\")", |
| 4112 | result.find("x") != result.end()); |
| 4113 | assertTrue("getKeywords set::find(\"foo\")", |
| 4114 | result.find("foo") == result.end()); |
| 4115 | } |
| 4116 | |
| 4117 | void |
| 4118 | LocaleTest::TestCreateUnicodeKeywordSet(void) { |
| 4119 | IcuTestErrorCode status(*this, "TestCreateUnicodeKeywordSet()"); |
| 4120 | |
| 4121 | static const Locale l("de@calendar=buddhist;collation=phonebook"); |
| 4122 | |
| 4123 | std::set<std::string> result; |
| 4124 | l.getUnicodeKeywords<std::string>( |
| 4125 | std::insert_iterator<decltype(result)>(result, result.begin()), |
| 4126 | status); |
| 4127 | status.errIfFailureAndReset("\"%s\"", l.getName()); |
| 4128 | |
| 4129 | assertEquals("set::size()", 2, static_cast<int32_t>(result.size())); |
| 4130 | assertTrue("set::find(\"ca\")", |
| 4131 | result.find("ca") != result.end()); |
| 4132 | assertTrue("set::find(\"co\")", |
| 4133 | result.find("co") != result.end()); |
| 4134 | } |
| 4135 | |
| 4136 | void |
| 4137 | LocaleTest::TestCreateUnicodeKeywordSetEmpty(void) { |
| 4138 | IcuTestErrorCode status(*this, "TestCreateUnicodeKeywordSetEmpty()"); |
| 4139 | |
| 4140 | static const Locale l("de"); |
| 4141 | |
| 4142 | std::set<std::string> result; |
| 4143 | l.getUnicodeKeywords<std::string>( |
| 4144 | std::insert_iterator<decltype(result)>(result, result.begin()), |
| 4145 | status); |
| 4146 | status.errIfFailureAndReset("\"%s\"", l.getName()); |
| 4147 | |
| 4148 | assertEquals("set::size()", 0, static_cast<int32_t>(result.size())); |
| 4149 | } |
| 4150 | |
| 4151 | void |
| 4152 | LocaleTest::TestCreateUnicodeKeywordSetWithPrivateUse(void) { |
| 4153 | IcuTestErrorCode status(*this, "TestCreateUnicodeKeywordSetWithPrivateUse()"); |
| 4154 | |
| 4155 | static const char tag[] = "en-US-u-ca-gregory-x-foo"; |
| 4156 | static const Locale l = Locale::forLanguageTag(tag, status); |
| 4157 | |
| 4158 | std::set<std::string> result; |
| 4159 | l.getUnicodeKeywords<std::string>( |
| 4160 | std::insert_iterator<decltype(result)>(result, result.begin()), |
| 4161 | status); |
| 4162 | status.errIfFailureAndReset("getUnicodeKeywords \"%s\"", l.getName()); |
| 4163 | assertTrue("getUnicodeKeywords set::find(\"ca\")", |
| 4164 | result.find("ca") != result.end()); |
| 4165 | assertTrue("getUnicodeKeywords set::find(\"x\")", |
| 4166 | result.find("x") == result.end()); |
| 4167 | assertTrue("getUnicodeKeywords set::find(\"foo\")", |
| 4168 | result.find("foo") == result.end()); |
| 4169 | } |
| 4170 | |
| 4171 | void |
| 4172 | LocaleTest::TestGetKeywordValueStdString(void) { |
| 4173 | IcuTestErrorCode status(*this, "TestGetKeywordValueStdString()"); |
| 4174 | |
| 4175 | static const char tag[] = "fa-u-nu-latn"; |
| 4176 | static const char keyword[] = "numbers"; |
| 4177 | static const char expected[] = "latn"; |
| 4178 | |
| 4179 | Locale l = Locale::forLanguageTag(tag, status); |
| 4180 | status.errIfFailureAndReset("\"%s\"", tag); |
| 4181 | |
| 4182 | std::string result = l.getKeywordValue<std::string>(keyword, status); |
| 4183 | status.errIfFailureAndReset("\"%s\"", keyword); |
| 4184 | assertEquals(keyword, expected, result.c_str()); |
| 4185 | } |
| 4186 | |
| 4187 | void |
| 4188 | LocaleTest::TestGetUnicodeKeywordValueStdString(void) { |
| 4189 | IcuTestErrorCode status(*this, "TestGetUnicodeKeywordValueStdString()"); |
| 4190 | |
| 4191 | static const char keyword[] = "co"; |
| 4192 | static const char expected[] = "phonebk"; |
| 4193 | |
| 4194 | static const Locale l("de@calendar=buddhist;collation=phonebook"); |
| 4195 | |
| 4196 | std::string result = l.getUnicodeKeywordValue<std::string>(keyword, status); |
| 4197 | status.errIfFailureAndReset("\"%s\"", keyword); |
| 4198 | assertEquals(keyword, expected, result.c_str()); |
| 4199 | } |
| 4200 | |
| 4201 | void |
| 4202 | LocaleTest::TestSetKeywordValue(void) { |
| 4203 | static const struct { |
| 4204 | const char *keyword; |
| 4205 | const char *value; |
| 4206 | } testCases[] = { |
| 4207 | { "collation", "phonebook" }, |
| 4208 | { "currency", "euro" }, |
| 4209 | { "calendar", "buddhist" } |
| 4210 | }; |
| 4211 | |
| 4212 | IcuTestErrorCode status(*this, "TestSetKeywordValue()"); |
| 4213 | |
| 4214 | int32_t i = 0; |
| 4215 | int32_t resultLen = 0; |
| 4216 | char buffer[256]; |
| 4217 | |
| 4218 | Locale l(Locale::getGerman()); |
| 4219 | |
| 4220 | for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { |
| 4221 | l.setKeywordValue(testCases[i].keyword, testCases[i].value, status); |
| 4222 | if(U_FAILURE(status)) { |
| 4223 | err("FAIL: Locale::setKeywordValue failed - %s\n", u_errorName(status)); |
| 4224 | } |
| 4225 | |
| 4226 | *buffer = 0; |
| 4227 | resultLen = l.getKeywordValue(testCases[i].keyword, buffer, 256, status); |
| 4228 | (void)resultLen; // Suppress unused variable warning. |
| 4229 | if(uprv_strcmp(testCases[i].value, buffer) != 0) { |
| 4230 | err("Expected to extract \"%s\" for keyword \"%s\". Got \"%s\" instead\n", |
| 4231 | testCases[i].value, testCases[i].keyword, buffer); |
| 4232 | } |
| 4233 | } |
| 4234 | |
| 4235 | // Test long locale |
| 4236 | { |
| 4237 | status.errIfFailureAndReset(); |
| 4238 | const char* input = |
| 4239 | "de__POSIX@colnormalization=no;colstrength=primary;currency=eur;" |
| 4240 | "em=default;kv=space;lb=strict;lw=normal;measure=metric;" |
| 4241 | "numbers=latn;rg=atzzzz;sd=atat1"; |
| 4242 | const char* expected = |
| 4243 | "de__POSIX@colnormalization=no;colstrength=primary;currency=eur;" |
| 4244 | "em=default;kv=space;lb=strict;lw=normal;measure=metric;" |
| 4245 | "numbers=latn;rg=atzzzz;sd=atat1;ss=none"; |
| 4246 | // Bug ICU-21385 |
| 4247 | Locale l2(input); |
| 4248 | l2.setKeywordValue("ss", "none", status); |
| 4249 | assertEquals("", expected, l2.getName()); |
| 4250 | status.errIfFailureAndReset(); |
| 4251 | } |
| 4252 | } |
| 4253 | |
| 4254 | void |
| 4255 | LocaleTest::TestSetKeywordValueStringPiece(void) { |
| 4256 | IcuTestErrorCode status(*this, "TestSetKeywordValueStringPiece()"); |
| 4257 | Locale l(Locale::getGerman()); |
| 4258 | |
| 4259 | l.setKeywordValue(StringPiece("collation"), StringPiece("phonebook"), status); |
| 4260 | l.setKeywordValue(StringPiece("calendarxxx", 8), StringPiece("buddhistxxx", 8), status); |
| 4261 | |
| 4262 | static const char expected[] = "de@calendar=buddhist;collation=phonebook"; |
| 4263 | assertEquals("", expected, l.getName()); |
| 4264 | } |
| 4265 | |
| 4266 | void |
| 4267 | LocaleTest::TestSetUnicodeKeywordValueStringPiece(void) { |
| 4268 | IcuTestErrorCode status(*this, "TestSetUnicodeKeywordValueStringPiece()"); |
| 4269 | Locale l(Locale::getGerman()); |
| 4270 | |
| 4271 | l.setUnicodeKeywordValue(StringPiece("co"), StringPiece("phonebk"), status); |
| 4272 | status.errIfFailureAndReset(); |
| 4273 | |
| 4274 | l.setUnicodeKeywordValue(StringPiece("caxxx", 2), StringPiece("buddhistxxx", 8), status); |
| 4275 | status.errIfFailureAndReset(); |
| 4276 | |
| 4277 | static const char expected[] = "de@calendar=buddhist;collation=phonebook"; |
| 4278 | assertEquals("", expected, l.getName()); |
| 4279 | |
| 4280 | l.setUnicodeKeywordValue("cu", nullptr, status); |
| 4281 | status.errIfFailureAndReset(); |
| 4282 | assertEquals("", expected, l.getName()); |
| 4283 | |
| 4284 | l.setUnicodeKeywordValue("!!", nullptr, status); |
| 4285 | assertEquals("status", U_ILLEGAL_ARGUMENT_ERROR, status.reset()); |
| 4286 | assertEquals("", expected, l.getName()); |
| 4287 | |
| 4288 | l.setUnicodeKeywordValue("co", "!!", status); |
| 4289 | assertEquals("status", U_ILLEGAL_ARGUMENT_ERROR, status.reset()); |
| 4290 | assertEquals("", expected, l.getName()); |
| 4291 | |
| 4292 | l.setUnicodeKeywordValue("co", nullptr, status); |
| 4293 | status.errIfFailureAndReset(); |
| 4294 | |
| 4295 | l.setUnicodeKeywordValue("ca", "", status); |
| 4296 | status.errIfFailureAndReset(); |
| 4297 | |
| 4298 | assertEquals("", Locale::getGerman().getName(), l.getName()); |
| 4299 | } |
| 4300 | |
| 4301 | void |
| 4302 | LocaleTest::TestGetBaseName(void) { |
| 4303 | static const struct { |
| 4304 | const char *localeID; |
| 4305 | const char *baseName; |
| 4306 | } testCases[] = { |
| 4307 | { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" }, |
| 4308 | { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" }, |
| 4309 | { "ja@calendar = buddhist", "ja" }, |
| 4310 | { "de-u-co-phonebk", "de"} |
| 4311 | }; |
| 4312 | |
| 4313 | int32_t i = 0; |
| 4314 | |
| 4315 | for(i = 0; i < UPRV_LENGTHOF(testCases); i++) { |
| 4316 | Locale loc(testCases[i].localeID); |
| 4317 | if(strcmp(testCases[i].baseName, loc.getBaseName())) { |
| 4318 | errln("For locale \"%s\" expected baseName \"%s\", but got \"%s\"", |
| 4319 | testCases[i].localeID, testCases[i].baseName, loc.getBaseName()); |
| 4320 | return; |
| 4321 | } |
| 4322 | } |
| 4323 | |
| 4324 | // Verify that adding a keyword to an existing Locale doesn't change the base name. |
| 4325 | UErrorCode status = U_ZERO_ERROR; |
| 4326 | Locale loc2("en-US"); |
| 4327 | if (strcmp("en_US", loc2.getBaseName())) { |
| 4328 | errln("%s:%d Expected \"en_US\", got \"%s\"", __FILE__, __LINE__, loc2.getBaseName()); |
| 4329 | } |
| 4330 | loc2.setKeywordValue("key", "value", status); |
| 4331 | if (strcmp("en_US@key=value", loc2.getName())) { |
| 4332 | errln("%s:%d Expected \"en_US@key=value\", got \"%s\"", __FILE__, __LINE__, loc2.getName()); |
| 4333 | } |
| 4334 | if (strcmp("en_US", loc2.getBaseName())) { |
| 4335 | errln("%s:%d Expected \"en_US\", got \"%s\"", __FILE__, __LINE__, loc2.getBaseName()); |
| 4336 | } |
| 4337 | } |
| 4338 | |
| 4339 | /** |
| 4340 | * Compare two locale IDs. If they are equal, return 0. If `string' |
| 4341 | * starts with `prefix' plus an additional element, that is, string == |
| 4342 | * prefix + '_' + x, then return 1. Otherwise return a value < 0. |
| 4343 | */ |
| 4344 | static UBool _loccmp(const char* string, const char* prefix) { |
| 4345 | int32_t slen = (int32_t)strlen(string), |
| 4346 | plen = (int32_t)strlen(prefix); |
| 4347 | int32_t c = uprv_strncmp(string, prefix, plen); |
| 4348 | /* 'root' is "less than" everything */ |
| 4349 | if (prefix[0] == '\0') { |
| 4350 | return string[0] != '\0'; |
| 4351 | } |
| 4352 | if (c) return -1; /* mismatch */ |
| 4353 | if (slen == plen) return 0; |
| 4354 | if (string[plen] == '_') return 1; |
| 4355 | return -2; /* false match, e.g. "en_USX" cmp "en_US" */ |
| 4356 | } |
| 4357 | |
| 4358 | /** |
| 4359 | * Check the relationship between requested locales, and report problems. |
| 4360 | * The caller specifies the expected relationships between requested |
| 4361 | * and valid (expReqValid) and between valid and actual (expValidActual). |
| 4362 | * Possible values are: |
| 4363 | * "gt" strictly greater than, e.g., en_US > en |
| 4364 | * "ge" greater or equal, e.g., en >= en |
| 4365 | * "eq" equal, e.g., en == en |
| 4366 | */ |
| 4367 | void LocaleTest::_checklocs(const char* label, |
| 4368 | const char* req, |
| 4369 | const Locale& validLoc, |
| 4370 | const Locale& actualLoc, |
| 4371 | const char* expReqValid, |
| 4372 | const char* expValidActual) { |
| 4373 | const char* valid = validLoc.getName(); |
| 4374 | const char* actual = actualLoc.getName(); |
| 4375 | int32_t reqValid = _loccmp(req, valid); |
| 4376 | int32_t validActual = _loccmp(valid, actual); |
| 4377 | if (((0 == uprv_strcmp(expReqValid, "gt") && reqValid > 0) || |
| 4378 | (0 == uprv_strcmp(expReqValid, "ge") && reqValid >= 0) || |
| 4379 | (0 == uprv_strcmp(expReqValid, "eq") && reqValid == 0)) && |
| 4380 | ((0 == uprv_strcmp(expValidActual, "gt") && validActual > 0) || |
| 4381 | (0 == uprv_strcmp(expValidActual, "ge") && validActual >= 0) || |
| 4382 | (0 == uprv_strcmp(expValidActual, "eq") && validActual == 0))) { |
| 4383 | logln("%s; req=%s, valid=%s, actual=%s", |
| 4384 | label, req, valid, actual); |
| 4385 | } else { |
| 4386 | dataerrln("FAIL: %s; req=%s, valid=%s, actual=%s. Require (R %s V) and (V %s A)", |
| 4387 | label, req, valid, actual, |
| 4388 | expReqValid, expValidActual); |
| 4389 | } |
| 4390 | } |
| 4391 | |
| 4392 | void LocaleTest::TestGetLocale(void) { |
| 4393 | #if !UCONFIG_NO_SERVICE |
| 4394 | const char *req; |
| 4395 | Locale valid, actual, reqLoc; |
| 4396 | |
| 4397 | // Calendar |
| 4398 | #if !UCONFIG_NO_FORMATTING |
| 4399 | { |
| 4400 | UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code |
| 4401 | req = "en_US_BROOKLYN"; |
| 4402 | Calendar* cal = Calendar::createInstance(Locale::createFromName(req), ec); |
| 4403 | if (U_FAILURE(ec)) { |
| 4404 | dataerrln("FAIL: Calendar::createInstance failed - %s", u_errorName(ec)); |
| 4405 | } else { |
| 4406 | valid = cal->getLocale(ULOC_VALID_LOCALE, ec); |
| 4407 | actual = cal->getLocale(ULOC_ACTUAL_LOCALE, ec); |
| 4408 | if (U_FAILURE(ec)) { |
| 4409 | errln("FAIL: Calendar::getLocale() failed"); |
| 4410 | } else { |
| 4411 | _checklocs("Calendar", req, valid, actual); |
| 4412 | } |
| 4413 | /* Make sure that it fails correctly */ |
| 4414 | ec = U_FILE_ACCESS_ERROR; |
| 4415 | if (cal->getLocale(ULOC_VALID_LOCALE, ec).getName()[0] != 0) { |
| 4416 | errln("FAIL: Calendar::getLocale() failed to fail correctly. It should have returned \"\""); |
| 4417 | } |
| 4418 | ec = U_ZERO_ERROR; |
| 4419 | } |
| 4420 | delete cal; |
| 4421 | } |
| 4422 | #endif |
| 4423 | |
| 4424 | // DecimalFormat, DecimalFormatSymbols |
| 4425 | #if !UCONFIG_NO_FORMATTING |
| 4426 | { |
| 4427 | UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code |
| 4428 | req = "fr_FR_NICE"; |
| 4429 | NumberFormat* nf = NumberFormat::createInstance(Locale::createFromName(req), ec); |
| 4430 | if (U_FAILURE(ec)) { |
| 4431 | dataerrln("FAIL: NumberFormat::createInstance failed - %s", u_errorName(ec)); |
| 4432 | } else { |
| 4433 | DecimalFormat* dec = dynamic_cast<DecimalFormat*>(nf); |
| 4434 | if (dec == NULL) { |
| 4435 | errln("FAIL: NumberFormat::createInstance does not return a DecimalFormat"); |
| 4436 | return; |
| 4437 | } |
| 4438 | valid = dec->getLocale(ULOC_VALID_LOCALE, ec); |
| 4439 | actual = dec->getLocale(ULOC_ACTUAL_LOCALE, ec); |
| 4440 | if (U_FAILURE(ec)) { |
| 4441 | errln("FAIL: DecimalFormat::getLocale() failed"); |
| 4442 | } else { |
| 4443 | _checklocs("DecimalFormat", req, valid, actual); |
| 4444 | } |
| 4445 | |
| 4446 | const DecimalFormatSymbols* sym = dec->getDecimalFormatSymbols(); |
| 4447 | if (sym == NULL) { |
| 4448 | errln("FAIL: getDecimalFormatSymbols returned NULL"); |
| 4449 | return; |
| 4450 | } |
| 4451 | valid = sym->getLocale(ULOC_VALID_LOCALE, ec); |
| 4452 | actual = sym->getLocale(ULOC_ACTUAL_LOCALE, ec); |
| 4453 | if (U_FAILURE(ec)) { |
| 4454 | errln("FAIL: DecimalFormatSymbols::getLocale() failed"); |
| 4455 | } else { |
| 4456 | _checklocs("DecimalFormatSymbols", req, valid, actual); |
| 4457 | } |
| 4458 | } |
| 4459 | delete nf; |
| 4460 | } |
| 4461 | #endif |
| 4462 | |
| 4463 | // DateFormat, DateFormatSymbols |
| 4464 | #if !UCONFIG_NO_FORMATTING |
| 4465 | { |
| 4466 | UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code |
| 4467 | req = "de_CH_LUCERNE"; |
| 4468 | DateFormat* df = |
| 4469 | DateFormat::createDateInstance(DateFormat::kDefault, |
| 4470 | Locale::createFromName(req)); |
| 4471 | if (df == 0){ |
| 4472 | dataerrln("Error calling DateFormat::createDateInstance()"); |
| 4473 | } else { |
| 4474 | SimpleDateFormat* dat = dynamic_cast<SimpleDateFormat*>(df); |
| 4475 | if (dat == NULL) { |
| 4476 | errln("FAIL: DateFormat::createInstance does not return a SimpleDateFormat"); |
| 4477 | return; |
| 4478 | } |
| 4479 | valid = dat->getLocale(ULOC_VALID_LOCALE, ec); |
| 4480 | actual = dat->getLocale(ULOC_ACTUAL_LOCALE, ec); |
| 4481 | if (U_FAILURE(ec)) { |
| 4482 | errln("FAIL: SimpleDateFormat::getLocale() failed"); |
| 4483 | } else { |
| 4484 | _checklocs("SimpleDateFormat", req, valid, actual); |
| 4485 | } |
| 4486 | |
| 4487 | const DateFormatSymbols* sym = dat->getDateFormatSymbols(); |
| 4488 | if (sym == NULL) { |
| 4489 | errln("FAIL: getDateFormatSymbols returned NULL"); |
| 4490 | return; |
| 4491 | } |
| 4492 | valid = sym->getLocale(ULOC_VALID_LOCALE, ec); |
| 4493 | actual = sym->getLocale(ULOC_ACTUAL_LOCALE, ec); |
| 4494 | if (U_FAILURE(ec)) { |
| 4495 | errln("FAIL: DateFormatSymbols::getLocale() failed"); |
| 4496 | } else { |
| 4497 | _checklocs("DateFormatSymbols", req, valid, actual); |
| 4498 | } |
| 4499 | } |
| 4500 | delete df; |
| 4501 | } |
| 4502 | #endif |
| 4503 | |
| 4504 | // BreakIterator |
| 4505 | #if !UCONFIG_NO_BREAK_ITERATION |
| 4506 | { |
| 4507 | UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code |
| 4508 | req = "es_ES_BARCELONA"; |
| 4509 | reqLoc = Locale::createFromName(req); |
| 4510 | BreakIterator* brk = BreakIterator::createWordInstance(reqLoc, ec); |
| 4511 | if (U_FAILURE(ec)) { |
| 4512 | dataerrln("FAIL: BreakIterator::createWordInstance failed - %s", u_errorName(ec)); |
| 4513 | } else { |
| 4514 | valid = brk->getLocale(ULOC_VALID_LOCALE, ec); |
| 4515 | actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec); |
| 4516 | if (U_FAILURE(ec)) { |
| 4517 | errln("FAIL: BreakIterator::getLocale() failed"); |
| 4518 | } else { |
| 4519 | _checklocs("BreakIterator", req, valid, actual); |
| 4520 | } |
| 4521 | |
| 4522 | // After registering something, the behavior should be different |
| 4523 | URegistryKey key = BreakIterator::registerInstance(brk, reqLoc, UBRK_WORD, ec); |
| 4524 | brk = 0; // registerInstance adopts |
| 4525 | if (U_FAILURE(ec)) { |
| 4526 | errln("FAIL: BreakIterator::registerInstance() failed"); |
| 4527 | } else { |
| 4528 | brk = BreakIterator::createWordInstance(reqLoc, ec); |
| 4529 | if (U_FAILURE(ec)) { |
| 4530 | errln("FAIL: BreakIterator::createWordInstance failed"); |
| 4531 | } else { |
| 4532 | valid = brk->getLocale(ULOC_VALID_LOCALE, ec); |
| 4533 | actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec); |
| 4534 | if (U_FAILURE(ec)) { |
| 4535 | errln("FAIL: BreakIterator::getLocale() failed"); |
| 4536 | } else { |
| 4537 | // N.B.: now expect valid==actual==req |
| 4538 | _checklocs("BreakIterator(registered)", |
| 4539 | req, valid, actual, "eq", "eq"); |
| 4540 | } |
| 4541 | } |
| 4542 | // No matter what, unregister |
| 4543 | BreakIterator::unregister(key, ec); |
| 4544 | if (U_FAILURE(ec)) { |
| 4545 | errln("FAIL: BreakIterator::unregister() failed"); |
| 4546 | } |
| 4547 | delete brk; |
| 4548 | brk = 0; |
| 4549 | } |
| 4550 | |
| 4551 | // After unregistering, should behave normally again |
| 4552 | brk = BreakIterator::createWordInstance(reqLoc, ec); |
| 4553 | if (U_FAILURE(ec)) { |
| 4554 | errln("FAIL: BreakIterator::createWordInstance failed"); |
| 4555 | } else { |
| 4556 | valid = brk->getLocale(ULOC_VALID_LOCALE, ec); |
| 4557 | actual = brk->getLocale(ULOC_ACTUAL_LOCALE, ec); |
| 4558 | if (U_FAILURE(ec)) { |
| 4559 | errln("FAIL: BreakIterator::getLocale() failed"); |
| 4560 | } else { |
| 4561 | _checklocs("BreakIterator(unregistered)", req, valid, actual); |
| 4562 | } |
| 4563 | } |
| 4564 | } |
| 4565 | delete brk; |
| 4566 | } |
| 4567 | #endif |
| 4568 | |
| 4569 | // Collator |
| 4570 | #if !UCONFIG_NO_COLLATION |
| 4571 | { |
| 4572 | UErrorCode ec = U_ZERO_ERROR; // give each resource type its own error code |
| 4573 | |
| 4574 | checkRegisteredCollators(NULL); // Don't expect any extras |
| 4575 | |
| 4576 | req = "hi_IN_BHOPAL"; |
| 4577 | reqLoc = Locale::createFromName(req); |
| 4578 | Collator* coll = Collator::createInstance(reqLoc, ec); |
| 4579 | if (U_FAILURE(ec)) { |
| 4580 | dataerrln("FAIL: Collator::createInstance failed - %s", u_errorName(ec)); |
| 4581 | } else { |
| 4582 | valid = coll->getLocale(ULOC_VALID_LOCALE, ec); |
| 4583 | actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec); |
| 4584 | if (U_FAILURE(ec)) { |
| 4585 | errln("FAIL: Collator::getLocale() failed"); |
| 4586 | } else { |
| 4587 | _checklocs("Collator", req, valid, actual); |
| 4588 | } |
| 4589 | |
| 4590 | // After registering something, the behavior should be different |
| 4591 | URegistryKey key = Collator::registerInstance(coll, reqLoc, ec); |
| 4592 | coll = 0; // registerInstance adopts |
| 4593 | if (U_FAILURE(ec)) { |
| 4594 | errln("FAIL: Collator::registerInstance() failed"); |
| 4595 | } else { |
| 4596 | coll = Collator::createInstance(reqLoc, ec); |
| 4597 | if (U_FAILURE(ec)) { |
| 4598 | errln("FAIL: Collator::createWordInstance failed"); |
| 4599 | } else { |
| 4600 | valid = coll->getLocale(ULOC_VALID_LOCALE, ec); |
| 4601 | actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec); |
| 4602 | if (U_FAILURE(ec)) { |
| 4603 | errln("FAIL: Collator::getLocale() failed"); |
| 4604 | } else { |
| 4605 | // N.B.: now expect valid==actual==req |
| 4606 | _checklocs("Collator(registered)", |
| 4607 | req, valid, actual, "eq", "eq"); |
| 4608 | } |
| 4609 | } |
| 4610 | checkRegisteredCollators(req); // include hi_IN_BHOPAL |
| 4611 | |
| 4612 | // No matter what, unregister |
| 4613 | Collator::unregister(key, ec); |
| 4614 | if (U_FAILURE(ec)) { |
| 4615 | errln("FAIL: Collator::unregister() failed"); |
| 4616 | } |
| 4617 | delete coll; |
| 4618 | coll = 0; |
| 4619 | } |
| 4620 | |
| 4621 | // After unregistering, should behave normally again |
| 4622 | coll = Collator::createInstance(reqLoc, ec); |
| 4623 | if (U_FAILURE(ec)) { |
| 4624 | errln("FAIL: Collator::createInstance failed"); |
| 4625 | } else { |
| 4626 | valid = coll->getLocale(ULOC_VALID_LOCALE, ec); |
| 4627 | actual = coll->getLocale(ULOC_ACTUAL_LOCALE, ec); |
| 4628 | if (U_FAILURE(ec)) { |
| 4629 | errln("FAIL: Collator::getLocale() failed"); |
| 4630 | } else { |
| 4631 | _checklocs("Collator(unregistered)", req, valid, actual); |
| 4632 | } |
| 4633 | } |
| 4634 | } |
| 4635 | delete coll; |
| 4636 | |
| 4637 | checkRegisteredCollators(NULL); // extra should be gone again |
| 4638 | } |
| 4639 | #endif |
| 4640 | #endif |
| 4641 | } |
| 4642 | |
| 4643 | #if !UCONFIG_NO_COLLATION |
| 4644 | /** |
| 4645 | * Compare Collator::getAvailableLocales(int) [ "old", returning an array ] |
| 4646 | * with Collator::getAvailableLocales() [ "new", returning a StringEnumeration ] |
| 4647 | * These should be identical (check their API docs) EXCEPT that |
| 4648 | * if expectExtra is non-NULL, it will be in the "new" array but not "old". |
| 4649 | * Does not return any status but calls errln on error. |
| 4650 | * @param expectExtra an extra locale, will be in "new" but not "old". Or NULL. |
| 4651 | */ |
| 4652 | void LocaleTest::checkRegisteredCollators(const char *expectExtra) { |
| 4653 | UErrorCode status = U_ZERO_ERROR; |
| 4654 | int32_t count1=0,count2=0; |
| 4655 | Hashtable oldHash(status); |
| 4656 | Hashtable newHash(status); |
| 4657 | assertSuccess(WHERE, status); |
| 4658 | |
| 4659 | UnicodeString expectStr(expectExtra?expectExtra:"n/a", ""); |
| 4660 | |
| 4661 | // the 'old' list (non enumeration) |
| 4662 | const Locale* oldList = Collator::getAvailableLocales(count1); |
| 4663 | if(oldList == NULL) { |
| 4664 | dataerrln("Error: Collator::getAvailableLocales(count) returned NULL"); |
| 4665 | return; |
| 4666 | } |
| 4667 | |
| 4668 | // the 'new' list (enumeration) |
| 4669 | LocalPointer<StringEnumeration> newEnum(Collator::getAvailableLocales()); |
| 4670 | if(newEnum.isNull()) { |
| 4671 | errln("Error: collator::getAvailableLocales() returned NULL"); |
| 4672 | return; |
| 4673 | } |
| 4674 | |
| 4675 | // OK. Let's add all of the OLD |
| 4676 | // then check for any in the NEW not in OLD |
| 4677 | // then check for any in OLD not in NEW. |
| 4678 | |
| 4679 | // 1. add all of OLD |
| 4680 | for(int32_t i=0;i<count1;i++) { |
| 4681 | const UnicodeString key(oldList[i].getName(), ""); |
| 4682 | int32_t oldI = oldHash.puti(key, 1, status); |
| 4683 | if( oldI == 1 ){ |
| 4684 | errln("Error: duplicate key %s in Collator::getAvailableLocales(count) list.\n", |
| 4685 | oldList[i].getName()); |
| 4686 | return; |
| 4687 | } |
| 4688 | if(expectExtra != NULL && !strcmp(expectExtra, oldList[i].getName())) { |
| 4689 | errln("Inexplicably, Collator::getAvailableCollators(count) had registered collator %s. This shouldn't happen, so I am going to consider it an error.\n", expectExtra); |
| 4690 | } |
| 4691 | } |
| 4692 | |
| 4693 | // 2. add all of NEW |
| 4694 | const UnicodeString *locStr; |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 4695 | UBool foundExpected = false; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 4696 | while((locStr = newEnum->snext(status)) && U_SUCCESS(status)) { |
| 4697 | count2++; |
| 4698 | |
| 4699 | if(expectExtra != NULL && expectStr == *locStr) { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 4700 | foundExpected = true; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 4701 | logln(UnicodeString("Found expected registered collator: ","") + expectStr); |
| 4702 | } |
| 4703 | (void)foundExpected; // Hush unused variable compiler warning. |
| 4704 | |
| 4705 | if( oldHash.geti(*locStr) == 0 ) { |
| 4706 | if(expectExtra != NULL && expectStr==*locStr) { |
| 4707 | logln(UnicodeString("As expected, Collator::getAvailableLocales(count) is missing registered collator ") + expectStr); |
| 4708 | } else { |
| 4709 | errln(UnicodeString("Error: Collator::getAvailableLocales(count) is missing: ","") |
| 4710 | + *locStr); |
| 4711 | } |
| 4712 | } |
| 4713 | newHash.puti(*locStr, 1, status); |
| 4714 | } |
| 4715 | |
| 4716 | // 3. check all of OLD again |
| 4717 | for(int32_t i=0;i<count1;i++) { |
| 4718 | const UnicodeString key(oldList[i].getName(), ""); |
| 4719 | int32_t newI = newHash.geti(key); |
| 4720 | if(newI == 0) { |
| 4721 | errln(UnicodeString("Error: Collator::getAvailableLocales() is missing: ","") |
| 4722 | + key); |
| 4723 | } |
| 4724 | } |
| 4725 | |
| 4726 | int32_t expectCount2 = count1; |
| 4727 | if(expectExtra != NULL) { |
| 4728 | expectCount2 ++; // if an extra item registered, bump the expect count |
| 4729 | } |
| 4730 | |
| 4731 | assertEquals("Collator::getAvail() count", expectCount2, count2); |
| 4732 | } |
| 4733 | #endif |
| 4734 | |
| 4735 | |
| 4736 | |
| 4737 | void LocaleTest::TestVariantWithOutCountry(void) { |
| 4738 | Locale loc("en","","POSIX"); |
| 4739 | if (0 != strcmp(loc.getVariant(), "POSIX")) { |
| 4740 | errln("FAIL: en__POSIX didn't get parsed correctly - name is %s - expected %s got %s", loc.getName(), "POSIX", loc.getVariant()); |
| 4741 | } |
| 4742 | Locale loc2("en","","FOUR"); |
| 4743 | if (0 != strcmp(loc2.getVariant(), "FOUR")) { |
| 4744 | errln("FAIL: en__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc2.getName(), "FOUR", loc2.getVariant()); |
| 4745 | } |
| 4746 | Locale loc3("en","Latn","","FOUR"); |
| 4747 | if (0 != strcmp(loc3.getVariant(), "FOUR")) { |
| 4748 | errln("FAIL: en_Latn__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc3.getName(), "FOUR", loc3.getVariant()); |
| 4749 | } |
| 4750 | Locale loc4("","Latn","","FOUR"); |
| 4751 | if (0 != strcmp(loc4.getVariant(), "FOUR")) { |
| 4752 | errln("FAIL: _Latn__FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc4.getName(), "FOUR", loc4.getVariant()); |
| 4753 | } |
| 4754 | Locale loc5("","Latn","US","FOUR"); |
| 4755 | if (0 != strcmp(loc5.getVariant(), "FOUR")) { |
| 4756 | errln("FAIL: _Latn_US_FOUR didn't get parsed correctly - name is %s - expected %s got %s", loc5.getName(), "FOUR", loc5.getVariant()); |
| 4757 | } |
| 4758 | Locale loc6("de-1901"); |
| 4759 | if (0 != strcmp(loc6.getVariant(), "1901")) { |
| 4760 | errln("FAIL: de-1901 didn't get parsed correctly - name is %s - expected %s got %s", loc6.getName(), "1901", loc6.getVariant()); |
| 4761 | } |
| 4762 | } |
| 4763 | |
| 4764 | static Locale _canonicalize(int32_t selector, /* 0==createFromName, 1==createCanonical, 2==Locale ct */ |
| 4765 | const char* localeID) { |
| 4766 | switch (selector) { |
| 4767 | case 0: |
| 4768 | return Locale::createFromName(localeID); |
| 4769 | case 1: |
| 4770 | return Locale::createCanonical(localeID); |
| 4771 | case 2: |
| 4772 | return Locale(localeID); |
| 4773 | default: |
| 4774 | return Locale(""); |
| 4775 | } |
| 4776 | } |
| 4777 | |
| 4778 | void LocaleTest::TestCanonicalization(void) |
| 4779 | { |
| 4780 | static const struct { |
| 4781 | const char *localeID; /* input */ |
| 4782 | const char *getNameID; /* expected getName() result */ |
| 4783 | const char *canonicalID; /* expected canonicalize() result */ |
| 4784 | } testCases[] = { |
| 4785 | { "ca_ES-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage", |
| 4786 | "ca_ES_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE", |
| 4787 | "ca_ES_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_WITH_YOU'RE TRYING TO INCREASE CODE COVERAGE"}, |
| 4788 | { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" }, |
| 4789 | { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" }, |
| 4790 | { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" }, |
| 4791 | { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" }, |
| 4792 | { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" }, |
| 4793 | { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ }, |
| 4794 | { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */ |
| 4795 | { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" }, /* POSIX ID */ |
| 4796 | { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ_EURO" }, /* qz-qz uses private use iso codes */ |
| 4797 | // NOTE: uloc_getName() works on en-BOONT, but Locale() parser considers it BOGUS |
| 4798 | // TODO: unify this behavior |
| 4799 | { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */ |
| 4800 | { "de-1901", "de__1901", "de__1901" }, /* registered name */ |
| 4801 | { "de-1906", "de__1906", "de__1906" }, /* registered name */ |
| 4802 | // New in CLDR 39 / ICU 69 |
| 4803 | { "nb", "nb", "nb" }, |
| 4804 | |
| 4805 | /* posix behavior that used to be performed by getName */ |
| 4806 | { "mr.utf8", "mr.utf8", "mr" }, |
| 4807 | { "de-tv.koi8r", "de_TV.koi8r", "de_TV" }, |
| 4808 | { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" }, |
| 4809 | { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" }, |
| 4810 | { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" }, |
| 4811 | { "no-no-ny.utf8@B", "no_NO_NY.utf8@B", "no_NO@b=ny" /* not: "nn_NO" [alan ICU3.0] */ }, /* @ ignored unless variant is empty */ |
| 4812 | |
| 4813 | /* fleshing out canonicalization */ |
| 4814 | /* trim space and sort keywords, ';' is separator so not present at end in canonical form */ |
| 4815 | { "en_Hant_IL_VALLEY_GIRL@ currency = EUR; calendar = Japanese ;", |
| 4816 | "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", |
| 4817 | "en_Hant_IL_GIRL_VALLEY@calendar=Japanese;currency=EUR" }, |
| 4818 | /* already-canonical ids are not changed */ |
| 4819 | { "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", |
| 4820 | "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", |
| 4821 | "en_Hant_IL_GIRL_VALLEY@calendar=Japanese;currency=EUR" }, |
| 4822 | /* norwegian is just too weird, if we handle things in their full generality */ |
| 4823 | { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ }, |
| 4824 | |
| 4825 | /* test cases reflecting internal resource bundle usage */ |
| 4826 | { "root@kw=foo", "root@kw=foo", "root@kw=foo" }, |
| 4827 | { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" }, |
| 4828 | { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" }, |
| 4829 | |
| 4830 | // Before ICU 64, ICU locale canonicalization had some additional mappings. |
| 4831 | // They were removed for ICU-20187 "drop support for long-obsolete locale ID variants". |
| 4832 | // The following now use standard canonicalization. |
| 4833 | { "", "", "" }, |
| 4834 | { "C", "c", "c" }, |
| 4835 | { "POSIX", "posix", "posix" }, |
| 4836 | { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES_PREEURO" }, |
| 4837 | { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT_PREEURO" }, |
| 4838 | { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE_PREEURO" }, |
| 4839 | { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU_PREEURO" }, |
| 4840 | { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR_PREEURO" }, |
| 4841 | { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE_PREEURO" }, |
| 4842 | { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE_PREEURO" }, |
| 4843 | { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES_PREEURO" }, |
| 4844 | { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES_PREEURO" }, |
| 4845 | { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI_PREEURO" }, |
| 4846 | { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE_PREEURO" }, |
| 4847 | { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR_PREEURO" }, |
| 4848 | { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU_PREEURO" }, |
| 4849 | { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE_PREEURO" }, |
| 4850 | { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES_PREEURO" }, |
| 4851 | { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT_PREEURO" }, |
| 4852 | { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE_PREEURO" }, |
| 4853 | { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL_PREEURO" }, |
| 4854 | { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT_PREEURO" }, |
| 4855 | { "de__PHONEBOOK", "de__PHONEBOOK", "de__PHONEBOOK" }, |
| 4856 | { "en_GB_EURO", "en_GB_EURO", "en_GB_EURO" }, |
| 4857 | { "en_GB@EURO", "en_GB@EURO", "en_GB_EURO" }, /* POSIX ID */ |
| 4858 | { "es__TRADITIONAL", "es__TRADITIONAL", "es__TRADITIONAL" }, |
| 4859 | { "hi__DIRECT", "hi__DIRECT", "hi__DIRECT" }, |
| 4860 | { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL" }, |
| 4861 | { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH_TRADITIONAL" }, |
| 4862 | { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW_STROKE" }, |
| 4863 | { "zh__PINYIN", "zh__PINYIN", "zh__PINYIN" }, |
| 4864 | { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_SP_CYRL" }, /* .NET name */ |
| 4865 | { "sr-SP-Latn", "sr_SP_LATN", "sr_SP_LATN" }, /* .NET name */ |
| 4866 | { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_RS_CYRILLIC" }, /* Linux name */ |
| 4867 | { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_UZ_CYRL" }, /* .NET name */ |
| 4868 | { "uz-UZ-Latn", "uz_UZ_LATN", "uz_UZ_LATN" }, /* .NET name */ |
| 4869 | { "zh-CHS", "zh_CHS", "zh_CHS" }, /* .NET name */ |
| 4870 | { "zh-CHT", "zh_CHT", "zh_CHT" }, /* .NET name This may change back to zh_Hant */ |
| 4871 | /* PRE_EURO and EURO conversions don't affect other keywords */ |
| 4872 | { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES_PREEURO@calendar=Japanese" }, |
| 4873 | { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah" }, |
| 4874 | /* currency keyword overrides PRE_EURO and EURO currency */ |
| 4875 | { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR" }, |
| 4876 | { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP" }, |
| 4877 | }; |
| 4878 | |
| 4879 | static const char* label[] = { "createFromName", "createCanonical", "Locale" }; |
| 4880 | |
| 4881 | int32_t i, j; |
| 4882 | |
| 4883 | for (i=0; i < UPRV_LENGTHOF(testCases); i++) { |
| 4884 | for (j=0; j<3; ++j) { |
| 4885 | const char* expected = (j==1) ? testCases[i].canonicalID : testCases[i].getNameID; |
| 4886 | Locale loc = _canonicalize(j, testCases[i].localeID); |
| 4887 | const char* getName = loc.isBogus() ? "BOGUS" : loc.getName(); |
| 4888 | if(uprv_strcmp(expected, getName) != 0) { |
| 4889 | errln("FAIL: %s(%s).getName() => \"%s\", expected \"%s\"", |
| 4890 | label[j], testCases[i].localeID, getName, expected); |
| 4891 | } else { |
| 4892 | logln("Ok: %s(%s) => \"%s\"", |
| 4893 | label[j], testCases[i].localeID, getName); |
| 4894 | } |
| 4895 | } |
| 4896 | } |
| 4897 | } |
| 4898 | |
| 4899 | void LocaleTest::TestCanonicalize(void) |
| 4900 | { |
| 4901 | static const struct { |
| 4902 | const char *localeID; /* input */ |
| 4903 | const char *canonicalID; /* expected canonicalize() result */ |
| 4904 | } testCases[] = { |
| 4905 | // language _ variant -> language |
| 4906 | { "no-BOKMAL", "nb" }, |
| 4907 | // also test with script, country and extensions |
| 4908 | { "no-Cyrl-ID-BOKMAL-u-ca-japanese", "nb-Cyrl-ID-u-ca-japanese" }, |
| 4909 | { "no-Cyrl-ID-1901-BOKMAL-xsistemo-u-ca-japanese", "nb-Cyrl-ID-1901-xsistemo-u-ca-japanese" }, |
| 4910 | { "no-Cyrl-ID-1901-BOKMAL-u-ca-japanese", "nb-Cyrl-ID-1901-u-ca-japanese" }, |
| 4911 | { "no-Cyrl-ID-BOKMAL-xsistemo-u-ca-japanese", "nb-Cyrl-ID-xsistemo-u-ca-japanese" }, |
| 4912 | { "no-NYNORSK", "nn" }, |
| 4913 | { "no-Cyrl-ID-NYNORSK-u-ca-japanese", "nn-Cyrl-ID-u-ca-japanese" }, |
| 4914 | { "aa-SAAHO", "ssy" }, |
| 4915 | // also test with script, country and extensions |
| 4916 | { "aa-Deva-IN-SAAHO-u-ca-japanese", "ssy-Deva-IN-u-ca-japanese" }, |
| 4917 | |
| 4918 | // language -> language |
| 4919 | { "aam", "aas" }, |
| 4920 | // also test with script, country, variants and extensions |
| 4921 | { "aam-Cyrl-ID-3456-u-ca-japanese", "aas-Cyrl-ID-3456-u-ca-japanese" }, |
| 4922 | |
| 4923 | // language -> language _ Script |
| 4924 | { "sh", "sr-Latn" }, |
| 4925 | // also test with script |
| 4926 | { "sh-Cyrl", "sr-Cyrl" }, |
| 4927 | // also test with country, variants and extensions |
| 4928 | { "sh-ID-3456-u-ca-roc", "sr-Latn-ID-3456-u-ca-roc" }, |
| 4929 | |
| 4930 | // language -> language _ country |
| 4931 | { "prs", "fa-AF" }, |
| 4932 | // also test with country |
| 4933 | { "prs-RU", "fa-RU" }, |
| 4934 | // also test with script, variants and extensions |
| 4935 | { "prs-Cyrl-1009-u-ca-roc", "fa-Cyrl-AF-1009-u-ca-roc" }, |
| 4936 | |
| 4937 | { "pa-IN", "pa-IN" }, |
| 4938 | // also test with script |
| 4939 | { "pa-Latn-IN", "pa-Latn-IN" }, |
| 4940 | // also test with variants and extensions |
| 4941 | { "pa-IN-5678-u-ca-hindi", "pa-IN-5678-u-ca-hindi" }, |
| 4942 | |
| 4943 | { "ky-Cyrl-KG", "ky-Cyrl-KG" }, |
| 4944 | // also test with variants and extensions |
| 4945 | { "ky-Cyrl-KG-3456-u-ca-roc", "ky-Cyrl-KG-3456-u-ca-roc" }, |
| 4946 | |
| 4947 | // Test replacement of scriptAlias |
| 4948 | { "en-Qaai", "en-Zinh" }, |
| 4949 | |
| 4950 | // Test replacement of territoryAlias |
| 4951 | // 554 has one replacement |
| 4952 | { "en-554", "en-NZ" }, |
| 4953 | { "en-554-u-nu-arab", "en-NZ-u-nu-arab" }, |
| 4954 | // 172 has multiple replacements |
| 4955 | // also test with variants |
| 4956 | { "ru-172-1234", "ru-RU-1234" }, |
| 4957 | // also test with extensions |
| 4958 | { "ru-172-1234-u-nu-latn", "ru-RU-1234-u-nu-latn" }, |
| 4959 | // also test with scripts |
| 4960 | { "uz-172", "uz-UZ" }, |
| 4961 | { "uz-Cyrl-172", "uz-Cyrl-UZ" }, |
| 4962 | { "uz-Bopo-172", "uz-Bopo-UZ" }, |
| 4963 | // also test with variants and scripts |
| 4964 | { "uz-Cyrl-172-5678-u-nu-latn", "uz-Cyrl-UZ-5678-u-nu-latn" }, |
| 4965 | // a language not used in this region |
| 4966 | { "fr-172", "fr-RU" }, |
| 4967 | |
| 4968 | // variant |
| 4969 | { "ja-Latn-hepburn-heploc", "ja-Latn-alalc97"}, |
| 4970 | |
| 4971 | { "aaa-Fooo-SU", "aaa-Fooo-RU"}, |
| 4972 | |
| 4973 | // ICU-21344 |
| 4974 | { "ku-Arab-NT", "ku-Arab-IQ"}, |
| 4975 | |
| 4976 | // ICU-21402 |
| 4977 | { "und-u-rg-no23", "und-u-rg-no50"}, |
| 4978 | { "und-u-rg-cn11", "und-u-rg-cnbj"}, |
| 4979 | { "und-u-rg-cz10a", "und-u-rg-cz110"}, |
| 4980 | { "und-u-rg-fra", "und-u-rg-frges"}, |
| 4981 | { "und-u-rg-frg", "und-u-rg-frges"}, |
| 4982 | { "und-u-rg-lud", "und-u-rg-lucl"}, |
| 4983 | |
| 4984 | { "und-NO-u-sd-no23", "und-NO-u-sd-no50"}, |
| 4985 | { "und-CN-u-sd-cn11", "und-CN-u-sd-cnbj"}, |
| 4986 | { "und-CZ-u-sd-cz10a", "und-CZ-u-sd-cz110"}, |
| 4987 | { "und-FR-u-sd-fra", "und-FR-u-sd-frges"}, |
| 4988 | { "und-FR-u-sd-frg", "und-FR-u-sd-frges"}, |
| 4989 | { "und-LU-u-sd-lud", "und-LU-u-sd-lucl"}, |
| 4990 | |
| 4991 | // ICU-21550 |
| 4992 | { "und-u-rg-fi01", "und-u-rg-axzzzz"}, |
| 4993 | { "und-u-rg-frcp", "und-u-rg-cpzzzz"}, |
| 4994 | { "und-u-rg-frpm", "und-u-rg-pmzzzz"}, |
| 4995 | { "und-u-rg-usvi", "und-u-rg-vizzzz"}, |
| 4996 | { "und-u-rg-cn91", "und-u-rg-hkzzzz"}, |
| 4997 | { "und-u-rg-nlaw", "und-u-rg-awzzzz"}, |
| 4998 | |
| 4999 | { "und-NO-u-sd-frre", "und-NO-u-sd-rezzzz"}, |
| 5000 | { "und-CN-u-sd-nlcw", "und-CN-u-sd-cwzzzz"}, |
| 5001 | { "und-CZ-u-sd-usgu", "und-CZ-u-sd-guzzzz"}, |
| 5002 | { "und-FR-u-sd-shta", "und-FR-u-sd-tazzzz"}, |
| 5003 | { "und-FR-u-sd-cn71", "und-FR-u-sd-twzzzz"}, |
| 5004 | |
| 5005 | |
| 5006 | // ICU-21401 |
| 5007 | { "cel-gaulish", "xtg"}, |
| 5008 | |
| 5009 | // ICU-21406 |
| 5010 | // Inside T extension |
| 5011 | // Case of Script and Region |
| 5012 | { "ja-kana-jp-t-it-latn-it", "ja-Kana-JP-t-it-latn-it"}, |
| 5013 | { "und-t-zh-hani-tw", "und-t-zh-hani-tw"}, |
| 5014 | { "und-cyrl-t-und-Latn", "und-Cyrl-t-und-latn"}, |
| 5015 | // Order of singleton |
| 5016 | { "und-u-ca-roc-t-zh", "und-t-zh-u-ca-roc"}, |
| 5017 | // Variant subtags are alphabetically ordered. |
| 5018 | { "sl-t-sl-rozaj-biske-1994", "sl-t-sl-1994-biske-rozaj"}, |
| 5019 | // tfield subtags are alphabetically ordered. |
| 5020 | // (Also tests subtag case normalisation.) |
| 5021 | { "DE-T-lv-M0-DIN", "de-t-lv-m0-din"}, |
| 5022 | { "DE-T-M0-DIN-K0-QWERTZ", "de-t-k0-qwertz-m0-din"}, |
| 5023 | { "DE-T-lv-M0-DIN-K0-QWERTZ", "de-t-lv-k0-qwertz-m0-din"}, |
| 5024 | // "true" tvalue subtags aren't removed. |
| 5025 | // (UTS 35 version 36, §3.2.1 claims otherwise, but tkey must be followed by |
| 5026 | // tvalue, so that's likely a spec bug in UTS 35.) |
| 5027 | { "en-t-m0-true", "en-t-m0-true"}, |
| 5028 | // tlang subtags are canonicalised. |
| 5029 | { "en-t-iw", "en-t-he"}, |
| 5030 | { "en-t-hy-latn-SU", "en-t-hy-latn-am"}, |
| 5031 | { "ru-t-ru-cyrl-SU", "ru-t-ru-cyrl-ru"}, |
| 5032 | { "fr-t-fr-172", "fr-t-fr-ru"}, |
| 5033 | { "und-t-no-latn-BOKMAL", "und-t-nb-latn" }, |
| 5034 | { "und-t-sgn-qAAi-NL", "und-t-dse-zinh" }, |
| 5035 | // alias of tvalue should be replaced |
| 5036 | { "en-t-m0-NaMeS", "en-t-m0-prprname" }, |
| 5037 | { "en-t-s0-ascii-d0-NaMe", "en-t-d0-charname-s0-ascii" }, |
| 5038 | }; |
| 5039 | int32_t i; |
| 5040 | for (i=0; i < UPRV_LENGTHOF(testCases); i++) { |
| 5041 | UErrorCode status = U_ZERO_ERROR; |
| 5042 | std::string otag = testCases[i].localeID; |
| 5043 | Locale loc = Locale::forLanguageTag(otag.c_str(), status); |
| 5044 | loc.canonicalize(status); |
| 5045 | std::string tag = loc.toLanguageTag<std::string>(status); |
| 5046 | if (tag != testCases[i].canonicalID) { |
| 5047 | errcheckln(status, "FAIL: %s should be canonicalized to %s but got %s - %s", |
| 5048 | otag.c_str(), |
| 5049 | testCases[i].canonicalID, |
| 5050 | tag.c_str(), |
| 5051 | u_errorName(status)); |
| 5052 | } |
| 5053 | } |
| 5054 | } |
| 5055 | |
| 5056 | void LocaleTest::TestCurrencyByDate(void) |
| 5057 | { |
| 5058 | #if !UCONFIG_NO_FORMATTING |
| 5059 | UErrorCode status = U_ZERO_ERROR; |
| 5060 | UDate date = uprv_getUTCtime(); |
| 5061 | UChar TMP[4] = {0, 0, 0, 0}; |
| 5062 | int32_t index = 0; |
| 5063 | int32_t resLen = 0; |
| 5064 | UnicodeString tempStr, resultStr; |
| 5065 | |
| 5066 | // Cycle through historical currencies |
| 5067 | date = (UDate)-630720000000.0; // pre 1961 - no currency defined |
| 5068 | index = ucurr_countCurrencies("eo_AM", date, &status); |
| 5069 | if (index != 0) |
| 5070 | { |
| 5071 | errcheckln(status, "FAIL: didn't return 0 for eo_AM - %s", u_errorName(status)); |
| 5072 | } |
| 5073 | resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status); |
| 5074 | if (resLen != 0) { |
| 5075 | errcheckln(status, "FAIL: eo_AM didn't return NULL - %s", u_errorName(status)); |
| 5076 | } |
| 5077 | status = U_ZERO_ERROR; |
| 5078 | |
| 5079 | date = (UDate)0.0; // 1970 - one currency defined |
| 5080 | index = ucurr_countCurrencies("eo_AM", date, &status); |
| 5081 | if (index != 1) |
| 5082 | { |
| 5083 | errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status)); |
| 5084 | } |
| 5085 | resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status); |
| 5086 | tempStr.setTo(TMP); |
| 5087 | resultStr.setTo("SUR"); |
| 5088 | if (resultStr != tempStr) { |
| 5089 | errcheckln(status, "FAIL: didn't return SUR for eo_AM - %s", u_errorName(status)); |
| 5090 | } |
| 5091 | |
| 5092 | date = (UDate)693792000000.0; // 1992 - one currency defined |
| 5093 | index = ucurr_countCurrencies("eo_AM", date, &status); |
| 5094 | if (index != 1) |
| 5095 | { |
| 5096 | errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status)); |
| 5097 | } |
| 5098 | resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status); |
| 5099 | tempStr.setTo(TMP); |
| 5100 | resultStr.setTo("RUR"); |
| 5101 | if (resultStr != tempStr) { |
| 5102 | errcheckln(status, "FAIL: didn't return RUR for eo_AM - %s", u_errorName(status)); |
| 5103 | } |
| 5104 | |
| 5105 | date = (UDate)977616000000.0; // post 1993 - one currency defined |
| 5106 | index = ucurr_countCurrencies("eo_AM", date, &status); |
| 5107 | if (index != 1) |
| 5108 | { |
| 5109 | errcheckln(status, "FAIL: didn't return 1 for eo_AM - %s", u_errorName(status)); |
| 5110 | } |
| 5111 | resLen = ucurr_forLocaleAndDate("eo_AM", date, index, TMP, 4, &status); |
| 5112 | tempStr.setTo(TMP); |
| 5113 | resultStr.setTo("AMD"); |
| 5114 | if (resultStr != tempStr) { |
| 5115 | errcheckln(status, "FAIL: didn't return AMD for eo_AM - %s", u_errorName(status)); |
| 5116 | } |
| 5117 | |
| 5118 | // Locale AD has multiple currencies at once |
| 5119 | date = (UDate)977616000000.0; // year 2001 |
| 5120 | index = ucurr_countCurrencies("eo_AD", date, &status); |
| 5121 | if (index != 4) |
| 5122 | { |
| 5123 | errcheckln(status, "FAIL: didn't return 4 for eo_AD - %s", u_errorName(status)); |
| 5124 | } |
| 5125 | resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status); |
| 5126 | tempStr.setTo(TMP); |
| 5127 | resultStr.setTo("EUR"); |
| 5128 | if (resultStr != tempStr) { |
| 5129 | errcheckln(status, "FAIL: didn't return EUR for eo_AD - %s", u_errorName(status)); |
| 5130 | } |
| 5131 | resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status); |
| 5132 | tempStr.setTo(TMP); |
| 5133 | resultStr.setTo("ESP"); |
| 5134 | if (resultStr != tempStr) { |
| 5135 | errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status)); |
| 5136 | } |
| 5137 | resLen = ucurr_forLocaleAndDate("eo_AD", date, 3, TMP, 4, &status); |
| 5138 | tempStr.setTo(TMP); |
| 5139 | resultStr.setTo("FRF"); |
| 5140 | if (resultStr != tempStr) { |
| 5141 | errcheckln(status, "FAIL: didn't return FRF for eo_AD - %s", u_errorName(status)); |
| 5142 | } |
| 5143 | resLen = ucurr_forLocaleAndDate("eo_AD", date, 4, TMP, 4, &status); |
| 5144 | tempStr.setTo(TMP); |
| 5145 | resultStr.setTo("ADP"); |
| 5146 | if (resultStr != tempStr) { |
| 5147 | errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status)); |
| 5148 | } |
| 5149 | |
| 5150 | date = (UDate)0.0; // year 1970 |
| 5151 | index = ucurr_countCurrencies("eo_AD", date, &status); |
| 5152 | if (index != 3) |
| 5153 | { |
| 5154 | errcheckln(status, "FAIL: didn't return 3 for eo_AD - %s", u_errorName(status)); |
| 5155 | } |
| 5156 | resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status); |
| 5157 | tempStr.setTo(TMP); |
| 5158 | resultStr.setTo("ESP"); |
| 5159 | if (resultStr != tempStr) { |
| 5160 | errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status)); |
| 5161 | } |
| 5162 | resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status); |
| 5163 | tempStr.setTo(TMP); |
| 5164 | resultStr.setTo("FRF"); |
| 5165 | if (resultStr != tempStr) { |
| 5166 | errcheckln(status, "FAIL: didn't return FRF for eo_AD - %s", u_errorName(status)); |
| 5167 | } |
| 5168 | resLen = ucurr_forLocaleAndDate("eo_AD", date, 3, TMP, 4, &status); |
| 5169 | tempStr.setTo(TMP); |
| 5170 | resultStr.setTo("ADP"); |
| 5171 | if (resultStr != tempStr) { |
| 5172 | errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status)); |
| 5173 | } |
| 5174 | |
| 5175 | date = (UDate)-630720000000.0; // year 1950 |
| 5176 | index = ucurr_countCurrencies("eo_AD", date, &status); |
| 5177 | if (index != 2) |
| 5178 | { |
| 5179 | errcheckln(status, "FAIL: didn't return 2 for eo_AD - %s", u_errorName(status)); |
| 5180 | } |
| 5181 | resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status); |
| 5182 | tempStr.setTo(TMP); |
| 5183 | resultStr.setTo("ESP"); |
| 5184 | if (resultStr != tempStr) { |
| 5185 | errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status)); |
| 5186 | } |
| 5187 | resLen = ucurr_forLocaleAndDate("eo_AD", date, 2, TMP, 4, &status); |
| 5188 | tempStr.setTo(TMP); |
| 5189 | resultStr.setTo("ADP"); |
| 5190 | if (resultStr != tempStr) { |
| 5191 | errcheckln(status, "FAIL: didn't return ADP for eo_AD - %s", u_errorName(status)); |
| 5192 | } |
| 5193 | |
| 5194 | date = (UDate)-2207520000000.0; // year 1900 |
| 5195 | index = ucurr_countCurrencies("eo_AD", date, &status); |
| 5196 | if (index != 1) |
| 5197 | { |
| 5198 | errcheckln(status, "FAIL: didn't return 1 for eo_AD - %s", u_errorName(status)); |
| 5199 | } |
| 5200 | resLen = ucurr_forLocaleAndDate("eo_AD", date, 1, TMP, 4, &status); |
| 5201 | tempStr.setTo(TMP); |
| 5202 | resultStr.setTo("ESP"); |
| 5203 | if (resultStr != tempStr) { |
| 5204 | errcheckln(status, "FAIL: didn't return ESP for eo_AD - %s", u_errorName(status)); |
| 5205 | } |
| 5206 | |
| 5207 | // Locale UA has gap between years 1994 - 1996 |
| 5208 | date = (UDate)788400000000.0; |
| 5209 | index = ucurr_countCurrencies("eo_UA", date, &status); |
| 5210 | if (index != 0) |
| 5211 | { |
| 5212 | errcheckln(status, "FAIL: didn't return 0 for eo_UA - %s", u_errorName(status)); |
| 5213 | } |
| 5214 | resLen = ucurr_forLocaleAndDate("eo_UA", date, index, TMP, 4, &status); |
| 5215 | if (resLen != 0) { |
| 5216 | errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status)); |
| 5217 | } |
| 5218 | status = U_ZERO_ERROR; |
| 5219 | |
| 5220 | // Test index bounds |
| 5221 | resLen = ucurr_forLocaleAndDate("eo_UA", date, 100, TMP, 4, &status); |
| 5222 | if (resLen != 0) { |
| 5223 | errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status)); |
| 5224 | } |
| 5225 | status = U_ZERO_ERROR; |
| 5226 | |
| 5227 | resLen = ucurr_forLocaleAndDate("eo_UA", date, 0, TMP, 4, &status); |
| 5228 | if (resLen != 0) { |
| 5229 | errcheckln(status, "FAIL: eo_UA didn't return NULL - %s", u_errorName(status)); |
| 5230 | } |
| 5231 | status = U_ZERO_ERROR; |
| 5232 | |
| 5233 | // Test for bogus locale |
| 5234 | index = ucurr_countCurrencies("eo_QQ", date, &status); |
| 5235 | if (index != 0) |
| 5236 | { |
| 5237 | errcheckln(status, "FAIL: didn't return 0 for eo_QQ - %s", u_errorName(status)); |
| 5238 | } |
| 5239 | status = U_ZERO_ERROR; |
| 5240 | resLen = ucurr_forLocaleAndDate("eo_QQ", date, 1, TMP, 4, &status); |
| 5241 | if (resLen != 0) { |
| 5242 | errcheckln(status, "FAIL: eo_QQ didn't return NULL - %s", u_errorName(status)); |
| 5243 | } |
| 5244 | status = U_ZERO_ERROR; |
| 5245 | resLen = ucurr_forLocaleAndDate("eo_QQ", date, 0, TMP, 4, &status); |
| 5246 | if (resLen != 0) { |
| 5247 | errcheckln(status, "FAIL: eo_QQ didn't return NULL - %s", u_errorName(status)); |
| 5248 | } |
| 5249 | status = U_ZERO_ERROR; |
| 5250 | |
| 5251 | // Cycle through histrocial currencies |
| 5252 | date = (UDate)977616000000.0; // 2001 - one currency |
| 5253 | index = ucurr_countCurrencies("eo_AO", date, &status); |
| 5254 | if (index != 1) |
| 5255 | { |
| 5256 | errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status)); |
| 5257 | } |
| 5258 | resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status); |
| 5259 | tempStr.setTo(TMP); |
| 5260 | resultStr.setTo("AOA"); |
| 5261 | if (resultStr != tempStr) { |
| 5262 | errcheckln(status, "FAIL: didn't return AOA for eo_AO - %s", u_errorName(status)); |
| 5263 | } |
| 5264 | |
| 5265 | date = (UDate)819936000000.0; // 1996 - 2 currencies |
| 5266 | index = ucurr_countCurrencies("eo_AO", date, &status); |
| 5267 | if (index != 2) |
| 5268 | { |
| 5269 | errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status)); |
| 5270 | } |
| 5271 | resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status); |
| 5272 | tempStr.setTo(TMP); |
| 5273 | resultStr.setTo("AOR"); |
| 5274 | if (resultStr != tempStr) { |
| 5275 | errcheckln(status, "FAIL: didn't return AOR for eo_AO - %s", u_errorName(status)); |
| 5276 | } |
| 5277 | resLen = ucurr_forLocaleAndDate("eo_AO", date, 2, TMP, 4, &status); |
| 5278 | tempStr.setTo(TMP); |
| 5279 | resultStr.setTo("AON"); |
| 5280 | if (resultStr != tempStr) { |
| 5281 | errcheckln(status, "FAIL: didn't return AON for eo_AO - %s", u_errorName(status)); |
| 5282 | } |
| 5283 | |
| 5284 | date = (UDate)662256000000.0; // 1991 - 2 currencies |
| 5285 | index = ucurr_countCurrencies("eo_AO", date, &status); |
| 5286 | if (index != 2) |
| 5287 | { |
| 5288 | errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status)); |
| 5289 | } |
| 5290 | resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status); |
| 5291 | tempStr.setTo(TMP); |
| 5292 | resultStr.setTo("AON"); |
| 5293 | if (resultStr != tempStr) { |
| 5294 | errcheckln(status, "FAIL: didn't return AON for eo_AO - %s", u_errorName(status)); |
| 5295 | } |
| 5296 | resLen = ucurr_forLocaleAndDate("eo_AO", date, 2, TMP, 4, &status); |
| 5297 | tempStr.setTo(TMP); |
| 5298 | resultStr.setTo("AOK"); |
| 5299 | if (resultStr != tempStr) { |
| 5300 | errcheckln(status, "FAIL: didn't return AOK for eo_AO - %s", u_errorName(status)); |
| 5301 | } |
| 5302 | |
| 5303 | date = (UDate)315360000000.0; // 1980 - one currency |
| 5304 | index = ucurr_countCurrencies("eo_AO", date, &status); |
| 5305 | if (index != 1) |
| 5306 | { |
| 5307 | errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status)); |
| 5308 | } |
| 5309 | resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status); |
| 5310 | tempStr.setTo(TMP); |
| 5311 | resultStr.setTo("AOK"); |
| 5312 | if (resultStr != tempStr) { |
| 5313 | errcheckln(status, "FAIL: didn't return AOK for eo_AO - %s", u_errorName(status)); |
| 5314 | } |
| 5315 | |
| 5316 | date = (UDate)0.0; // 1970 - no currencies |
| 5317 | index = ucurr_countCurrencies("eo_AO", date, &status); |
| 5318 | if (index != 0) |
| 5319 | { |
| 5320 | errcheckln(status, "FAIL: didn't return 1 for eo_AO - %s", u_errorName(status)); |
| 5321 | } |
| 5322 | resLen = ucurr_forLocaleAndDate("eo_AO", date, 1, TMP, 4, &status); |
| 5323 | if (resLen != 0) { |
| 5324 | errcheckln(status, "FAIL: eo_AO didn't return NULL - %s", u_errorName(status)); |
| 5325 | } |
| 5326 | status = U_ZERO_ERROR; |
| 5327 | |
| 5328 | // Test with currency keyword override |
| 5329 | date = (UDate)977616000000.0; // 2001 - two currencies |
| 5330 | index = ucurr_countCurrencies("eo_DE@currency=DEM", date, &status); |
| 5331 | if (index != 2) |
| 5332 | { |
| 5333 | errcheckln(status, "FAIL: didn't return 2 for eo_DE@currency=DEM - %s", u_errorName(status)); |
| 5334 | } |
| 5335 | resLen = ucurr_forLocaleAndDate("eo_DE@currency=DEM", date, 1, TMP, 4, &status); |
| 5336 | tempStr.setTo(TMP); |
| 5337 | resultStr.setTo("EUR"); |
| 5338 | if (resultStr != tempStr) { |
| 5339 | errcheckln(status, "FAIL: didn't return EUR for eo_DE@currency=DEM - %s", u_errorName(status)); |
| 5340 | } |
| 5341 | resLen = ucurr_forLocaleAndDate("eo_DE@currency=DEM", date, 2, TMP, 4, &status); |
| 5342 | tempStr.setTo(TMP); |
| 5343 | resultStr.setTo("DEM"); |
| 5344 | if (resultStr != tempStr) { |
| 5345 | errcheckln(status, "FAIL: didn't return DEM for eo_DE@currency=DEM - %s", u_errorName(status)); |
| 5346 | } |
| 5347 | |
| 5348 | // Test Euro Support |
| 5349 | status = U_ZERO_ERROR; // reset |
| 5350 | date = uprv_getUTCtime(); |
| 5351 | |
| 5352 | UChar USD[4]; |
| 5353 | ucurr_forLocaleAndDate("en_US", date, 1, USD, 4, &status); |
| 5354 | |
| 5355 | UChar YEN[4]; |
| 5356 | ucurr_forLocaleAndDate("ja_JP", date, 1, YEN, 4, &status); |
| 5357 | |
| 5358 | ucurr_forLocaleAndDate("en_US", date, 1, TMP, 4, &status); |
| 5359 | if (u_strcmp(USD, TMP) != 0) { |
| 5360 | errcheckln(status, "Fail: en_US didn't return USD - %s", u_errorName(status)); |
| 5361 | } |
| 5362 | ucurr_forLocaleAndDate("en_US_Q", date, 1, TMP, 4, &status); |
| 5363 | if (u_strcmp(USD, TMP) != 0) { |
| 5364 | errcheckln(status, "Fail: en_US_Q didn't fallback to en_US - %s", u_errorName(status)); |
| 5365 | } |
| 5366 | status = U_ZERO_ERROR; // reset |
| 5367 | #endif |
| 5368 | } |
| 5369 | |
| 5370 | void LocaleTest::TestGetVariantWithKeywords(void) |
| 5371 | { |
| 5372 | Locale l("en_US_VALLEY@foo=value"); |
| 5373 | const char *variant = l.getVariant(); |
| 5374 | logln(variant); |
| 5375 | test_assert(strcmp("VALLEY", variant) == 0); |
| 5376 | |
| 5377 | UErrorCode status = U_ZERO_ERROR; |
| 5378 | char buffer[50]; |
| 5379 | int32_t len = l.getKeywordValue("foo", buffer, 50, status); |
| 5380 | buffer[len] = '\0'; |
| 5381 | test_assert(strcmp("value", buffer) == 0); |
| 5382 | } |
| 5383 | |
| 5384 | void LocaleTest::TestIsRightToLeft() { |
| 5385 | assertFalse("root LTR", Locale::getRoot().isRightToLeft()); |
| 5386 | assertFalse("zh LTR", Locale::getChinese().isRightToLeft()); |
| 5387 | assertTrue("ar RTL", Locale("ar").isRightToLeft()); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 5388 | assertTrue("und-EG RTL", Locale("und-EG").isRightToLeft(), false, true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 5389 | assertFalse("fa-Cyrl LTR", Locale("fa-Cyrl").isRightToLeft()); |
| 5390 | assertTrue("en-Hebr RTL", Locale("en-Hebr").isRightToLeft()); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 5391 | assertTrue("ckb RTL", Locale("ckb").isRightToLeft(), false, true); // Sorani Kurdish |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 5392 | assertFalse("fil LTR", Locale("fil").isRightToLeft()); |
| 5393 | assertFalse("he-Zyxw LTR", Locale("he-Zyxw").isRightToLeft()); |
| 5394 | } |
| 5395 | |
| 5396 | void LocaleTest::TestBug11421() { |
| 5397 | Locale::getDefault().getBaseName(); |
| 5398 | int32_t numLocales; |
| 5399 | const Locale *localeList = Locale::getAvailableLocales(numLocales); |
| 5400 | for (int localeIndex = 0; localeIndex < numLocales; localeIndex++) { |
| 5401 | const Locale &loc = localeList[localeIndex]; |
| 5402 | if (strncmp(loc.getName(), loc.getBaseName(), strlen(loc.getBaseName()))) { |
| 5403 | errln("%s:%d loc.getName=\"%s\"; loc.getBaseName=\"%s\"", |
| 5404 | __FILE__, __LINE__, loc.getName(), loc.getBaseName()); |
| 5405 | break; |
| 5406 | } |
| 5407 | } |
| 5408 | } |
| 5409 | |
| 5410 | // TestBug13277. The failure manifests as valgrind errors. |
| 5411 | // See the trac ticket for details. |
| 5412 | // |
| 5413 | |
| 5414 | void LocaleTest::TestBug13277() { |
| 5415 | UErrorCode status = U_ZERO_ERROR; |
| 5416 | CharString name("en-us-x-foo", -1, status); |
| 5417 | while (name.length() < 152) { |
| 5418 | name.append("-x-foo", -1, status); |
| 5419 | } |
| 5420 | |
| 5421 | while (name.length() < 160) { |
| 5422 | name.append('z', status); |
| 5423 | Locale loc(name.data(), nullptr, nullptr, nullptr); |
| 5424 | } |
| 5425 | } |
| 5426 | |
| 5427 | // TestBug13554 Check for read past end of array in getPosixID(). |
| 5428 | // The bug shows as an Address Sanitizer failure. |
| 5429 | |
| 5430 | void LocaleTest::TestBug13554() { |
| 5431 | UErrorCode status = U_ZERO_ERROR; |
| 5432 | const int BUFFER_SIZE = 100; |
| 5433 | char posixID[BUFFER_SIZE]; |
| 5434 | |
| 5435 | for (uint32_t hostid = 0; hostid < 0x500; ++hostid) { |
| 5436 | status = U_ZERO_ERROR; |
| 5437 | uprv_convertToPosix(hostid, posixID, BUFFER_SIZE, &status); |
| 5438 | } |
| 5439 | } |
| 5440 | |
| 5441 | void LocaleTest::TestBug20410() { |
| 5442 | IcuTestErrorCode status(*this, "TestBug20410()"); |
| 5443 | |
| 5444 | static const char tag1[] = "art-lojban-x-0"; |
| 5445 | static const Locale expected1("jbo@x=0"); |
| 5446 | Locale result1 = Locale::forLanguageTag(tag1, status); |
| 5447 | status.errIfFailureAndReset("\"%s\"", tag1); |
| 5448 | assertEquals(tag1, expected1.getName(), result1.getName()); |
| 5449 | |
| 5450 | static const char tag2[] = "zh-xiang-u-nu-thai-x-0"; |
| 5451 | static const Locale expected2("hsn@numbers=thai;x=0"); |
| 5452 | Locale result2 = Locale::forLanguageTag(tag2, status); |
| 5453 | status.errIfFailureAndReset("\"%s\"", tag2); |
| 5454 | assertEquals(tag2, expected2.getName(), result2.getName()); |
| 5455 | |
| 5456 | static const char locid3[] = "art__lojban@x=0"; |
| 5457 | Locale result3 = Locale::createCanonical(locid3); |
| 5458 | static const Locale expected3("jbo@x=0"); |
| 5459 | assertEquals(locid3, expected3.getName(), result3.getName()); |
| 5460 | |
| 5461 | static const char locid4[] = "art-lojban-x-0"; |
| 5462 | Locale result4 = Locale::createCanonical(locid4); |
| 5463 | static const Locale expected4("jbo@x=0"); |
| 5464 | assertEquals(locid4, expected4.getName(), result4.getName()); |
| 5465 | } |
| 5466 | |
| 5467 | void LocaleTest::TestBug20900() { |
| 5468 | static const struct { |
| 5469 | const char *localeID; /* input */ |
| 5470 | const char *canonicalID; /* expected canonicalize() result */ |
| 5471 | } testCases[] = { |
| 5472 | { "art-lojban", "jbo" }, |
| 5473 | { "zh-guoyu", "zh" }, |
| 5474 | { "zh-hakka", "hak" }, |
| 5475 | { "zh-xiang", "hsn" }, |
| 5476 | { "zh-min-nan", "nan" }, |
| 5477 | { "zh-gan", "gan" }, |
| 5478 | { "zh-wuu", "wuu" }, |
| 5479 | { "zh-yue", "yue" }, |
| 5480 | }; |
| 5481 | |
| 5482 | IcuTestErrorCode status(*this, "TestBug20900"); |
| 5483 | for (int32_t i=0; i < UPRV_LENGTHOF(testCases); i++) { |
| 5484 | Locale loc = Locale::createCanonical(testCases[i].localeID); |
| 5485 | std::string result = loc.toLanguageTag<std::string>(status); |
| 5486 | const char* tag = loc.isBogus() ? "BOGUS" : result.c_str(); |
| 5487 | status.errIfFailureAndReset("FAIL: createCanonical(%s).toLanguageTag() expected \"%s\"", |
| 5488 | testCases[i].localeID, tag); |
| 5489 | assertEquals("createCanonical", testCases[i].canonicalID, tag); |
| 5490 | } |
| 5491 | } |
| 5492 | |
| 5493 | U_DEFINE_LOCAL_OPEN_POINTER(LocalStdioFilePointer, FILE, fclose); |
| 5494 | void LocaleTest::TestLocaleCanonicalizationFromFile() |
| 5495 | { |
| 5496 | IcuTestErrorCode status(*this, "TestLocaleCanonicalizationFromFile"); |
| 5497 | const char *sourceTestDataPath=getSourceTestData(status); |
| 5498 | if(status.errIfFailureAndReset("unable to find the source/test/testdata " |
| 5499 | "folder (getSourceTestData())")) { |
| 5500 | return; |
| 5501 | } |
| 5502 | char testPath[400]; |
| 5503 | char line[256]; |
| 5504 | strcpy(testPath, sourceTestDataPath); |
| 5505 | strcat(testPath, "localeCanonicalization.txt"); |
| 5506 | LocalStdioFilePointer testFile(fopen(testPath, "r")); |
| 5507 | if(testFile.isNull()) { |
| 5508 | errln("unable to open %s", testPath); |
| 5509 | return; |
| 5510 | } |
| 5511 | // Format: |
| 5512 | // <source locale identifier> ; <expected canonicalized locale identifier> |
| 5513 | while (fgets(line, (int)sizeof(line), testFile.getAlias())!=NULL) { |
| 5514 | if (line[0] == '#') { |
| 5515 | // ignore any lines start with # |
| 5516 | continue; |
| 5517 | } |
| 5518 | char *semi = strchr(line, ';'); |
| 5519 | if (semi == nullptr) { |
| 5520 | // ignore any lines without ; |
| 5521 | continue; |
| 5522 | } |
| 5523 | *semi = '\0'; // null terminiate on the spot of semi |
| 5524 | const char* from = u_skipWhitespace((const char*)line); |
| 5525 | u_rtrim((char*)from); |
| 5526 | const char* to = u_skipWhitespace((const char*)semi + 1); |
| 5527 | u_rtrim((char*)to); |
| 5528 | std::string expect(to); |
| 5529 | // Change the _ to - |
| 5530 | std::transform(expect.begin(), expect.end(), expect.begin(), |
| 5531 | [](unsigned char c){ return c == '_' ? '-' : c; }); |
| 5532 | |
| 5533 | Locale loc = Locale::createCanonical(from); |
| 5534 | std::string result = loc.toLanguageTag<std::string>(status); |
| 5535 | const char* tag = loc.isBogus() ? "BOGUS" : result.c_str(); |
| 5536 | status.errIfFailureAndReset( |
| 5537 | "FAIL: createCanonical(%s).toLanguageTag() expected \"%s\" locale is %s", |
| 5538 | from, tag, loc.getName()); |
| 5539 | std::string msg("createCanonical("); |
| 5540 | msg += from; |
| 5541 | msg += ") locale = "; |
| 5542 | msg += loc.getName(); |
| 5543 | assertEquals(msg.c_str(), expect.c_str(), tag); |
| 5544 | } |
| 5545 | } |
| 5546 | |
| 5547 | void LocaleTest::TestKnownCanonicalizedListCorrect() |
| 5548 | { |
| 5549 | IcuTestErrorCode status(*this, "TestKnownCanonicalizedListCorrect"); |
| 5550 | int32_t numOfKnownCanonicalized; |
| 5551 | const char* const* knownCanonicalized = |
| 5552 | ulocimp_getKnownCanonicalizedLocaleForTest(&numOfKnownCanonicalized); |
| 5553 | for (int32_t i = 0; i < numOfKnownCanonicalized; i++) { |
| 5554 | std::string msg("Known Canonicalized Locale is not canonicalized: "); |
| 5555 | assertTrue((msg + knownCanonicalized[i]).c_str(), |
| 5556 | ulocimp_isCanonicalizedLocaleForTest(knownCanonicalized[i])); |
| 5557 | } |
| 5558 | } |
| 5559 | |
| 5560 | void LocaleTest::TestConstructorAcceptsBCP47() { |
| 5561 | IcuTestErrorCode status(*this, "TestConstructorAcceptsBCP47"); |
| 5562 | |
| 5563 | Locale loc1("ar-EG-u-nu-latn"); |
| 5564 | Locale loc2("ar-EG@numbers=latn"); |
| 5565 | Locale loc3("ar-EG"); |
| 5566 | std::string val; |
| 5567 | |
| 5568 | // Check getKeywordValue "numbers" |
| 5569 | val = loc1.getKeywordValue<std::string>("numbers", status); |
| 5570 | assertEquals("BCP47 syntax has ICU keyword value", "latn", val.c_str()); |
| 5571 | |
| 5572 | val = loc2.getKeywordValue<std::string>("numbers", status); |
| 5573 | assertEquals("ICU syntax has ICU keyword value", "latn", val.c_str()); |
| 5574 | |
| 5575 | val = loc3.getKeywordValue<std::string>("numbers", status); |
| 5576 | assertEquals("Default, ICU keyword", "", val.c_str()); |
| 5577 | |
| 5578 | // Check getUnicodeKeywordValue "nu" |
| 5579 | val = loc1.getUnicodeKeywordValue<std::string>("nu", status); |
| 5580 | assertEquals("BCP47 syntax has short unicode keyword value", "latn", val.c_str()); |
| 5581 | |
| 5582 | val = loc2.getUnicodeKeywordValue<std::string>("nu", status); |
| 5583 | assertEquals("ICU syntax has short unicode keyword value", "latn", val.c_str()); |
| 5584 | |
| 5585 | val = loc3.getUnicodeKeywordValue<std::string>("nu", status); |
| 5586 | status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default, short unicode keyword"); |
| 5587 | |
| 5588 | // Check getUnicodeKeywordValue "numbers" |
| 5589 | val = loc1.getUnicodeKeywordValue<std::string>("numbers", status); |
| 5590 | assertEquals("BCP47 syntax has long unicode keyword value", "latn", val.c_str()); |
| 5591 | |
| 5592 | val = loc2.getUnicodeKeywordValue<std::string>("numbers", status); |
| 5593 | assertEquals("ICU syntax has long unicode keyword value", "latn", val.c_str()); |
| 5594 | |
| 5595 | val = loc3.getUnicodeKeywordValue<std::string>("numbers", status); |
| 5596 | status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default, long unicode keyword"); |
| 5597 | } |
| 5598 | |
| 5599 | void LocaleTest::TestForLanguageTag() { |
| 5600 | IcuTestErrorCode status(*this, "TestForLanguageTag()"); |
| 5601 | |
| 5602 | static const char tag_en[] = "en-US"; |
| 5603 | static const char tag_oed[] = "en-GB-oed"; |
| 5604 | static const char tag_af[] = "af-t-ar-i0-handwrit-u-ca-coptic-x-foo"; |
| 5605 | static const char tag_ill[] = "!"; |
| 5606 | static const char tag_no_nul[] = { 'e', 'n', '-', 'G', 'B' }; |
| 5607 | static const char tag_ext[] = "en-GB-1-abc-efg-a-xyz"; |
| 5608 | static const char tag_var[] = "sl-rozaj-biske-1994"; |
| 5609 | |
| 5610 | static const Locale loc_en("en_US"); |
| 5611 | static const Locale loc_oed("en_GB_OXENDICT"); |
| 5612 | static const Locale loc_af("af@calendar=coptic;t=ar-i0-handwrit;x=foo"); |
| 5613 | static const Locale loc_null(""); |
| 5614 | static const Locale loc_gb("en_GB"); |
| 5615 | static const Locale loc_ext("en_GB@1=abc-efg;a=xyz"); |
| 5616 | static const Locale loc_var("sl__1994_BISKE_ROZAJ"); |
| 5617 | |
| 5618 | Locale result_en = Locale::forLanguageTag(tag_en, status); |
| 5619 | status.errIfFailureAndReset("\"%s\"", tag_en); |
| 5620 | assertEquals(tag_en, loc_en.getName(), result_en.getName()); |
| 5621 | |
| 5622 | Locale result_oed = Locale::forLanguageTag(tag_oed, status); |
| 5623 | status.errIfFailureAndReset("\"%s\"", tag_oed); |
| 5624 | assertEquals(tag_oed, loc_oed.getName(), result_oed.getName()); |
| 5625 | |
| 5626 | Locale result_af = Locale::forLanguageTag(tag_af, status); |
| 5627 | status.errIfFailureAndReset("\"%s\"", tag_af); |
| 5628 | assertEquals(tag_af, loc_af.getName(), result_af.getName()); |
| 5629 | |
| 5630 | Locale result_var = Locale::forLanguageTag(tag_var, status); |
| 5631 | status.errIfFailureAndReset("\"%s\"", tag_var); |
| 5632 | assertEquals(tag_var, loc_var.getName(), result_var.getName()); |
| 5633 | |
| 5634 | Locale result_ill = Locale::forLanguageTag(tag_ill, status); |
| 5635 | assertEquals(tag_ill, U_ILLEGAL_ARGUMENT_ERROR, status.reset()); |
| 5636 | assertTrue(result_ill.getName(), result_ill.isBogus()); |
| 5637 | |
| 5638 | Locale result_null = Locale::forLanguageTag(nullptr, status); |
| 5639 | status.errIfFailureAndReset("nullptr"); |
| 5640 | assertEquals("nullptr", loc_null.getName(), result_null.getName()); |
| 5641 | |
| 5642 | StringPiece sp_substr(tag_oed, 5); // "en-GB", no NUL. |
| 5643 | Locale result_substr = Locale::forLanguageTag(sp_substr, status); |
| 5644 | status.errIfFailureAndReset("\"%.*s\"", sp_substr.size(), sp_substr.data()); |
| 5645 | assertEquals(CharString(sp_substr, status).data(), |
| 5646 | loc_gb.getName(), result_substr.getName()); |
| 5647 | |
| 5648 | StringPiece sp_no_nul(tag_no_nul, sizeof tag_no_nul); // "en-GB", no NUL. |
| 5649 | Locale result_no_nul = Locale::forLanguageTag(sp_no_nul, status); |
| 5650 | status.errIfFailureAndReset("\"%.*s\"", sp_no_nul.size(), sp_no_nul.data()); |
| 5651 | assertEquals(CharString(sp_no_nul, status).data(), |
| 5652 | loc_gb.getName(), result_no_nul.getName()); |
| 5653 | |
| 5654 | Locale result_ext = Locale::forLanguageTag(tag_ext, status); |
| 5655 | status.errIfFailureAndReset("\"%s\"", tag_ext); |
| 5656 | assertEquals(tag_ext, loc_ext.getName(), result_ext.getName()); |
| 5657 | |
| 5658 | static const struct { |
| 5659 | const char *inputTag; /* input */ |
| 5660 | const char *expectedID; /* expected forLanguageTag().getName() result */ |
| 5661 | } testCases[] = { |
| 5662 | // ICU-21433 |
| 5663 | {"und-1994-biske-rozaj", "__1994_BISKE_ROZAJ"}, |
| 5664 | {"de-1994-biske-rozaj", "de__1994_BISKE_ROZAJ"}, |
| 5665 | {"und-x-private", "@x=private"}, |
| 5666 | {"de-1994-biske-rozaj-x-private", "de__1994_BISKE_ROZAJ@x=private"}, |
| 5667 | {"und-1994-biske-rozaj-x-private", "__1994_BISKE_ROZAJ@x=private"}, |
| 5668 | }; |
| 5669 | int32_t i; |
| 5670 | for (i=0; i < UPRV_LENGTHOF(testCases); i++) { |
| 5671 | UErrorCode status = U_ZERO_ERROR; |
| 5672 | std::string otag = testCases[i].inputTag; |
| 5673 | std::string tag = Locale::forLanguageTag(otag.c_str(), status).getName(); |
| 5674 | if (tag != testCases[i].expectedID) { |
| 5675 | errcheckln(status, "FAIL: %s should be toLanguageTag to %s but got %s - %s", |
| 5676 | otag.c_str(), |
| 5677 | testCases[i].expectedID, |
| 5678 | tag.c_str(), |
| 5679 | u_errorName(status)); |
| 5680 | } |
| 5681 | } |
| 5682 | } |
| 5683 | |
| 5684 | void LocaleTest::TestForLanguageTagLegacyTagBug21676() { |
| 5685 | IcuTestErrorCode status(*this, "TestForLanguageTagLegacyTagBug21676()"); |
| 5686 | std::string tag( |
| 5687 | "i-enochian-1nochian-129-515VNTR-64863775-X3il6-110Y101-29-515VNTR-" |
| 5688 | "64863775-153zu-u-Y4-H0-t6-X3-u6-110Y101-X"); |
| 5689 | std::string input(tag); |
| 5690 | input += "EXTRA MEMORY AFTER NON-NULL TERMINATED STRING"; |
| 5691 | StringPiece stringp(input.c_str(), tag.length()); |
| 5692 | std::string name = Locale::forLanguageTag(stringp, status).getName(); |
| 5693 | std::string expected( |
| 5694 | "@x=i-enochian-1nochian-129-515vntr-64863775-x3il6-110y101-29-515vntr-" |
| 5695 | "64863775-153zu-u-y4-h0-t6-x3-u6-110y101-x"); |
| 5696 | if (name != expected) { |
| 5697 | errcheckln( |
| 5698 | status, |
| 5699 | "FAIL: forLanguageTag('%s', \n%d).getName() should be \n'%s' but got %s", |
| 5700 | tag.c_str(), tag.length(), expected.c_str(), name.c_str()); |
| 5701 | } |
| 5702 | } |
| 5703 | |
| 5704 | void LocaleTest::TestToLanguageTag() { |
| 5705 | IcuTestErrorCode status(*this, "TestToLanguageTag()"); |
| 5706 | |
| 5707 | static const Locale loc_c("en_US_POSIX"); |
| 5708 | static const Locale loc_en("en_US"); |
| 5709 | static const Locale loc_af("af@calendar=coptic;t=ar-i0-handwrit;x=foo"); |
| 5710 | static const Locale loc_ext("en@0=abc;a=xyz"); |
| 5711 | static const Locale loc_empty(""); |
| 5712 | static const Locale loc_ill("!"); |
| 5713 | static const Locale loc_variant("sl__ROZAJ_BISKE_1994"); |
| 5714 | |
| 5715 | static const char tag_c[] = "en-US-u-va-posix"; |
| 5716 | static const char tag_en[] = "en-US"; |
| 5717 | static const char tag_af[] = "af-t-ar-i0-handwrit-u-ca-coptic-x-foo"; |
| 5718 | static const char tag_ext[] = "en-0-abc-a-xyz"; |
| 5719 | static const char tag_und[] = "und"; |
| 5720 | static const char tag_variant[] = "sl-1994-biske-rozaj"; |
| 5721 | |
| 5722 | std::string result; |
| 5723 | StringByteSink<std::string> sink(&result); |
| 5724 | loc_c.toLanguageTag(sink, status); |
| 5725 | status.errIfFailureAndReset("\"%s\"", loc_c.getName()); |
| 5726 | assertEquals(loc_c.getName(), tag_c, result.c_str()); |
| 5727 | |
| 5728 | std::string result_c = loc_c.toLanguageTag<std::string>(status); |
| 5729 | status.errIfFailureAndReset("\"%s\"", loc_c.getName()); |
| 5730 | assertEquals(loc_c.getName(), tag_c, result_c.c_str()); |
| 5731 | |
| 5732 | std::string result_en = loc_en.toLanguageTag<std::string>(status); |
| 5733 | status.errIfFailureAndReset("\"%s\"", loc_en.getName()); |
| 5734 | assertEquals(loc_en.getName(), tag_en, result_en.c_str()); |
| 5735 | |
| 5736 | std::string result_af = loc_af.toLanguageTag<std::string>(status); |
| 5737 | status.errIfFailureAndReset("\"%s\"", loc_af.getName()); |
| 5738 | assertEquals(loc_af.getName(), tag_af, result_af.c_str()); |
| 5739 | |
| 5740 | std::string result_ext = loc_ext.toLanguageTag<std::string>(status); |
| 5741 | status.errIfFailureAndReset("\"%s\"", loc_ext.getName()); |
| 5742 | assertEquals(loc_ext.getName(), tag_ext, result_ext.c_str()); |
| 5743 | |
| 5744 | std::string result_empty = loc_empty.toLanguageTag<std::string>(status); |
| 5745 | status.errIfFailureAndReset("\"%s\"", loc_empty.getName()); |
| 5746 | assertEquals(loc_empty.getName(), tag_und, result_empty.c_str()); |
| 5747 | |
| 5748 | std::string result_ill = loc_ill.toLanguageTag<std::string>(status); |
| 5749 | status.errIfFailureAndReset("\"%s\"", loc_ill.getName()); |
| 5750 | assertEquals(loc_ill.getName(), tag_und, result_ill.c_str()); |
| 5751 | |
| 5752 | std::string result_variant = loc_variant.toLanguageTag<std::string>(status); |
| 5753 | status.errIfFailureAndReset("\"%s\"", loc_variant.getName()); |
| 5754 | assertEquals(loc_variant.getName(), tag_variant, result_variant.c_str()); |
| 5755 | |
| 5756 | Locale loc_bogus; |
| 5757 | loc_bogus.setToBogus(); |
| 5758 | std::string result_bogus = loc_bogus.toLanguageTag<std::string>(status); |
| 5759 | assertEquals("bogus", U_ILLEGAL_ARGUMENT_ERROR, status.reset()); |
| 5760 | assertTrue(result_bogus.c_str(), result_bogus.empty()); |
| 5761 | |
| 5762 | static const struct { |
| 5763 | const char *localeID; /* input */ |
| 5764 | const char *expectedID; /* expected toLanguageTag() result */ |
| 5765 | } testCases[] = { |
| 5766 | /* ICU-21414 */ |
| 5767 | {"und-x-abc-private", "und-x-abc-private"}, |
| 5768 | {"und-x-private", "und-x-private"}, |
| 5769 | {"und-u-ca-roc-x-private", "und-u-ca-roc-x-private"}, |
| 5770 | {"und-US-x-private", "und-US-x-private"}, |
| 5771 | {"und-Latn-x-private", "und-Latn-x-private"}, |
| 5772 | {"und-1994-biske-rozaj", "und-1994-biske-rozaj"}, |
| 5773 | {"und-1994-biske-rozaj-x-private", "und-1994-biske-rozaj-x-private"}, |
| 5774 | }; |
| 5775 | int32_t i; |
| 5776 | for (i=0; i < UPRV_LENGTHOF(testCases); i++) { |
| 5777 | UErrorCode status = U_ZERO_ERROR; |
| 5778 | std::string otag = testCases[i].localeID; |
| 5779 | std::string tag = Locale::forLanguageTag(otag.c_str(), status).toLanguageTag<std::string>(status); |
| 5780 | if (tag != testCases[i].expectedID) { |
| 5781 | errcheckln(status, "FAIL: %s should be toLanguageTag to %s but got %s - %s", |
| 5782 | otag.c_str(), |
| 5783 | testCases[i].expectedID, |
| 5784 | tag.c_str(), |
| 5785 | u_errorName(status)); |
| 5786 | } |
| 5787 | } |
| 5788 | } |
| 5789 | |
| 5790 | /* ICU-20310 */ |
| 5791 | void LocaleTest::TestToLanguageTagOmitTrue() { |
| 5792 | IcuTestErrorCode status(*this, "TestToLanguageTagOmitTrue()"); |
| 5793 | assertEquals("en-u-kn should drop true", |
| 5794 | "en-u-kn", Locale("en-u-kn-true").toLanguageTag<std::string>(status).c_str()); |
| 5795 | status.errIfFailureAndReset(); |
| 5796 | assertEquals("en-u-kn should drop true", |
| 5797 | "en-u-kn", Locale("en-u-kn").toLanguageTag<std::string>(status).c_str()); |
| 5798 | status.errIfFailureAndReset(); |
| 5799 | |
| 5800 | assertEquals("de-u-co should drop true", |
| 5801 | "de-u-co", Locale("de-u-co").toLanguageTag<std::string>(status).c_str()); |
| 5802 | status.errIfFailureAndReset(); |
| 5803 | assertEquals("de-u-co should drop true", |
| 5804 | "de-u-co", Locale("de-u-co-yes").toLanguageTag<std::string>(status).c_str()); |
| 5805 | status.errIfFailureAndReset(); |
| 5806 | assertEquals("de@collation=yes should drop true", |
| 5807 | "de-u-co", Locale("de@collation=yes").toLanguageTag<std::string>(status).c_str()); |
| 5808 | status.errIfFailureAndReset(); |
| 5809 | |
| 5810 | assertEquals("cmn-Hans-CN-t-ca-u-ca-x-t-u should drop true", |
| 5811 | "cmn-Hans-CN-t-ca-u-ca-x-t-u", |
| 5812 | Locale("cmn-hans-cn-u-ca-t-ca-x-t-u").toLanguageTag<std::string>(status).c_str()); |
| 5813 | status.errIfFailureAndReset(); |
| 5814 | } |
| 5815 | |
| 5816 | void LocaleTest::TestMoveAssign() { |
| 5817 | // ULOC_FULLNAME_CAPACITY == 157 (uloc.h) |
| 5818 | Locale l1("de@collation=phonebook;x=" |
| 5819 | "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh" |
| 5820 | "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh" |
| 5821 | "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh" |
| 5822 | "aaaaabbbbbzz"); |
| 5823 | |
| 5824 | Locale l2; |
| 5825 | { |
| 5826 | Locale l3(l1); |
| 5827 | assertTrue("l1 == l3", l1 == l3); |
| 5828 | l2 = std::move(l3); |
| 5829 | assertTrue("l1 == l2", l1 == l2); |
| 5830 | assertTrue("l2 != l3", l2.getName() != l3.getName()); |
| 5831 | } |
| 5832 | |
| 5833 | // This should remain true also after l3 has been destructed. |
| 5834 | assertTrue("l1 == l2, again", l1 == l2); |
| 5835 | |
| 5836 | Locale l4("de@collation=phonebook"); |
| 5837 | |
| 5838 | Locale l5; |
| 5839 | { |
| 5840 | Locale l6(l4); |
| 5841 | assertTrue("l4 == l6", l4 == l6); |
| 5842 | l5 = std::move(l6); |
| 5843 | assertTrue("l4 == l5", l4 == l5); |
| 5844 | assertTrue("l5 != l6", l5.getName() != l6.getName()); |
| 5845 | } |
| 5846 | |
| 5847 | // This should remain true also after l6 has been destructed. |
| 5848 | assertTrue("l4 == l5, again", l4 == l5); |
| 5849 | |
| 5850 | Locale l7("vo_Cyrl_AQ_EURO"); |
| 5851 | |
| 5852 | Locale l8; |
| 5853 | { |
| 5854 | Locale l9(l7); |
| 5855 | assertTrue("l7 == l9", l7 == l9); |
| 5856 | l8 = std::move(l9); |
| 5857 | assertTrue("l7 == l8", l7 == l8); |
| 5858 | assertTrue("l8 != l9", l8.getName() != l9.getName()); |
| 5859 | } |
| 5860 | |
| 5861 | // This should remain true also after l9 has been destructed. |
| 5862 | assertTrue("l7 == l8, again", l7 == l8); |
| 5863 | |
| 5864 | assertEquals("language", l7.getLanguage(), l8.getLanguage()); |
| 5865 | assertEquals("script", l7.getScript(), l8.getScript()); |
| 5866 | assertEquals("country", l7.getCountry(), l8.getCountry()); |
| 5867 | assertEquals("variant", l7.getVariant(), l8.getVariant()); |
| 5868 | assertEquals("bogus", l7.isBogus(), l8.isBogus()); |
| 5869 | } |
| 5870 | |
| 5871 | void LocaleTest::TestMoveCtor() { |
| 5872 | // ULOC_FULLNAME_CAPACITY == 157 (uloc.h) |
| 5873 | Locale l1("de@collation=phonebook;x=" |
| 5874 | "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh" |
| 5875 | "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh" |
| 5876 | "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh" |
| 5877 | "aaaaabbbbbzz"); |
| 5878 | |
| 5879 | Locale l3(l1); |
| 5880 | assertTrue("l1 == l3", l1 == l3); |
| 5881 | Locale l2(std::move(l3)); |
| 5882 | assertTrue("l1 == l2", l1 == l2); |
| 5883 | assertTrue("l2 != l3", l2.getName() != l3.getName()); |
| 5884 | |
| 5885 | Locale l4("de@collation=phonebook"); |
| 5886 | |
| 5887 | Locale l6(l4); |
| 5888 | assertTrue("l4 == l6", l4 == l6); |
| 5889 | Locale l5(std::move(l6)); |
| 5890 | assertTrue("l4 == l5", l4 == l5); |
| 5891 | assertTrue("l5 != l6", l5.getName() != l6.getName()); |
| 5892 | |
| 5893 | Locale l7("vo_Cyrl_AQ_EURO"); |
| 5894 | |
| 5895 | Locale l9(l7); |
| 5896 | assertTrue("l7 == l9", l7 == l9); |
| 5897 | Locale l8(std::move(l9)); |
| 5898 | assertTrue("l7 == l8", l7 == l8); |
| 5899 | assertTrue("l8 != l9", l8.getName() != l9.getName()); |
| 5900 | |
| 5901 | assertEquals("language", l7.getLanguage(), l8.getLanguage()); |
| 5902 | assertEquals("script", l7.getScript(), l8.getScript()); |
| 5903 | assertEquals("country", l7.getCountry(), l8.getCountry()); |
| 5904 | assertEquals("variant", l7.getVariant(), l8.getVariant()); |
| 5905 | assertEquals("bogus", l7.isBogus(), l8.isBogus()); |
| 5906 | } |
| 5907 | |
| 5908 | void LocaleTest::TestBug20407iVariantPreferredValue() { |
| 5909 | IcuTestErrorCode status(*this, "TestBug20407iVariantPreferredValue()"); |
| 5910 | |
| 5911 | Locale l = Locale::forLanguageTag("hy-arevela", status); |
| 5912 | status.errIfFailureAndReset("hy-arevela fail"); |
| 5913 | assertTrue("!l.isBogus()", !l.isBogus()); |
| 5914 | |
| 5915 | std::string result = l.toLanguageTag<std::string>(status); |
| 5916 | assertEquals(l.getName(), "hy", result.c_str()); |
| 5917 | |
| 5918 | l = Locale::forLanguageTag("hy-arevmda", status); |
| 5919 | status.errIfFailureAndReset("hy-arevmda"); |
| 5920 | assertTrue("!l.isBogus()", !l.isBogus()); |
| 5921 | |
| 5922 | result = l.toLanguageTag<std::string>(status); |
| 5923 | assertEquals(l.getName(), "hyw", result.c_str()); |
| 5924 | } |
| 5925 | |
| 5926 | void LocaleTest::TestBug13417VeryLongLanguageTag() { |
| 5927 | IcuTestErrorCode status(*this, "TestBug13417VeryLongLanguageTag()"); |
| 5928 | |
| 5929 | static const char tag[] = |
| 5930 | "zh-x" |
| 5931 | "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz" |
| 5932 | "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz" |
| 5933 | "-foo-bar-baz-foo-bar-baz-foo-bar-baz-foo-bar-baz" |
| 5934 | "-foo-bar-baz-fxx" |
| 5935 | ; |
| 5936 | |
| 5937 | Locale l = Locale::forLanguageTag(tag, status); |
| 5938 | status.errIfFailureAndReset("\"%s\"", tag); |
| 5939 | assertTrue("!l.isBogus()", !l.isBogus()); |
| 5940 | |
| 5941 | std::string result = l.toLanguageTag<std::string>(status); |
| 5942 | status.errIfFailureAndReset("\"%s\"", l.getName()); |
| 5943 | assertEquals("equals", tag, result.c_str()); |
| 5944 | } |
| 5945 | |
| 5946 | void LocaleTest::TestBug11053UnderlineTimeZone() { |
| 5947 | static const char* const tz_in_ext[] = { |
| 5948 | "etadd", |
| 5949 | "tzdar", |
| 5950 | "eheai", |
| 5951 | "sttms", |
| 5952 | "arirj", |
| 5953 | "arrgl", |
| 5954 | "aruaq", |
| 5955 | "arluq", |
| 5956 | "mxpvr", |
| 5957 | "brbvb", |
| 5958 | "arbue", |
| 5959 | "caycb", |
| 5960 | "brcgr", |
| 5961 | "cayzs", |
| 5962 | "crsjo", |
| 5963 | "caydq", |
| 5964 | "svsal", |
| 5965 | "cafne", |
| 5966 | "caglb", |
| 5967 | "cagoo", |
| 5968 | "tcgdt", |
| 5969 | "ustel", |
| 5970 | "bolpb", |
| 5971 | "uslax", |
| 5972 | "sxphi", |
| 5973 | "mxmex", |
| 5974 | "usnyc", |
| 5975 | "usxul", |
| 5976 | "usndcnt", |
| 5977 | "usndnsl", |
| 5978 | "ttpos", |
| 5979 | "brpvh", |
| 5980 | "prsju", |
| 5981 | "clpuq", |
| 5982 | "caffs", |
| 5983 | "cayek", |
| 5984 | "brrbr", |
| 5985 | "mxstis", |
| 5986 | "dosdq", |
| 5987 | "brsao", |
| 5988 | "gpsbh", |
| 5989 | "casjf", |
| 5990 | "knbas", |
| 5991 | "lccas", |
| 5992 | "vistt", |
| 5993 | "vcsvd", |
| 5994 | "cayyn", |
| 5995 | "cathu", |
| 5996 | "hkhkg", |
| 5997 | "mykul", |
| 5998 | "khpnh", |
| 5999 | "cvrai", |
| 6000 | "gsgrv", |
| 6001 | "shshn", |
| 6002 | "aubhq", |
| 6003 | "auldh", |
| 6004 | "imdgs", |
| 6005 | "smsai", |
| 6006 | "asppg", |
| 6007 | "pgpom", |
| 6008 | }; |
| 6009 | static const char* const tzname_with_underline[] = { |
| 6010 | "America/Buenos_Aires", |
| 6011 | "America/Coral_Harbour", |
| 6012 | "America/Los_Angeles", |
| 6013 | "America/Mexico_City", |
| 6014 | "America/New_York", |
| 6015 | "America/Rio_Branco", |
| 6016 | "America/Sao_Paulo", |
| 6017 | "America/St_Johns", |
| 6018 | "America/St_Thomas", |
| 6019 | "Australia/Broken_Hill", |
| 6020 | "Australia/Lord_Howe", |
| 6021 | "Pacific/Pago_Pago", |
| 6022 | }; |
| 6023 | std::string locale_str; |
| 6024 | for (int32_t i = 0; i < UPRV_LENGTHOF(tz_in_ext); i++) { |
| 6025 | locale_str = "en-u-tz-"; |
| 6026 | locale_str += tz_in_ext[i]; |
| 6027 | Locale l(locale_str.c_str()); |
| 6028 | assertTrue((locale_str + " !l.isBogus()").c_str(), !l.isBogus()); |
| 6029 | } |
| 6030 | for (int32_t i = 0; i < UPRV_LENGTHOF(tzname_with_underline); i++) { |
| 6031 | locale_str = "en@timezone="; |
| 6032 | locale_str += tzname_with_underline[i]; |
| 6033 | Locale l(locale_str.c_str()); |
| 6034 | assertTrue((locale_str + " !l.isBogus()").c_str(), !l.isBogus()); |
| 6035 | } |
| 6036 | locale_str = "en_US@timezone=America/Coral_Harbour"; |
| 6037 | Locale l2(locale_str.c_str()); |
| 6038 | assertTrue((locale_str + " !l2.isBogus()").c_str(), !l2.isBogus()); |
| 6039 | locale_str = "en_Latn@timezone=America/New_York"; |
| 6040 | Locale l3(locale_str.c_str()); |
| 6041 | assertTrue((locale_str + " !l3.isBogus()").c_str(), !l3.isBogus()); |
| 6042 | locale_str = "en_Latn_US@timezone=Australia/Broken_Hill"; |
| 6043 | Locale l4(locale_str.c_str()); |
| 6044 | assertTrue((locale_str + " !l4.isBogus()").c_str(), !l4.isBogus()); |
| 6045 | locale_str = "en-u-tz-ciabj"; |
| 6046 | Locale l5(locale_str.c_str()); |
| 6047 | assertTrue((locale_str + " !l5.isBogus()").c_str(), !l5.isBogus()); |
| 6048 | locale_str = "en-US-u-tz-asppg"; |
| 6049 | Locale l6(locale_str.c_str()); |
| 6050 | assertTrue((locale_str + " !l6.isBogus()").c_str(), !l6.isBogus()); |
| 6051 | locale_str = "fil-Latn-u-tz-cvrai"; |
| 6052 | Locale l7(locale_str.c_str()); |
| 6053 | assertTrue((locale_str + " !l7.isBogus()").c_str(), !l7.isBogus()); |
| 6054 | locale_str = "fil-Latn-PH-u-tz-gsgrv"; |
| 6055 | Locale l8(locale_str.c_str()); |
| 6056 | assertTrue((locale_str + " !l8.isBogus()").c_str(), !l8.isBogus()); |
| 6057 | } |
| 6058 | |
| 6059 | void LocaleTest::TestUnd() { |
| 6060 | IcuTestErrorCode status(*this, "TestUnd()"); |
| 6061 | |
| 6062 | static const char empty[] = ""; |
| 6063 | static const char root[] = "root"; |
| 6064 | static const char und[] = "und"; |
| 6065 | |
| 6066 | Locale empty_ctor(empty); |
| 6067 | Locale empty_tag = Locale::forLanguageTag(empty, status); |
| 6068 | status.errIfFailureAndReset("\"%s\"", empty); |
| 6069 | |
| 6070 | Locale root_ctor(root); |
| 6071 | Locale root_tag = Locale::forLanguageTag(root, status); |
| 6072 | Locale root_build = LocaleBuilder().setLanguageTag(root).build(status); |
| 6073 | status.errIfFailureAndReset("\"%s\"", root); |
| 6074 | |
| 6075 | Locale und_ctor(und); |
| 6076 | Locale und_tag = Locale::forLanguageTag(und, status); |
| 6077 | Locale und_build = LocaleBuilder().setLanguageTag(und).build(status); |
| 6078 | status.errIfFailureAndReset("\"%s\"", und); |
| 6079 | |
| 6080 | assertEquals("getName()", empty, empty_ctor.getName()); |
| 6081 | assertEquals("getName()", empty, root_ctor.getName()); |
| 6082 | assertEquals("getName()", empty, und_ctor.getName()); |
| 6083 | |
| 6084 | assertEquals("getName()", empty, empty_tag.getName()); |
| 6085 | assertEquals("getName()", empty, root_tag.getName()); |
| 6086 | assertEquals("getName()", empty, und_tag.getName()); |
| 6087 | |
| 6088 | assertEquals("getName()", empty, root_build.getName()); |
| 6089 | assertEquals("getName()", empty, und_build.getName()); |
| 6090 | |
| 6091 | assertEquals("toLanguageTag()", und, empty_ctor.toLanguageTag<std::string>(status).c_str()); |
| 6092 | assertEquals("toLanguageTag()", und, root_ctor.toLanguageTag<std::string>(status).c_str()); |
| 6093 | assertEquals("toLanguageTag()", und, und_ctor.toLanguageTag<std::string>(status).c_str()); |
| 6094 | status.errIfFailureAndReset(); |
| 6095 | |
| 6096 | assertEquals("toLanguageTag()", und, empty_tag.toLanguageTag<std::string>(status).c_str()); |
| 6097 | assertEquals("toLanguageTag()", und, root_tag.toLanguageTag<std::string>(status).c_str()); |
| 6098 | assertEquals("toLanguageTag()", und, und_tag.toLanguageTag<std::string>(status).c_str()); |
| 6099 | status.errIfFailureAndReset(); |
| 6100 | |
| 6101 | assertEquals("toLanguageTag()", und, root_build.toLanguageTag<std::string>(status).c_str()); |
| 6102 | assertEquals("toLanguageTag()", und, und_build.toLanguageTag<std::string>(status).c_str()); |
| 6103 | status.errIfFailureAndReset(); |
| 6104 | |
| 6105 | assertTrue("empty_ctor == empty_tag", empty_ctor == empty_tag); |
| 6106 | |
| 6107 | assertTrue("root_ctor == root_tag", root_ctor == root_tag); |
| 6108 | assertTrue("root_ctor == root_build", root_ctor == root_build); |
| 6109 | assertTrue("root_tag == root_build", root_tag == root_build); |
| 6110 | |
| 6111 | assertTrue("und_ctor == und_tag", und_ctor == und_tag); |
| 6112 | assertTrue("und_ctor == und_build", und_ctor == und_build); |
| 6113 | assertTrue("und_tag == und_build", und_tag == und_build); |
| 6114 | |
| 6115 | assertTrue("empty_ctor == root_ctor", empty_ctor == root_ctor); |
| 6116 | assertTrue("empty_ctor == und_ctor", empty_ctor == und_ctor); |
| 6117 | assertTrue("root_ctor == und_ctor", root_ctor == und_ctor); |
| 6118 | |
| 6119 | assertTrue("empty_tag == root_tag", empty_tag == root_tag); |
| 6120 | assertTrue("empty_tag == und_tag", empty_tag == und_tag); |
| 6121 | assertTrue("root_tag == und_tag", root_tag == und_tag); |
| 6122 | |
| 6123 | assertTrue("root_build == und_build", root_build == und_build); |
| 6124 | |
| 6125 | static const Locale& displayLocale = Locale::getEnglish(); |
| 6126 | static const UnicodeString displayName("Unknown language"); |
| 6127 | UnicodeString tmp; |
| 6128 | |
| 6129 | assertEquals("getDisplayName()", displayName, empty_ctor.getDisplayName(displayLocale, tmp)); |
| 6130 | assertEquals("getDisplayName()", displayName, root_ctor.getDisplayName(displayLocale, tmp)); |
| 6131 | assertEquals("getDisplayName()", displayName, und_ctor.getDisplayName(displayLocale, tmp)); |
| 6132 | |
| 6133 | assertEquals("getDisplayName()", displayName, empty_tag.getDisplayName(displayLocale, tmp)); |
| 6134 | assertEquals("getDisplayName()", displayName, root_tag.getDisplayName(displayLocale, tmp)); |
| 6135 | assertEquals("getDisplayName()", displayName, und_tag.getDisplayName(displayLocale, tmp)); |
| 6136 | |
| 6137 | assertEquals("getDisplayName()", displayName, root_build.getDisplayName(displayLocale, tmp)); |
| 6138 | assertEquals("getDisplayName()", displayName, und_build.getDisplayName(displayLocale, tmp)); |
| 6139 | } |
| 6140 | |
| 6141 | void LocaleTest::TestUndScript() { |
| 6142 | IcuTestErrorCode status(*this, "TestUndScript()"); |
| 6143 | |
| 6144 | static const char id[] = "_Cyrl"; |
| 6145 | static const char tag[] = "und-Cyrl"; |
| 6146 | static const char script[] = "Cyrl"; |
| 6147 | |
| 6148 | Locale locale_ctor(id); |
| 6149 | Locale locale_legacy(tag); |
| 6150 | Locale locale_tag = Locale::forLanguageTag(tag, status); |
| 6151 | Locale locale_build = LocaleBuilder().setScript(script).build(status); |
| 6152 | status.errIfFailureAndReset("\"%s\"", tag); |
| 6153 | |
| 6154 | assertEquals("getName()", id, locale_ctor.getName()); |
| 6155 | assertEquals("getName()", id, locale_legacy.getName()); |
| 6156 | assertEquals("getName()", id, locale_tag.getName()); |
| 6157 | assertEquals("getName()", id, locale_build.getName()); |
| 6158 | |
| 6159 | assertEquals("toLanguageTag()", tag, locale_ctor.toLanguageTag<std::string>(status).c_str()); |
| 6160 | assertEquals("toLanguageTag()", tag, locale_legacy.toLanguageTag<std::string>(status).c_str()); |
| 6161 | assertEquals("toLanguageTag()", tag, locale_tag.toLanguageTag<std::string>(status).c_str()); |
| 6162 | assertEquals("toLanguageTag()", tag, locale_build.toLanguageTag<std::string>(status).c_str()); |
| 6163 | status.errIfFailureAndReset(); |
| 6164 | |
| 6165 | static const Locale& displayLocale = Locale::getEnglish(); |
| 6166 | static const UnicodeString displayName("Unknown language (Cyrillic)"); |
| 6167 | UnicodeString tmp; |
| 6168 | |
| 6169 | assertEquals("getDisplayName()", displayName, locale_ctor.getDisplayName(displayLocale, tmp)); |
| 6170 | assertEquals("getDisplayName()", displayName, locale_legacy.getDisplayName(displayLocale, tmp)); |
| 6171 | assertEquals("getDisplayName()", displayName, locale_tag.getDisplayName(displayLocale, tmp)); |
| 6172 | assertEquals("getDisplayName()", displayName, locale_build.getDisplayName(displayLocale, tmp)); |
| 6173 | } |
| 6174 | |
| 6175 | void LocaleTest::TestUndRegion() { |
| 6176 | IcuTestErrorCode status(*this, "TestUndRegion()"); |
| 6177 | |
| 6178 | static const char id[] = "_AQ"; |
| 6179 | static const char tag[] = "und-AQ"; |
| 6180 | static const char region[] = "AQ"; |
| 6181 | |
| 6182 | Locale locale_ctor(id); |
| 6183 | Locale locale_legacy(tag); |
| 6184 | Locale locale_tag = Locale::forLanguageTag(tag, status); |
| 6185 | Locale locale_build = LocaleBuilder().setRegion(region).build(status); |
| 6186 | status.errIfFailureAndReset("\"%s\"", tag); |
| 6187 | |
| 6188 | assertEquals("getName()", id, locale_ctor.getName()); |
| 6189 | assertEquals("getName()", id, locale_legacy.getName()); |
| 6190 | assertEquals("getName()", id, locale_tag.getName()); |
| 6191 | assertEquals("getName()", id, locale_build.getName()); |
| 6192 | |
| 6193 | assertEquals("toLanguageTag()", tag, locale_ctor.toLanguageTag<std::string>(status).c_str()); |
| 6194 | assertEquals("toLanguageTag()", tag, locale_legacy.toLanguageTag<std::string>(status).c_str()); |
| 6195 | assertEquals("toLanguageTag()", tag, locale_tag.toLanguageTag<std::string>(status).c_str()); |
| 6196 | assertEquals("toLanguageTag()", tag, locale_build.toLanguageTag<std::string>(status).c_str()); |
| 6197 | status.errIfFailureAndReset(); |
| 6198 | |
| 6199 | static const Locale& displayLocale = Locale::getEnglish(); |
| 6200 | static const UnicodeString displayName("Unknown language (Antarctica)"); |
| 6201 | UnicodeString tmp; |
| 6202 | |
| 6203 | assertEquals("getDisplayName()", displayName, locale_ctor.getDisplayName(displayLocale, tmp)); |
| 6204 | assertEquals("getDisplayName()", displayName, locale_legacy.getDisplayName(displayLocale, tmp)); |
| 6205 | assertEquals("getDisplayName()", displayName, locale_tag.getDisplayName(displayLocale, tmp)); |
| 6206 | assertEquals("getDisplayName()", displayName, locale_build.getDisplayName(displayLocale, tmp)); |
| 6207 | } |
| 6208 | |
| 6209 | void LocaleTest::TestUndCAPI() { |
| 6210 | IcuTestErrorCode status(*this, "TestUndCAPI()"); |
| 6211 | |
| 6212 | static const char empty[] = ""; |
| 6213 | static const char root[] = "root"; |
| 6214 | static const char und[] = "und"; |
| 6215 | |
| 6216 | static const char empty_script[] = "_Cyrl"; |
| 6217 | static const char empty_region[] = "_AQ"; |
| 6218 | |
| 6219 | static const char und_script[] = "und_Cyrl"; |
| 6220 | static const char und_region[] = "und_AQ"; |
| 6221 | |
| 6222 | char tmp[ULOC_FULLNAME_CAPACITY]; |
| 6223 | int32_t reslen; |
| 6224 | |
| 6225 | // uloc_getName() |
| 6226 | |
| 6227 | uprv_memset(tmp, '!', sizeof tmp); |
| 6228 | reslen = uloc_getName(empty, tmp, sizeof tmp, status); |
| 6229 | status.errIfFailureAndReset("\"%s\"", empty); |
| 6230 | assertTrue("reslen >= 0", reslen >= 0); |
| 6231 | assertEquals("uloc_getName()", empty, tmp); |
| 6232 | |
| 6233 | uprv_memset(tmp, '!', sizeof tmp); |
| 6234 | reslen = uloc_getName(root, tmp, sizeof tmp, status); |
| 6235 | status.errIfFailureAndReset("\"%s\"", root); |
| 6236 | assertTrue("reslen >= 0", reslen >= 0); |
| 6237 | assertEquals("uloc_getName()", empty, tmp); |
| 6238 | |
| 6239 | uprv_memset(tmp, '!', sizeof tmp); |
| 6240 | reslen = uloc_getName(und, tmp, sizeof tmp, status); |
| 6241 | status.errIfFailureAndReset("\"%s\"", und); |
| 6242 | assertTrue("reslen >= 0", reslen >= 0); |
| 6243 | assertEquals("uloc_getName()", empty, tmp); |
| 6244 | |
| 6245 | uprv_memset(tmp, '!', sizeof tmp); |
| 6246 | reslen = uloc_getName(empty_script, tmp, sizeof tmp, status); |
| 6247 | status.errIfFailureAndReset("\"%s\"", empty_script); |
| 6248 | assertTrue("reslen >= 0", reslen >= 0); |
| 6249 | assertEquals("uloc_getName()", empty_script, tmp); |
| 6250 | |
| 6251 | uprv_memset(tmp, '!', sizeof tmp); |
| 6252 | reslen = uloc_getName(empty_region, tmp, sizeof tmp, status); |
| 6253 | status.errIfFailureAndReset("\"%s\"", empty_region); |
| 6254 | assertTrue("reslen >= 0", reslen >= 0); |
| 6255 | assertEquals("uloc_getName()", empty_region, tmp); |
| 6256 | |
| 6257 | uprv_memset(tmp, '!', sizeof tmp); |
| 6258 | reslen = uloc_getName(und_script, tmp, sizeof tmp, status); |
| 6259 | status.errIfFailureAndReset("\"%s\"", und_script); |
| 6260 | assertTrue("reslen >= 0", reslen >= 0); |
| 6261 | assertEquals("uloc_getName()", empty_script, tmp); |
| 6262 | |
| 6263 | uprv_memset(tmp, '!', sizeof tmp); |
| 6264 | reslen = uloc_getName(und_region, tmp, sizeof tmp, status); |
| 6265 | status.errIfFailureAndReset("\"%s\"", und_region); |
| 6266 | assertTrue("reslen >= 0", reslen >= 0); |
| 6267 | assertEquals("uloc_getName()", empty_region, tmp); |
| 6268 | |
| 6269 | // uloc_getBaseName() |
| 6270 | |
| 6271 | uprv_memset(tmp, '!', sizeof tmp); |
| 6272 | reslen = uloc_getBaseName(empty, tmp, sizeof tmp, status); |
| 6273 | status.errIfFailureAndReset("\"%s\"", empty); |
| 6274 | assertTrue("reslen >= 0", reslen >= 0); |
| 6275 | assertEquals("uloc_getBaseName()", empty, tmp); |
| 6276 | |
| 6277 | uprv_memset(tmp, '!', sizeof tmp); |
| 6278 | reslen = uloc_getBaseName(root, tmp, sizeof tmp, status); |
| 6279 | status.errIfFailureAndReset("\"%s\"", root); |
| 6280 | assertTrue("reslen >= 0", reslen >= 0); |
| 6281 | assertEquals("uloc_getBaseName()", empty, tmp); |
| 6282 | |
| 6283 | uprv_memset(tmp, '!', sizeof tmp); |
| 6284 | reslen = uloc_getBaseName(und, tmp, sizeof tmp, status); |
| 6285 | status.errIfFailureAndReset("\"%s\"", und); |
| 6286 | assertTrue("reslen >= 0", reslen >= 0); |
| 6287 | assertEquals("uloc_getBaseName()", empty, tmp); |
| 6288 | |
| 6289 | uprv_memset(tmp, '!', sizeof tmp); |
| 6290 | reslen = uloc_getBaseName(empty_script, tmp, sizeof tmp, status); |
| 6291 | status.errIfFailureAndReset("\"%s\"", empty_script); |
| 6292 | assertTrue("reslen >= 0", reslen >= 0); |
| 6293 | assertEquals("uloc_getBaseName()", empty_script, tmp); |
| 6294 | |
| 6295 | uprv_memset(tmp, '!', sizeof tmp); |
| 6296 | reslen = uloc_getBaseName(empty_region, tmp, sizeof tmp, status); |
| 6297 | status.errIfFailureAndReset("\"%s\"", empty_region); |
| 6298 | assertTrue("reslen >= 0", reslen >= 0); |
| 6299 | assertEquals("uloc_getBaseName()", empty_region, tmp); |
| 6300 | |
| 6301 | uprv_memset(tmp, '!', sizeof tmp); |
| 6302 | reslen = uloc_getBaseName(und_script, tmp, sizeof tmp, status); |
| 6303 | status.errIfFailureAndReset("\"%s\"", und_script); |
| 6304 | assertTrue("reslen >= 0", reslen >= 0); |
| 6305 | assertEquals("uloc_getBaseName()", empty_script, tmp); |
| 6306 | |
| 6307 | uprv_memset(tmp, '!', sizeof tmp); |
| 6308 | reslen = uloc_getBaseName(und_region, tmp, sizeof tmp, status); |
| 6309 | status.errIfFailureAndReset("\"%s\"", und_region); |
| 6310 | assertTrue("reslen >= 0", reslen >= 0); |
| 6311 | assertEquals("uloc_getBaseName()", empty_region, tmp); |
| 6312 | |
| 6313 | // uloc_getParent() |
| 6314 | |
| 6315 | uprv_memset(tmp, '!', sizeof tmp); |
| 6316 | reslen = uloc_getParent(empty, tmp, sizeof tmp, status); |
| 6317 | status.errIfFailureAndReset("\"%s\"", empty); |
| 6318 | assertTrue("reslen >= 0", reslen >= 0); |
| 6319 | assertEquals("uloc_getParent()", empty, tmp); |
| 6320 | |
| 6321 | uprv_memset(tmp, '!', sizeof tmp); |
| 6322 | reslen = uloc_getParent(root, tmp, sizeof tmp, status); |
| 6323 | status.errIfFailureAndReset("\"%s\"", root); |
| 6324 | assertTrue("reslen >= 0", reslen >= 0); |
| 6325 | assertEquals("uloc_getParent()", empty, tmp); |
| 6326 | |
| 6327 | uprv_memset(tmp, '!', sizeof tmp); |
| 6328 | reslen = uloc_getParent(und, tmp, sizeof tmp, status); |
| 6329 | status.errIfFailureAndReset("\"%s\"", und); |
| 6330 | assertTrue("reslen >= 0", reslen >= 0); |
| 6331 | assertEquals("uloc_getParent()", empty, tmp); |
| 6332 | |
| 6333 | uprv_memset(tmp, '!', sizeof tmp); |
| 6334 | reslen = uloc_getParent(empty_script, tmp, sizeof tmp, status); |
| 6335 | status.errIfFailureAndReset("\"%s\"", empty_script); |
| 6336 | assertTrue("reslen >= 0", reslen >= 0); |
| 6337 | assertEquals("uloc_getParent()", empty, tmp); |
| 6338 | |
| 6339 | uprv_memset(tmp, '!', sizeof tmp); |
| 6340 | reslen = uloc_getParent(empty_region, tmp, sizeof tmp, status); |
| 6341 | status.errIfFailureAndReset("\"%s\"", empty_region); |
| 6342 | assertTrue("reslen >= 0", reslen >= 0); |
| 6343 | assertEquals("uloc_getParent()", empty, tmp); |
| 6344 | |
| 6345 | uprv_memset(tmp, '!', sizeof tmp); |
| 6346 | reslen = uloc_getParent(und_script, tmp, sizeof tmp, status); |
| 6347 | status.errIfFailureAndReset("\"%s\"", und_script); |
| 6348 | assertTrue("reslen >= 0", reslen >= 0); |
| 6349 | assertEquals("uloc_getParent()", empty, tmp); |
| 6350 | |
| 6351 | uprv_memset(tmp, '!', sizeof tmp); |
| 6352 | reslen = uloc_getParent(und_region, tmp, sizeof tmp, status); |
| 6353 | status.errIfFailureAndReset("\"%s\"", und_region); |
| 6354 | assertTrue("reslen >= 0", reslen >= 0); |
| 6355 | assertEquals("uloc_getParent()", empty, tmp); |
| 6356 | |
| 6357 | // uloc_getLanguage() |
| 6358 | |
| 6359 | uprv_memset(tmp, '!', sizeof tmp); |
| 6360 | reslen = uloc_getLanguage(empty, tmp, sizeof tmp, status); |
| 6361 | status.errIfFailureAndReset("\"%s\"", empty); |
| 6362 | assertTrue("reslen >= 0", reslen >= 0); |
| 6363 | assertEquals("uloc_getLanguage()", empty, tmp); |
| 6364 | |
| 6365 | uprv_memset(tmp, '!', sizeof tmp); |
| 6366 | reslen = uloc_getLanguage(root, tmp, sizeof tmp, status); |
| 6367 | status.errIfFailureAndReset("\"%s\"", root); |
| 6368 | assertTrue("reslen >= 0", reslen >= 0); |
| 6369 | assertEquals("uloc_getLanguage()", empty, tmp); |
| 6370 | |
| 6371 | uprv_memset(tmp, '!', sizeof tmp); |
| 6372 | reslen = uloc_getLanguage(und, tmp, sizeof tmp, status); |
| 6373 | status.errIfFailureAndReset("\"%s\"", und); |
| 6374 | assertTrue("reslen >= 0", reslen >= 0); |
| 6375 | assertEquals("uloc_getLanguage()", empty, tmp); |
| 6376 | |
| 6377 | uprv_memset(tmp, '!', sizeof tmp); |
| 6378 | reslen = uloc_getLanguage(empty_script, tmp, sizeof tmp, status); |
| 6379 | status.errIfFailureAndReset("\"%s\"", empty_script); |
| 6380 | assertTrue("reslen >= 0", reslen >= 0); |
| 6381 | assertEquals("uloc_getLanguage()", empty, tmp); |
| 6382 | |
| 6383 | uprv_memset(tmp, '!', sizeof tmp); |
| 6384 | reslen = uloc_getLanguage(empty_region, tmp, sizeof tmp, status); |
| 6385 | status.errIfFailureAndReset("\"%s\"", empty_region); |
| 6386 | assertTrue("reslen >= 0", reslen >= 0); |
| 6387 | assertEquals("uloc_getLanguage()", empty, tmp); |
| 6388 | |
| 6389 | uprv_memset(tmp, '!', sizeof tmp); |
| 6390 | reslen = uloc_getLanguage(und_script, tmp, sizeof tmp, status); |
| 6391 | status.errIfFailureAndReset("\"%s\"", und_script); |
| 6392 | assertTrue("reslen >= 0", reslen >= 0); |
| 6393 | assertEquals("uloc_getLanguage()", empty, tmp); |
| 6394 | |
| 6395 | uprv_memset(tmp, '!', sizeof tmp); |
| 6396 | reslen = uloc_getLanguage(und_region, tmp, sizeof tmp, status); |
| 6397 | status.errIfFailureAndReset("\"%s\"", und_region); |
| 6398 | assertTrue("reslen >= 0", reslen >= 0); |
| 6399 | assertEquals("uloc_getLanguage()", empty, tmp); |
| 6400 | } |
| 6401 | |
| 6402 | #define ARRAY_RANGE(array) (array), ((array) + UPRV_LENGTHOF(array)) |
| 6403 | |
| 6404 | void LocaleTest::TestRangeIterator() { |
| 6405 | IcuTestErrorCode status(*this, "TestRangeIterator"); |
| 6406 | Locale locales[] = { "fr", "en_GB", "en" }; |
| 6407 | Locale::RangeIterator<Locale *> iter(ARRAY_RANGE(locales)); |
| 6408 | |
| 6409 | assertTrue("0.hasNext()", iter.hasNext()); |
| 6410 | const Locale &l0 = iter.next(); |
| 6411 | assertEquals("0.next()", "fr", l0.getName()); |
| 6412 | assertTrue("&0.next()", &l0 == &locales[0]); |
| 6413 | |
| 6414 | assertTrue("1.hasNext()", iter.hasNext()); |
| 6415 | const Locale &l1 = iter.next(); |
| 6416 | assertEquals("1.next()", "en_GB", l1.getName()); |
| 6417 | assertTrue("&1.next()", &l1 == &locales[1]); |
| 6418 | |
| 6419 | assertTrue("2.hasNext()", iter.hasNext()); |
| 6420 | const Locale &l2 = iter.next(); |
| 6421 | assertEquals("2.next()", "en", l2.getName()); |
| 6422 | assertTrue("&2.next()", &l2 == &locales[2]); |
| 6423 | |
| 6424 | assertFalse("3.hasNext()", iter.hasNext()); |
| 6425 | } |
| 6426 | |
| 6427 | void LocaleTest::TestPointerConvertingIterator() { |
| 6428 | IcuTestErrorCode status(*this, "TestPointerConvertingIterator"); |
| 6429 | Locale locales[] = { "fr", "en_GB", "en" }; |
| 6430 | Locale *pointers[] = { locales, locales + 1, locales + 2 }; |
| 6431 | // Lambda with explicit reference return type to prevent copy-constructing a temporary |
| 6432 | // which would be destructed right away. |
| 6433 | Locale::ConvertingIterator<Locale **, std::function<const Locale &(const Locale *)>> iter( |
| 6434 | ARRAY_RANGE(pointers), [](const Locale *p) -> const Locale & { return *p; }); |
| 6435 | |
| 6436 | assertTrue("0.hasNext()", iter.hasNext()); |
| 6437 | const Locale &l0 = iter.next(); |
| 6438 | assertEquals("0.next()", "fr", l0.getName()); |
| 6439 | assertTrue("&0.next()", &l0 == pointers[0]); |
| 6440 | |
| 6441 | assertTrue("1.hasNext()", iter.hasNext()); |
| 6442 | const Locale &l1 = iter.next(); |
| 6443 | assertEquals("1.next()", "en_GB", l1.getName()); |
| 6444 | assertTrue("&1.next()", &l1 == pointers[1]); |
| 6445 | |
| 6446 | assertTrue("2.hasNext()", iter.hasNext()); |
| 6447 | const Locale &l2 = iter.next(); |
| 6448 | assertEquals("2.next()", "en", l2.getName()); |
| 6449 | assertTrue("&2.next()", &l2 == pointers[2]); |
| 6450 | |
| 6451 | assertFalse("3.hasNext()", iter.hasNext()); |
| 6452 | } |
| 6453 | |
| 6454 | namespace { |
| 6455 | |
| 6456 | class LocaleFromTag { |
| 6457 | public: |
| 6458 | LocaleFromTag() : locale(Locale::getRoot()) {} |
| 6459 | const Locale &operator()(const char *tag) { return locale = Locale(tag); } |
| 6460 | |
| 6461 | private: |
| 6462 | // Store the locale in the converter, rather than return a reference to a temporary, |
| 6463 | // or a value which could go out of scope with the caller's reference to it. |
| 6464 | Locale locale; |
| 6465 | }; |
| 6466 | |
| 6467 | } // namespace |
| 6468 | |
| 6469 | void LocaleTest::TestTagConvertingIterator() { |
| 6470 | IcuTestErrorCode status(*this, "TestTagConvertingIterator"); |
| 6471 | const char *tags[] = { "fr", "en_GB", "en" }; |
| 6472 | LocaleFromTag converter; |
| 6473 | Locale::ConvertingIterator<const char **, LocaleFromTag> iter(ARRAY_RANGE(tags), converter); |
| 6474 | |
| 6475 | assertTrue("0.hasNext()", iter.hasNext()); |
| 6476 | const Locale &l0 = iter.next(); |
| 6477 | assertEquals("0.next()", "fr", l0.getName()); |
| 6478 | |
| 6479 | assertTrue("1.hasNext()", iter.hasNext()); |
| 6480 | const Locale &l1 = iter.next(); |
| 6481 | assertEquals("1.next()", "en_GB", l1.getName()); |
| 6482 | |
| 6483 | assertTrue("2.hasNext()", iter.hasNext()); |
| 6484 | const Locale &l2 = iter.next(); |
| 6485 | assertEquals("2.next()", "en", l2.getName()); |
| 6486 | |
| 6487 | assertFalse("3.hasNext()", iter.hasNext()); |
| 6488 | } |
| 6489 | |
| 6490 | void LocaleTest::TestCapturingTagConvertingIterator() { |
| 6491 | IcuTestErrorCode status(*this, "TestCapturingTagConvertingIterator"); |
| 6492 | const char *tags[] = { "fr", "en_GB", "en" }; |
| 6493 | // Store the converted locale in a locale variable, |
| 6494 | // rather than return a reference to a temporary, |
| 6495 | // or a value which could go out of scope with the caller's reference to it. |
| 6496 | Locale locale; |
| 6497 | // Lambda with explicit reference return type to prevent copy-constructing a temporary |
| 6498 | // which would be destructed right away. |
| 6499 | Locale::ConvertingIterator<const char **, std::function<const Locale &(const char *)>> iter( |
| 6500 | ARRAY_RANGE(tags), [&](const char *tag) -> const Locale & { return locale = Locale(tag); }); |
| 6501 | |
| 6502 | assertTrue("0.hasNext()", iter.hasNext()); |
| 6503 | const Locale &l0 = iter.next(); |
| 6504 | assertEquals("0.next()", "fr", l0.getName()); |
| 6505 | |
| 6506 | assertTrue("1.hasNext()", iter.hasNext()); |
| 6507 | const Locale &l1 = iter.next(); |
| 6508 | assertEquals("1.next()", "en_GB", l1.getName()); |
| 6509 | |
| 6510 | assertTrue("2.hasNext()", iter.hasNext()); |
| 6511 | const Locale &l2 = iter.next(); |
| 6512 | assertEquals("2.next()", "en", l2.getName()); |
| 6513 | |
| 6514 | assertFalse("3.hasNext()", iter.hasNext()); |
| 6515 | } |
| 6516 | |
| 6517 | void LocaleTest::TestSetUnicodeKeywordValueInLongLocale() { |
| 6518 | IcuTestErrorCode status(*this, "TestSetUnicodeKeywordValueInLongLocale"); |
| 6519 | const char* value = "efghijkl"; |
| 6520 | icu::Locale l("de"); |
| 6521 | char keyword[3]; |
| 6522 | CharString expected("de-u", status); |
| 6523 | keyword[2] = '\0'; |
| 6524 | for (char i = 'a'; i < 's'; i++) { |
| 6525 | keyword[0] = keyword[1] = i; |
| 6526 | expected.append("-", status); |
| 6527 | expected.append(keyword, status); |
| 6528 | expected.append("-", status); |
| 6529 | expected.append(value, status); |
| 6530 | l.setUnicodeKeywordValue(keyword, value, status); |
| 6531 | if (status.errIfFailureAndReset( |
| 6532 | "setUnicodeKeywordValue(\"%s\", \"%s\") fail while locale is \"%s\"", |
| 6533 | keyword, value, l.getName())) { |
| 6534 | return; |
| 6535 | } |
| 6536 | std::string tag = l.toLanguageTag<std::string>(status); |
| 6537 | if (status.errIfFailureAndReset( |
| 6538 | "toLanguageTag fail on \"%s\"", l.getName())) { |
| 6539 | return; |
| 6540 | } |
| 6541 | if (tag != expected.data()) { |
| 6542 | errln("Expected to get \"%s\" bug got \"%s\"", tag.c_str(), |
| 6543 | expected.data()); |
| 6544 | return; |
| 6545 | } |
| 6546 | } |
| 6547 | } |
| 6548 | |
| 6549 | void LocaleTest::TestLongLocaleSetKeywordAssign() { |
| 6550 | IcuTestErrorCode status(*this, "TestLongLocaleSetKeywordAssign"); |
| 6551 | // A long base name, with an illegal keyword and copy constructor |
| 6552 | icu::Locale l("de_AAAAAAA1_AAAAAAA2_AAAAAAA3_AAAAAAA4_AAAAAAA5_AAAAAAA6_" |
| 6553 | "AAAAAAA7_AAAAAAA8_AAAAAAA9_AAAAAA10_AAAAAA11_AAAAAA12_" |
| 6554 | "AAAAAA13_AAAAAA14_AAAAAA15_AAAAAA16_AAAAAA17_AAAAAA18"); |
| 6555 | Locale l2; |
| 6556 | l.setUnicodeKeywordValue("co", "12", status); // Cause an error |
| 6557 | status.reset(); |
| 6558 | l2 = l; // copy operator on such bogus locale. |
| 6559 | } |
| 6560 | |
| 6561 | void LocaleTest::TestLongLocaleSetKeywordMoveAssign() { |
| 6562 | IcuTestErrorCode status(*this, "TestLongLocaleSetKeywordMoveAssign"); |
| 6563 | // A long base name, with an illegal keyword and copy constructor |
| 6564 | icu::Locale l("de_AAAAAAA1_AAAAAAA2_AAAAAAA3_AAAAAAA4_AAAAAAA5_AAAAAAA6_" |
| 6565 | "AAAAAAA7_AAAAAAA8_AAAAAAA9_AAAAAA10_AAAAAA11_AAAAAA12_" |
| 6566 | "AAAAAA13_AAAAAA14_AAAAAA15_AAAAAA16_AAAAAA17"); |
| 6567 | Locale l2; |
| 6568 | l.setUnicodeKeywordValue("co", "12", status); // Cause an error |
| 6569 | status.reset(); |
| 6570 | Locale l3 = std::move(l); // move assign |
| 6571 | } |
| 6572 | |
| 6573 | void LocaleTest::TestSetUnicodeKeywordValueNullInLongLocale() { |
| 6574 | IcuTestErrorCode status(*this, "TestSetUnicodeKeywordValueNullInLongLocale"); |
| 6575 | const char *exts[] = {"cf", "cu", "em", "kk", "kr", "ks", "kv", "lb", "lw", |
| 6576 | "ms", "nu", "rg", "sd", "ss", "tz"}; |
| 6577 | for (int32_t i = 0; i < UPRV_LENGTHOF(exts); i++) { |
| 6578 | CharString tag("de-u", status); |
| 6579 | for (int32_t j = 0; j <= i; j++) { |
| 6580 | tag.append("-", status).append(exts[j], status); |
| 6581 | } |
| 6582 | if (status.errIfFailureAndReset( |
| 6583 | "Cannot create tag \"%s\"", tag.data())) { |
| 6584 | continue; |
| 6585 | } |
| 6586 | Locale l = Locale::forLanguageTag(tag.data(), status); |
| 6587 | if (status.errIfFailureAndReset( |
| 6588 | "Locale::forLanguageTag(\"%s\") failed", tag.data())) { |
| 6589 | continue; |
| 6590 | } |
| 6591 | for (int32_t j = 0; j <= i; j++) { |
| 6592 | l.setUnicodeKeywordValue(exts[j], nullptr, status); |
| 6593 | if (status.errIfFailureAndReset( |
| 6594 | "Locale(\"%s\").setUnicodeKeywordValue(\"%s\", nullptr) failed", |
| 6595 | tag.data(), exts[j])) { |
| 6596 | continue; |
| 6597 | } |
| 6598 | } |
| 6599 | if (strcmp("de", l.getName()) != 0) { |
| 6600 | errln("setUnicodeKeywordValue should remove all extensions from " |
| 6601 | "\"%s\" and only have \"de\", but is \"%s\" instead.", |
| 6602 | tag.data(), l.getName()); |
| 6603 | } |
| 6604 | } |
| 6605 | } |
| 6606 | |
| 6607 | void LocaleTest::TestLeak21419() { |
| 6608 | IcuTestErrorCode status(*this, "TestLeak21419"); |
| 6609 | Locale l = Locale("s-yU"); |
| 6610 | l.canonicalize(status); |
| 6611 | status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR); |
| 6612 | } |
| 6613 | |
| 6614 | void LocaleTest::TestNullDereferenceWrite21597() { |
| 6615 | IcuTestErrorCode status(*this, "TestNullDereferenceWrite21597"); |
| 6616 | Locale l = Locale("zu-t-q5-X1-vKf-KK-Ks-cO--Kc"); |
| 6617 | l.canonicalize(status); |
| 6618 | status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR); |
| 6619 | } |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 6620 | #if !UCONFIG_NO_FORMATTING |
| 6621 | void LocaleTest::TestSierraLeoneCurrency21997() { |
| 6622 | // CLDR 41: Check that currency of Sierra Leone is SLL (which is legal tender) |
| 6623 | // and not the newer currency SLE (which is not legal tender), as of CLDR 41. |
| 6624 | // Test will fail once SLE is declared legal. |
| 6625 | // CLDR 42: Now check that currency of Sierra Leone is SLE (which is legal tender) |
| 6626 | UnicodeString sllStr("SLE", ""), resultStr; |
| 6627 | UChar tmp[4]; |
| 6628 | UErrorCode status = U_ZERO_ERROR; |
| 6629 | |
| 6630 | ucurr_forLocale("en_SL", tmp, 4, &status); |
| 6631 | resultStr.setTo(tmp); |
| 6632 | if (sllStr != resultStr) { |
| 6633 | errcheckln(status, "Fail: en_SL didn't return SLE - %s", u_errorName(status)); |
| 6634 | } |
| 6635 | } |
| 6636 | #endif |