Home | History | Annotate | Download | only in util
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package java.util;
     19 
     20 import com.ibm.icu4jni.util.ICU;
     21 import java.io.IOException;
     22 import java.io.ObjectInputStream;
     23 import java.io.ObjectOutputStream;
     24 import java.io.ObjectStreamField;
     25 import java.io.Serializable;
     26 import java.security.AccessController;
     27 import org.apache.harmony.luni.util.PriviAction;
     28 import org.apache.harmony.luni.util.Util;
     29 
     30 /**
     31  * {@code Locale} represents a language/country/variant combination. Locales are used to
     32  * alter the presentation of information such as numbers or dates to suit the conventions
     33  * in the region they describe.
     34  *
     35  * <p>The language codes are two-letter lowercase ISO language codes (such as "en") as defined by
     36  * <a href="http://en.wikipedia.org/wiki/ISO_639-1">ISO 639-1</a>.
     37  * The country codes are two-letter uppercase ISO country codes (such as "US") as defined by
     38  * <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-3">ISO 3166-1</a>.
     39  * The variant codes are unspecified.
     40  *
     41  * <p>Note that Java uses several deprecated two-letter codes. The Hebrew ("he") language
     42  * code is rewritten as "iw", Indonesian ("id") as "in", and Yiddish ("yi") as "ji". This
     43  * rewriting happens even if you construct your own {@code Locale} object, not just for
     44  * instances returned by the various lookup methods.
     45  *
     46  * <a name="available_locales"><h3>Available locales</h3></a>
     47  * <p>This class' constructors do no error checking. You can create a {@code Locale} for languages
     48  * and countries that don't exist, and you can create instances for combinations that don't
     49  * exist (such as "de_US" for "German as spoken in the US").
     50  *
     51  * <p>Note that locale data is not necessarily available for any of the locales pre-defined as
     52  * constants in this class except for en_US, which is the only locale Java guarantees is always
     53  * available.
     54  *
     55  * <p>It is also a mistake to assume that all devices have the same locales available.
     56  * A device sold in the US will almost certainly support en_US and es_US, but not necessarily
     57  * any locales with the same language but different countries (such as en_GB or es_ES),
     58  * nor any locales for other languages (such as de_DE). The opposite may well be true for a device
     59  * sold in Europe.
     60  *
     61  * <p>You can use {@code getDefault} to get an appropriate locale for the <i>user</i> of
     62  * the device you're running on, or {@code getAvailableLocales} to get a list of all the locales
     63  * available on the device you're running on.
     64  *
     65  * <a name="locale_data"><h3>Locale data</h3></a>
     66  * <p>Note that locale data comes solely from ICU. User-supplied locale service providers (using
     67  * the {@code java.text.spi} or {@code java.util.spi} mechanisms) are not supported.
     68  *
     69  * <p>Here are the versions of ICU (and the corresponding CLDR and Unicode versions) used in
     70  * various Android releases:
     71  * <table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
     72  * <tr><td>cupcake/donut/eclair</td> <td>ICU 3.8</td> <td><a href="http://www.unicode.org/press/pr-cldr1.5.html">CLDR 1.5</a></td> <td><a href="http://www.unicode.org/versions/Unicode5.0.0/">Unicode 5.0</a></td></tr>
     73  * <tr><td>froyo</td>                <td>ICU 4.2</td> <td><a href="http://www.unicode.org/press/pr-cldr1.7.html">CLDR 1.7</a></td> <td><a href="http://www.unicode.org/versions/Unicode5.1.0/">Unicode 5.1</a></td></tr>
     74  * <tr><td>gingerbread</td>          <td>ICU 4.4</td> <td><a href="http://www.unicode.org/press/pr-cldr1.8.html">CLDR 1.8</a></td> <td><a href="http://www.unicode.org/versions/Unicode5.2.0/">Unicode 5.2</a></td></tr>
     75  * </table>
     76  *
     77  * <a name="default_locale"><h3>Be wary of the default locale</h3></a>
     78  * <p>Note that there are many convenience methods that automatically use the default locale, but
     79  * these may not be as convenient as you imagine. The default locale is appropriate for anything
     80  * that involves presenting data to the user. You should use the user's date/time formats, number
     81  * formats, rules for conversion to lowercase, and so on. A common mistake is to implicitly use the
     82  * default locale when producing output meant to be machine-readable. This tends to work on the
     83  * developer's test devices but fail when run on a device whose user is in a less conventional
     84  * locale. For example, if you're formatting integers some locales will use non-ASCII decimal
     85  * digits. As another example, if you're formatting floating-point numbers some locales will use
     86  * {@code ','} as the decimal point. That's correct for human-readable output, but likely to cause
     87  * problems if presented to another computer ({@code Double.parseDouble} can't parse such a number,
     88  * for example). The best choice for computer-readable output is usually {@code Locale.US}: this
     89  * locale is guaranteed to be available on all devices, and the combination of no surprising
     90  * behavior and frequent use (especially for computer-computer communication) means that it tends
     91  * to be the most efficient choice too.
     92  */
     93 public final class Locale implements Cloneable, Serializable {
     94 
     95     private static final long serialVersionUID = 9149081749638150636L;
     96 
     97     // Initialize a default which is used during static
     98     // initialization of the default for the platform.
     99     private static Locale defaultLocale = new Locale();
    100 
    101     /**
    102      * Locale constant for en_CA.
    103      */
    104     public static final Locale CANADA = new Locale("en", "CA");
    105 
    106     /**
    107      * Locale constant for fr_CA.
    108      */
    109     public static final Locale CANADA_FRENCH = new Locale("fr", "CA");
    110 
    111     /**
    112      * Locale constant for zh_CN.
    113      */
    114     public static final Locale CHINA = new Locale("zh", "CN");
    115 
    116     /**
    117      * Locale constant for zh.
    118      */
    119     public static final Locale CHINESE = new Locale("zh", "");
    120 
    121     /**
    122      * Locale constant for en.
    123      */
    124     public static final Locale ENGLISH = new Locale("en", "");
    125 
    126     /**
    127      * Locale constant for fr_FR.
    128      */
    129     public static final Locale FRANCE = new Locale("fr", "FR");
    130 
    131     /**
    132      * Locale constant for fr.
    133      */
    134     public static final Locale FRENCH = new Locale("fr", "");
    135 
    136     /**
    137      * Locale constant for de.
    138      */
    139     public static final Locale GERMAN = new Locale("de", "");
    140 
    141     /**
    142      * Locale constant for de_DE.
    143      */
    144     public static final Locale GERMANY = new Locale("de", "DE");
    145 
    146     /**
    147      * Locale constant for it.
    148      */
    149     public static final Locale ITALIAN = new Locale("it", "");
    150 
    151     /**
    152      * Locale constant for it_IT.
    153      */
    154     public static final Locale ITALY = new Locale("it", "IT");
    155 
    156     /**
    157      * Locale constant for ja_JP.
    158      */
    159     public static final Locale JAPAN = new Locale("ja", "JP");
    160 
    161     /**
    162      * Locale constant for ja.
    163      */
    164     public static final Locale JAPANESE = new Locale("ja", "");
    165 
    166     /**
    167      * Locale constant for ko_KR.
    168      */
    169     public static final Locale KOREA = new Locale("ko", "KR");
    170 
    171     /**
    172      * Locale constant for ko.
    173      */
    174     public static final Locale KOREAN = new Locale("ko", "");
    175 
    176     /**
    177      * Locale constant for zh_CN.
    178      */
    179     public static final Locale PRC = new Locale("zh", "CN");
    180 
    181     /**
    182      * Locale constant for the root locale. The root locale has an empty language,
    183      * country, and variant.
    184      *
    185      * @since 1.6
    186      */
    187     public static final Locale ROOT = new Locale("", "", "");
    188 
    189     /**
    190      * Locale constant for zh_CN.
    191      */
    192     public static final Locale SIMPLIFIED_CHINESE = new Locale("zh", "CN");
    193 
    194     /**
    195      * Locale constant for zh_TW.
    196      */
    197     public static final Locale TAIWAN = new Locale("zh", "TW");
    198 
    199     /**
    200      * Locale constant for zh_TW.
    201      */
    202     public static final Locale TRADITIONAL_CHINESE = new Locale("zh", "TW");
    203 
    204     /**
    205      * Locale constant for en_GB.
    206      */
    207     public static final Locale UK = new Locale("en", "GB");
    208 
    209     /**
    210      * Locale constant for en_US.
    211      */
    212     public static final Locale US = new Locale("en", "US");
    213 
    214     private static final PropertyPermission setLocalePermission = new PropertyPermission(
    215             "user.language", "write");
    216 
    217     static {
    218         String language = AccessController.doPrivileged(new PriviAction<String>("user.language", "en"));
    219         String region = AccessController.doPrivileged(new PriviAction<String>("user.region", "US"));
    220         String variant = AccessController.doPrivileged(new PriviAction<String>("user.variant", ""));
    221         defaultLocale = new Locale(language, region, variant);
    222     }
    223 
    224     private transient String countryCode;
    225     private transient String languageCode;
    226     private transient String variantCode;
    227     private transient String cachedToStringResult;
    228 
    229     /**
    230      * Constructs a default which is used during static initialization of the
    231      * default for the platform.
    232      */
    233     private Locale() {
    234         languageCode = "en";
    235         countryCode = "US";
    236         variantCode = "";
    237     }
    238 
    239     /**
    240      * Constructs a new {@code Locale} using the specified language.
    241      */
    242     public Locale(String language) {
    243         this(language, "", "");
    244     }
    245 
    246     /**
    247      * Constructs a new {@code Locale} using the specified language and country codes.
    248      */
    249     public Locale(String language, String country) {
    250         this(language, country, "");
    251     }
    252 
    253     /**
    254      * Constructs a new {@code Locale} using the specified language, country,
    255      * and variant codes.
    256      */
    257     public Locale(String language, String country, String variant) {
    258         if (language == null || country == null || variant == null) {
    259             throw new NullPointerException();
    260         }
    261         if(language.isEmpty() && country.isEmpty()){
    262             languageCode = "";
    263             countryCode = "";
    264             variantCode = variant;
    265             return;
    266         }
    267         // BEGIN android-changed
    268         // this.uLocale = new ULocale(language, country, variant);
    269         // languageCode = uLocale.getLanguage();
    270         languageCode = Util.toASCIILowerCase(language);
    271         // END android-changed
    272         // Map new language codes to the obsolete language
    273         // codes so the correct resource bundles will be used.
    274         if (languageCode.equals("he")) {
    275             languageCode = "iw";
    276         } else if (languageCode.equals("id")) {
    277             languageCode = "in";
    278         } else if (languageCode.equals("yi")) {
    279             languageCode = "ji";
    280         }
    281 
    282         // countryCode is defined in ASCII character set
    283         // BEGIN android-changed
    284         // countryCode = country.length()!=0?uLocale.getCountry():"";
    285         countryCode = Util.toASCIIUpperCase(country);
    286         // END android-changed
    287 
    288         // Work around for be compatible with RI
    289         variantCode = variant;
    290     }
    291 
    292     @Override public Object clone() {
    293         try {
    294             return super.clone();
    295         } catch (CloneNotSupportedException e) {
    296             throw new AssertionError(e);
    297         }
    298     }
    299 
    300     /**
    301      * Returns true if {@code object} is a locale with the same language,
    302      * country and variant.
    303      */
    304     @Override public boolean equals(Object object) {
    305         if (object == this) {
    306             return true;
    307         }
    308         if (object instanceof Locale) {
    309             Locale o = (Locale) object;
    310             return languageCode.equals(o.languageCode)
    311                     && countryCode.equals(o.countryCode)
    312                     && variantCode.equals(o.variantCode);
    313         }
    314         return false;
    315     }
    316 
    317     /**
    318      * Returns the system's installed locales. This array always includes {@code
    319      * Locale.US}, and usually several others. Most locale-sensitive classes
    320      * offer their own {@code getAvailableLocales} method, which should be
    321      * preferred over this general purpose method.
    322      *
    323      * @see java.text.BreakIterator#getAvailableLocales()
    324      * @see java.text.Collator#getAvailableLocales()
    325      * @see java.text.DateFormat#getAvailableLocales()
    326      * @see java.text.DateFormatSymbols#getAvailableLocales()
    327      * @see java.text.DecimalFormatSymbols#getAvailableLocales()
    328      * @see java.text.NumberFormat#getAvailableLocales()
    329      * @see java.util.Calendar#getAvailableLocales()
    330      */
    331     public static Locale[] getAvailableLocales() {
    332         return ICU.getAvailableLocales();
    333     }
    334 
    335     /**
    336      * Returns the country code for this locale, or {@code ""} if this locale
    337      * doesn't correspond to a specific country.
    338      */
    339     public String getCountry() {
    340         return countryCode;
    341     }
    342 
    343     /**
    344      * Returns the user's preferred locale. This may have been overridden for
    345      * this process with {@link #setDefault}.
    346      *
    347      * <p>Since the user's locale changes dynamically, avoid caching this value.
    348      * Instead, use this method to look it up for each use.
    349      */
    350     public static Locale getDefault() {
    351         return defaultLocale;
    352     }
    353 
    354     /**
    355      * Equivalent to {@code getDisplayCountry(Locale.getDefault())}.
    356      */
    357     public final String getDisplayCountry() {
    358         return getDisplayCountry(getDefault());
    359     }
    360 
    361     /**
    362      * Returns the name of this locale's country, localized to {@code locale}.
    363      * Returns the empty string if this locale does not correspond to a specific
    364      * country.
    365      */
    366     public String getDisplayCountry(Locale locale) {
    367         if (countryCode.isEmpty()) {
    368             return "";
    369         }
    370         String result = ICU.getDisplayCountryNative(toString(), locale.toString());
    371         if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
    372             result = ICU.getDisplayCountryNative(toString(), Locale.getDefault().toString());
    373         }
    374         return result;
    375     }
    376 
    377     /**
    378      * Equivalent to {@code getDisplayLanguage(Locale.getDefault())}.
    379      */
    380     public final String getDisplayLanguage() {
    381         return getDisplayLanguage(getDefault());
    382     }
    383 
    384     /**
    385      * Returns the name of this locale's language, localized to {@code locale}.
    386      * If the language name is unknown, the language code is returned.
    387      */
    388     public String getDisplayLanguage(Locale locale) {
    389         if (languageCode.isEmpty()) {
    390             return "";
    391         }
    392         String result = ICU.getDisplayLanguageNative(toString(), locale.toString());
    393         if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
    394             result = ICU.getDisplayLanguageNative(toString(), Locale.getDefault().toString());
    395         }
    396         return result;
    397     }
    398 
    399     /**
    400      * Equivalent to {@code getDisplayName(Locale.getDefault())}.
    401      */
    402     public final String getDisplayName() {
    403         return getDisplayName(getDefault());
    404     }
    405 
    406     /**
    407      * Returns this locale's language name, country name, and variant, localized
    408      * to {@code locale}. The exact output form depends on whether this locale
    409      * corresponds to a specific language, country and variant, such as:
    410      * {@code English}, {@code English (United States)}, {@code English (United
    411      * States,Computer)}, {@code anglais (&#x00c9;tats-Unis)}, {@code anglais
    412      * (&#x00c9;tats-Unis,informatique)}.
    413      */
    414     public String getDisplayName(Locale locale) {
    415         int count = 0;
    416         StringBuilder buffer = new StringBuilder();
    417         if (!languageCode.isEmpty()) {
    418             String displayLanguage = getDisplayLanguage(locale);
    419             buffer.append(displayLanguage.isEmpty() ? languageCode : displayLanguage);
    420             ++count;
    421         }
    422         if (!countryCode.isEmpty()) {
    423             if (count == 1) {
    424                 buffer.append(" (");
    425             }
    426             String displayCountry = getDisplayCountry(locale);
    427             buffer.append(displayCountry.isEmpty() ? countryCode : displayCountry);
    428             ++count;
    429         }
    430         if (!variantCode.isEmpty()) {
    431             if (count == 1) {
    432                 buffer.append(" (");
    433             } else if (count == 2) {
    434                 buffer.append(",");
    435             }
    436             String displayVariant = getDisplayVariant(locale);
    437             buffer.append(displayVariant.isEmpty() ? variantCode : displayVariant);
    438             ++count;
    439         }
    440         if (count > 1) {
    441             buffer.append(")");
    442         }
    443         return buffer.toString();
    444     }
    445 
    446     /**
    447      * Gets the full variant name in the default {@code Locale} for the variant code of
    448      * this {@code Locale}. If there is no matching variant name, the variant code is
    449      * returned.
    450      *
    451      * @return a variant name.
    452      */
    453     public final String getDisplayVariant() {
    454         return getDisplayVariant(getDefault());
    455     }
    456 
    457     /**
    458      * Gets the full variant name in the specified {@code Locale} for the variant code
    459      * of this {@code Locale}. If there is no matching variant name, the variant code is
    460      * returned.
    461      *
    462      * @param locale
    463      *            the {@code Locale} for which the display name is retrieved.
    464      * @return a variant name.
    465      */
    466     public String getDisplayVariant(Locale locale) {
    467         if (variantCode.length() == 0) {
    468             return variantCode;
    469         }
    470         String result = ICU.getDisplayVariantNative(toString(), locale.toString());
    471         if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
    472             result = ICU.getDisplayVariantNative(toString(), Locale.getDefault().toString());
    473         }
    474         return result;
    475     }
    476 
    477     /**
    478      * Gets the three letter ISO country code which corresponds to the country
    479      * code for this {@code Locale}.
    480      *
    481      * @return a three letter ISO language code.
    482      * @throws MissingResourceException
    483      *                if there is no matching three letter ISO country code.
    484      */
    485     public String getISO3Country() throws MissingResourceException {
    486         if (countryCode.length() == 0) {
    487             return countryCode;
    488         }
    489         return ICU.getISO3CountryNative(toString());
    490     }
    491 
    492     /**
    493      * Gets the three letter ISO language code which corresponds to the language
    494      * code for this {@code Locale}.
    495      *
    496      * @return a three letter ISO language code.
    497      * @throws MissingResourceException
    498      *                if there is no matching three letter ISO language code.
    499      */
    500     public String getISO3Language() throws MissingResourceException {
    501         if (languageCode.length() == 0) {
    502             return languageCode;
    503         }
    504         return ICU.getISO3LanguageNative(toString());
    505     }
    506 
    507     /**
    508      * Gets the list of two letter ISO country codes which can be used as the
    509      * country code for a {@code Locale}.
    510      *
    511      * @return an array of strings.
    512      */
    513     public static String[] getISOCountries() {
    514         return ICU.getISOCountries();
    515     }
    516 
    517     /**
    518      * Gets the list of two letter ISO language codes which can be used as the
    519      * language code for a {@code Locale}.
    520      *
    521      * @return an array of strings.
    522      */
    523     public static String[] getISOLanguages() {
    524         return ICU.getISOLanguages();
    525     }
    526 
    527     /**
    528      * Gets the language code for this {@code Locale} or the empty string of no language
    529      * was set.
    530      *
    531      * @return a language code.
    532      */
    533     public String getLanguage() {
    534         return languageCode;
    535     }
    536 
    537     /**
    538      * Gets the variant code for this {@code Locale} or an empty {@code String} if no variant
    539      * was set.
    540      *
    541      * @return a variant code.
    542      */
    543     public String getVariant() {
    544         return variantCode;
    545     }
    546 
    547     /**
    548      * Returns an integer hash code for the receiver. Objects which are equal
    549      * return the same value for this method.
    550      *
    551      * @return the receiver's hash.
    552      * @see #equals
    553      */
    554     @Override
    555     public synchronized int hashCode() {
    556         return countryCode.hashCode() + languageCode.hashCode()
    557                 + variantCode.hashCode();
    558     }
    559 
    560     /**
    561      * Overrides the default locale. This does not affect system configuration,
    562      * and attempts to override the system-provided default locale may
    563      * themselves be overridden by actual changes to the system configuration.
    564      * Code that calls this method is usually incorrect, and should be fixed by
    565      * passing the appropriate locale to each locale-sensitive method that's
    566      * called.
    567      */
    568     public synchronized static void setDefault(Locale locale) {
    569         if (locale == null) {
    570             throw new NullPointerException();
    571         }
    572 
    573         SecurityManager security = System.getSecurityManager();
    574         if (security != null) {
    575             security.checkPermission(setLocalePermission);
    576         }
    577 
    578         defaultLocale = locale;
    579     }
    580 
    581     /**
    582      * Returns the string representation of this {@code Locale}. It consists of the
    583      * language code, country code and variant separated by underscores.
    584      * If the language is missing the string begins
    585      * with an underscore. If the country is missing there are 2 underscores
    586      * between the language and the variant. The variant cannot stand alone
    587      * without a language and/or country code: in this case this method would
    588      * return the empty string.
    589      *
    590      * <p>Examples: "en", "en_US", "_US", "en__POSIX", "en_US_POSIX"
    591      *
    592      * @return the string representation of this {@code Locale}.
    593      */
    594     @Override
    595     public final String toString() {
    596         String result = cachedToStringResult;
    597         return (result == null) ? (cachedToStringResult = toNewString()) : result;
    598     }
    599 
    600     private String toNewString() {
    601         // The string form of a locale that only has a variant is the empty string.
    602         if (languageCode.length() == 0 && countryCode.length() == 0) {
    603             return "";
    604         }
    605         // Otherwise, the output format is "ll_cc_variant", where language and country are always
    606         // two letters, but the variant is an arbitrary length. A size of 11 characters has room
    607         // for "en_US_POSIX", the largest "common" value. (In practice, the string form is almost
    608         // always 5 characters: "ll_cc".)
    609         StringBuilder result = new StringBuilder(11);
    610         result.append(languageCode);
    611         if (countryCode.length() > 0 || variantCode.length() > 0) {
    612             result.append('_');
    613         }
    614         result.append(countryCode);
    615         if (variantCode.length() > 0) {
    616             result.append('_');
    617         }
    618         result.append(variantCode);
    619         return result.toString();
    620     }
    621 
    622     private static final ObjectStreamField[] serialPersistentFields = {
    623             new ObjectStreamField("country", String.class),
    624             new ObjectStreamField("hashcode", Integer.TYPE),
    625             new ObjectStreamField("language", String.class),
    626             new ObjectStreamField("variant", String.class) };
    627 
    628     private void writeObject(ObjectOutputStream stream) throws IOException {
    629         ObjectOutputStream.PutField fields = stream.putFields();
    630         fields.put("country", countryCode);
    631         fields.put("hashcode", -1);
    632         fields.put("language", languageCode);
    633         fields.put("variant", variantCode);
    634         stream.writeFields();
    635     }
    636 
    637     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
    638         ObjectInputStream.GetField fields = stream.readFields();
    639         countryCode = (String) fields.get("country", "");
    640         languageCode = (String) fields.get("language", "");
    641         variantCode = (String) fields.get("variant", "");
    642     }
    643 }
    644