0001 /*
0002 * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 /*
0027 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
0028 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
0029 *
0030 * The original version of this source code and documentation
0031 * is copyrighted and owned by Taligent, Inc., a wholly-owned
0032 * subsidiary of IBM. These materials are provided under terms
0033 * of a License Agreement between Taligent and Sun. This technology
0034 * is protected by multiple US and International patents.
0035 *
0036 * This notice and attribution to Taligent may not be removed.
0037 * Taligent is a registered trademark of Taligent, Inc.
0038 *
0039 */
0040
0041 package java.util;
0042
0043 import java.io.*;
0044 import java.security.AccessController;
0045 import java.text.MessageFormat;
0046 import java.util.List;
0047 import java.util.concurrent.ConcurrentHashMap;
0048 import java.util.spi.LocaleNameProvider;
0049 import java.util.spi.LocaleServiceProvider;
0050 import sun.security.action.GetPropertyAction;
0051 import sun.util.LocaleServiceProviderPool;
0052 import sun.util.resources.LocaleData;
0053 import sun.util.resources.OpenListResourceBundle;
0054
0055 /**
0056 *
0057 * A <code>Locale</code> object represents a specific geographical, political,
0058 * or cultural region. An operation that requires a <code>Locale</code> to perform
0059 * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code>
0060 * to tailor information for the user. For example, displaying a number
0061 * is a locale-sensitive operation--the number should be formatted
0062 * according to the customs/conventions of the user's native country,
0063 * region, or culture.
0064 *
0065 * <P>
0066 * Create a <code>Locale</code> object using the constructors in this class:
0067 * <blockquote>
0068 * <pre>
0069 * Locale(String language)
0070 * Locale(String language, String country)
0071 * Locale(String language, String country, String variant)
0072 * </pre>
0073 * </blockquote>
0074 * The language argument is a valid <STRONG>ISO Language Code.</STRONG>
0075 * These codes are the lower-case, two-letter codes as defined by ISO-639.
0076 * You can find a full list of these codes at a number of sites, such as:
0077 * <BR><a href ="http://www.loc.gov/standards/iso639-2/php/English_list.php">
0078 * <code>http://www.loc.gov/standards/iso639-2/php/English_list.php</code></a>
0079 *
0080 * <P>
0081 * The country argument is a valid <STRONG>ISO Country Code.</STRONG> These
0082 * codes are the upper-case, two-letter codes as defined by ISO-3166.
0083 * You can find a full list of these codes at a number of sites, such as:
0084 * <BR><a href="http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html">
0085 * <code>http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html</code></a>
0086 *
0087 * <P>
0088 * The variant argument is a vendor or browser-specific code.
0089 * For example, use WIN for Windows, MAC for Macintosh, and POSIX for POSIX.
0090 * Where there are two variants, separate them with an underscore, and
0091 * put the most important one first. For example, a Traditional Spanish collation
0092 * might construct a locale with parameters for language, country and variant as:
0093 * "es", "ES", "Traditional_WIN".
0094 *
0095 * <P>
0096 * Because a <code>Locale</code> object is just an identifier for a region,
0097 * no validity check is performed when you construct a <code>Locale</code>.
0098 * If you want to see whether particular resources are available for the
0099 * <code>Locale</code> you construct, you must query those resources. For
0100 * example, ask the <code>NumberFormat</code> for the locales it supports
0101 * using its <code>getAvailableLocales</code> method.
0102 * <BR><STRONG>Note:</STRONG> When you ask for a resource for a particular
0103 * locale, you get back the best available match, not necessarily
0104 * precisely what you asked for. For more information, look at
0105 * {@link ResourceBundle}.
0106 *
0107 * <P>
0108 * The <code>Locale</code> class provides a number of convenient constants
0109 * that you can use to create <code>Locale</code> objects for commonly used
0110 * locales. For example, the following creates a <code>Locale</code> object
0111 * for the United States:
0112 * <blockquote>
0113 * <pre>
0114 * Locale.US
0115 * </pre>
0116 * </blockquote>
0117 *
0118 * <P>
0119 * Once you've created a <code>Locale</code> you can query it for information about
0120 * itself. Use <code>getCountry</code> to get the ISO Country Code and
0121 * <code>getLanguage</code> to get the ISO Language Code. You can
0122 * use <code>getDisplayCountry</code> to get the
0123 * name of the country suitable for displaying to the user. Similarly,
0124 * you can use <code>getDisplayLanguage</code> to get the name of
0125 * the language suitable for displaying to the user. Interestingly,
0126 * the <code>getDisplayXXX</code> methods are themselves locale-sensitive
0127 * and have two versions: one that uses the default locale and one
0128 * that uses the locale specified as an argument.
0129 *
0130 * <P>
0131 * The Java Platform provides a number of classes that perform locale-sensitive
0132 * operations. For example, the <code>NumberFormat</code> class formats
0133 * numbers, currency, or percentages in a locale-sensitive manner. Classes
0134 * such as <code>NumberFormat</code> have a number of convenience methods
0135 * for creating a default object of that type. For example, the
0136 * <code>NumberFormat</code> class provides these three convenience methods
0137 * for creating a default <code>NumberFormat</code> object:
0138 * <blockquote>
0139 * <pre>
0140 * NumberFormat.getInstance()
0141 * NumberFormat.getCurrencyInstance()
0142 * NumberFormat.getPercentInstance()
0143 * </pre>
0144 * </blockquote>
0145 * These methods have two variants; one with an explicit locale
0146 * and one without; the latter using the default locale.
0147 * <blockquote>
0148 * <pre>
0149 * NumberFormat.getInstance(myLocale)
0150 * NumberFormat.getCurrencyInstance(myLocale)
0151 * NumberFormat.getPercentInstance(myLocale)
0152 * </pre>
0153 * </blockquote>
0154 * A <code>Locale</code> is the mechanism for identifying the kind of object
0155 * (<code>NumberFormat</code>) that you would like to get. The locale is
0156 * <STRONG>just</STRONG> a mechanism for identifying objects,
0157 * <STRONG>not</STRONG> a container for the objects themselves.
0158 *
0159 * @see ResourceBundle
0160 * @see java.text.Format
0161 * @see java.text.NumberFormat
0162 * @see java.text.Collator
0163 * @author Mark Davis
0164 * @since 1.1
0165 */
0166
0167 public final class Locale implements Cloneable, Serializable {
0168
0169 // cache to store singleton Locales
0170 private final static ConcurrentHashMap<String, Locale> cache = new ConcurrentHashMap<String, Locale>(
0171 32);
0172
0173 /** Useful constant for language.
0174 */
0175 static public final Locale ENGLISH = createSingleton("en__", "en",
0176 "");
0177
0178 /** Useful constant for language.
0179 */
0180 static public final Locale FRENCH = createSingleton("fr__", "fr",
0181 "");
0182
0183 /** Useful constant for language.
0184 */
0185 static public final Locale GERMAN = createSingleton("de__", "de",
0186 "");
0187
0188 /** Useful constant for language.
0189 */
0190 static public final Locale ITALIAN = createSingleton("it__", "it",
0191 "");
0192
0193 /** Useful constant for language.
0194 */
0195 static public final Locale JAPANESE = createSingleton("ja__", "ja",
0196 "");
0197
0198 /** Useful constant for language.
0199 */
0200 static public final Locale KOREAN = createSingleton("ko__", "ko",
0201 "");
0202
0203 /** Useful constant for language.
0204 */
0205 static public final Locale CHINESE = createSingleton("zh__", "zh",
0206 "");
0207
0208 /** Useful constant for language.
0209 */
0210 static public final Locale SIMPLIFIED_CHINESE = createSingleton(
0211 "zh_CN_", "zh", "CN");
0212
0213 /** Useful constant for language.
0214 */
0215 static public final Locale TRADITIONAL_CHINESE = createSingleton(
0216 "zh_TW_", "zh", "TW");
0217
0218 /** Useful constant for country.
0219 */
0220 static public final Locale FRANCE = createSingleton("fr_FR_", "fr",
0221 "FR");
0222
0223 /** Useful constant for country.
0224 */
0225 static public final Locale GERMANY = createSingleton("de_DE_",
0226 "de", "DE");
0227
0228 /** Useful constant for country.
0229 */
0230 static public final Locale ITALY = createSingleton("it_IT_", "it",
0231 "IT");
0232
0233 /** Useful constant for country.
0234 */
0235 static public final Locale JAPAN = createSingleton("ja_JP_", "ja",
0236 "JP");
0237
0238 /** Useful constant for country.
0239 */
0240 static public final Locale KOREA = createSingleton("ko_KR_", "ko",
0241 "KR");
0242
0243 /** Useful constant for country.
0244 */
0245 static public final Locale CHINA = SIMPLIFIED_CHINESE;
0246
0247 /** Useful constant for country.
0248 */
0249 static public final Locale PRC = SIMPLIFIED_CHINESE;
0250
0251 /** Useful constant for country.
0252 */
0253 static public final Locale TAIWAN = TRADITIONAL_CHINESE;
0254
0255 /** Useful constant for country.
0256 */
0257 static public final Locale UK = createSingleton("en_GB_", "en",
0258 "GB");
0259
0260 /** Useful constant for country.
0261 */
0262 static public final Locale US = createSingleton("en_US_", "en",
0263 "US");
0264
0265 /** Useful constant for country.
0266 */
0267 static public final Locale CANADA = createSingleton("en_CA_", "en",
0268 "CA");
0269
0270 /** Useful constant for country.
0271 */
0272 static public final Locale CANADA_FRENCH = createSingleton(
0273 "fr_CA_", "fr", "CA");
0274
0275 /**
0276 * Useful constant for the root locale. The root locale is the locale whose
0277 * language, country, and variant are empty ("") strings. This is regarded
0278 * as the base locale of all locales, and is used as the language/country
0279 * neutral locale for the locale sensitive operations.
0280 *
0281 * @since 1.6
0282 */
0283 static public final Locale ROOT = createSingleton("__", "", "");
0284
0285 /** serialization ID
0286 */
0287 static final long serialVersionUID = 9149081749638150636L;
0288
0289 /**
0290 * Display types for retrieving localized names from the name providers.
0291 */
0292 private static final int DISPLAY_LANGUAGE = 0;
0293 private static final int DISPLAY_COUNTRY = 1;
0294 private static final int DISPLAY_VARIANT = 2;
0295
0296 /**
0297 * Construct a locale from language, country, variant.
0298 * NOTE: ISO 639 is not a stable standard; some of the language codes it defines
0299 * (specifically iw, ji, and in) have changed. This constructor accepts both the
0300 * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other
0301 * API on Locale will return only the OLD codes.
0302 * @param language lowercase two-letter ISO-639 code.
0303 * @param country uppercase two-letter ISO-3166 code.
0304 * @param variant vendor and browser specific code. See class description.
0305 * @exception NullPointerException thrown if any argument is null.
0306 */
0307 public Locale(String language, String country, String variant) {
0308 this .language = convertOldISOCodes(language);
0309 this .country = toUpperCase(country).intern();
0310 this .variant = variant.intern();
0311 }
0312
0313 /**
0314 * Construct a locale from language, country.
0315 * NOTE: ISO 639 is not a stable standard; some of the language codes it defines
0316 * (specifically iw, ji, and in) have changed. This constructor accepts both the
0317 * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other
0318 * API on Locale will return only the OLD codes.
0319 * @param language lowercase two-letter ISO-639 code.
0320 * @param country uppercase two-letter ISO-3166 code.
0321 * @exception NullPointerException thrown if either argument is null.
0322 */
0323 public Locale(String language, String country) {
0324 this (language, country, "");
0325 }
0326
0327 /**
0328 * Construct a locale from a language code.
0329 * NOTE: ISO 639 is not a stable standard; some of the language codes it defines
0330 * (specifically iw, ji, and in) have changed. This constructor accepts both the
0331 * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other
0332 * API on Locale will return only the OLD codes.
0333 * @param language lowercase two-letter ISO-639 code.
0334 * @exception NullPointerException thrown if argument is null.
0335 * @since 1.4
0336 */
0337 public Locale(String language) {
0338 this (language, "", "");
0339 }
0340
0341 /**
0342 * Constructs a <code>Locale</code> using <code>language</code>
0343 * and <code>country</code>. This constructor assumes that
0344 * <code>language</code> and <code>contry</code> are interned and
0345 * it is invoked by createSingleton only. (flag is just for
0346 * avoiding the conflict with the public constructors.
0347 */
0348 private Locale(String language, String country, boolean flag) {
0349 this .language = language;
0350 this .country = country;
0351 this .variant = "";
0352 }
0353
0354 /**
0355 * Creates a <code>Locale</code> instance with the given
0356 * <code>language</code> and <code>counry</code> and puts the
0357 * instance under the given <code>key</code> in the cache. This
0358 * method must be called only when initializing the Locale
0359 * constants.
0360 */
0361 private static Locale createSingleton(String key, String language,
0362 String country) {
0363 Locale locale = new Locale(language, country, false);
0364 cache.put(key, locale);
0365 return locale;
0366 }
0367
0368 /**
0369 * Returns a <code>Locale</code> constructed from the given
0370 * <code>language</code>, <code>country</code> and
0371 * <code>variant</code>. If the same <code>Locale</code> instance
0372 * is available in the cache, then that instance is
0373 * returned. Otherwise, a new <code>Locale</code> instance is
0374 * created and cached.
0375 *
0376 * @param language lowercase two-letter ISO-639 code.
0377 * @param country uppercase two-letter ISO-3166 code.
0378 * @param variant vendor and browser specific code. See class description.
0379 * @return the <code>Locale</code> instance requested
0380 * @exception NullPointerException if any argument is null.
0381 */
0382 static Locale getInstance(String language, String country,
0383 String variant) {
0384 if (language == null || country == null || variant == null) {
0385 throw new NullPointerException();
0386 }
0387
0388 StringBuilder sb = new StringBuilder();
0389 sb.append(language).append('_').append(country).append('_')
0390 .append(variant);
0391 String key = sb.toString();
0392 Locale locale = cache.get(key);
0393 if (locale == null) {
0394 locale = new Locale(language, country, variant);
0395 Locale l = cache.putIfAbsent(key, locale);
0396 if (l != null) {
0397 locale = l;
0398 }
0399 }
0400 return locale;
0401 }
0402
0403 /**
0404 * Gets the current value of the default locale for this instance
0405 * of the Java Virtual Machine.
0406 * <p>
0407 * The Java Virtual Machine sets the default locale during startup
0408 * based on the host environment. It is used by many locale-sensitive
0409 * methods if no locale is explicitly specified.
0410 * It can be changed using the
0411 * {@link #setDefault(java.util.Locale) setDefault} method.
0412 *
0413 * @return the default locale for this instance of the Java Virtual Machine
0414 */
0415 public static Locale getDefault() {
0416 // do not synchronize this method - see 4071298
0417 // it's OK if more than one default locale happens to be created
0418 if (defaultLocale == null) {
0419 String language, region, country, variant;
0420 language = (String) AccessController
0421 .doPrivileged(new GetPropertyAction(
0422 "user.language", "en"));
0423 // for compatibility, check for old user.region property
0424 region = (String) AccessController
0425 .doPrivileged(new GetPropertyAction("user.region"));
0426 if (region != null) {
0427 // region can be of form country, country_variant, or _variant
0428 int i = region.indexOf('_');
0429 if (i >= 0) {
0430 country = region.substring(0, i);
0431 variant = region.substring(i + 1);
0432 } else {
0433 country = region;
0434 variant = "";
0435 }
0436 } else {
0437 country = (String) AccessController
0438 .doPrivileged(new GetPropertyAction(
0439 "user.country", ""));
0440 variant = (String) AccessController
0441 .doPrivileged(new GetPropertyAction(
0442 "user.variant", ""));
0443 }
0444 defaultLocale = getInstance(language, country, variant);
0445 }
0446 return defaultLocale;
0447 }
0448
0449 /**
0450 * Sets the default locale for this instance of the Java Virtual Machine.
0451 * This does not affect the host locale.
0452 * <p>
0453 * If there is a security manager, its <code>checkPermission</code>
0454 * method is called with a <code>PropertyPermission("user.language", "write")</code>
0455 * permission before the default locale is changed.
0456 * <p>
0457 * The Java Virtual Machine sets the default locale during startup
0458 * based on the host environment. It is used by many locale-sensitive
0459 * methods if no locale is explicitly specified.
0460 * <p>
0461 * Since changing the default locale may affect many different areas
0462 * of functionality, this method should only be used if the caller
0463 * is prepared to reinitialize locale-sensitive code running
0464 * within the same Java Virtual Machine.
0465 *
0466 * @throws SecurityException
0467 * if a security manager exists and its
0468 * <code>checkPermission</code> method doesn't allow the operation.
0469 * @throws NullPointerException if <code>newLocale</code> is null
0470 * @param newLocale the new default locale
0471 * @see SecurityManager#checkPermission
0472 * @see java.util.PropertyPermission
0473 */
0474 public static synchronized void setDefault(Locale newLocale) {
0475 if (newLocale == null)
0476 throw new NullPointerException(
0477 "Can't set default locale to NULL");
0478
0479 SecurityManager sm = System.getSecurityManager();
0480 if (sm != null)
0481 sm.checkPermission(new PropertyPermission("user.language",
0482 "write"));
0483 defaultLocale = newLocale;
0484 }
0485
0486 /**
0487 * Returns an array of all installed locales.
0488 * The returned array represents the union of locales supported
0489 * by the Java runtime environment and by installed
0490 * {@link java.util.spi.LocaleServiceProvider LocaleServiceProvider}
0491 * implementations. It must contain at least a <code>Locale</code>
0492 * instance equal to {@link java.util.Locale#US Locale.US}.
0493 *
0494 * @return An array of installed locales.
0495 */
0496 public static Locale[] getAvailableLocales() {
0497 return LocaleServiceProviderPool.getAllAvailableLocales();
0498 }
0499
0500 /**
0501 * Returns a list of all 2-letter country codes defined in ISO 3166.
0502 * Can be used to create Locales.
0503 */
0504 public static String[] getISOCountries() {
0505 if (isoCountries == null) {
0506 isoCountries = getISO2Table(LocaleISOData.isoCountryTable);
0507 }
0508 String[] result = new String[isoCountries.length];
0509 System.arraycopy(isoCountries, 0, result, 0,
0510 isoCountries.length);
0511 return result;
0512 }
0513
0514 /**
0515 * Returns a list of all 2-letter language codes defined in ISO 639.
0516 * Can be used to create Locales.
0517 * [NOTE: ISO 639 is not a stable standard-- some languages' codes have changed.
0518 * The list this function returns includes both the new and the old codes for the
0519 * languages whose codes have changed.]
0520 */
0521 public static String[] getISOLanguages() {
0522 if (isoLanguages == null) {
0523 isoLanguages = getISO2Table(LocaleISOData.isoLanguageTable);
0524 }
0525 String[] result = new String[isoLanguages.length];
0526 System.arraycopy(isoLanguages, 0, result, 0,
0527 isoLanguages.length);
0528 return result;
0529 }
0530
0531 private static final String[] getISO2Table(String table) {
0532 int len = table.length() / 5;
0533 String[] isoTable = new String[len];
0534 for (int i = 0, j = 0; i < len; i++, j += 5) {
0535 isoTable[i] = table.substring(j, j + 2);
0536 }
0537 return isoTable;
0538 }
0539
0540 /**
0541 * Returns the language code for this locale, which will either be the empty string
0542 * or a lowercase ISO 639 code.
0543 * <p>NOTE: ISO 639 is not a stable standard-- some languages' codes have changed.
0544 * Locale's constructor recognizes both the new and the old codes for the languages
0545 * whose codes have changed, but this function always returns the old code. If you
0546 * want to check for a specific language whose code has changed, don't do <pre>
0547 * if (locale.getLanguage().equals("he"))
0548 * ...
0549 * </pre>Instead, do<pre>
0550 * if (locale.getLanguage().equals(new Locale("he", "", "").getLanguage()))
0551 * ...</pre>
0552 * @see #getDisplayLanguage
0553 */
0554 public String getLanguage() {
0555 return language;
0556 }
0557
0558 /**
0559 * Returns the country/region code for this locale, which will
0560 * either be the empty string or an uppercase ISO 3166 2-letter code.
0561 * @see #getDisplayCountry
0562 */
0563 public String getCountry() {
0564 return country;
0565 }
0566
0567 /**
0568 * Returns the variant code for this locale.
0569 * @see #getDisplayVariant
0570 */
0571 public String getVariant() {
0572 return variant;
0573 }
0574
0575 /**
0576 * Getter for the programmatic name of the entire locale,
0577 * with the language, country and variant separated by underbars.
0578 * Language is always lower case, and country is always upper case.
0579 * If the language is missing, the string will begin with an underbar.
0580 * If both the language and country fields are missing, this function
0581 * will return the empty string, even if the variant field is filled in
0582 * (you can't have a locale with just a variant-- the variant must accompany
0583 * a valid language or country code).
0584 * Examples: "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "fr__MAC"
0585 * @see #getDisplayName
0586 */
0587 public final String toString() {
0588 boolean l = language.length() != 0;
0589 boolean c = country.length() != 0;
0590 boolean v = variant.length() != 0;
0591 StringBuilder result = new StringBuilder(language);
0592 if (c || (l && v)) {
0593 result.append('_').append(country); // This may just append '_'
0594 }
0595 if (v && (l || c)) {
0596 result.append('_').append(variant);
0597 }
0598 return result.toString();
0599 }
0600
0601 /**
0602 * Returns a three-letter abbreviation for this locale's language. If the locale
0603 * doesn't specify a language, this will be the empty string. Otherwise, this will
0604 * be a lowercase ISO 639-2/T language code.
0605 * The ISO 639-2 language codes can be found on-line at
0606 * <a href="http://www.loc.gov/standards/iso639-2/englangn.html">
0607 * <code>http://www.loc.gov/standards/iso639-2/englangn.html</code>.</a>
0608 * @exception MissingResourceException Throws MissingResourceException if the
0609 * three-letter language abbreviation is not available for this locale.
0610 */
0611 public String getISO3Language() throws MissingResourceException {
0612 String language3 = getISO3Code(language,
0613 LocaleISOData.isoLanguageTable);
0614 if (language3 == null) {
0615 throw new MissingResourceException(
0616 "Couldn't find 3-letter language code for "
0617 + language, "FormatData_" + toString(),
0618 "ShortLanguage");
0619 }
0620 return language3;
0621 }
0622
0623 /**
0624 * Returns a three-letter abbreviation for this locale's country. If the locale
0625 * doesn't specify a country, this will be the empty string. Otherwise, this will
0626 * be an uppercase ISO 3166 3-letter country code.
0627 * The ISO 3166-2 country codes can be found on-line at
0628 * <a href="http://www.davros.org/misc/iso3166.txt">
0629 * <code>http://www.davros.org/misc/iso3166.txt</code>.</a>
0630 * @exception MissingResourceException Throws MissingResourceException if the
0631 * three-letter country abbreviation is not available for this locale.
0632 */
0633 public String getISO3Country() throws MissingResourceException {
0634 String country3 = getISO3Code(country,
0635 LocaleISOData.isoCountryTable);
0636 if (country3 == null) {
0637 throw new MissingResourceException(
0638 "Couldn't find 3-letter country code for "
0639 + country, "FormatData_" + toString(),
0640 "ShortCountry");
0641 }
0642 return country3;
0643 }
0644
0645 private static final String getISO3Code(String iso2Code,
0646 String table) {
0647 int codeLength = iso2Code.length();
0648 if (codeLength == 0) {
0649 return "";
0650 }
0651
0652 int tableLength = table.length();
0653 int index = tableLength;
0654 if (codeLength == 2) {
0655 char c1 = iso2Code.charAt(0);
0656 char c2 = iso2Code.charAt(1);
0657 for (index = 0; index < tableLength; index += 5) {
0658 if (table.charAt(index) == c1
0659 && table.charAt(index + 1) == c2) {
0660 break;
0661 }
0662 }
0663 }
0664 return index < tableLength ? table.substring(index + 2,
0665 index + 5) : null;
0666 }
0667
0668 /**
0669 * Returns a name for the locale's language that is appropriate for display to the
0670 * user.
0671 * If possible, the name returned will be localized for the default locale.
0672 * For example, if the locale is fr_FR and the default locale
0673 * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
0674 * the default locale is fr_FR, getDisplayLanguage() will return "anglais".
0675 * If the name returned cannot be localized for the default locale,
0676 * (say, we don't have a Japanese name for Croatian),
0677 * this function falls back on the English name, and uses the ISO code as a last-resort
0678 * value. If the locale doesn't specify a language, this function returns the empty string.
0679 */
0680 public final String getDisplayLanguage() {
0681 return getDisplayLanguage(getDefault());
0682 }
0683
0684 /**
0685 * Returns a name for the locale's language that is appropriate for display to the
0686 * user.
0687 * If possible, the name returned will be localized according to inLocale.
0688 * For example, if the locale is fr_FR and inLocale
0689 * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
0690 * inLocale is fr_FR, getDisplayLanguage() will return "anglais".
0691 * If the name returned cannot be localized according to inLocale,
0692 * (say, we don't have a Japanese name for Croatian),
0693 * this function falls back on the English name, and finally
0694 * on the ISO code as a last-resort value. If the locale doesn't specify a language,
0695 * this function returns the empty string.
0696 *
0697 * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
0698 */
0699 public String getDisplayLanguage(Locale inLocale) {
0700 return getDisplayString(language, inLocale, DISPLAY_LANGUAGE);
0701 }
0702
0703 /**
0704 * Returns a name for the locale's country that is appropriate for display to the
0705 * user.
0706 * If possible, the name returned will be localized for the default locale.
0707 * For example, if the locale is fr_FR and the default locale
0708 * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
0709 * the default locale is fr_FR, getDisplayCountry() will return "Etats-Unis".
0710 * If the name returned cannot be localized for the default locale,
0711 * (say, we don't have a Japanese name for Croatia),
0712 * this function falls back on the English name, and uses the ISO code as a last-resort
0713 * value. If the locale doesn't specify a country, this function returns the empty string.
0714 */
0715 public final String getDisplayCountry() {
0716 return getDisplayCountry(getDefault());
0717 }
0718
0719 /**
0720 * Returns a name for the locale's country that is appropriate for display to the
0721 * user.
0722 * If possible, the name returned will be localized according to inLocale.
0723 * For example, if the locale is fr_FR and inLocale
0724 * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
0725 * inLocale is fr_FR, getDisplayCountry() will return "Etats-Unis".
0726 * If the name returned cannot be localized according to inLocale.
0727 * (say, we don't have a Japanese name for Croatia),
0728 * this function falls back on the English name, and finally
0729 * on the ISO code as a last-resort value. If the locale doesn't specify a country,
0730 * this function returns the empty string.
0731 *
0732 * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
0733 */
0734 public String getDisplayCountry(Locale inLocale) {
0735 return getDisplayString(country, inLocale, DISPLAY_COUNTRY);
0736 }
0737
0738 private String getDisplayString(String code, Locale inLocale,
0739 int type) {
0740 if (code.length() == 0) {
0741 return "";
0742 }
0743
0744 if (inLocale == null) {
0745 throw new NullPointerException();
0746 }
0747
0748 try {
0749 OpenListResourceBundle bundle = LocaleData
0750 .getLocaleNames(inLocale);
0751 String key = (type == DISPLAY_VARIANT ? "%%" + code : code);
0752 String result = null;
0753
0754 // Check whether a provider can provide an implementation that's closer
0755 // to the requested locale than what the Java runtime itself can provide.
0756 LocaleServiceProviderPool pool = LocaleServiceProviderPool
0757 .getPool(LocaleNameProvider.class);
0758 if (pool.hasProviders()) {
0759 result = pool.getLocalizedObject(
0760 LocaleNameGetter.INSTANCE, inLocale, bundle,
0761 key, type, code);
0762 }
0763
0764 if (result == null) {
0765 result = bundle.getString(key);
0766 }
0767
0768 if (result != null) {
0769 return result;
0770 }
0771 } catch (Exception e) {
0772 // just fall through
0773 }
0774 return code;
0775 }
0776
0777 /**
0778 * Returns a name for the locale's variant code that is appropriate for display to the
0779 * user. If possible, the name will be localized for the default locale. If the locale
0780 * doesn't specify a variant code, this function returns the empty string.
0781 */
0782 public final String getDisplayVariant() {
0783 return getDisplayVariant(getDefault());
0784 }
0785
0786 /**
0787 * Returns a name for the locale's variant code that is appropriate for display to the
0788 * user. If possible, the name will be localized for inLocale. If the locale
0789 * doesn't specify a variant code, this function returns the empty string.
0790 *
0791 * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
0792 */
0793 public String getDisplayVariant(Locale inLocale) {
0794 if (variant.length() == 0)
0795 return "";
0796
0797 OpenListResourceBundle bundle = LocaleData
0798 .getLocaleNames(inLocale);
0799
0800 String names[] = getDisplayVariantArray(bundle, inLocale);
0801
0802 // Get the localized patterns for formatting a list, and use
0803 // them to format the list.
0804 String listPattern = null;
0805 String listCompositionPattern = null;
0806 try {
0807 listPattern = bundle.getString("ListPattern");
0808 listCompositionPattern = bundle
0809 .getString("ListCompositionPattern");
0810 } catch (MissingResourceException e) {
0811 }
0812 return formatList(names, listPattern, listCompositionPattern);
0813 }
0814
0815 /**
0816 * Returns a name for the locale that is appropriate for display to the
0817 * user. This will be the values returned by getDisplayLanguage(), getDisplayCountry(),
0818 * and getDisplayVariant() assembled into a single string. The display name will have
0819 * one of the following forms:<p><blockquote>
0820 * language (country, variant)<p>
0821 * language (country)<p>
0822 * language (variant)<p>
0823 * country (variant)<p>
0824 * language<p>
0825 * country<p>
0826 * variant<p></blockquote>
0827 * depending on which fields are specified in the locale. If the language, country,
0828 * and variant fields are all empty, this function returns the empty string.
0829 */
0830 public final String getDisplayName() {
0831 return getDisplayName(getDefault());
0832 }
0833
0834 /**
0835 * Returns a name for the locale that is appropriate for display to the
0836 * user. This will be the values returned by getDisplayLanguage(), getDisplayCountry(),
0837 * and getDisplayVariant() assembled into a single string. The display name will have
0838 * one of the following forms:<p><blockquote>
0839 * language (country, variant)<p>
0840 * language (country)<p>
0841 * language (variant)<p>
0842 * country (variant)<p>
0843 * language<p>
0844 * country<p>
0845 * variant<p></blockquote>
0846 * depending on which fields are specified in the locale. If the language, country,
0847 * and variant fields are all empty, this function returns the empty string.
0848 *
0849 * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
0850 */
0851 public String getDisplayName(Locale inLocale) {
0852 OpenListResourceBundle bundle = LocaleData
0853 .getLocaleNames(inLocale);
0854
0855 String languageName = getDisplayLanguage(inLocale);
0856 String countryName = getDisplayCountry(inLocale);
0857 String[] variantNames = getDisplayVariantArray(bundle, inLocale);
0858
0859 // Get the localized patterns for formatting a display name.
0860 String displayNamePattern = null;
0861 String listPattern = null;
0862 String listCompositionPattern = null;
0863 try {
0864 displayNamePattern = bundle.getString("DisplayNamePattern");
0865 listPattern = bundle.getString("ListPattern");
0866 listCompositionPattern = bundle
0867 .getString("ListCompositionPattern");
0868 } catch (MissingResourceException e) {
0869 }
0870
0871 // The display name consists of a main name, followed by qualifiers.
0872 // Typically, the format is "MainName (Qualifier, Qualifier)" but this
0873 // depends on what pattern is stored in the display locale.
0874 String mainName = null;
0875 String[] qualifierNames = null;
0876
0877 // The main name is the language, or if there is no language, the country.
0878 // If there is neither language nor country (an anomalous situation) then
0879 // the display name is simply the variant's display name.
0880 if (languageName.length() != 0) {
0881 mainName = languageName;
0882 if (countryName.length() != 0) {
0883 qualifierNames = new String[variantNames.length + 1];
0884 System.arraycopy(variantNames, 0, qualifierNames, 1,
0885 variantNames.length);
0886 qualifierNames[0] = countryName;
0887 } else
0888 qualifierNames = variantNames;
0889 } else if (countryName.length() != 0) {
0890 mainName = countryName;
0891 qualifierNames = variantNames;
0892 } else {
0893 return formatList(variantNames, listPattern,
0894 listCompositionPattern);
0895 }
0896
0897 // Create an array whose first element is the number of remaining
0898 // elements. This serves as a selector into a ChoiceFormat pattern from
0899 // the resource. The second and third elements are the main name and
0900 // the qualifier; if there are no qualifiers, the third element is
0901 // unused by the format pattern.
0902 Object[] displayNames = {
0903 new Integer(qualifierNames.length != 0 ? 2 : 1),
0904 mainName,
0905 // We could also just call formatList() and have it handle the empty
0906 // list case, but this is more efficient, and we want it to be
0907 // efficient since all the language-only locales will not have any
0908 // qualifiers.
0909 qualifierNames.length != 0 ? formatList(qualifierNames,
0910 listPattern, listCompositionPattern) : null };
0911
0912 if (displayNamePattern != null) {
0913 return new MessageFormat(displayNamePattern)
0914 .format(displayNames);
0915 } else {
0916 // If we cannot get the message format pattern, then we use a simple
0917 // hard-coded pattern. This should not occur in practice unless the
0918 // installation is missing some core files (FormatData etc.).
0919 StringBuilder result = new StringBuilder();
0920 result.append((String) displayNames[1]);
0921 if (displayNames.length > 2) {
0922 result.append(" (");
0923 result.append((String) displayNames[2]);
0924 result.append(')');
0925 }
0926 return result.toString();
0927 }
0928 }
0929
0930 /**
0931 * Overrides Cloneable
0932 */
0933 public Object clone() {
0934 try {
0935 Locale that = (Locale) super .clone();
0936 return that;
0937 } catch (CloneNotSupportedException e) {
0938 throw new InternalError();
0939 }
0940 }
0941
0942 /**
0943 * Override hashCode.
0944 * Since Locales are often used in hashtables, caches the value
0945 * for speed.
0946 */
0947 public int hashCode() {
0948 int hc = hashCodeValue;
0949 if (hc == 0) {
0950 hc = (language.hashCode() << 8) ^ country.hashCode()
0951 ^ (variant.hashCode() << 4);
0952 hashCodeValue = hc;
0953 }
0954 return hc;
0955 }
0956
0957 // Overrides
0958
0959 /**
0960 * Returns true if this Locale is equal to another object. A Locale is
0961 * deemed equal to another Locale with identical language, country,
0962 * and variant, and unequal to all other objects.
0963 *
0964 * @return true if this Locale is equal to the specified object.
0965 */
0966
0967 public boolean equals(Object obj) {
0968 if (this == obj) // quick check
0969 return true;
0970 if (!(obj instanceof Locale))
0971 return false;
0972 Locale other = (Locale) obj;
0973 return language == other.language && country == other.country
0974 && variant == other.variant;
0975 }
0976
0977 // ================= privates =====================================
0978
0979 // XXX instance and class variables. For now keep these separate, since it is
0980 // faster to match. Later, make into single string.
0981
0982 /**
0983 * @serial
0984 * @see #getLanguage
0985 */
0986 private final String language;
0987
0988 /**
0989 * @serial
0990 * @see #getCountry
0991 */
0992 private final String country;
0993
0994 /**
0995 * @serial
0996 * @see #getVariant
0997 */
0998 private final String variant;
0999
1000 /**
1001 * Placeholder for the object's hash code. Always -1.
1002 * @serial
1003 */
1004 private volatile int hashcode = -1; // lazy evaluate
1005
1006 /**
1007 * Calculated hashcode to fix 4518797.
1008 */
1009 private transient volatile int hashCodeValue = 0;
1010
1011 private static Locale defaultLocale = null;
1012
1013 /**
1014 * Return an array of the display names of the variant.
1015 * @param bundle the ResourceBundle to use to get the display names
1016 * @return an array of display names, possible of zero length.
1017 */
1018 private String[] getDisplayVariantArray(
1019 OpenListResourceBundle bundle, Locale inLocale) {
1020 // Split the variant name into tokens separated by '_'.
1021 StringTokenizer tokenizer = new StringTokenizer(variant, "_");
1022 String[] names = new String[tokenizer.countTokens()];
1023
1024 // For each variant token, lookup the display name. If
1025 // not found, use the variant name itself.
1026 for (int i = 0; i < names.length; ++i) {
1027 names[i] = getDisplayString(tokenizer.nextToken(),
1028 inLocale, DISPLAY_VARIANT);
1029 }
1030
1031 return names;
1032 }
1033
1034 /**
1035 * Format a list using given pattern strings.
1036 * If either of the patterns is null, then a the list is
1037 * formatted by concatenation with the delimiter ','.
1038 * @param stringList the list of strings to be formatted.
1039 * @param listPattern should create a MessageFormat taking 0-3 arguments
1040 * and formatting them into a list.
1041 * @param listCompositionPattern should take 2 arguments
1042 * and is used by composeList.
1043 * @return a string representing the list.
1044 */
1045 private static String formatList(String[] stringList,
1046 String listPattern, String listCompositionPattern) {
1047 // If we have no list patterns, compose the list in a simple,
1048 // non-localized way.
1049 if (listPattern == null || listCompositionPattern == null) {
1050 StringBuffer result = new StringBuffer();
1051 for (int i = 0; i < stringList.length; ++i) {
1052 if (i > 0)
1053 result.append(',');
1054 result.append(stringList[i]);
1055 }
1056 return result.toString();
1057 }
1058
1059 // Compose the list down to three elements if necessary
1060 if (stringList.length > 3) {
1061 MessageFormat format = new MessageFormat(
1062 listCompositionPattern);
1063 stringList = composeList(format, stringList);
1064 }
1065
1066 // Rebuild the argument list with the list length as the first element
1067 Object[] args = new Object[stringList.length + 1];
1068 System.arraycopy(stringList, 0, args, 1, stringList.length);
1069 args[0] = new Integer(stringList.length);
1070
1071 // Format it using the pattern in the resource
1072 MessageFormat format = new MessageFormat(listPattern);
1073 return format.format(args);
1074 }
1075
1076 /**
1077 * Given a list of strings, return a list shortened to three elements.
1078 * Shorten it by applying the given format to the first two elements
1079 * recursively.
1080 * @param format a format which takes two arguments
1081 * @param list a list of strings
1082 * @return if the list is three elements or shorter, the same list;
1083 * otherwise, a new list of three elements.
1084 */
1085 private static String[] composeList(MessageFormat format,
1086 String[] list) {
1087 if (list.length <= 3)
1088 return list;
1089
1090 // Use the given format to compose the first two elements into one
1091 String[] listItems = { list[0], list[1] };
1092 String newItem = format.format(listItems);
1093
1094 // Form a new list one element shorter
1095 String[] newList = new String[list.length - 1];
1096 System.arraycopy(list, 2, newList, 1, newList.length - 1);
1097 newList[0] = newItem;
1098
1099 // Recurse
1100 return composeList(format, newList);
1101 }
1102
1103 /**
1104 * Replace the deserialized Locale object with a newly
1105 * created object. Newer language codes are replaced with older ISO
1106 * codes. The country and variant codes are replaced with internalized
1107 * String copies.
1108 */
1109 private Object readResolve() throws java.io.ObjectStreamException {
1110 return getInstance(language, country, variant);
1111 }
1112
1113 private static volatile String[] isoLanguages = null;
1114
1115 private static volatile String[] isoCountries = null;
1116
1117 /*
1118 * Locale needs its own, locale insensitive version of toLowerCase to
1119 * avoid circularity problems between Locale and String.
1120 * The most straightforward algorithm is used. Look at optimizations later.
1121 */
1122 private String toLowerCase(String str) {
1123 char[] buf = new char[str.length()];
1124 for (int i = 0; i < buf.length; i++) {
1125 buf[i] = Character.toLowerCase(str.charAt(i));
1126 }
1127 return new String(buf);
1128 }
1129
1130 /*
1131 * Locale needs its own, locale insensitive version of toUpperCase to
1132 * avoid circularity problems between Locale and String.
1133 * The most straightforward algorithm is used. Look at optimizations later.
1134 */
1135 private String toUpperCase(String str) {
1136 char[] buf = new char[str.length()];
1137 for (int i = 0; i < buf.length; i++) {
1138 buf[i] = Character.toUpperCase(str.charAt(i));
1139 }
1140 return new String(buf);
1141 }
1142
1143 private String convertOldISOCodes(String language) {
1144 // we accept both the old and the new ISO codes for the languages whose ISO
1145 // codes have changed, but we always store the OLD code, for backward compatibility
1146 language = toLowerCase(language).intern();
1147 if (language == "he") {
1148 return "iw";
1149 } else if (language == "yi") {
1150 return "ji";
1151 } else if (language == "id") {
1152 return "in";
1153 } else {
1154 return language;
1155 }
1156 }
1157
1158 /**
1159 * Obtains a localized locale names from a LocaleNameProvider
1160 * implementation.
1161 */
1162 private static class LocaleNameGetter
1163 implements
1164 LocaleServiceProviderPool.LocalizedObjectGetter<LocaleNameProvider, String> {
1165 private static final LocaleNameGetter INSTANCE = new LocaleNameGetter();
1166
1167 public String getObject(LocaleNameProvider localeNameProvider,
1168 Locale locale, String key, Object... params) {
1169 assert params.length == 2;
1170 int type = (Integer) params[0];
1171 String code = (String) params[1];
1172
1173 switch (type) {
1174 case DISPLAY_LANGUAGE:
1175 return localeNameProvider.getDisplayLanguage(code,
1176 locale);
1177 case DISPLAY_COUNTRY:
1178 return localeNameProvider.getDisplayCountry(code,
1179 locale);
1180 case DISPLAY_VARIANT:
1181 return localeNameProvider.getDisplayVariant(code,
1182 locale);
1183 default:
1184 assert false; // shouldn't happen
1185 }
1186
1187 return null;
1188 }
1189 }
1190 }
|