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