1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package libcore.java.util; 18 19 import java.text.BreakIterator; 20 import java.text.Collator; 21 import java.text.DateFormat; 22 import java.text.DateFormatSymbols; 23 import java.text.DecimalFormatSymbols; 24 import java.text.NumberFormat; 25 import java.util.Calendar; 26 import java.util.IllformedLocaleException; 27 import java.util.Locale; 28 import java.util.MissingResourceException; 29 30 public class LocaleTest extends junit.framework.TestCase { 31 // http://b/2611311; if there's no display language/country/variant, use the raw codes. 32 public void test_getDisplayName_invalid() throws Exception { 33 Locale invalid = new Locale("AaBbCc", "DdEeFf", "GgHhIi"); 34 35 assertEquals("aabbcc", invalid.getLanguage()); 36 assertEquals("DDEEFF", invalid.getCountry()); 37 assertEquals("GgHhIi", invalid.getVariant()); 38 39 // Android using icu4c < 49.2 returned empty strings for display language, country, 40 // and variant, but a display name made up of the raw strings. 41 // Newer releases return slightly different results, but no less unreasonable. 42 assertEquals("aabbcc", invalid.getDisplayLanguage()); 43 assertEquals("DDEEFF", invalid.getDisplayCountry()); 44 assertEquals("GGHHII", invalid.getDisplayVariant()); 45 assertEquals("aabbcc (DDEEFF,GGHHII)", invalid.getDisplayName()); 46 } 47 48 public void test_getDisplayName_emptyCodes() { 49 Locale emptyLanguage = new Locale("", "DdeEFf"); 50 assertEquals("", emptyLanguage.getDisplayLanguage()); 51 52 Locale emptyCountry = new Locale("AaBbCc", ""); 53 assertEquals("", emptyCountry.getDisplayCountry()); 54 55 Locale emptyCountryAndLanguage = new Locale("", "", "Farl"); 56 assertEquals("", emptyCountryAndLanguage.getDisplayLanguage()); 57 assertEquals("", emptyCountryAndLanguage.getDisplayCountry()); 58 assertEquals("Farl", emptyCountryAndLanguage.getDisplayVariant()); 59 } 60 61 // http://b/2611311; if there's no display language/country/variant, use the raw codes. 62 public void test_getDisplayName_unknown() throws Exception { 63 Locale unknown = new Locale("xx", "YY", "Traditional"); 64 assertEquals("xx", unknown.getLanguage()); 65 assertEquals("YY", unknown.getCountry()); 66 assertEquals("Traditional", unknown.getVariant()); 67 68 assertEquals("xx", unknown.getDisplayLanguage()); 69 assertEquals("YY", unknown.getDisplayCountry()); 70 assertEquals("Traditional", unknown.getDisplayVariant()); 71 assertEquals("xx (YY,Traditional)", unknown.getDisplayName()); 72 } 73 74 public void test_getDisplayName_easy() throws Exception { 75 assertEquals("English", Locale.ENGLISH.getDisplayLanguage(Locale.ENGLISH)); 76 assertEquals("German", Locale.GERMAN.getDisplayLanguage(Locale.ENGLISH)); 77 assertEquals("Englisch", Locale.ENGLISH.getDisplayLanguage(Locale.GERMAN)); 78 assertEquals("Deutsch", Locale.GERMAN.getDisplayLanguage(Locale.GERMAN)); 79 } 80 81 // https://b/issue?id=13790528 82 public void test_getDisplayName_withScriptsAndVariants() throws Exception { 83 // Script + Country. 84 assertEquals("Chinese (Traditional Han,China)", 85 Locale.forLanguageTag("zh-Hant-CN").getDisplayName(Locale.US)); 86 // Script + Variant. 87 assertEquals("Chinese (Traditional Han,VARIANT)", 88 Locale.forLanguageTag("zh-Hant-VARIANT").getDisplayName(Locale.US)); 89 // Country + Variant. 90 assertEquals("Chinese (China,VARIANT)", 91 Locale.forLanguageTag("zh-CN-VARIANT").getDisplayName(Locale.US)); 92 // Script + Country + variant. 93 assertEquals("Chinese (Traditional Han,China,VARIANT)", 94 Locale.forLanguageTag("zh-Hant-CN-VARIANT").getDisplayName(Locale.US)); 95 } 96 97 public void test_getDisplayCountry_8870289() throws Exception { 98 assertEquals("Hong Kong", new Locale("", "HK").getDisplayCountry(Locale.US)); 99 assertEquals("Macau", new Locale("", "MO").getDisplayCountry(Locale.US)); 100 assertEquals("Palestine", new Locale("", "PS").getDisplayCountry(Locale.US)); 101 102 assertEquals("Cocos (Keeling) Islands", new Locale("", "CC").getDisplayCountry(Locale.US)); 103 assertEquals("Congo (DRC)", new Locale("", "CD").getDisplayCountry(Locale.US)); 104 assertEquals("Congo (Republic)", new Locale("", "CG").getDisplayCountry(Locale.US)); 105 assertEquals("Falkland Islands (Islas Malvinas)", new Locale("", "FK").getDisplayCountry(Locale.US)); 106 assertEquals("Macedonia (FYROM)", new Locale("", "MK").getDisplayCountry(Locale.US)); 107 assertEquals("Myanmar (Burma)", new Locale("", "MM").getDisplayCountry(Locale.US)); 108 assertEquals("Taiwan", new Locale("", "TW").getDisplayCountry(Locale.US)); 109 } 110 111 public void test_tl_and_fil() throws Exception { 112 // In jb-mr1, we had a last-minute hack to always return "Filipino" because 113 // icu4c 4.8 didn't have any localizations for fil. (http://b/7291355). 114 // 115 // After the icu4c 4.9 upgrade, we could localize "fil" correctly, though we 116 // needed another hack to supply "fil" instead of "tl" to icu4c. (http://b/8023288). 117 // 118 // These hacks have now been reverted, so "tl" really does represent 119 // tagalog and not filipino. 120 Locale tl = new Locale("tl"); 121 Locale tl_PH = new Locale("tl", "PH"); 122 assertEquals("Tagalog", tl.getDisplayLanguage(Locale.ENGLISH)); 123 assertEquals("Tagalog", tl_PH.getDisplayLanguage(Locale.ENGLISH)); 124 assertEquals("tl", tl.getDisplayLanguage(tl)); 125 assertEquals("tl", tl_PH.getDisplayLanguage(tl_PH)); 126 127 Locale es_MX = new Locale("es", "MX"); 128 assertEquals("tagalo", tl.getDisplayLanguage(es_MX)); 129 assertEquals("tagalo", tl_PH.getDisplayLanguage(es_MX)); 130 131 // Assert that we can deal with "fil" correctly, since we've switched 132 // to using "fil" for Filipino, and not "tl". (http://b/15873165). 133 Locale fil = new Locale("fil"); 134 Locale fil_PH = new Locale("fil", "PH"); 135 assertEquals("Filipino", fil.getDisplayLanguage(Locale.ENGLISH)); 136 assertEquals("Filipino", fil_PH.getDisplayLanguage(Locale.ENGLISH)); 137 assertEquals("Filipino", fil.getDisplayLanguage(fil)); 138 assertEquals("Filipino", fil_PH.getDisplayLanguage(fil_PH)); 139 140 assertEquals("filipino", fil.getDisplayLanguage(es_MX)); 141 assertEquals("filipino", fil_PH.getDisplayLanguage(es_MX)); 142 } 143 144 // http://b/3452611; Locale.getDisplayLanguage fails for the obsolete language codes. 145 public void test_getDisplayName_obsolete() throws Exception { 146 // he (new) -> iw (obsolete) 147 assertObsolete("he", "iw", ""); 148 // id (new) -> in (obsolete) 149 assertObsolete("id", "in", "Bahasa Indonesia"); 150 } 151 152 private static void assertObsolete(String newCode, String oldCode, String displayName) { 153 // Either code should get you the same locale. 154 Locale newLocale = new Locale(newCode); 155 Locale oldLocale = new Locale(oldCode); 156 assertEquals(newLocale, oldLocale); 157 158 // No matter what code you used to create the locale, you should get the old code back. 159 assertEquals(oldCode, newLocale.getLanguage()); 160 assertEquals(oldCode, oldLocale.getLanguage()); 161 162 // Check we get the right display name. 163 assertEquals(displayName, newLocale.getDisplayLanguage(newLocale)); 164 assertEquals(displayName, oldLocale.getDisplayLanguage(newLocale)); 165 assertEquals(displayName, newLocale.getDisplayLanguage(oldLocale)); 166 assertEquals(displayName, oldLocale.getDisplayLanguage(oldLocale)); 167 168 // Check that none of the 'getAvailableLocales' methods are accidentally returning two 169 // equal locales (because to ICU they're different, but we mangle one into the other). 170 assertOnce(newLocale, BreakIterator.getAvailableLocales()); 171 assertOnce(newLocale, Calendar.getAvailableLocales()); 172 assertOnce(newLocale, Collator.getAvailableLocales()); 173 assertOnce(newLocale, DateFormat.getAvailableLocales()); 174 assertOnce(newLocale, DateFormatSymbols.getAvailableLocales()); 175 assertOnce(newLocale, NumberFormat.getAvailableLocales()); 176 assertOnce(newLocale, Locale.getAvailableLocales()); 177 } 178 179 private static void assertOnce(Locale element, Locale[] array) { 180 int count = 0; 181 for (Locale l : array) { 182 if (l.equals(element)) { 183 ++count; 184 } 185 } 186 assertEquals(1, count); 187 } 188 189 public void test_getISO3Country() { 190 // Empty country code. 191 assertEquals("", new Locale("en", "").getISO3Country()); 192 193 // Invalid country code. 194 try { 195 assertEquals("", new Locale("en", "XX").getISO3Country()); 196 fail(); 197 } catch (MissingResourceException expected) { 198 assertEquals("FormatData_en_XX", expected.getClassName()); 199 assertEquals("ShortCountry", expected.getKey()); 200 } 201 202 // Valid country code. 203 assertEquals("CAN", new Locale("", "CA").getISO3Country()); 204 assertEquals("CAN", new Locale("en", "CA").getISO3Country()); 205 assertEquals("CAN", new Locale("xx", "CA").getISO3Country()); 206 207 // 3 letter country codes. 208 assertEquals("CAN", new Locale("en", "CAN").getISO3Country()); 209 assertEquals("CAN", new Locale("frankenderp", "CAN").getISO3Country()); 210 } 211 212 public void test_getISO3Language() { 213 // Empty language code. 214 assertEquals("", new Locale("", "US").getISO3Language()); 215 216 // Invalid language code. 217 try { 218 assertEquals("", new Locale("xx", "US").getISO3Language()); 219 fail(); 220 } catch (MissingResourceException expected) { 221 assertEquals("FormatData_xx_US", expected.getClassName()); 222 assertEquals("ShortLanguage", expected.getKey()); 223 } 224 225 // Valid language code. 226 assertEquals("eng", new Locale("en", "").getISO3Language()); 227 assertEquals("eng", new Locale("en", "CA").getISO3Language()); 228 assertEquals("eng", new Locale("en", "XX").getISO3Language()); 229 230 // 3 letter language code. 231 assertEquals("eng", new Locale("eng", "USA").getISO3Language()); 232 assertEquals("eng", new Locale("eng", "US").getISO3Language()); 233 } 234 235 public void test_Builder_setLanguage() { 236 Locale.Builder b = new Locale.Builder(); 237 238 // Should normalize to lower case. 239 b.setLanguage("EN"); 240 assertEquals("en", b.build().getLanguage()); 241 242 b = new Locale.Builder(); 243 244 // Too short. 245 try { 246 b.setLanguage("e"); 247 fail(); 248 } catch (IllformedLocaleException expected) { 249 } 250 251 // Too long 252 try { 253 b.setLanguage("engl"); 254 fail(); 255 } catch (IllformedLocaleException expected) { 256 } 257 258 // Contains non ASCII characters 259 try { 260 b.setLanguage(""); 261 fail(); 262 } catch (IllformedLocaleException expected) { 263 } 264 265 // Null or empty languages must clear state. 266 b = new Locale.Builder(); 267 b.setLanguage("en"); 268 b.setLanguage(null); 269 assertEquals("", b.build().getLanguage()); 270 271 b = new Locale.Builder(); 272 b.setLanguage("en"); 273 b.setLanguage(""); 274 assertEquals("", b.build().getLanguage()); 275 } 276 277 public void test_Builder_setRegion() { 278 Locale.Builder b = new Locale.Builder(); 279 280 // Should normalize to upper case. 281 b.setRegion("us"); 282 assertEquals("US", b.build().getCountry()); 283 284 b = new Locale.Builder(); 285 286 // Too short. 287 try { 288 b.setRegion("e"); 289 fail(); 290 } catch (IllformedLocaleException expected) { 291 } 292 293 // Too long 294 try { 295 b.setRegion("USA"); 296 fail(); 297 } catch (IllformedLocaleException expected) { 298 } 299 300 // Contains non ASCII characters 301 try { 302 b.setLanguage(""); 303 fail(); 304 } catch (IllformedLocaleException expected) { 305 } 306 307 // Null or empty regions must clear state. 308 b = new Locale.Builder(); 309 b.setRegion("US"); 310 b.setRegion(null); 311 assertEquals("", b.build().getCountry()); 312 313 b = new Locale.Builder(); 314 b.setRegion("US"); 315 b.setRegion(""); 316 assertEquals("", b.build().getCountry()); 317 } 318 319 public void test_Builder_setVariant() { 320 Locale.Builder b = new Locale.Builder(); 321 322 // Should normalize "_" to "-" 323 b = new Locale.Builder(); 324 b.setVariant("vArIaNt-VaRiAnT-VARIANT"); 325 assertEquals("vArIaNt_VaRiAnT_VARIANT", b.build().getVariant()); 326 327 b = new Locale.Builder(); 328 // Too short 329 try { 330 b.setVariant("shor"); 331 fail(); 332 } catch (IllformedLocaleException expected) { 333 } 334 335 // Too long 336 try { 337 b.setVariant("waytoolong"); 338 fail(); 339 } catch (IllformedLocaleException expected) { 340 } 341 342 try { 343 b.setVariant("foooo-foooo-fo"); 344 fail(); 345 } catch (IllformedLocaleException expected) { 346 } 347 348 // Special case. Variants of length 4 are allowed when the first 349 // character is a digit. 350 b.setVariant("0ABC"); 351 assertEquals("0ABC", b.build().getVariant()); 352 353 b = new Locale.Builder(); 354 b.setVariant("variant"); 355 b.setVariant(null); 356 assertEquals("", b.build().getVariant()); 357 358 b = new Locale.Builder(); 359 b.setVariant("variant"); 360 b.setVariant(""); 361 assertEquals("", b.build().getVariant()); 362 } 363 364 public void test_Builder_setLocale() { 365 // Default case. 366 Locale.Builder b = new Locale.Builder(); 367 b.setLocale(Locale.US); 368 assertEquals("en", b.build().getLanguage()); 369 assertEquals("US", b.build().getCountry()); 370 371 // Should throw when locale is malformed. 372 // - Bad language 373 Locale bad = new Locale("e", "US"); 374 b = new Locale.Builder(); 375 try { 376 b.setLocale(bad); 377 fail(); 378 } catch (IllformedLocaleException expected) { 379 } 380 // - Bad country 381 bad = new Locale("en", "USA"); 382 try { 383 b.setLocale(bad); 384 fail(); 385 } catch (IllformedLocaleException expected) { 386 } 387 388 // - Bad variant 389 bad = new Locale("en", "US", "c"); 390 try { 391 b.setLocale(bad); 392 fail(); 393 } catch (IllformedLocaleException expected) { 394 } 395 396 // Test values are normalized as they should be 397 b = new Locale.Builder(); 398 Locale good = new Locale("EN", "us", "variant-VARIANT"); 399 b.setLocale(good); 400 Locale l = b.build(); 401 assertEquals("en", l.getLanguage()); 402 assertEquals("US", l.getCountry()); 403 assertEquals("variant_VARIANT", l.getVariant()); 404 405 // Test that none of the existing fields are messed with 406 // if the locale update fails. 407 b = new Locale.Builder(); 408 b.setLanguage("fr").setRegion("FR"); 409 410 try { 411 b.setLocale(bad); 412 fail(); 413 } catch (IllformedLocaleException expected) { 414 } 415 416 l = b.build(); 417 assertEquals("fr", l.getLanguage()); 418 assertEquals("FR", l.getCountry()); 419 } 420 421 public void test_Builder_setScript() { 422 Locale.Builder b = new Locale.Builder(); 423 424 // Should normalize variants to lower case. 425 b.setScript("lAtN"); 426 assertEquals("Latn", b.build().getScript()); 427 428 b = new Locale.Builder(); 429 // Too short 430 try { 431 b.setScript("lat"); 432 fail(); 433 } catch (IllformedLocaleException expected) { 434 } 435 436 // Too long 437 try { 438 b.setScript("latin"); 439 fail(); 440 } catch (IllformedLocaleException expected) { 441 } 442 443 b = new Locale.Builder(); 444 b.setScript("Latn"); 445 b.setScript(null); 446 assertEquals("", b.build().getScript()); 447 448 b = new Locale.Builder(); 449 b.setScript("Latn"); 450 b.setScript(""); 451 assertEquals("", b.build().getScript()); 452 } 453 454 public void test_Builder_clear() { 455 Locale.Builder b = new Locale.Builder(); 456 b.setLanguage("en").setScript("Latn").setRegion("US") 457 .setVariant("POSIX").setExtension('g', "foo") 458 .setUnicodeLocaleKeyword("fo", "baar") 459 .addUnicodeLocaleAttribute("baaaaz"); 460 461 Locale l = b.clear().build(); 462 assertEquals("", l.getLanguage()); 463 assertEquals("", l.getCountry()); 464 assertEquals("", l.getVariant()); 465 assertEquals("", l.getScript()); 466 assertTrue(l.getExtensionKeys().isEmpty()); 467 } 468 469 public void test_Builder_setExtension() { 470 Locale.Builder b = new Locale.Builder(); 471 b.setExtension('g', "FO_ba-BR_bg"); 472 473 Locale l = b.build(); 474 assertEquals("fo-ba-br-bg", l.getExtension('g')); 475 476 b = new Locale.Builder(); 477 478 // Too short 479 try { 480 b.setExtension('g', "fo-ba-br-x"); 481 fail(); 482 } catch (IllformedLocaleException expected) { 483 } 484 485 // Too long 486 try { 487 b.setExtension('g', "fo-ba-br-extension"); 488 fail(); 489 } catch (IllformedLocaleException expected) { 490 } 491 492 // Special case, the private use extension allows single char subtags. 493 b.setExtension(Locale.PRIVATE_USE_EXTENSION, "fo-ba-br-m"); 494 l = b.build(); 495 assertEquals("fo-ba-br-m", l.getExtension('x')); 496 497 // Special case, the unicode locale extension must be parsed into 498 // its individual components. The correctness of the parse is tested 499 // in test_parseUnicodeExtension. 500 b.setExtension(Locale.UNICODE_LOCALE_EXTENSION, "foooo_BaaaR-BA_Baz-bI_BIZ"); 501 l = b.build(); 502 // Note that attributes and keywords are sorted alphabetically. 503 assertEquals("baaar-foooo-ba-baz-bi-biz", l.getExtension('u')); 504 505 assertTrue(l.getUnicodeLocaleAttributes().contains("foooo")); 506 assertTrue(l.getUnicodeLocaleAttributes().contains("baaar")); 507 assertEquals("baz", l.getUnicodeLocaleType("ba")); 508 assertEquals("biz", l.getUnicodeLocaleType("bi")); 509 } 510 511 public void test_Builder_clearExtensions() { 512 Locale.Builder b = new Locale.Builder(); 513 b.setExtension('g', "FO_ba-BR_bg"); 514 b.setExtension(Locale.PRIVATE_USE_EXTENSION, "fo-ba-br-m"); 515 b.clearExtensions(); 516 517 assertTrue(b.build().getExtensionKeys().isEmpty()); 518 } 519 520 private static Locale fromLanguageTag(String languageTag, boolean useBuilder) { 521 if (useBuilder) { 522 return (new Locale.Builder().setLanguageTag(languageTag).build()); 523 } else { 524 return Locale.forLanguageTag(languageTag); 525 } 526 } 527 528 private void test_setLanguageTag_wellFormedsingleSubtag(boolean useBuilder) { 529 Locale l = fromLanguageTag("en", useBuilder); 530 assertEquals("en", l.getLanguage()); 531 532 l = fromLanguageTag("eng", useBuilder); 533 assertEquals("eng", l.getLanguage()); 534 } 535 536 private void test_setLanguageTag_twoWellFormedSubtags(boolean useBuilder) { 537 Locale l = fromLanguageTag("en-US", useBuilder); 538 assertEquals("en", l.getLanguage()); 539 assertEquals("US", l.getCountry()); 540 541 l = fromLanguageTag("eng-419", useBuilder); 542 assertEquals("eng", l.getLanguage()); 543 assertEquals("419", l.getCountry()); 544 545 // Script tags shouldn't be mis-recognized as regions. 546 l = fromLanguageTag("en-Latn", useBuilder); 547 assertEquals("en", l.getLanguage()); 548 assertEquals("", l.getCountry()); 549 assertEquals("Latn", l.getScript()); 550 551 // Neither should variant tags. 552 l = fromLanguageTag("en-POSIX", useBuilder); 553 assertEquals("en", l.getLanguage()); 554 assertEquals("", l.getCountry()); 555 assertEquals("", l.getScript()); 556 assertEquals("POSIX", l.getVariant()); 557 } 558 559 public void test_Builder_setLanguageTag_malformedTags() { 560 try { 561 fromLanguageTag("a", true); 562 fail(); 563 } catch (IllformedLocaleException ifle) { 564 } 565 566 // Three subtags 567 // lang-region-illformedvariant 568 try { 569 fromLanguageTag("en-US-BA", true); 570 fail(); 571 } catch (IllformedLocaleException expected) { 572 } 573 574 // lang-variant-illformedvariant 575 try { 576 fromLanguageTag("en-FOOOO-BA", true); 577 fail(); 578 } catch (IllformedLocaleException expected) { 579 } 580 581 // Four or more sub tags 582 try { 583 fromLanguageTag("en-US-POSIX-P2", true); 584 fail(); 585 } catch (IllformedLocaleException expected) { 586 } 587 588 try { 589 fromLanguageTag("en-Latn-US-P2", true); 590 fail(); 591 } catch (IllformedLocaleException expected) { 592 } 593 594 // Extensions 595 // Ill-formed empty extension. 596 try { 597 fromLanguageTag("en-f-f", true); 598 fail(); 599 } catch (IllformedLocaleException expected) { 600 } 601 602 // Ill-formed empty extension. 603 try { 604 fromLanguageTag("en-f", true); 605 fail(); 606 } catch (IllformedLocaleException expected) { 607 } 608 609 // Two extension keys in a row (i.e, another case of an ill-formed 610 // empty exception). 611 try { 612 fromLanguageTag("en-f-g-fo-baar", true); 613 fail(); 614 } catch (IllformedLocaleException expected) { 615 } 616 617 // Dangling empty key after a well formed extension. 618 try { 619 fromLanguageTag("en-f-fo-baar-g", true); 620 fail(); 621 } catch (IllformedLocaleException expected) { 622 } 623 624 // Ill-formed extension with long subtag. 625 try { 626 fromLanguageTag("en-f-fooobaaaz", true); 627 fail(); 628 } catch (IllformedLocaleException expected) { 629 } 630 } 631 632 private void test_setLanguageTag_threeWellFormedSubtags(boolean useBuilder) { 633 // lang-region-variant 634 Locale l = fromLanguageTag("en-US-FOOOO", useBuilder); 635 assertEquals("en", l.getLanguage()); 636 assertEquals("US", l.getCountry()); 637 assertEquals("", l.getScript()); 638 assertEquals("FOOOO", l.getVariant()); 639 640 // lang-script-variant 641 l = fromLanguageTag("en-Latn-FOOOO", useBuilder); 642 assertEquals("en", l.getLanguage()); 643 assertEquals("", l.getCountry()); 644 assertEquals("Latn", l.getScript()); 645 assertEquals("FOOOO", l.getVariant()); 646 647 // lang-script-region 648 l = fromLanguageTag("en-Latn-US", useBuilder); 649 assertEquals("en", l.getLanguage()); 650 assertEquals("US", l.getCountry()); 651 assertEquals("Latn", l.getScript()); 652 assertEquals("", l.getVariant()); 653 654 // lang-variant-variant 655 l = fromLanguageTag("en-FOOOO-BAAAR", useBuilder); 656 assertEquals("en", l.getLanguage()); 657 assertEquals("", l.getCountry()); 658 assertEquals("", l.getScript()); 659 assertEquals("FOOOO_BAAAR", l.getVariant()); 660 } 661 662 private void test_setLanguageTag_fourOrMoreWellFormedSubtags(boolean useBuilder) { 663 // lang-script-region-variant. 664 Locale l = fromLanguageTag("en-Latn-US-foooo", useBuilder); 665 assertEquals("en", l.getLanguage()); 666 assertEquals("Latn", l.getScript()); 667 assertEquals("US", l.getCountry()); 668 assertEquals("foooo", l.getVariant()); 669 670 // Variant with multiple subtags. 671 l = fromLanguageTag("en-Latn-US-foooo-gfffh", useBuilder); 672 assertEquals("en", l.getLanguage()); 673 assertEquals("Latn", l.getScript()); 674 assertEquals("US", l.getCountry()); 675 assertEquals("foooo_gfffh", l.getVariant()); 676 677 // Variant with 3 subtags. POSIX shouldn't be recognized 678 // as a region or a script. 679 l = fromLanguageTag("en-POSIX-P2003-P2004", useBuilder); 680 assertEquals("en", l.getLanguage()); 681 assertEquals("", l.getScript()); 682 assertEquals("", l.getCountry()); 683 assertEquals("POSIX_P2003_P2004", l.getVariant()); 684 685 // lang-script-variant-variant. 686 l = fromLanguageTag("en-Latn-POSIX-P2003", useBuilder); 687 assertEquals("en", l.getLanguage()); 688 assertEquals("Latn", l.getScript()); 689 assertEquals("", l.getCountry()); 690 assertEquals("POSIX_P2003", l.getVariant()); 691 692 // lang-region-variant-variant 693 l = fromLanguageTag("en-US-POSIX-P2003", useBuilder); 694 assertEquals("en", l.getLanguage()); 695 assertEquals("", l.getScript()); 696 assertEquals("US", l.getCountry()); 697 assertEquals("POSIX_P2003", l.getVariant()); 698 } 699 700 private void test_setLanguageTag_withWellFormedExtensions(boolean useBuilder) { 701 Locale l = fromLanguageTag("en-Latn-GB-foooo-g-fo-bar-baaz", useBuilder); 702 assertEquals("en", l.getLanguage()); 703 assertEquals("Latn", l.getScript()); 704 assertEquals("GB", l.getCountry()); 705 assertEquals("foooo", l.getVariant()); 706 assertEquals("fo-bar-baaz", l.getExtension('g')); 707 708 // Multiple extensions 709 l = fromLanguageTag("en-Latn-US-foooo-g-fo-bar-h-go-gaz", useBuilder); 710 assertEquals("en", l.getLanguage()); 711 assertEquals("Latn", l.getScript()); 712 assertEquals("US", l.getCountry()); 713 assertEquals("foooo", l.getVariant()); 714 assertEquals("fo-bar", l.getExtension('g')); 715 assertEquals("go-gaz", l.getExtension('h')); 716 717 // Unicode locale extension. 718 l = fromLanguageTag("en-Latn-US-foooo-u-koooo-fo-bar", useBuilder); 719 assertEquals("en", l.getLanguage()); 720 assertEquals("Latn", l.getScript()); 721 assertEquals("US", l.getCountry()); 722 assertEquals("koooo-fo-bar", l.getExtension('u')); 723 assertTrue(l.getUnicodeLocaleAttributes().contains("koooo")); 724 assertEquals("bar", l.getUnicodeLocaleType("fo")); 725 726 // Extensions without variants 727 l = fromLanguageTag("en-Latn-US-f-fo", useBuilder); 728 assertEquals("en", l.getLanguage()); 729 assertEquals("Latn", l.getScript()); 730 assertEquals("US", l.getCountry()); 731 assertEquals("fo", l.getExtension('f')); 732 733 l = fromLanguageTag("en-Latn-f-fo", useBuilder); 734 assertEquals("en", l.getLanguage()); 735 assertEquals("Latn", l.getScript()); 736 assertEquals("fo", l.getExtension('f')); 737 738 l = fromLanguageTag("en-f-fo", useBuilder); 739 assertEquals("en", l.getLanguage()); 740 assertEquals("", l.getScript()); 741 assertEquals("", l.getCountry()); 742 assertEquals("fo", l.getExtension('f')); 743 744 l = fromLanguageTag("en-f-fo-x-a-b-c-d-e-fo", useBuilder); 745 assertEquals("en", l.getLanguage()); 746 assertEquals("", l.getScript()); 747 assertEquals("", l.getCountry()); 748 assertEquals("fo", l.getExtension('f')); 749 assertEquals("a-b-c-d-e-fo", l.getExtension('x')); 750 } 751 752 public void test_forLanguageTag() { 753 test_setLanguageTag_wellFormedsingleSubtag(false); 754 test_setLanguageTag_twoWellFormedSubtags(false); 755 test_setLanguageTag_threeWellFormedSubtags(false); 756 test_setLanguageTag_fourOrMoreWellFormedSubtags(false); 757 test_setLanguageTag_withWellFormedExtensions(false); 758 } 759 760 public void test_Builder_setLanguageTag() { 761 test_setLanguageTag_wellFormedsingleSubtag(true); 762 test_setLanguageTag_twoWellFormedSubtags(true); 763 test_setLanguageTag_threeWellFormedSubtags(true); 764 test_setLanguageTag_fourOrMoreWellFormedSubtags(true); 765 test_setLanguageTag_withWellFormedExtensions(true); 766 } 767 768 public void test_getDisplayScript() { 769 Locale.Builder b = new Locale.Builder(); 770 b.setLanguage("en").setRegion("US").setScript("Latn"); 771 772 Locale l = b.build(); 773 774 // getDisplayScript() test relies on the default locale. We set it here to avoid test 775 // failures if the test device is set to a non-English locale. 776 Locale.setDefault(Locale.US); 777 assertEquals("Latin", l.getDisplayScript()); 778 779 assertEquals("Lateinisch", l.getDisplayScript(Locale.GERMAN)); 780 // Fallback for navajo, a language for which we don't have data. 781 assertEquals("Latin", l.getDisplayScript(new Locale("nv", "US"))); 782 783 b= new Locale.Builder(); 784 b.setLanguage("en").setRegion("US").setScript("Fooo"); 785 786 // Will be equivalent to getScriptCode for scripts that aren't 787 // registered with ISO-15429 (but are otherwise well formed). 788 l = b.build(); 789 assertEquals("Fooo", l.getDisplayScript()); 790 } 791 792 public void test_setLanguageTag_malformedTags() { 793 Locale l = fromLanguageTag("a", false); 794 assertEquals("und", l.getLanguage()); 795 assertEquals("", l.getCountry()); 796 assertEquals("", l.getVariant()); 797 assertEquals("", l.getScript()); 798 799 l = fromLanguageTag("en-US-BA", false); 800 assertEquals("en", l.getLanguage()); 801 assertEquals("US", l.getCountry()); 802 assertEquals("", l.getVariant()); 803 assertEquals("", l.getScript()); 804 805 l = fromLanguageTag("en-FOOOO-BA", false); 806 assertEquals("en", l.getLanguage()); 807 assertEquals("", l.getCountry()); 808 assertEquals("FOOOO", l.getVariant()); 809 assertEquals("", l.getScript()); 810 811 l = fromLanguageTag("en-US-POSIX-P2", false); 812 assertEquals("en", l.getLanguage()); 813 assertEquals("US", l.getCountry()); 814 assertEquals("POSIX", l.getVariant()); 815 assertEquals("", l.getScript()); 816 817 l = fromLanguageTag("en-Latn-US-P2", false); 818 assertEquals("en", l.getLanguage()); 819 assertEquals("US", l.getCountry()); 820 assertEquals("Latn", l.getScript()); 821 822 l = fromLanguageTag("en-f-f", false); 823 assertEquals("en", l.getLanguage()); 824 assertEquals("", l.getCountry()); 825 assertEquals("", l.getVariant()); 826 assertEquals("", l.getScript()); 827 828 l = fromLanguageTag("en-f", false); 829 assertEquals("en", l.getLanguage()); 830 assertEquals("", l.getCountry()); 831 assertEquals("", l.getVariant()); 832 assertEquals("", l.getScript()); 833 834 l = fromLanguageTag("en-f-fooobaaaz", false); 835 assertEquals("en", l.getLanguage()); 836 assertEquals("", l.getCountry()); 837 assertEquals("", l.getVariant()); 838 assertEquals("", l.getScript()); 839 840 l = fromLanguageTag("en-9-baa", false); 841 assertEquals("en", l.getLanguage()); 842 assertEquals("", l.getCountry()); 843 assertEquals("", l.getVariant()); 844 assertEquals("", l.getScript()); 845 } 846 847 public void test_Builder_unicodeAttributes() { 848 // Adding and removing attributes 849 Locale.Builder b = new Locale.Builder(); 850 b.setLanguage("en"); 851 852 // Well formed attribute. 853 b.addUnicodeLocaleAttribute("foooo"); 854 855 try { 856 b.addUnicodeLocaleAttribute("fo"); 857 fail(); 858 } catch (IllformedLocaleException ifle) { 859 } 860 861 try { 862 b.removeUnicodeLocaleAttribute("fo"); 863 fail(); 864 } catch (IllformedLocaleException ifle) { 865 } 866 867 try { 868 b.addUnicodeLocaleAttribute("greaterthaneightchars"); 869 fail(); 870 } catch (IllformedLocaleException ifle) { 871 } 872 873 try { 874 b.removeUnicodeLocaleAttribute("greaterthaneightchars"); 875 fail(); 876 } catch (IllformedLocaleException ifle) { 877 } 878 879 try { 880 b.addUnicodeLocaleAttribute(null); 881 fail(); 882 } catch (NullPointerException npe) { 883 } 884 885 try { 886 b.removeUnicodeLocaleAttribute(null); 887 fail(); 888 } catch (NullPointerException npe) { 889 } 890 891 Locale l = b.build(); 892 assertEquals("en-u-foooo", l.toLanguageTag()); 893 assertTrue(l.getUnicodeLocaleAttributes().contains("foooo")); 894 895 b.addUnicodeLocaleAttribute("dAtA"); 896 l = b.build(); 897 assertEquals("data-foooo", l.getExtension('u')); 898 assertTrue(l.getUnicodeLocaleAttributes().contains("data")); 899 assertTrue(l.getUnicodeLocaleAttributes().contains("foooo")); 900 } 901 902 public void test_Builder_unicodeKeywords() { 903 // Adding and removing attributes 904 Locale.Builder b = new Locale.Builder(); 905 b.setLanguage("en"); 906 907 // Key not of length 2. 908 try { 909 b.setUnicodeLocaleKeyword("k", "fooo"); 910 fail(); 911 } catch (IllformedLocaleException ifle) { 912 } 913 914 // Value too short 915 try { 916 b.setUnicodeLocaleKeyword("k", "fo"); 917 fail(); 918 } catch (IllformedLocaleException ifle) { 919 } 920 921 // Value too long 922 try { 923 b.setUnicodeLocaleKeyword("k", "foooooooo"); 924 fail(); 925 } catch (IllformedLocaleException ifle) { 926 } 927 928 929 // Null should clear the key. 930 b.setUnicodeLocaleKeyword("bo", "baaz"); 931 Locale l = b.build(); 932 assertEquals("bo-baaz", l.getExtension('u')); 933 assertEquals("baaz", l.getUnicodeLocaleType("bo")); 934 935 b = new Locale.Builder(); 936 b.setUnicodeLocaleKeyword("bo", "baaz"); 937 b.setUnicodeLocaleKeyword("bo", null); 938 l = b.build(); 939 assertNull(l.getExtension('u')); 940 assertNull(l.getUnicodeLocaleType("bo")); 941 942 // When we set attributes, they should show up before extensions. 943 b = new Locale.Builder(); 944 b.addUnicodeLocaleAttribute("fooo"); 945 b.addUnicodeLocaleAttribute("gooo"); 946 b.setUnicodeLocaleKeyword("fo", "baz"); 947 b.setUnicodeLocaleKeyword("ka", "kaz"); 948 l = b.build(); 949 assertEquals("fooo-gooo-fo-baz-ka-kaz", l.getExtension('u')); 950 assertEquals("baz", l.getUnicodeLocaleType("fo")); 951 assertEquals("kaz", l.getUnicodeLocaleType("ka")); 952 assertTrue(l.getUnicodeLocaleAttributes().contains("fooo")); 953 assertTrue(l.getUnicodeLocaleAttributes().contains("gooo")); 954 } 955 956 public void test_multipleExtensions() { 957 Locale.Builder b = new Locale.Builder(); 958 b.setLanguage("en"); 959 b.addUnicodeLocaleAttribute("attrib"); 960 b.addUnicodeLocaleAttribute("attrib2"); 961 b.setExtension('f', "fo-baaz-ga-gaaz"); 962 b.setExtension('x', "xo-baaz-ga-gaaz"); 963 b.setExtension('z', "zo-baaz-ga-gaaz"); 964 965 Locale l = b.build(); 966 // Implicitly added because we added unicode locale attributes. 967 assertEquals("attrib-attrib2", l.getExtension('u')); 968 assertEquals("fo-baaz-ga-gaaz", l.getExtension('f')); 969 assertEquals("xo-baaz-ga-gaaz", l.getExtension('x')); 970 assertEquals("zo-baaz-ga-gaaz", l.getExtension('z')); 971 } 972 973 public void test_immutability() { 974 Locale.Builder b = new Locale.Builder(); 975 b.setExtension('g', "fooo-baaz-baar"); 976 b.setExtension('u', "foooo-baaar-ba-baaz-ka-kaaz"); 977 978 Locale l = b.build(); 979 try { 980 l.getExtensionKeys().add('g'); 981 fail(); 982 } catch (UnsupportedOperationException expected) { 983 } 984 985 try { 986 l.getUnicodeLocaleAttributes().add("fooo"); 987 fail(); 988 } catch (UnsupportedOperationException expected) { 989 } 990 } 991 992 public void test_toLanguageTag() { 993 Locale.Builder b = new Locale.Builder(); 994 995 // Empty builder. 996 Locale l = b.build(); 997 // TODO: Fix this. We should return "und" and not NULL. 998 // assertEquals("und", l.toLanguageTag()); 999 1000 // Only language. 1001 b = new Locale.Builder(); 1002 b.setLanguage("en"); 1003 assertEquals("en", b.build().toLanguageTag()); 1004 1005 // Language & Region 1006 b = new Locale.Builder(); 1007 b.setLanguage("en").setRegion("US"); 1008 assertEquals("en-US", b.build().toLanguageTag()); 1009 1010 // Language & Script 1011 b = new Locale.Builder(); 1012 b.setLanguage("en").setScript("Latn"); 1013 assertEquals("en-Latn", b.build().toLanguageTag()); 1014 1015 // Language & Variant 1016 b = new Locale.Builder(); 1017 b.setLanguage("en").setVariant("foooo"); 1018 assertEquals("en-foooo", b.build().toLanguageTag()); 1019 1020 // Language / script & country 1021 b = new Locale.Builder(); 1022 b.setLanguage("en").setScript("Latn").setRegion("US"); 1023 assertEquals("en-Latn-US", b.build().toLanguageTag()); 1024 1025 // Language / script & variant 1026 b = new Locale.Builder(); 1027 b.setLanguage("en").setScript("Latn").setVariant("foooo"); 1028 assertEquals("en-Latn-foooo", b.build().toLanguageTag()); 1029 1030 // Language / script / country / variant. 1031 b = new Locale.Builder(); 1032 b.setLanguage("en").setScript("Latn").setVariant("foooo").setRegion("US"); 1033 assertEquals("en-Latn-US-foooo", b.build().toLanguageTag()); 1034 1035 // Language / extension 1036 b = new Locale.Builder(); 1037 b.setLanguage("en").setExtension('x', "fooo-baar"); 1038 assertEquals("en-x-fooo-baar", b.build().toLanguageTag()); 1039 1040 // Language & multiple extensions (including unicode). 1041 b = new Locale.Builder(); 1042 b.setLanguage("en"); 1043 b.addUnicodeLocaleAttribute("attrib"); 1044 b.addUnicodeLocaleAttribute("attrib2"); 1045 b.setExtension('f', "fo-baaz-ga-gaaz"); 1046 b.setExtension('x', "xo-baaz-ga-gaaz"); 1047 b.setExtension('z', "zo-baaz-ga-gaaz"); 1048 1049 l = b.build(); 1050 // Implicitly added because we added unicode locale attributes. 1051 assertEquals("attrib-attrib2", l.getExtension('u')); 1052 assertEquals("fo-baaz-ga-gaaz", l.getExtension('f')); 1053 assertEquals("xo-baaz-ga-gaaz", l.getExtension('x')); 1054 assertEquals("zo-baaz-ga-gaaz", l.getExtension('z')); 1055 1056 assertEquals("en-" + 1057 "f-fo-baaz-ga-gaaz-" + // extension tags in lexical order 1058 "u-attrib-attrib2-z-zo-baaz-ga-gaaz-" + // unicode attribs & keywords in lex order 1059 "x-xo-baaz-ga-gaaz", // private use extension unmodified. 1060 l.toLanguageTag()); 1061 } 1062 1063 public void test_toString() { 1064 Locale.Builder b = new Locale.Builder(); 1065 1066 // Empty builder. 1067 Locale l = b.build(); 1068 assertEquals("", l.toString()); 1069 1070 // Only language. 1071 b = new Locale.Builder(); 1072 b.setLanguage("en"); 1073 assertEquals("en", b.build().toString()); 1074 1075 // Only region 1076 b = new Locale.Builder(); 1077 b.setRegion("US"); 1078 assertEquals("_US", b.build().toString()); 1079 1080 // Language & Region 1081 b = new Locale.Builder(); 1082 b.setLanguage("en").setRegion("US"); 1083 assertEquals("en_US", b.build().toString()); 1084 1085 // Language & Script 1086 b = new Locale.Builder(); 1087 b.setLanguage("en").setScript("Latn"); 1088 assertEquals("en__#Latn", b.build().toString()); 1089 1090 // Language & Variant 1091 b = new Locale.Builder(); 1092 b.setLanguage("en").setVariant("foooo"); 1093 assertEquals("en__foooo", b.build().toString()); 1094 1095 // Language / script & country 1096 b = new Locale.Builder(); 1097 b.setLanguage("en").setScript("Latn").setRegion("US"); 1098 assertEquals("en_US_#Latn", b.build().toString()); 1099 1100 // Language / script & variant 1101 b = new Locale.Builder(); 1102 b.setLanguage("en").setScript("Latn").setVariant("foooo"); 1103 assertEquals("en__foooo_#Latn", b.build().toString()); 1104 1105 // Language / script / country / variant. 1106 b = new Locale.Builder(); 1107 b.setLanguage("en").setScript("Latn").setVariant("foooo").setRegion("US"); 1108 assertEquals("en_US_foooo_#Latn", b.build().toString()); 1109 1110 // Language / extension 1111 b = new Locale.Builder(); 1112 b.setLanguage("en").setExtension('x', "fooo-baar"); 1113 assertEquals("en__#x-fooo-baar", b.build().toString()); 1114 } 1115 1116 // Tests cases where our "guess" for the output size is incorrect. 1117 // 1118 // https://b.corp.google.com/issue?id=13414549 1119 public void test_toLanguageTag_largerTag() { 1120 Locale posix = new Locale.Builder() 1121 .setLanguage("en").setRegion("US").setVariant("POSIX") 1122 .build(); 1123 assertEquals("en-US-POSIX", posix.toLanguageTag()); 1124 } 1125 1126 public void test_forLanguageTag_grandFatheredLocale() { 1127 // Regular grandfathered locale. 1128 Locale gaulish = Locale.forLanguageTag("cel-gaulish"); 1129 assertEquals("xtg", gaulish.getLanguage()); 1130 assertEquals("cel-gaulish", gaulish.getExtension(Locale.PRIVATE_USE_EXTENSION)); 1131 assertEquals("", gaulish.getCountry()); 1132 assertEquals("", gaulish.getScript()); 1133 assertEquals("", gaulish.getVariant()); 1134 1135 // Irregular grandfathered locale. 1136 Locale enochian = Locale.forLanguageTag("i-enochian"); 1137 assertEquals("und", enochian.getLanguage()); 1138 assertEquals("i-enochian", enochian.getExtension(Locale.PRIVATE_USE_EXTENSION)); 1139 assertEquals("", enochian.getCountry()); 1140 assertEquals("", enochian.getScript()); 1141 assertEquals("", enochian.getVariant()); 1142 } 1143 1144 // Test case from http://b/16811867 1145 public void testVariantsCaseSensitive() { 1146 final Locale locale = new Locale("en", "US", "variant"); 1147 assertEquals("variant", locale.getVariant()); 1148 assertEquals(locale, Locale.forLanguageTag(locale.toLanguageTag())); 1149 } 1150 1151 public void testArabicDigits() throws Exception { 1152 // ar-DZ uses latn digits by default, but we can override that. 1153 Locale ar_DZ = Locale.forLanguageTag("ar-DZ"); 1154 Locale ar_DZ_arab = Locale.forLanguageTag("ar-DZ-u-nu-arab"); 1155 Locale ar_DZ_latn = Locale.forLanguageTag("ar-DZ-u-nu-latn"); 1156 assertEquals('0', new DecimalFormatSymbols(ar_DZ).getZeroDigit()); 1157 assertEquals('\u0660', new DecimalFormatSymbols(ar_DZ_arab).getZeroDigit()); 1158 assertEquals('0', new DecimalFormatSymbols(ar_DZ_latn).getZeroDigit()); 1159 1160 // ar-EG uses arab digits by default, but we can override that. 1161 Locale ar_EG = Locale.forLanguageTag("ar-EG"); 1162 Locale ar_EG_arab = Locale.forLanguageTag("ar-EG-u-nu-arab"); 1163 Locale ar_EG_latn = Locale.forLanguageTag("ar-EG-u-nu-latn"); 1164 assertEquals('\u0660', new DecimalFormatSymbols(ar_EG).getZeroDigit()); 1165 assertEquals('\u0660', new DecimalFormatSymbols(ar_EG_arab).getZeroDigit()); 1166 assertEquals('0', new DecimalFormatSymbols(ar_EG_latn).getZeroDigit()); 1167 } 1168 1169 public void testDefaultLocale() throws Exception { 1170 final String userLanguage = System.getProperty("user.language", ""); 1171 final String userRegion = System.getProperty("user.region", ""); 1172 final String userLocale = System.getProperty("user.locale", ""); 1173 try { 1174 // Assert that user.locale gets priority. 1175 System.setUnchangeableSystemProperty("user.locale", "de-DE"); 1176 System.setUnchangeableSystemProperty("user.language", "en"); 1177 System.setUnchangeableSystemProperty("user.region", "US"); 1178 1179 Locale l = Locale.getDefaultLocaleFromSystemProperties(); 1180 assertEquals("de", l.getLanguage()); 1181 assertEquals("DE", l.getCountry()); 1182 1183 // Assert that it's parsed as a full language tag. 1184 System.setUnchangeableSystemProperty("user.locale", "de-Latn-DE"); 1185 System.setUnchangeableSystemProperty("user.language", "en"); 1186 System.setUnchangeableSystemProperty("user.region", "US"); 1187 1188 l = Locale.getDefaultLocaleFromSystemProperties(); 1189 assertEquals("de", l.getLanguage()); 1190 assertEquals("DE", l.getCountry()); 1191 assertEquals("Latn", l.getScript()); 1192 1193 // Assert that we use "und" if we're faced with a bad language tag, and 1194 // that we don't end up with a null default locale or an exception. 1195 System.setUnchangeableSystemProperty("user.locale", "dexx-Latn-DE"); 1196 1197 l = Locale.getDefaultLocaleFromSystemProperties(); 1198 assertEquals("und", l.getLanguage()); 1199 assertEquals("DE", l.getCountry()); 1200 } finally { 1201 System.setUnchangeableSystemProperty("user.language", userLanguage); 1202 System.setUnchangeableSystemProperty("user.region", userRegion); 1203 System.setUnchangeableSystemProperty("user.locale", userLocale); 1204 } 1205 } 1206 1207 // http://b/20252611 1208 public void testLegacyLocalesWithExtensions() { 1209 Locale ja_JP_JP = new Locale("ja", "JP", "JP"); 1210 assertEquals("ca-japanese", ja_JP_JP.getExtension(Locale.UNICODE_LOCALE_EXTENSION)); 1211 assertEquals("japanese", ja_JP_JP.getUnicodeLocaleType("ca")); 1212 1213 Locale th_TH_TH = new Locale("th", "TH", "TH"); 1214 assertEquals("nu-thai", th_TH_TH.getExtension(Locale.UNICODE_LOCALE_EXTENSION)); 1215 assertEquals("thai", th_TH_TH.getUnicodeLocaleType("nu")); 1216 } 1217 1218 // http://b/20252611 1219 public void testLowerCaseExtensionKeys() { 1220 // We must lowercase extension keys in forLanguageTag.. 1221 Locale ar_EG = Locale.forLanguageTag("ar-EG-U-nu-arab"); 1222 assertEquals("nu-arab", ar_EG.getExtension(Locale.UNICODE_LOCALE_EXTENSION)); 1223 assertEquals("ar-EG-u-nu-arab", ar_EG.toLanguageTag()); 1224 1225 // ... and in builders. 1226 Locale.Builder b = new Locale.Builder(); 1227 b.setLanguage("ar"); 1228 b.setRegion("EG"); 1229 b.setExtension('U', "nu-arab"); 1230 assertEquals("ar-EG-u-nu-arab", b.build().toLanguageTag()); 1231 1232 // Corollary : extension keys are case insensitive. 1233 b = new Locale.Builder(); 1234 b.setLanguage("ar"); 1235 b.setRegion("EG"); 1236 b.setExtension('U', "nu-arab"); 1237 b.setExtension('u', "nu-thai"); 1238 assertEquals("ar-EG-u-nu-thai", b.build().toLanguageTag()); 1239 } 1240 } 1241