/*
* Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
*
* The original version of this source code and documentation
* is copyrighted and owned by Taligent, Inc., a wholly-owned
* subsidiary of IBM. These materials are provided under terms
* of a License Agreement between Taligent and Sun. This technology
* is protected by multiple US and International patents.
*
* This notice and attribution to Taligent may not be removed.
* Taligent is a registered trademark of Taligent, Inc.
*
*/
package java.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
import java.text.NumberFormat;
import java.text.MessageFormat;
import java.text.ParsePosition;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.spi.LocaleNameProvider;
import java.util.stream.Stream;
import jdk.internal.util.ReferencedKeyMap;
import jdk.internal.util.StaticProperty;
import jdk.internal.vm.annotation.Stable;
import sun.util.locale.BaseLocale;
import sun.util.locale.InternalLocaleBuilder;
import sun.util.locale.LanguageTag;
import sun.util.locale.LocaleExtensions;
import sun.util.locale.LocaleMatcher;
import sun.util.locale.LocaleSyntaxException;
import sun.util.locale.LocaleUtils;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleResources;
import sun.util.locale.provider.LocaleServiceProviderPool;
import sun.util.locale.provider.TimeZoneNameUtility;
/**
* A {@code Locale} represents a specific geographical, political,
* or cultural region. An API that requires a {@code Locale} to perform
* its task is {@index "locale-sensitive"} and uses the {@code Locale}
* to tailor information for the user. These locale-sensitive APIs
* are principally in the java.text and java.util packages.
* For example, displaying a number is a locale-sensitive operation—
* the number should be formatted according to the customs and conventions of the
* user's native country, region, or culture.
*
*
The {@code Locale} class implements IETF BCP 47 which is composed of
* RFC 4647 "Matching of Language
* Tags" and RFC 5646 "Tags
* for Identifying Languages" with support for the LDML (UTS#35, "Unicode
* Locale Data Markup Language") BCP 47-compatible extensions for locale data
* exchange. Each {@code Locale} is associated with locale data which is provided
* by the Java runtime environment or any deployed {@link
* java.util.spi.LocaleServiceProvider LocaleServiceProvider} implementations.
* The locale data provided by the Java runtime environment may vary by release.
*
*
Locale Composition
*
A {@code Locale} is composed of the bolded fields described below; note that a
* {@code Locale} need not have all such fields. For example, {@link
* Locale#ENGLISH Locale.ENGLISH} is only comprised of the language field.
* In contrast, a {@code Locale} such as the one returned by {@code
* Locale.forLanguageTag("en-Latn-US-POSIX-u-nu-latn")} would be comprised of all
* the fields below. This particular {@code Locale} would represent English in
* the United States using the Latin script and numerics for use in POSIX
* environments.
*
* {@code Locale} implements IETF BCP 47 and any deviations should be observed
* by the comments prefixed by "BCP 47 deviation:".
* RFC 5646
* combines subtags from various ISO (639, 3166, 15924) standards which are also
* included in the composition of {@code Locale}.
* Additionally, the full list of valid codes for each field can be found in the
*
* IANA Language Subtag Registry (e.g. search for "Type: region").
*
*
ISO 639 alpha-2/alpha-3 language code or a registered
* language subtag up to 8 alpha letters (for future enhancements).
* When a language has both an alpha-2 code and an alpha-3 code, the
* alpha-2 code must be used.
*
*
Case convention: {@code language} is case insensitive, but
* {@code Locale} always canonicalizes to lower case.
*
*
Syntax: Well-formed {@code language} values have the form {@code [a-zA-Z]{2,8}}.
*
BCP 47 deviation: this is not the full BCP 47 language production, since it excludes
* extlang
* (as modern three-letter language codes are preferred).
Case convention: {@code script} is case insensitive, but
* {@code Locale} always canonicalizes to title case (the first
* letter is upper case and the rest of the letters are lower
* case).
*
*
Syntax: Well-formed {@code script} values have the form {@code
* [a-zA-Z]{4}}
Any arbitrary value used to indicate a variation of a
* {@code Locale}. When multiple variants exist, they should be separated by
* {@code ('_'|'-')}. Variants of higher importance should precede the others.
*
BCP 47 deviation: BCP 47 subtags are strictly used to indicate
* additional variations that define a language or its dialects that
* are not covered by any combinations of language, script and
* region subtags. However, the variant field in {@code Locale} has
* historically been used for any kind of variation, not just
* language variations. For example, some supported variants
* available in Java SE Runtime Environments indicate alternative
* cultural behaviors such as calendar type or number script. In
* BCP 47, this kind of information which does not identify the
* language, is supported by extension subtags or private use
* subtags.
*
*
Case convention: {@code variant} is case sensitive. BCP 47
* deviation: BCP 47 treats the variant field as case insensitive.
*
*
Syntax: Well-formed {@code variant} values have the form {@code
* SUBTAG (('_'|'-') SUBTAG)*} where {@code SUBTAG =
* [0-9][0-9a-zA-Z]{3} | [0-9a-zA-Z]{5,8}}.
*
BCP 47 deviation: BCP 47 only
* uses hyphen ('-') as a delimiter, {@code Locale} is more lenient.
A map from single character keys to string values, indicating
* extensions apart from language identification.
*
BCP 47 deviation: The {@code
* extensions} in {@code Locale} implement the semantics and syntax of BCP 47
* extension subtags and private use subtags. The {@code extensions}
* field cannot have empty values.
*
*
Case convention: {@code extensions} are
* case insensitive, but {@code Locale} canonicalizes all
* extension keys and values to lower case.
*
*
Syntax: Well-formed keys are single characters from the set
* {@code [0-9a-zA-Z]}. Well-formed values have the form
* {@code SUBTAG ('-' SUBTAG)*} where for the key 'x'
* {@code SUBTAG = [0-9a-zA-Z]{1,8}} and for other keys
* {@code SUBTAG = [0-9a-zA-Z]{2,8}} (that is, 'x' allows
* single-character subtags).
*
* BCP 47 deviation: Although BCP 47 requires field values to be registered
* in the IANA Language Subtag Registry, the {@code Locale} class
* does not validate this requirement. For example, the variant code "foobar"
* is well-formed since it is composed of 5 to 8 alphanumerics, but is not defined
* the IANA Language Subtag Registry. The {@link Builder}
* only checks if an individual field satisfies the syntactic
* requirement (is well-formed), but does not validate the value
* itself. Conversely, {@link #of(String, String, String) Locale::of} and its
* overloads do not make any syntactic checks on the input.
*
*
UTS#35, "Unicode Locale Data Markup Language" defines optional
* attributes and keywords to override or refine the default behavior
* associated with a locale. A keyword is represented by a pair of
* key and type. For example, "nu-thai" indicates that Thai local
* digits (value:"thai") should be used for formatting numbers
* (key:"nu").
*
*
The keywords are mapped to a BCP 47 extension value using the
* extension key 'u' ({@link #UNICODE_LOCALE_EXTENSION}). The above
* example, "nu-thai", becomes the extension "u-nu-thai".
*
*
Thus, when a {@code Locale} object contains Unicode locale
* attributes and keywords,
* {@code getExtension(UNICODE_LOCALE_EXTENSION)} will return a
* String representing this information, for example, "nu-thai". The
* {@code Locale} class also provides {@link
* #getUnicodeLocaleAttributes}, {@link #getUnicodeLocaleKeys}, and
* {@link #getUnicodeLocaleType(String)} which provides access to the Unicode
* locale attributes and key/type pairs directly. When represented as
* a string, the Unicode Locale Extension lists attributes
* alphabetically, followed by key/type sequences with keys listed
* alphabetically (the order of subtags comprising a key's type is
* fixed when the type is defined)
*
*
A well-formed locale key has the form
* {@code [0-9a-zA-Z]{2}}. A well-formed locale type has the
* form {@code "" | [0-9a-zA-Z]{3,8} ('-' [0-9a-zA-Z]{3,8})*} (it
* can be empty, or a series of subtags 3-8 alphanums in length). A
* well-formed locale attribute has the form
* {@code [0-9a-zA-Z]{3,8}} (it is a single subtag with the same
* form as a locale type subtag).
*
*
The Unicode locale extension specifies optional behavior in
* locale-sensitive services. Although the LDML specification defines
* various keys and values, actual locale-sensitive service
* implementations in a Java Runtime Environment might not support any
* particular Unicode locale attributes or key/type pairs.
*
*
The default Locale is provided for any locale-sensitive methods if no
* {@code Locale} is explicitly specified as an argument, such as
* {@link NumberFormat#getInstance()}. The default Locale is determined at startup
* of the Java runtime and established in the following three phases:
*
*
The locale-related system properties listed below are established from the
* host environment. Some system properties (except for {@code user.language}) may
* not have values from the host environment.
*
*
Shows property keys and associated values
*
*
Locale-related System Properties Key
*
Description
*
*
*
{@systemProperty user.language}
*
{@link ##def_language language} for the default Locale,
* such as "en" (English)
*
{@systemProperty user.script}
*
{@link ##def_script script} for the default Locale,
* such as "Latn" (Latin)
*
{@systemProperty user.country}
*
{@link ##def_region country} for the default Locale,
* such as "US" (United States)
*
{@systemProperty user.variant}
*
{@link ##def_variant variant} for the default Locale,
* such as "POSIX"
*
{@systemProperty user.extensions}
*
{@link ##def_extensions extensions} for the default Locale,
* such as "u-ca-japanese" (Japanese Calendar)
*
*
*
*
The values of these system properties can be overridden by values designated
* at startup time. If the overriding value of the {@code user.extensions} property
* is unparsable, it is ignored. The overriding values of other properties are not
* checked for syntax or validity and are used directly in the default Locale.
* (Typically, system property values can be provided using the {@code -D} command-line
* option of a launcher. For example, specifying {@code -Duser.extensions=foobarbaz}
* results in a default Locale with no extensions, while specifying
* {@code -Duser.language=foobarbaz} results in a default Locale whose language is
* "foobarbaz".)
*
*
The default {@code Locale} instance is constructed from the values of these
* system properties.
*
*
*
Altering the system property values with {@link System#setProperties(Properties)}/
* {@link System#setProperty(String, String)} has no effect on the default Locale.
*
Once the default Locale is established, applications can query the default
* Locale with {@link #getDefault()} and change it with {@link #setDefault(Locale)}.
* If the default Locale is changed with {@link #setDefault(Locale)}, the corresponding
* system properties are not altered. It is not recommended that applications read
* these system properties and parse or interpret them as their values may be out of date.
*
*
Locale Category
*
There are finer-grained default Locales specific for each {@link Locale.Category}.
* These category specific default Locales can be queried by {@link #getDefault(Category)},
* and set by {@link #setDefault(Category, Locale)}. Construction of these category
* specific default Locales are determined by the corresponding system properties,
* which consist of the base system properties as listed above, suffixed by either
* {@code ".display"} or {@code ".format"} depending on the category. For example,
* the value of the {@code user.language.display} system property will be used in the
* {@code language} part of the default Locale for the {@link Locale.Category#DISPLAY}
* category. In the absence of category specific system properties, the "category-less"
* system properties are used, such as {@code user.language} in the previous example.
*
*
There are several ways to obtain a {@code Locale} object.
* It is advised against using the deprecated {@code Locale} constructors.
*
*
*
Locale Constants
*
A number of convenient constants are provided that return {@code Locale}
* objects for commonly used locales. For example, {@link #US Locale.US} is the
* {@code Locale} object for the United States.
*
Factory Methods
*
{@link #of(String, String, String) Locale::of} and its overloads obtain a
* {@code Locale} object from the given {@code language}, {@code country},
* and/or {@code variant}. {@link #forLanguageTag(String)} obtains a {@code Locale}
* object for a well-formed BCP 47 language tag.
*
Builder
*
{@link Builder} is used to construct a {@code Locale} object that conforms
* to BCP 47 syntax. Use a builder to enforce syntactic restrictions on the input.
*
*
The following invocations produce Locale objects that are all equivalent:
* {@snippet lang=java :
* Locale.US;
* Locale.of("en", "US");
* Locale.forLanguageTag("en-US");
* new Locale.Builder().setLanguage("en").setRegion("US").build();
* }
*
*
Usage Examples
*
*
Once a {@code Locale} is {@linkplain ##ObtainingLocale obtained},
* it can be queried for information about itself. For example, use {@link
* #getCountry} to get the country (or region) code and {@link #getLanguage} to
* get the language. {@link #getDisplayCountry} can be used to get the
* name of the country suitable for displaying to the user. Similarly,
* use {@link #getDisplayLanguage()} to get the name of
* the language suitable for displaying to the user. The {@code getDisplayXXX}
* methods are themselves locale-sensitive and have two variants; one with an explicit
* locale parameter, and one without. The latter uses the default {@link
* Locale.Category#DISPLAY DISPLAY} locale, so the following are equivalent :
* {@snippet lang=java :
* Locale.getDefault().getDisplayCountry();
* Locale.getDefault().getDisplayCountry(Locale.getDefault(Locale.Category.DISPLAY));
* }
*
*
The Java Platform provides a number of classes that perform locale-sensitive
* operations. For example, the {@code NumberFormat} class formats
* numbers, currency, and percentages in a locale-sensitive manner. Classes such
* as {@code NumberFormat} have several factory methods for creating a default object
* of that type. These methods generally have two variants; one with an explicit
* locale parameter, and one without. The latter uses the default {@link
* Locale.Category#FORMAT FORMAT} locale, so the following are equivalent :
* {@snippet lang=java :
* NumberFormat.getCurrencyInstance();
* NumberFormat.getCurrencyInstance(Locale.getDefault(Locale.Category.FORMAT));
* }
*
*
* The following example demonstrates locale-sensitive currency and
* date related operations under different locales :
* {@snippet lang = java:
* var number = 1000;
* NumberFormat.getCurrencyInstance(Locale.US).format(number); // returns "$1,000.00"
* NumberFormat.getCurrencyInstance(Locale.JAPAN).format(number); // returns "\u00A51,000""
* var date = LocalDate.of(2024, 1, 1);
* DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).localizedBy(Locale.US).format(date); // returns "January 1, 2024"
* DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).localizedBy(Locale.JAPAN).format(date); // returns "2024\u5e741\u67081\u65e5"
* }
*
*
If an application is internationalized and provides localized
* resources for multiple locales, it sometimes needs to find one or more
* locales (or language tags) which meet each user's specific preferences. Note
* that the term "{@index "language tag"}" is used interchangeably
* with "locale" in the following locale matching documentation.
*
*
In order to match a user's preferred locales to a set of language
* tags, RFC 4647 Matching of
* Language Tags defines two mechanisms: filtering and lookup.
* Filtering is used to get all matching locales, whereas
* lookup is to select the best matching locale.
* Matching is done case-insensitively. These matching mechanisms are described
* in the following sections.
*
*
A user's preference is called a Language Priority List and is
* expressed as a list of language ranges. There are syntactically two types of
* language ranges: basic and extended. See
* {@link Locale.LanguageRange Locale.LanguageRange} for details.
*
*
*
Filtering
*
*
The filtering operation returns all matching language tags. It is defined
* in RFC 4647 as follows:
* "In filtering, each language range represents the least specific language
* tag (that is, the language tag with fewest number of subtags) that is an
* acceptable match. All of the language tags in the matching set of tags will
* have an equal or greater number of subtags than the language range. Every
* non-wildcard subtag in the language range will appear in every one of the
* matching language tags."
*
*
There are two types of filtering: filtering for basic language ranges
* (called "basic filtering") and filtering for extended language ranges
* (called "extended filtering"). They may return different results by what
* kind of language ranges are included in the given Language Priority List.
* {@link Locale.FilteringMode} is a parameter to specify how filtering should
* be done.
*
*
Lookup
*
*
The lookup operation returns the best matching language tags. It is
* defined in RFC 4647 as follows:
* "By contrast with filtering, each language range represents the most
* specific tag that is an acceptable match. The first matching tag found,
* according to the user's priority, is considered the closest match and is the
* item returned."
*
*
For example, if a Language Priority List consists of two language ranges,
* {@code "zh-Hant-TW"} and {@code "en-US"}, in prioritized order, lookup
* method progressively searches the language tags below in order to find the
* best matching language tag.
*
* If there is a language tag which matches completely to a language range
* above, the language tag is returned.
*
*
{@code "*"} is the special language range, and it is ignored in lookup.
*
*
If multiple language tags match as a result of the subtag {@code '*'}
* included in a language range, the first matching language tag returned by
* an {@link Iterator} over a {@link Collection} of language tags is treated as
* the best matching one.
*
*
Serialization
*
*
During serialization, writeObject writes all fields to the output
* stream, including extensions.
*
*
During deserialization, readResolve adds extensions as described
* in {@linkplain ##special_cases_constructor Special Cases}, only
* for the two cases th_TH_TH and ja_JP_JP.
*
* @implNote
*
Compatibility
*
The following commentary is provided for apps that want to ensure
* interoperability with older releases of {@code Locale} provided by the
* reference implementation.
*
* In order to maintain compatibility, Locale's (deprecated) constructors,
* {@link #of(String, String, String)}, and its overloads retain their behavior prior to the Java Runtime
* Environment version 1.7. That is, a length constraint is not imposed on any of
* the input parameters. Similarly, the same preservation of past behavior is largely true
* for the {@link #toString()} method.
* Apps that previously parsed the output of {@link #toString()} into language,
* country, and variant fields can continue to do so (although this is strongly
* discouraged). A caveat is that the variant field will have additional
* information in it if script or extensions are present.
*
*
In addition, BCP 47 imposes syntax restrictions that are not
* imposed by Locale's constructors. This means that conversions
* between some Locales and BCP 47 language tags cannot be made without
* losing information. Thus {@link #toLanguageTag} cannot
* represent the state of locales whose language, country, or variant
* do not conform to BCP 47.
*
*
Because of these issues, it is recommended that apps migrate
* away from constructing non-conforming locales and use the
* {@link #forLanguageTag(String)} and {@link Locale.Builder} APIs instead.
* Apps desiring a string representation of the complete locale can
* then always rely on {@link #toLanguageTag} for this purpose.
*
*
For compatibility reasons, two
* non-conforming locales are treated as special cases. These are
* {@code ja_JP_JP} and {@code th_TH_TH}. These are ill-formed
* in BCP 47 since the {@linkplain ##def_variant variants} are too short. To ease migration to BCP 47,
* these are treated specially during construction. These two cases (and only
* these) cause a constructor to generate an extension, all other values behave
* exactly as they did prior to Java 7.
*
*
Java has used {@code ja_JP_JP} to represent Japanese as used in
* Japan together with the Japanese Imperial calendar. This is now
* representable using a Unicode locale extension, by specifying the
* Unicode locale key {@code ca} (for "calendar") and type
* {@code japanese}. When the Locale constructor is called with the
* arguments "ja", "JP", "JP", the extension "u-ca-japanese" is
* automatically added.
*
*
Java has used {@code th_TH_TH} to represent Thai as used in
* Thailand together with Thai digits. This is also now representable using
* a Unicode locale extension, by specifying the Unicode locale key
* {@code nu} (for "number") and value {@code thai}. When the Locale
* constructor is called with the arguments "th", "TH", "TH", the
* extension "u-nu-thai" is automatically added.
*
*
Locale's constructors have always converted three language codes to
* their earlier, obsoleted forms: {@code he} maps to {@code iw},
* {@code yi} maps to {@code ji}, and {@code id} maps to
* {@code in}. Since Java SE 17, this is no longer the case. Each
* language maps to its new form; {@code iw} maps to {@code he}, {@code ji}
* maps to {@code yi}, and {@code in} maps to {@code id}.
*
*
For backwards compatible behavior, the system property
* {@systemProperty java.locale.useOldISOCodes} reverts the behavior
* back to that of before Java SE 17. If the system property is set to
* {@code true}, those three current language codes are mapped to their
* backward compatible forms. The property is only read at Java runtime
* startup and subsequent calls to {@code System.setProperty()} will
* have no effect.
*
*
The APIs added in 1.7 map between the old and new language codes,
* maintaining the mapped codes internal to Locale (so that
* {@code getLanguage} and {@code toString} reflect the mapped
* code, which depends on the {@code java.locale.useOldISOCodes} system
* property), but using the new codes in the BCP 47 language tag APIs (so
* that {@code toLanguageTag} reflects the new one). This
* preserves the equivalence between Locales no matter which code or
* API is used to construct them. Java's default resource bundle
* lookup mechanism also implements this mapping, so that resources
* can be named using either convention, see {@link ResourceBundle.Control}.
*
* @spec https://www.rfc-editor.org/info/rfc4647
* RFC 4647: Matching of Language Tags
* @spec https://www.rfc-editor.org/info/rfc5646
* RFC 5646: Tags for Identifying Languages
* @spec https://unicode.org/reports/tr35/
* Unicode Locale Data Markup Language
* @see Builder
* @see ResourceBundle
* @see java.text.Format
* @see java.text.NumberFormat
* @see java.text.Collator
* @author Mark Davis
* @since 1.1
*/
public final class Locale implements Cloneable, Serializable {
/** Useful constant for language.
*/
public static final Locale ENGLISH;
/** Useful constant for language.
*/
public static final Locale FRENCH;
/** Useful constant for language.
*/
public static final Locale GERMAN;
/** Useful constant for language.
*/
public static final Locale ITALIAN;
/** Useful constant for language.
*/
public static final Locale JAPANESE;
/** Useful constant for language.
*/
public static final Locale KOREAN;
/** Useful constant for language.
*/
public static final Locale CHINESE;
/** Useful constant for language.
*/
public static final Locale SIMPLIFIED_CHINESE;
/** Useful constant for language.
*/
public static final Locale TRADITIONAL_CHINESE;
/** Useful constant for country.
*/
public static final Locale FRANCE;
/** Useful constant for country.
*/
public static final Locale GERMANY;
/** Useful constant for country.
*/
public static final Locale ITALY;
/** Useful constant for country.
*/
public static final Locale JAPAN;
/** Useful constant for country.
*/
public static final Locale KOREA;
/** Useful constant for country.
*/
public static final Locale UK;
/** Useful constant for country.
*/
public static final Locale US;
/** Useful constant for country.
*/
public static final Locale CANADA;
/** Useful constant for country.
*/
public static final Locale CANADA_FRENCH;
/**
* Useful constant for the root locale. The root locale is the locale whose
* language, country, and variant are empty ("") strings. This is regarded
* as the base locale of all locales, and is used as the language/country
* neutral locale for the locale sensitive operations.
*
* @since 1.6
*/
public static final Locale ROOT;
private static final Map CONSTANT_LOCALES = new HashMap<>();
static {
ENGLISH = createConstant(BaseLocale.ENGLISH);
FRENCH = createConstant(BaseLocale.FRENCH);
GERMAN = createConstant(BaseLocale.GERMAN);
ITALIAN = createConstant(BaseLocale.ITALIAN);
JAPANESE = createConstant(BaseLocale.JAPANESE);
KOREAN = createConstant(BaseLocale.KOREAN);
CHINESE = createConstant(BaseLocale.CHINESE);
SIMPLIFIED_CHINESE = createConstant(BaseLocale.SIMPLIFIED_CHINESE);
TRADITIONAL_CHINESE = createConstant(BaseLocale.TRADITIONAL_CHINESE);
FRANCE = createConstant(BaseLocale.FRANCE);
GERMANY = createConstant(BaseLocale.GERMANY);
ITALY = createConstant(BaseLocale.ITALY);
JAPAN = createConstant(BaseLocale.JAPAN);
KOREA = createConstant(BaseLocale.KOREA);
UK = createConstant(BaseLocale.UK);
US = createConstant(BaseLocale.US);
CANADA = createConstant(BaseLocale.CANADA);
CANADA_FRENCH = createConstant(BaseLocale.CANADA_FRENCH);
ROOT = createConstant(BaseLocale.ROOT);
}
/** Useful constant for country.
*/
public static final Locale CHINA = SIMPLIFIED_CHINESE;
/** Useful constant for country.
*/
public static final Locale PRC = SIMPLIFIED_CHINESE;
/** Useful constant for country.
*/
public static final Locale TAIWAN = TRADITIONAL_CHINESE;
/**
* This method must be called only for creating the Locale.*
* constants due to making shortcuts.
*/
private static Locale createConstant(byte baseType) {
BaseLocale base = BaseLocale.constantBaseLocales[baseType];
Locale locale = new Locale(base, null);
CONSTANT_LOCALES.put(base, locale);
return locale;
}
/**
* The key for the private use extension ('x').
*
* @see #getExtension(char)
* @see Builder#setExtension(char, String)
* @since 1.7
*/
public static final char PRIVATE_USE_EXTENSION = 'x';
/**
* The key for Unicode locale extension ('u').
*
* @see #getExtension(char)
* @see Builder#setExtension(char, String)
* @since 1.7
*/
public static final char UNICODE_LOCALE_EXTENSION = 'u';
/** serialization ID
*/
@java.io.Serial
static final long serialVersionUID = 9149081749638150636L;
/**
* Enum for specifying the type defined in ISO 3166. This enum is used to
* retrieve the two-letter ISO3166-1 alpha-2, three-letter ISO3166-1
* alpha-3, four-letter ISO3166-3 country codes.
*
* @see #getISOCountries(Locale.IsoCountryCode)
* @since 9
*/
public static enum IsoCountryCode {
/**
* PART1_ALPHA2 is used to represent the ISO3166-1 alpha-2 two letter
* country codes.
*/
PART1_ALPHA2 {
@Override
Set createCountryCodeSet() {
return Set.of(Locale.getISOCountries());
}
},
/**
*
* PART1_ALPHA3 is used to represent the ISO3166-1 alpha-3 three letter
* country codes.
*/
PART1_ALPHA3 {
@Override
Set createCountryCodeSet() {
return LocaleISOData.computeISO3166_1Alpha3Countries();
}
},
/**
* PART3 is used to represent the ISO3166-3 four letter country codes.
*/
PART3 {
@Override
Set createCountryCodeSet() {
return Set.of(LocaleISOData.ISO3166_3);
}
};
/**
* Concrete implementation of this method attempts to compute value
* for iso3166CodesMap for each IsoCountryCode type key.
*/
abstract Set createCountryCodeSet();
/**
* Map to hold country codes for each ISO3166 part.
*/
private static final Map> iso3166CodesMap = new ConcurrentHashMap<>();
/**
* This method is called from Locale class to retrieve country code set
* for getISOCountries(type)
*/
static Set retrieveISOCountryCodes(IsoCountryCode type) {
return iso3166CodesMap.computeIfAbsent(type, IsoCountryCode::createCountryCodeSet);
}
}
/**
* Display types for retrieving localized names from the name providers.
*/
private static final int DISPLAY_LANGUAGE = 0;
private static final int DISPLAY_COUNTRY = 1;
private static final int DISPLAY_VARIANT = 2;
private static final int DISPLAY_SCRIPT = 3;
private static final int DISPLAY_UEXT_KEY = 4;
private static final int DISPLAY_UEXT_TYPE = 5;
/**
* Private constructor used by getInstance method
*/
private Locale(BaseLocale baseLocale, LocaleExtensions extensions) {
this.baseLocale = baseLocale;
this.localeExtensions = extensions;
}
/**
* Construct a locale from language, country and variant.
* This constructor normalizes the language value to lowercase and
* the country value to uppercase.
* @implNote
*
*
Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to
* their current forms. See {@linkplain ##legacy_language_codes Legacy language
* codes} for more information.
*
For backward compatibility reasons, this constructor does not make
* any syntactic checks on the input.
*
The two cases ("ja", "JP", "JP") and ("th", "TH", "TH") are handled specially,
* see {@linkplain ##special_cases_constructor Special Cases} for more information.
*
*
* @deprecated Locale constructors have been deprecated. See {@linkplain ##ObtainingLocale
* Obtaining a Locale} for other options.
*
* @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
* up to 8 characters in length. See the {@code Locale} class description about
* valid language values.
* @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
* See the {@code Locale} class description about valid country values.
* @param variant Any arbitrary value used to indicate a variation of a {@code Locale}.
* See the {@code Locale} class description for the details.
* @throws NullPointerException thrown if any argument is null.
*/
@Deprecated(since="19")
public Locale(String language, String country, String variant) {
if (language == null || country == null || variant == null) {
throw new NullPointerException();
}
baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant);
localeExtensions = getCompatibilityExtensions(language, "", country, variant);
}
/**
* Construct a locale from language and country.
* This constructor normalizes the language value to lowercase and
* the country value to uppercase.
* @implNote
*
*
Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to
* their current forms. See {@linkplain ##legacy_language_codes Legacy language
* codes} for more information.
*
For backward compatibility reasons, this constructor does not make
* any syntactic checks on the input.
*
*
* @deprecated Locale constructors have been deprecated. See {@linkplain
* ##ObtainingLocale Obtaining a Locale} for other options.
*
* @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
* up to 8 characters in length. See the {@code Locale} class description about
* valid language values.
* @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
* See the {@code Locale} class description about valid country values.
* @throws NullPointerException thrown if either argument is null.
*/
@Deprecated(since="19")
public Locale(String language, String country) {
this(language, country, "");
}
/**
* Construct a locale from a language code.
* This constructor normalizes the language value to lowercase.
* @implNote
*
*
Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to
* their current forms. See {@linkplain ##legacy_language_codes Legacy language
* codes} for more information.
*
For backward compatibility reasons, this constructor does not make
* any syntactic checks on the input.
*
*
* @deprecated Locale constructors have been deprecated. See {@linkplain
* ##ObtainingLocale Obtaining a Locale} for other options.
*
* @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
* up to 8 characters in length. See the {@code Locale} class description about
* valid language values.
* @throws NullPointerException thrown if argument is null.
* @since 1.4
*/
@Deprecated(since="19")
public Locale(String language) {
this(language, "", "");
}
/**
* Obtains a locale from language, country and variant.
* This method normalizes the language value to lowercase and
* the country value to uppercase.
* @implNote
*
*
This method does not make any syntactic checks on the input.
* Use {@link Locale.Builder} for full syntactic checks with BCP47.
*
The two cases ("ja", "JP", "JP") and ("th", "TH", "TH") are handled specially,
* see {@linkplain ##special_cases_constructor Special Cases} for more information.
*
Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to
* their current forms. See {@linkplain ##legacy_language_codes Legacy language
* codes} for more information.
*
*
* @param language A language code. See the {@code Locale} class description of
* {@linkplain ##def_language language} values.
* @param country A country code. See the {@code Locale} class description of
* {@linkplain ##def_region country} values.
* @param variant Any arbitrary value used to indicate a variation of a {@code Locale}.
* See the {@code Locale} class description of {@linkplain ##def_variant
* variant} values.
* @throws NullPointerException thrown if any argument is null.
* @return A {@code Locale} object
* @since 19
*/
public static Locale of(String language, String country, String variant) {
return getInstance(language, "", country, variant, null);
}
/**
* Obtains a locale from language and country.
* This method normalizes the language value to lowercase and
* the country value to uppercase.
* @implNote
*
*
This method does not make any syntactic checks on the input.
* Use {@link Locale.Builder} for full syntactic checks with BCP47.
*
Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to
* their current forms. See {@linkplain ##legacy_language_codes Legacy language
* codes} for more information.
*
*
* @param language A language code. See the {@code Locale} class description of
* {@linkplain ##def_language language} values.
* @param country A country code. See the {@code Locale} class description of
* {@linkplain ##def_region country} values.
* @throws NullPointerException thrown if either argument is null.
* @return A {@code Locale} object
* @since 19
*/
public static Locale of(String language, String country) {
return getInstance(language, "", country, "", null);
}
/**
* Obtains a locale from a language code.
* This method normalizes the language value to lowercase.
* @implNote
*
*
This method does not make any syntactic checks on the input.
* Use {@link Locale.Builder} for full syntactic checks with BCP47.
*
Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to
* their current forms. See {@linkplain ##legacy_language_codes Legacy language
* codes} for more information.
*
*
* @param language A language code. See the {@code Locale} class description of
* {@linkplain ##def_language language} values.
* @throws NullPointerException thrown if argument is null.
* @return A {@code Locale} object
* @since 19
*/
public static Locale of(String language) {
return getInstance(language, "", "", "", null);
}
/**
* Returns a {@code Locale} constructed from the given
* {@code language}, {@code country} and
* {@code variant}. If the same {@code Locale} instance
* is available in the cache, then that instance is
* returned. Otherwise, a new {@code Locale} instance is
* created and cached.
*
* @param language lowercase 2 to 8 language code.
* @param country uppercase two-letter ISO-3166 code and numeric-3 UN M.49 area code.
* @param variant vendor and browser specific code. See class description.
* @return the {@code Locale} instance requested
* @throws NullPointerException if any argument is null.
*/
static Locale getInstance(String language, String country, String variant) {
return getInstance(language, "", country, variant, null);
}
static Locale getInstance(String language, String script, String country,
String variant, LocaleExtensions extensions) {
if (language== null || script == null || country == null || variant == null) {
throw new NullPointerException();
}
if (extensions == null) {
extensions = getCompatibilityExtensions(language, script, country, variant);
}
BaseLocale baseloc = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
return getInstance(baseloc, extensions);
}
static Locale getInstance(BaseLocale baseloc, LocaleExtensions extensions) {
if (extensions == null) {
Locale locale = CONSTANT_LOCALES.get(baseloc);
if (locale != null) {
return locale;
}
return LocaleCache.cache(baseloc);
} else {
LocaleKey key = new LocaleKey(baseloc, extensions);
return LocaleCache.cache(key);
}
}
private static final class LocaleCache implements Function