KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > Locale


1 /*
2  * @(#)Locale.java 1.79 04/05/10
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN 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 JavaDoc;
27 import java.text.MessageFormat JavaDoc;
28 import sun.security.action.GetPropertyAction;
29 import sun.text.resources.LocaleData;
30
31 /**
32  *
33  * A <code>Locale</code> object represents a specific geographical, political,
34  * or cultural region. An operation that requires a <code>Locale</code> to perform
35  * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code>
36  * to tailor information for the user. For example, displaying a number
37  * is a locale-sensitive operation--the number should be formatted
38  * according to the customs/conventions of the user's native country,
39  * region, or culture.
40  *
41  * <P>
42  * Create a <code>Locale</code> object using the constructors in this class:
43  * <blockquote>
44  * <pre>
45  * Locale(String language)
46  * Locale(String language, String country)
47  * Locale(String language, String country, String variant)
48  * </pre>
49  * </blockquote>
50  * The language argument is a valid <STRONG>ISO Language Code.</STRONG>
51  * These codes are the lower-case, two-letter codes as defined by ISO-639.
52  * You can find a full list of these codes at a number of sites, such as:
53  * <BR><a href ="http://www.loc.gov/standards/iso639-2/englangn.html">
54  * <code>http://www.loc.gov/standards/iso639-2/englangn.html</code></a>
55  *
56  * <P>
57  * The country argument is a valid <STRONG>ISO Country Code.</STRONG> These
58  * codes are the upper-case, two-letter codes as defined by ISO-3166.
59  * You can find a full list of these codes at a number of sites, such as:
60  * <BR><a HREF="http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html">
61  * <code>http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html</code></a>
62  *
63  * <P>
64  * The variant argument is a vendor or browser-specific code.
65  * For example, use WIN for Windows, MAC for Macintosh, and POSIX for POSIX.
66  * Where there are two variants, separate them with an underscore, and
67  * put the most important one first. For example, a Traditional Spanish collation
68  * might construct a locale with parameters for language, country and variant as:
69  * "es", "ES", "Traditional_WIN".
70  *
71  * <P>
72  * Because a <code>Locale</code> object is just an identifier for a region,
73  * no validity check is performed when you construct a <code>Locale</code>.
74  * If you want to see whether particular resources are available for the
75  * <code>Locale</code> you construct, you must query those resources. For
76  * example, ask the <code>NumberFormat</code> for the locales it supports
77  * using its <code>getAvailableLocales</code> method.
78  * <BR><STRONG>Note:</STRONG> When you ask for a resource for a particular
79  * locale, you get back the best available match, not necessarily
80  * precisely what you asked for. For more information, look at
81  * {@link ResourceBundle}.
82  *
83  * <P>
84  * The <code>Locale</code> class provides a number of convenient constants
85  * that you can use to create <code>Locale</code> objects for commonly used
86  * locales. For example, the following creates a <code>Locale</code> object
87  * for the United States:
88  * <blockquote>
89  * <pre>
90  * Locale.US
91  * </pre>
92  * </blockquote>
93  *
94  * <P>
95  * Once you've created a <code>Locale</code> you can query it for information about
96  * itself. Use <code>getCountry</code> to get the ISO Country Code and
97  * <code>getLanguage</code> to get the ISO Language Code. You can
98  * use <code>getDisplayCountry</code> to get the
99  * name of the country suitable for displaying to the user. Similarly,
100  * you can use <code>getDisplayLanguage</code> to get the name of
101  * the language suitable for displaying to the user. Interestingly,
102  * the <code>getDisplayXXX</code> methods are themselves locale-sensitive
103  * and have two versions: one that uses the default locale and one
104  * that uses the locale specified as an argument.
105  *
106  * <P>
107  * The Java 2 platform provides a number of classes that perform locale-sensitive
108  * operations. For example, the <code>NumberFormat</code> class formats
109  * numbers, currency, or percentages in a locale-sensitive manner. Classes
110  * such as <code>NumberFormat</code> have a number of convenience methods
111  * for creating a default object of that type. For example, the
112  * <code>NumberFormat</code> class provides these three convenience methods
113  * for creating a default <code>NumberFormat</code> object:
114  * <blockquote>
115  * <pre>
116  * NumberFormat.getInstance()
117  * NumberFormat.getCurrencyInstance()
118  * NumberFormat.getPercentInstance()
119  * </pre>
120  * </blockquote>
121  * These methods have two variants; one with an explicit locale
122  * and one without; the latter using the default locale.
123  * <blockquote>
124  * <pre>
125  * NumberFormat.getInstance(myLocale)
126  * NumberFormat.getCurrencyInstance(myLocale)
127  * NumberFormat.getPercentInstance(myLocale)
128  * </pre>
129  * </blockquote>
130  * A <code>Locale</code> is the mechanism for identifying the kind of object
131  * (<code>NumberFormat</code>) that you would like to get. The locale is
132  * <STRONG>just</STRONG> a mechanism for identifying objects,
133  * <STRONG>not</STRONG> a container for the objects themselves.
134  *
135  * @see ResourceBundle
136  * @see java.text.Format
137  * @see java.text.NumberFormat
138  * @see java.text.Collator
139  * @author Mark Davis
140  * @since 1.1
141  */

