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