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