142
143 public final class Locale implements Cloneable JavaDoc, Serializable {
144
145     /** Useful constant for language.
146      */

147     static public final Locale JavaDoc ENGLISH = new Locale JavaDoc("en","","");
148
149     /** Useful constant for language.
150      */

151     static public final Locale JavaDoc FRENCH = new Locale JavaDoc("fr","","");
152
153     /** Useful constant for language.
154      */

155     static public final Locale JavaDoc GERMAN = new Locale JavaDoc("de","","");
156
157     /** Useful constant for language.
158      */

159     static public final Locale JavaDoc ITALIAN = new Locale JavaDoc("it","","");
160
161     /** Useful constant for language.
162      */

163     static public final Locale JavaDoc JAPANESE = new Locale JavaDoc("ja","","");
164
165     /** Useful constant for language.
166      */

167     static public final Locale JavaDoc KOREAN = new Locale JavaDoc("ko","","");
168
169     /** Useful constant for language.
170      */

171     static public final Locale JavaDoc CHINESE = new Locale JavaDoc("zh","","");
172
173     /** Useful constant for language.
174      */

175     static public final Locale JavaDoc SIMPLIFIED_CHINESE = new Locale JavaDoc("zh","CN","");
176
177     /** Useful constant for language.
178      */

179     static public final Locale JavaDoc TRADITIONAL_CHINESE = new Locale JavaDoc("zh","TW","");
180
181     /** Useful constant for country.
182      */

183     static public final Locale JavaDoc FRANCE = new Locale JavaDoc("fr","FR","");
184
185     /** Useful constant for country.
186      */

187     static public final Locale JavaDoc GERMANY = new Locale JavaDoc("de","DE","");
188
189     /** Useful constant for country.
190      */

191     static public final Locale JavaDoc ITALY = new Locale JavaDoc("it","IT","");
192
193     /** Useful constant for country.
194      */

195     static public final Locale JavaDoc JAPAN = new Locale JavaDoc("ja","JP","");
196
197     /** Useful constant for country.
198      */

199     static public final Locale JavaDoc KOREA = new Locale JavaDoc("ko","KR","");
200
201     /** Useful constant for country.
202      */

203     static public final Locale JavaDoc CHINA = new Locale JavaDoc("zh","CN","");
204
205     /** Useful constant for country.
206      */

207     static public final Locale JavaDoc PRC = new Locale JavaDoc("zh","CN","");
208
209     /** Useful constant for country.
210      */

211     static public final Locale JavaDoc TAIWAN = new Locale JavaDoc("zh","TW","");
212
213     /** Useful constant for country.
214      */

215     static public final Locale JavaDoc UK = new Locale JavaDoc("en","GB","");
216
217     /** Useful constant for country.
218      */

219     static public final Locale JavaDoc US = new Locale JavaDoc("en","US","");
220
221     /** Useful constant for country.
222      */

223     static public final Locale JavaDoc CANADA = new Locale JavaDoc("en","CA","");
224
225     /** Useful constant for country.
226      */

227     static public final Locale JavaDoc CANADA_FRENCH = new Locale JavaDoc("fr","CA","");
228
229     /** serialization ID
230      */

231     static final long serialVersionUID = 9149081749638150636L;
232
233     /**
234      * Construct a locale from language, country, variant.
235      * NOTE: ISO 639 is not a stable standard; some of the language codes it defines
236      * (specifically iw, ji, and in) have changed. This constructor accepts both the
237      * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other
238      * API on Locale will return only the OLD codes.
239      * @param language lowercase two-letter ISO-639 code.
240      * @param country uppercase two-letter ISO-3166 code.
241      * @param variant vendor and browser specific code. See class description.
242      * @exception NullPointerException thrown if any argument is null.
243      */

244     public Locale(String JavaDoc language, String JavaDoc country, String JavaDoc variant) {
245         this.language = convertOldISOCodes(language);
246         this.country = toUpperCase(country).intern();
247         this.variant = variant.intern();
248     }
249
250     /**
251      * Construct a locale from language, country.
252      * NOTE: ISO 639 is not a stable standard; some of the language codes it defines
253      * (specifically iw, ji, and in) have changed. This constructor accepts both the
254      * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other
255      * API on Locale will return only the OLD codes.
256      * @param language lowercase two-letter ISO-639 code.
257      * @param country uppercase two-letter ISO-3166 code.
258      * @exception NullPointerException thrown if either argument is null.
259      */

260     public Locale(String JavaDoc language, String JavaDoc country) {
261         this(language, country, "");
262     }
263
264     /**
265      * Construct a locale from a language code.
266      * NOTE: ISO 639 is not a stable standard; some of the language codes it defines
267      * (specifically iw, ji, and in) have changed. This constructor accepts both the
268      * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other
269      * API on Locale will return only the OLD codes.
270      * @param language lowercase two-letter ISO-639 code.
271      * @exception NullPointerException thrown if argument is null.
272      * @since 1.4
273      */

274     public Locale(String JavaDoc language) {
275         this(language, "", "");
276     }
277
278
279     /**
280      * Gets the current value of the default locale for this instance
281      * of the Java Virtual Machine.
282      * <p>
283      * The Java Virtual Machine sets the default locale during startup
284      * based on the host environment. It is used by many locale-sensitive
285      * methods if no locale is explicitly specified.
286      * It can be changed using the
287      * {@link #setDefault(java.util.Locale) setDefault} method.
288      *
289      * @return the default locale for this instance of the Java Virtual Machine
290      */

291     public static Locale JavaDoc getDefault() {
292         // do not synchronize this method - see 4071298
293
// it's OK if more than one default locale happens to be created
294
if (defaultLocale == null) {
295             String JavaDoc language, region, country, variant;
296             language = (String JavaDoc) AccessController.doPrivileged(
297                             new GetPropertyAction("user.language", "en"));
298             // for compatibility, check for old user.region property
299
region = (String JavaDoc) AccessController.doPrivileged(
300                             new GetPropertyAction("user.region"));
301             if (region != null) {
302                 // region can be of form country, country_variant, or _variant
303
int i = region.indexOf('_');
304                 if (i >= 0) {
305                     country = region.substring(0, i);
306                     variant = region.substring(i + 1);
307                 } else {
308                     country = region;
309                     variant = "";
310                 }
311             } else {
312                 country = (String JavaDoc) AccessController.doPrivileged(
313                                 new GetPropertyAction("user.country", ""));
314                 variant = (String JavaDoc) AccessController.doPrivileged(
315                                 new GetPropertyAction("user.variant", ""));
316             }
317             defaultLocale = new Locale JavaDoc(language, country, variant);
318         }
319         return defaultLocale;
320     }
321
322     /**
323      * Sets the default locale for this instance of the Java Virtual Machine.
324      * This does not affect the host locale.
325      * <p>
326      * If there is a security manager, its <code>checkPermission</code>
327      * method is called with a <code>PropertyPermission("user.language", "write")</code>
328      * permission before the default locale is changed.
329      * <p>
330      * The Java Virtual Machine sets the default locale during startup
331      * based on the host environment. It is used by many locale-sensitive
332      * methods if no locale is explicitly specified.
333      * <p>
334      * Since changing the default locale may affect many different areas
335      * of functionality, this method should only be used if the caller
336      * is prepared to reinitialize locale-sensitive code running
337      * within the same Java Virtual Machine, such as the user interface.
338      *
339      * @throws SecurityException
340      * if a security manager exists and its
341      * <code>checkPermission</code> method doesn't allow the operation.
342      * @throws NullPointerException if <code>newLocale</code> is null
343      * @param newLocale the new default locale
344      * @see SecurityManager#checkPermission
345      * @see java.util.PropertyPermission
346      */

347     public static synchronized void setDefault(Locale JavaDoc newLocale) {
348         if (newLocale == null)
349             throw new NullPointerException JavaDoc("Can't set default locale to NULL");
350
351         SecurityManager JavaDoc sm = System.getSecurityManager();
352         if (sm != null) sm.checkPermission(new PropertyPermission JavaDoc
353                         ("user.language", "write"));
354             defaultLocale = newLocale;
355     }
356
357     /**
358      * Returns an array of all installed locales.
359      * The array returned must contain at least a <code>Locale</code>
360      * instance equal to {@link java.util.Locale#US Locale.US}.
361      *
362      * @return An array of installed locales.
363      */

364     public static Locale JavaDoc[] getAvailableLocales() {
365         return LocaleData.getAvailableLocales("LocaleString");
366     }
367
368     /**
369      * Returns a list of all 2-letter country codes defined in ISO 3166.
370      * Can be used to create Locales.
371      */

372     public static String JavaDoc[] getISOCountries() {
373         if (isoCountries == null) {
374             isoCountries = new String JavaDoc[compressedIsoCountries.length() / 6];
375             for (int i = 0; i < isoCountries.length; i++)
376                 isoCountries[i] = compressedIsoCountries.substring((i * 6) + 1, (i * 6) + 3);
377         }
378         String JavaDoc[] result = new String JavaDoc[isoCountries.length];
379         System.arraycopy(isoCountries, 0, result, 0, isoCountries.length);
380         return result;
381     }
382
383     /**
384      * Returns a list of all 2-letter language codes defined in ISO 639.
385      * Can be used to create Locales.
386      * [NOTE: ISO 639 is not a stable standard-- some languages' codes have changed.
387      * The list this function returns includes both the new and the old codes for the
388      * languages whose codes have changed.]
389      */

390     public static String JavaDoc[] getISOLanguages() {
391         if (isoLanguages == null) {
392             isoLanguages = new String JavaDoc[compressedIsoLanguages.length() / 6];
393             for (int i = 0; i < isoLanguages.length; i++)
394                 isoLanguages[i] = compressedIsoLanguages.substring((i * 6) + 1, (i * 6) + 3);
395         }
396         String JavaDoc[] result = new String JavaDoc[isoLanguages.length];
397         System.arraycopy(isoLanguages, 0, result, 0, isoLanguages.length);
398         return result;
399     }
400
401     /**
402      * Returns the language code for this locale, which will either be the empty string
403      * or a lowercase ISO 639 code.
404      * <p>NOTE: ISO 639 is not a stable standard-- some languages' codes have changed.
405      * Locale's constructor recognizes both the new and the old codes for the languages
406      * whose codes have changed, but this function always returns the old code. If you
407      * want to check for a specific language whose code has changed, don't do <pre>
408      * if (locale.getLanguage().equals("he")
409      * ...
410      * </pre>Instead, do<pre>
411      * if (locale.getLanguage().equals(new Locale("he", "", "").getLanguage())
412      * ...</pre>
413      * @see #getDisplayLanguage
414      */

415     public String JavaDoc getLanguage() {
416         return language;
417     }
418
419     /**
420      * Returns the country/region code for this locale, which will
421      * either be the empty string or an uppercase ISO 3166 2-letter code.
422      * @see #getDisplayCountry
423      */

424     public String JavaDoc getCountry() {
425         return country;
426     }
427
428     /**
429      * Returns the variant code for this locale.
430      * @see #getDisplayVariant
431      */

432     public String JavaDoc getVariant() {
433         return variant;
434     }
435
436     /**
437      * Getter for the programmatic name of the entire locale,
438      * with the language, country and variant separated by underbars.
439      * Language is always lower case, and country is always upper case.
440      * If the language is missing, the string will begin with an underbar.
441      * If both the language and country fields are missing, this function
442      * will return the empty string, even if the variant field is filled in
443      * (you can't have a locale with just a variant-- the variant must accompany
444      * a valid language or country code).
445      * Examples: "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "fr__MAC"
446      * @see #getDisplayName
447      */

448     public final String JavaDoc toString() {
449         boolean l = language.length() != 0;
450         boolean c = country.length() != 0;
451         boolean v = variant.length() != 0;
452         StringBuffer JavaDoc result = new StringBuffer JavaDoc(language);
453         if (c||(l&&v)) {
454             result.append('_').append(country); // This may just append '_'
455
}
456         if (v&&(l||c)) {
457             result.append('_').append(variant);
458         }
459         return result.toString();
460     }
461
462     /**
463      * Returns a three-letter abbreviation for this locale's language. If the locale
464      * doesn't specify a language, this will be the empty string. Otherwise, this will
465      * be a lowercase ISO 639-2/T language code.
466      * The ISO 639-2 language codes can be found on-line at
467      * <a HREF="http://www.loc.gov/standards/iso639-2/englangn.html"><code>http://www.loc.gov/standards/iso639-2/englangn.html</code></a>
468      * @exception MissingResourceException Throws MissingResourceException if the
469      * three-letter language abbreviation is not available for this locale.
470      */

471     public String JavaDoc getISO3Language() throws MissingResourceException JavaDoc {
472         int length = language.length();
473
474         if (length == 0) {
475             return "";
476         }
477
478         int index = compressedIsoLanguages.indexOf("," + language);
479         if (index == -1 || length != 2) {
480             throw new MissingResourceException JavaDoc("Couldn't find 3-letter language code for "
481                     + language, "LocaleElements_" + toString(), "ShortLanguage");
482         }
483         return compressedIsoLanguages.substring(index + 3, index + 6);
484     }
485
486     /**
487      * Returns a three-letter abbreviation for this locale's country. If the locale
488      * doesn't specify a country, this will be the empty string. Otherwise, this will
489      * be an uppercase ISO 3166 3-letter country code.
490      * The ISO 3166-2 country codes can be found on-line at
491      * <a HREF="http://www.davros.org/misc/iso3166.txt"><code>http://www.davros.org/misc/iso3166.txt</code></a>
492      * @exception MissingResourceException Throws MissingResourceException if the
493      * three-letter country abbreviation is not available for this locale.
494      */

495     public String JavaDoc getISO3Country() throws MissingResourceException JavaDoc {
496         int length = country.length();
497
498         if (length == 0) {
499             return "";
500         }
501
502         int index = compressedIsoCountries.indexOf("," + country);
503         if (index == -1 || length != 2) {
504             throw new MissingResourceException JavaDoc("Couldn't find 3-letter country code for "
505                     + country, "LocaleElements_" + toString(), "ShortCountry");
506         }
507         return compressedIsoCountries.substring(index + 3, index + 6);
508     }
509
510     /**
511      * Returns a name for the locale's language that is appropriate for display to the
512      * user.
513      * If possible, the name returned will be localized for the default locale.
514      * For example, if the locale is fr_FR and the default locale
515      * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
516      * the default locale is fr_FR, getDisplayLanguage() will return "anglais".
517      * If the name returned cannot be localized for the default locale,
518      * (say, we don't have a Japanese name for Croatian),
519      * this function falls back on the English name, and uses the ISO code as a last-resort
520      * value. If the locale doesn't specify a language, this function returns the empty string.
521      */

522     public final String JavaDoc getDisplayLanguage() {
523         return getDisplayLanguage(getDefault());
524     }
525
526     /**
527      * Returns a name for the locale's language that is appropriate for display to the
528      * user.
529      * If possible, the name returned will be localized according to inLocale.
530      * For example, if the locale is fr_FR and inLocale
531      * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
532      * inLocale is fr_FR, getDisplayLanguage() will return "anglais".
533      * If the name returned cannot be localized according to inLocale,
534      * (say, we don't have a Japanese name for Croatian),
535      * this function falls back on the default locale, on the English name, and finally
536      * on the ISO code as a last-resort value. If the locale doesn't specify a language,
537      * this function returns the empty string.
538      */

539     public String JavaDoc getDisplayLanguage(Locale JavaDoc inLocale) {
540         String JavaDoc langCode = language;
541         if (langCode.length() == 0)
542             return "";
543
544         Locale JavaDoc workingLocale = (Locale JavaDoc)inLocale.clone();
545         String JavaDoc result = null;
546         int phase = 0;
547         boolean done = false;
548
549         if (workingLocale.variant.length() == 0)
550             phase = 1;
551         if (workingLocale.country.length() == 0)
552             phase = 2;
553
554         while (!done) {
555             try {
556                 ResourceBundle JavaDoc bundle = LocaleData.getLocaleElements(workingLocale);
557                 result = findStringMatch((String JavaDoc[][])bundle.getObject("Languages"),
558                                     langCode, langCode);
559                 if (result.length() != 0)
560                     done = true;
561             }
562             catch (Exception JavaDoc e) {
563                 // just fall through
564
}
565
566             if (!done) {
567                 switch (phase) {
568                     case 0:
569                         workingLocale = new Locale JavaDoc(workingLocale.language,
570                                                    workingLocale.country,
571                                                    "");
572                         break;
573
574                     case 1:
575                         workingLocale = new Locale JavaDoc(workingLocale.language,
576                                                    "",
577                                                    workingLocale.variant);
578                         break;
579
580                     case 2:
581                         workingLocale = getDefault();
582                         break;
583
584                     case 3:
585                         workingLocale = new Locale JavaDoc("", "", "");
586                         break;
587
588                     default:
589                         return langCode;
590                 }
591                 phase++;
592             }
593         }
594         return result;
595     }
596
597     /**
598      * Returns a name for the locale's country that is appropriate for display to the
599      * user.
600      * If possible, the name returned will be localized for the default locale.
601      * For example, if the locale is fr_FR and the default locale
602      * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
603      * the default locale is fr_FR, getDisplayLanguage() will return "Etats-Unis".
604      * If the name returned cannot be localized for the default locale,
605      * (say, we don't have a Japanese name for Croatia),
606      * this function falls back on the English name, and uses the ISO code as a last-resort
607      * value. If the locale doesn't specify a country, this function returns the empty string.
608      */

609     public final String JavaDoc getDisplayCountry() {
610         return getDisplayCountry(getDefault());
611     }
612
613     /**
614      * Returns a name for the locale's country that is appropriate for display to the
615      * user.
616      * If possible, the name returned will be localized according to inLocale.
617      * For example, if the locale is fr_FR and inLocale
618      * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
619      * inLocale is fr_FR, getDisplayLanguage() will return "Etats-Unis".
620      * If the name returned cannot be localized according to inLocale.
621      * (say, we don't have a Japanese name for Croatia),
622      * this function falls back on the default locale, on the English name, and finally
623      * on the ISO code as a last-resort value. If the locale doesn't specify a country,
624      * this function returns the empty string.
625      */

626     public String JavaDoc getDisplayCountry(Locale JavaDoc inLocale) {
627         String JavaDoc ctryCode = country;
628         if (ctryCode.length() == 0)
629             return "";
630
631         Locale JavaDoc workingLocale = (Locale JavaDoc)inLocale.clone();
632         String JavaDoc result = null;
633         int phase = 0;
634         boolean done = false;
635
636         if (workingLocale.variant.length() == 0)
637             phase = 1;
638         if (workingLocale.country.length() == 0)
639             phase = 2;
640
641         while (!done) {
642             try {
643                 ResourceBundle JavaDoc bundle = LocaleData.getLocaleElements(workingLocale);
644                 result = findStringMatch((String JavaDoc[][])bundle.getObject("Countries"),
645                                     ctryCode, ctryCode);
646                 if (result.length() != 0)
647                     done = true;
648             }
649             catch (Exception JavaDoc e) {
650                 // just fall through
651
}
652
653             if (!done) {
654                 switch (phase) {
655                     case 0:
656                         workingLocale = new Locale JavaDoc(workingLocale.language,
657                                                    workingLocale.country,
658                                                    "");
659                         break;
660
661                     case 1:
662                         workingLocale = new Locale JavaDoc(workingLocale.language,
663                                                    "",
664                                                    workingLocale.variant);
665                         break;
666
667                     case 2:
668                         workingLocale = getDefault();
669                         break;
670
671                     case 3:
672                         workingLocale = new Locale JavaDoc("", "", "");
673                         break;
674
675                     default:
676                         return ctryCode;
677                 }
678                 phase++;
679             }
680         }
681         return result;
682     }
683
684     /**
685      * Returns a name for the locale's variant code that is appropriate for display to the
686      * user. If possible, the name will be localized for the default locale. If the locale
687      * doesn't specify a variant code, this function returns the empty string.
688      */

689     public final String JavaDoc getDisplayVariant() {
690         return getDisplayVariant(getDefault());
691     }
692
693     /**
694      * Returns a name for the locale's variant code that is appropriate for display to the
695      * user. If possible, the name will be localized for inLocale. If the locale
696      * doesn't specify a variant code, this function returns the empty string.
697      */

698     public String JavaDoc getDisplayVariant(Locale JavaDoc inLocale) {
699         if (variant.length() == 0)
700             return "";
701
702         ResourceBundle JavaDoc bundle = LocaleData.getLocaleElements(inLocale);
703
704         String JavaDoc names[] = getDisplayVariantArray(bundle);
705
706         // Get the localized patterns for formatting a list, and use
707
// them to format the list.
708
String JavaDoc[] patterns;
709         try {
710             patterns = (String JavaDoc[])bundle.getObject("LocaleNamePatterns");
711         }
712         catch (MissingResourceException JavaDoc e) {
713             patterns = null;
714         }
715         return formatList(patterns, names);
716     }
717
718     /**
719      * Returns a name for the locale that is appropriate for display to the
720      * user. This will be the values returned by getDisplayLanguage(), getDisplayCountry(),
721      * and getDisplayVariant() assembled into a single string. The display name will have
722      * one of the following forms:<p><blockquote>
723      * language (country, variant)<p>
724      * language (country)<p>
725      * language (variant)<p>
726      * country (variant)<p>
727      * language<p>
728      * country<p>
729      * variant<p></blockquote>
730      * depending on which fields are specified in the locale. If the language, country,
731      * and variant fields are all empty, this function returns the empty string.
732      */

733     public final String JavaDoc getDisplayName() {
734         return getDisplayName(getDefault());
735     }
736
737     /**
738      * Returns a name for the locale that is appropriate for display to the
739      * user. This will be the values returned by getDisplayLanguage(), getDisplayCountry(),
740      * and getDisplayVariant() assembled into a single string. The display name will have
741      * one of the following forms:<p><blockquote>
742      * language (country, variant)<p>
743      * language (country)<p>
744      * language (variant)<p>
745      * country (variant)<p>
746      * language<p>
747      * country<p>
748      * variant<p></blockquote>
749      * depending on which fields are specified in the locale. If the language, country,
750      * and variant fields are all empty, this function returns the empty string.
751      */

752     public String JavaDoc getDisplayName(Locale JavaDoc inLocale) {
753         ResourceBundle JavaDoc bundle = LocaleData.getLocaleElements(inLocale);
754
755         String JavaDoc languageName = getDisplayLanguage(inLocale);
756         String JavaDoc countryName = getDisplayCountry(inLocale);
757         String JavaDoc[] variantNames = getDisplayVariantArray(bundle);
758
759         // Get the localized patterns for formatting a display name.
760
String JavaDoc[] patterns;
761         try {
762             patterns = (String JavaDoc[])bundle.getObject("LocaleNamePatterns");
763         }
764         catch (MissingResourceException JavaDoc e) {
765             patterns = null;
766         }
767
768         // The display name consists of a main name, followed by qualifiers.
769
// Typically, the format is "MainName (Qualifier, Qualifier)" but this
770
// depends on what pattern is stored in the display locale.
771
String JavaDoc mainName = null;
772         String JavaDoc[] qualifierNames = null;
773
774         // The main name is the language, or if there is no language, the country.
775
// If there is neither language nor country (an anomalous situation) then
776
// the display name is simply the variant's display name.
777
if (languageName.length() != 0) {
778             mainName = languageName;
779             if (countryName.length() != 0) {
780                 qualifierNames = new String JavaDoc[variantNames.length + 1];
781                 System.arraycopy(variantNames, 0, qualifierNames, 1, variantNames.length);
782                 qualifierNames[0] = countryName;
783             }
784             else qualifierNames = variantNames;
785         }
786         else if (countryName.length() != 0) {
787             mainName = countryName;
788             qualifierNames = variantNames;
789         }
790         else {
791             return formatList(patterns, variantNames);
792         }
793
794         // Create an array whose first element is the number of remaining
795
// elements. This serves as a selector into a ChoiceFormat pattern from
796
// the resource. The second and third elements are the main name and
797
// the qualifier; if there are no qualifiers, the third element is
798
// unused by the format pattern.
799
Object JavaDoc[] displayNames = {
800             new Integer JavaDoc(qualifierNames.length != 0 ? 2 : 1),
801             mainName,
802             // We could also just call formatList() and have it handle the empty
803
// list case, but this is more efficient, and we want it to be
804
// efficient since all the language-only locales will not have any
805
// qualifiers.
806
qualifierNames.length != 0 ? formatList(patterns, qualifierNames) : null
807         };
808
809         if (patterns != null) {
810             return new MessageFormat JavaDoc(patterns[0]).format(displayNames);
811         }
812         else {
813             // If we cannot get the message format pattern, then we use a simple
814
// hard-coded pattern. This should not occur in practice unless the
815
// installation is missing some core files (LocaleElements etc.).
816
StringBuffer JavaDoc result = new StringBuffer JavaDoc();
817             result.append((String JavaDoc)displayNames[1]);
818             if (displayNames.length > 2) {
819                 result.append(" (");
820                 result.append((String JavaDoc)displayNames[2]);
821                 result.append(")");
822             }
823             return result.toString();
824         }
825     }
826
827     /**
828      * Overrides Cloneable
829      */

830     public Object JavaDoc clone()
831     {
832         try {
833             Locale JavaDoc that = (Locale JavaDoc)super.clone();
834             return that;
835         } catch (CloneNotSupportedException JavaDoc e) {
836             throw new InternalError JavaDoc();
837         }
838     }
839
840     /**
841      * Override hashCode.
842      * Since Locales are often used in hashtables, caches the value
843      * for speed.
844      */

845     public int hashCode() {
846         int hc = hashCodeValue;
847         if (hc == 0) {
848             hc = (language.hashCode() << 8) ^ country.hashCode() ^ (variant.hashCode() << 4);
849             hashCodeValue = hc;
850         }
851         return hc;
852     }
853
854     // Overrides
855

856     /**
857      * Returns true if this Locale is equal to another object. A Locale is
858      * deemed equal to another Locale with identical language, country,
859      * and variant, and unequal to all other objects.
860      *
861      * @return true if this Locale is equal to the specified object.
862      */

863
864     public boolean equals(Object JavaDoc obj) {
865         if (this == obj) // quick check
866
return true;
867         if (!(obj instanceof Locale JavaDoc))
868             return false;
869         Locale JavaDoc other = (Locale JavaDoc) obj;
870     return language == other.language
871             && country == other.country
872             && variant == other.variant;
873     }
874
875     // ================= privates =====================================
876

877     // XXX instance and class variables. For now keep these separate, since it is
878
// faster to match. Later, make into single string.
879

880     /**
881      * @serial
882      * @see #getLanguage
883      */

884     private final String JavaDoc language;
885
886     /**
887      * @serial
888      * @see #getCountry
889      */

890     private final String JavaDoc country;
891
892     /**
893      * @serial
894      * @see #getVariant
895      */

896     private final String JavaDoc variant;
897
898     /**
899      * Placeholder for the object's hash code. Always -1.
900      * @serial
901      */

902     private volatile int hashcode = -1; // lazy evaluate
903

904     /**
905      * Calculated hashcode to fix 4518797.
906      */

907     private transient volatile int hashCodeValue = 0;
908
909     private static Locale JavaDoc defaultLocale = null;
910
911     /**
912      * Return an array of the display names of the variant.
913      * @param bundle the ResourceBundle to use to get the display names
914      * @return an array of display names, possible of zero length.
915      */

916     private String JavaDoc[] getDisplayVariantArray(ResourceBundle JavaDoc bundle) {
917         // Split the variant name into tokens separated by '_'.
918
StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(variant, "_");
919         String JavaDoc[] names = new String JavaDoc[tokenizer.countTokens()];
920
921         // For each variant token, lookup the display name. If
922
// not found, use the variant name itself.
923
for (int i=0; i<names.length; ++i) {
924             String JavaDoc token = tokenizer.nextToken();
925             try {
926                 names[i] = (String JavaDoc)bundle.getObject("%%" + token);
927             }
928             catch (MissingResourceException JavaDoc e) {
929                 names[i] = token;
930             }
931         }
932
933         return names;
934     }
935
936     /**
937      * Format a list with an array of patterns.
938      * @param patterns an array of three patterns. The first pattern is not
939      * used. The second pattern should create a MessageFormat taking 0-3 arguments
940      * and formatting them into a list. The third pattern should take 2 arguments
941      * and is used by composeList. If patterns is null, then a the list is
942      * formatted by concatenation with the delimiter ','.
943      * @param stringList the list of strings to be formatted.
944      * @return a string representing the list.
945      */

946     private static String JavaDoc formatList(String JavaDoc[] patterns, String JavaDoc[] stringList) {
947         // If we have no list patterns, compose the list in a simple,
948
// non-localized way.
949
if (patterns == null) {
950             StringBuffer JavaDoc result = new StringBuffer JavaDoc();
951             for (int i=0; i<stringList.length; ++i) {
952                 if (i>0) result.append(',');
953                 result.append(stringList[i]);
954             }
955             return result.toString();
956         }
957
958         // Compose the list down to three elements if necessary
959
if (stringList.length > 3) {
960             MessageFormat JavaDoc format = new MessageFormat JavaDoc(patterns[2]);
961             stringList = composeList(format, stringList);
962         }
963
964         // Rebuild the argument list with the list length as the first element
965
Object JavaDoc[] args = new Object JavaDoc[stringList.length + 1];
966         System.arraycopy(stringList, 0, args, 1, stringList.length);
967         args[0] = new Integer JavaDoc(stringList.length);
968
969         // Format it using the pattern in the resource
970
MessageFormat JavaDoc format = new MessageFormat JavaDoc(patterns[1]);
971         return format.format(args);
972     }
973
974     /**
975      * Given a list of strings, return a list shortened to three elements.
976      * Shorten it by applying the given format to the first two elements
977      * recursively.
978      * @param format a format which takes two arguments
979      * @param list a list of strings
980      * @return if the list is three elements or shorter, the same list;
981      * otherwise, a new list of three elements.
982      */

983     private static String JavaDoc[] composeList(MessageFormat JavaDoc format, String JavaDoc[] list) {
984         if (list.length <= 3) return list;
985
986         // Use the given format to compose the first two elements into one
987
String JavaDoc[] listItems = { list[0], list[1] };
988         String JavaDoc newItem = format.format(listItems);
989
990         // Form a new list one element shorter
991
String JavaDoc[] newList = new String JavaDoc[list.length-1];
992         System.arraycopy(list, 2, newList, 1, newList.length-1);
993         newList[0] = newItem;
994
995         // Recurse
996
return composeList(format, newList);
997     }
998
999     /**
1000     * Replace the deserialized Locale object with a newly
1001     * created object. Older language codes are replaced with newer ISO
1002     * codes. The country and variant codes are replaced with internalized
1003     * String copies.
1004     */

1005    private Object JavaDoc readResolve() throws java.io.ObjectStreamException JavaDoc {
1006        return new Locale JavaDoc(language, country, variant);
1007    }
1008
1009
1010    /**
1011     * List of all 2-letter language codes currently defined in ISO 639.
1012     * (Because the Java VM specification turns an array constant into executable code
1013     * that generates the array element by element, we keep the array in compressed
1014     * form in a single string and build the array from it at run time when requested.)
1015     * [We're now also using this table to store a mapping from 2-letter ISO language codes
1016     * to 3-letter ISO language codes. Each group of characters consists of a comma, a
1017     * 2-letter code, and a 3-letter code. We look up a 3-letter code by searching for
1018     * a comma followed by a 2-letter code and then getting the three letters following
1019     * the 2-letter code.]
1020     */

1021    private static String JavaDoc[] isoLanguages = null;
1022    private static final String JavaDoc compressedIsoLanguages =
1023        ",aaaar,ababk,aeave,afafr,akaka,amamh,anarg,arara,asasm,avava"
1024      + ",ayaym,azaze,babak,bebel,bgbul,bhbih,bibis,bmbam,bnben,bobod"
1025      + ",brbre,bsbos,cacat,ceche,chcha,cocos,crcre,csces,cuchu,cvchv"
1026      + ",cycym,dadan,dedeu,dvdiv,dzdzo,eeewe,elell,eneng,eoepo,esspa"
1027      + ",etest,eueus,fafas,ffful,fifin,fjfij,fofao,frfra,fyfry,gagle"
1028      + ",gdgla,glglg,gngrn,guguj,gvglv,hahau,heheb,hihin,hohmo,hrhrv"
1029      + ",hthat,huhun,hyhye,hzher,iaina,idind,ieile,igibo,iiiii,ikipk"
1030      + ",inind,ioido,isisl,itita,iuiku,iwheb,jajpn,jiyid,jvjav,kakat"
1031      + ",kgkon,kikik,kjkua,kkkaz,klkal,kmkhm,knkan,kokor,krkau,kskas"
1032      + ",kukur,kvkom,kwcor,kykir,lalat,lbltz,lglug,lilim,lnlin,lolao"
1033      + ",ltlit,lulub,lvlav,mgmlg,mhmah,mimri,mkmkd,mlmal,mnmon,momol"
1034      + ",mrmar,msmsa,mtmlt,mymya,nanau,nbnob,ndnde,nenep,ngndo,nlnld"
1035      + ",nnnno,nonor,nrnbl,nvnav,nynya,ococi,ojoji,omorm,orori,ososs"
1036      + ",papan,pipli,plpol,pspus,ptpor,quque,rmroh,rnrun,roron,rurus"
1037      + ",rwkin,sasan,scsrd,sdsnd,sesme,sgsag,sisin,skslk,slslv,smsmo"
1038      + ",snsna,sosom,sqsqi,srsrp,ssssw,stsot,susun,svswe,swswa,tatam"
1039      + ",tetel,tgtgk,ththa,titir,tktuk,tltgl,tntsn,toton,trtur,tstso"
1040      + ",tttat,twtwi,tytah,uguig,ukukr,ururd,uzuzb,veven,vivie,vovol"
1041      + ",wawln,wowol,xhxho,yiyid,yoyor,zazha,zhzho,zuzul";
1042
1043    /**
1044     * List of all 2-letter country codes currently defined in ISO 3166.
1045     * (Because the Java VM specification turns an array constant into executable code
1046     * that generates the array element by element, we keep the array in compressed
1047     * form in a single string and build the array from it at run time when requested.)
1048     * [We're now also using this table to store a mapping from 2-letter ISO country codes
1049     * to 3-letter ISO country codes. Each group of characters consists of a comma, a
1050     * 2-letter code, and a 3-letter code. We look up a 3-letter code by searching for
1051     * a comma followed by a 2-letter code and then getting the three letters following
1052     * the 2-letter code.]
1053     */

1054    private static String JavaDoc[] isoCountries = null;
1055    private static final String JavaDoc compressedIsoCountries =
1056        ",ADAND,AEARE,AFAFG,AGATG,AIAIA,ALALB,AMARM,ANANT,AOAGO,AQATA"
1057      + ",ARARG,ASASM,ATAUT,AUAUS,AWABW,AXALA,AZAZE,BABIH,BBBRB,BDBGD,BEBEL"
1058      + ",BFBFA,BGBGR,BHBHR,BIBDI,BJBEN,BMBMU,BNBRN,BOBOL,BRBRA,BSBHS"
1059      + ",BTBTN,BVBVT,BWBWA,BYBLR,BZBLZ,CACAN,CCCCK,CDCOD,CFCAF,CGCOG"
1060      + ",CHCHE,CICIV,CKCOK,CLCHL,CMCMR,CNCHN,COCOL,CRCRI,CSSCG,CUCUB"
1061      + ",CVCPV,CXCXR,CYCYP,CZCZE,DEDEU,DJDJI,DKDNK,DMDMA,DODOM,DZDZA"
1062      + ",ECECU,EEEST,EGEGY,EHESH,ERERI,ESESP,ETETH,FIFIN,FJFJI,FKFLK"
1063      + ",FMFSM,FOFRO,FRFRA,GAGAB,GBGBR,GDGRD,GEGEO,GFGUF,GHGHA,GIGIB"
1064      + ",GLGRL,GMGMB,GNGIN,GPGLP,GQGNQ,GRGRC,GSSGS,GTGTM,GUGUM,GWGNB"
1065      + ",GYGUY,HKHKG,HMHMD,HNHND,HRHRV,HTHTI,HUHUN,IDIDN,IEIRL,ILISR"
1066      + ",ININD,IOIOT,IQIRQ,IRIRN,ISISL,ITITA,JMJAM,JOJOR,JPJPN,KEKEN"
1067      + ",KGKGZ,KHKHM,KIKIR,KMCOM,KNKNA,KPPRK,KRKOR,KWKWT,KYCYM,KZKAZ"
1068      + ",LALAO,LBLBN,LCLCA,LILIE,LKLKA,LRLBR,LSLSO,LTLTU,LULUX,LVLVA"
1069      + ",LYLBY,MAMAR,MCMCO,MDMDA,MGMDG,MHMHL,MKMKD,MLMLI,MMMMR,MNMNG"
1070      + ",MOMAC,MPMNP,MQMTQ,MRMRT,MSMSR,MTMLT,MUMUS,MVMDV,MWMWI,MXMEX"
1071      + ",MYMYS,MZMOZ,NANAM,NCNCL,NENER,NFNFK,NGNGA,NINIC,NLNLD,NONOR"
1072      + ",NPNPL,NRNRU,NUNIU,NZNZL,OMOMN,PAPAN,PEPER,PFPYF,PGPNG,PHPHL"
1073      + ",PKPAK,PLPOL,PMSPM,PNPCN,PRPRI,PSPSE,PTPRT,PWPLW,PYPRY,QAQAT"
1074      + ",REREU,ROROU,RURUS,RWRWA,SASAU,SBSLB,SCSYC,SDSDN,SESWE,SGSGP"
1075      + ",SHSHN,SISVN,SJSJM,SKSVK,SLSLE,SMSMR,SNSEN,SOSOM,SRSUR,STSTP"
1076      + ",SVSLV,SYSYR,SZSWZ,TCTCA,TDTCD,TFATF,TGTGO,THTHA,TJTJK,TKTKL"
1077      + ",TLTLS,TMTKM,TNTUN,TOTON,TRTUR,TTTTO,TVTUV,TWTWN,TZTZA,UAUKR"
1078      + ",UGUGA,UMUMI,USUSA,UYURY,UZUZB,VAVAT,VCVCT,VEVEN,VGVGB,VIVIR"
1079      + ",VNVNM,VUVUT,WFWLF,WSWSM,YEYEM,YTMYT,ZAZAF,ZMZMB,ZWZWE";
1080
1081    /*
1082     * Locale needs its own, locale insensitive version of toLowerCase to
1083     * avoid circularity problems between Locale and String.
1084     * The most straightforward algorithm is used. Look at optimizations later.
1085     */

1086    private String JavaDoc toLowerCase(String JavaDoc str) {
1087    char[] buf = new char[str.length()];
1088        for (int i = 0; i < buf.length; i++) {
1089        buf[i] = Character.toLowerCase(str.charAt(i));
1090        }
1091        return new String JavaDoc( buf );
1092    }
1093
1094    /*
1095     * Locale needs its own, locale insensitive version of toUpperCase to
1096     * avoid circularity problems between Locale and String.
1097     * The most straightforward algorithm is used. Look at optimizations later.
1098     */

1099    private String JavaDoc toUpperCase(String JavaDoc str) {
1100    char[] buf = new char[str.length()];
1101        for (int i = 0; i < buf.length; i++) {
1102        buf[i] = Character.toUpperCase(str.charAt(i));
1103        }
1104        return new String JavaDoc( buf );
1105    }
1106
1107    private String JavaDoc findStringMatch(String JavaDoc[][] languages,
1108                                   String JavaDoc desiredLanguage, String JavaDoc fallbackLanguage)
1109    {
1110        for (int i = 0; i < languages.length; ++i)
1111            if (desiredLanguage.equals(languages[i][0]))
1112                return languages[i][1];
1113        if (!fallbackLanguage.equals(desiredLanguage))
1114            for (int i = 0; i < languages.length; ++i)
1115                if (fallbackLanguage.equals(languages[i][0]))
1116                    return languages[i][1];
1117        if (!"EN".equals(desiredLanguage) && "EN".equals(fallbackLanguage))
1118            for (int i = 0; i < languages.length; ++i)
1119                if ("EN".equals(languages[i][0]))
1120                    return languages[i][1];
1121        return "";
1122    }
1123
1124    private String JavaDoc convertOldISOCodes(String JavaDoc language) {
1125        // we accept both the old and the new ISO codes for the languages whose ISO
1126
// codes have changed, but we always store the OLD code, for backward compatibility
1127
language = toLowerCase(language).intern();
1128        if (language == "he") {
1129            return "iw";
1130        } else if (language == "yi") {
1131            return "ji";
1132        } else if (language == "id") {
1133            return "in";
1134        } else {
1135            return language;
1136        }
1137    }
1138}
1139
Popular Tags