1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.util; 19 20 import java.io.IOException; 21 import java.io.ObjectInputStream; 22 import java.io.ObjectOutputStream; 23 import java.io.ObjectStreamField; 24 import java.io.Serializable; 25 import libcore.icu.ICU; 26 27 /** 28 * {@code Locale} represents a language/country/variant combination. Locales are used to 29 * alter the presentation of information such as numbers or dates to suit the conventions 30 * in the region they describe. 31 * 32 * <p>The language codes are two-letter lowercase ISO language codes (such as "en") as defined by 33 * <a href="http://en.wikipedia.org/wiki/ISO_639-1">ISO 639-1</a>. 34 * The country codes are two-letter uppercase ISO country codes (such as "US") as defined by 35 * <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-3">ISO 3166-1</a>. 36 * The variant codes are unspecified. 37 * 38 * <p>Note that Java uses several deprecated two-letter codes. The Hebrew ("he") language 39 * code is rewritten as "iw", Indonesian ("id") as "in", and Yiddish ("yi") as "ji". This 40 * rewriting happens even if you construct your own {@code Locale} object, not just for 41 * instances returned by the various lookup methods. 42 * 43 * <a name="available_locales"><h3>Available locales</h3></a> 44 * <p>This class' constructors do no error checking. You can create a {@code Locale} for languages 45 * and countries that don't exist, and you can create instances for combinations that don't 46 * exist (such as "de_US" for "German as spoken in the US"). 47 * 48 * <p>Note that locale data is not necessarily available for any of the locales pre-defined as 49 * constants in this class except for en_US, which is the only locale Java guarantees is always 50 * available. 51 * 52 * <p>It is also a mistake to assume that all devices have the same locales available. 53 * A device sold in the US will almost certainly support en_US and es_US, but not necessarily 54 * any locales with the same language but different countries (such as en_GB or es_ES), 55 * nor any locales for other languages (such as de_DE). The opposite may well be true for a device 56 * sold in Europe. 57 * 58 * <p>You can use {@link Locale#getDefault} to get an appropriate locale for the <i>user</i> of the 59 * device you're running on, or {@link Locale#getAvailableLocales} to get a list of all the locales 60 * available on the device you're running on. 61 * 62 * <a name="locale_data"><h3>Locale data</h3></a> 63 * <p>Note that locale data comes solely from ICU. User-supplied locale service providers (using 64 * the {@code java.text.spi} or {@code java.util.spi} mechanisms) are not supported. 65 * 66 * <p>Here are the versions of ICU (and the corresponding CLDR and Unicode versions) used in 67 * various Android releases: 68 * <table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY=""> 69 * <tr><td>cupcake/donut/eclair</td> <td>ICU 3.8</td> <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-5">CLDR 1.5</a></td> <td><a href="http://www.unicode.org/versions/Unicode5.0.0/">Unicode 5.0</a></td></tr> 70 * <tr><td>froyo</td> <td>ICU 4.2</td> <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-7">CLDR 1.7</a></td> <td><a href="http://www.unicode.org/versions/Unicode5.1.0/">Unicode 5.1</a></td></tr> 71 * <tr><td>gingerbread/honeycomb</td><td>ICU 4.4</td> <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-8">CLDR 1.8</a></td> <td><a href="http://www.unicode.org/versions/Unicode5.2.0/">Unicode 5.2</a></td></tr> 72 * <tr><td>ice cream sandwich</td><td>ICU 4.6</td> <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-9">CLDR 1.9</a></td> <td><a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode 6.0</a></td></tr> 73 * </table> 74 * 75 * <a name="default_locale"><h3>Be wary of the default locale</h3></a> 76 * <p>Note that there are many convenience methods that automatically use the default locale, but 77 * using them may lead to subtle bugs. 78 * 79 * <p>The default locale is appropriate for tasks that involve presenting data to the user. In 80 * this case, you want to use the user's date/time formats, number 81 * formats, rules for conversion to lowercase, and so on. In this case, it's safe to use the 82 * convenience methods. 83 * 84 * <p>The default locale is <i>not</i> appropriate for machine-readable output. The best choice 85 * there is usually {@code Locale.US} – this locale is guaranteed to be available on all 86 * devices, and the fact that it has no surprising special cases and is frequently used (especially 87 * for computer-computer communication) means that it tends to be the most efficient choice too. 88 * 89 * <p>A common mistake is to implicitly use the default locale when producing output meant to be 90 * machine-readable. This tends to work on the developer's test devices (especially because so many 91 * developers use en_US), but fails when run on a device whose user is in a more complex locale. 92 * 93 * <p>For example, if you're formatting integers some locales will use non-ASCII decimal 94 * digits. As another example, if you're formatting floating-point numbers some locales will use 95 * {@code ','} as the decimal point and {@code '.'} for digit grouping. That's correct for 96 * human-readable output, but likely to cause problems if presented to another 97 * computer ({@link Double#parseDouble} can't parse such a number, for example). 98 * You should also be wary of the {@link String#toLowerCase} and 99 * {@link String#toUpperCase} overloads that don't take a {@code Locale}: in Turkey, for example, 100 * the characters {@code 'i'} and {@code 'I'} won't be converted to {@code 'I'} and {@code 'i'}. 101 * This is the correct behavior for Turkish text (such as user input), but inappropriate for, say, 102 * HTTP headers. 103 */ 104 public final class Locale implements Cloneable, Serializable { 105 106 private static final long serialVersionUID = 9149081749638150636L; 107 108 /** 109 * Locale constant for en_CA. 110 */ 111 public static final Locale CANADA = new Locale(true, "en", "CA"); 112 113 /** 114 * Locale constant for fr_CA. 115 */ 116 public static final Locale CANADA_FRENCH = new Locale(true, "fr", "CA"); 117 118 /** 119 * Locale constant for zh_CN. 120 */ 121 public static final Locale CHINA = new Locale(true, "zh", "CN"); 122 123 /** 124 * Locale constant for zh. 125 */ 126 public static final Locale CHINESE = new Locale(true, "zh", ""); 127 128 /** 129 * Locale constant for en. 130 */ 131 public static final Locale ENGLISH = new Locale(true, "en", ""); 132 133 /** 134 * Locale constant for fr_FR. 135 */ 136 public static final Locale FRANCE = new Locale(true, "fr", "FR"); 137 138 /** 139 * Locale constant for fr. 140 */ 141 public static final Locale FRENCH = new Locale(true, "fr", ""); 142 143 /** 144 * Locale constant for de. 145 */ 146 public static final Locale GERMAN = new Locale(true, "de", ""); 147 148 /** 149 * Locale constant for de_DE. 150 */ 151 public static final Locale GERMANY = new Locale(true, "de", "DE"); 152 153 /** 154 * Locale constant for it. 155 */ 156 public static final Locale ITALIAN = new Locale(true, "it", ""); 157 158 /** 159 * Locale constant for it_IT. 160 */ 161 public static final Locale ITALY = new Locale(true, "it", "IT"); 162 163 /** 164 * Locale constant for ja_JP. 165 */ 166 public static final Locale JAPAN = new Locale(true, "ja", "JP"); 167 168 /** 169 * Locale constant for ja. 170 */ 171 public static final Locale JAPANESE = new Locale(true, "ja", ""); 172 173 /** 174 * Locale constant for ko_KR. 175 */ 176 public static final Locale KOREA = new Locale(true, "ko", "KR"); 177 178 /** 179 * Locale constant for ko. 180 */ 181 public static final Locale KOREAN = new Locale(true, "ko", ""); 182 183 /** 184 * Locale constant for zh_CN. 185 */ 186 public static final Locale PRC = new Locale(true, "zh", "CN"); 187 188 /** 189 * Locale constant for the root locale. The root locale has an empty language, 190 * country, and variant. 191 * 192 * @since 1.6 193 */ 194 public static final Locale ROOT = new Locale(true, "", ""); 195 196 /** 197 * Locale constant for zh_CN. 198 */ 199 public static final Locale SIMPLIFIED_CHINESE = new Locale(true, "zh", "CN"); 200 201 /** 202 * Locale constant for zh_TW. 203 */ 204 public static final Locale TAIWAN = new Locale(true, "zh", "TW"); 205 206 /** 207 * Locale constant for zh_TW. 208 */ 209 public static final Locale TRADITIONAL_CHINESE = new Locale(true, "zh", "TW"); 210 211 /** 212 * Locale constant for en_GB. 213 */ 214 public static final Locale UK = new Locale(true, "en", "GB"); 215 216 /** 217 * Locale constant for en_US. 218 */ 219 public static final Locale US = new Locale(true, "en", "US"); 220 221 /** 222 * The current default locale. It is temporarily assigned to US because we 223 * need a default locale to lookup the real default locale. 224 */ 225 private static Locale defaultLocale = US; 226 227 static { 228 String language = System.getProperty("user.language", "en"); 229 String region = System.getProperty("user.region", "US"); 230 String variant = System.getProperty("user.variant", ""); 231 defaultLocale = new Locale(language, region, variant); 232 } 233 234 private transient String countryCode; 235 private transient String languageCode; 236 private transient String variantCode; 237 private transient String cachedToStringResult; 238 239 /** 240 * There's a circular dependency between toLowerCase/toUpperCase and 241 * Locale.US. Work around this by avoiding these methods when constructing 242 * the built-in locales. 243 * 244 * @param unused required for this constructor to have a unique signature 245 */ 246 private Locale(boolean unused, String lowerCaseLanguageCode, String upperCaseCountryCode) { 247 this.languageCode = lowerCaseLanguageCode; 248 this.countryCode = upperCaseCountryCode; 249 this.variantCode = ""; 250 } 251 252 /** 253 * Constructs a new {@code Locale} using the specified language. 254 */ 255 public Locale(String language) { 256 this(language, "", ""); 257 } 258 259 /** 260 * Constructs a new {@code Locale} using the specified language and country codes. 261 */ 262 public Locale(String language, String country) { 263 this(language, country, ""); 264 } 265 266 /** 267 * Constructs a new {@code Locale} using the specified language, country, 268 * and variant codes. 269 */ 270 public Locale(String language, String country, String variant) { 271 if (language == null || country == null || variant == null) { 272 throw new NullPointerException(); 273 } 274 if (language.isEmpty() && country.isEmpty()) { 275 languageCode = ""; 276 countryCode = ""; 277 variantCode = variant; 278 return; 279 } 280 281 languageCode = language.toLowerCase(Locale.US); 282 // Map new language codes to the obsolete language 283 // codes so the correct resource bundles will be used. 284 if (languageCode.equals("he")) { 285 languageCode = "iw"; 286 } else if (languageCode.equals("id")) { 287 languageCode = "in"; 288 } else if (languageCode.equals("yi")) { 289 languageCode = "ji"; 290 } 291 292 countryCode = country.toUpperCase(Locale.US); 293 294 // Work around for be compatible with RI 295 variantCode = variant; 296 } 297 298 @Override public Object clone() { 299 try { 300 return super.clone(); 301 } catch (CloneNotSupportedException e) { 302 throw new AssertionError(e); 303 } 304 } 305 306 /** 307 * Returns true if {@code object} is a locale with the same language, 308 * country and variant. 309 */ 310 @Override public boolean equals(Object object) { 311 if (object == this) { 312 return true; 313 } 314 if (object instanceof Locale) { 315 Locale o = (Locale) object; 316 return languageCode.equals(o.languageCode) 317 && countryCode.equals(o.countryCode) 318 && variantCode.equals(o.variantCode); 319 } 320 return false; 321 } 322 323 /** 324 * Returns the system's installed locales. This array always includes {@code 325 * Locale.US}, and usually several others. Most locale-sensitive classes 326 * offer their own {@code getAvailableLocales} method, which should be 327 * preferred over this general purpose method. 328 * 329 * @see java.text.BreakIterator#getAvailableLocales() 330 * @see java.text.Collator#getAvailableLocales() 331 * @see java.text.DateFormat#getAvailableLocales() 332 * @see java.text.DateFormatSymbols#getAvailableLocales() 333 * @see java.text.DecimalFormatSymbols#getAvailableLocales() 334 * @see java.text.NumberFormat#getAvailableLocales() 335 * @see java.util.Calendar#getAvailableLocales() 336 */ 337 public static Locale[] getAvailableLocales() { 338 return ICU.getAvailableLocales(); 339 } 340 341 /** 342 * Returns the country code for this locale, or {@code ""} if this locale 343 * doesn't correspond to a specific country. 344 */ 345 public String getCountry() { 346 return countryCode; 347 } 348 349 /** 350 * Returns the user's preferred locale. This may have been overridden for 351 * this process with {@link #setDefault}. 352 * 353 * <p>Since the user's locale changes dynamically, avoid caching this value. 354 * Instead, use this method to look it up for each use. 355 */ 356 public static Locale getDefault() { 357 return defaultLocale; 358 } 359 360 /** 361 * Equivalent to {@code getDisplayCountry(Locale.getDefault())}. 362 */ 363 public final String getDisplayCountry() { 364 return getDisplayCountry(getDefault()); 365 } 366 367 /** 368 * Returns the name of this locale's country, localized to {@code locale}. 369 * Returns the empty string if this locale does not correspond to a specific 370 * country. 371 */ 372 public String getDisplayCountry(Locale locale) { 373 if (countryCode.isEmpty()) { 374 return ""; 375 } 376 String result = ICU.getDisplayCountryNative(toString(), locale.toString()); 377 if (result == null) { // TODO: do we need to do this, or does ICU do it for us? 378 result = ICU.getDisplayCountryNative(toString(), Locale.getDefault().toString()); 379 } 380 return result; 381 } 382 383 /** 384 * Equivalent to {@code getDisplayLanguage(Locale.getDefault())}. 385 */ 386 public final String getDisplayLanguage() { 387 return getDisplayLanguage(getDefault()); 388 } 389 390 /** 391 * Returns the name of this locale's language, localized to {@code locale}. 392 * If the language name is unknown, the language code is returned. 393 */ 394 public String getDisplayLanguage(Locale locale) { 395 if (languageCode.isEmpty()) { 396 return ""; 397 } 398 String result = ICU.getDisplayLanguageNative(toString(), locale.toString()); 399 if (result == null) { // TODO: do we need to do this, or does ICU do it for us? 400 result = ICU.getDisplayLanguageNative(toString(), Locale.getDefault().toString()); 401 } 402 return result; 403 } 404 405 /** 406 * Equivalent to {@code getDisplayName(Locale.getDefault())}. 407 */ 408 public final String getDisplayName() { 409 return getDisplayName(getDefault()); 410 } 411 412 /** 413 * Returns this locale's language name, country name, and variant, localized 414 * to {@code locale}. The exact output form depends on whether this locale 415 * corresponds to a specific language, country and variant. 416 * 417 * <p>For example: 418 * <ul> 419 * <li>{@code new Locale("en").getDisplayName(Locale.US)} -> {@code English} 420 * <li>{@code new Locale("en", "US").getDisplayName(Locale.US)} -> {@code English (United States)} 421 * <li>{@code new Locale("en", "US", "POSIX").getDisplayName(Locale.US)} -> {@code English (United States,Computer)} 422 * <li>{@code new Locale("en").getDisplayName(Locale.FRANCE)} -> {@code anglais} 423 * <li>{@code new Locale("en", "US").getDisplayName(Locale.FRANCE)} -> {@code anglais (tats-Unis)} 424 * <li>{@code new Locale("en", "US", "POSIX").getDisplayName(Locale.FRANCE)} -> {@code anglais (tats-Unis,informatique)}. 425 * </ul> 426 */ 427 public String getDisplayName(Locale locale) { 428 int count = 0; 429 StringBuilder buffer = new StringBuilder(); 430 if (!languageCode.isEmpty()) { 431 String displayLanguage = getDisplayLanguage(locale); 432 buffer.append(displayLanguage.isEmpty() ? languageCode : displayLanguage); 433 ++count; 434 } 435 if (!countryCode.isEmpty()) { 436 if (count == 1) { 437 buffer.append(" ("); 438 } 439 String displayCountry = getDisplayCountry(locale); 440 buffer.append(displayCountry.isEmpty() ? countryCode : displayCountry); 441 ++count; 442 } 443 if (!variantCode.isEmpty()) { 444 if (count == 1) { 445 buffer.append(" ("); 446 } else if (count == 2) { 447 buffer.append(","); 448 } 449 String displayVariant = getDisplayVariant(locale); 450 buffer.append(displayVariant.isEmpty() ? variantCode : displayVariant); 451 ++count; 452 } 453 if (count > 1) { 454 buffer.append(")"); 455 } 456 return buffer.toString(); 457 } 458 459 /** 460 * Returns the full variant name in the default {@code Locale} for the variant code of 461 * this {@code Locale}. If there is no matching variant name, the variant code is 462 * returned. 463 */ 464 public final String getDisplayVariant() { 465 return getDisplayVariant(getDefault()); 466 } 467 468 /** 469 * Returns the full variant name in the specified {@code Locale} for the variant code 470 * of this {@code Locale}. If there is no matching variant name, the variant code is 471 * returned. 472 */ 473 public String getDisplayVariant(Locale locale) { 474 if (variantCode.length() == 0) { 475 return variantCode; 476 } 477 String result = ICU.getDisplayVariantNative(toString(), locale.toString()); 478 if (result == null) { // TODO: do we need to do this, or does ICU do it for us? 479 result = ICU.getDisplayVariantNative(toString(), Locale.getDefault().toString()); 480 } 481 return result; 482 } 483 484 /** 485 * Returns the three letter ISO country code which corresponds to the country 486 * code for this {@code Locale}. 487 */ 488 public String getISO3Country() { 489 if (countryCode.length() == 0) { 490 return countryCode; 491 } 492 return ICU.getISO3CountryNative(toString()); 493 } 494 495 /** 496 * Returns the three letter ISO language code which corresponds to the language 497 * code for this {@code Locale}. 498 */ 499 public String getISO3Language() { 500 if (languageCode.length() == 0) { 501 return languageCode; 502 } 503 return ICU.getISO3LanguageNative(toString()); 504 } 505 506 /** 507 * Returns an array of strings containing all the two-letter ISO country codes that can be 508 * used as the country code when constructing a {@code Locale}. 509 */ 510 public static String[] getISOCountries() { 511 return ICU.getISOCountries(); 512 } 513 514 /** 515 * Returns an array of strings containing all the two-letter ISO language codes that can be 516 * used as the language code when constructing a {@code Locale}. 517 */ 518 public static String[] getISOLanguages() { 519 return ICU.getISOLanguages(); 520 } 521 522 /** 523 * Returns the language code for this {@code Locale} or the empty string if no language 524 * was set. 525 */ 526 public String getLanguage() { 527 return languageCode; 528 } 529 530 /** 531 * Returns the variant code for this {@code Locale} or an empty {@code String} if no variant 532 * was set. 533 */ 534 public String getVariant() { 535 return variantCode; 536 } 537 538 @Override 539 public synchronized int hashCode() { 540 return countryCode.hashCode() + languageCode.hashCode() 541 + variantCode.hashCode(); 542 } 543 544 /** 545 * Overrides the default locale. This does not affect system configuration, 546 * and attempts to override the system-provided default locale may 547 * themselves be overridden by actual changes to the system configuration. 548 * Code that calls this method is usually incorrect, and should be fixed by 549 * passing the appropriate locale to each locale-sensitive method that's 550 * called. 551 */ 552 public synchronized static void setDefault(Locale locale) { 553 if (locale == null) { 554 throw new NullPointerException(); 555 } 556 defaultLocale = locale; 557 } 558 559 /** 560 * Returns the string representation of this {@code Locale}. It consists of the 561 * language code, country code and variant separated by underscores. 562 * If the language is missing the string begins 563 * with an underscore. If the country is missing there are 2 underscores 564 * between the language and the variant. The variant cannot stand alone 565 * without a language and/or country code: in this case this method would 566 * return the empty string. 567 * 568 * <p>Examples: "en", "en_US", "_US", "en__POSIX", "en_US_POSIX" 569 */ 570 @Override 571 public final String toString() { 572 String result = cachedToStringResult; 573 return (result == null) ? (cachedToStringResult = toNewString()) : result; 574 } 575 576 private String toNewString() { 577 // The string form of a locale that only has a variant is the empty string. 578 if (languageCode.length() == 0 && countryCode.length() == 0) { 579 return ""; 580 } 581 // Otherwise, the output format is "ll_cc_variant", where language and country are always 582 // two letters, but the variant is an arbitrary length. A size of 11 characters has room 583 // for "en_US_POSIX", the largest "common" value. (In practice, the string form is almost 584 // always 5 characters: "ll_cc".) 585 StringBuilder result = new StringBuilder(11); 586 result.append(languageCode); 587 if (countryCode.length() > 0 || variantCode.length() > 0) { 588 result.append('_'); 589 } 590 result.append(countryCode); 591 if (variantCode.length() > 0) { 592 result.append('_'); 593 } 594 result.append(variantCode); 595 return result.toString(); 596 } 597 598 private static final ObjectStreamField[] serialPersistentFields = { 599 new ObjectStreamField("country", String.class), 600 new ObjectStreamField("hashcode", int.class), 601 new ObjectStreamField("language", String.class), 602 new ObjectStreamField("variant", String.class), 603 }; 604 605 private void writeObject(ObjectOutputStream stream) throws IOException { 606 ObjectOutputStream.PutField fields = stream.putFields(); 607 fields.put("country", countryCode); 608 fields.put("hashcode", -1); 609 fields.put("language", languageCode); 610 fields.put("variant", variantCode); 611 stream.writeFields(); 612 } 613 614 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 615 ObjectInputStream.GetField fields = stream.readFields(); 616 countryCode = (String) fields.get("country", ""); 617 languageCode = (String) fields.get("language", ""); 618 variantCode = (String) fields.get("variant", ""); 619 } 620 } 621