1 /******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2015, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ********************************************************************/ 6 /***************************************************************************** 7 * 8 * File CLOCTST.C 9 * 10 * Modification History: 11 * Name Description 12 * Madhu Katragadda Ported for C API 13 ****************************************************************************** 14 */ 15 #include "cloctst.h" 16 #include <stdlib.h> 17 #include <stdio.h> 18 #include <string.h> 19 #include "cintltst.h" 20 #include "cstring.h" 21 #include "uparse.h" 22 #include "uresimp.h" 23 24 #include "unicode/putil.h" 25 #include "unicode/ubrk.h" 26 #include "unicode/uchar.h" 27 #include "unicode/ucol.h" 28 #include "unicode/udat.h" 29 #include "unicode/uloc.h" 30 #include "unicode/umsg.h" 31 #include "unicode/ures.h" 32 #include "unicode/uset.h" 33 #include "unicode/ustring.h" 34 #include "unicode/utypes.h" 35 #include "unicode/ulocdata.h" 36 #include "unicode/uldnames.h" 37 #include "unicode/parseerr.h" /* may not be included with some uconfig switches */ 38 #include "udbgutil.h" 39 40 static void TestNullDefault(void); 41 static void TestNonexistentLanguageExemplars(void); 42 static void TestLocDataErrorCodeChaining(void); 43 static void TestLanguageExemplarsFallbacks(void); 44 static void TestDisplayNameBrackets(void); 45 46 static void TestUnicodeDefines(void); 47 48 static void TestIsRightToLeft(void); 49 50 void PrintDataTable(); 51 52 /*--------------------------------------------------- 53 table of valid data 54 --------------------------------------------------- */ 55 #define LOCALE_SIZE 9 56 #define LOCALE_INFO_SIZE 28 57 58 static const char* const rawData2[LOCALE_INFO_SIZE][LOCALE_SIZE] = { 59 /* language code */ 60 { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" }, 61 /* script code */ 62 { "", "", "", "", "", "", "", "", "" }, 63 /* country code */ 64 { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" }, 65 /* variant code */ 66 { "", "", "", "", "NY", "", "", "", "" }, 67 /* full name */ 68 { "en_US", "fr_FR", "ca_ES", 69 "el_GR", "no_NO_NY", "zh_Hans_CN", 70 "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" }, 71 /* ISO-3 language */ 72 { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" }, 73 /* ISO-3 country */ 74 { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" }, 75 /* LCID */ 76 { "409", "40c", "403", "408", "814", "804", "10407", "40a", "411" }, 77 78 /* display language (English) */ 79 { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" }, 80 /* display script code (English) */ 81 { "", "", "", "", "", "Simplified Han", "", "", "" }, 82 /* display country (English) */ 83 { "United States", "France", "Spain", "Greece", "Norway", "China", "Germany", "", "Japan" }, 84 /* display variant (English) */ 85 { "", "", "", "", "NY", "", "", "", "" }, 86 /* display name (English) */ 87 { "English (United States)", "French (France)", "Catalan (Spain)", 88 "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese (Simplified, China)", 89 "German (Germany, Sort Order=Phonebook Sort Order)", "Spanish (Sort Order=Traditional Sort Order)", "Japanese (Japan, Calendar=Japanese Calendar)" }, 90 91 /* display language (French) */ 92 { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" }, 93 /* display script code (French) */ 94 { "", "", "", "", "", "sinogrammes simplifi\\u00e9s", "", "", "" }, 95 /* display country (French) */ 96 { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine", "Allemagne", "", "Japon" }, 97 /* display variant (French) */ 98 { "", "", "", "", "NY", "", "", "", "" }, 99 /* display name (French) */ 100 { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)", 101 "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois (simplifi\\u00e9, Chine)", 102 "allemand (Allemagne, ordre de tri=Ordre de l\\u2019annuaire)", "espagnol (ordre de tri=Ordre traditionnel)", "japonais (Japon, calendrier=calendrier japonais)" }, 103 104 /* display language (Catalan) */ 105 { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E8s", "alemany", "espanyol", "japon\\u00E8s" }, 106 /* display script code (Catalan) */ 107 { "", "", "", "", "", "han simplificat", "", "", "" }, 108 /* display country (Catalan) */ 109 { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina", "Alemanya", "", "Jap\\u00F3" }, 110 /* display variant (Catalan) */ 111 { "", "", "", "", "NY", "", "", "", "" }, 112 /* display name (Catalan) */ 113 { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)", 114 "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E8s (simplificat, Xina)", 115 "alemany (Alemanya, ordenaci\\u00F3=ordre de la guia telef\\u00F2nica)", "espanyol (ordenaci\\u00F3=ordre tradicional)", "japon\\u00E8s (Jap\\u00F3, calendari=calendari japon\\u00e8s)" }, 116 117 /* display language (Greek) */ 118 { 119 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac", 120 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac", 121 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac", 122 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac", 123 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac", 124 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC", 125 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC", 126 "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC", 127 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC" 128 }, 129 /* display script code (Greek) */ 130 131 { "", "", "", "", "", "\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf \\u03a7\\u03b1\\u03bd", "", "", "" }, 132 /* display country (Greek) */ 133 { 134 "\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2", 135 "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1", 136 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1", 137 "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1", 138 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1", 139 "\\u039A\\u03AF\\u03BD\\u03B1", 140 "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1", 141 "", 142 "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1" 143 }, 144 /* display variant (Greek) */ 145 { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */ 146 /* display name (Greek) */ 147 { 148 "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03BD\\u03C9\\u03BC\\u03AD\\u03BD\\u03B5\\u03C2 \\u03A0\\u03BF\\u03BB\\u03B9\\u03C4\\u03B5\\u03AF\\u03B5\\u03C2)", 149 "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)", 150 "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)", 151 "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)", 152 "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)", 153 "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)", 154 "\\u0393\\u03b5\\u03c1\\u03bc\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0393\\u03b5\\u03c1\\u03bc\\u03b1\\u03bd\\u03af\\u03b1, \\u03a3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2=\\u03a3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2 \\u03c4\\u03b7\\u03bb\\u03b5\\u03c6\\u03c9\\u03bd\\u03b9\\u03ba\\u03bf\\u03cd \\u03ba\\u03b1\\u03c4\\u03b1\\u03bb\\u03cc\\u03b3\\u03bf\\u03c5)", 155 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u03a3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2=\\u03a0\\u03b1\\u03c1\\u03b1\\u03b4\\u03bf\\u03c3\\u03b9\\u03b1\\u03ba\\u03ae \\u03c3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2)", 156 "\\u0399\\u03b1\\u03c0\\u03c9\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03b1\\u03c0\\u03c9\\u03bd\\u03af\\u03b1, \\u0397\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf=\\u0399\\u03b1\\u03c0\\u03c9\\u03bd\\u03b9\\u03ba\\u03cc \\u03b7\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf)" 157 } 158 }; 159 160 static UChar*** dataTable=0; 161 enum { 162 ENGLISH = 0, 163 FRENCH = 1, 164 CATALAN = 2, 165 GREEK = 3, 166 NORWEGIAN = 4 167 }; 168 169 enum { 170 LANG = 0, 171 SCRIPT = 1, 172 CTRY = 2, 173 VAR = 3, 174 NAME = 4, 175 LANG3 = 5, 176 CTRY3 = 6, 177 LCID = 7, 178 DLANG_EN = 8, 179 DSCRIPT_EN = 9, 180 DCTRY_EN = 10, 181 DVAR_EN = 11, 182 DNAME_EN = 12, 183 DLANG_FR = 13, 184 DSCRIPT_FR = 14, 185 DCTRY_FR = 15, 186 DVAR_FR = 16, 187 DNAME_FR = 17, 188 DLANG_CA = 18, 189 DSCRIPT_CA = 19, 190 DCTRY_CA = 20, 191 DVAR_CA = 21, 192 DNAME_CA = 22, 193 DLANG_EL = 23, 194 DSCRIPT_EL = 24, 195 DCTRY_EL = 25, 196 DVAR_EL = 26, 197 DNAME_EL = 27 198 }; 199 200 #define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name) 201 202 void addLocaleTest(TestNode** root); 203 204 void addLocaleTest(TestNode** root) 205 { 206 TESTCASE(TestObsoleteNames); /* srl- move */ 207 TESTCASE(TestBasicGetters); 208 TESTCASE(TestNullDefault); 209 TESTCASE(TestPrefixes); 210 TESTCASE(TestSimpleResourceInfo); 211 TESTCASE(TestDisplayNames); 212 TESTCASE(TestGetAvailableLocales); 213 TESTCASE(TestDataDirectory); 214 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION 215 TESTCASE(TestISOFunctions); 216 #endif 217 TESTCASE(TestISO3Fallback); 218 TESTCASE(TestUninstalledISO3Names); 219 TESTCASE(TestSimpleDisplayNames); 220 TESTCASE(TestVariantParsing); 221 TESTCASE(TestKeywordVariants); 222 TESTCASE(TestKeywordVariantParsing); 223 TESTCASE(TestCanonicalization); 224 TESTCASE(TestKeywordSet); 225 TESTCASE(TestKeywordSetError); 226 TESTCASE(TestDisplayKeywords); 227 TESTCASE(TestDisplayKeywordValues); 228 TESTCASE(TestGetBaseName); 229 #if !UCONFIG_NO_FILE_IO 230 TESTCASE(TestGetLocale); 231 #endif 232 TESTCASE(TestDisplayNameWarning); 233 TESTCASE(TestNonexistentLanguageExemplars); 234 TESTCASE(TestLocDataErrorCodeChaining); 235 TESTCASE(TestLanguageExemplarsFallbacks); 236 TESTCASE(TestCalendar); 237 TESTCASE(TestDateFormat); 238 TESTCASE(TestCollation); 239 TESTCASE(TestULocale); 240 TESTCASE(TestUResourceBundle); 241 TESTCASE(TestDisplayName); 242 TESTCASE(TestAcceptLanguage); 243 TESTCASE(TestGetLocaleForLCID); 244 TESTCASE(TestOrientation); 245 TESTCASE(TestLikelySubtags); 246 TESTCASE(TestToLanguageTag); 247 TESTCASE(TestForLanguageTag); 248 TESTCASE(TestTrailingNull); 249 TESTCASE(TestUnicodeDefines); 250 TESTCASE(TestEnglishExemplarCharacters); 251 TESTCASE(TestDisplayNameBrackets); 252 TESTCASE(TestIsRightToLeft); 253 TESTCASE(TestToUnicodeLocaleKey); 254 TESTCASE(TestToLegacyKey); 255 TESTCASE(TestToUnicodeLocaleType); 256 TESTCASE(TestToLegacyType); 257 } 258 259 260 /* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */ 261 static void TestBasicGetters() { 262 int32_t i; 263 int32_t cap; 264 UErrorCode status = U_ZERO_ERROR; 265 char *testLocale = 0; 266 char *temp = 0, *name = 0; 267 log_verbose("Testing Basic Getters\n"); 268 for (i = 0; i < LOCALE_SIZE; i++) { 269 testLocale=(char*)malloc(sizeof(char) * (strlen(rawData2[NAME][i])+1)); 270 strcpy(testLocale,rawData2[NAME][i]); 271 272 log_verbose("Testing %s .....\n", testLocale); 273 cap=uloc_getLanguage(testLocale, NULL, 0, &status); 274 if(status==U_BUFFER_OVERFLOW_ERROR){ 275 status=U_ZERO_ERROR; 276 temp=(char*)malloc(sizeof(char) * (cap+1)); 277 uloc_getLanguage(testLocale, temp, cap+1, &status); 278 } 279 if(U_FAILURE(status)){ 280 log_err("ERROR: in uloc_getLanguage %s\n", myErrorName(status)); 281 } 282 if (0 !=strcmp(temp,rawData2[LANG][i])) { 283 log_err(" Language code mismatch: %s versus %s\n", temp, rawData2[LANG][i]); 284 } 285 286 287 cap=uloc_getCountry(testLocale, temp, cap, &status); 288 if(status==U_BUFFER_OVERFLOW_ERROR){ 289 status=U_ZERO_ERROR; 290 temp=(char*)realloc(temp, sizeof(char) * (cap+1)); 291 uloc_getCountry(testLocale, temp, cap+1, &status); 292 } 293 if(U_FAILURE(status)){ 294 log_err("ERROR: in uloc_getCountry %s\n", myErrorName(status)); 295 } 296 if (0 != strcmp(temp, rawData2[CTRY][i])) { 297 log_err(" Country code mismatch: %s versus %s\n", temp, rawData2[CTRY][i]); 298 299 } 300 301 cap=uloc_getVariant(testLocale, temp, cap, &status); 302 if(status==U_BUFFER_OVERFLOW_ERROR){ 303 status=U_ZERO_ERROR; 304 temp=(char*)realloc(temp, sizeof(char) * (cap+1)); 305 uloc_getVariant(testLocale, temp, cap+1, &status); 306 } 307 if(U_FAILURE(status)){ 308 log_err("ERROR: in uloc_getVariant %s\n", myErrorName(status)); 309 } 310 if (0 != strcmp(temp, rawData2[VAR][i])) { 311 log_err("Variant code mismatch: %s versus %s\n", temp, rawData2[VAR][i]); 312 } 313 314 cap=uloc_getName(testLocale, NULL, 0, &status); 315 if(status==U_BUFFER_OVERFLOW_ERROR){ 316 status=U_ZERO_ERROR; 317 name=(char*)malloc(sizeof(char) * (cap+1)); 318 uloc_getName(testLocale, name, cap+1, &status); 319 } else if(status==U_ZERO_ERROR) { 320 log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale); 321 } 322 if(U_FAILURE(status)){ 323 log_err("ERROR: in uloc_getName %s\n", myErrorName(status)); 324 } 325 if (0 != strcmp(name, rawData2[NAME][i])){ 326 log_err(" Mismatch in getName: %s versus %s\n", name, rawData2[NAME][i]); 327 } 328 329 free(temp); 330 free(name); 331 332 free(testLocale); 333 } 334 } 335 336 static void TestNullDefault() { 337 UErrorCode status = U_ZERO_ERROR; 338 char original[ULOC_FULLNAME_CAPACITY]; 339 340 uprv_strcpy(original, uloc_getDefault()); 341 uloc_setDefault("qq_BLA", &status); 342 if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) { 343 log_err(" Mismatch in uloc_setDefault: qq_BLA versus %s\n", uloc_getDefault()); 344 } 345 uloc_setDefault(NULL, &status); 346 if (uprv_strcmp(uloc_getDefault(), original) != 0) { 347 log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n"); 348 } 349 350 { 351 /* Test that set & get of default locale work, and that 352 * default locales are cached and reused, and not overwritten. 353 */ 354 const char *n_en_US; 355 const char *n_fr_FR; 356 const char *n2_en_US; 357 358 status = U_ZERO_ERROR; 359 uloc_setDefault("en_US", &status); 360 n_en_US = uloc_getDefault(); 361 if (strcmp(n_en_US, "en_US") != 0) { 362 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US); 363 } 364 365 uloc_setDefault("fr_FR", &status); 366 n_fr_FR = uloc_getDefault(); 367 if (strcmp(n_en_US, "en_US") != 0) { 368 log_err("uloc_setDefault altered previously default string." 369 "Expected \"en_US\", got \"%s\"\n", n_en_US); 370 } 371 if (strcmp(n_fr_FR, "fr_FR") != 0) { 372 log_err("Wrong result from uloc_getDefault(). Expected \"fr_FR\", got %s\n", n_fr_FR); 373 } 374 375 uloc_setDefault("en_US", &status); 376 n2_en_US = uloc_getDefault(); 377 if (strcmp(n2_en_US, "en_US") != 0) { 378 log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US); 379 } 380 if (n2_en_US != n_en_US) { 381 log_err("Default locale cache failed to reuse en_US locale.\n"); 382 } 383 384 if (U_FAILURE(status)) { 385 log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status)); 386 } 387 388 } 389 390 } 391 /* Test the i- and x- and @ and . functionality 392 */ 393 394 #define PREFIXBUFSIZ 128 395 396 static void TestPrefixes() { 397 int row = 0; 398 int n; 399 const char *loc, *expected; 400 401 static const char * const testData[][7] = 402 { 403 /* NULL canonicalize() column means "expect same as getName()" */ 404 {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL}, 405 {"en", "", "GB", "", "en-gb", "en_GB", NULL}, 406 {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL}, 407 {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL}, 408 {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL}, 409 {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL}, 410 411 {"zh", "Hans", "", "PINYIN", "zh-Hans-pinyin", "zh_Hans__PINYIN", "zh_Hans@collation=pinyin"}, 412 {"hy", "", "", "AREVMDA", "hy_AREVMDA", "hy__AREVMDA", NULL}, 413 414 {"de", "", "", "1901", "de-1901", "de__1901", NULL}, 415 {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"}, 416 {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"}, 417 {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */ 418 {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"}, 419 {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"}, 420 {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"}, 421 {"no", "", "NO", "", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"}, 422 {"no", "", "", "NY", "no__ny", "no__NY", NULL}, 423 {"no", "", "", "", "no@ny", "no@ny", "no__NY"}, 424 {"el", "Latn", "", "", "el-latn", "el_Latn", NULL}, 425 {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL}, 426 {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", "zh_Hant_TW@collation=stroke"}, 427 {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL}, 428 {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL}, 429 {"ab", "Cdef", "GH", "IJ", "ab_cdef_gh_ij", "ab_Cdef_GH_IJ", NULL}, /* total garbage */ 430 431 {NULL,NULL,NULL,NULL,NULL,NULL,NULL} 432 }; 433 434 static const char * const testTitles[] = { 435 "uloc_getLanguage()", 436 "uloc_getScript()", 437 "uloc_getCountry()", 438 "uloc_getVariant()", 439 "name", 440 "uloc_getName()", 441 "uloc_canonicalize()" 442 }; 443 444 char buf[PREFIXBUFSIZ]; 445 int32_t len; 446 UErrorCode err; 447 448 449 for(row=0;testData[row][0] != NULL;row++) { 450 loc = testData[row][NAME]; 451 log_verbose("Test #%d: %s\n", row, loc); 452 453 err = U_ZERO_ERROR; 454 len=0; 455 buf[0]=0; 456 for(n=0;n<=(NAME+2);n++) { 457 if(n==NAME) continue; 458 459 for(len=0;len<PREFIXBUFSIZ;len++) { 460 buf[len] = '%'; /* Set a tripwire.. */ 461 } 462 len = 0; 463 464 switch(n) { 465 case LANG: 466 len = uloc_getLanguage(loc, buf, PREFIXBUFSIZ, &err); 467 break; 468 469 case SCRIPT: 470 len = uloc_getScript(loc, buf, PREFIXBUFSIZ, &err); 471 break; 472 473 case CTRY: 474 len = uloc_getCountry(loc, buf, PREFIXBUFSIZ, &err); 475 break; 476 477 case VAR: 478 len = uloc_getVariant(loc, buf, PREFIXBUFSIZ, &err); 479 break; 480 481 case NAME+1: 482 len = uloc_getName(loc, buf, PREFIXBUFSIZ, &err); 483 break; 484 485 case NAME+2: 486 len = uloc_canonicalize(loc, buf, PREFIXBUFSIZ, &err); 487 break; 488 489 default: 490 strcpy(buf, "**??"); 491 len=4; 492 } 493 494 if(U_FAILURE(err)) { 495 log_err("#%d: %s on %s: err %s\n", 496 row, testTitles[n], loc, u_errorName(err)); 497 } else { 498 log_verbose("#%d: %s on %s: -> [%s] (length %d)\n", 499 row, testTitles[n], loc, buf, len); 500 501 if(len != (int32_t)strlen(buf)) { 502 log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n", 503 row, testTitles[n], loc, buf, len, strlen(buf)+1); 504 505 } 506 507 /* see if they smashed something */ 508 if(buf[len+1] != '%') { 509 log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n", 510 row, testTitles[n], loc, buf, buf[len+1]); 511 } 512 513 expected = testData[row][n]; 514 if (expected == NULL && n == (NAME+2)) { 515 /* NULL expected canonicalize() means "expect same as getName()" */ 516 expected = testData[row][NAME+1]; 517 } 518 if(strcmp(buf, expected)) { 519 log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n", 520 row, testTitles[n], loc, buf, expected); 521 522 } 523 } 524 } 525 } 526 } 527 528 529 /* testing uloc_getISO3Language(), uloc_getISO3Country(), */ 530 static void TestSimpleResourceInfo() { 531 int32_t i; 532 char* testLocale = 0; 533 UChar* expected = 0; 534 535 const char* temp; 536 char temp2[20]; 537 testLocale=(char*)malloc(sizeof(char) * 1); 538 expected=(UChar*)malloc(sizeof(UChar) * 1); 539 540 setUpDataTable(); 541 log_verbose("Testing getISO3Language and getISO3Country\n"); 542 for (i = 0; i < LOCALE_SIZE; i++) { 543 544 testLocale=(char*)realloc(testLocale, sizeof(char) * (u_strlen(dataTable[NAME][i])+1)); 545 u_austrcpy(testLocale, dataTable[NAME][i]); 546 547 log_verbose("Testing %s ......\n", testLocale); 548 549 temp=uloc_getISO3Language(testLocale); 550 expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1)); 551 u_uastrcpy(expected,temp); 552 if (0 != u_strcmp(expected, dataTable[LANG3][i])) { 553 log_err(" ISO-3 language code mismatch: %s versus %s\n", austrdup(expected), 554 austrdup(dataTable[LANG3][i])); 555 } 556 557 temp=uloc_getISO3Country(testLocale); 558 expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1)); 559 u_uastrcpy(expected,temp); 560 if (0 != u_strcmp(expected, dataTable[CTRY3][i])) { 561 log_err(" ISO-3 Country code mismatch: %s versus %s\n", austrdup(expected), 562 austrdup(dataTable[CTRY3][i])); 563 } 564 sprintf(temp2, "%x", (int)uloc_getLCID(testLocale)); 565 if (strcmp(temp2, rawData2[LCID][i]) != 0) { 566 log_err("LCID mismatch: %s versus %s\n", temp2 , rawData2[LCID][i]); 567 } 568 } 569 570 free(expected); 571 free(testLocale); 572 cleanUpDataTable(); 573 } 574 575 /* if len < 0, we convert until we hit UChar 0x0000, which is not output. will add trailing null 576 * if there's room but won't be included in result. result < 0 indicates an error. 577 * Returns the number of chars written (not those that would be written if there's enough room.*/ 578 static int32_t UCharsToEscapedAscii(const UChar* utext, int32_t len, char* resultChars, int32_t buflen) { 579 static const struct { 580 char escapedChar; 581 UChar sourceVal; 582 } ESCAPE_MAP[] = { 583 /*a*/ {'a', 0x07}, 584 /*b*/ {'b', 0x08}, 585 /*e*/ {'e', 0x1b}, 586 /*f*/ {'f', 0x0c}, 587 /*n*/ {'n', 0x0a}, 588 /*r*/ {'r', 0x0d}, 589 /*t*/ {'t', 0x09}, 590 /*v*/ {'v', 0x0b} 591 }; 592 static const int32_t ESCAPE_MAP_LENGTH = sizeof(ESCAPE_MAP)/sizeof(ESCAPE_MAP[0]); 593 static const char HEX_DIGITS[] = { 594 '0', '1', '2', '3', '4', '5', '6', '7', 595 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' 596 }; 597 int32_t i, j; 598 int32_t resultLen = 0; 599 const int32_t limit = len<0 ? buflen : len; /* buflen is long enough to hit the buffer limit */ 600 const int32_t escapeLimit1 = buflen-2; 601 const int32_t escapeLimit2 = buflen-6; 602 UChar uc; 603 604 if(utext==NULL || resultChars==NULL || buflen<0) { 605 return -1; 606 } 607 608 for(i=0;i<limit && resultLen<buflen;++i) { 609 uc=utext[i]; 610 if(len<0 && uc==0) { 611 break; 612 } 613 if(uc<0x20) { 614 for(j=0;j<ESCAPE_MAP_LENGTH && uc!=ESCAPE_MAP[j].sourceVal;j++) { 615 } 616 if(j<ESCAPE_MAP_LENGTH) { 617 if(resultLen>escapeLimit1) { 618 break; 619 } 620 resultChars[resultLen++]='\\'; 621 resultChars[resultLen++]=ESCAPE_MAP[j].escapedChar; 622 continue; 623 } 624 } else if(uc<0x7f) { 625 u_austrncpy(resultChars + resultLen, &uc, 1); 626 resultLen++; 627 continue; 628 } 629 630 if(resultLen>escapeLimit2) { 631 break; 632 } 633 634 /* have to escape the uchar */ 635 resultChars[resultLen++]='\\'; 636 resultChars[resultLen++]='u'; 637 resultChars[resultLen++]=HEX_DIGITS[(uc>>12)&0xff]; 638 resultChars[resultLen++]=HEX_DIGITS[(uc>>8)&0xff]; 639 resultChars[resultLen++]=HEX_DIGITS[(uc>>4)&0xff]; 640 resultChars[resultLen++]=HEX_DIGITS[uc&0xff]; 641 } 642 643 if(resultLen<buflen) { 644 resultChars[resultLen] = 0; 645 } 646 647 return resultLen; 648 } 649 650 /* 651 * Jitterbug 2439 -- markus 20030425 652 * 653 * The lookup of display names must not fall back through the default 654 * locale because that yields useless results. 655 */ 656 static void TestDisplayNames() 657 { 658 UChar buffer[100]; 659 UErrorCode errorCode=U_ZERO_ERROR; 660 int32_t length; 661 log_verbose("Testing getDisplayName for different locales\n"); 662 663 log_verbose(" In locale = en_US...\n"); 664 doTestDisplayNames("en_US", DLANG_EN); 665 log_verbose(" In locale = fr_FR....\n"); 666 doTestDisplayNames("fr_FR", DLANG_FR); 667 log_verbose(" In locale = ca_ES...\n"); 668 doTestDisplayNames("ca_ES", DLANG_CA); 669 log_verbose(" In locale = gr_EL..\n"); 670 doTestDisplayNames("el_GR", DLANG_EL); 671 672 /* test that the default locale has a display name for its own language */ 673 errorCode=U_ZERO_ERROR; 674 length=uloc_getDisplayLanguage(NULL, NULL, buffer, UPRV_LENGTHOF(buffer), &errorCode); 675 if(U_FAILURE(errorCode) || (length<=3 && buffer[0]<=0x7f)) { 676 /* check <=3 to reject getting the language code as a display name */ 677 log_data_err("unable to get a display string for the language of the default locale - %s (Are you missing data?)\n", u_errorName(errorCode)); 678 } 679 680 /* test that we get the language code itself for an unknown language, and a default warning */ 681 errorCode=U_ZERO_ERROR; 682 length=uloc_getDisplayLanguage("qq", "rr", buffer, UPRV_LENGTHOF(buffer), &errorCode); 683 if(errorCode!=U_USING_DEFAULT_WARNING || length!=2 || buffer[0]!=0x71 || buffer[1]!=0x71) { 684 log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode)); 685 } 686 687 /* test that we get a default warning for a display name where one component is unknown (4255) */ 688 errorCode=U_ZERO_ERROR; 689 length=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer, UPRV_LENGTHOF(buffer), &errorCode); 690 if(errorCode!=U_USING_DEFAULT_WARNING) { 691 log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode)); 692 } 693 694 { 695 int32_t i; 696 static const char *aLocale = "es@collation=traditional;calendar=japanese"; 697 static const char *testL[] = { "en_US", 698 "fr_FR", 699 "ca_ES", 700 "el_GR" }; 701 static const char *expect[] = { "Spanish (Calendar=Japanese Calendar, Sort Order=Traditional Sort Order)", /* note sorted order of keywords */ 702 "espagnol (calendrier=calendrier japonais, ordre de tri=Ordre traditionnel)", 703 "espanyol (calendari=calendari japon\\u00e8s, ordenaci\\u00f3=ordre tradicional)", 704 "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0397\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf=\\u0399\\u03b1\\u03c0\\u03c9\\u03bd\\u03b9\\u03ba\\u03cc \\u03b7\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf, \\u03a3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2=\\u03a0\\u03b1\\u03c1\\u03b1\\u03b4\\u03bf\\u03c3\\u03b9\\u03b1\\u03ba\\u03ae \\u03c3\\u03b5\\u03b9\\u03c1\\u03ac \\u03c4\\u03b1\\u03be\\u03b9\\u03bd\\u03cc\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2)" }; 705 UChar *expectBuffer; 706 707 for(i=0;i<UPRV_LENGTHOF(testL);i++) { 708 errorCode = U_ZERO_ERROR; 709 uloc_getDisplayName(aLocale, testL[i], buffer, UPRV_LENGTHOF(buffer), &errorCode); 710 if(U_FAILURE(errorCode)) { 711 log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale, testL[i], u_errorName(errorCode)); 712 } else { 713 expectBuffer = CharsToUChars(expect[i]); 714 if(u_strcmp(buffer,expectBuffer)) { 715 log_data_err("FAIL in uloc_getDisplayName(%s,%s,..) expected '%s' got '%s' (Are you missing data?)\n", aLocale, testL[i], expect[i], austrdup(buffer)); 716 } else { 717 log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale, testL[i], expect[i]); 718 } 719 free(expectBuffer); 720 } 721 } 722 } 723 724 /* test that we properly preflight and return data when there's a non-default pattern, 725 see ticket #8262. */ 726 { 727 int32_t i; 728 static const char *locale="az_Cyrl"; 729 static const char *displayLocale="ja"; 730 static const char *expectedChars = 731 "\\u30a2\\u30bc\\u30eb\\u30d0\\u30a4\\u30b8\\u30e3\\u30f3\\u8a9e " 732 "(\\u30ad\\u30ea\\u30eb\\u6587\\u5b57)"; 733 UErrorCode ec=U_ZERO_ERROR; 734 UChar result[256]; 735 int32_t len; 736 int32_t preflightLen=uloc_getDisplayName(locale, displayLocale, NULL, 0, &ec); 737 /* inconvenient semantics when preflighting, this condition is expected... */ 738 if(ec==U_BUFFER_OVERFLOW_ERROR) { 739 ec=U_ZERO_ERROR; 740 } 741 len=uloc_getDisplayName(locale, displayLocale, result, UPRV_LENGTHOF(result), &ec); 742 if(U_FAILURE(ec)) { 743 log_err("uloc_getDisplayName(%s, %s...) returned error: %s", 744 locale, displayLocale, u_errorName(ec)); 745 } else { 746 UChar *expected=CharsToUChars(expectedChars); 747 int32_t expectedLen=u_strlen(expected); 748 749 if(len!=expectedLen) { 750 log_data_err("uloc_getDisplayName(%s, %s...) returned string of length %d, expected length %d", 751 locale, displayLocale, len, expectedLen); 752 } else if(preflightLen!=expectedLen) { 753 log_err("uloc_getDisplayName(%s, %s...) returned preflight length %d, expected length %d", 754 locale, displayLocale, preflightLen, expectedLen); 755 } else if(u_strncmp(result, expected, len)) { 756 int32_t cap=len*6+1; /* worst case + space for trailing null */ 757 char* resultChars=(char*)malloc(cap); 758 int32_t resultCharsLen=UCharsToEscapedAscii(result, len, resultChars, cap); 759 if(resultCharsLen<0 || resultCharsLen<cap-1) { 760 log_err("uloc_getDisplayName(%s, %s...) mismatch", locale, displayLocale); 761 } else { 762 log_err("uloc_getDisplayName(%s, %s...) returned '%s' but expected '%s'", 763 locale, displayLocale, resultChars, expectedChars); 764 } 765 free(resultChars); 766 resultChars=NULL; 767 } else { 768 /* test all buffer sizes */ 769 for(i=len+1;i>=0;--i) { 770 len=uloc_getDisplayName(locale, displayLocale, result, i, &ec); 771 if(ec==U_BUFFER_OVERFLOW_ERROR) { 772 ec=U_ZERO_ERROR; 773 } 774 if(U_FAILURE(ec)) { 775 log_err("using buffer of length %d returned error %s", i, u_errorName(ec)); 776 break; 777 } 778 if(len!=expectedLen) { 779 log_err("with buffer of length %d, expected length %d but got %d", i, expectedLen, len); 780 break; 781 } 782 /* There's no guarantee about what's in the buffer if we've overflowed, in particular, 783 * we don't know that it's been filled, so no point in checking. */ 784 } 785 } 786 787 free(expected); 788 } 789 } 790 } 791 792 793 /* test for uloc_getAvialable() and uloc_countAvilable()*/ 794 static void TestGetAvailableLocales() 795 { 796 797 const char *locList; 798 int32_t locCount,i; 799 800 log_verbose("Testing the no of avialable locales\n"); 801 locCount=uloc_countAvailable(); 802 if (locCount == 0) 803 log_data_err("countAvailable() returned an empty list!\n"); 804 805 /* use something sensible w/o hardcoding the count */ 806 else if(locCount < 0){ 807 log_data_err("countAvailable() returned a wrong value!= %d\n", locCount); 808 } 809 else{ 810 log_info("Number of locales returned = %d\n", locCount); 811 } 812 for(i=0;i<locCount;i++){ 813 locList=uloc_getAvailable(i); 814 815 log_verbose(" %s\n", locList); 816 } 817 } 818 819 /* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */ 820 static void TestDataDirectory() 821 { 822 823 char oldDirectory[512]; 824 const char *temp,*testValue1,*testValue2,*testValue3; 825 const char path[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING; /*give the required path */ 826 827 log_verbose("Testing getDataDirectory()\n"); 828 temp = u_getDataDirectory(); 829 strcpy(oldDirectory, temp); 830 831 testValue1=uloc_getISO3Language("en_US"); 832 log_verbose("first fetch of language retrieved %s\n", testValue1); 833 834 if (0 != strcmp(testValue1,"eng")){ 835 log_err("Initial check of ISO3 language failed: expected \"eng\", got %s \n", testValue1); 836 } 837 838 /*defining the path for DataDirectory */ 839 log_verbose("Testing setDataDirectory\n"); 840 u_setDataDirectory( path ); 841 if(strcmp(path, u_getDataDirectory())==0) 842 log_verbose("setDataDirectory working fine\n"); 843 else 844 log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path); 845 846 testValue2=uloc_getISO3Language("en_US"); 847 log_verbose("second fetch of language retrieved %s \n", testValue2); 848 849 u_setDataDirectory(oldDirectory); 850 testValue3=uloc_getISO3Language("en_US"); 851 log_verbose("third fetch of language retrieved %s \n", testValue3); 852 853 if (0 != strcmp(testValue3,"eng")) { 854 log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s \" \n", testValue3); 855 } 856 } 857 858 859 860 /*=========================================================== */ 861 862 static UChar _NUL=0; 863 864 static void doTestDisplayNames(const char* displayLocale, int32_t compareIndex) 865 { 866 UErrorCode status = U_ZERO_ERROR; 867 int32_t i; 868 int32_t maxresultsize; 869 870 const char *testLocale; 871 872 873 UChar *testLang = 0; 874 UChar *testScript = 0; 875 UChar *testCtry = 0; 876 UChar *testVar = 0; 877 UChar *testName = 0; 878 879 880 UChar* expectedLang = 0; 881 UChar* expectedScript = 0; 882 UChar* expectedCtry = 0; 883 UChar* expectedVar = 0; 884 UChar* expectedName = 0; 885 886 setUpDataTable(); 887 888 for(i=0;i<LOCALE_SIZE; ++i) 889 { 890 testLocale=rawData2[NAME][i]; 891 892 log_verbose("Testing..... %s\n", testLocale); 893 894 maxresultsize=0; 895 maxresultsize=uloc_getDisplayLanguage(testLocale, displayLocale, NULL, maxresultsize, &status); 896 if(status==U_BUFFER_OVERFLOW_ERROR) 897 { 898 status=U_ZERO_ERROR; 899 testLang=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); 900 uloc_getDisplayLanguage(testLocale, displayLocale, testLang, maxresultsize + 1, &status); 901 } 902 else 903 { 904 testLang=&_NUL; 905 } 906 if(U_FAILURE(status)){ 907 log_err("Error in getDisplayLanguage() %s\n", myErrorName(status)); 908 } 909 910 maxresultsize=0; 911 maxresultsize=uloc_getDisplayScript(testLocale, displayLocale, NULL, maxresultsize, &status); 912 if(status==U_BUFFER_OVERFLOW_ERROR) 913 { 914 status=U_ZERO_ERROR; 915 testScript=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); 916 uloc_getDisplayScript(testLocale, displayLocale, testScript, maxresultsize + 1, &status); 917 } 918 else 919 { 920 testScript=&_NUL; 921 } 922 if(U_FAILURE(status)){ 923 log_err("Error in getDisplayScript() %s\n", myErrorName(status)); 924 } 925 926 maxresultsize=0; 927 maxresultsize=uloc_getDisplayCountry(testLocale, displayLocale, NULL, maxresultsize, &status); 928 if(status==U_BUFFER_OVERFLOW_ERROR) 929 { 930 status=U_ZERO_ERROR; 931 testCtry=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); 932 uloc_getDisplayCountry(testLocale, displayLocale, testCtry, maxresultsize + 1, &status); 933 } 934 else 935 { 936 testCtry=&_NUL; 937 } 938 if(U_FAILURE(status)){ 939 log_err("Error in getDisplayCountry() %s\n", myErrorName(status)); 940 } 941 942 maxresultsize=0; 943 maxresultsize=uloc_getDisplayVariant(testLocale, displayLocale, NULL, maxresultsize, &status); 944 if(status==U_BUFFER_OVERFLOW_ERROR) 945 { 946 status=U_ZERO_ERROR; 947 testVar=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); 948 uloc_getDisplayVariant(testLocale, displayLocale, testVar, maxresultsize + 1, &status); 949 } 950 else 951 { 952 testVar=&_NUL; 953 } 954 if(U_FAILURE(status)){ 955 log_err("Error in getDisplayVariant() %s\n", myErrorName(status)); 956 } 957 958 maxresultsize=0; 959 maxresultsize=uloc_getDisplayName(testLocale, displayLocale, NULL, maxresultsize, &status); 960 if(status==U_BUFFER_OVERFLOW_ERROR) 961 { 962 status=U_ZERO_ERROR; 963 testName=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); 964 uloc_getDisplayName(testLocale, displayLocale, testName, maxresultsize + 1, &status); 965 } 966 else 967 { 968 testName=&_NUL; 969 } 970 if(U_FAILURE(status)){ 971 log_err("Error in getDisplayName() %s\n", myErrorName(status)); 972 } 973 974 expectedLang=dataTable[compareIndex][i]; 975 if(u_strlen(expectedLang)== 0) 976 expectedLang=dataTable[DLANG_EN][i]; 977 978 expectedScript=dataTable[compareIndex + 1][i]; 979 if(u_strlen(expectedScript)== 0) 980 expectedScript=dataTable[DSCRIPT_EN][i]; 981 982 expectedCtry=dataTable[compareIndex + 2][i]; 983 if(u_strlen(expectedCtry)== 0) 984 expectedCtry=dataTable[DCTRY_EN][i]; 985 986 expectedVar=dataTable[compareIndex + 3][i]; 987 if(u_strlen(expectedVar)== 0) 988 expectedVar=dataTable[DVAR_EN][i]; 989 990 expectedName=dataTable[compareIndex + 4][i]; 991 if(u_strlen(expectedName) == 0) 992 expectedName=dataTable[DNAME_EN][i]; 993 994 if (0 !=u_strcmp(testLang,expectedLang)) { 995 log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testLang), austrdup(expectedLang), displayLocale); 996 } 997 998 if (0 != u_strcmp(testScript,expectedScript)) { 999 log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testScript), austrdup(expectedScript), displayLocale); 1000 } 1001 1002 if (0 != u_strcmp(testCtry,expectedCtry)) { 1003 log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testCtry), austrdup(expectedCtry), displayLocale); 1004 } 1005 1006 if (0 != u_strcmp(testVar,expectedVar)) { 1007 log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testVar), austrdup(expectedVar), displayLocale); 1008 } 1009 1010 if(0 != u_strcmp(testName, expectedName)) { 1011 log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s (Are you missing data?)\n", austrdup(testName), austrdup(expectedName), displayLocale); 1012 } 1013 1014 if(testName!=&_NUL) { 1015 free(testName); 1016 } 1017 if(testLang!=&_NUL) { 1018 free(testLang); 1019 } 1020 if(testScript!=&_NUL) { 1021 free(testScript); 1022 } 1023 if(testCtry!=&_NUL) { 1024 free(testCtry); 1025 } 1026 if(testVar!=&_NUL) { 1027 free(testVar); 1028 } 1029 } 1030 cleanUpDataTable(); 1031 } 1032 1033 /*------------------------------ 1034 * TestDisplayNameBrackets 1035 */ 1036 1037 typedef struct { 1038 const char * displayLocale; 1039 const char * namedRegion; 1040 const char * namedLocale; 1041 const char * regionName; 1042 const char * localeName; 1043 } DisplayNameBracketsItem; 1044 1045 static const DisplayNameBracketsItem displayNameBracketsItems[] = { 1046 { "en", "CC", "en_CC", "Cocos (Keeling) Islands", "English (Cocos [Keeling] Islands)" }, 1047 { "en", "MM", "my_MM", "Myanmar (Burma)", "Burmese (Myanmar [Burma])" }, 1048 { "en", "MM", "my_Mymr_MM", "Myanmar (Burma)", "Burmese (Myanmar, Myanmar [Burma])" }, 1049 { "zh", "CC", "en_CC", "\\u79D1\\u79D1\\u65AF\\uFF08\\u57FA\\u6797\\uFF09\\u7FA4\\u5C9B", "\\u82F1\\u6587\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09" }, 1050 { "zh", "CG", "fr_CG", "\\u521A\\u679C\\uFF08\\u5E03\\uFF09", "\\u6CD5\\u6587\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09" }, 1051 { NULL, NULL, NULL, NULL, NULL } 1052 }; 1053 1054 enum { kDisplayNameBracketsMax = 128 }; 1055 1056 static void TestDisplayNameBrackets() 1057 { 1058 const DisplayNameBracketsItem * itemPtr = displayNameBracketsItems; 1059 for (; itemPtr->displayLocale != NULL; itemPtr++) { 1060 ULocaleDisplayNames * uldn; 1061 UErrorCode status; 1062 UChar expectRegionName[kDisplayNameBracketsMax]; 1063 UChar expectLocaleName[kDisplayNameBracketsMax]; 1064 UChar getName[kDisplayNameBracketsMax]; 1065 int32_t ulen; 1066 1067 (void) u_unescape(itemPtr->regionName, expectRegionName, kDisplayNameBracketsMax); 1068 (void) u_unescape(itemPtr->localeName, expectLocaleName, kDisplayNameBracketsMax); 1069 1070 status = U_ZERO_ERROR; 1071 ulen = uloc_getDisplayCountry(itemPtr->namedLocale, itemPtr->displayLocale, getName, kDisplayNameBracketsMax, &status); 1072 if ( U_FAILURE(status) || u_strcmp(getName, expectRegionName) != 0 ) { 1073 log_data_err("uloc_getDisplayCountry for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status)); 1074 } 1075 1076 status = U_ZERO_ERROR; 1077 ulen = uloc_getDisplayName(itemPtr->namedLocale, itemPtr->displayLocale, getName, kDisplayNameBracketsMax, &status); 1078 if ( U_FAILURE(status) || u_strcmp(getName, expectLocaleName) != 0 ) { 1079 log_data_err("uloc_getDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status)); 1080 } 1081 1082 #if !UCONFIG_NO_FORMATTING 1083 status = U_ZERO_ERROR; 1084 uldn = uldn_open(itemPtr->displayLocale, ULDN_STANDARD_NAMES, &status); 1085 if (U_SUCCESS(status)) { 1086 status = U_ZERO_ERROR; 1087 ulen = uldn_regionDisplayName(uldn, itemPtr->namedRegion, getName, kDisplayNameBracketsMax, &status); 1088 if ( U_FAILURE(status) || u_strcmp(getName, expectRegionName) != 0 ) { 1089 log_data_err("uldn_regionDisplayName for displayLocale %s and namedRegion %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedRegion, myErrorName(status)); 1090 } 1091 1092 status = U_ZERO_ERROR; 1093 ulen = uldn_localeDisplayName(uldn, itemPtr->namedLocale, getName, kDisplayNameBracketsMax, &status); 1094 if ( U_FAILURE(status) || u_strcmp(getName, expectLocaleName) != 0 ) { 1095 log_data_err("uldn_localeDisplayName for displayLocale %s and namedLocale %s returns unexpected name or status %s\n", itemPtr->displayLocale, itemPtr->namedLocale, myErrorName(status)); 1096 } 1097 1098 uldn_close(uldn); 1099 } else { 1100 log_data_err("uldn_open fails for displayLocale %s, status=%s\n", itemPtr->displayLocale, u_errorName(status)); 1101 } 1102 #endif 1103 (void)ulen; /* Suppress variable not used warning */ 1104 } 1105 } 1106 1107 /*------------------------------ 1108 * TestISOFunctions 1109 */ 1110 1111 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION 1112 /* test for uloc_getISOLanguages, uloc_getISOCountries */ 1113 static void TestISOFunctions() 1114 { 1115 const char* const* str=uloc_getISOLanguages(); 1116 const char* const* str1=uloc_getISOCountries(); 1117 const char* test; 1118 const char *key = NULL; 1119 int32_t count = 0, skipped = 0; 1120 int32_t expect; 1121 UResourceBundle *res; 1122 UResourceBundle *subRes; 1123 UErrorCode status = U_ZERO_ERROR; 1124 1125 /* test getISOLanguages*/ 1126 /*str=uloc_getISOLanguages(); */ 1127 log_verbose("Testing ISO Languages: \n"); 1128 1129 /* use structLocale - this data is no longer in root */ 1130 res = ures_openDirect(loadTestData(&status), "structLocale", &status); 1131 subRes = ures_getByKey(res, "Languages", NULL, &status); 1132 if (U_FAILURE(status)) { 1133 log_data_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status)); 1134 return; 1135 } 1136 1137 expect = ures_getSize(subRes); 1138 for(count = 0; *(str+count) != 0; count++) 1139 { 1140 key = NULL; 1141 test = *(str+count); 1142 status = U_ZERO_ERROR; 1143 1144 do { 1145 /* Skip over language tags. This API only returns language codes. */ 1146 skipped += (key != NULL); 1147 ures_getNextString(subRes, NULL, &key, &status); 1148 } 1149 while (key != NULL && strchr(key, '_')); 1150 1151 if(key == NULL) 1152 break; 1153 /* TODO: Consider removing sh, which is deprecated */ 1154 if(strcmp(key,"root") == 0 || strcmp(key,"Fallback") == 0 || strcmp(key,"sh") == 0) { 1155 ures_getNextString(subRes, NULL, &key, &status); 1156 skipped++; 1157 } 1158 #if U_CHARSET_FAMILY==U_ASCII_FAMILY 1159 /* This code only works on ASCII machines where the keys are stored in ASCII order */ 1160 if(strcmp(test,key)) { 1161 /* The first difference usually implies the place where things get out of sync */ 1162 log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count, test, key); 1163 } 1164 #endif 1165 1166 if(!strcmp(test,"in")) 1167 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); 1168 if(!strcmp(test,"iw")) 1169 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); 1170 if(!strcmp(test,"ji")) 1171 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); 1172 if(!strcmp(test,"jw")) 1173 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); 1174 if(!strcmp(test,"sh")) 1175 log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); 1176 } 1177 1178 expect -= skipped; /* Ignore the skipped resources from structLocale */ 1179 1180 if(count!=expect) { 1181 log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count, expect); 1182 } 1183 1184 subRes = ures_getByKey(res, "Countries", subRes, &status); 1185 log_verbose("Testing ISO Countries"); 1186 skipped = 0; 1187 expect = ures_getSize(subRes) - 1; /* Skip ZZ */ 1188 for(count = 0; *(str1+count) != 0; count++) 1189 { 1190 key = NULL; 1191 test = *(str1+count); 1192 do { 1193 /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */ 1194 skipped += (key != NULL); 1195 ures_getNextString(subRes, NULL, &key, &status); 1196 } 1197 while (key != NULL && strlen(key) != 2); 1198 1199 if(key == NULL) 1200 break; 1201 /* TODO: Consider removing CS, which is deprecated */ 1202 while(strcmp(key,"QO") == 0 || strcmp(key,"QU") == 0 || strcmp(key,"CS") == 0) { 1203 ures_getNextString(subRes, NULL, &key, &status); 1204 skipped++; 1205 } 1206 #if U_CHARSET_FAMILY==U_ASCII_FAMILY 1207 /* This code only works on ASCII machines where the keys are stored in ASCII order */ 1208 if(strcmp(test,key)) { 1209 /* The first difference usually implies the place where things get out of sync */ 1210 log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count, test, key); 1211 } 1212 #endif 1213 if(!strcmp(test,"FX")) 1214 log_err("FAIL getISOCountries() has obsolete country code %s\n", test); 1215 if(!strcmp(test,"YU")) 1216 log_err("FAIL getISOCountries() has obsolete country code %s\n", test); 1217 if(!strcmp(test,"ZR")) 1218 log_err("FAIL getISOCountries() has obsolete country code %s\n", test); 1219 } 1220 1221 ures_getNextString(subRes, NULL, &key, &status); 1222 if (strcmp(key, "ZZ") != 0) { 1223 log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key); 1224 } 1225 #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY 1226 /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */ 1227 key = NULL; 1228 do { 1229 /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */ 1230 skipped += (key != NULL); 1231 ures_getNextString(subRes, NULL, &key, &status); 1232 } 1233 while (U_SUCCESS(status) && key != NULL && strlen(key) != 2); 1234 #endif 1235 expect -= skipped; /* Ignore the skipped resources from structLocale */ 1236 if(count!=expect) 1237 { 1238 log_err("There is an error in getISOCountries, got %d, expected %d \n", count, expect); 1239 } 1240 ures_close(subRes); 1241 ures_close(res); 1242 } 1243 #endif 1244 1245 static void setUpDataTable() 1246 { 1247 int32_t i,j; 1248 dataTable = (UChar***)(calloc(sizeof(UChar**),LOCALE_INFO_SIZE)); 1249 1250 for (i = 0; i < LOCALE_INFO_SIZE; i++) { 1251 dataTable[i] = (UChar**)(calloc(sizeof(UChar*),LOCALE_SIZE)); 1252 for (j = 0; j < LOCALE_SIZE; j++){ 1253 dataTable[i][j] = CharsToUChars(rawData2[i][j]); 1254 } 1255 } 1256 } 1257 1258 static void cleanUpDataTable() 1259 { 1260 int32_t i,j; 1261 if(dataTable != NULL) { 1262 for (i=0; i<LOCALE_INFO_SIZE; i++) { 1263 for(j = 0; j < LOCALE_SIZE; j++) { 1264 free(dataTable[i][j]); 1265 } 1266 free(dataTable[i]); 1267 } 1268 free(dataTable); 1269 } 1270 dataTable = NULL; 1271 } 1272 1273 /** 1274 * @bug 4011756 4011380 1275 */ 1276 static void TestISO3Fallback() 1277 { 1278 const char* test="xx_YY"; 1279 1280 const char * result; 1281 1282 result = uloc_getISO3Language(test); 1283 1284 /* Conform to C API usage */ 1285 1286 if (!result || (result[0] != 0)) 1287 log_err("getISO3Language() on xx_YY returned %s instead of \"\""); 1288 1289 result = uloc_getISO3Country(test); 1290 1291 if (!result || (result[0] != 0)) 1292 log_err("getISO3Country() on xx_YY returned %s instead of \"\""); 1293 } 1294 1295 /** 1296 * @bug 4118587 1297 */ 1298 static void TestSimpleDisplayNames() 1299 { 1300 /* 1301 This test is different from TestDisplayNames because TestDisplayNames checks 1302 fallback behavior, combination of language and country names to form locale 1303 names, and other stuff like that. This test just checks specific language 1304 and country codes to make sure we have the correct names for them. 1305 */ 1306 char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za", "419" }; 1307 const char* languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish", 1308 "Zhuang", "419" }; 1309 const char* inLocale [] = { "en_US", "zh_Hant"}; 1310 UErrorCode status=U_ZERO_ERROR; 1311 1312 int32_t i; 1313 int32_t localeIndex = 0; 1314 for (i = 0; i < 7; i++) { 1315 UChar *testLang=0; 1316 UChar *expectedLang=0; 1317 int size=0; 1318 1319 if (i == 6) { 1320 localeIndex = 1; /* Use the second locale for the rest of the test. */ 1321 } 1322 1323 size=uloc_getDisplayLanguage(languageCodes[i], inLocale[localeIndex], NULL, size, &status); 1324 if(status==U_BUFFER_OVERFLOW_ERROR) { 1325 status=U_ZERO_ERROR; 1326 testLang=(UChar*)malloc(sizeof(UChar) * (size + 1)); 1327 uloc_getDisplayLanguage(languageCodes[i], inLocale[localeIndex], testLang, size + 1, &status); 1328 } 1329 expectedLang=(UChar*)malloc(sizeof(UChar) * (strlen(languageNames[i])+1)); 1330 u_uastrcpy(expectedLang, languageNames[i]); 1331 if (u_strcmp(testLang, expectedLang) != 0) 1332 log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n", 1333 languageCodes[i], languageNames[i], austrdup(testLang)); 1334 free(testLang); 1335 free(expectedLang); 1336 } 1337 1338 } 1339 1340 /** 1341 * @bug 4118595 1342 */ 1343 static void TestUninstalledISO3Names() 1344 { 1345 /* This test checks to make sure getISO3Language and getISO3Country work right 1346 even for locales that are not installed. */ 1347 static const char iso2Languages [][4] = { "am", "ba", "fy", "mr", "rn", 1348 "ss", "tw", "zu" }; 1349 static const char iso3Languages [][5] = { "amh", "bak", "fry", "mar", "run", 1350 "ssw", "twi", "zul" }; 1351 static const char iso2Countries [][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN", 1352 "ss_SB", "tw_TC", "zu_ZW" }; 1353 static const char iso3Countries [][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG", 1354 "SLB", "TCA", "ZWE" }; 1355 int32_t i; 1356 1357 for (i = 0; i < 8; i++) { 1358 UErrorCode err = U_ZERO_ERROR; 1359 const char *test; 1360 test = uloc_getISO3Language(iso2Languages[i]); 1361 if(strcmp(test, iso3Languages[i]) !=0 || U_FAILURE(err)) 1362 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n", 1363 iso2Languages[i], iso3Languages[i], test, myErrorName(err)); 1364 } 1365 for (i = 0; i < 8; i++) { 1366 UErrorCode err = U_ZERO_ERROR; 1367 const char *test; 1368 test = uloc_getISO3Country(iso2Countries[i]); 1369 if(strcmp(test, iso3Countries[i]) !=0 || U_FAILURE(err)) 1370 log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n", 1371 iso2Countries[i], iso3Countries[i], test, myErrorName(err)); 1372 } 1373 } 1374 1375 1376 static void TestVariantParsing() 1377 { 1378 static const char* en_US_custom="en_US_De Anza_Cupertino_California_United States_Earth"; 1379 static const char* dispName="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)"; 1380 static const char* dispVar="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH"; 1381 static const char* shortVariant="fr_FR_foo"; 1382 static const char* bogusVariant="fr_FR__foo"; 1383 static const char* bogusVariant2="fr_FR_foo_"; 1384 static const char* bogusVariant3="fr_FR__foo_"; 1385 1386 1387 UChar displayVar[100]; 1388 UChar displayName[100]; 1389 UErrorCode status=U_ZERO_ERROR; 1390 UChar* got=0; 1391 int32_t size=0; 1392 size=uloc_getDisplayVariant(en_US_custom, "en_US", NULL, size, &status); 1393 if(status==U_BUFFER_OVERFLOW_ERROR) { 1394 status=U_ZERO_ERROR; 1395 got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); 1396 uloc_getDisplayVariant(en_US_custom, "en_US", got, size + 1, &status); 1397 } 1398 else { 1399 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); 1400 } 1401 u_uastrcpy(displayVar, dispVar); 1402 if(u_strcmp(got,displayVar)!=0) { 1403 log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar, austrdup(got)); 1404 } 1405 size=0; 1406 size=uloc_getDisplayName(en_US_custom, "en_US", NULL, size, &status); 1407 if(status==U_BUFFER_OVERFLOW_ERROR) { 1408 status=U_ZERO_ERROR; 1409 got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); 1410 uloc_getDisplayName(en_US_custom, "en_US", got, size + 1, &status); 1411 } 1412 else { 1413 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); 1414 } 1415 u_uastrcpy(displayName, dispName); 1416 if(u_strcmp(got,displayName)!=0) { 1417 if (status == U_USING_DEFAULT_WARNING) { 1418 log_data_err("FAIL: getDisplayName() got %s. Perhaps you are missing data?\n", u_errorName(status)); 1419 } else { 1420 log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName, austrdup(got)); 1421 } 1422 } 1423 1424 size=0; 1425 status=U_ZERO_ERROR; 1426 size=uloc_getDisplayVariant(shortVariant, NULL, NULL, size, &status); 1427 if(status==U_BUFFER_OVERFLOW_ERROR) { 1428 status=U_ZERO_ERROR; 1429 got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); 1430 uloc_getDisplayVariant(shortVariant, NULL, got, size + 1, &status); 1431 } 1432 else { 1433 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); 1434 } 1435 if(strcmp(austrdup(got),"FOO")!=0) { 1436 log_err("FAIL: getDisplayVariant() Wanted: foo Got: %s\n", austrdup(got)); 1437 } 1438 size=0; 1439 status=U_ZERO_ERROR; 1440 size=uloc_getDisplayVariant(bogusVariant, NULL, NULL, size, &status); 1441 if(status==U_BUFFER_OVERFLOW_ERROR) { 1442 status=U_ZERO_ERROR; 1443 got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); 1444 uloc_getDisplayVariant(bogusVariant, NULL, got, size + 1, &status); 1445 } 1446 else { 1447 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); 1448 } 1449 if(strcmp(austrdup(got),"_FOO")!=0) { 1450 log_err("FAIL: getDisplayVariant() Wanted: _FOO Got: %s\n", austrdup(got)); 1451 } 1452 size=0; 1453 status=U_ZERO_ERROR; 1454 size=uloc_getDisplayVariant(bogusVariant2, NULL, NULL, size, &status); 1455 if(status==U_BUFFER_OVERFLOW_ERROR) { 1456 status=U_ZERO_ERROR; 1457 got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); 1458 uloc_getDisplayVariant(bogusVariant2, NULL, got, size + 1, &status); 1459 } 1460 else { 1461 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); 1462 } 1463 if(strcmp(austrdup(got),"FOO_")!=0) { 1464 log_err("FAIL: getDisplayVariant() Wanted: FOO_ Got: %s\n", austrdup(got)); 1465 } 1466 size=0; 1467 status=U_ZERO_ERROR; 1468 size=uloc_getDisplayVariant(bogusVariant3, NULL, NULL, size, &status); 1469 if(status==U_BUFFER_OVERFLOW_ERROR) { 1470 status=U_ZERO_ERROR; 1471 got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); 1472 uloc_getDisplayVariant(bogusVariant3, NULL, got, size + 1, &status); 1473 } 1474 else { 1475 log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); 1476 } 1477 if(strcmp(austrdup(got),"_FOO_")!=0) { 1478 log_err("FAIL: getDisplayVariant() Wanted: _FOO_ Got: %s\n", austrdup(got)); 1479 } 1480 free(got); 1481 } 1482 1483 1484 static void TestObsoleteNames(void) 1485 { 1486 int32_t i; 1487 UErrorCode status = U_ZERO_ERROR; 1488 char buff[256]; 1489 1490 static const struct 1491 { 1492 char locale[9]; 1493 char lang3[4]; 1494 char lang[4]; 1495 char ctry3[4]; 1496 char ctry[4]; 1497 } tests[] = 1498 { 1499 { "eng_USA", "eng", "en", "USA", "US" }, 1500 { "kok", "kok", "kok", "", "" }, 1501 { "in", "ind", "in", "", "" }, 1502 { "id", "ind", "id", "", "" }, /* NO aliasing */ 1503 { "sh", "srp", "sh", "", "" }, 1504 { "zz_CS", "", "zz", "SCG", "CS" }, 1505 { "zz_FX", "", "zz", "FXX", "FX" }, 1506 { "zz_RO", "", "zz", "ROU", "RO" }, 1507 { "zz_TP", "", "zz", "TMP", "TP" }, 1508 { "zz_TL", "", "zz", "TLS", "TL" }, 1509 { "zz_ZR", "", "zz", "ZAR", "ZR" }, 1510 { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */ 1511 { "zz_ROM", "", "zz", "ROU", "RO" }, 1512 { "zz_ROU", "", "zz", "ROU", "RO" }, 1513 { "zz_ZAR", "", "zz", "ZAR", "ZR" }, 1514 { "zz_TMP", "", "zz", "TMP", "TP" }, 1515 { "zz_TLS", "", "zz", "TLS", "TL" }, 1516 { "zz_YUG", "", "zz", "YUG", "YU" }, 1517 { "mlt_PSE", "mlt", "mt", "PSE", "PS" }, 1518 { "iw", "heb", "iw", "", "" }, 1519 { "ji", "yid", "ji", "", "" }, 1520 { "jw", "jaw", "jw", "", "" }, 1521 { "sh", "srp", "sh", "", "" }, 1522 { "", "", "", "", "" } 1523 }; 1524 1525 for(i=0;tests[i].locale[0];i++) 1526 { 1527 const char *locale; 1528 1529 locale = tests[i].locale; 1530 log_verbose("** %s:\n", locale); 1531 1532 status = U_ZERO_ERROR; 1533 if(strcmp(tests[i].lang3,uloc_getISO3Language(locale))) 1534 { 1535 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n", 1536 locale, uloc_getISO3Language(locale), tests[i].lang3); 1537 } 1538 else 1539 { 1540 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n", 1541 uloc_getISO3Language(locale) ); 1542 } 1543 1544 status = U_ZERO_ERROR; 1545 uloc_getLanguage(locale, buff, 256, &status); 1546 if(U_FAILURE(status)) 1547 { 1548 log_err("FAIL: error getting language from %s\n", locale); 1549 } 1550 else 1551 { 1552 if(strcmp(buff,tests[i].lang)) 1553 { 1554 log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n", 1555 locale, buff, tests[i].lang); 1556 } 1557 else 1558 { 1559 log_verbose(" uloc_getLanguage(%s)==\t%s\n", locale, buff); 1560 } 1561 } 1562 if(strcmp(tests[i].lang3,uloc_getISO3Language(locale))) 1563 { 1564 log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n", 1565 locale, uloc_getISO3Language(locale), tests[i].lang3); 1566 } 1567 else 1568 { 1569 log_verbose(" uloc_getISO3Language()==\t\"%s\"\n", 1570 uloc_getISO3Language(locale) ); 1571 } 1572 1573 if(strcmp(tests[i].ctry3,uloc_getISO3Country(locale))) 1574 { 1575 log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n", 1576 locale, uloc_getISO3Country(locale), tests[i].ctry3); 1577 } 1578 else 1579 { 1580 log_verbose(" uloc_getISO3Country()==\t\"%s\"\n", 1581 uloc_getISO3Country(locale) ); 1582 } 1583 1584 status = U_ZERO_ERROR; 1585 uloc_getCountry(locale, buff, 256, &status); 1586 if(U_FAILURE(status)) 1587 { 1588 log_err("FAIL: error getting country from %s\n", locale); 1589 } 1590 else 1591 { 1592 if(strcmp(buff,tests[i].ctry)) 1593 { 1594 log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n", 1595 locale, buff, tests[i].ctry); 1596 } 1597 else 1598 { 1599 log_verbose(" uloc_getCountry(%s)==\t%s\n", locale, buff); 1600 } 1601 } 1602 } 1603 1604 if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) { 1605 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL")); 1606 } 1607 1608 if (uloc_getLCID("iw") != uloc_getLCID("he")) { 1609 log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he")); 1610 } 1611 1612 #if 0 1613 1614 i = uloc_getLanguage("kok",NULL,0,&icu_err); 1615 if(U_FAILURE(icu_err)) 1616 { 1617 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err)); 1618 } 1619 1620 icu_err = U_ZERO_ERROR; 1621 uloc_getLanguage("kok",r1_buff,12,&icu_err); 1622 if(U_FAILURE(icu_err)) 1623 { 1624 log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err)); 1625 } 1626 1627 r1_addr = (char *)uloc_getISO3Language("kok"); 1628 1629 icu_err = U_ZERO_ERROR; 1630 if (strcmp(r1_buff,"kok") != 0) 1631 { 1632 log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff); 1633 line--; 1634 } 1635 r1_addr = (char *)uloc_getISO3Language("in"); 1636 i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err); 1637 if (strcmp(r1_buff,"id") != 0) 1638 { 1639 printf("uloc_getLanguage error (%s)\n",r1_buff); 1640 line--; 1641 } 1642 r1_addr = (char *)uloc_getISO3Language("sh"); 1643 i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err); 1644 if (strcmp(r1_buff,"sr") != 0) 1645 { 1646 printf("uloc_getLanguage error (%s)\n",r1_buff); 1647 line--; 1648 } 1649 1650 r1_addr = (char *)uloc_getISO3Country("zz_ZR"); 1651 strcpy(p1_buff,"zz_"); 1652 strcat(p1_buff,r1_addr); 1653 i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err); 1654 if (strcmp(r1_buff,"ZR") != 0) 1655 { 1656 printf("uloc_getCountry error (%s)\n",r1_buff); 1657 line--; 1658 } 1659 r1_addr = (char *)uloc_getISO3Country("zz_FX"); 1660 strcpy(p1_buff,"zz_"); 1661 strcat(p1_buff,r1_addr); 1662 i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err); 1663 if (strcmp(r1_buff,"FX") != 0) 1664 { 1665 printf("uloc_getCountry error (%s)\n",r1_buff); 1666 line--; 1667 } 1668 1669 #endif 1670 1671 } 1672 1673 static void TestKeywordVariants(void) 1674 { 1675 static const struct { 1676 const char *localeID; 1677 const char *expectedLocaleID; 1678 const char *expectedLocaleIDNoKeywords; 1679 const char *expectedCanonicalID; 1680 const char *expectedKeywords[10]; 1681 int32_t numKeywords; 1682 UErrorCode expectedStatus; /* from uloc_openKeywords */ 1683 } testCases[] = { 1684 { 1685 "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ", 1686 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro", 1687 "de_DE", 1688 "de_DE@calendar=buddhist;collation=Phonebook;currency=euro", 1689 {"calendar", "collation", "currency"}, 1690 3, 1691 U_ZERO_ERROR 1692 }, 1693 { 1694 "de_DE@euro", 1695 "de_DE@euro", 1696 "de_DE", 1697 "de_DE@currency=EUR", 1698 {"","","","","","",""}, 1699 0, 1700 U_INVALID_FORMAT_ERROR /* must have '=' after '@' */ 1701 }, 1702 { 1703 "de_DE@euro;collation=phonebook", 1704 "de_DE", /* error result; bad format */ 1705 "de_DE", /* error result; bad format */ 1706 "de_DE", /* error result; bad format */ 1707 {"","","","","","",""}, 1708 0, 1709 U_INVALID_FORMAT_ERROR 1710 } 1711 }; 1712 UErrorCode status = U_ZERO_ERROR; 1713 1714 int32_t i = 0, j = 0; 1715 int32_t resultLen = 0; 1716 char buffer[256]; 1717 UEnumeration *keywords; 1718 int32_t keyCount = 0; 1719 const char *keyword = NULL; 1720 int32_t keywordLen = 0; 1721 1722 for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { 1723 status = U_ZERO_ERROR; 1724 *buffer = 0; 1725 keywords = uloc_openKeywords(testCases[i].localeID, &status); 1726 1727 if(status != testCases[i].expectedStatus) { 1728 log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n", 1729 testCases[i].localeID, 1730 u_errorName(testCases[i].expectedStatus), u_errorName(status)); 1731 } 1732 status = U_ZERO_ERROR; 1733 if(keywords) { 1734 if((keyCount = uenum_count(keywords, &status)) != testCases[i].numKeywords) { 1735 log_err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount); 1736 } 1737 if(keyCount) { 1738 j = 0; 1739 while((keyword = uenum_next(keywords, &keywordLen, &status))) { 1740 if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) { 1741 log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword); 1742 } 1743 j++; 1744 } 1745 j = 0; 1746 uenum_reset(keywords, &status); 1747 while((keyword = uenum_next(keywords, &keywordLen, &status))) { 1748 if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) { 1749 log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword); 1750 } 1751 j++; 1752 } 1753 } 1754 uenum_close(keywords); 1755 } 1756 resultLen = uloc_getName(testCases[i].localeID, buffer, 256, &status); 1757 (void)resultLen; /* Suppress set but not used warning. */ 1758 if (uprv_strcmp(testCases[i].expectedLocaleID, buffer) != 0) { 1759 log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n", 1760 testCases[i].localeID, testCases[i].expectedLocaleID, buffer); 1761 } 1762 resultLen = uloc_canonicalize(testCases[i].localeID, buffer, 256, &status); 1763 if (uprv_strcmp(testCases[i].expectedCanonicalID, buffer) != 0) { 1764 log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n", 1765 testCases[i].localeID, testCases[i].expectedCanonicalID, buffer); 1766 } 1767 } 1768 1769 } 1770 1771 static void TestKeywordVariantParsing(void) 1772 { 1773 static const struct { 1774 const char *localeID; 1775 const char *keyword; 1776 const char *expectedValue; 1777 } testCases[] = { 1778 { "de_DE@ C o ll A t i o n = Phonebook ", "c o ll a t i o n", "Phonebook" }, 1779 { "de_DE", "collation", ""}, 1780 { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" }, 1781 { "de_DE@currency = euro; CoLLaTion = PHONEBOOk", "collatiON", "PHONEBOOk" }, 1782 }; 1783 1784 UErrorCode status = U_ZERO_ERROR; 1785 1786 int32_t i = 0; 1787 int32_t resultLen = 0; 1788 char buffer[256]; 1789 1790 for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { 1791 *buffer = 0; 1792 resultLen = uloc_getKeywordValue(testCases[i].localeID, testCases[i].keyword, buffer, 256, &status); 1793 (void)resultLen; /* Suppress set but not used warning. */ 1794 if(uprv_strcmp(testCases[i].expectedValue, buffer) != 0) { 1795 log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n", 1796 testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer); 1797 } 1798 } 1799 } 1800 1801 static const struct { 1802 const char *l; /* locale */ 1803 const char *k; /* kw */ 1804 const char *v; /* value */ 1805 const char *x; /* expected */ 1806 } kwSetTestCases[] = { 1807 #if 1 1808 { "en_US", "calendar", "japanese", "en_US@calendar=japanese" }, 1809 { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" }, 1810 { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" }, 1811 { "en_US@calendar=slovakian", "calendar", "gregorian", "en_US@calendar=gregorian" }, /* don't know what this means, but it has the same # of chars as gregorian */ 1812 { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" }, 1813 { "de", "Currency", "CHF", "de@currency=CHF" }, 1814 { "de", "Currency", "CHF", "de@currency=CHF" }, 1815 1816 { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" }, 1817 { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" }, 1818 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }, 1819 { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" }, 1820 { "en_US@calendar=slovakian;collation=phonebook", "calendar", "gregorian", "en_US@calendar=gregorian;collation=phonebook" }, /* don't know what this means, but it has the same # of chars as gregorian */ 1821 { "en_US@calendar=slovakian;collation=videobook", "collation", "phonebook", "en_US@calendar=slovakian;collation=phonebook" }, /* don't know what this means, but it has the same # of chars as gregorian */ 1822 { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" }, 1823 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }, 1824 #endif 1825 #if 1 1826 { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" }, 1827 { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" }, 1828 { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" }, 1829 { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" }, 1830 { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" }, 1831 { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" }, 1832 { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" }, 1833 { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" }, 1834 { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" }, 1835 #endif 1836 #if 1 1837 /* removal tests */ 1838 /* 1. removal of item at end */ 1839 { "de@collation=phonebook;currency=CHF", "currency", "", "de@collation=phonebook" }, 1840 { "de@collation=phonebook;currency=CHF", "currency", NULL, "de@collation=phonebook" }, 1841 /* 2. removal of item at beginning */ 1842 { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" }, 1843 { "de@collation=phonebook;currency=CHF", "collation", NULL, "de@currency=CHF" }, 1844 /* 3. removal of an item not there */ 1845 { "de@collation=phonebook;currency=CHF", "calendar", NULL, "de@collation=phonebook;currency=CHF" }, 1846 /* 4. removal of only item */ 1847 { "de@collation=phonebook", "collation", NULL, "de" }, 1848 #endif 1849 { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" } 1850 }; 1851 1852 1853 static void TestKeywordSet(void) 1854 { 1855 int32_t i = 0; 1856 int32_t resultLen = 0; 1857 char buffer[1024]; 1858 1859 char cbuffer[1024]; 1860 1861 for(i = 0; i < sizeof(kwSetTestCases)/sizeof(kwSetTestCases[0]); i++) { 1862 UErrorCode status = U_ZERO_ERROR; 1863 memset(buffer,'%',1023); 1864 strcpy(buffer, kwSetTestCases[i].l); 1865 1866 uloc_canonicalize(kwSetTestCases[i].l, cbuffer, 1023, &status); 1867 if(strcmp(buffer,cbuffer)) { 1868 log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i, cbuffer, buffer); 1869 } 1870 /* sanity check test case results for canonicity */ 1871 uloc_canonicalize(kwSetTestCases[i].x, cbuffer, 1023, &status); 1872 if(strcmp(kwSetTestCases[i].x,cbuffer)) { 1873 log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__, __LINE__, i, kwSetTestCases[i].x, cbuffer); 1874 } 1875 1876 resultLen = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, 1023, &status); 1877 if(U_FAILURE(status)) { 1878 log_err("Err on test case %d: got error %s\n", i, u_errorName(status)); 1879 continue; 1880 } 1881 if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=resultLen)) { 1882 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, 1883 kwSetTestCases[i].v, buffer, resultLen, kwSetTestCases[i].x, strlen(buffer)); 1884 } else { 1885 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,buffer); 1886 } 1887 } 1888 } 1889 1890 static void TestKeywordSetError(void) 1891 { 1892 char buffer[1024]; 1893 UErrorCode status; 1894 int32_t res; 1895 int32_t i; 1896 int32_t blen; 1897 1898 /* 0-test whether an error condition modifies the buffer at all */ 1899 blen=0; 1900 i=0; 1901 memset(buffer,'%',1023); 1902 status = U_ZERO_ERROR; 1903 res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status); 1904 if(status != U_ILLEGAL_ARGUMENT_ERROR) { 1905 log_err("expected illegal err got %s\n", u_errorName(status)); 1906 return; 1907 } 1908 /* if(res!=strlen(kwSetTestCases[i].x)) { 1909 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res); 1910 return; 1911 } */ 1912 if(buffer[blen]!='%') { 1913 log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]); 1914 return; 1915 } 1916 log_verbose("0-buffer modify OK\n"); 1917 1918 for(i=0;i<=2;i++) { 1919 /* 1- test a short buffer with growing text */ 1920 blen=(int32_t)strlen(kwSetTestCases[i].l)+1; 1921 memset(buffer,'%',1023); 1922 strcpy(buffer,kwSetTestCases[i].l); 1923 status = U_ZERO_ERROR; 1924 res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status); 1925 if(status != U_BUFFER_OVERFLOW_ERROR) { 1926 log_err("expected buffer overflow on buffer %d got %s, len %d (%s + [%s=%s])\n", blen, u_errorName(status), res, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v); 1927 return; 1928 } 1929 if(res!=(int32_t)strlen(kwSetTestCases[i].x)) { 1930 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res); 1931 return; 1932 } 1933 if(buffer[blen]!='%') { 1934 log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]); 1935 return; 1936 } 1937 log_verbose("1/%d-buffer modify OK\n",i); 1938 } 1939 1940 for(i=3;i<=4;i++) { 1941 /* 2- test a short buffer - text the same size or shrinking */ 1942 blen=(int32_t)strlen(kwSetTestCases[i].l)+1; 1943 memset(buffer,'%',1023); 1944 strcpy(buffer,kwSetTestCases[i].l); 1945 status = U_ZERO_ERROR; 1946 res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status); 1947 if(status != U_ZERO_ERROR) { 1948 log_err("expected zero error got %s\n", u_errorName(status)); 1949 return; 1950 } 1951 if(buffer[blen+1]!='%') { 1952 log_err("Buffer byte %d was modified: now %c\n", blen+1, buffer[blen+1]); 1953 return; 1954 } 1955 if(res!=(int32_t)strlen(kwSetTestCases[i].x)) { 1956 log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res); 1957 return; 1958 } 1959 if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=res)) { 1960 log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, 1961 kwSetTestCases[i].v, buffer, res, kwSetTestCases[i].x, strlen(buffer)); 1962 } else { 1963 log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v, 1964 buffer); 1965 } 1966 log_verbose("2/%d-buffer modify OK\n",i); 1967 } 1968 } 1969 1970 static int32_t _canonicalize(int32_t selector, /* 0==getName, 1==canonicalize */ 1971 const char* localeID, 1972 char* result, 1973 int32_t resultCapacity, 1974 UErrorCode* ec) { 1975 /* YOU can change this to use function pointers if you like */ 1976 switch (selector) { 1977 case 0: 1978 return uloc_getName(localeID, result, resultCapacity, ec); 1979 case 1: 1980 return uloc_canonicalize(localeID, result, resultCapacity, ec); 1981 default: 1982 return -1; 1983 } 1984 } 1985 1986 static void TestCanonicalization(void) 1987 { 1988 static const struct { 1989 const char *localeID; /* input */ 1990 const char *getNameID; /* expected getName() result */ 1991 const char *canonicalID; /* expected canonicalize() result */ 1992 } testCases[] = { 1993 { "ca_ES_PREEURO-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage", 1994 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE", 1995 "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"}, 1996 { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES@currency=ESP" }, 1997 { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT@currency=ATS" }, 1998 { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE@currency=DEM" }, 1999 { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU@currency=LUF" }, 2000 { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR@currency=GRD" }, 2001 { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE@currency=BEF" }, 2002 { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE@currency=IEP" }, 2003 { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES@currency=ESP" }, 2004 { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES@currency=ESP" }, 2005 { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI@currency=FIM" }, 2006 { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE@currency=BEF" }, 2007 { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR@currency=FRF" }, 2008 { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU@currency=LUF" }, 2009 { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE@currency=IEP" }, 2010 { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES@currency=ESP" }, 2011 { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT@currency=ITL" }, 2012 { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE@currency=BEF" }, 2013 { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL@currency=NLG" }, 2014 { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT@currency=PTE" }, 2015 { "de__PHONEBOOK", "de__PHONEBOOK", "de@collation=phonebook" }, 2016 { "en_GB_EURO", "en_GB_EURO", "en_GB@currency=EUR" }, 2017 { "en_GB@EURO", "en_GB@EURO", "en_GB@currency=EUR" }, /* POSIX ID */ 2018 { "es__TRADITIONAL", "es__TRADITIONAL", "es@collation=traditional" }, 2019 { "hi__DIRECT", "hi__DIRECT", "hi@collation=direct" }, 2020 { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP@calendar=japanese" }, 2021 { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH@calendar=buddhist" }, 2022 { "zh_TW_STROKE", "zh_TW_STROKE", "zh_TW@collation=stroke" }, 2023 { "zh__PINYIN", "zh__PINYIN", "zh@collation=pinyin" }, 2024 { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" }, 2025 { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" }, 2026 { "zh_CN_STROKE", "zh_CN_STROKE", "zh_CN@collation=stroke" }, 2027 { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" }, 2028 { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" }, 2029 { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" }, 2030 { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ }, 2031 { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */ 2032 { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */ 2033 { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ@currency=EUR" }, /* qz-qz uses private use iso codes */ 2034 { "en-BOONT", "en__BOONT", "en__BOONT" }, /* registered name */ 2035 { "de-1901", "de__1901", "de__1901" }, /* registered name */ 2036 { "de-1906", "de__1906", "de__1906" }, /* registered name */ 2037 { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_Cyrl_RS" }, /* .NET name */ 2038 { "sr-SP-Latn", "sr_SP_LATN", "sr_Latn_RS" }, /* .NET name */ 2039 { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_Cyrl_RS" }, /* Linux name */ 2040 { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_Cyrl_UZ" }, /* .NET name */ 2041 { "uz-UZ-Latn", "uz_UZ_LATN", "uz_Latn_UZ" }, /* .NET name */ 2042 { "zh-CHS", "zh_CHS", "zh_Hans" }, /* .NET name */ 2043 { "zh-CHT", "zh_CHT", "zh_Hant" }, /* .NET name This may change back to zh_Hant */ 2044 2045 /* posix behavior that used to be performed by getName */ 2046 { "mr.utf8", "mr.utf8", "mr" }, 2047 { "de-tv.koi8r", "de_TV.koi8r", "de_TV" }, 2048 { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" }, 2049 { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" }, 2050 { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" }, 2051 { "no-no-ny.utf8@B", "no_NO_NY.utf8@B", "no_NO_NY_B" /* not: "nn_NO" [alan ICU3.0] */ }, /* @ ignored unless variant is empty */ 2052 2053 /* fleshing out canonicalization */ 2054 /* trim space and sort keywords, ';' is separator so not present at end in canonical form */ 2055 { "en_Hant_IL_VALLEY_GIRL@ currency = EUR; calendar = Japanese ;", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR" }, 2056 /* already-canonical ids are not changed */ 2057 { "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR" }, 2058 /* PRE_EURO and EURO conversions don't affect other keywords */ 2059 { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES@calendar=Japanese;currency=ESP" }, 2060 { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES@currency=EUR;shout=zipeedeedoodah" }, 2061 /* currency keyword overrides PRE_EURO and EURO currency */ 2062 { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES@currency=EUR" }, 2063 { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES@currency=ESP" }, 2064 /* norwegian is just too weird, if we handle things in their full generality */ 2065 { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ }, 2066 2067 /* test cases reflecting internal resource bundle usage */ 2068 { "root@kw=foo", "root@kw=foo", "root@kw=foo" }, 2069 { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" }, 2070 { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" }, 2071 { "ja_JP", "ja_JP", "ja_JP" }, 2072 2073 /* test case for "i-default" */ 2074 { "i-default", "en@x=i-default", "en@x=i-default" } 2075 }; 2076 2077 static const char* label[] = { "getName", "canonicalize" }; 2078 2079 UErrorCode status = U_ZERO_ERROR; 2080 int32_t i, j, resultLen = 0, origResultLen; 2081 char buffer[256]; 2082 2083 for (i=0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { 2084 for (j=0; j<2; ++j) { 2085 const char* expected = (j==0) ? testCases[i].getNameID : testCases[i].canonicalID; 2086 *buffer = 0; 2087 status = U_ZERO_ERROR; 2088 2089 if (expected == NULL) { 2090 expected = uloc_getDefault(); 2091 } 2092 2093 /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */ 2094 origResultLen = _canonicalize(j, testCases[i].localeID, NULL, 0, &status); 2095 if (status != U_BUFFER_OVERFLOW_ERROR) { 2096 log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n", 2097 label[j], testCases[i].localeID, u_errorName(status)); 2098 continue; 2099 } 2100 status = U_ZERO_ERROR; 2101 resultLen = _canonicalize(j, testCases[i].localeID, buffer, sizeof(buffer), &status); 2102 if (U_FAILURE(status)) { 2103 log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n", 2104 label[j], testCases[i].localeID, u_errorName(status)); 2105 continue; 2106 } 2107 if(uprv_strcmp(expected, buffer) != 0) { 2108 log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n", 2109 label[j], testCases[i].localeID, buffer, expected); 2110 } else { 2111 log_verbose("Ok: uloc_%s(%s) => \"%s\"\n", 2112 label[j], testCases[i].localeID, buffer); 2113 } 2114 if (resultLen != (int32_t)strlen(buffer)) { 2115 log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n", 2116 label[j], testCases[i].localeID, resultLen, strlen(buffer)); 2117 } 2118 if (origResultLen != resultLen) { 2119 log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n", 2120 label[j], testCases[i].localeID, origResultLen, resultLen); 2121 } 2122 } 2123 } 2124 } 2125 2126 static void TestDisplayKeywords(void) 2127 { 2128 int32_t i; 2129 2130 static const struct { 2131 const char *localeID; 2132 const char *displayLocale; 2133 UChar displayKeyword[200]; 2134 } testCases[] = { 2135 { "ca_ES@currency=ESP", "de_AT", 2136 {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}, 2137 }, 2138 { "ja_JP@calendar=japanese", "de", 2139 { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000} 2140 }, 2141 { "de_DE@collation=traditional", "de_DE", 2142 {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000} 2143 }, 2144 }; 2145 for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { 2146 UErrorCode status = U_ZERO_ERROR; 2147 const char* keyword =NULL; 2148 int32_t keywordLen = 0; 2149 int32_t keywordCount = 0; 2150 UChar *displayKeyword=NULL; 2151 int32_t displayKeywordLen = 0; 2152 UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status); 2153 for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){ 2154 if(U_FAILURE(status)){ 2155 log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases[i].localeID, u_errorName(status)); 2156 break; 2157 } 2158 /* the uenum_next returns NUL terminated string */ 2159 keyword = uenum_next(keywordEnum, &keywordLen, &status); 2160 /* fetch the displayKeyword */ 2161 displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status); 2162 if(status==U_BUFFER_OVERFLOW_ERROR){ 2163 status = U_ZERO_ERROR; 2164 displayKeywordLen++; /* for null termination */ 2165 displayKeyword = (UChar*) malloc(displayKeywordLen * U_SIZEOF_UCHAR); 2166 displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status); 2167 if(U_FAILURE(status)){ 2168 log_err("uloc_getDisplayKeyword filed for keyword : %s in locale id: %s for display locale: %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status)); 2169 break; 2170 } 2171 if(u_strncmp(displayKeyword, testCases[i].displayKeyword, displayKeywordLen)!=0){ 2172 if (status == U_USING_DEFAULT_WARNING) { 2173 log_data_err("uloc_getDisplayKeyword did not get the expected value for keyword : %s in locale id: %s for display locale: %s . Got error: %s. Perhaps you are missing data?\n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status)); 2174 } else { 2175 log_err("uloc_getDisplayKeyword did not get the expected value for keyword : %s in locale id: %s for display locale: %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale); 2176 } 2177 break; 2178 } 2179 }else{ 2180 log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status)); 2181 } 2182 2183 free(displayKeyword); 2184 2185 } 2186 uenum_close(keywordEnum); 2187 } 2188 } 2189 2190 static void TestDisplayKeywordValues(void){ 2191 int32_t i; 2192 2193 static const struct { 2194 const char *localeID; 2195 const char *displayLocale; 2196 UChar displayKeywordValue[500]; 2197 } testCases[] = { 2198 { "ca_ES@currency=ESP", "de_AT", 2199 {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0000} 2200 }, 2201 { "de_AT@currency=ATS", "fr_FR", 2202 {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000} 2203 }, 2204 { "de_DE@currency=DEM", "it", 2205 {0x006d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0074, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000} 2206 }, 2207 { "el_GR@currency=GRD", "en", 2208 {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000} 2209 }, 2210 { "eu_ES@currency=ESP", "it_IT", 2211 {0x0070, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0073, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000} 2212 }, 2213 { "de@collation=phonebook", "es", 2214 {0x006F, 0x0072, 0x0064, 0x0065, 0x006E, 0x0020, 0x0064, 0x0065, 0x0020, 0x006C, 0x0069, 0x0073, 0x0074, 0x00ED, 0x006E, 0x0020, 0x0074, 0x0065, 0x006C, 0x0065, 0x0066, 0x00F3, 0x006E, 0x0069, 0x0063, 0x006F, 0x0000} 2215 }, 2216 2217 { "de_DE@collation=phonebook", "es", 2218 {0x006F, 0x0072, 0x0064, 0x0065, 0x006E, 0x0020, 0x0064, 0x0065, 0x0020, 0x006C, 0x0069, 0x0073, 0x0074, 0x00ED, 0x006E, 0x0020, 0x0074, 0x0065, 0x006C, 0x0065, 0x0066, 0x00F3, 0x006E, 0x0069, 0x0063, 0x006F, 0x0000} 2219 }, 2220 { "es_ES@collation=traditional","de", 2221 {0x0054, 0x0072, 0x0061, 0x0064, 0x0069, 0x0074, 0x0069, 0x006f, 0x006e, 0x0065, 0x006c, 0x006c, 0x0065, 0x0020, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0072, 0x0065, 0x0067, 0x0065, 0x006c, 0x006e, 0x0000} 2222 }, 2223 { "ja_JP@calendar=japanese", "de", 2224 {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000} 2225 }, 2226 }; 2227 for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { 2228 UErrorCode status = U_ZERO_ERROR; 2229 const char* keyword =NULL; 2230 int32_t keywordLen = 0; 2231 int32_t keywordCount = 0; 2232 UChar *displayKeywordValue = NULL; 2233 int32_t displayKeywordValueLen = 0; 2234 UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status); 2235 for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){ 2236 if(U_FAILURE(status)){ 2237 log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", testCases[i].localeID, testCases[i].displayLocale, u_errorName(status)); 2238 break; 2239 } 2240 /* the uenum_next returns NUL terminated string */ 2241 keyword = uenum_next(keywordEnum, &keywordLen, &status); 2242 2243 /* fetch the displayKeywordValue */ 2244 displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status); 2245 if(status==U_BUFFER_OVERFLOW_ERROR){ 2246 status = U_ZERO_ERROR; 2247 displayKeywordValueLen++; /* for null termination */ 2248 displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR); 2249 displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status); 2250 if(U_FAILURE(status)){ 2251 log_err("uloc_getDisplayKeywordValue failed for keyword : %s in locale id: %s for display locale: %s with error : %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status)); 2252 break; 2253 } 2254 if(u_strncmp(displayKeywordValue, testCases[i].displayKeywordValue, displayKeywordValueLen)!=0){ 2255 if (status == U_USING_DEFAULT_WARNING) { 2256 log_data_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s with error : %s Perhaps you are missing data\n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status)); 2257 } else { 2258 log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s with error : %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status)); 2259 } 2260 break; 2261 } 2262 }else{ 2263 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status)); 2264 } 2265 free(displayKeywordValue); 2266 } 2267 uenum_close(keywordEnum); 2268 } 2269 { 2270 /* test a multiple keywords */ 2271 UErrorCode status = U_ZERO_ERROR; 2272 const char* keyword =NULL; 2273 int32_t keywordLen = 0; 2274 int32_t keywordCount = 0; 2275 const char* localeID = "es@collation=phonebook;calendar=buddhist;currency=DEM"; 2276 const char* displayLocale = "de"; 2277 static const UChar expected[][50] = { 2278 {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}, 2279 2280 {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}, 2281 {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000}, 2282 }; 2283 2284 UEnumeration* keywordEnum = uloc_openKeywords(localeID, &status); 2285 2286 for(keywordCount = 0; keywordCount < uenum_count(keywordEnum, &status) ; keywordCount++){ 2287 UChar *displayKeywordValue = NULL; 2288 int32_t displayKeywordValueLen = 0; 2289 if(U_FAILURE(status)){ 2290 log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID, displayLocale, u_errorName(status)); 2291 break; 2292 } 2293 /* the uenum_next returns NUL terminated string */ 2294 keyword = uenum_next(keywordEnum, &keywordLen, &status); 2295 2296 /* fetch the displayKeywordValue */ 2297 displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status); 2298 if(status==U_BUFFER_OVERFLOW_ERROR){ 2299 status = U_ZERO_ERROR; 2300 displayKeywordValueLen++; /* for null termination */ 2301 displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR); 2302 displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status); 2303 if(U_FAILURE(status)){ 2304 log_err("uloc_getDisplayKeywordValue failed for keyword : %s in locale id: %s for display locale: %s with error : %s \n", localeID, keyword, displayLocale, u_errorName(status)); 2305 break; 2306 } 2307 if(u_strncmp(displayKeywordValue, expected[keywordCount], displayKeywordValueLen)!=0){ 2308 if (status == U_USING_DEFAULT_WARNING) { 2309 log_data_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s got error: %s. Perhaps you are missing data?\n", localeID, keyword, displayLocale, u_errorName(status)); 2310 } else { 2311 log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID, keyword, displayLocale); 2312 } 2313 break; 2314 } 2315 }else{ 2316 log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status)); 2317 } 2318 free(displayKeywordValue); 2319 } 2320 uenum_close(keywordEnum); 2321 2322 } 2323 { 2324 /* Test non existent keywords */ 2325 UErrorCode status = U_ZERO_ERROR; 2326 const char* localeID = "es"; 2327 const char* displayLocale = "de"; 2328 UChar *displayKeywordValue = NULL; 2329 int32_t displayKeywordValueLen = 0; 2330 2331 /* fetch the displayKeywordValue */ 2332 displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, "calendar", displayLocale, displayKeywordValue, displayKeywordValueLen, &status); 2333 if(U_FAILURE(status)) { 2334 log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status)); 2335 } else if(displayKeywordValueLen != 0) { 2336 log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen); 2337 } 2338 } 2339 } 2340 2341 2342 static void TestGetBaseName(void) { 2343 static const struct { 2344 const char *localeID; 2345 const char *baseName; 2346 } testCases[] = { 2347 { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" }, 2348 { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" }, 2349 { "ja@calendar = buddhist", "ja" } 2350 }; 2351 2352 int32_t i = 0, baseNameLen = 0; 2353 char baseName[256]; 2354 UErrorCode status = U_ZERO_ERROR; 2355 2356 for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { 2357 baseNameLen = uloc_getBaseName(testCases[i].localeID, baseName, 256, &status); 2358 (void)baseNameLen; /* Suppress set but not used warning. */ 2359 if(strcmp(testCases[i].baseName, baseName)) { 2360 log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n", 2361 testCases[i].localeID, testCases[i].baseName, baseName); 2362 return; 2363 } 2364 } 2365 } 2366 2367 static void TestTrailingNull(void) { 2368 const char* localeId = "zh_Hans"; 2369 UChar buffer[128]; /* sufficient for this test */ 2370 int32_t len; 2371 UErrorCode status = U_ZERO_ERROR; 2372 int i; 2373 2374 len = uloc_getDisplayName(localeId, localeId, buffer, 128, &status); 2375 if (len > 128) { 2376 log_err("buffer too small"); 2377 return; 2378 } 2379 2380 for (i = 0; i < len; ++i) { 2381 if (buffer[i] == 0) { 2382 log_err("name contained null"); 2383 return; 2384 } 2385 } 2386 } 2387 2388 /* Jitterbug 4115 */ 2389 static void TestDisplayNameWarning(void) { 2390 UChar name[256]; 2391 int32_t size; 2392 UErrorCode status = U_ZERO_ERROR; 2393 2394 size = uloc_getDisplayLanguage("qqq", "kl", name, sizeof(name)/sizeof(name[0]), &status); 2395 (void)size; /* Suppress set but not used warning. */ 2396 if (status != U_USING_DEFAULT_WARNING) { 2397 log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n", 2398 u_errorName(status)); 2399 } 2400 } 2401 2402 2403 /** 2404 * Compare two locale IDs. If they are equal, return 0. If `string' 2405 * starts with `prefix' plus an additional element, that is, string == 2406 * prefix + '_' + x, then return 1. Otherwise return a value < 0. 2407 */ 2408 static UBool _loccmp(const char* string, const char* prefix) { 2409 int32_t slen = (int32_t)uprv_strlen(string), 2410 plen = (int32_t)uprv_strlen(prefix); 2411 int32_t c = uprv_strncmp(string, prefix, plen); 2412 /* 'root' is less than everything */ 2413 if (uprv_strcmp(prefix, "root") == 0) { 2414 return (uprv_strcmp(string, "root") == 0) ? 0 : 1; 2415 } 2416 if (c) return -1; /* mismatch */ 2417 if (slen == plen) return 0; 2418 if (string[plen] == '_') return 1; 2419 return -2; /* false match, e.g. "en_USX" cmp "en_US" */ 2420 } 2421 2422 static void _checklocs(const char* label, 2423 const char* req, 2424 const char* valid, 2425 const char* actual) { 2426 /* We want the valid to be strictly > the bogus requested locale, 2427 and the valid to be >= the actual. */ 2428 if (_loccmp(req, valid) > 0 && 2429 _loccmp(valid, actual) >= 0) { 2430 log_verbose("%s; req=%s, valid=%s, actual=%s\n", 2431 label, req, valid, actual); 2432 } else { 2433 log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n", 2434 label, req, valid, actual); 2435 } 2436 } 2437 2438 static void TestGetLocale(void) { 2439 UErrorCode ec = U_ZERO_ERROR; 2440 UParseError pe; 2441 UChar EMPTY[1] = {0}; 2442 2443 /* === udat === */ 2444 #if !UCONFIG_NO_FORMATTING 2445 { 2446 UDateFormat *obj; 2447 const char *req = "en_US_REDWOODSHORES", *valid, *actual; 2448 obj = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, 2449 req, 2450 NULL, 0, 2451 NULL, 0, &ec); 2452 if (U_FAILURE(ec)) { 2453 log_data_err("udat_open failed.Error %s\n", u_errorName(ec)); 2454 return; 2455 } 2456 valid = udat_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); 2457 actual = udat_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); 2458 if (U_FAILURE(ec)) { 2459 log_err("udat_getLocaleByType() failed\n"); 2460 return; 2461 } 2462 _checklocs("udat", req, valid, actual); 2463 udat_close(obj); 2464 } 2465 #endif 2466 2467 /* === ucal === */ 2468 #if !UCONFIG_NO_FORMATTING 2469 { 2470 UCalendar *obj; 2471 const char *req = "fr_FR_PROVENCAL", *valid, *actual; 2472 obj = ucal_open(NULL, 0, 2473 req, 2474 UCAL_GREGORIAN, 2475 &ec); 2476 if (U_FAILURE(ec)) { 2477 log_err("ucal_open failed with error: %s\n", u_errorName(ec)); 2478 return; 2479 } 2480 valid = ucal_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); 2481 actual = ucal_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); 2482 if (U_FAILURE(ec)) { 2483 log_err("ucal_getLocaleByType() failed\n"); 2484 return; 2485 } 2486 _checklocs("ucal", req, valid, actual); 2487 ucal_close(obj); 2488 } 2489 #endif 2490 2491 /* === unum === */ 2492 #if !UCONFIG_NO_FORMATTING 2493 { 2494 UNumberFormat *obj; 2495 const char *req = "zh_Hant_TW_TAINAN", *valid, *actual; 2496 obj = unum_open(UNUM_DECIMAL, 2497 NULL, 0, 2498 req, 2499 &pe, &ec); 2500 if (U_FAILURE(ec)) { 2501 log_err("unum_open failed\n"); 2502 return; 2503 } 2504 valid = unum_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); 2505 actual = unum_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); 2506 if (U_FAILURE(ec)) { 2507 log_err("unum_getLocaleByType() failed\n"); 2508 return; 2509 } 2510 _checklocs("unum", req, valid, actual); 2511 unum_close(obj); 2512 } 2513 #endif 2514 2515 /* === umsg === */ 2516 #if 0 2517 /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */ 2518 #if !UCONFIG_NO_FORMATTING 2519 { 2520 UMessageFormat *obj; 2521 const char *req = "ja_JP_TAKAYAMA", *valid, *actual; 2522 UBool test; 2523 obj = umsg_open(EMPTY, 0, 2524 req, 2525 &pe, &ec); 2526 if (U_FAILURE(ec)) { 2527 log_err("umsg_open failed\n"); 2528 return; 2529 } 2530 valid = umsg_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); 2531 actual = umsg_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); 2532 if (U_FAILURE(ec)) { 2533 log_err("umsg_getLocaleByType() failed\n"); 2534 return; 2535 } 2536 /* We want the valid to be strictly > the bogus requested locale, 2537 and the valid to be >= the actual. */ 2538 /* TODO MessageFormat is currently just storing the locale it is given. 2539 As a result, it will return whatever it was given, even if the 2540 locale is invalid. */ 2541 test = (_cmpversion("3.2") <= 0) ? 2542 /* Here is the weakened test for 3.0: */ 2543 (_loccmp(req, valid) >= 0) : 2544 /* Here is what the test line SHOULD be: */ 2545 (_loccmp(req, valid) > 0); 2546 2547 if (test && 2548 _loccmp(valid, actual) >= 0) { 2549 log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual); 2550 } else { 2551 log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual); 2552 } 2553 umsg_close(obj); 2554 } 2555 #endif 2556 #endif 2557 2558 /* === ubrk === */ 2559 #if !UCONFIG_NO_BREAK_ITERATION 2560 { 2561 UBreakIterator *obj; 2562 const char *req = "ar_KW_ABDALI", *valid, *actual; 2563 obj = ubrk_open(UBRK_WORD, 2564 req, 2565 EMPTY, 2566 0, 2567 &ec); 2568 if (U_FAILURE(ec)) { 2569 log_err("ubrk_open failed. Error: %s \n", u_errorName(ec)); 2570 return; 2571 } 2572 valid = ubrk_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); 2573 actual = ubrk_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); 2574 if (U_FAILURE(ec)) { 2575 log_err("ubrk_getLocaleByType() failed\n"); 2576 return; 2577 } 2578 _checklocs("ubrk", req, valid, actual); 2579 ubrk_close(obj); 2580 } 2581 #endif 2582 2583 /* === ucol === */ 2584 #if !UCONFIG_NO_COLLATION 2585 { 2586 UCollator *obj; 2587 const char *req = "es_AR_BUENOSAIRES", *valid, *actual; 2588 obj = ucol_open(req, &ec); 2589 if (U_FAILURE(ec)) { 2590 log_err("ucol_open failed - %s\n", u_errorName(ec)); 2591 return; 2592 } 2593 valid = ucol_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); 2594 actual = ucol_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); 2595 if (U_FAILURE(ec)) { 2596 log_err("ucol_getLocaleByType() failed\n"); 2597 return; 2598 } 2599 _checklocs("ucol", req, valid, actual); 2600 ucol_close(obj); 2601 } 2602 #endif 2603 } 2604 static void TestEnglishExemplarCharacters(void) { 2605 UErrorCode status = U_ZERO_ERROR; 2606 int i; 2607 USet *exSet = NULL; 2608 UChar testChars[] = { 2609 0x61, /* standard */ 2610 0xE1, /* auxiliary */ 2611 0x41, /* index */ 2612 0x2D /* punctuation */ 2613 }; 2614 ULocaleData *uld = ulocdata_open("en", &status); 2615 if (U_FAILURE(status)) { 2616 log_data_err("ulocdata_open() failed : %s - (Are you missing data?)\n", u_errorName(status)); 2617 return; 2618 } 2619 2620 for (i = 0; i < ULOCDATA_ES_COUNT; i++) { 2621 exSet = ulocdata_getExemplarSet(uld, exSet, 0, (ULocaleDataExemplarSetType)i, &status); 2622 if (U_FAILURE(status)) { 2623 log_err_status(status, "ulocdata_getExemplarSet() for type %d failed\n", i); 2624 status = U_ZERO_ERROR; 2625 continue; 2626 } 2627 if (!uset_contains(exSet, (UChar32)testChars[i])) { 2628 log_err("Character U+%04X is not included in exemplar type %d\n", testChars[i], i); 2629 } 2630 } 2631 2632 uset_close(exSet); 2633 ulocdata_close(uld); 2634 } 2635 2636 static void TestNonexistentLanguageExemplars(void) { 2637 /* JB 4068 - Nonexistent language */ 2638 UErrorCode ec = U_ZERO_ERROR; 2639 ULocaleData *uld = ulocdata_open("qqq",&ec); 2640 if (ec != U_USING_DEFAULT_WARNING) { 2641 log_err_status(ec, "Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n", 2642 u_errorName(ec)); 2643 } 2644 uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec)); 2645 ulocdata_close(uld); 2646 } 2647 2648 static void TestLocDataErrorCodeChaining(void) { 2649 UErrorCode ec = U_USELESS_COLLATOR_ERROR; 2650 ulocdata_open(NULL, &ec); 2651 ulocdata_getExemplarSet(NULL, NULL, 0, ULOCDATA_ES_STANDARD, &ec); 2652 ulocdata_getDelimiter(NULL, ULOCDATA_DELIMITER_COUNT, NULL, -1, &ec); 2653 ulocdata_getMeasurementSystem(NULL, &ec); 2654 ulocdata_getPaperSize(NULL, NULL, NULL, &ec); 2655 if (ec != U_USELESS_COLLATOR_ERROR) { 2656 log_err("ulocdata API changed the error code to %s\n", u_errorName(ec)); 2657 } 2658 } 2659 2660 static void TestLanguageExemplarsFallbacks(void) { 2661 /* Test that en_US fallsback, but en doesn't fallback. */ 2662 UErrorCode ec = U_ZERO_ERROR; 2663 ULocaleData *uld = ulocdata_open("en_US",&ec); 2664 uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec)); 2665 if (ec != U_USING_FALLBACK_WARNING) { 2666 log_err_status(ec, "Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n", 2667 u_errorName(ec)); 2668 } 2669 ulocdata_close(uld); 2670 ec = U_ZERO_ERROR; 2671 uld = ulocdata_open("en",&ec); 2672 uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec)); 2673 if (ec != U_ZERO_ERROR) { 2674 log_err_status(ec, "Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n", 2675 u_errorName(ec)); 2676 } 2677 ulocdata_close(uld); 2678 } 2679 2680 static const char *acceptResult(UAcceptResult uar) { 2681 return udbg_enumName(UDBG_UAcceptResult, uar); 2682 } 2683 2684 static void TestAcceptLanguage(void) { 2685 UErrorCode status = U_ZERO_ERROR; 2686 UAcceptResult outResult; 2687 UEnumeration *available; 2688 char tmp[200]; 2689 int i; 2690 int32_t rc = 0; 2691 2692 struct { 2693 int32_t httpSet; /**< Which of http[] should be used? */ 2694 const char *icuSet; /**< ? */ 2695 const char *expect; /**< The expected locale result */ 2696 UAcceptResult res; /**< The expected error code */ 2697 } tests[] = { 2698 /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID }, 2699 /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID }, 2700 /*2*/{ 2, NULL, "en", ULOC_ACCEPT_FALLBACK }, 2701 /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED }, 2702 /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID }, 2703 2704 /*5*/{ 5, NULL, "en", ULOC_ACCEPT_VALID }, /* XF */ 2705 /*6*/{ 6, NULL, "ja", ULOC_ACCEPT_FALLBACK }, /* XF */ 2706 /*7*/{ 7, NULL, "zh", ULOC_ACCEPT_FALLBACK }, /* XF */ 2707 }; 2708 const int32_t numTests = sizeof(tests)/sizeof(tests[0]); 2709 static const char *http[] = { 2710 /*0*/ "mt-mt, ja;q=0.76, en-us;q=0.95, en;q=0.92, en-gb;q=0.89, fr;q=0.87, iu-ca;q=0.84, iu;q=0.82, ja-jp;q=0.79, mt;q=0.97, de-de;q=0.74, de;q=0.71, es;q=0.68, it-it;q=0.66, it;q=0.63, vi-vn;q=0.61, vi;q=0.58, nl-nl;q=0.55, nl;q=0.53, th-th-traditional;q=.01", 2711 /*1*/ "ja;q=0.5, en;q=0.8, tlh", 2712 /*2*/ "en-wf, de-lx;q=0.8", 2713 /*3*/ "mga-ie;q=0.9, tlh", 2714 /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, " 2715 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, " 2716 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, " 2717 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, " 2718 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, " 2719 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, " 2720 "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, " 2721 "es", 2722 2723 /*5*/ "zh-xx;q=0.9, en;q=0.6", 2724 /*6*/ "ja-JA", 2725 /*7*/ "zh-xx;q=0.9", 2726 }; 2727 2728 for(i=0;i<numTests;i++) { 2729 outResult = -3; 2730 status=U_ZERO_ERROR; 2731 log_verbose("test #%d: http[%s], ICU[%s], expect %s, %s\n", 2732 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res)); 2733 2734 available = ures_openAvailableLocales(tests[i].icuSet, &status); 2735 tmp[0]=0; 2736 rc = uloc_acceptLanguageFromHTTP(tmp, 199, &outResult, http[tests[i].httpSet], available, &status); 2737 (void)rc; /* Suppress set but not used warning. */ 2738 uenum_close(available); 2739 log_verbose(" got %s, %s [%s]\n", tmp[0]?tmp:"(EMPTY)", acceptResult(outResult), u_errorName(status)); 2740 if(outResult != tests[i].res) { 2741 log_err_status(status, "FAIL: #%d: expected outResult of %s but got %s\n", i, 2742 acceptResult( tests[i].res), 2743 acceptResult( outResult)); 2744 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n", 2745 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect,acceptResult(tests[i].res)); 2746 } 2747 if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) { 2748 log_err_status(status, "FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp); 2749 log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n", 2750 i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res)); 2751 } 2752 } 2753 } 2754 2755 static const char* LOCALE_ALIAS[][2] = { 2756 {"in", "id"}, 2757 {"in_ID", "id_ID"}, 2758 {"iw", "he"}, 2759 {"iw_IL", "he_IL"}, 2760 {"ji", "yi"}, 2761 {"en_BU", "en_MM"}, 2762 {"en_DY", "en_BJ"}, 2763 {"en_HV", "en_BF"}, 2764 {"en_NH", "en_VU"}, 2765 {"en_RH", "en_ZW"}, 2766 {"en_TP", "en_TL"}, 2767 {"en_ZR", "en_CD"} 2768 }; 2769 static UBool isLocaleAvailable(UResourceBundle* resIndex, const char* loc){ 2770 UErrorCode status = U_ZERO_ERROR; 2771 int32_t len = 0; 2772 ures_getStringByKey(resIndex, loc,&len, &status); 2773 if(U_FAILURE(status)){ 2774 return FALSE; 2775 } 2776 return TRUE; 2777 } 2778 2779 static void TestCalendar() { 2780 #if !UCONFIG_NO_FORMATTING 2781 int i; 2782 UErrorCode status = U_ZERO_ERROR; 2783 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status); 2784 if(U_FAILURE(status)){ 2785 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); 2786 return; 2787 } 2788 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) { 2789 const char* oldLoc = LOCALE_ALIAS[i][0]; 2790 const char* newLoc = LOCALE_ALIAS[i][1]; 2791 UCalendar* c1 = NULL; 2792 UCalendar* c2 = NULL; 2793 2794 /*Test function "getLocale(ULocale.VALID_LOCALE)"*/ 2795 const char* l1 = ucal_getLocaleByType(c1, ULOC_VALID_LOCALE, &status); 2796 const char* l2 = ucal_getLocaleByType(c2, ULOC_VALID_LOCALE, &status); 2797 2798 if(!isLocaleAvailable(resIndex, newLoc)){ 2799 continue; 2800 } 2801 c1 = ucal_open(NULL, -1, oldLoc, UCAL_GREGORIAN, &status); 2802 c2 = ucal_open(NULL, -1, newLoc, UCAL_GREGORIAN, &status); 2803 2804 if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0 || status!=U_ZERO_ERROR) { 2805 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); 2806 } 2807 log_verbose("ucal_getLocaleByType old:%s new:%s\n", l1, l2); 2808 ucal_close(c1); 2809 ucal_close(c2); 2810 } 2811 ures_close(resIndex); 2812 #endif 2813 } 2814 2815 static void TestDateFormat() { 2816 #if !UCONFIG_NO_FORMATTING 2817 int i; 2818 UErrorCode status = U_ZERO_ERROR; 2819 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status); 2820 if(U_FAILURE(status)){ 2821 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); 2822 return; 2823 } 2824 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) { 2825 const char* oldLoc = LOCALE_ALIAS[i][0]; 2826 const char* newLoc = LOCALE_ALIAS[i][1]; 2827 UDateFormat* df1 = NULL; 2828 UDateFormat* df2 = NULL; 2829 const char* l1 = NULL; 2830 const char* l2 = NULL; 2831 2832 if(!isLocaleAvailable(resIndex, newLoc)){ 2833 continue; 2834 } 2835 df1 = udat_open(UDAT_FULL, UDAT_FULL,oldLoc, NULL, 0, NULL, -1, &status); 2836 df2 = udat_open(UDAT_FULL, UDAT_FULL,newLoc, NULL, 0, NULL, -1, &status); 2837 if(U_FAILURE(status)){ 2838 log_err("Creation of date format failed %s\n", u_errorName(status)); 2839 return; 2840 } 2841 /*Test function "getLocale"*/ 2842 l1 = udat_getLocaleByType(df1, ULOC_VALID_LOCALE, &status); 2843 l2 = udat_getLocaleByType(df2, ULOC_VALID_LOCALE, &status); 2844 if(U_FAILURE(status)){ 2845 log_err("Fetching the locale by type failed. %s\n", u_errorName(status)); 2846 } 2847 if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) { 2848 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); 2849 } 2850 log_verbose("udat_getLocaleByType old:%s new:%s\n", l1, l2); 2851 udat_close(df1); 2852 udat_close(df2); 2853 } 2854 ures_close(resIndex); 2855 #endif 2856 } 2857 2858 static void TestCollation() { 2859 #if !UCONFIG_NO_COLLATION 2860 int i; 2861 UErrorCode status = U_ZERO_ERROR; 2862 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status); 2863 if(U_FAILURE(status)){ 2864 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); 2865 return; 2866 } 2867 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) { 2868 const char* oldLoc = LOCALE_ALIAS[i][0]; 2869 const char* newLoc = LOCALE_ALIAS[i][1]; 2870 UCollator* c1 = NULL; 2871 UCollator* c2 = NULL; 2872 const char* l1 = NULL; 2873 const char* l2 = NULL; 2874 2875 status = U_ZERO_ERROR; 2876 if(!isLocaleAvailable(resIndex, newLoc)){ 2877 continue; 2878 } 2879 if(U_FAILURE(status)){ 2880 log_err("Creation of collators failed %s\n", u_errorName(status)); 2881 return; 2882 } 2883 c1 = ucol_open(oldLoc, &status); 2884 c2 = ucol_open(newLoc, &status); 2885 l1 = ucol_getLocaleByType(c1, ULOC_VALID_LOCALE, &status); 2886 l2 = ucol_getLocaleByType(c2, ULOC_VALID_LOCALE, &status); 2887 if(U_FAILURE(status)){ 2888 log_err("Fetching the locale names failed failed %s\n", u_errorName(status)); 2889 } 2890 if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) { 2891 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); 2892 } 2893 log_verbose("ucol_getLocaleByType old:%s new:%s\n", l1, l2); 2894 ucol_close(c1); 2895 ucol_close(c2); 2896 } 2897 ures_close(resIndex); 2898 #endif 2899 } 2900 2901 typedef struct OrientationStructTag { 2902 const char* localeId; 2903 ULayoutType character; 2904 ULayoutType line; 2905 } OrientationStruct; 2906 2907 static const char* ULayoutTypeToString(ULayoutType type) 2908 { 2909 switch(type) 2910 { 2911 case ULOC_LAYOUT_LTR: 2912 return "ULOC_LAYOUT_LTR"; 2913 break; 2914 case ULOC_LAYOUT_RTL: 2915 return "ULOC_LAYOUT_RTL"; 2916 break; 2917 case ULOC_LAYOUT_TTB: 2918 return "ULOC_LAYOUT_TTB"; 2919 break; 2920 case ULOC_LAYOUT_BTT: 2921 return "ULOC_LAYOUT_BTT"; 2922 break; 2923 case ULOC_LAYOUT_UNKNOWN: 2924 break; 2925 } 2926 2927 return "Unknown enum value for ULayoutType!"; 2928 } 2929 2930 static void TestOrientation() 2931 { 2932 static const OrientationStruct toTest [] = { 2933 { "ar", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, 2934 { "aR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, 2935 { "ar_Arab", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, 2936 { "fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, 2937 { "Fa", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, 2938 { "he", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, 2939 { "ps", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, 2940 { "ur", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, 2941 { "UR", ULOC_LAYOUT_RTL, ULOC_LAYOUT_TTB }, 2942 { "en", ULOC_LAYOUT_LTR, ULOC_LAYOUT_TTB } 2943 }; 2944 2945 size_t i = 0; 2946 for (; i < sizeof(toTest) / sizeof(toTest[0]); ++i) { 2947 UErrorCode statusCO = U_ZERO_ERROR; 2948 UErrorCode statusLO = U_ZERO_ERROR; 2949 const char* const localeId = toTest[i].localeId; 2950 const ULayoutType co = uloc_getCharacterOrientation(localeId, &statusCO); 2951 const ULayoutType expectedCO = toTest[i].character; 2952 const ULayoutType lo = uloc_getLineOrientation(localeId, &statusLO); 2953 const ULayoutType expectedLO = toTest[i].line; 2954 if (U_FAILURE(statusCO)) { 2955 log_err_status(statusCO, 2956 " unexpected failure for uloc_getCharacterOrientation(), with localId \"%s\" and status %s\n", 2957 localeId, 2958 u_errorName(statusCO)); 2959 } 2960 else if (co != expectedCO) { 2961 log_err( 2962 " unexpected result for uloc_getCharacterOrientation(), with localeId \"%s\". Expected %s but got result %s\n", 2963 localeId, 2964 ULayoutTypeToString(expectedCO), 2965 ULayoutTypeToString(co)); 2966 } 2967 if (U_FAILURE(statusLO)) { 2968 log_err_status(statusLO, 2969 " unexpected failure for uloc_getLineOrientation(), with localId \"%s\" and status %s\n", 2970 localeId, 2971 u_errorName(statusLO)); 2972 } 2973 else if (lo != expectedLO) { 2974 log_err( 2975 " unexpected result for uloc_getLineOrientation(), with localeId \"%s\". Expected %s but got result %s\n", 2976 localeId, 2977 ULayoutTypeToString(expectedLO), 2978 ULayoutTypeToString(lo)); 2979 } 2980 } 2981 } 2982 2983 static void TestULocale() { 2984 int i; 2985 UErrorCode status = U_ZERO_ERROR; 2986 UResourceBundle *resIndex = ures_open(NULL,"res_index", &status); 2987 if(U_FAILURE(status)){ 2988 log_err_status(status, "Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); 2989 return; 2990 } 2991 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) { 2992 const char* oldLoc = LOCALE_ALIAS[i][0]; 2993 const char* newLoc = LOCALE_ALIAS[i][1]; 2994 UChar name1[256], name2[256]; 2995 char names1[256], names2[256]; 2996 int32_t capacity = 256; 2997 2998 status = U_ZERO_ERROR; 2999 if(!isLocaleAvailable(resIndex, newLoc)){ 3000 continue; 3001 } 3002 uloc_getDisplayName(oldLoc, ULOC_US, name1, capacity, &status); 3003 if(U_FAILURE(status)){ 3004 log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc, u_errorName(status)); 3005 } 3006 3007 uloc_getDisplayName(newLoc, ULOC_US, name2, capacity, &status); 3008 if(U_FAILURE(status)){ 3009 log_err("uloc_getDisplayName(%s) failed %s\n", newLoc, u_errorName(status)); 3010 } 3011 3012 if (u_strcmp(name1, name2)!=0) { 3013 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); 3014 } 3015 u_austrcpy(names1, name1); 3016 u_austrcpy(names2, name2); 3017 log_verbose("uloc_getDisplayName old:%s new:%s\n", names1, names2); 3018 } 3019 ures_close(resIndex); 3020 3021 } 3022 3023 static void TestUResourceBundle() { 3024 const char* us1; 3025 const char* us2; 3026 3027 UResourceBundle* rb1 = NULL; 3028 UResourceBundle* rb2 = NULL; 3029 UErrorCode status = U_ZERO_ERROR; 3030 int i; 3031 UResourceBundle *resIndex = NULL; 3032 if(U_FAILURE(status)){ 3033 log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); 3034 return; 3035 } 3036 resIndex = ures_open(NULL,"res_index", &status); 3037 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) { 3038 3039 const char* oldLoc = LOCALE_ALIAS[i][0]; 3040 const char* newLoc = LOCALE_ALIAS[i][1]; 3041 if(!isLocaleAvailable(resIndex, newLoc)){ 3042 continue; 3043 } 3044 rb1 = ures_open(NULL, oldLoc, &status); 3045 if (U_FAILURE(status)) { 3046 log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status)); 3047 } 3048 3049 us1 = ures_getLocaleByType(rb1, ULOC_ACTUAL_LOCALE, &status); 3050 3051 status = U_ZERO_ERROR; 3052 rb2 = ures_open(NULL, newLoc, &status); 3053 if (U_FAILURE(status)) { 3054 log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status)); 3055 } 3056 us2 = ures_getLocaleByType(rb2, ULOC_ACTUAL_LOCALE, &status); 3057 3058 if (strcmp(us1,newLoc)!=0 || strcmp(us1,us2)!=0 ) { 3059 log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); 3060 } 3061 3062 log_verbose("ures_getStringByKey old:%s new:%s\n", us1, us2); 3063 ures_close(rb1); 3064 rb1 = NULL; 3065 ures_close(rb2); 3066 rb2 = NULL; 3067 } 3068 ures_close(resIndex); 3069 } 3070 3071 static void TestDisplayName() { 3072 3073 UChar oldCountry[256] = {'\0'}; 3074 UChar newCountry[256] = {'\0'}; 3075 UChar oldLang[256] = {'\0'}; 3076 UChar newLang[256] = {'\0'}; 3077 char country[256] ={'\0'}; 3078 char language[256] ={'\0'}; 3079 int32_t capacity = 256; 3080 int i =0; 3081 int j=0; 3082 for (i=0; i<UPRV_LENGTHOF(LOCALE_ALIAS); i++) { 3083 const char* oldLoc = LOCALE_ALIAS[i][0]; 3084 const char* newLoc = LOCALE_ALIAS[i][1]; 3085 UErrorCode status = U_ZERO_ERROR; 3086 int32_t available = uloc_countAvailable(); 3087 3088 for(j=0; j<available; j++){ 3089 3090 const char* dispLoc = uloc_getAvailable(j); 3091 int32_t oldCountryLen = uloc_getDisplayCountry(oldLoc,dispLoc, oldCountry, capacity, &status); 3092 int32_t newCountryLen = uloc_getDisplayCountry(newLoc, dispLoc, newCountry, capacity, &status); 3093 int32_t oldLangLen = uloc_getDisplayLanguage(oldLoc, dispLoc, oldLang, capacity, &status); 3094 int32_t newLangLen = uloc_getDisplayLanguage(newLoc, dispLoc, newLang, capacity, &status ); 3095 3096 int32_t countryLen = uloc_getCountry(newLoc, country, capacity, &status); 3097 int32_t langLen = uloc_getLanguage(newLoc, language, capacity, &status); 3098 /* there is a display name for the current country ID */ 3099 if(countryLen != newCountryLen ){ 3100 if(u_strncmp(oldCountry,newCountry,oldCountryLen)!=0){ 3101 log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc, dispLoc); 3102 } 3103 } 3104 /* there is a display name for the current lang ID */ 3105 if(langLen!=newLangLen){ 3106 if(u_strncmp(oldLang,newLang,oldLangLen)){ 3107 log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc, dispLoc); } 3108 } 3109 } 3110 } 3111 } 3112 3113 static void TestGetLocaleForLCID() { 3114 int32_t i, length, lengthPre; 3115 const char* testLocale = 0; 3116 UErrorCode status = U_ZERO_ERROR; 3117 char temp2[40], temp3[40]; 3118 uint32_t lcid; 3119 3120 lcid = uloc_getLCID("en_US"); 3121 if (lcid != 0x0409) { 3122 log_err(" uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid); 3123 } 3124 3125 lengthPre = uloc_getLocaleForLCID(lcid, temp2, 4, &status); 3126 if (status != U_BUFFER_OVERFLOW_ERROR) { 3127 log_err(" unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status)); 3128 } 3129 else { 3130 status = U_ZERO_ERROR; 3131 } 3132 3133 length = uloc_getLocaleForLCID(lcid, temp2, sizeof(temp2)/sizeof(char), &status); 3134 if (U_FAILURE(status)) { 3135 log_err(" unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status)); 3136 status = U_ZERO_ERROR; 3137 } 3138 3139 if (length != lengthPre) { 3140 log_err(" uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length, lengthPre); 3141 } 3142 3143 length = uloc_getLocaleForLCID(0x12345, temp2, sizeof(temp2)/sizeof(char), &status); 3144 if (U_SUCCESS(status)) { 3145 log_err(" unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2, u_errorName(status)); 3146 } 3147 status = U_ZERO_ERROR; 3148 3149 log_verbose("Testing getLocaleForLCID vs. locale data\n"); 3150 for (i = 0; i < LOCALE_SIZE; i++) { 3151 3152 testLocale=rawData2[NAME][i]; 3153 3154 log_verbose("Testing %s ......\n", testLocale); 3155 3156 sscanf(rawData2[LCID][i], "%x", &lcid); 3157 length = uloc_getLocaleForLCID(lcid, temp2, sizeof(temp2)/sizeof(char), &status); 3158 if (U_FAILURE(status)) { 3159 log_err(" unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid, u_errorName(status)); 3160 status = U_ZERO_ERROR; 3161 continue; 3162 } 3163 3164 if (length != uprv_strlen(temp2)) { 3165 log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length, lcid, uprv_strlen(temp2)); 3166 } 3167 3168 /* Compare language, country, script */ 3169 length = uloc_getLanguage(temp2, temp3, sizeof(temp3)/sizeof(char), &status); 3170 if (U_FAILURE(status)) { 3171 log_err(" couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status)); 3172 status = U_ZERO_ERROR; 3173 } 3174 else if (uprv_strcmp(temp3, rawData2[LANG][i]) && !(uprv_strcmp(temp3, "nn") == 0 && uprv_strcmp(rawData2[VAR][i], "NY") == 0)) { 3175 log_err(" language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[LANG][i], lcid, temp2); 3176 } 3177 3178 length = uloc_getScript(temp2, temp3, sizeof(temp3)/sizeof(char), &status); 3179 if (U_FAILURE(status)) { 3180 log_err(" couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status)); 3181 status = U_ZERO_ERROR; 3182 } 3183 else if (uprv_strcmp(temp3, rawData2[SCRIPT][i])) { 3184 log_err(" script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[SCRIPT][i], lcid, temp2); 3185 } 3186 3187 length = uloc_getCountry(temp2, temp3, sizeof(temp3)/sizeof(char), &status); 3188 if (U_FAILURE(status)) { 3189 log_err(" couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status)); 3190 status = U_ZERO_ERROR; 3191 } 3192 else if (uprv_strlen(rawData2[CTRY][i]) && uprv_strcmp(temp3, rawData2[CTRY][i])) { 3193 log_err(" country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[CTRY][i], lcid, temp2); 3194 } 3195 } 3196 3197 } 3198 3199 const char* const basic_maximize_data[][2] = { 3200 { 3201 "zu_Zzzz_Zz", 3202 "zu_Latn_ZA", 3203 }, { 3204 "ZU_Zz", 3205 "zu_Latn_ZA" 3206 }, { 3207 "zu_LATN", 3208 "zu_Latn_ZA" 3209 }, { 3210 "en_Zz", 3211 "en_Latn_US" 3212 }, { 3213 "en_us", 3214 "en_Latn_US" 3215 }, { 3216 "en_Kore", 3217 "en_Kore_US" 3218 }, { 3219 "en_Kore_Zz", 3220 "en_Kore_US" 3221 }, { 3222 "en_Kore_ZA", 3223 "en_Kore_ZA" 3224 }, { 3225 "en_Kore_ZA_POSIX", 3226 "en_Kore_ZA_POSIX" 3227 }, { 3228 "en_Gujr", 3229 "en_Gujr_US" 3230 }, { 3231 "en_ZA", 3232 "en_Latn_ZA" 3233 }, { 3234 "en_Gujr_Zz", 3235 "en_Gujr_US" 3236 }, { 3237 "en_Gujr_ZA", 3238 "en_Gujr_ZA" 3239 }, { 3240 "en_Gujr_ZA_POSIX", 3241 "en_Gujr_ZA_POSIX" 3242 }, { 3243 "en_US_POSIX_1901", 3244 "en_Latn_US_POSIX_1901" 3245 }, { 3246 "en_Latn__POSIX_1901", 3247 "en_Latn_US_POSIX_1901" 3248 }, { 3249 "en__POSIX_1901", 3250 "en_Latn_US_POSIX_1901" 3251 }, { 3252 "de__POSIX_1901", 3253 "de_Latn_DE_POSIX_1901" 3254 }, { 3255 "en_US_BOSTON", 3256 "en_Latn_US_BOSTON" 3257 }, { 3258 "th@calendar=buddhist", 3259 "th_Thai_TH@calendar=buddhist" 3260 }, { 3261 "ar_ZZ", 3262 "ar_Arab_EG" 3263 }, { 3264 "zh", 3265 "zh_Hans_CN" 3266 }, { 3267 "zh_TW", 3268 "zh_Hant_TW" 3269 }, { 3270 "zh_HK", 3271 "zh_Hant_HK" 3272 }, { 3273 "zh_Hant", 3274 "zh_Hant_TW" 3275 }, { 3276 "zh_Zzzz_CN", 3277 "zh_Hans_CN" 3278 }, { 3279 "und_US", 3280 "en_Latn_US" 3281 }, { 3282 "und_HK", 3283 "zh_Hant_HK" 3284 }, { 3285 "zzz", 3286 "" 3287 }, { 3288 "de_u_co_phonebk", 3289 "de_Latn_DE_U_CO_PHONEBK" 3290 }, { 3291 "de_Latn_u_co_phonebk", 3292 "de_Latn_DE_U_CO_PHONEBK" 3293 }, { 3294 "de_Latn_DE_u_co_phonebk", 3295 "de_Latn_DE_U_CO_PHONEBK" 3296 } 3297 }; 3298 3299 const char* const basic_minimize_data[][2] = { 3300 { 3301 "en_Latn_US", 3302 "en" 3303 }, { 3304 "en_Latn_US_POSIX_1901", 3305 "en__POSIX_1901" 3306 }, { 3307 "EN_Latn_US_POSIX_1901", 3308 "en__POSIX_1901" 3309 }, { 3310 "en_Zzzz_US_POSIX_1901", 3311 "en__POSIX_1901" 3312 }, { 3313 "de_Latn_DE_POSIX_1901", 3314 "de__POSIX_1901" 3315 }, { 3316 "und", 3317 "" 3318 }, { 3319 "en_Latn_US@calendar=gregorian", 3320 "en@calendar=gregorian" 3321 } 3322 }; 3323 3324 const char* const full_data[][3] = { 3325 { 3326 /* "FROM", */ 3327 /* "ADD-LIKELY", */ 3328 /* "REMOVE-LIKELY" */ 3329 /* }, { */ 3330 "aa", 3331 "aa_Latn_ET", 3332 "aa" 3333 }, { 3334 "af", 3335 "af_Latn_ZA", 3336 "af" 3337 }, { 3338 "ak", 3339 "ak_Latn_GH", 3340 "ak" 3341 }, { 3342 "am", 3343 "am_Ethi_ET", 3344 "am" 3345 }, { 3346 "ar", 3347 "ar_Arab_EG", 3348 "ar" 3349 }, { 3350 "as", 3351 "as_Beng_IN", 3352 "as" 3353 }, { 3354 "az", 3355 "az_Latn_AZ", 3356 "az" 3357 }, { 3358 "be", 3359 "be_Cyrl_BY", 3360 "be" 3361 }, { 3362 "bg", 3363 "bg_Cyrl_BG", 3364 "bg" 3365 }, { 3366 "bn", 3367 "bn_Beng_BD", 3368 "bn" 3369 }, { 3370 "bo", 3371 "bo_Tibt_CN", 3372 "bo" 3373 }, { 3374 "bs", 3375 "bs_Latn_BA", 3376 "bs" 3377 }, { 3378 "ca", 3379 "ca_Latn_ES", 3380 "ca" 3381 }, { 3382 "ch", 3383 "ch_Latn_GU", 3384 "ch" 3385 }, { 3386 "chk", 3387 "chk_Latn_FM", 3388 "chk" 3389 }, { 3390 "cs", 3391 "cs_Latn_CZ", 3392 "cs" 3393 }, { 3394 "cy", 3395 "cy_Latn_GB", 3396 "cy" 3397 }, { 3398 "da", 3399 "da_Latn_DK", 3400 "da" 3401 }, { 3402 "de", 3403 "de_Latn_DE", 3404 "de" 3405 }, { 3406 "dv", 3407 "dv_Thaa_MV", 3408 "dv" 3409 }, { 3410 "dz", 3411 "dz_Tibt_BT", 3412 "dz" 3413 }, { 3414 "ee", 3415 "ee_Latn_GH", 3416 "ee" 3417 }, { 3418 "el", 3419 "el_Grek_GR", 3420 "el" 3421 }, { 3422 "en", 3423 "en_Latn_US", 3424 "en" 3425 }, { 3426 "es", 3427 "es_Latn_ES", 3428 "es" 3429 }, { 3430 "et", 3431 "et_Latn_EE", 3432 "et" 3433 }, { 3434 "eu", 3435 "eu_Latn_ES", 3436 "eu" 3437 }, { 3438 "fa", 3439 "fa_Arab_IR", 3440 "fa" 3441 }, { 3442 "fi", 3443 "fi_Latn_FI", 3444 "fi" 3445 }, { 3446 "fil", 3447 "fil_Latn_PH", 3448 "fil" 3449 }, { 3450 "fo", 3451 "fo_Latn_FO", 3452 "fo" 3453 }, { 3454 "fr", 3455 "fr_Latn_FR", 3456 "fr" 3457 }, { 3458 "fur", 3459 "fur_Latn_IT", 3460 "fur" 3461 }, { 3462 "ga", 3463 "ga_Latn_IE", 3464 "ga" 3465 }, { 3466 "gaa", 3467 "gaa_Latn_GH", 3468 "gaa" 3469 }, { 3470 "gl", 3471 "gl_Latn_ES", 3472 "gl" 3473 }, { 3474 "gn", 3475 "gn_Latn_PY", 3476 "gn" 3477 }, { 3478 "gu", 3479 "gu_Gujr_IN", 3480 "gu" 3481 }, { 3482 "ha", 3483 "ha_Latn_NG", 3484 "ha" 3485 }, { 3486 "haw", 3487 "haw_Latn_US", 3488 "haw" 3489 }, { 3490 "he", 3491 "he_Hebr_IL", 3492 "he" 3493 }, { 3494 "hi", 3495 "hi_Deva_IN", 3496 "hi" 3497 }, { 3498 "hr", 3499 "hr_Latn_HR", 3500 "hr" 3501 }, { 3502 "ht", 3503 "ht_Latn_HT", 3504 "ht" 3505 }, { 3506 "hu", 3507 "hu_Latn_HU", 3508 "hu" 3509 }, { 3510 "hy", 3511 "hy_Armn_AM", 3512 "hy" 3513 }, { 3514 "id", 3515 "id_Latn_ID", 3516 "id" 3517 }, { 3518 "ig", 3519 "ig_Latn_NG", 3520 "ig" 3521 }, { 3522 "ii", 3523 "ii_Yiii_CN", 3524 "ii" 3525 }, { 3526 "is", 3527 "is_Latn_IS", 3528 "is" 3529 }, { 3530 "it", 3531 "it_Latn_IT", 3532 "it" 3533 }, { 3534 "ja", 3535 "ja_Jpan_JP", 3536 "ja" 3537 }, { 3538 "ka", 3539 "ka_Geor_GE", 3540 "ka" 3541 }, { 3542 "kaj", 3543 "kaj_Latn_NG", 3544 "kaj" 3545 }, { 3546 "kam", 3547 "kam_Latn_KE", 3548 "kam" 3549 }, { 3550 "kk", 3551 "kk_Cyrl_KZ", 3552 "kk" 3553 }, { 3554 "kl", 3555 "kl_Latn_GL", 3556 "kl" 3557 }, { 3558 "km", 3559 "km_Khmr_KH", 3560 "km" 3561 }, { 3562 "kn", 3563 "kn_Knda_IN", 3564 "kn" 3565 }, { 3566 "ko", 3567 "ko_Kore_KR", 3568 "ko" 3569 }, { 3570 "kok", 3571 "kok_Deva_IN", 3572 "kok" 3573 }, { 3574 "kpe", 3575 "kpe_Latn_LR", 3576 "kpe" 3577 }, { 3578 "ku", 3579 "ku_Latn_TR", 3580 "ku" 3581 }, { 3582 "ky", 3583 "ky_Cyrl_KG", 3584 "ky" 3585 }, { 3586 "la", 3587 "la_Latn_VA", 3588 "la" 3589 }, { 3590 "ln", 3591 "ln_Latn_CD", 3592 "ln" 3593 }, { 3594 "lo", 3595 "lo_Laoo_LA", 3596 "lo" 3597 }, { 3598 "lt", 3599 "lt_Latn_LT", 3600 "lt" 3601 }, { 3602 "lv", 3603 "lv_Latn_LV", 3604 "lv" 3605 }, { 3606 "mg", 3607 "mg_Latn_MG", 3608 "mg" 3609 }, { 3610 "mh", 3611 "mh_Latn_MH", 3612 "mh" 3613 }, { 3614 "mk", 3615 "mk_Cyrl_MK", 3616 "mk" 3617 }, { 3618 "ml", 3619 "ml_Mlym_IN", 3620 "ml" 3621 }, { 3622 "mn", 3623 "mn_Cyrl_MN", 3624 "mn" 3625 }, { 3626 "mr", 3627 "mr_Deva_IN", 3628 "mr" 3629 }, { 3630 "ms", 3631 "ms_Latn_MY", 3632 "ms" 3633 }, { 3634 "mt", 3635 "mt_Latn_MT", 3636 "mt" 3637 }, { 3638 "my", 3639 "my_Mymr_MM", 3640 "my" 3641 }, { 3642 "na", 3643 "na_Latn_NR", 3644 "na" 3645 }, { 3646 "ne", 3647 "ne_Deva_NP", 3648 "ne" 3649 }, { 3650 "niu", 3651 "niu_Latn_NU", 3652 "niu" 3653 }, { 3654 "nl", 3655 "nl_Latn_NL", 3656 "nl" 3657 }, { 3658 "nn", 3659 "nn_Latn_NO", 3660 "nn" 3661 }, { 3662 "nr", 3663 "nr_Latn_ZA", 3664 "nr" 3665 }, { 3666 "nso", 3667 "nso_Latn_ZA", 3668 "nso" 3669 }, { 3670 "ny", 3671 "ny_Latn_MW", 3672 "ny" 3673 }, { 3674 "om", 3675 "om_Latn_ET", 3676 "om" 3677 }, { 3678 "or", 3679 "or_Orya_IN", 3680 "or" 3681 }, { 3682 "pa", 3683 "pa_Guru_IN", 3684 "pa" 3685 }, { 3686 "pa_Arab", 3687 "pa_Arab_PK", 3688 "pa_PK" 3689 }, { 3690 "pa_PK", 3691 "pa_Arab_PK", 3692 "pa_PK" 3693 }, { 3694 "pap", 3695 "pap_Latn_AW", 3696 "pap" 3697 }, { 3698 "pau", 3699 "pau_Latn_PW", 3700 "pau" 3701 }, { 3702 "pl", 3703 "pl_Latn_PL", 3704 "pl" 3705 }, { 3706 "ps", 3707 "ps_Arab_AF", 3708 "ps" 3709 }, { 3710 "pt", 3711 "pt_Latn_BR", 3712 "pt" 3713 }, { 3714 "rn", 3715 "rn_Latn_BI", 3716 "rn" 3717 }, { 3718 "ro", 3719 "ro_Latn_RO", 3720 "ro" 3721 }, { 3722 "ru", 3723 "ru_Cyrl_RU", 3724 "ru" 3725 }, { 3726 "rw", 3727 "rw_Latn_RW", 3728 "rw" 3729 }, { 3730 "sa", 3731 "sa_Deva_IN", 3732 "sa" 3733 }, { 3734 "se", 3735 "se_Latn_NO", 3736 "se" 3737 }, { 3738 "sg", 3739 "sg_Latn_CF", 3740 "sg" 3741 }, { 3742 "si", 3743 "si_Sinh_LK", 3744 "si" 3745 }, { 3746 "sid", 3747 "sid_Latn_ET", 3748 "sid" 3749 }, { 3750 "sk", 3751 "sk_Latn_SK", 3752 "sk" 3753 }, { 3754 "sl", 3755 "sl_Latn_SI", 3756 "sl" 3757 }, { 3758 "sm", 3759 "sm_Latn_WS", 3760 "sm" 3761 }, { 3762 "so", 3763 "so_Latn_SO", 3764 "so" 3765 }, { 3766 "sq", 3767 "sq_Latn_AL", 3768 "sq" 3769 }, { 3770 "sr", 3771 "sr_Cyrl_RS", 3772 "sr" 3773 }, { 3774 "ss", 3775 "ss_Latn_ZA", 3776 "ss" 3777 }, { 3778 "st", 3779 "st_Latn_ZA", 3780 "st" 3781 }, { 3782 "sv", 3783 "sv_Latn_SE", 3784 "sv" 3785 }, { 3786 "sw", 3787 "sw_Latn_TZ", 3788 "sw" 3789 }, { 3790 "ta", 3791 "ta_Taml_IN", 3792 "ta" 3793 }, { 3794 "te", 3795 "te_Telu_IN", 3796 "te" 3797 }, { 3798 "tet", 3799 "tet_Latn_TL", 3800 "tet" 3801 }, { 3802 "tg", 3803 "tg_Cyrl_TJ", 3804 "tg" 3805 }, { 3806 "th", 3807 "th_Thai_TH", 3808 "th" 3809 }, { 3810 "ti", 3811 "ti_Ethi_ET", 3812 "ti" 3813 }, { 3814 "tig", 3815 "tig_Ethi_ER", 3816 "tig" 3817 }, { 3818 "tk", 3819 "tk_Latn_TM", 3820 "tk" 3821 }, { 3822 "tkl", 3823 "tkl_Latn_TK", 3824 "tkl" 3825 }, { 3826 "tn", 3827 "tn_Latn_ZA", 3828 "tn" 3829 }, { 3830 "to", 3831 "to_Latn_TO", 3832 "to" 3833 }, { 3834 "tpi", 3835 "tpi_Latn_PG", 3836 "tpi" 3837 }, { 3838 "tr", 3839 "tr_Latn_TR", 3840 "tr" 3841 }, { 3842 "ts", 3843 "ts_Latn_ZA", 3844 "ts" 3845 }, { 3846 "tt", 3847 "tt_Cyrl_RU", 3848 "tt" 3849 }, { 3850 "tvl", 3851 "tvl_Latn_TV", 3852 "tvl" 3853 }, { 3854 "ty", 3855 "ty_Latn_PF", 3856 "ty" 3857 }, { 3858 "uk", 3859 "uk_Cyrl_UA", 3860 "uk" 3861 }, { 3862 "und", 3863 "en_Latn_US", 3864 "en" 3865 }, { 3866 "und_AD", 3867 "ca_Latn_AD", 3868 "ca_AD" 3869 }, { 3870 "und_AE", 3871 "ar_Arab_AE", 3872 "ar_AE" 3873 }, { 3874 "und_AF", 3875 "fa_Arab_AF", 3876 "fa_AF" 3877 }, { 3878 "und_AL", 3879 "sq_Latn_AL", 3880 "sq" 3881 }, { 3882 "und_AM", 3883 "hy_Armn_AM", 3884 "hy" 3885 }, { 3886 "und_AO", 3887 "pt_Latn_AO", 3888 "pt_AO" 3889 }, { 3890 "und_AR", 3891 "es_Latn_AR", 3892 "es_AR" 3893 }, { 3894 "und_AS", 3895 "sm_Latn_AS", 3896 "sm_AS" 3897 }, { 3898 "und_AT", 3899 "de_Latn_AT", 3900 "de_AT" 3901 }, { 3902 "und_AW", 3903 "nl_Latn_AW", 3904 "nl_AW" 3905 }, { 3906 "und_AX", 3907 "sv_Latn_AX", 3908 "sv_AX" 3909 }, { 3910 "und_AZ", 3911 "az_Latn_AZ", 3912 "az" 3913 }, { 3914 "und_Arab", 3915 "ar_Arab_EG", 3916 "ar" 3917 }, { 3918 "und_Arab_IN", 3919 "ur_Arab_IN", 3920 "ur_IN" 3921 }, { 3922 "und_Arab_PK", 3923 "ur_Arab_PK", 3924 "ur" 3925 }, { 3926 "und_Arab_SN", 3927 "ar_Arab_SN", 3928 "ar_SN" 3929 }, { 3930 "und_Armn", 3931 "hy_Armn_AM", 3932 "hy" 3933 }, { 3934 "und_BA", 3935 "bs_Latn_BA", 3936 "bs" 3937 }, { 3938 "und_BD", 3939 "bn_Beng_BD", 3940 "bn" 3941 }, { 3942 "und_BE", 3943 "nl_Latn_BE", 3944 "nl_BE" 3945 }, { 3946 "und_BF", 3947 "fr_Latn_BF", 3948 "fr_BF" 3949 }, { 3950 "und_BG", 3951 "bg_Cyrl_BG", 3952 "bg" 3953 }, { 3954 "und_BH", 3955 "ar_Arab_BH", 3956 "ar_BH" 3957 }, { 3958 "und_BI", 3959 "rn_Latn_BI", 3960 "rn" 3961 }, { 3962 "und_BJ", 3963 "fr_Latn_BJ", 3964 "fr_BJ" 3965 }, { 3966 "und_BN", 3967 "ms_Latn_BN", 3968 "ms_BN" 3969 }, { 3970 "und_BO", 3971 "es_Latn_BO", 3972 "es_BO" 3973 }, { 3974 "und_BR", 3975 "pt_Latn_BR", 3976 "pt" 3977 }, { 3978 "und_BT", 3979 "dz_Tibt_BT", 3980 "dz" 3981 }, { 3982 "und_BY", 3983 "be_Cyrl_BY", 3984 "be" 3985 }, { 3986 "und_Beng", 3987 "bn_Beng_BD", 3988 "bn" 3989 }, { 3990 "und_Beng_IN", 3991 "bn_Beng_IN", 3992 "bn_IN" 3993 }, { 3994 "und_CD", 3995 "sw_Latn_CD", 3996 "sw_CD" 3997 }, { 3998 "und_CF", 3999 "fr_Latn_CF", 4000 "fr_CF" 4001 }, { 4002 "und_CG", 4003 "fr_Latn_CG", 4004 "fr_CG" 4005 }, { 4006 "und_CH", 4007 "de_Latn_CH", 4008 "de_CH" 4009 }, { 4010 "und_CI", 4011 "fr_Latn_CI", 4012 "fr_CI" 4013 }, { 4014 "und_CL", 4015 "es_Latn_CL", 4016 "es_CL" 4017 }, { 4018 "und_CM", 4019 "fr_Latn_CM", 4020 "fr_CM" 4021 }, { 4022 "und_CN", 4023 "zh_Hans_CN", 4024 "zh" 4025 }, { 4026 "und_CO", 4027 "es_Latn_CO", 4028 "es_CO" 4029 }, { 4030 "und_CR", 4031 "es_Latn_CR", 4032 "es_CR" 4033 }, { 4034 "und_CU", 4035 "es_Latn_CU", 4036 "es_CU" 4037 }, { 4038 "und_CV", 4039 "pt_Latn_CV", 4040 "pt_CV" 4041 }, { 4042 "und_CY", 4043 "el_Grek_CY", 4044 "el_CY" 4045 }, { 4046 "und_CZ", 4047 "cs_Latn_CZ", 4048 "cs" 4049 }, { 4050 "und_Cher", 4051 "chr_Cher_US", 4052 "chr" 4053 }, { 4054 "und_Cyrl", 4055 "ru_Cyrl_RU", 4056 "ru" 4057 }, { 4058 "und_Cyrl_KZ", 4059 "ru_Cyrl_KZ", 4060 "ru_KZ" 4061 }, { 4062 "und_DE", 4063 "de_Latn_DE", 4064 "de" 4065 }, { 4066 "und_DJ", 4067 "aa_Latn_DJ", 4068 "aa_DJ" 4069 }, { 4070 "und_DK", 4071 "da_Latn_DK", 4072 "da" 4073 }, { 4074 "und_DO", 4075 "es_Latn_DO", 4076 "es_DO" 4077 }, { 4078 "und_DZ", 4079 "ar_Arab_DZ", 4080 "ar_DZ" 4081 }, { 4082 "und_Deva", 4083 "hi_Deva_IN", 4084 "hi" 4085 }, { 4086 "und_EC", 4087 "es_Latn_EC", 4088 "es_EC" 4089 }, { 4090 "und_EE", 4091 "et_Latn_EE", 4092 "et" 4093 }, { 4094 "und_EG", 4095 "ar_Arab_EG", 4096 "ar" 4097 }, { 4098 "und_EH", 4099 "ar_Arab_EH", 4100 "ar_EH" 4101 }, { 4102 "und_ER", 4103 "ti_Ethi_ER", 4104 "ti_ER" 4105 }, { 4106 "und_ES", 4107 "es_Latn_ES", 4108 "es" 4109 }, { 4110 "und_ET", 4111 "am_Ethi_ET", 4112 "am" 4113 }, { 4114 "und_Ethi", 4115 "am_Ethi_ET", 4116 "am" 4117 }, { 4118 "und_Ethi_ER", 4119 "am_Ethi_ER", 4120 "am_ER" 4121 }, { 4122 "und_FI", 4123 "fi_Latn_FI", 4124 "fi" 4125 }, { 4126 "und_FM", 4127 "en_Latn_FM", 4128 "en_FM" 4129 }, { 4130 "und_FO", 4131 "fo_Latn_FO", 4132 "fo" 4133 }, { 4134 "und_FR", 4135 "fr_Latn_FR", 4136 "fr" 4137 }, { 4138 "und_GA", 4139 "fr_Latn_GA", 4140 "fr_GA" 4141 }, { 4142 "und_GE", 4143 "ka_Geor_GE", 4144 "ka" 4145 }, { 4146 "und_GF", 4147 "fr_Latn_GF", 4148 "fr_GF" 4149 }, { 4150 "und_GL", 4151 "kl_Latn_GL", 4152 "kl" 4153 }, { 4154 "und_GN", 4155 "fr_Latn_GN", 4156 "fr_GN" 4157 }, { 4158 "und_GP", 4159 "fr_Latn_GP", 4160 "fr_GP" 4161 }, { 4162 "und_GQ", 4163 "es_Latn_GQ", 4164 "es_GQ" 4165 }, { 4166 "und_GR", 4167 "el_Grek_GR", 4168 "el" 4169 }, { 4170 "und_GT", 4171 "es_Latn_GT", 4172 "es_GT" 4173 }, { 4174 "und_GU", 4175 "en_Latn_GU", 4176 "en_GU" 4177 }, { 4178 "und_GW", 4179 "pt_Latn_GW", 4180 "pt_GW" 4181 }, { 4182 "und_Geor", 4183 "ka_Geor_GE", 4184 "ka" 4185 }, { 4186 "und_Grek", 4187 "el_Grek_GR", 4188 "el" 4189 }, { 4190 "und_Gujr", 4191 "gu_Gujr_IN", 4192 "gu" 4193 }, { 4194 "und_Guru", 4195 "pa_Guru_IN", 4196 "pa" 4197 }, { 4198 "und_HK", 4199 "zh_Hant_HK", 4200 "zh_HK" 4201 }, { 4202 "und_HN", 4203 "es_Latn_HN", 4204 "es_HN" 4205 }, { 4206 "und_HR", 4207 "hr_Latn_HR", 4208 "hr" 4209 }, { 4210 "und_HT", 4211 "ht_Latn_HT", 4212 "ht" 4213 }, { 4214 "und_HU", 4215 "hu_Latn_HU", 4216 "hu" 4217 }, { 4218 "und_Hani", 4219 "zh_Hani_CN", 4220 "zh_Hani" 4221 }, { 4222 "und_Hans", 4223 "zh_Hans_CN", 4224 "zh" 4225 }, { 4226 "und_Hant", 4227 "zh_Hant_TW", 4228 "zh_TW" 4229 }, { 4230 "und_Hebr", 4231 "he_Hebr_IL", 4232 "he" 4233 }, { 4234 "und_IL", 4235 "he_Hebr_IL", 4236 "he" 4237 }, { 4238 "und_IN", 4239 "hi_Deva_IN", 4240 "hi" 4241 }, { 4242 "und_IQ", 4243 "ar_Arab_IQ", 4244 "ar_IQ" 4245 }, { 4246 "und_IR", 4247 "fa_Arab_IR", 4248 "fa" 4249 }, { 4250 "und_IS", 4251 "is_Latn_IS", 4252 "is" 4253 }, { 4254 "und_IT", 4255 "it_Latn_IT", 4256 "it" 4257 }, { 4258 "und_JO", 4259 "ar_Arab_JO", 4260 "ar_JO" 4261 }, { 4262 "und_JP", 4263 "ja_Jpan_JP", 4264 "ja" 4265 }, { 4266 "und_Jpan", 4267 "ja_Jpan_JP", 4268 "ja" 4269 }, { 4270 "und_KG", 4271 "ky_Cyrl_KG", 4272 "ky" 4273 }, { 4274 "und_KH", 4275 "km_Khmr_KH", 4276 "km" 4277 }, { 4278 "und_KM", 4279 "ar_Arab_KM", 4280 "ar_KM" 4281 }, { 4282 "und_KP", 4283 "ko_Kore_KP", 4284 "ko_KP" 4285 }, { 4286 "und_KR", 4287 "ko_Kore_KR", 4288 "ko" 4289 }, { 4290 "und_KW", 4291 "ar_Arab_KW", 4292 "ar_KW" 4293 }, { 4294 "und_KZ", 4295 "ru_Cyrl_KZ", 4296 "ru_KZ" 4297 }, { 4298 "und_Khmr", 4299 "km_Khmr_KH", 4300 "km" 4301 }, { 4302 "und_Knda", 4303 "kn_Knda_IN", 4304 "kn" 4305 }, { 4306 "und_Kore", 4307 "ko_Kore_KR", 4308 "ko" 4309 }, { 4310 "und_LA", 4311 "lo_Laoo_LA", 4312 "lo" 4313 }, { 4314 "und_LB", 4315 "ar_Arab_LB", 4316 "ar_LB" 4317 }, { 4318 "und_LI", 4319 "de_Latn_LI", 4320 "de_LI" 4321 }, { 4322 "und_LK", 4323 "si_Sinh_LK", 4324 "si" 4325 }, { 4326 "und_LS", 4327 "st_Latn_LS", 4328 "st_LS" 4329 }, { 4330 "und_LT", 4331 "lt_Latn_LT", 4332 "lt" 4333 }, { 4334 "und_LU", 4335 "fr_Latn_LU", 4336 "fr_LU" 4337 }, { 4338 "und_LV", 4339 "lv_Latn_LV", 4340 "lv" 4341 }, { 4342 "und_LY", 4343 "ar_Arab_LY", 4344 "ar_LY" 4345 }, { 4346 "und_Laoo", 4347 "lo_Laoo_LA", 4348 "lo" 4349 }, { 4350 "und_Latn_ES", 4351 "es_Latn_ES", 4352 "es" 4353 }, { 4354 "und_Latn_ET", 4355 "en_Latn_ET", 4356 "en_ET" 4357 }, { 4358 "und_Latn_GB", 4359 "en_Latn_GB", 4360 "en_GB" 4361 }, { 4362 "und_Latn_GH", 4363 "ak_Latn_GH", 4364 "ak" 4365 }, { 4366 "und_Latn_ID", 4367 "id_Latn_ID", 4368 "id" 4369 }, { 4370 "und_Latn_IT", 4371 "it_Latn_IT", 4372 "it" 4373 }, { 4374 "und_Latn_NG", 4375 "en_Latn_NG", 4376 "en_NG" 4377 }, { 4378 "und_Latn_TR", 4379 "tr_Latn_TR", 4380 "tr" 4381 }, { 4382 "und_Latn_ZA", 4383 "en_Latn_ZA", 4384 "en_ZA" 4385 }, { 4386 "und_MA", 4387 "ar_Arab_MA", 4388 "ar_MA" 4389 }, { 4390 "und_MC", 4391 "fr_Latn_MC", 4392 "fr_MC" 4393 }, { 4394 "und_MD", 4395 "ro_Latn_MD", 4396 "ro_MD" 4397 }, { 4398 "und_ME", 4399 "sr_Latn_ME", 4400 "sr_ME" 4401 }, { 4402 "und_MG", 4403 "mg_Latn_MG", 4404 "mg" 4405 }, { 4406 "und_MH", 4407 "en_Latn_MH", 4408 "en_MH" 4409 }, { 4410 "und_MK", 4411 "mk_Cyrl_MK", 4412 "mk" 4413 }, { 4414 "und_ML", 4415 "bm_Latn_ML", 4416 "bm" 4417 }, { 4418 "und_MM", 4419 "my_Mymr_MM", 4420 "my" 4421 }, { 4422 "und_MN", 4423 "mn_Cyrl_MN", 4424 "mn" 4425 }, { 4426 "und_MO", 4427 "zh_Hant_MO", 4428 "zh_MO" 4429 }, { 4430 "und_MQ", 4431 "fr_Latn_MQ", 4432 "fr_MQ" 4433 }, { 4434 "und_MR", 4435 "ar_Arab_MR", 4436 "ar_MR" 4437 }, { 4438 "und_MT", 4439 "mt_Latn_MT", 4440 "mt" 4441 }, { 4442 "und_MV", 4443 "dv_Thaa_MV", 4444 "dv" 4445 }, { 4446 "und_MW", 4447 "en_Latn_MW", 4448 "en_MW" 4449 }, { 4450 "und_MX", 4451 "es_Latn_MX", 4452 "es_MX" 4453 }, { 4454 "und_MY", 4455 "ms_Latn_MY", 4456 "ms" 4457 }, { 4458 "und_MZ", 4459 "pt_Latn_MZ", 4460 "pt_MZ" 4461 }, { 4462 "und_Mlym", 4463 "ml_Mlym_IN", 4464 "ml" 4465 }, { 4466 "und_Mymr", 4467 "my_Mymr_MM", 4468 "my" 4469 }, { 4470 "und_NC", 4471 "fr_Latn_NC", 4472 "fr_NC" 4473 }, { 4474 "und_NE", 4475 "ha_Latn_NE", 4476 "ha_NE" 4477 }, { 4478 "und_NG", 4479 "en_Latn_NG", 4480 "en_NG" 4481 }, { 4482 "und_NI", 4483 "es_Latn_NI", 4484 "es_NI" 4485 }, { 4486 "und_NL", 4487 "nl_Latn_NL", 4488 "nl" 4489 }, { 4490 "und_NO", 4491 "no_Latn_NO", /* Google patch */ 4492 "no" /* Google patch */ 4493 }, { 4494 "und_NP", 4495 "ne_Deva_NP", 4496 "ne" 4497 }, { 4498 "und_NR", 4499 "en_Latn_NR", 4500 "en_NR" 4501 }, { 4502 "und_NU", 4503 "en_Latn_NU", 4504 "en_NU" 4505 }, { 4506 "und_OM", 4507 "ar_Arab_OM", 4508 "ar_OM" 4509 }, { 4510 "und_Orya", 4511 "or_Orya_IN", 4512 "or" 4513 }, { 4514 "und_PA", 4515 "es_Latn_PA", 4516 "es_PA" 4517 }, { 4518 "und_PE", 4519 "es_Latn_PE", 4520 "es_PE" 4521 }, { 4522 "und_PF", 4523 "fr_Latn_PF", 4524 "fr_PF" 4525 }, { 4526 "und_PG", 4527 "tpi_Latn_PG", 4528 "tpi" 4529 }, { 4530 "und_PH", 4531 "fil_Latn_PH", 4532 "fil" 4533 }, { 4534 "und_PL", 4535 "pl_Latn_PL", 4536 "pl" 4537 }, { 4538 "und_PM", 4539 "fr_Latn_PM", 4540 "fr_PM" 4541 }, { 4542 "und_PR", 4543 "es_Latn_PR", 4544 "es_PR" 4545 }, { 4546 "und_PS", 4547 "ar_Arab_PS", 4548 "ar_PS" 4549 }, { 4550 "und_PT", 4551 "pt_Latn_PT", 4552 "pt_PT" 4553 }, { 4554 "und_PW", 4555 "pau_Latn_PW", 4556 "pau" 4557 }, { 4558 "und_PY", 4559 "gn_Latn_PY", 4560 "gn" 4561 }, { 4562 "und_QA", 4563 "ar_Arab_QA", 4564 "ar_QA" 4565 }, { 4566 "und_RE", 4567 "fr_Latn_RE", 4568 "fr_RE" 4569 }, { 4570 "und_RO", 4571 "ro_Latn_RO", 4572 "ro" 4573 }, { 4574 "und_RS", 4575 "sr_Cyrl_RS", 4576 "sr" 4577 }, { 4578 "und_RU", 4579 "ru_Cyrl_RU", 4580 "ru" 4581 }, { 4582 "und_RW", 4583 "rw_Latn_RW", 4584 "rw" 4585 }, { 4586 "und_SA", 4587 "ar_Arab_SA", 4588 "ar_SA" 4589 }, { 4590 "und_SD", 4591 "ar_Arab_SD", 4592 "ar_SD" 4593 }, { 4594 "und_SE", 4595 "sv_Latn_SE", 4596 "sv" 4597 }, { 4598 "und_SG", 4599 "en_Latn_SG", 4600 "en_SG" 4601 }, { 4602 "und_SI", 4603 "sl_Latn_SI", 4604 "sl" 4605 }, { 4606 "und_SJ", 4607 "no_Latn_SJ", /* Google patch */ 4608 "no_SJ" /* Google patch */ 4609 }, { 4610 "und_SK", 4611 "sk_Latn_SK", 4612 "sk" 4613 }, { 4614 "und_SM", 4615 "it_Latn_SM", 4616 "it_SM" 4617 }, { 4618 "und_SN", 4619 "fr_Latn_SN", 4620 "fr_SN" 4621 }, { 4622 "und_SO", 4623 "so_Latn_SO", 4624 "so" 4625 }, { 4626 "und_SR", 4627 "nl_Latn_SR", 4628 "nl_SR" 4629 }, { 4630 "und_ST", 4631 "pt_Latn_ST", 4632 "pt_ST" 4633 }, { 4634 "und_SV", 4635 "es_Latn_SV", 4636 "es_SV" 4637 }, { 4638 "und_SY", 4639 "ar_Arab_SY", 4640 "ar_SY" 4641 }, { 4642 "und_Sinh", 4643 "si_Sinh_LK", 4644 "si" 4645 }, { 4646 "und_TD", 4647 "fr_Latn_TD", 4648 "fr_TD" 4649 }, { 4650 "und_TG", 4651 "fr_Latn_TG", 4652 "fr_TG" 4653 }, { 4654 "und_TH", 4655 "th_Thai_TH", 4656 "th" 4657 }, { 4658 "und_TJ", 4659 "tg_Cyrl_TJ", 4660 "tg" 4661 }, { 4662 "und_TK", 4663 "tkl_Latn_TK", 4664 "tkl" 4665 }, { 4666 "und_TL", 4667 "pt_Latn_TL", 4668 "pt_TL" 4669 }, { 4670 "und_TM", 4671 "tk_Latn_TM", 4672 "tk" 4673 }, { 4674 "und_TN", 4675 "ar_Arab_TN", 4676 "ar_TN" 4677 }, { 4678 "und_TO", 4679 "to_Latn_TO", 4680 "to" 4681 }, { 4682 "und_TR", 4683 "tr_Latn_TR", 4684 "tr" 4685 }, { 4686 "und_TV", 4687 "tvl_Latn_TV", 4688 "tvl" 4689 }, { 4690 "und_TW", 4691 "zh_Hant_TW", 4692 "zh_TW" 4693 }, { 4694 "und_Taml", 4695 "ta_Taml_IN", 4696 "ta" 4697 }, { 4698 "und_Telu", 4699 "te_Telu_IN", 4700 "te" 4701 }, { 4702 "und_Thaa", 4703 "dv_Thaa_MV", 4704 "dv" 4705 }, { 4706 "und_Thai", 4707 "th_Thai_TH", 4708 "th" 4709 }, { 4710 "und_Tibt", 4711 "bo_Tibt_CN", 4712 "bo" 4713 }, { 4714 "und_UA", 4715 "uk_Cyrl_UA", 4716 "uk" 4717 }, { 4718 "und_UY", 4719 "es_Latn_UY", 4720 "es_UY" 4721 }, { 4722 "und_UZ", 4723 "uz_Latn_UZ", 4724 "uz" 4725 }, { 4726 "und_VA", 4727 "it_Latn_VA", 4728 "it_VA" 4729 }, { 4730 "und_VE", 4731 "es_Latn_VE", 4732 "es_VE" 4733 }, { 4734 "und_VN", 4735 "vi_Latn_VN", 4736 "vi" 4737 }, { 4738 "und_VU", 4739 "bi_Latn_VU", 4740 "bi" 4741 }, { 4742 "und_WF", 4743 "fr_Latn_WF", 4744 "fr_WF" 4745 }, { 4746 "und_WS", 4747 "sm_Latn_WS", 4748 "sm" 4749 }, { 4750 "und_YE", 4751 "ar_Arab_YE", 4752 "ar_YE" 4753 }, { 4754 "und_YT", 4755 "fr_Latn_YT", 4756 "fr_YT" 4757 }, { 4758 "und_Yiii", 4759 "ii_Yiii_CN", 4760 "ii" 4761 }, { 4762 "ur", 4763 "ur_Arab_PK", 4764 "ur" 4765 }, { 4766 "uz", 4767 "uz_Latn_UZ", 4768 "uz" 4769 }, { 4770 "uz_AF", 4771 "uz_Arab_AF", 4772 "uz_AF" 4773 }, { 4774 "uz_Arab", 4775 "uz_Arab_AF", 4776 "uz_AF" 4777 }, { 4778 "ve", 4779 "ve_Latn_ZA", 4780 "ve" 4781 }, { 4782 "vi", 4783 "vi_Latn_VN", 4784 "vi" 4785 }, { 4786 "wal", 4787 "wal_Ethi_ET", 4788 "wal" 4789 }, { 4790 "wo", 4791 "wo_Latn_SN", 4792 "wo" 4793 }, { 4794 "xh", 4795 "xh_Latn_ZA", 4796 "xh" 4797 }, { 4798 "yo", 4799 "yo_Latn_NG", 4800 "yo" 4801 }, { 4802 "zh", 4803 "zh_Hans_CN", 4804 "zh" 4805 }, { 4806 "zh_HK", 4807 "zh_Hant_HK", 4808 "zh_HK" 4809 }, { 4810 "zh_Hani", 4811 "zh_Hani_CN", /* changed due to cldrbug 6204, may be an error */ 4812 "zh_Hani", /* changed due to cldrbug 6204, may be an error */ 4813 }, { 4814 "zh_Hant", 4815 "zh_Hant_TW", 4816 "zh_TW" 4817 }, { 4818 "zh_MO", 4819 "zh_Hant_MO", 4820 "zh_MO" 4821 }, { 4822 "zh_TW", 4823 "zh_Hant_TW", 4824 "zh_TW" 4825 }, { 4826 "zu", 4827 "zu_Latn_ZA", 4828 "zu" 4829 }, { 4830 "und", 4831 "en_Latn_US", 4832 "en" 4833 }, { 4834 "und_ZZ", 4835 "en_Latn_US", 4836 "en" 4837 }, { 4838 "und_CN", 4839 "zh_Hans_CN", 4840 "zh" 4841 }, { 4842 "und_TW", 4843 "zh_Hant_TW", 4844 "zh_TW" 4845 }, { 4846 "und_HK", 4847 "zh_Hant_HK", 4848 "zh_HK" 4849 }, { 4850 "und_AQ", 4851 "und_Latn_AQ", 4852 "und_AQ" 4853 }, { 4854 "und_Zzzz", 4855 "en_Latn_US", 4856 "en" 4857 }, { 4858 "und_Zzzz_ZZ", 4859 "en_Latn_US", 4860 "en" 4861 }, { 4862 "und_Zzzz_CN", 4863 "zh_Hans_CN", 4864 "zh" 4865 }, { 4866 "und_Zzzz_TW", 4867 "zh_Hant_TW", 4868 "zh_TW" 4869 }, { 4870 "und_Zzzz_HK", 4871 "zh_Hant_HK", 4872 "zh_HK" 4873 }, { 4874 "und_Zzzz_AQ", 4875 "und_Latn_AQ", 4876 "und_AQ" 4877 }, { 4878 "und_Latn", 4879 "en_Latn_US", 4880 "en" 4881 }, { 4882 "und_Latn_ZZ", 4883 "en_Latn_US", 4884 "en" 4885 }, { 4886 "und_Latn_CN", 4887 "za_Latn_CN", 4888 "za" 4889 }, { 4890 "und_Latn_TW", 4891 "trv_Latn_TW", 4892 "trv" 4893 }, { 4894 "und_Latn_HK", 4895 "zh_Latn_HK", 4896 "zh_Latn_HK" 4897 }, { 4898 "und_Latn_AQ", 4899 "und_Latn_AQ", 4900 "und_AQ" 4901 }, { 4902 "und_Hans", 4903 "zh_Hans_CN", 4904 "zh" 4905 }, { 4906 "und_Hans_ZZ", 4907 "zh_Hans_CN", 4908 "zh" 4909 }, { 4910 "und_Hans_CN", 4911 "zh_Hans_CN", 4912 "zh" 4913 }, { 4914 "und_Hans_TW", 4915 "zh_Hans_TW", 4916 "zh_Hans_TW" 4917 }, { 4918 "und_Hans_HK", 4919 "zh_Hans_HK", 4920 "zh_Hans_HK" 4921 }, { 4922 "und_Hans_AQ", 4923 "zh_Hans_AQ", 4924 "zh_AQ" 4925 }, { 4926 "und_Hant", 4927 "zh_Hant_TW", 4928 "zh_TW" 4929 }, { 4930 "und_Hant_ZZ", 4931 "zh_Hant_TW", 4932 "zh_TW" 4933 }, { 4934 "und_Hant_CN", 4935 "zh_Hant_CN", 4936 "zh_Hant_CN" 4937 }, { 4938 "und_Hant_TW", 4939 "zh_Hant_TW", 4940 "zh_TW" 4941 }, { 4942 "und_Hant_HK", 4943 "zh_Hant_HK", 4944 "zh_HK" 4945 }, { 4946 "und_Hant_AQ", 4947 "zh_Hant_AQ", 4948 "zh_Hant_AQ" 4949 }, { 4950 "und_Moon", 4951 "en_Moon_US", 4952 "en_Moon" 4953 }, { 4954 "und_Moon_ZZ", 4955 "en_Moon_US", 4956 "en_Moon" 4957 }, { 4958 "und_Moon_CN", 4959 "zh_Moon_CN", 4960 "zh_Moon" 4961 }, { 4962 "und_Moon_TW", 4963 "zh_Moon_TW", 4964 "zh_Moon_TW" 4965 }, { 4966 "und_Moon_HK", 4967 "zh_Moon_HK", 4968 "zh_Moon_HK" 4969 }, { 4970 "und_Moon_AQ", 4971 "und_Moon_AQ", 4972 "und_Moon_AQ" 4973 }, { 4974 "es", 4975 "es_Latn_ES", 4976 "es" 4977 }, { 4978 "es_ZZ", 4979 "es_Latn_ES", 4980 "es" 4981 }, { 4982 "es_CN", 4983 "es_Latn_CN", 4984 "es_CN" 4985 }, { 4986 "es_TW", 4987 "es_Latn_TW", 4988 "es_TW" 4989 }, { 4990 "es_HK", 4991 "es_Latn_HK", 4992 "es_HK" 4993 }, { 4994 "es_AQ", 4995 "es_Latn_AQ", 4996 "es_AQ" 4997 }, { 4998 "es_Zzzz", 4999 "es_Latn_ES", 5000 "es" 5001 }, { 5002 "es_Zzzz_ZZ", 5003 "es_Latn_ES", 5004 "es" 5005 }, { 5006 "es_Zzzz_CN", 5007 "es_Latn_CN", 5008 "es_CN" 5009 }, { 5010 "es_Zzzz_TW", 5011 "es_Latn_TW", 5012 "es_TW" 5013 }, { 5014 "es_Zzzz_HK", 5015 "es_Latn_HK", 5016 "es_HK" 5017 }, { 5018 "es_Zzzz_AQ", 5019 "es_Latn_AQ", 5020 "es_AQ" 5021 }, { 5022 "es_Latn", 5023 "es_Latn_ES", 5024 "es" 5025 }, { 5026 "es_Latn_ZZ", 5027 "es_Latn_ES", 5028 "es" 5029 }, { 5030 "es_Latn_CN", 5031 "es_Latn_CN", 5032 "es_CN" 5033 }, { 5034 "es_Latn_TW", 5035 "es_Latn_TW", 5036 "es_TW" 5037 }, { 5038 "es_Latn_HK", 5039 "es_Latn_HK", 5040 "es_HK" 5041 }, { 5042 "es_Latn_AQ", 5043 "es_Latn_AQ", 5044 "es_AQ" 5045 }, { 5046 "es_Hans", 5047 "es_Hans_ES", 5048 "es_Hans" 5049 }, { 5050 "es_Hans_ZZ", 5051 "es_Hans_ES", 5052 "es_Hans" 5053 }, { 5054 "es_Hans_CN", 5055 "es_Hans_CN", 5056 "es_Hans_CN" 5057 }, { 5058 "es_Hans_TW", 5059 "es_Hans_TW", 5060 "es_Hans_TW" 5061 }, { 5062 "es_Hans_HK", 5063 "es_Hans_HK", 5064 "es_Hans_HK" 5065 }, { 5066 "es_Hans_AQ", 5067 "es_Hans_AQ", 5068 "es_Hans_AQ" 5069 }, { 5070 "es_Hant", 5071 "es_Hant_ES", 5072 "es_Hant" 5073 }, { 5074 "es_Hant_ZZ", 5075 "es_Hant_ES", 5076 "es_Hant" 5077 }, { 5078 "es_Hant_CN", 5079 "es_Hant_CN", 5080 "es_Hant_CN" 5081 }, { 5082 "es_Hant_TW", 5083 "es_Hant_TW", 5084 "es_Hant_TW" 5085 }, { 5086 "es_Hant_HK", 5087 "es_Hant_HK", 5088 "es_Hant_HK" 5089 }, { 5090 "es_Hant_AQ", 5091 "es_Hant_AQ", 5092 "es_Hant_AQ" 5093 }, { 5094 "es_Moon", 5095 "es_Moon_ES", 5096 "es_Moon" 5097 }, { 5098 "es_Moon_ZZ", 5099 "es_Moon_ES", 5100 "es_Moon" 5101 }, { 5102 "es_Moon_CN", 5103 "es_Moon_CN", 5104 "es_Moon_CN" 5105 }, { 5106 "es_Moon_TW", 5107 "es_Moon_TW", 5108 "es_Moon_TW" 5109 }, { 5110 "es_Moon_HK", 5111 "es_Moon_HK", 5112 "es_Moon_HK" 5113 }, { 5114 "es_Moon_AQ", 5115 "es_Moon_AQ", 5116 "es_Moon_AQ" 5117 }, { 5118 "zh", 5119 "zh_Hans_CN", 5120 "zh" 5121 }, { 5122 "zh_ZZ", 5123 "zh_Hans_CN", 5124 "zh" 5125 }, { 5126 "zh_CN", 5127 "zh_Hans_CN", 5128 "zh" 5129 }, { 5130 "zh_TW", 5131 "zh_Hant_TW", 5132 "zh_TW" 5133 }, { 5134 "zh_HK", 5135 "zh_Hant_HK", 5136 "zh_HK" 5137 }, { 5138 "zh_AQ", 5139 "zh_Hans_AQ", 5140 "zh_AQ" 5141 }, { 5142 "zh_Zzzz", 5143 "zh_Hans_CN", 5144 "zh" 5145 }, { 5146 "zh_Zzzz_ZZ", 5147 "zh_Hans_CN", 5148 "zh" 5149 }, { 5150 "zh_Zzzz_CN", 5151 "zh_Hans_CN", 5152 "zh" 5153 }, { 5154 "zh_Zzzz_TW", 5155 "zh_Hant_TW", 5156 "zh_TW" 5157 }, { 5158 "zh_Zzzz_HK", 5159 "zh_Hant_HK", 5160 "zh_HK" 5161 }, { 5162 "zh_Zzzz_AQ", 5163 "zh_Hans_AQ", 5164 "zh_AQ" 5165 }, { 5166 "zh_Latn", 5167 "zh_Latn_CN", 5168 "zh_Latn" 5169 }, { 5170 "zh_Latn_ZZ", 5171 "zh_Latn_CN", 5172 "zh_Latn" 5173 }, { 5174 "zh_Latn_CN", 5175 "zh_Latn_CN", 5176 "zh_Latn" 5177 }, { 5178 "zh_Latn_TW", 5179 "zh_Latn_TW", 5180 "zh_Latn_TW" 5181 }, { 5182 "zh_Latn_HK", 5183 "zh_Latn_HK", 5184 "zh_Latn_HK" 5185 }, { 5186 "zh_Latn_AQ", 5187 "zh_Latn_AQ", 5188 "zh_Latn_AQ" 5189 }, { 5190 "zh_Hans", 5191 "zh_Hans_CN", 5192 "zh" 5193 }, { 5194 "zh_Hans_ZZ", 5195 "zh_Hans_CN", 5196 "zh" 5197 }, { 5198 "zh_Hans_TW", 5199 "zh_Hans_TW", 5200 "zh_Hans_TW" 5201 }, { 5202 "zh_Hans_HK", 5203 "zh_Hans_HK", 5204 "zh_Hans_HK" 5205 }, { 5206 "zh_Hans_AQ", 5207 "zh_Hans_AQ", 5208 "zh_AQ" 5209 }, { 5210 "zh_Hant", 5211 "zh_Hant_TW", 5212 "zh_TW" 5213 }, { 5214 "zh_Hant_ZZ", 5215 "zh_Hant_TW", 5216 "zh_TW" 5217 }, { 5218 "zh_Hant_CN", 5219 "zh_Hant_CN", 5220 "zh_Hant_CN" 5221 }, { 5222 "zh_Hant_AQ", 5223 "zh_Hant_AQ", 5224 "zh_Hant_AQ" 5225 }, { 5226 "zh_Moon", 5227 "zh_Moon_CN", 5228 "zh_Moon" 5229 }, { 5230 "zh_Moon_ZZ", 5231 "zh_Moon_CN", 5232 "zh_Moon" 5233 }, { 5234 "zh_Moon_CN", 5235 "zh_Moon_CN", 5236 "zh_Moon" 5237 }, { 5238 "zh_Moon_TW", 5239 "zh_Moon_TW", 5240 "zh_Moon_TW" 5241 }, { 5242 "zh_Moon_HK", 5243 "zh_Moon_HK", 5244 "zh_Moon_HK" 5245 }, { 5246 "zh_Moon_AQ", 5247 "zh_Moon_AQ", 5248 "zh_Moon_AQ" 5249 }, { 5250 "art", 5251 "", 5252 "" 5253 }, { 5254 "art_ZZ", 5255 "", 5256 "" 5257 }, { 5258 "art_CN", 5259 "", 5260 "" 5261 }, { 5262 "art_TW", 5263 "", 5264 "" 5265 }, { 5266 "art_HK", 5267 "", 5268 "" 5269 }, { 5270 "art_AQ", 5271 "", 5272 "" 5273 }, { 5274 "art_Zzzz", 5275 "", 5276 "" 5277 }, { 5278 "art_Zzzz_ZZ", 5279 "", 5280 "" 5281 }, { 5282 "art_Zzzz_CN", 5283 "", 5284 "" 5285 }, { 5286 "art_Zzzz_TW", 5287 "", 5288 "" 5289 }, { 5290 "art_Zzzz_HK", 5291 "", 5292 "" 5293 }, { 5294 "art_Zzzz_AQ", 5295 "", 5296 "" 5297 }, { 5298 "art_Latn", 5299 "", 5300 "" 5301 }, { 5302 "art_Latn_ZZ", 5303 "", 5304 "" 5305 }, { 5306 "art_Latn_CN", 5307 "", 5308 "" 5309 }, { 5310 "art_Latn_TW", 5311 "", 5312 "" 5313 }, { 5314 "art_Latn_HK", 5315 "", 5316 "" 5317 }, { 5318 "art_Latn_AQ", 5319 "", 5320 "" 5321 }, { 5322 "art_Hans", 5323 "", 5324 "" 5325 }, { 5326 "art_Hans_ZZ", 5327 "", 5328 "" 5329 }, { 5330 "art_Hans_CN", 5331 "", 5332 "" 5333 }, { 5334 "art_Hans_TW", 5335 "", 5336 "" 5337 }, { 5338 "art_Hans_HK", 5339 "", 5340 "" 5341 }, { 5342 "art_Hans_AQ", 5343 "", 5344 "" 5345 }, { 5346 "art_Hant", 5347 "", 5348 "" 5349 }, { 5350 "art_Hant_ZZ", 5351 "", 5352 "" 5353 }, { 5354 "art_Hant_CN", 5355 "", 5356 "" 5357 }, { 5358 "art_Hant_TW", 5359 "", 5360 "" 5361 }, { 5362 "art_Hant_HK", 5363 "", 5364 "" 5365 }, { 5366 "art_Hant_AQ", 5367 "", 5368 "" 5369 }, { 5370 "art_Moon", 5371 "", 5372 "" 5373 }, { 5374 "art_Moon_ZZ", 5375 "", 5376 "" 5377 }, { 5378 "art_Moon_CN", 5379 "", 5380 "" 5381 }, { 5382 "art_Moon_TW", 5383 "", 5384 "" 5385 }, { 5386 "art_Moon_HK", 5387 "", 5388 "" 5389 }, { 5390 "art_Moon_AQ", 5391 "", 5392 "" 5393 }, { 5394 "de@collation=phonebook", 5395 "de_Latn_DE@collation=phonebook", 5396 "de@collation=phonebook" 5397 } 5398 }; 5399 5400 typedef struct errorDataTag { 5401 const char* tag; 5402 const char* expected; 5403 UErrorCode uerror; 5404 int32_t bufferSize; 5405 } errorData; 5406 5407 const errorData maximizeErrors[] = { 5408 { 5409 "enfueiujhytdf", 5410 NULL, 5411 U_ILLEGAL_ARGUMENT_ERROR, 5412 -1 5413 }, 5414 { 5415 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG", 5416 NULL, 5417 U_ILLEGAL_ARGUMENT_ERROR, 5418 -1 5419 }, 5420 { 5421 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG", 5422 NULL, 5423 U_ILLEGAL_ARGUMENT_ERROR, 5424 -1 5425 }, 5426 { 5427 "en_Latn_US_POSIX@currency=EURO", 5428 "en_Latn_US_POSIX@currency=EURO", 5429 U_BUFFER_OVERFLOW_ERROR, 5430 29 5431 }, 5432 { 5433 "en_Latn_US_POSIX@currency=EURO", 5434 "en_Latn_US_POSIX@currency=EURO", 5435 U_STRING_NOT_TERMINATED_WARNING, 5436 30 5437 } 5438 }; 5439 5440 const errorData minimizeErrors[] = { 5441 { 5442 "enfueiujhytdf", 5443 NULL, 5444 U_ILLEGAL_ARGUMENT_ERROR, 5445 -1 5446 }, 5447 { 5448 "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG", 5449 NULL, 5450 U_ILLEGAL_ARGUMENT_ERROR, 5451 -1 5452 }, 5453 { 5454 "en_Latn_US_POSIX@currency=EURO", 5455 "en__POSIX@currency=EURO", 5456 U_BUFFER_OVERFLOW_ERROR, 5457 22 5458 }, 5459 { 5460 "en_Latn_US_POSIX@currency=EURO", 5461 "en__POSIX@currency=EURO", 5462 U_STRING_NOT_TERMINATED_WARNING, 5463 23 5464 } 5465 }; 5466 5467 static int32_t getExpectedReturnValue(const errorData* data) 5468 { 5469 if (data->uerror == U_BUFFER_OVERFLOW_ERROR || 5470 data->uerror == U_STRING_NOT_TERMINATED_WARNING) 5471 { 5472 return strlen(data->expected); 5473 } 5474 else 5475 { 5476 return -1; 5477 } 5478 } 5479 5480 static int32_t getBufferSize(const errorData* data, int32_t actualSize) 5481 { 5482 if (data->expected == NULL) 5483 { 5484 return actualSize; 5485 } 5486 else if (data->bufferSize < 0) 5487 { 5488 return strlen(data->expected) + 1; 5489 } 5490 else 5491 { 5492 return data->bufferSize; 5493 } 5494 } 5495 5496 static void TestLikelySubtags() 5497 { 5498 char buffer[ULOC_FULLNAME_CAPACITY + ULOC_KEYWORD_AND_VALUES_CAPACITY + 1]; 5499 int32_t i = 0; 5500 5501 for (; i < sizeof(basic_maximize_data) / sizeof(basic_maximize_data[0]); ++i) 5502 { 5503 UErrorCode status = U_ZERO_ERROR; 5504 const char* const minimal = basic_maximize_data[i][0]; 5505 const char* const maximal = basic_maximize_data[i][1]; 5506 5507 /* const int32_t length = */ 5508 uloc_addLikelySubtags( 5509 minimal, 5510 buffer, 5511 sizeof(buffer), 5512 &status); 5513 if (U_FAILURE(status)) { 5514 log_err_status(status, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status %s\n", minimal, u_errorName(status)); 5515 status = U_ZERO_ERROR; 5516 } 5517 else if (uprv_strlen(maximal) == 0) { 5518 if (uprv_stricmp(minimal, buffer) != 0) { 5519 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer); 5520 } 5521 } 5522 else if (uprv_stricmp(maximal, buffer) != 0) { 5523 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %s\n", maximal, minimal, buffer); 5524 } 5525 } 5526 5527 for (i = 0; i < sizeof(basic_minimize_data) / sizeof(basic_minimize_data[0]); ++i) { 5528 5529 UErrorCode status = U_ZERO_ERROR; 5530 const char* const maximal = basic_minimize_data[i][0]; 5531 const char* const minimal = basic_minimize_data[i][1]; 5532 5533 /* const int32_t length = */ 5534 uloc_minimizeSubtags( 5535 maximal, 5536 buffer, 5537 sizeof(buffer), 5538 &status); 5539 5540 if (U_FAILURE(status)) { 5541 log_err_status(status, " unexpected failure of uloc_MinimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status)); 5542 status = U_ZERO_ERROR; 5543 } 5544 else if (uprv_strlen(minimal) == 0) { 5545 if (uprv_stricmp(maximal, buffer) != 0) { 5546 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer); 5547 } 5548 } 5549 else if (uprv_stricmp(minimal, buffer) != 0) { 5550 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer); 5551 } 5552 } 5553 5554 for (i = 0; i < sizeof(full_data) / sizeof(full_data[0]); ++i) { 5555 5556 UErrorCode status = U_ZERO_ERROR; 5557 const char* const minimal = full_data[i][0]; 5558 const char* const maximal = full_data[i][1]; 5559 5560 /* const int32_t length = */ 5561 uloc_addLikelySubtags( 5562 minimal, 5563 buffer, 5564 sizeof(buffer), 5565 &status); 5566 if (U_FAILURE(status)) { 5567 log_err_status(status, " unexpected failure of uloc_addLikelySubtags(), minimal \"%s\" status \"%s\"\n", minimal, u_errorName(status)); 5568 status = U_ZERO_ERROR; 5569 } 5570 else if (uprv_strlen(maximal) == 0) { 5571 if (uprv_stricmp(minimal, buffer) != 0) { 5572 log_err(" unexpected maximal value \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer); 5573 } 5574 } 5575 else if (uprv_stricmp(maximal, buffer) != 0) { 5576 log_err(" maximal doesn't match expected \"%s\" in uloc_addLikelySubtags(), minimal \"%s\" = \"%s\"\n", maximal, minimal, buffer); 5577 } 5578 } 5579 5580 for (i = 0; i < sizeof(full_data) / sizeof(full_data[0]); ++i) { 5581 5582 UErrorCode status = U_ZERO_ERROR; 5583 const char* const maximal = full_data[i][1]; 5584 const char* const minimal = full_data[i][2]; 5585 5586 if (strlen(maximal) > 0) { 5587 5588 /* const int32_t length = */ 5589 uloc_minimizeSubtags( 5590 maximal, 5591 buffer, 5592 sizeof(buffer), 5593 &status); 5594 5595 if (U_FAILURE(status)) { 5596 log_err_status(status, " unexpected failure of uloc_minimizeSubtags(), maximal \"%s\" status %s\n", maximal, u_errorName(status)); 5597 status = U_ZERO_ERROR; 5598 } 5599 else if (uprv_strlen(minimal) == 0) { 5600 if (uprv_stricmp(maximal, buffer) != 0) { 5601 log_err(" unexpected minimal value \"%s\" in uloc_minimizeSubtags(), maximal \"%s\" = \"%s\"\n", minimal, maximal, buffer); 5602 } 5603 } 5604 else if (uprv_stricmp(minimal, buffer) != 0) { 5605 log_err(" minimal doesn't match expected %s in uloc_MinimizeSubtags(), maximal \"%s\" = %s\n", minimal, maximal, buffer); 5606 } 5607 } 5608 } 5609 5610 for (i = 0; i < sizeof(maximizeErrors) / sizeof(maximizeErrors[0]); ++i) { 5611 5612 UErrorCode status = U_ZERO_ERROR; 5613 const char* const minimal = maximizeErrors[i].tag; 5614 const char* const maximal = maximizeErrors[i].expected; 5615 const UErrorCode expectedStatus = maximizeErrors[i].uerror; 5616 const int32_t expectedLength = getExpectedReturnValue(&maximizeErrors[i]); 5617 const int32_t bufferSize = getBufferSize(&maximizeErrors[i], sizeof(buffer)); 5618 5619 const int32_t length = 5620 uloc_addLikelySubtags( 5621 minimal, 5622 buffer, 5623 bufferSize, 5624 &status); 5625 5626 if (status == U_ZERO_ERROR) { 5627 log_err(" unexpected U_ZERO_ERROR for uloc_addLikelySubtags(), minimal \"%s\" expected status %s\n", minimal, u_errorName(expectedStatus)); 5628 status = U_ZERO_ERROR; 5629 } 5630 else if (status != expectedStatus) { 5631 log_err_status(status, " unexpected status for uloc_addLikelySubtags(), minimal \"%s\" expected status %s, but got %s\n", minimal, u_errorName(expectedStatus), u_errorName(status)); 5632 } 5633 else if (length != expectedLength) { 5634 log_err(" unexpected length for uloc_addLikelySubtags(), minimal \"%s\" expected length %d, but got %d\n", minimal, expectedLength, length); 5635 } 5636 else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) { 5637 if (uprv_strnicmp(maximal, buffer, bufferSize) != 0) { 5638 log_err(" maximal doesn't match expected %s in uloc_addLikelySubtags(), minimal \"%s\" = %*s\n", 5639 maximal, minimal, (int)sizeof(buffer), buffer); 5640 } 5641 } 5642 } 5643 5644 for (i = 0; i < sizeof(minimizeErrors) / sizeof(minimizeErrors[0]); ++i) { 5645 5646 UErrorCode status = U_ZERO_ERROR; 5647 const char* const maximal = minimizeErrors[i].tag; 5648 const char* const minimal = minimizeErrors[i].expected; 5649 const UErrorCode expectedStatus = minimizeErrors[i].uerror; 5650 const int32_t expectedLength = getExpectedReturnValue(&minimizeErrors[i]); 5651 const int32_t bufferSize = getBufferSize(&minimizeErrors[i], sizeof(buffer)); 5652 5653 const int32_t length = 5654 uloc_minimizeSubtags( 5655 maximal, 5656 buffer, 5657 bufferSize, 5658 &status); 5659 5660 if (status == U_ZERO_ERROR) { 5661 log_err(" unexpected U_ZERO_ERROR for uloc_minimizeSubtags(), maximal \"%s\" expected status %s\n", maximal, u_errorName(expectedStatus)); 5662 status = U_ZERO_ERROR; 5663 } 5664 else if (status != expectedStatus) { 5665 log_err_status(status, " unexpected status for uloc_minimizeSubtags(), maximal \"%s\" expected status %s, but got %s\n", maximal, u_errorName(expectedStatus), u_errorName(status)); 5666 } 5667 else if (length != expectedLength) { 5668 log_err(" unexpected length for uloc_minimizeSubtags(), maximal \"%s\" expected length %d, but got %d\n", maximal, expectedLength, length); 5669 } 5670 else if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) { 5671 if (uprv_strnicmp(minimal, buffer, bufferSize) != 0) { 5672 log_err(" minimal doesn't match expected \"%s\" in uloc_minimizeSubtags(), minimal \"%s\" = \"%*s\"\n", 5673 minimal, maximal, (int)sizeof(buffer), buffer); 5674 } 5675 } 5676 } 5677 } 5678 5679 const char* const locale_to_langtag[][3] = { 5680 {"", "und", "und"}, 5681 {"en", "en", "en"}, 5682 {"en_US", "en-US", "en-US"}, 5683 {"iw_IL", "he-IL", "he-IL"}, 5684 {"sr_Latn_SR", "sr-Latn-SR", "sr-Latn-SR"}, 5685 {"en__POSIX", "en-u-va-posix", "en-u-va-posix"}, 5686 {"en_POSIX", "en-u-va-posix", "en-u-va-posix"}, 5687 {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var", NULL}, /* variant POSIX_VAR is processed as regular variant */ 5688 {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix", NULL}, /* variant VAR_POSIX is processed as regular variant */ 5689 {"en_US_POSIX@va=posix2", "en-US-u-va-posix2", "en-US-u-va-posix2"}, /* if keyword va=xxx already exists, variant POSIX is simply dropped */ 5690 {"en_US_POSIX@ca=japanese", "en-US-u-ca-japanese-va-posix", "en-US-u-ca-japanese-va-posix"}, 5691 {"und_555", "und-555", "und-555"}, 5692 {"123", "und", NULL}, 5693 {"%$#&", "und", NULL}, 5694 {"_Latn", "und-Latn", "und-Latn"}, 5695 {"_DE", "und-DE", "und-DE"}, 5696 {"und_FR", "und-FR", "und-FR"}, 5697 {"th_TH_TH", "th-TH-x-lvariant-th", NULL}, 5698 {"bogus", "bogus", "bogus"}, 5699 {"foooobarrr", "und", NULL}, 5700 {"az_AZ_CYRL", "az-Cyrl-AZ", "az-Cyrl-AZ"}, 5701 {"aa_BB_CYRL", "aa-BB-x-lvariant-cyrl", NULL}, 5702 {"en_US_1234", "en-US-1234", "en-US-1234"}, 5703 {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb", "en-US-varianta-variantb"}, 5704 {"ja__9876_5432", "ja-9876-5432", "ja-9876-5432"}, 5705 {"zh_Hant__VAR", "zh-Hant-x-lvariant-var", NULL}, 5706 {"es__BADVARIANT_GOODVAR", "es-goodvar", NULL}, 5707 {"en@calendar=gregorian", "en-u-ca-gregory", "en-u-ca-gregory"}, 5708 {"de@collation=phonebook;calendar=gregorian", "de-u-ca-gregory-co-phonebk", "de-u-ca-gregory-co-phonebk"}, 5709 {"th@numbers=thai;z=extz;x=priv-use;a=exta", "th-a-exta-u-nu-thai-z-extz-x-priv-use", "th-a-exta-u-nu-thai-z-extz-x-priv-use"}, 5710 {"en@timezone=America/New_York;calendar=japanese", "en-u-ca-japanese-tz-usnyc", "en-u-ca-japanese-tz-usnyc"}, 5711 {"en@timezone=US/Eastern", "en-u-tz-usnyc", "en-u-tz-usnyc"}, 5712 {"en@x=x-y-z;a=a-b-c", "en-x-x-y-z", NULL}, 5713 {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-cu-usd-eur-ks-identic", NULL}, 5714 {"en_US_POSIX", "en-US-u-va-posix", "en-US-u-va-posix"}, 5715 {"en_US_POSIX@calendar=japanese;currency=EUR","en-US-u-ca-japanese-cu-eur-va-posix", "en-US-u-ca-japanese-cu-eur-va-posix"}, 5716 {"@x=elmer", "x-elmer", "x-elmer"}, 5717 {"en@x=elmer", "en-x-elmer", "en-x-elmer"}, 5718 {"@x=elmer;a=exta", "und-a-exta-x-elmer", "und-a-exta-x-elmer"}, 5719 {"en_US@attribute=attr1-attr2;calendar=gregorian", "en-US-u-attr1-attr2-ca-gregory", "en-US-u-attr1-attr2-ca-gregory"}, 5720 {NULL, NULL, NULL} 5721 }; 5722 5723 static void TestToLanguageTag(void) { 5724 char langtag[256]; 5725 int32_t i; 5726 UErrorCode status; 5727 int32_t len; 5728 const char *inloc; 5729 const char *expected; 5730 5731 for (i = 0; locale_to_langtag[i][0] != NULL; i++) { 5732 inloc = locale_to_langtag[i][0]; 5733 5734 /* testing non-strict mode */ 5735 status = U_ZERO_ERROR; 5736 langtag[0] = 0; 5737 expected = locale_to_langtag[i][1]; 5738 5739 len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), FALSE, &status); 5740 (void)len; /* Suppress set but not used warning. */ 5741 if (U_FAILURE(status)) { 5742 if (expected != NULL) { 5743 log_err("Error returned by uloc_toLanguageTag for locale id [%s] - error: %s\n", 5744 inloc, u_errorName(status)); 5745 } 5746 } else { 5747 if (expected == NULL) { 5748 log_err("Error should be returned by uloc_toLanguageTag for locale id [%s], but [%s] is returned without errors\n", 5749 inloc, langtag); 5750 } else if (uprv_strcmp(langtag, expected) != 0) { 5751 log_data_err("uloc_toLanguageTag returned language tag [%s] for input locale [%s] - expected: [%s]. Are you missing data?\n", 5752 langtag, inloc, expected); 5753 } 5754 } 5755 5756 /* testing strict mode */ 5757 status = U_ZERO_ERROR; 5758 langtag[0] = 0; 5759 expected = locale_to_langtag[i][2]; 5760 5761 len = uloc_toLanguageTag(inloc, langtag, sizeof(langtag), TRUE, &status); 5762 if (U_FAILURE(status)) { 5763 if (expected != NULL) { 5764 log_data_err("Error returned by uloc_toLanguageTag {strict} for locale id [%s] - error: %s Are you missing data?\n", 5765 inloc, u_errorName(status)); 5766 } 5767 } else { 5768 if (expected == NULL) { 5769 log_err("Error should be returned by uloc_toLanguageTag {strict} for locale id [%s], but [%s] is returned without errors\n", 5770 inloc, langtag); 5771 } else if (uprv_strcmp(langtag, expected) != 0) { 5772 log_err("uloc_toLanguageTag {strict} returned language tag [%s] for input locale [%s] - expected: [%s]\n", 5773 langtag, inloc, expected); 5774 } 5775 } 5776 } 5777 } 5778 5779 #define FULL_LENGTH -1 5780 static const struct { 5781 const char *bcpID; 5782 const char *locID; 5783 int32_t len; 5784 } langtag_to_locale[] = { 5785 {"ja-u-ijkl-efgh-abcd-ca-japanese-xx-yyy-zzz-kn", "ja@attribute=abcd-efgh-ijkl;calendar=japanese;colnumeric=yes;xx=yyy-zzz", FULL_LENGTH}, 5786 {"en", "en", FULL_LENGTH}, 5787 {"en-us", "en_US", FULL_LENGTH}, 5788 {"und-US", "_US", FULL_LENGTH}, 5789 {"und-latn", "_Latn", FULL_LENGTH}, 5790 {"en-US-posix", "en_US_POSIX", FULL_LENGTH}, 5791 {"de-de_euro", "de", 2}, 5792 {"kok-IN", "kok_IN", FULL_LENGTH}, 5793 {"123", "", 0}, 5794 {"en_us", "", 0}, 5795 {"en-latn-x", "en_Latn", 7}, 5796 {"art-lojban", "jbo", FULL_LENGTH}, 5797 {"zh-hakka", "hak", FULL_LENGTH}, 5798 {"zh-cmn-CH", "cmn_CH", FULL_LENGTH}, 5799 {"xxx-yy", "xxx_YY", FULL_LENGTH}, 5800 {"fr-234", "fr_234", FULL_LENGTH}, 5801 {"i-default", "en@x=i-default", FULL_LENGTH}, 5802 {"i-test", "", 0}, 5803 {"ja-jp-jp", "ja_JP", 5}, 5804 {"bogus", "bogus", FULL_LENGTH}, 5805 {"boguslang", "", 0}, 5806 {"EN-lATN-us", "en_Latn_US", FULL_LENGTH}, 5807 {"und-variant-1234", "__VARIANT_1234", FULL_LENGTH}, 5808 {"und-varzero-var1-vartwo", "__VARZERO", 11}, 5809 {"en-u-ca-gregory", "en@calendar=gregorian", FULL_LENGTH}, 5810 {"en-U-cu-USD", "en@currency=usd", FULL_LENGTH}, 5811 {"en-US-u-va-posix", "en_US_POSIX", FULL_LENGTH}, 5812 {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian", FULL_LENGTH}, 5813 {"en-us-posix-u-va-posix", "en_US_POSIX@va=posix", FULL_LENGTH}, 5814 {"en-us-u-va-posix2", "en_US@va=posix2", FULL_LENGTH}, 5815 {"en-us-vari1-u-va-posix", "en_US_VARI1@va=posix", FULL_LENGTH}, 5816 {"ar-x-1-2-3", "ar@x=1-2-3", FULL_LENGTH}, 5817 {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", FULL_LENGTH}, 5818 {"de-k-kext-u-co-phonebk-nu-latn", "de@collation=phonebook;k=kext;numbers=latn", FULL_LENGTH}, 5819 {"ja-u-cu-jpy-ca-jp", "ja@calendar=yes;currency=jpy;jp=yes", FULL_LENGTH}, 5820 {"en-us-u-tz-usnyc", "en_US@timezone=America/New_York", FULL_LENGTH}, 5821 {"und-a-abc-def", "und@a=abc-def", FULL_LENGTH}, 5822 {"zh-u-ca-chinese-x-u-ca-chinese", "zh@calendar=chinese;x=u-ca-chinese", FULL_LENGTH}, 5823 {"x-elmer", "@x=elmer", FULL_LENGTH}, 5824 {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian", FULL_LENGTH}, 5825 {"sr-u-kn", "sr@colnumeric=yes", FULL_LENGTH}, 5826 {"de-u-kn-co-phonebk", "de@collation=phonebook;colnumeric=yes", FULL_LENGTH}, 5827 {"en-u-attr2-attr1-kn-kb", "en@attribute=attr1-attr2;colbackwards=yes;colnumeric=yes", FULL_LENGTH}, 5828 {"ja-u-ijkl-efgh-abcd-ca-japanese-xx-yyy-zzz-kn", "ja@attribute=abcd-efgh-ijkl;calendar=japanese;colnumeric=yes;xx=yyy-zzz", FULL_LENGTH}, 5829 5830 {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer", 5831 "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that;xz=yes", 91}, 5832 {NULL, NULL, 0} 5833 }; 5834 5835 static void TestForLanguageTag(void) { 5836 char locale[256]; 5837 int32_t i; 5838 UErrorCode status; 5839 int32_t parsedLen; 5840 int32_t expParsedLen; 5841 5842 for (i = 0; langtag_to_locale[i].bcpID != NULL; i++) { 5843 status = U_ZERO_ERROR; 5844 locale[0] = 0; 5845 expParsedLen = langtag_to_locale[i].len; 5846 if (expParsedLen == FULL_LENGTH) { 5847 expParsedLen = uprv_strlen(langtag_to_locale[i].bcpID); 5848 } 5849 uloc_forLanguageTag(langtag_to_locale[i].bcpID, locale, sizeof(locale), &parsedLen, &status); 5850 if (U_FAILURE(status)) { 5851 log_err_status(status, "Error returned by uloc_forLanguageTag for language tag [%s] - error: %s\n", 5852 langtag_to_locale[i].bcpID, u_errorName(status)); 5853 } else { 5854 if (uprv_strcmp(langtag_to_locale[i].locID, locale) != 0) { 5855 log_data_err("uloc_forLanguageTag returned locale [%s] for input language tag [%s] - expected: [%s]\n", 5856 locale, langtag_to_locale[i].bcpID, langtag_to_locale[i].locID); 5857 } 5858 if (parsedLen != expParsedLen) { 5859 log_err("uloc_forLanguageTag parsed length of %d for input language tag [%s] - expected parsed length: %d\n", 5860 parsedLen, langtag_to_locale[i].bcpID, expParsedLen); 5861 } 5862 } 5863 } 5864 } 5865 5866 static void TestToUnicodeLocaleKey(void) 5867 { 5868 /* $IN specifies the result should be the input pointer itself */ 5869 static const char* DATA[][2] = { 5870 {"calendar", "ca"}, 5871 {"CALEndar", "ca"}, /* difference casing */ 5872 {"ca", "ca"}, /* bcp key itself */ 5873 {"kv", "kv"}, /* no difference between legacy and bcp */ 5874 {"foo", NULL}, /* unknown, bcp ill-formed */ 5875 {"ZZ", "$IN"}, /* unknown, bcp well-formed - */ 5876 {NULL, NULL} 5877 }; 5878 5879 int32_t i; 5880 for (i = 0; DATA[i][0] != NULL; i++) { 5881 const char* keyword = DATA[i][0]; 5882 const char* expected = DATA[i][1]; 5883 const char* bcpKey = NULL; 5884 5885 bcpKey = uloc_toUnicodeLocaleKey(keyword); 5886 if (expected == NULL) { 5887 if (bcpKey != NULL) { 5888 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", keyword, bcpKey); 5889 } 5890 } else if (bcpKey == NULL) { 5891 log_data_err("toUnicodeLocaleKey: keyword=%s => NULL, expected=%s\n", keyword, expected); 5892 } else if (uprv_strcmp(expected, "$IN") == 0) { 5893 if (bcpKey != keyword) { 5894 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword, bcpKey, keyword); 5895 } 5896 } else if (uprv_strcmp(bcpKey, expected) != 0) { 5897 log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=%s\n", keyword, bcpKey, expected); 5898 } 5899 } 5900 } 5901 5902 static void TestToLegacyKey(void) 5903 { 5904 /* $IN specifies the result should be the input pointer itself */ 5905 static const char* DATA[][2] = { 5906 {"kb", "colbackwards"}, 5907 {"kB", "colbackwards"}, /* different casing */ 5908 {"Collation", "collation"}, /* keyword itself with different casing */ 5909 {"kv", "kv"}, /* no difference between legacy and bcp */ 5910 {"foo", "$IN"}, /* unknown, bcp ill-formed */ 5911 {"ZZ", "$IN"}, /* unknown, bcp well-formed */ 5912 {"e=mc2", NULL}, /* unknown, bcp/legacy ill-formed */ 5913 {NULL, NULL} 5914 }; 5915 5916 int32_t i; 5917 for (i = 0; DATA[i][0] != NULL; i++) { 5918 const char* keyword = DATA[i][0]; 5919 const char* expected = DATA[i][1]; 5920 const char* legacyKey = NULL; 5921 5922 legacyKey = uloc_toLegacyKey(keyword); 5923 if (expected == NULL) { 5924 if (legacyKey != NULL) { 5925 log_err("toLegacyKey: keyword=%s => %s, expected=NULL\n", keyword, legacyKey); 5926 } 5927 } else if (legacyKey == NULL) { 5928 log_err("toLegacyKey: keyword=%s => NULL, expected=%s\n", keyword, expected); 5929 } else if (uprv_strcmp(expected, "$IN") == 0) { 5930 if (legacyKey != keyword) { 5931 log_err("toLegacyKey: keyword=%s => %s, expected=%s(input pointer)\n", keyword, legacyKey, keyword); 5932 } 5933 } else if (uprv_strcmp(legacyKey, expected) != 0) { 5934 log_data_err("toUnicodeLocaleKey: keyword=%s, %s, expected=%s\n", keyword, legacyKey, expected); 5935 } 5936 } 5937 } 5938 5939 static void TestToUnicodeLocaleType(void) 5940 { 5941 /* $IN specifies the result should be the input pointer itself */ 5942 static const char* DATA[][3] = { 5943 {"tz", "Asia/Kolkata", "inccu"}, 5944 {"calendar", "gregorian", "gregory"}, 5945 {"ca", "gregorian", "gregory"}, 5946 {"ca", "Gregorian", "gregory"}, 5947 {"ca", "buddhist", "buddhist"}, 5948 {"Calendar", "Japanese", "japanese"}, 5949 {"calendar", "Islamic-Civil", "islamic-civil"}, 5950 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */ 5951 {"colalternate", "NON-IGNORABLE", "noignore"}, 5952 {"colcaselevel", "yes", "true"}, 5953 {"tz", "america/new_york", "usnyc"}, 5954 {"tz", "Asia/Kolkata", "inccu"}, 5955 {"timezone", "navajo", "usden"}, 5956 {"ca", "aaaa", "$IN"}, /* unknown type, well-formed type */ 5957 {"ca", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */ 5958 {"zz", "gregorian", NULL}, /* unknown key, ill-formed type */ 5959 {"co", "foo-", NULL}, /* unknown type, ill-formed type */ 5960 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */ 5961 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */ 5962 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */ 5963 {"kr", "digit-spacepunct", NULL}, /* invalid (bcp ill-formed) reordercode type */ 5964 {NULL, NULL, NULL} 5965 }; 5966 5967 int32_t i; 5968 for (i = 0; DATA[i][0] != NULL; i++) { 5969 const char* keyword = DATA[i][0]; 5970 const char* value = DATA[i][1]; 5971 const char* expected = DATA[i][2]; 5972 const char* bcpType = NULL; 5973 5974 bcpType = uloc_toUnicodeLocaleType(keyword, value); 5975 if (expected == NULL) { 5976 if (bcpType != NULL) { 5977 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=NULL\n", keyword, value, bcpType); 5978 } 5979 } else if (bcpType == NULL) { 5980 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => NULL, expected=%s\n", keyword, value, expected); 5981 } else if (uprv_strcmp(expected, "$IN") == 0) { 5982 if (bcpType != value) { 5983 log_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword, value, bcpType, value); 5984 } 5985 } else if (uprv_strcmp(bcpType, expected) != 0) { 5986 log_data_err("toUnicodeLocaleType: keyword=%s, value=%s => %s, expected=%s\n", keyword, value, bcpType, expected); 5987 } 5988 } 5989 } 5990 5991 static void TestToLegacyType(void) 5992 { 5993 /* $IN specifies the result should be the input pointer itself */ 5994 static const char* DATA[][3] = { 5995 {"calendar", "gregory", "gregorian"}, 5996 {"ca", "gregory", "gregorian"}, 5997 {"ca", "Gregory", "gregorian"}, 5998 {"ca", "buddhist", "buddhist"}, 5999 {"Calendar", "Japanese", "japanese"}, 6000 {"calendar", "Islamic-Civil", "islamic-civil"}, 6001 {"calendar", "islamicc", "islamic-civil"}, /* bcp type alias */ 6002 {"colalternate", "noignore", "non-ignorable"}, 6003 {"colcaselevel", "true", "yes"}, 6004 {"tz", "usnyc", "America/New_York"}, 6005 {"tz", "inccu", "Asia/Calcutta"}, 6006 {"timezone", "usden", "America/Denver"}, 6007 {"timezone", "usnavajo", "America/Denver"}, /* bcp type alias */ 6008 {"colstrength", "quarternary", "quaternary"}, /* type alias */ 6009 {"ca", "aaaa", "$IN"}, /* unknown type */ 6010 {"calendar", "gregory-japanese-islamic", "$IN"}, /* unknown type, well-formed type */ 6011 {"zz", "gregorian", "$IN"}, /* unknown key, bcp ill-formed type */ 6012 {"ca", "gregorian-calendar", "$IN"}, /* known key, bcp ill-formed type */ 6013 {"co", "e=mc2", NULL}, /* known key, ill-formed bcp/legacy type */ 6014 {"variableTop", "00A0", "$IN"}, /* valid codepoints type */ 6015 {"variableTop", "wxyz", "$IN"}, /* invalid codepoints type - return as is for now */ 6016 {"kr", "space-punct", "space-punct"}, /* valid reordercode type */ 6017 {"kr", "digit-spacepunct", "digit-spacepunct"}, /* invalid reordercode type, but ok for legacy syntax */ 6018 {NULL, NULL, NULL} 6019 }; 6020 6021 int32_t i; 6022 for (i = 0; DATA[i][0] != NULL; i++) { 6023 const char* keyword = DATA[i][0]; 6024 const char* value = DATA[i][1]; 6025 const char* expected = DATA[i][2]; 6026 const char* legacyType = NULL; 6027 6028 legacyType = uloc_toLegacyType(keyword, value); 6029 if (expected == NULL) { 6030 if (legacyType != NULL) { 6031 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=NULL\n", keyword, value, legacyType); 6032 } 6033 } else if (legacyType == NULL) { 6034 log_err("toLegacyType: keyword=%s, value=%s => NULL, expected=%s\n", keyword, value, expected); 6035 } else if (uprv_strcmp(expected, "$IN") == 0) { 6036 if (legacyType != value) { 6037 log_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s(input pointer)\n", keyword, value, legacyType, value); 6038 } 6039 } else if (uprv_strcmp(legacyType, expected) != 0) { 6040 log_data_err("toLegacyType: keyword=%s, value=%s => %s, expected=%s\n", keyword, value, legacyType, expected); 6041 } 6042 } 6043 } 6044 6045 6046 6047 static void test_unicode_define(const char *namech, char ch, const char *nameu, UChar uch) 6048 { 6049 UChar asUch[1]; 6050 asUch[0]=0; 6051 log_verbose("Testing whether %s[\\x%02x,'%c'] == %s[U+%04X]\n", namech, ch,(int)ch, nameu, (int) uch); 6052 u_charsToUChars(&ch, asUch, 1); 6053 if(asUch[0] != uch) { 6054 log_err("FAIL: %s[\\x%02x,'%c'] maps to U+%04X, but %s = U+%04X\n", namech, ch, (int)ch, (int)asUch[0], nameu, (int)uch); 6055 } else { 6056 log_verbose(" .. OK, == U+%04X\n", (int)asUch[0]); 6057 } 6058 } 6059 6060 #define TEST_UNICODE_DEFINE(x,y) test_unicode_define(#x, (char)(x), #y, (UChar)(y)) 6061 6062 static void TestUnicodeDefines(void) { 6063 TEST_UNICODE_DEFINE(ULOC_KEYWORD_SEPARATOR, ULOC_KEYWORD_SEPARATOR_UNICODE); 6064 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN, ULOC_KEYWORD_ASSIGN_UNICODE); 6065 TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE); 6066 } 6067 6068 static void TestIsRightToLeft() { 6069 // API test only. More test cases in intltest/LocaleTest. 6070 if(uloc_isRightToLeft("root") || !uloc_isRightToLeft("EN-HEBR")) { 6071 log_err("uloc_isRightToLeft() failed"); 6072 } 6073 } 6074