Locale.java |
1 /* 2 * %W% %E% 3 * 4 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 5 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 6 */ 7 8 /* 9 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved 10 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved 11 * 12 * The original version of this source code and documentation 13 * is copyrighted and owned by Taligent, Inc., a wholly-owned 14 * subsidiary of IBM. These materials are provided under terms 15 * of a License Agreement between Taligent and Sun. This technology 16 * is protected by multiple US and International patents. 17 * 18 * This notice and attribution to Taligent may not be removed. 19 * Taligent is a registered trademark of Taligent, Inc. 20 * 21 */ 22 23 package java.util; 24 25 import java.io.*; 26 import java.security.AccessController; 27 import java.text.MessageFormat; 28 import java.util.List; 29 import java.util.concurrent.ConcurrentHashMap; 30 import java.util.spi.LocaleNameProvider; 31 import java.util.spi.LocaleServiceProvider; 32 import sun.security.action.GetPropertyAction; 33 import sun.util.LocaleServiceProviderPool; 34 import sun.util.resources.LocaleData; 35 import sun.util.resources.OpenListResourceBundle; 36 37 /** 38 * 39 * A <code>Locale</code> object represents a specific geographical, political, 40 * or cultural region. An operation that requires a <code>Locale</code> to perform 41 * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code> 42 * to tailor information for the user. For example, displaying a number 43 * is a locale-sensitive operation--the number should be formatted 44 * according to the customs/conventions of the user's native country, 45 * region, or culture. 46 * 47 * <P> 48 * Create a <code>Locale</code> object using the constructors in this class: 49 * <blockquote> 50 * <pre> 51 * Locale(String language) 52 * Locale(String language, String country) 53 * Locale(String language, String country, String variant) 54 * </pre> 55 * </blockquote> 56 * The language argument is a valid <STRONG>ISO Language Code.</STRONG> 57 * These codes are the lower-case, two-letter codes as defined by ISO-639. 58 * You can find a full list of these codes at a number of sites, such as: 59 * <BR><a href ="http://www.loc.gov/standards/iso639-2/englangn.html"> 60 * <code>http://www.loc.gov/standards/iso639-2/englangn.html</code></a> 61 * 62 * <P> 63 * The country argument is a valid <STRONG>ISO Country Code.</STRONG> These 64 * codes are the upper-case, two-letter codes as defined by ISO-3166. 65 * You can find a full list of these codes at a number of sites, such as: 66 * <BR><a href="http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html"> 67 * <code>http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html</code></a> 68 * 69 * <P> 70 * The variant argument is a vendor or browser-specific code. 71 * For example, use WIN for Windows, MAC for Macintosh, and POSIX for POSIX. 72 * Where there are two variants, separate them with an underscore, and 73 * put the most important one first. For example, a Traditional Spanish collation 74 * might construct a locale with parameters for language, country and variant as: 75 * "es", "ES", "Traditional_WIN". 76 * 77 * <P> 78 * Because a <code>Locale</code> object is just an identifier for a region, 79 * no validity check is performed when you construct a <code>Locale</code>. 80 * If you want to see whether particular resources are available for the 81 * <code>Locale</code> you construct, you must query those resources. For 82 * example, ask the <code>NumberFormat</code> for the locales it supports 83 * using its <code>getAvailableLocales</code> method. 84 * <BR><STRONG>Note:</STRONG> When you ask for a resource for a particular 85 * locale, you get back the best available match, not necessarily 86 * precisely what you asked for. For more information, look at 87 * {@link ResourceBundle}. 88 * 89 * <P> 90 * The <code>Locale</code> class provides a number of convenient constants 91 * that you can use to create <code>Locale</code> objects for commonly used 92 * locales. For example, the following creates a <code>Locale</code> object 93 * for the United States: 94 * <blockquote> 95 * <pre> 96 * Locale.US 97 * </pre> 98 * </blockquote> 99 * 100 * <P> 101 * Once you've created a <code>Locale</code> you can query it for information about 102 * itself. Use <code>getCountry</code> to get the ISO Country Code and 103 * <code>getLanguage</code> to get the ISO Language Code. You can 104 * use <code>getDisplayCountry</code> to get the 105 * name of the country suitable for displaying to the user. Similarly, 106 * you can use <code>getDisplayLanguage</code> to get the name of 107 * the language suitable for displaying to the user. Interestingly, 108 * the <code>getDisplayXXX</code> methods are themselves locale-sensitive 109 * and have two versions: one that uses the default locale and one 110 * that uses the locale specified as an argument. 111 * 112 * <P> 113 * The Java Platform provides a number of classes that perform locale-sensitive 114 * operations. For example, the <code>NumberFormat</code> class formats 115 * numbers, currency, or percentages in a locale-sensitive manner. Classes 116 * such as <code>NumberFormat</code> have a number of convenience methods 117 * for creating a default object of that type. For example, the 118 * <code>NumberFormat</code> class provides these three convenience methods 119 * for creating a default <code>NumberFormat</code> object: 120 * <blockquote> 121 * <pre> 122 * NumberFormat.getInstance() 123 * NumberFormat.getCurrencyInstance() 124 * NumberFormat.getPercentInstance() 125 * </pre> 126 * </blockquote> 127 * These methods have two variants; one with an explicit locale 128 * and one without; the latter using the default locale. 129 * <blockquote> 130 * <pre> 131 * NumberFormat.getInstance(myLocale) 132 * NumberFormat.getCurrencyInstance(myLocale) 133 * NumberFormat.getPercentInstance(myLocale) 134 * </pre> 135 * </blockquote> 136 * A <code>Locale</code> is the mechanism for identifying the kind of object 137 * (<code>NumberFormat</code>) that you would like to get. The locale is 138 * <STRONG>just</STRONG> a mechanism for identifying objects, 139 * <STRONG>not</STRONG> a container for the objects themselves. 140 * 141 * @see ResourceBundle 142 * @see java.text.Format 143 * @see java.text.NumberFormat 144 * @see java.text.Collator 145 * @author Mark Davis 146 * @since 1.1 147 */ 148 149 public final class Locale implements Cloneable, Serializable { 150 151 // cache to store singleton Locales 152 private final static ConcurrentHashMap<String, Locale> cache = 153 new ConcurrentHashMap<String, Locale>(32); 154 155 /** Useful constant for language. 156 */ 157 static public final Locale ENGLISH = createSingleton("en__", "en", ""); 158 159 /** Useful constant for language. 160 */ 161 static public final Locale FRENCH = createSingleton("fr__", "fr", ""); 162 163 /** Useful constant for language. 164 */ 165 static public final Locale GERMAN = createSingleton("de__", "de", ""); 166 167 /** Useful constant for language. 168 */ 169 static public final Locale ITALIAN = createSingleton("it__", "it", ""); 170 171 /** Useful constant for language. 172 */ 173 static public final Locale JAPANESE = createSingleton("ja__", "ja", ""); 174 175 /** Useful constant for language. 176 */ 177 static public final Locale KOREAN = createSingleton("ko__", "ko", ""); 178 179 /** Useful constant for language. 180 */ 181 static public final Locale CHINESE = createSingleton("zh__", "zh", ""); 182 183 /** Useful constant for language. 184 */ 185 static public final Locale SIMPLIFIED_CHINESE = createSingleton("zh_CN_", "zh", "CN"); 186 187 /** Useful constant for language. 188 */ 189 static public final Locale TRADITIONAL_CHINESE = createSingleton("zh_TW_", "zh", "TW"); 190 191 /** Useful constant for country. 192 */ 193 static public final Locale FRANCE = createSingleton("fr_FR_", "fr", "FR"); 194 195 /** Useful constant for country. 196 */ 197 static public final Locale GERMANY = createSingleton("de_DE_", "de", "DE"); 198 199 /** Useful constant for country. 200 */ 201 static public final Locale ITALY = createSingleton("it_IT_", "it", "IT"); 202 203 /** Useful constant for country. 204 */ 205 static public final Locale JAPAN = createSingleton("ja_JP_", "ja", "JP"); 206 207 /** Useful constant for country. 208 */ 209 static public final Locale KOREA = createSingleton("ko_KR_", "ko", "KR"); 210 211 /** Useful constant for country. 212 */ 213 static public final Locale CHINA = SIMPLIFIED_CHINESE; 214 215 /** Useful constant for country. 216 */ 217 static public final Locale PRC = SIMPLIFIED_CHINESE; 218 219 /** Useful constant for country. 220 */ 221 static public final Locale TAIWAN = TRADITIONAL_CHINESE; 222 223 /** Useful constant for country. 224 */ 225 static public final Locale UK = createSingleton("en_GB_", "en", "GB"); 226 227 /** Useful constant for country. 228 */ 229 static public final Locale US = createSingleton("en_US_", "en", "US"); 230 231 /** Useful constant for country. 232 */ 233 static public final Locale CANADA = createSingleton("en_CA_", "en", "CA"); 234 235 /** Useful constant for country. 236 */ 237 static public final Locale CANADA_FRENCH = createSingleton("fr_CA_", "fr", "CA"); 238 239 /** 240 * Useful constant for the root locale. The root locale is the locale whose 241 * language, country, and variant are empty ("") strings. This is regarded 242 * as the base locale of all locales, and is used as the language/country 243 * neutral locale for the locale sensitive operations. 244 * 245 * @since 1.6 246 */ 247 static public final Locale ROOT = createSingleton("__", "", ""); 248 249 /** serialization ID 250 */ 251 static final long serialVersionUID = 9149081749638150636L; 252 253 /** 254 * Display types for retrieving localized names from the name providers. 255 */ 256 private static final int DISPLAY_LANGUAGE = 0; 257 private static final int DISPLAY_COUNTRY = 1; 258 private static final int DISPLAY_VARIANT = 2; 259 260 /** 261 * Construct a locale from language, country, variant. 262 * NOTE: ISO 639 is not a stable standard; some of the language codes it defines 263 * (specifically iw, ji, and in) have changed. This constructor accepts both the 264 * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other 265 * API on Locale will return only the OLD codes. 266 * @param language lowercase two-letter ISO-639 code. 267 * @param country uppercase two-letter ISO-3166 code. 268 * @param variant vendor and browser specific code. See class description. 269 * @exception NullPointerException thrown if any argument is null. 270 */ 271 public Locale(String language, String country, String variant) { 272 this.language = convertOldISOCodes(language); 273 this.country = toUpperCase(country).intern(); 274 this.variant = variant.intern(); 275 } 276 277 /** 278 * Construct a locale from language, country. 279 * NOTE: ISO 639 is not a stable standard; some of the language codes it defines 280 * (specifically iw, ji, and in) have changed. This constructor accepts both the 281 * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other 282 * API on Locale will return only the OLD codes. 283 * @param language lowercase two-letter ISO-639 code. 284 * @param country uppercase two-letter ISO-3166 code. 285 * @exception NullPointerException thrown if either argument is null. 286 */ 287 public Locale(String language, String country) { 288 this(language, country, ""); 289 } 290 291 /** 292 * Construct a locale from a language code. 293 * NOTE: ISO 639 is not a stable standard; some of the language codes it defines 294 * (specifically iw, ji, and in) have changed. This constructor accepts both the 295 * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other 296 * API on Locale will return only the OLD codes. 297 * @param language lowercase two-letter ISO-639 code. 298 * @exception NullPointerException thrown if argument is null. 299 * @since 1.4 300 */ 301 public Locale(String language) { 302 this(language, "", ""); 303 } 304 305 /** 306 * Constructs a <code>Locale</code> using <code>language</code> 307 * and <code>country</code>. This constructor assumes that 308 * <code>language</code> and <code>contry</code> are interned and 309 * it is invoked by createSingleton only. (flag is just for 310 * avoiding the conflict with the public constructors. 311 */ 312 private Locale(String language, String country, boolean flag) { 313 this.language = language; 314 this.country = country; 315 this.variant = ""; 316 } 317 318 /** 319 * Creates a <code>Locale</code> instance with the given 320 * <code>language</code> and <code>counry</code> and puts the 321 * instance under the given <code>key</code> in the cache. This 322 * method must be called only when initializing the Locale 323 * constants. 324 */ 325 private static Locale createSingleton(String key, String language, String country) { 326 Locale locale = new Locale(language, country, false); 327 cache.put(key, locale); 328 return locale; 329 } 330 331 /** 332 * Returns a <code>Locale</code> constructed from the given 333 * <code>language</code>, <code>country</code> and 334 * <code>variant</code>. If the same <code>Locale</code> instance 335 * is available in the cache, then that instance is 336 * returned. Otherwise, a new <code>Locale</code> instance is 337 * created and cached. 338 * 339 * @param language lowercase two-letter ISO-639 code. 340 * @param country uppercase two-letter ISO-3166 code. 341 * @param variant vendor and browser specific code. See class description. 342 * @return the <code>Locale</code> instance requested 343 * @exception NullPointerException if any argument is null. 344 */ 345 static Locale getInstance(String language, String country, String variant) { 346 if (language== null || country == null || variant == null) { 347 throw new NullPointerException(); 348 } 349 350 StringBuilder sb = new StringBuilder(); 351 sb.append(language).append('_').append(country).append('_').append(variant); 352 String key = sb.toString(); 353 Locale locale = cache.get(key); 354 if (locale == null) { 355 locale = new Locale(language, country, variant); 356 Locale l = cache.putIfAbsent(key, locale); 357 if (l != null) { 358 locale = l; 359 } 360 } 361 return locale; 362 } 363 364 /** 365 * Gets the current value of the default locale for this instance 366 * of the Java Virtual Machine. 367 * <p> 368 * The Java Virtual Machine sets the default locale during startup 369 * based on the host environment. It is used by many locale-sensitive 370 * methods if no locale is explicitly specified. 371 * It can be changed using the 372 * {@link #setDefault(java.util.Locale) setDefault} method. 373 * 374 * @return the default locale for this instance of the Java Virtual Machine 375 */ 376 public static Locale getDefault() { 377 // do not synchronize this method - see 4071298 378 // it's OK if more than one default locale happens to be created 379 if (defaultLocale == null) { 380 String language, region, country, variant; 381 language = (String) AccessController.doPrivileged( 382 new GetPropertyAction("user.language", "en")); 383 // for compatibility, check for old user.region property 384 region = (String) AccessController.doPrivileged( 385 new GetPropertyAction("user.region")); 386 if (region != null) { 387 // region can be of form country, country_variant, or _variant 388 int i = region.indexOf('_'); 389 if (i >= 0) { 390 country = region.substring(0, i); 391 variant = region.substring(i + 1); 392 } else { 393 country = region; 394 variant = ""; 395 } 396 } else { 397 country = (String) AccessController.doPrivileged( 398 new GetPropertyAction("user.country", "")); 399 variant = (String) AccessController.doPrivileged( 400 new GetPropertyAction("user.variant", "")); 401 } 402 defaultLocale = getInstance(language, country, variant); 403 } 404 return defaultLocale; 405 } 406 407 /** 408 * Sets the default locale for this instance of the Java Virtual Machine. 409 * This does not affect the host locale. 410 * <p> 411 * If there is a security manager, its <code>checkPermission</code> 412 * method is called with a <code>PropertyPermission("user.language", "write")</code> 413 * permission before the default locale is changed. 414 * <p> 415 * The Java Virtual Machine sets the default locale during startup 416 * based on the host environment. It is used by many locale-sensitive 417 * methods if no locale is explicitly specified. 418 * <p> 419 * Since changing the default locale may affect many different areas 420 * of functionality, this method should only be used if the caller 421 * is prepared to reinitialize locale-sensitive code running 422 * within the same Java Virtual Machine. 423 * 424 * @throws SecurityException 425 * if a security manager exists and its 426 * <code>checkPermission</code> method doesn't allow the operation. 427 * @throws NullPointerException if <code>newLocale</code> is null 428 * @param newLocale the new default locale 429 * @see SecurityManager#checkPermission 430 * @see java.util.PropertyPermission 431 */ 432 public static synchronized void setDefault(Locale newLocale) { 433 if (newLocale == null) 434 throw new NullPointerException("Can't set default locale to NULL"); 435 436 SecurityManager sm = System.getSecurityManager(); 437 if (sm != null) sm.checkPermission(new PropertyPermission 438 ("user.language", "write")); 439 defaultLocale = newLocale; 440 } 441 442 /** 443 * Returns an array of all installed locales. 444 * The returned array represents the union of locales supported 445 * by the Java runtime environment and by installed 446 * {@link java.util.spi.LocaleServiceProvider LocaleServiceProvider} 447 * implementations. It must contain at least a <code>Locale</code> 448 * instance equal to {@link java.util.Locale#US Locale.US}. 449 * 450 * @return An array of installed locales. 451 */ 452 public static Locale[] getAvailableLocales() { 453 return LocaleServiceProviderPool.getAllAvailableLocales(); 454 } 455 456 /** 457 * Returns a list of all 2-letter country codes defined in ISO 3166. 458 * Can be used to create Locales. 459 */ 460 public static String[] getISOCountries() { 461 if (isoCountries == null) { 462 isoCountries = getISO2Table(LocaleISOData.isoCountryTable); 463 } 464 String[] result = new String[isoCountries.length]; 465 System.arraycopy(isoCountries, 0, result, 0, isoCountries.length); 466 return result; 467 } 468 469 /** 470 * Returns a list of all 2-letter language codes defined in ISO 639. 471 * Can be used to create Locales. 472 * [NOTE: ISO 639 is not a stable standard-- some languages' codes have changed. 473 * The list this function returns includes both the new and the old codes for the 474 * languages whose codes have changed.] 475 */ 476 public static String[] getISOLanguages() { 477 if (isoLanguages == null) { 478 isoLanguages = getISO2Table(LocaleISOData.isoLanguageTable); 479 } 480 String[] result = new String[isoLanguages.length]; 481 System.arraycopy(isoLanguages, 0, result, 0, isoLanguages.length); 482 return result; 483 } 484 485 private static final String[] getISO2Table(String table) { 486 int len = table.length() / 5; 487 String[] isoTable = new String[len]; 488 for (int i = 0, j = 0; i < len; i++, j += 5) { 489 isoTable[i] = table.substring(j, j + 2); 490 } 491 return isoTable; 492 } 493 494 /** 495 * Returns the language code for this locale, which will either be the empty string 496 * or a lowercase ISO 639 code. 497 * <p>NOTE: ISO 639 is not a stable standard-- some languages' codes have changed. 498 * Locale's constructor recognizes both the new and the old codes for the languages 499 * whose codes have changed, but this function always returns the old code. If you 500 * want to check for a specific language whose code has changed, don't do <pre> 501 * if (locale.getLanguage().equals("he")) 502 * ... 503 * </pre>Instead, do<pre> 504 * if (locale.getLanguage().equals(new Locale("he", "", "").getLanguage())) 505 * ...</pre> 506 * @see #getDisplayLanguage 507 */ 508 public String getLanguage() { 509 return language; 510 } 511 512 /** 513 * Returns the country/region code for this locale, which will 514 * either be the empty string or an uppercase ISO 3166 2-letter code. 515 * @see #getDisplayCountry 516 */ 517 public String getCountry() { 518 return country; 519 } 520 521 /** 522 * Returns the variant code for this locale. 523 * @see #getDisplayVariant 524 */ 525 public String getVariant() { 526 return variant; 527 } 528 529 /** 530 * Getter for the programmatic name of the entire locale, 531 * with the language, country and variant separated by underbars. 532 * Language is always lower case, and country is always upper case. 533 * If the language is missing, the string will begin with an underbar. 534 * If both the language and country fields are missing, this function 535 * will return the empty string, even if the variant field is filled in 536 * (you can't have a locale with just a variant-- the variant must accompany 537 * a valid language or country code). 538 * Examples: "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "fr__MAC" 539 * @see #getDisplayName 540 */ 541 public final String toString() { 542 boolean l = language.length() != 0; 543 boolean c = country.length() != 0; 544 boolean v = variant.length() != 0; 545 StringBuilder result = new StringBuilder(language); 546 if (c||(l&&v)) { 547 result.append('_').append(country); // This may just append '_' 548 } 549 if (v&&(l||c)) { 550 result.append('_').append(variant); 551 } 552 return result.toString(); 553 } 554 555 /** 556 * Returns a three-letter abbreviation for this locale's language. If the locale 557 * doesn't specify a language, this will be the empty string. Otherwise, this will 558 * be a lowercase ISO 639-2/T language code. 559 * The ISO 639-2 language codes can be found on-line at 560 * <a href="http://www.loc.gov/standards/iso639-2/englangn.html"> 561 * <code>http://www.loc.gov/standards/iso639-2/englangn.html</code>.</a> 562 * @exception MissingResourceException Throws MissingResourceException if the 563 * three-letter language abbreviation is not available for this locale. 564 */ 565 public String getISO3Language() throws MissingResourceException { 566 String language3 = getISO3Code(language, LocaleISOData.isoLanguageTable); 567 if (language3 == null) { 568 throw new MissingResourceException("Couldn't find 3-letter language code for " 569 + language, "FormatData_" + toString(), "ShortLanguage"); 570 } 571 return language3; 572 } 573 574 /** 575 * Returns a three-letter abbreviation for this locale's country. If the locale 576 * doesn't specify a country, this will be the empty string. Otherwise, this will 577 * be an uppercase ISO 3166 3-letter country code. 578 * The ISO 3166-2 country codes can be found on-line at 579 * <a href="http://www.davros.org/misc/iso3166.txt"> 580 * <code>http://www.davros.org/misc/iso3166.txt</code>.</a> 581 * @exception MissingResourceException Throws MissingResourceException if the 582 * three-letter country abbreviation is not available for this locale. 583 */ 584 public String getISO3Country() throws MissingResourceException { 585 String country3 = getISO3Code(country, LocaleISOData.isoCountryTable); 586 if (country3 == null) { 587 throw new MissingResourceException("Couldn't find 3-letter country code for " 588 + country, "FormatData_" + toString(), "ShortCountry"); 589 } 590 return country3; 591 } 592 593 private static final String getISO3Code(String iso2Code, String table) { 594 int codeLength = iso2Code.length(); 595 if (codeLength == 0) { 596 return ""; 597 } 598 599 int tableLength = table.length(); 600 int index = tableLength; 601 if (codeLength == 2) { 602 char c1 = iso2Code.charAt(0); 603 char c2 = iso2Code.charAt(1); 604 for (index = 0; index < tableLength; index += 5) { 605 if (table.charAt(index) == c1 606 && table.charAt(index + 1) == c2) { 607 break; 608 } 609 } 610 } 611 return index < tableLength ? table.substring(index + 2, index + 5) : null; 612 } 613 614 /** 615 * Returns a name for the locale's language that is appropriate for display to the 616 * user. 617 * If possible, the name returned will be localized for the default locale. 618 * For example, if the locale is fr_FR and the default locale 619 * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and 620 * the default locale is fr_FR, getDisplayLanguage() will return "anglais". 621 * If the name returned cannot be localized for the default locale, 622 * (say, we don't have a Japanese name for Croatian), 623 * this function falls back on the English name, and uses the ISO code as a last-resort 624 * value. If the locale doesn't specify a language, this function returns the empty string. 625 */ 626 public final String getDisplayLanguage() { 627 return getDisplayLanguage(getDefault()); 628 } 629 630 /** 631 * Returns a name for the locale's language that is appropriate for display to the 632 * user. 633 * If possible, the name returned will be localized according to inLocale. 634 * For example, if the locale is fr_FR and inLocale 635 * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and 636 * inLocale is fr_FR, getDisplayLanguage() will return "anglais". 637 * If the name returned cannot be localized according to inLocale, 638 * (say, we don't have a Japanese name for Croatian), 639 * this function falls back on the English name, and finally 640 * on the ISO code as a last-resort value. If the locale doesn't specify a language, 641 * this function returns the empty string. 642 * 643 * @exception NullPointerException if <code>inLocale</code> is <code>null</code> 644 */ 645 public String getDisplayLanguage(Locale inLocale) { 646 return getDisplayString(language, inLocale, DISPLAY_LANGUAGE); 647 } 648 649 /** 650 * Returns a name for the locale's country that is appropriate for display to the 651 * user. 652 * If possible, the name returned will be localized for the default locale. 653 * For example, if the locale is fr_FR and the default locale 654 * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and 655 * the default locale is fr_FR, getDisplayCountry() will return "Etats-Unis". 656 * If the name returned cannot be localized for the default locale, 657 * (say, we don't have a Japanese name for Croatia), 658 * this function falls back on the English name, and uses the ISO code as a last-resort 659 * value. If the locale doesn't specify a country, this function returns the empty string. 660 */ 661 public final String getDisplayCountry() { 662 return getDisplayCountry(getDefault()); 663 } 664 665 /** 666 * Returns a name for the locale's country that is appropriate for display to the 667 * user. 668 * If possible, the name returned will be localized according to inLocale. 669 * For example, if the locale is fr_FR and inLocale 670 * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and 671 * inLocale is fr_FR, getDisplayCountry() will return "Etats-Unis". 672 * If the name returned cannot be localized according to inLocale. 673 * (say, we don't have a Japanese name for Croatia), 674 * this function falls back on the English name, and finally 675 * on the ISO code as a last-resort value. If the locale doesn't specify a country, 676 * this function returns the empty string. 677 * 678 * @exception NullPointerException if <code>inLocale</code> is <code>null</code> 679 */ 680 public String getDisplayCountry(Locale inLocale) { 681 return getDisplayString(country, inLocale, DISPLAY_COUNTRY); 682 } 683 684 private String getDisplayString(String code, Locale inLocale, int type) { 685 if (code.length() == 0) { 686 return ""; 687 } 688 689 if (inLocale == null) { 690 throw new NullPointerException(); 691 } 692 693 try { 694 OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale); 695 String key = (type == DISPLAY_VARIANT ? "%%"+code : code); 696 String result = null; 697 698 // Check whether a provider can provide an implementation that's closer 699 // to the requested locale than what the Java runtime itself can provide. 700 LocaleServiceProviderPool pool = 701 LocaleServiceProviderPool.getPool(LocaleNameProvider.class); 702 if (pool.hasProviders()) { 703 result = pool.getLocalizedObject( 704 LocaleNameGetter.INSTANCE, 705 inLocale, bundle, key, 706 type, code); 707 } 708 709 if (result == null) { 710 result = bundle.getString(key); 711 } 712 713 if (result != null) { 714 return result; 715 } 716 } 717 catch (Exception e) { 718 // just fall through 719 } 720 return code; 721 } 722 723 /** 724 * Returns a name for the locale's variant code that is appropriate for display to the 725 * user. If possible, the name will be localized for the default locale. If the locale 726 * doesn't specify a variant code, this function returns the empty string. 727 */ 728 public final String getDisplayVariant() { 729 return getDisplayVariant(getDefault()); 730 } 731 732 /** 733 * Returns a name for the locale's variant code that is appropriate for display to the 734 * user. If possible, the name will be localized for inLocale. If the locale 735 * doesn't specify a variant code, this function returns the empty string. 736 * 737 * @exception NullPointerException if <code>inLocale</code> is <code>null</code> 738 */ 739 public String getDisplayVariant(Locale inLocale) { 740 if (variant.length() == 0) 741 return ""; 742 743 OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale); 744 745 String names[] = getDisplayVariantArray(bundle, inLocale); 746 747 // Get the localized patterns for formatting a list, and use 748 // them to format the list. 749 String listPattern = null; 750 String listCompositionPattern = null; 751 try { 752 listPattern = bundle.getString("ListPattern"); 753 listCompositionPattern = bundle.getString("ListCompositionPattern"); 754 } catch (MissingResourceException e) { 755 } 756 return formatList(names, listPattern, listCompositionPattern); 757 } 758 759 /** 760 * Returns a name for the locale that is appropriate for display to the 761 * user. This will be the values returned by getDisplayLanguage(), getDisplayCountry(), 762 * and getDisplayVariant() assembled into a single string. The display name will have 763 * one of the following forms:<p><blockquote> 764 * language (country, variant)<p> 765 * language (country)<p> 766 * language (variant)<p> 767 * country (variant)<p> 768 * language<p> 769 * country<p> 770 * variant<p></blockquote> 771 * depending on which fields are specified in the locale. If the language, country, 772 * and variant fields are all empty, this function returns the empty string. 773 */ 774 public final String getDisplayName() { 775 return getDisplayName(getDefault()); 776 } 777 778 /** 779 * Returns a name for the locale that is appropriate for display to the 780 * user. This will be the values returned by getDisplayLanguage(), getDisplayCountry(), 781 * and getDisplayVariant() assembled into a single string. The display name will have 782 * one of the following forms:<p><blockquote> 783 * language (country, variant)<p> 784 * language (country)<p> 785 * language (variant)<p> 786 * country (variant)<p> 787 * language<p> 788 * country<p> 789 * variant<p></blockquote> 790 * depending on which fields are specified in the locale. If the language, country, 791 * and variant fields are all empty, this function returns the empty string. 792 * 793 * @exception NullPointerException if <code>inLocale</code> is <code>null</code> 794 */ 795 public String getDisplayName(Locale inLocale) { 796 OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale); 797 798 String languageName = getDisplayLanguage(inLocale); 799 String countryName = getDisplayCountry(inLocale); 800 String[] variantNames = getDisplayVariantArray(bundle, inLocale); 801 802 // Get the localized patterns for formatting a display name. 803 String displayNamePattern = null; 804 String listPattern = null; 805 String listCompositionPattern = null; 806 try { 807 displayNamePattern = bundle.getString("DisplayNamePattern"); 808 listPattern = bundle.getString("ListPattern"); 809 listCompositionPattern = bundle.getString("ListCompositionPattern"); 810 } catch (MissingResourceException e) { 811 } 812 813 // The display name consists of a main name, followed by qualifiers. 814 // Typically, the format is "MainName (Qualifier, Qualifier)" but this 815 // depends on what pattern is stored in the display locale. 816 String mainName = null; 817 String[] qualifierNames = null; 818 819 // The main name is the language, or if there is no language, the country. 820 // If there is neither language nor country (an anomalous situation) then 821 // the display name is simply the variant's display name. 822 if (languageName.length() != 0) { 823 mainName = languageName; 824 if (countryName.length() != 0) { 825 qualifierNames = new String[variantNames.length + 1]; 826 System.arraycopy(variantNames, 0, qualifierNames, 1, variantNames.length); 827 qualifierNames[0] = countryName; 828 } 829 else qualifierNames = variantNames; 830 } 831 else if (countryName.length() != 0) { 832 mainName = countryName; 833 qualifierNames = variantNames; 834 } 835 else { 836 return formatList(variantNames, listPattern, listCompositionPattern); 837 } 838 839 // Create an array whose first element is the number of remaining 840 // elements. This serves as a selector into a ChoiceFormat pattern from 841 // the resource. The second and third elements are the main name and 842 // the qualifier; if there are no qualifiers, the third element is 843 // unused by the format pattern. 844 Object[] displayNames = { 845 new Integer(qualifierNames.length != 0 ? 2 : 1), 846 mainName, 847 // We could also just call formatList() and have it handle the empty 848 // list case, but this is more efficient, and we want it to be 849 // efficient since all the language-only locales will not have any 850 // qualifiers. 851 qualifierNames.length != 0 ? formatList(qualifierNames, listPattern, listCompositionPattern) : null 852 }; 853 854 if (displayNamePattern != null) { 855 return new MessageFormat(displayNamePattern).format(displayNames); 856 } 857 else { 858 // If we cannot get the message format pattern, then we use a simple 859 // hard-coded pattern. This should not occur in practice unless the 860 // installation is missing some core files (FormatData etc.). 861 StringBuilder result = new StringBuilder(); 862 result.append((String)displayNames[1]); 863 if (displayNames.length > 2) { 864 result.append(" ("); 865 result.append((String)displayNames[2]); 866 result.append(')'); 867 } 868 return result.toString(); 869 } 870 } 871 872 /** 873 * Overrides Cloneable 874 */ 875 public Object clone() 876 { 877 try { 878 Locale that = (Locale)super.clone(); 879 return that; 880 } catch (CloneNotSupportedException e) { 881 throw new InternalError(); 882 } 883 } 884 885 /** 886 * Override hashCode. 887 * Since Locales are often used in hashtables, caches the value 888 * for speed. 889 */ 890 public int hashCode() { 891 int hc = hashCodeValue; 892 if (hc == 0) { 893 hc = (language.hashCode() << 8) ^ country.hashCode() ^ (variant.hashCode() << 4); 894 hashCodeValue = hc; 895 } 896 return hc; 897 } 898 899 // Overrides 900 901 /** 902 * Returns true if this Locale is equal to another object. A Locale is 903 * deemed equal to another Locale with identical language, country, 904 * and variant, and unequal to all other objects. 905 * 906 * @return true if this Locale is equal to the specified object. 907 */ 908 909 public boolean equals(Object obj) { 910 if (this == obj) // quick check 911 return true; 912 if (!(obj instanceof Locale)) 913 return false; 914 Locale other = (Locale) obj; 915 return language == other.language 916 && country == other.country 917 && variant == other.variant; 918 } 919 920 // ================= privates ===================================== 921 922 // XXX instance and class variables. For now keep these separate, since it is 923 // faster to match. Later, make into single string. 924 925 /** 926 * @serial 927 * @see #getLanguage 928 */ 929 private final String language; 930 931 /** 932 * @serial 933 * @see #getCountry 934 */ 935 private final String country; 936 937 /** 938 * @serial 939 * @see #getVariant 940 */ 941 private final String variant; 942 943 /** 944 * Placeholder for the object's hash code. Always -1. 945 * @serial 946 */ 947 private volatile int hashcode = -1; // lazy evaluate 948 949 /** 950 * Calculated hashcode to fix 4518797. 951 */ 952 private transient volatile int hashCodeValue = 0; 953 954 private static Locale defaultLocale = null; 955 956 /** 957 * Return an array of the display names of the variant. 958 * @param bundle the ResourceBundle to use to get the display names 959 * @return an array of display names, possible of zero length. 960 */ 961 private String[] getDisplayVariantArray(OpenListResourceBundle bundle, Locale inLocale) { 962 // Split the variant name into tokens separated by '_'. 963 StringTokenizer tokenizer = new StringTokenizer(variant, "_"); 964 String[] names = new String[tokenizer.countTokens()]; 965 966 // For each variant token, lookup the display name. If 967 // not found, use the variant name itself. 968 for (int i=0; i<names.length; ++i) { 969 names[i] = getDisplayString(tokenizer.nextToken(), 970 inLocale, DISPLAY_VARIANT); 971 } 972 973 return names; 974 } 975 976 /** 977 * Format a list using given pattern strings. 978 * If either of the patterns is null, then a the list is 979 * formatted by concatenation with the delimiter ','. 980 * @param stringList the list of strings to be formatted. 981 * @param listPattern should create a MessageFormat taking 0-3 arguments 982 * and formatting them into a list. 983 * @param listCompositionPattern should take 2 arguments 984 * and is used by composeList. 985 * @return a string representing the list. 986 */ 987 private static String formatList(String[] stringList, String listPattern, String listCompositionPattern) { 988 // If we have no list patterns, compose the list in a simple, 989 // non-localized way. 990 if (listPattern == null || listCompositionPattern == null) { 991 StringBuffer result = new StringBuffer(); 992 for (int i=0; i<stringList.length; ++i) { 993 if (i>0) result.append(','); 994 result.append(stringList[i]); 995 } 996 return result.toString(); 997 } 998 999 // Compose the list down to three elements if necessary 1000 if (stringList.length > 3) { 1001 MessageFormat format = new MessageFormat(listCompositionPattern); 1002 stringList = composeList(format, stringList); 1003 } 1004 1005 // Rebuild the argument list with the list length as the first element 1006 Object[] args = new Object[stringList.length + 1]; 1007 System.arraycopy(stringList, 0, args, 1, stringList.length); 1008 args[0] = new Integer(stringList.length); 1009 1010 // Format it using the pattern in the resource 1011 MessageFormat format = new MessageFormat(listPattern); 1012 return format.format(args); 1013 } 1014 1015 /** 1016 * Given a list of strings, return a list shortened to three elements. 1017 * Shorten it by applying the given format to the first two elements 1018 * recursively. 1019 * @param format a format which takes two arguments 1020 * @param list a list of strings 1021 * @return if the list is three elements or shorter, the same list; 1022 * otherwise, a new list of three elements. 1023 */ 1024 private static String[] composeList(MessageFormat format, String[] list) { 1025 if (list.length <= 3) return list; 1026 1027 // Use the given format to compose the first two elements into one 1028 String[] listItems = { list[0], list[1] }; 1029 String newItem = format.format(listItems); 1030 1031 // Form a new list one element shorter 1032 String[] newList = new String[list.length-1]; 1033 System.arraycopy(list, 2, newList, 1, newList.length-1); 1034 newList[0] = newItem; 1035 1036 // Recurse 1037 return composeList(format, newList); 1038 } 1039 1040 /** 1041 * Replace the deserialized Locale object with a newly 1042 * created object. Newer language codes are replaced with older ISO 1043 * codes. The country and variant codes are replaced with internalized 1044 * String copies. 1045 */ 1046 private Object readResolve() throws java.io.ObjectStreamException { 1047 return getInstance(language, country, variant); 1048 } 1049 1050 private static volatile String[] isoLanguages = null; 1051 1052 private static volatile String[] isoCountries = null; 1053 1054 /* 1055 * Locale needs its own, locale insensitive version of toLowerCase to 1056 * avoid circularity problems between Locale and String. 1057 * The most straightforward algorithm is used. Look at optimizations later. 1058 */ 1059 private String toLowerCase(String str) { 1060 char[] buf = new char[str.length()]; 1061 for (int i = 0; i < buf.length; i++) { 1062 buf[i] = Character.toLowerCase(str.charAt(i)); 1063 } 1064 return new String( buf ); 1065 } 1066 1067 /* 1068 * Locale needs its own, locale insensitive version of toUpperCase to 1069 * avoid circularity problems between Locale and String. 1070 * The most straightforward algorithm is used. Look at optimizations later. 1071 */ 1072 private String toUpperCase(String str) { 1073 char[] buf = new char[str.length()]; 1074 for (int i = 0; i < buf.length; i++) { 1075 buf[i] = Character.toUpperCase(str.charAt(i)); 1076 } 1077 return new String( buf ); 1078 } 1079 1080 private String convertOldISOCodes(String language) { 1081 // we accept both the old and the new ISO codes for the languages whose ISO 1082 // codes have changed, but we always store the OLD code, for backward compatibility 1083 language = toLowerCase(language).intern(); 1084 if (language == "he") { 1085 return "iw"; 1086 } else if (language == "yi") { 1087 return "ji"; 1088 } else if (language == "id") { 1089 return "in"; 1090 } else { 1091 return language; 1092 } 1093 } 1094 1095 /** 1096 * Obtains a localized locale names from a LocaleNameProvider 1097 * implementation. 1098 */ 1099 private static class LocaleNameGetter 1100 implements LocaleServiceProviderPool.LocalizedObjectGetter<LocaleNameProvider, String> { 1101 private static final LocaleNameGetter INSTANCE = new LocaleNameGetter(); 1102 1103 public String getObject(LocaleNameProvider localeNameProvider, 1104 Locale locale, 1105 String key, 1106 Object... params) { 1107 assert params.length == 2; 1108 int type = (Integer)params[0]; 1109 String code = (String)params[1]; 1110 1111 switch(type) { 1112 case DISPLAY_LANGUAGE: 1113 return localeNameProvider.getDisplayLanguage(code, locale); 1114 case DISPLAY_COUNTRY: 1115 return localeNameProvider.getDisplayCountry(code, locale); 1116 case DISPLAY_VARIANT: 1117 return localeNameProvider.getDisplayVariant(code, locale); 1118 default: 1119 assert false; // shouldn't happen 1120 } 1121 1122 return null; 1123 } 1124 } 1125} 1126