1 /*
2 * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 /*
27 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
28 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
29 *
30 * The original version of this source code and documentation
31 * is copyrighted and owned by Taligent, Inc., a wholly-owned
32 * subsidiary of IBM. These materials are provided under terms
33 * of a License Agreement between Taligent and Sun. This technology
34 * is protected by multiple US and International patents.
35 *
36 * This notice and attribution to Taligent may not be removed.
37 * Taligent is a registered trademark of Taligent, Inc.
38 *
39 */
40
41 package java.util;
42
43 import java.io.IOException;
44 import java.io.ObjectInputStream;
45 import java.io.ObjectOutputStream;
46 import java.io.ObjectStreamField;
47 import java.io.Serializable;
48 import java.text.MessageFormat;
49 import java.util.concurrent.ConcurrentHashMap;
50 import java.util.spi.LocaleNameProvider;
51 import java.util.stream.Collectors;
52
53 import sun.security.action.GetPropertyAction;
54 import sun.util.locale.BaseLocale;
55 import sun.util.locale.InternalLocaleBuilder;
56 import sun.util.locale.LanguageTag;
57 import sun.util.locale.LocaleExtensions;
58 import sun.util.locale.LocaleMatcher;
59 import sun.util.locale.LocaleObjectCache;
60 import sun.util.locale.LocaleSyntaxException;
61 import sun.util.locale.LocaleUtils;
62 import sun.util.locale.ParseStatus;
63 import sun.util.locale.provider.LocaleProviderAdapter;
64 import sun.util.locale.provider.LocaleResources;
65 import sun.util.locale.provider.LocaleServiceProviderPool;
66 import sun.util.locale.provider.TimeZoneNameUtility;
67
68 /**
69 * A <code>Locale</code> object represents a specific geographical, political,
70 * or cultural region. An operation that requires a <code>Locale</code> to perform
71 * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code>
72 * to tailor information for the user. For example, displaying a number
73 * is a locale-sensitive operation— the number should be formatted
74 * according to the customs and conventions of the user's native country,
75 * region, or culture.
76 *
77 * <p> The {@code Locale} class implements IETF BCP 47 which is composed of
78 * <a href="http://tools.ietf.org/html/rfc4647">RFC 4647 "Matching of Language
79 * Tags"</a> and <a href="http://tools.ietf.org/html/rfc5646">RFC 5646 "Tags
80 * for Identifying Languages"</a> with support for the LDML (UTS#35, "Unicode
81 * Locale Data Markup Language") BCP 47-compatible extensions for locale data
82 * exchange.
83 *
84 * <p> A <code>Locale</code> object logically consists of the fields
85 * described below.
86 *
87 * <dl>
88 * <dt><a id="def_language"><b>language</b></a></dt>
89 *
90 * <dd>ISO 639 alpha-2 or alpha-3 language code, or registered
91 * language subtags up to 8 alpha letters (for future enhancements).
92 * When a language has both an alpha-2 code and an alpha-3 code, the
93 * alpha-2 code must be used. You can find a full list of valid
94 * language codes in the IANA Language Subtag Registry (search for
95 * "Type: language"). The language field is case insensitive, but
96 * <code>Locale</code> always canonicalizes to lower case.</dd>
97 *
98 * <dd>Well-formed language values have the form
99 * <code>[a-zA-Z]{2,8}</code>. Note that this is not the full
100 * BCP47 language production, since it excludes extlang. They are
101 * not needed since modern three-letter language codes replace
102 * them.</dd>
103 *
104 * <dd>Example: "en" (English), "ja" (Japanese), "kok" (Konkani)</dd>
105 *
106 * <dt><a id="def_script"><b>script</b></a></dt>
107 *
108 * <dd>ISO 15924 alpha-4 script code. You can find a full list of
109 * valid script codes in the IANA Language Subtag Registry (search
110 * for "Type: script"). The script field is case insensitive, but
111 * <code>Locale</code> always canonicalizes to title case (the first
112 * letter is upper case and the rest of the letters are lower
113 * case).</dd>
114 *
115 * <dd>Well-formed script values have the form
116 * <code>[a-zA-Z]{4}</code></dd>
117 *
118 * <dd>Example: "Latn" (Latin), "Cyrl" (Cyrillic)</dd>
119 *
120 * <dt><a id="def_region"><b>country (region)</b></a></dt>
121 *
122 * <dd>ISO 3166 alpha-2 country code or UN M.49 numeric-3 area code.
123 * You can find a full list of valid country and region codes in the
124 * IANA Language Subtag Registry (search for "Type: region"). The
125 * country (region) field is case insensitive, but
126 * <code>Locale</code> always canonicalizes to upper case.</dd>
127 *
128 * <dd>Well-formed country/region values have
129 * the form <code>[a-zA-Z]{2} | [0-9]{3}</code></dd>
130 *
131 * <dd>Example: "US" (United States), "FR" (France), "029"
132 * (Caribbean)</dd>
133 *
134 * <dt><a id="def_variant"><b>variant</b></a></dt>
135 *
136 * <dd>Any arbitrary value used to indicate a variation of a
137 * <code>Locale</code>. Where there are two or more variant values
138 * each indicating its own semantics, these values should be ordered
139 * by importance, with most important first, separated by
140 * underscore('_'). The variant field is case sensitive.</dd>
141 *
142 * <dd>Note: IETF BCP 47 places syntactic restrictions on variant
143 * subtags. Also BCP 47 subtags are strictly used to indicate
144 * additional variations that define a language or its dialects that
145 * are not covered by any combinations of language, script and
146 * region subtags. You can find a full list of valid variant codes
147 * in the IANA Language Subtag Registry (search for "Type: variant").
148 *
149 * <p>However, the variant field in <code>Locale</code> has
150 * historically been used for any kind of variation, not just
151 * language variations. For example, some supported variants
152 * available in Java SE Runtime Environments indicate alternative
153 * cultural behaviors such as calendar type or number script. In
154 * BCP 47 this kind of information, which does not identify the
155 * language, is supported by extension subtags or private use
156 * subtags.</dd>
157 *
158 * <dd>Well-formed variant values have the form <code>SUBTAG
159 * (('_'|'-') SUBTAG)*</code> where <code>SUBTAG =
160 * [0-9][0-9a-zA-Z]{3} | [0-9a-zA-Z]{5,8}</code>. (Note: BCP 47 only
161 * uses hyphen ('-') as a delimiter, this is more lenient).</dd>
162 *
163 * <dd>Example: "polyton" (Polytonic Greek), "POSIX"</dd>
164 *
165 * <dt><a id="def_extensions"><b>extensions</b></a></dt>
166 *
167 * <dd>A map from single character keys to string values, indicating
168 * extensions apart from language identification. The extensions in
169 * <code>Locale</code> implement the semantics and syntax of BCP 47
170 * extension subtags and private use subtags. The extensions are
171 * case insensitive, but <code>Locale</code> canonicalizes all
172 * extension keys and values to lower case. Note that extensions
173 * cannot have empty values.</dd>
174 *
175 * <dd>Well-formed keys are single characters from the set
176 * <code>[0-9a-zA-Z]</code>. Well-formed values have the form
177 * <code>SUBTAG ('-' SUBTAG)*</code> where for the key 'x'
178 * <code>SUBTAG = [0-9a-zA-Z]{1,8}</code> and for other keys
179 * <code>SUBTAG = [0-9a-zA-Z]{2,8}</code> (that is, 'x' allows
180 * single-character subtags).</dd>
181 *
182 * <dd>Example: key="u"/value="ca-japanese" (Japanese Calendar),
183 * key="x"/value="java-1-7"</dd>
184 * </dl>
185 *
186 * <b>Note:</b> Although BCP 47 requires field values to be registered
187 * in the IANA Language Subtag Registry, the <code>Locale</code> class
188 * does not provide any validation features. The <code>Builder</code>
189 * only checks if an individual field satisfies the syntactic
190 * requirement (is well-formed), but does not validate the value
191 * itself. See {@link Builder} for details.
192 *
193 * <h3><a id="def_locale_extension">Unicode locale/language extension</a></h3>
194 *
195 * <p>UTS#35, "Unicode Locale Data Markup Language" defines optional
196 * attributes and keywords to override or refine the default behavior
197 * associated with a locale. A keyword is represented by a pair of
198 * key and type. For example, "nu-thai" indicates that Thai local
199 * digits (value:"thai") should be used for formatting numbers
200 * (key:"nu").
201 *
202 * <p>The keywords are mapped to a BCP 47 extension value using the
203 * extension key 'u' ({@link #UNICODE_LOCALE_EXTENSION}). The above
204 * example, "nu-thai", becomes the extension "u-nu-thai".
205 *
206 * <p>Thus, when a <code>Locale</code> object contains Unicode locale
207 * attributes and keywords,
208 * <code>getExtension(UNICODE_LOCALE_EXTENSION)</code> will return a
209 * String representing this information, for example, "nu-thai". The
210 * <code>Locale</code> class also provides {@link
211 * #getUnicodeLocaleAttributes}, {@link #getUnicodeLocaleKeys}, and
212 * {@link #getUnicodeLocaleType} which allow you to access Unicode
213 * locale attributes and key/type pairs directly. When represented as
214 * a string, the Unicode Locale Extension lists attributes
215 * alphabetically, followed by key/type sequences with keys listed
216 * alphabetically (the order of subtags comprising a key's type is
217 * fixed when the type is defined)
218 *
219 * <p>A well-formed locale key has the form
220 * <code>[0-9a-zA-Z]{2}</code>. A well-formed locale type has the
221 * form <code>"" | [0-9a-zA-Z]{3,8} ('-' [0-9a-zA-Z]{3,8})*</code> (it
222 * can be empty, or a series of subtags 3-8 alphanums in length). A
223 * well-formed locale attribute has the form
224 * <code>[0-9a-zA-Z]{3,8}</code> (it is a single subtag with the same
225 * form as a locale type subtag).
226 *
227 * <p>The Unicode locale extension specifies optional behavior in
228 * locale-sensitive services. Although the LDML specification defines
229 * various keys and values, actual locale-sensitive service
230 * implementations in a Java Runtime Environment might not support any
231 * particular Unicode locale attributes or key/type pairs.
232 *
233 * <h4>Creating a Locale</h4>
234 *
235 * <p>There are several different ways to create a <code>Locale</code>
236 * object.
237 *
238 * <h5>Builder</h5>
239 *
240 * <p>Using {@link Builder} you can construct a <code>Locale</code> object
241 * that conforms to BCP 47 syntax.
242 *
243 * <h5>Constructors</h5>
244 *
245 * <p>The <code>Locale</code> class provides three constructors:
246 * <blockquote>
247 * <pre>
248 * {@link #Locale(String language)}
249 * {@link #Locale(String language, String country)}
250 * {@link #Locale(String language, String country, String variant)}
251 * </pre>
252 * </blockquote>
253 * These constructors allow you to create a <code>Locale</code> object
254 * with language, country and variant, but you cannot specify
255 * script or extensions.
256 *
257 * <h5>Factory Methods</h5>
258 *
259 * <p>The method {@link #forLanguageTag} creates a <code>Locale</code>
260 * object for a well-formed BCP 47 language tag.
261 *
262 * <h5>Locale Constants</h5>
263 *
264 * <p>The <code>Locale</code> class provides a number of convenient constants
265 * that you can use to create <code>Locale</code> objects for commonly used
266 * locales. For example, the following creates a <code>Locale</code> object
267 * for the United States:
268 * <blockquote>
269 * <pre>
270 * Locale.US
271 * </pre>
272 * </blockquote>
273 *
274 * <h4><a id="LocaleMatching">Locale Matching</a></h4>
275 *
276 * <p>If an application or a system is internationalized and provides localized
277 * resources for multiple locales, it sometimes needs to find one or more
278 * locales (or language tags) which meet each user's specific preferences. Note
279 * that a term "language tag" is used interchangeably with "locale" in this
280 * locale matching documentation.
281 *
282 * <p>In order to do matching a user's preferred locales to a set of language
283 * tags, <a href="http://tools.ietf.org/html/rfc4647">RFC 4647 Matching of
284 * Language Tags</a> defines two mechanisms: filtering and lookup.
285 * <em>Filtering</em> is used to get all matching locales, whereas
286 * <em>lookup</em> is to choose the best matching locale.
287 * Matching is done case-insensitively. These matching mechanisms are described
288 * in the following sections.
289 *
290 * <p>A user's preference is called a <em>Language Priority List</em> and is
291 * expressed as a list of language ranges. There are syntactically two types of
292 * language ranges: basic and extended. See
293 * {@link Locale.LanguageRange Locale.LanguageRange} for details.
294 *
295 * <h5>Filtering</h5>
296 *
297 * <p>The filtering operation returns all matching language tags. It is defined
298 * in RFC 4647 as follows:
299 * "In filtering, each language range represents the least specific language
300 * tag (that is, the language tag with fewest number of subtags) that is an
301 * acceptable match. All of the language tags in the matching set of tags will
302 * have an equal or greater number of subtags than the language range. Every
303 * non-wildcard subtag in the language range will appear in every one of the
304 * matching language tags."
305 *
306 * <p>There are two types of filtering: filtering for basic language ranges
307 * (called "basic filtering") and filtering for extended language ranges
308 * (called "extended filtering"). They may return different results by what
309 * kind of language ranges are included in the given Language Priority List.
310 * {@link Locale.FilteringMode} is a parameter to specify how filtering should
311 * be done.
312 *
313 * <h5>Lookup</h5>
314 *
315 * <p>The lookup operation returns the best matching language tags. It is
316 * defined in RFC 4647 as follows:
317 * "By contrast with filtering, each language range represents the most
318 * specific tag that is an acceptable match. The first matching tag found,
319 * according to the user's priority, is considered the closest match and is the
320 * item returned."
321 *
322 * <p>For example, if a Language Priority List consists of two language ranges,
323 * {@code "zh-Hant-TW"} and {@code "en-US"}, in prioritized order, lookup
324 * method progressively searches the language tags below in order to find the
325 * best matching language tag.
326 * <blockquote>
327 * <pre>
328 * 1. zh-Hant-TW
329 * 2. zh-Hant
330 * 3. zh
331 * 4. en-US
332 * 5. en
333 * </pre>
334 * </blockquote>
335 * If there is a language tag which matches completely to a language range
336 * above, the language tag is returned.
337 *
338 * <p>{@code "*"} is the special language range, and it is ignored in lookup.
339 *
340 * <p>If multiple language tags match as a result of the subtag {@code '*'}
341 * included in a language range, the first matching language tag returned by
342 * an {@link Iterator} over a {@link Collection} of language tags is treated as
343 * the best matching one.
344 *
345 * <h4>Use of Locale</h4>
346 *
347 * <p>Once you've created a <code>Locale</code> you can query it for information
348 * about itself. Use <code>getCountry</code> to get the country (or region)
349 * code and <code>getLanguage</code> to get the language code.
350 * You can use <code>getDisplayCountry</code> to get the
351 * name of the country suitable for displaying to the user. Similarly,
352 * you can use <code>getDisplayLanguage</code> to get the name of
353 * the language suitable for displaying to the user. Interestingly,
354 * the <code>getDisplayXXX</code> methods are themselves locale-sensitive
355 * and have two versions: one that uses the default
356 * {@link Locale.Category#DISPLAY DISPLAY} locale and one
357 * that uses the locale specified as an argument.
358 *
359 * <p>The Java Platform provides a number of classes that perform locale-sensitive
360 * operations. For example, the <code>NumberFormat</code> class formats
361 * numbers, currency, and percentages in a locale-sensitive manner. Classes
362 * such as <code>NumberFormat</code> have several convenience methods
363 * for creating a default object of that type. For example, the
364 * <code>NumberFormat</code> class provides these three convenience methods
365 * for creating a default <code>NumberFormat</code> object:
366 * <blockquote>
367 * <pre>
368 * NumberFormat.getInstance()
369 * NumberFormat.getCurrencyInstance()
370 * NumberFormat.getPercentInstance()
371 * </pre>
372 * </blockquote>
373 * Each of these methods has two variants; one with an explicit locale
374 * and one without; the latter uses the default
375 * {@link Locale.Category#FORMAT FORMAT} locale:
376 * <blockquote>
377 * <pre>
378 * NumberFormat.getInstance(myLocale)
379 * NumberFormat.getCurrencyInstance(myLocale)
380 * NumberFormat.getPercentInstance(myLocale)
381 * </pre>
382 * </blockquote>
383 * A <code>Locale</code> is the mechanism for identifying the kind of object
384 * (<code>NumberFormat</code>) that you would like to get. The locale is
385 * <STRONG>just</STRONG> a mechanism for identifying objects,
386 * <STRONG>not</STRONG> a container for the objects themselves.
387 *
388 * <h4>Compatibility</h4>
389 *
390 * <p>In order to maintain compatibility with existing usage, Locale's
391 * constructors retain their behavior prior to the Java Runtime
392 * Environment version 1.7. The same is largely true for the
393 * <code>toString</code> method. Thus Locale objects can continue to
394 * be used as they were. In particular, clients who parse the output
395 * of toString into language, country, and variant fields can continue
396 * to do so (although this is strongly discouraged), although the
397 * variant field will have additional information in it if script or
398 * extensions are present.
399 *
400 * <p>In addition, BCP 47 imposes syntax restrictions that are not
401 * imposed by Locale's constructors. This means that conversions
402 * between some Locales and BCP 47 language tags cannot be made without
403 * losing information. Thus <code>toLanguageTag</code> cannot
404 * represent the state of locales whose language, country, or variant
405 * do not conform to BCP 47.
406 *
407 * <p>Because of these issues, it is recommended that clients migrate
408 * away from constructing non-conforming locales and use the
409 * <code>forLanguageTag</code> and <code>Locale.Builder</code> APIs instead.
410 * Clients desiring a string representation of the complete locale can
411 * then always rely on <code>toLanguageTag</code> for this purpose.
412 *
413 * <h5><a id="special_cases_constructor">Special cases</a></h5>
414 *
415 * <p>For compatibility reasons, two
416 * non-conforming locales are treated as special cases. These are
417 * <b>{@code ja_JP_JP}</b> and <b>{@code th_TH_TH}</b>. These are ill-formed
418 * in BCP 47 since the variants are too short. To ease migration to BCP 47,
419 * these are treated specially during construction. These two cases (and only
420 * these) cause a constructor to generate an extension, all other values behave
421 * exactly as they did prior to Java 7.
422 *
423 * <p>Java has used {@code ja_JP_JP} to represent Japanese as used in
424 * Japan together with the Japanese Imperial calendar. This is now
425 * representable using a Unicode locale extension, by specifying the
426 * Unicode locale key {@code ca} (for "calendar") and type
427 * {@code japanese}. When the Locale constructor is called with the
428 * arguments "ja", "JP", "JP", the extension "u-ca-japanese" is
429 * automatically added.
430 *
431 * <p>Java has used {@code th_TH_TH} to represent Thai as used in
432 * Thailand together with Thai digits. This is also now representable using
433 * a Unicode locale extension, by specifying the Unicode locale key
434 * {@code nu} (for "number") and value {@code thai}. When the Locale
435 * constructor is called with the arguments "th", "TH", "TH", the
436 * extension "u-nu-thai" is automatically added.
437 *
438 * <h5>Serialization</h5>
439 *
440 * <p>During serialization, writeObject writes all fields to the output
441 * stream, including extensions.
442 *
443 * <p>During deserialization, readResolve adds extensions as described
444 * in <a href="#special_cases_constructor">Special Cases</a>, only
445 * for the two cases th_TH_TH and ja_JP_JP.
446 *
447 * <h5>Legacy language codes</h5>
448 *
449 * <p>Locale's constructor has always converted three language codes to
450 * their earlier, obsoleted forms: {@code he} maps to {@code iw},
451 * {@code yi} maps to {@code ji}, and {@code id} maps to
452 * {@code in}. This continues to be the case, in order to not break
453 * backwards compatibility.
454 *
455 * <p>The APIs added in 1.7 map between the old and new language codes,
456 * maintaining the old codes internal to Locale (so that
457 * <code>getLanguage</code> and <code>toString</code> reflect the old
458 * code), but using the new codes in the BCP 47 language tag APIs (so
459 * that <code>toLanguageTag</code> reflects the new one). This
460 * preserves the equivalence between Locales no matter which code or
461 * API is used to construct them. Java's default resource bundle
462 * lookup mechanism also implements this mapping, so that resources
463 * can be named using either convention, see {@link ResourceBundle.Control}.
464 *
465 * <h5>Three-letter language/country(region) codes</h5>
466 *
467 * <p>The Locale constructors have always specified that the language
468 * and the country param be two characters in length, although in
469 * practice they have accepted any length. The specification has now
470 * been relaxed to allow language codes of two to eight characters and
471 * country (region) codes of two to three characters, and in
472 * particular, three-letter language codes and three-digit region
473 * codes as specified in the IANA Language Subtag Registry. For
474 * compatibility, the implementation still does not impose a length
475 * constraint.
476 *
477 * @see Builder
478 * @see ResourceBundle
479 * @see java.text.Format
480 * @see java.text.NumberFormat
481 * @see java.text.Collator
482 * @author Mark Davis
483 * @since 1.1
484 */
485 public final class Locale implements Cloneable, Serializable {
486
487 private static final Cache LOCALECACHE = new Cache();
488
489 /** Useful constant for language.
490 */
491 public static final Locale ENGLISH = createConstant("en", "");
492
493 /** Useful constant for language.
494 */
495 public static final Locale FRENCH = createConstant("fr", "");
496
497 /** Useful constant for language.
498 */
499 public static final Locale GERMAN = createConstant("de", "");
500
501 /** Useful constant for language.
502 */
503 public static final Locale ITALIAN = createConstant("it", "");
504
505 /** Useful constant for language.
506 */
507 public static final Locale JAPANESE = createConstant("ja", "");
508
509 /** Useful constant for language.
510 */
511 public static final Locale KOREAN = createConstant("ko", "");
512
513 /** Useful constant for language.
514 */
515 public static final Locale CHINESE = createConstant("zh", "");
516
517 /** Useful constant for language.
518 */
519 public static final Locale SIMPLIFIED_CHINESE = createConstant("zh", "CN");
520
521 /** Useful constant for language.
522 */
523 public static final Locale TRADITIONAL_CHINESE = createConstant("zh", "TW");
524
525 /** Useful constant for country.
526 */
527 public static final Locale FRANCE = createConstant("fr", "FR");
528
529 /** Useful constant for country.
530 */
531 public static final Locale GERMANY = createConstant("de", "DE");
532
533 /** Useful constant for country.
534 */
535 public static final Locale ITALY = createConstant("it", "IT");
536
537 /** Useful constant for country.
538 */
539 public static final Locale JAPAN = createConstant("ja", "JP");
540
541 /** Useful constant for country.
542 */
543 public static final Locale KOREA = createConstant("ko", "KR");
544
545 /** Useful constant for country.
546 */
547 public static final Locale CHINA = SIMPLIFIED_CHINESE;
548
549 /** Useful constant for country.
550 */
551 public static final Locale PRC = SIMPLIFIED_CHINESE;
552
553 /** Useful constant for country.
554 */
555 public static final Locale TAIWAN = TRADITIONAL_CHINESE;
556
557 /** Useful constant for country.
558 */
559 public static final Locale UK = createConstant("en", "GB");
560
561 /** Useful constant for country.
562 */
563 public static final Locale US = createConstant("en", "US");
564
565 /** Useful constant for country.
566 */
567 public static final Locale CANADA = createConstant("en", "CA");
568
569 /** Useful constant for country.
570 */
571 public static final Locale CANADA_FRENCH = createConstant("fr", "CA");
572
573 /**
574 * Useful constant for the root locale. The root locale is the locale whose
575 * language, country, and variant are empty ("") strings. This is regarded
576 * as the base locale of all locales, and is used as the language/country
577 * neutral locale for the locale sensitive operations.
578 *
579 * @since 1.6
580 */
581 public static final Locale ROOT = createConstant("", "");
582
583 /**
584 * The key for the private use extension ('x').
585 *
586 * @see #getExtension(char)
587 * @see Builder#setExtension(char, String)
588 * @since 1.7
589 */
590 public static final char PRIVATE_USE_EXTENSION = 'x';
591
592 /**
593 * The key for Unicode locale extension ('u').
594 *
595 * @see #getExtension(char)
596 * @see Builder#setExtension(char, String)
597 * @since 1.7
598 */
599 public static final char UNICODE_LOCALE_EXTENSION = 'u';
600
601 /** serialization ID
602 */
603 static final long serialVersionUID = 9149081749638150636L;
604
605 /**
606 * Enum for specifying the type defined in ISO 3166. This enum is used to
607 * retrieve the two-letter ISO3166-1 alpha-2, three-letter ISO3166-1
608 * alpha-3, four-letter ISO3166-3 country codes.
609 *
610 * @see #getISOCountries(Locale.IsoCountryCode)
611 * @since 9
612 */
613 public static enum IsoCountryCode {
614 /**
615 * PART1_ALPHA2 is used to represent the ISO3166-1 alpha-2 two letter
616 * country codes.
617 */
618 PART1_ALPHA2 {
619 @Override
620 Set<String> createCountryCodeSet() {
621 return Set.of(Locale.getISOCountries());
622 }
623 },
624
625 /**
626 *
627 * PART1_ALPHA3 is used to represent the ISO3166-1 alpha-3 three letter
628 * country codes.
629 */
630 PART1_ALPHA3 {
631 @Override
632 Set<String> createCountryCodeSet() {
633 return LocaleISOData.computeISO3166_1Alpha3Countries();
634 }
635 },
636
637 /**
638 * PART3 is used to represent the ISO3166-3 four letter country codes.
639 */
640 PART3 {
641 @Override
642 Set<String> createCountryCodeSet() {
643 return Set.of(LocaleISOData.ISO3166_3);
644 }
645 };
646
647 /**
648 * Concrete implementation of this method attempts to compute value
649 * for iso3166CodesMap for each IsoCountryCode type key.
650 */
651 abstract Set<String> createCountryCodeSet();
652
653 /**
654 * Map to hold country codes for each ISO3166 part.
655 */
656 private static Map<IsoCountryCode, Set<String>> iso3166CodesMap = new ConcurrentHashMap<>();
657
658 /**
659 * This method is called from Locale class to retrieve country code set
660 * for getISOCountries(type)
661 */
662 static Set<String> retrieveISOCountryCodes(IsoCountryCode type) {
663 return iso3166CodesMap.computeIfAbsent(type, IsoCountryCode::createCountryCodeSet);
664 }
665 }
666
667 /**
668 * Display types for retrieving localized names from the name providers.
669 */
670 private static final int DISPLAY_LANGUAGE = 0;
671 private static final int DISPLAY_COUNTRY = 1;
672 private static final int DISPLAY_VARIANT = 2;
673 private static final int DISPLAY_SCRIPT = 3;
674 private static final int DISPLAY_UEXT_KEY = 4;
675 private static final int DISPLAY_UEXT_TYPE = 5;
676
677 /**
678 * Private constructor used by getInstance method
679 */
680 private Locale(BaseLocale baseLocale, LocaleExtensions extensions) {
681 this.baseLocale = baseLocale;
682 this.localeExtensions = extensions;
683 }
684
685 /**
686 * Construct a locale from language, country and variant.
687 * This constructor normalizes the language value to lowercase and
688 * the country value to uppercase.
689 * <p>
690 * <b>Note:</b>
691 * <ul>
692 * <li>ISO 639 is not a stable standard; some of the language codes it defines
693 * (specifically "iw", "ji", and "in") have changed. This constructor accepts both the
694 * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
695 * API on Locale will return only the OLD codes.
696 * <li>For backward compatibility reasons, this constructor does not make
697 * any syntactic checks on the input.
698 * <li>The two cases ("ja", "JP", "JP") and ("th", "TH", "TH") are handled specially,
699 * see <a href="#special_cases_constructor">Special Cases</a> for more information.
700 * </ul>
701 *
702 * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
703 * up to 8 characters in length. See the <code>Locale</code> class description about
704 * valid language values.
705 * @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
706 * See the <code>Locale</code> class description about valid country values.
707 * @param variant Any arbitrary value used to indicate a variation of a <code>Locale</code>.
708 * See the <code>Locale</code> class description for the details.
709 * @exception NullPointerException thrown if any argument is null.
710 */
711 public Locale(String language, String country, String variant) {
712 if (language== null || country == null || variant == null) {
713 throw new NullPointerException();
714 }
715 baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant);
716 localeExtensions = getCompatibilityExtensions(language, "", country, variant);
717 }
718
719 /**
720 * Construct a locale from language and country.
721 * This constructor normalizes the language value to lowercase and
722 * the country value to uppercase.
723 * <p>
724 * <b>Note:</b>
725 * <ul>
726 * <li>ISO 639 is not a stable standard; some of the language codes it defines
727 * (specifically "iw", "ji", and "in") have changed. This constructor accepts both the
728 * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
729 * API on Locale will return only the OLD codes.
730 * <li>For backward compatibility reasons, this constructor does not make
731 * any syntactic checks on the input.
732 * </ul>
733 *
734 * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
735 * up to 8 characters in length. See the <code>Locale</code> class description about
736 * valid language values.
737 * @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
738 * See the <code>Locale</code> class description about valid country values.
739 * @exception NullPointerException thrown if either argument is null.
740 */
741 public Locale(String language, String country) {
742 this(language, country, "");
743 }
744
745 /**
746 * Construct a locale from a language code.
747 * This constructor normalizes the language value to lowercase.
748 * <p>
749 * <b>Note:</b>
750 * <ul>
751 * <li>ISO 639 is not a stable standard; some of the language codes it defines
752 * (specifically "iw", "ji", and "in") have changed. This constructor accepts both the
753 * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
754 * API on Locale will return only the OLD codes.
755 * <li>For backward compatibility reasons, this constructor does not make
756 * any syntactic checks on the input.
757 * </ul>
758 *
759 * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
760 * up to 8 characters in length. See the <code>Locale</code> class description about
761 * valid language values.
762 * @exception NullPointerException thrown if argument is null.
763 * @since 1.4
764 */
765 public Locale(String language) {
766 this(language, "", "");
767 }
768
769 /**
770 * This method must be called only for creating the Locale.*
771 * constants due to making shortcuts.
772 */
773 private static Locale createConstant(String lang, String country) {
774 BaseLocale base = BaseLocale.createInstance(lang, country);
775 return getInstance(base, null);
776 }
777
778 /**
779 * Returns a <code>Locale</code> constructed from the given
780 * <code>language</code>, <code>country</code> and
781 * <code>variant</code>. If the same <code>Locale</code> instance
782 * is available in the cache, then that instance is
783 * returned. Otherwise, a new <code>Locale</code> instance is
784 * created and cached.
785 *
786 * @param language lowercase 2 to 8 language code.
787 * @param country uppercase two-letter ISO-3166 code and numeric-3 UN M.49 area code.
788 * @param variant vendor and browser specific code. See class description.
789 * @return the <code>Locale</code> instance requested
790 * @exception NullPointerException if any argument is null.
791 */
792 static Locale getInstance(String language, String country, String variant) {
793 return getInstance(language, "", country, variant, null);
794 }
795
796 static Locale getInstance(String language, String script, String country,
797 String variant, LocaleExtensions extensions) {
798 if (language== null || script == null || country == null || variant == null) {
799 throw new NullPointerException();
800 }
801
802 if (extensions == null) {
803 extensions = getCompatibilityExtensions(language, script, country, variant);
804 }
805
806 BaseLocale baseloc = BaseLocale.getInstance(language, script, country, variant);
807 return getInstance(baseloc, extensions);
808 }
809
810 static Locale getInstance(BaseLocale baseloc, LocaleExtensions extensions) {
811 if (extensions == null) {
812 return LOCALECACHE.get(baseloc);
813 } else {
814 LocaleKey key = new LocaleKey(baseloc, extensions);
815 return LOCALECACHE.get(key);
816 }
817 }
818
819 private static class Cache extends LocaleObjectCache<Object, Locale> {
820 private Cache() {
821 }
822
823 @Override
824 protected Locale createObject(Object key) {
825 if (key instanceof BaseLocale) {
826 return new Locale((BaseLocale)key, null);
827 } else {
828 LocaleKey lk = (LocaleKey)key;
829 return new Locale(lk.base, lk.exts);
830 }
831 }
832 }
833
834 private static final class LocaleKey {
835 private final BaseLocale base;
836 private final LocaleExtensions exts;
837 private final int hash;
838
839 private LocaleKey(BaseLocale baseLocale, LocaleExtensions extensions) {
840 base = baseLocale;
841 exts = extensions;
842
843 // Calculate the hash value here because it's always used.
844 int h = base.hashCode();
845 if (exts != null) {
846 h ^= exts.hashCode();
847 }
848 hash = h;
849 }
850
851 @Override
852 public boolean equals(Object obj) {
853 if (this == obj) {
854 return true;
855 }
856 if (!(obj instanceof LocaleKey)) {
857 return false;
858 }
859 LocaleKey other = (LocaleKey)obj;
860 if (hash != other.hash || !base.equals(other.base)) {
861 return false;
862 }
863 if (exts == null) {
864 return other.exts == null;
865 }
866 return exts.equals(other.exts);
867 }
868
869 @Override
870 public int hashCode() {
871 return hash;
872 }
873 }
874
875 /**
876 * Gets the current value of the default locale for this instance
877 * of the Java Virtual Machine.
878 * <p>
879 * The Java Virtual Machine sets the default locale during startup
880 * based on the host environment. It is used by many locale-sensitive
881 * methods if no locale is explicitly specified.
882 * It can be changed using the
883 * {@link #setDefault(java.util.Locale) setDefault} method.
884 *
885 * @return the default locale for this instance of the Java Virtual Machine
886 */
887 public static Locale getDefault() {
888 // do not synchronize this method - see 4071298
889 return defaultLocale;
890 }
891
892 /**
893 * Gets the current value of the default locale for the specified Category
894 * for this instance of the Java Virtual Machine.
895 * <p>
896 * The Java Virtual Machine sets the default locale during startup based
897 * on the host environment. It is used by many locale-sensitive methods
898 * if no locale is explicitly specified. It can be changed using the
899 * setDefault(Locale.Category, Locale) method.
900 *
901 * @param category - the specified category to get the default locale
902 * @throws NullPointerException if category is null
903 * @return the default locale for the specified Category for this instance
904 * of the Java Virtual Machine
905 * @see #setDefault(Locale.Category, Locale)
906 * @since 1.7
907 */
908 public static Locale getDefault(Locale.Category category) {
909 // do not synchronize this method - see 4071298
910 switch (category) {
911 case DISPLAY:
912 if (defaultDisplayLocale == null) {
913 synchronized(Locale.class) {
914 if (defaultDisplayLocale == null) {
915 defaultDisplayLocale = initDefault(category);
916 }
917 }
918 }
919 return defaultDisplayLocale;
920 case FORMAT:
921 if (defaultFormatLocale == null) {
922 synchronized(Locale.class) {
923 if (defaultFormatLocale == null) {
924 defaultFormatLocale = initDefault(category);
925 }
926 }
927 }
928 return defaultFormatLocale;
929 default:
930 assert false: "Unknown Category";
931 }
932 return getDefault();
933 }
934
935 private static Locale initDefault() {
936 String language, region, script, country, variant;
937 Properties props = GetPropertyAction.privilegedGetProperties();
938 language = props.getProperty("user.language", "en");
939 // for compatibility, check for old user.region property
940 region = props.getProperty("user.region");
941 if (region != null) {
942 // region can be of form country, country_variant, or _variant
943 int i = region.indexOf('_');
944 if (i >= 0) {
945 country = region.substring(0, i);
946 variant = region.substring(i + 1);
947 } else {
948 country = region;
949 variant = "";
950 }
951 script = "";
952 } else {
953 script = props.getProperty("user.script", "");
954 country = props.getProperty("user.country", "");
955 variant = props.getProperty("user.variant", "");
956 }
957
958 return getInstance(language, script, country, variant,
959 getDefaultExtensions(props.getProperty("user.extensions", ""))
960 .orElse(null));
961 }
962
963 private static Locale initDefault(Locale.Category category) {
964 Properties props = GetPropertyAction.privilegedGetProperties();
965
966 return getInstance(
967 props.getProperty(category.languageKey,
968 defaultLocale.getLanguage()),
969 props.getProperty(category.scriptKey,
970 defaultLocale.getScript()),
971 props.getProperty(category.countryKey,
972 defaultLocale.getCountry()),
973 props.getProperty(category.variantKey,
974 defaultLocale.getVariant()),
975 getDefaultExtensions(props.getProperty(category.extensionsKey, ""))
976 .orElse(defaultLocale.getLocaleExtensions()));
977 }
978
979 private static Optional<LocaleExtensions> getDefaultExtensions(String extensionsProp) {
980 LocaleExtensions exts = null;
981
982 try {
983 exts = new InternalLocaleBuilder()
984 .setExtensions(extensionsProp)
985 .getLocaleExtensions();
986 } catch (LocaleSyntaxException e) {
987 // just ignore this incorrect property
988 }
989
990 return Optional.ofNullable(exts);
991 }
992
993 /**
994 * Sets the default locale for this instance of the Java Virtual Machine.
995 * This does not affect the host locale.
996 * <p>
997 * If there is a security manager, its <code>checkPermission</code>
998 * method is called with a <code>PropertyPermission("user.language", "write")</code>
999 * permission before the default locale is changed.
1000 * <p>
1001 * The Java Virtual Machine sets the default locale during startup
1002 * based on the host environment. It is used by many locale-sensitive
1003 * methods if no locale is explicitly specified.
1004 * <p>
1005 * Since changing the default locale may affect many different areas
1006 * of functionality, this method should only be used if the caller
1007 * is prepared to reinitialize locale-sensitive code running
1008 * within the same Java Virtual Machine.
1009 * <p>
1010 * By setting the default locale with this method, all of the default
1011 * locales for each Category are also set to the specified default locale.
1012 *
1013 * @throws SecurityException
1014 * if a security manager exists and its
1015 * <code>checkPermission</code> method doesn't allow the operation.
1016 * @throws NullPointerException if <code>newLocale</code> is null
1017 * @param newLocale the new default locale
1018 * @see SecurityManager#checkPermission
1019 * @see java.util.PropertyPermission
1020 */
1021 public static synchronized void setDefault(Locale newLocale) {
1022 setDefault(Category.DISPLAY, newLocale);
1023 setDefault(Category.FORMAT, newLocale);
1024 defaultLocale = newLocale;
1025 }
1026
1027 /**
1028 * Sets the default locale for the specified Category for this instance
1029 * of the Java Virtual Machine. This does not affect the host locale.
1030 * <p>
1031 * If there is a security manager, its checkPermission method is called
1032 * with a PropertyPermission("user.language", "write") permission before
1033 * the default locale is changed.
1034 * <p>
1035 * The Java Virtual Machine sets the default locale during startup based
1036 * on the host environment. It is used by many locale-sensitive methods
1037 * if no locale is explicitly specified.
1038 * <p>
1039 * Since changing the default locale may affect many different areas of
1040 * functionality, this method should only be used if the caller is
1041 * prepared to reinitialize locale-sensitive code running within the
1042 * same Java Virtual Machine.
1043 *
1044 * @param category - the specified category to set the default locale
1045 * @param newLocale - the new default locale
1046 * @throws SecurityException if a security manager exists and its
1047 * checkPermission method doesn't allow the operation.
1048 * @throws NullPointerException if category and/or newLocale is null
1049 * @see SecurityManager#checkPermission(java.security.Permission)
1050 * @see PropertyPermission
1051 * @see #getDefault(Locale.Category)
1052 * @since 1.7
1053 */
1054 public static synchronized void setDefault(Locale.Category category,
1055 Locale newLocale) {
1056 if (category == null)
1057 throw new NullPointerException("Category cannot be NULL");
1058 if (newLocale == null)
1059 throw new NullPointerException("Can't set default locale to NULL");
1060
1061 SecurityManager sm = System.getSecurityManager();
1062 if (sm != null) sm.checkPermission(new PropertyPermission
1063 ("user.language", "write"));
1064 switch (category) {
1065 case DISPLAY:
1066 defaultDisplayLocale = newLocale;
1067 break;
1068 case FORMAT:
1069 defaultFormatLocale = newLocale;
1070 break;
1071 default:
1072 assert false: "Unknown Category";
1073 }
1074 }
1075
1076 /**
1077 * Returns an array of all installed locales.
1078 * The returned array represents the union of locales supported
1079 * by the Java runtime environment and by installed
1080 * {@link java.util.spi.LocaleServiceProvider LocaleServiceProvider}
1081 * implementations. It must contain at least a <code>Locale</code>
1082 * instance equal to {@link java.util.Locale#US Locale.US}.
1083 *
1084 * @return An array of installed locales.
1085 */
1086 public static Locale[] getAvailableLocales() {
1087 return LocaleServiceProviderPool.getAllAvailableLocales();
1088 }
1089
1090 /**
1091 * Returns a list of all 2-letter country codes defined in ISO 3166.
1092 * Can be used to create Locales.
1093 * This method is equivalent to {@link #getISOCountries(Locale.IsoCountryCode type)}
1094 * with {@code type} {@link IsoCountryCode#PART1_ALPHA2}.
1095 * <p>
1096 * <b>Note:</b> The <code>Locale</code> class also supports other codes for
1097 * country (region), such as 3-letter numeric UN M.49 area codes.
1098 * Therefore, the list returned by this method does not contain ALL valid
1099 * codes that can be used to create Locales.
1100 * <p>
1101 * Note that this method does not return obsolete 2-letter country codes.
1102 * ISO3166-3 codes which designate country codes for those obsolete codes,
1103 * can be retrieved from {@link #getISOCountries(Locale.IsoCountryCode type)} with
1104 * {@code type} {@link IsoCountryCode#PART3}.
1105 * @return An array of ISO 3166 two-letter country codes.
1106 */
1107 public static String[] getISOCountries() {
1108 if (isoCountries == null) {
1109 isoCountries = getISO2Table(LocaleISOData.isoCountryTable);
1110 }
1111 String[] result = new String[isoCountries.length];
1112 System.arraycopy(isoCountries, 0, result, 0, isoCountries.length);
1113 return result;
1114 }
1115
1116 /**
1117 * Returns a {@code Set} of ISO3166 country codes for the specified type.
1118 *
1119 * @param type {@link Locale.IsoCountryCode} specified ISO code type.
1120 * @see java.util.Locale.IsoCountryCode
1121 * @throws NullPointerException if type is null
1122 * @return a {@code Set} of ISO country codes for the specified type.
1123 * @since 9
1124 */
1125 public static Set<String> getISOCountries(IsoCountryCode type) {
1126 Objects.requireNonNull(type);
1127 return IsoCountryCode.retrieveISOCountryCodes(type);
1128 }
1129
1130 /**
1131 * Returns a list of all 2-letter language codes defined in ISO 639.
1132 * Can be used to create Locales.
1133 * <p>
1134 * <b>Note:</b>
1135 * <ul>
1136 * <li>ISO 639 is not a stable standard— some languages' codes have changed.
1137 * The list this function returns includes both the new and the old codes for the
1138 * languages whose codes have changed.
1139 * <li>The <code>Locale</code> class also supports language codes up to
1140 * 8 characters in length. Therefore, the list returned by this method does
1141 * not contain ALL valid codes that can be used to create Locales.
1142 * </ul>
1143 *
1144 * @return An array of ISO 639 two-letter language codes.
1145 */
1146 public static String[] getISOLanguages() {
1147 if (isoLanguages == null) {
1148 isoLanguages = getISO2Table(LocaleISOData.isoLanguageTable);
1149 }
1150 String[] result = new String[isoLanguages.length];
1151 System.arraycopy(isoLanguages, 0, result, 0, isoLanguages.length);
1152 return result;
1153 }
1154
1155 private static String[] getISO2Table(String table) {
1156 int len = table.length() / 5;
1157 String[] isoTable = new String[len];
1158 for (int i = 0, j = 0; i < len; i++, j += 5) {
1159 isoTable[i] = table.substring(j, j + 2);
1160 }
1161 return isoTable;
1162 }
1163
1164 /**
1165 * Returns the language code of this Locale.
1166 *
1167 * <p><b>Note:</b> ISO 639 is not a stable standard— some languages' codes have changed.
1168 * Locale's constructor recognizes both the new and the old codes for the languages
1169 * whose codes have changed, but this function always returns the old code. If you
1170 * want to check for a specific language whose code has changed, don't do
1171 * <pre>
1172 * if (locale.getLanguage().equals("he")) // BAD!
1173 * ...
1174 * </pre>
1175 * Instead, do
1176 * <pre>
1177 * if (locale.getLanguage().equals(new Locale("he").getLanguage()))
1178 * ...
1179 * </pre>
1180 * @return The language code, or the empty string if none is defined.
1181 * @see #getDisplayLanguage
1182 */
1183 public String getLanguage() {
1184 return baseLocale.getLanguage();
1185 }
1186
1187 /**
1188 * Returns the script for this locale, which should
1189 * either be the empty string or an ISO 15924 4-letter script
1190 * code. The first letter is uppercase and the rest are
1191 * lowercase, for example, 'Latn', 'Cyrl'.
1192 *
1193 * @return The script code, or the empty string if none is defined.
1194 * @see #getDisplayScript
1195 * @since 1.7
1196 */
1197 public String getScript() {
1198 return baseLocale.getScript();
1199 }
1200
1201 /**
1202 * Returns the country/region code for this locale, which should
1203 * either be the empty string, an uppercase ISO 3166 2-letter code,
1204 * or a UN M.49 3-digit code.
1205 *
1206 * @return The country/region code, or the empty string if none is defined.
1207 * @see #getDisplayCountry
1208 */
1209 public String getCountry() {
1210 return baseLocale.getRegion();
1211 }
1212
1213 /**
1214 * Returns the variant code for this locale.
1215 *
1216 * @return The variant code, or the empty string if none is defined.
1217 * @see #getDisplayVariant
1218 */
1219 public String getVariant() {
1220 return baseLocale.getVariant();
1221 }
1222
1223 /**
1224 * Returns {@code true} if this {@code Locale} has any <a href="#def_extensions">
1225 * extensions</a>.
1226 *
1227 * @return {@code true} if this {@code Locale} has any extensions
1228 * @since 1.8
1229 */
1230 public boolean hasExtensions() {
1231 return localeExtensions != null;
1232 }
1233
1234 /**
1235 * Returns a copy of this {@code Locale} with no <a href="#def_extensions">
1236 * extensions</a>. If this {@code Locale} has no extensions, this {@code Locale}
1237 * is returned.
1238 *
1239 * @return a copy of this {@code Locale} with no extensions, or {@code this}
1240 * if {@code this} has no extensions
1241 * @since 1.8
1242 */
1243 public Locale stripExtensions() {
1244 return hasExtensions() ? Locale.getInstance(baseLocale, null) : this;
1245 }
1246
1247 /**
1248 * Returns the extension (or private use) value associated with
1249 * the specified key, or null if there is no extension
1250 * associated with the key. To be well-formed, the key must be one
1251 * of <code>[0-9A-Za-z]</code>. Keys are case-insensitive, so
1252 * for example 'z' and 'Z' represent the same extension.
1253 *
1254 * @param key the extension key
1255 * @return The extension, or null if this locale defines no
1256 * extension for the specified key.
1257 * @throws IllegalArgumentException if key is not well-formed
1258 * @see #PRIVATE_USE_EXTENSION
1259 * @see #UNICODE_LOCALE_EXTENSION
1260 * @since 1.7
1261 */
1262 public String getExtension(char key) {
1263 if (!LocaleExtensions.isValidKey(key)) {
1264 throw new IllegalArgumentException("Ill-formed extension key: " + key);
1265 }
1266 return hasExtensions() ? localeExtensions.getExtensionValue(key) : null;
1267 }
1268
1269 /**
1270 * Returns the set of extension keys associated with this locale, or the
1271 * empty set if it has no extensions. The returned set is unmodifiable.
1272 * The keys will all be lower-case.
1273 *
1274 * @return The set of extension keys, or the empty set if this locale has
1275 * no extensions.
1276 * @since 1.7
1277 */
1278 public Set<Character> getExtensionKeys() {
1279 if (!hasExtensions()) {
1280 return Collections.emptySet();
1281 }
1282 return localeExtensions.getKeys();
1283 }
1284
1285 /**
1286 * Returns the set of unicode locale attributes associated with
1287 * this locale, or the empty set if it has no attributes. The
1288 * returned set is unmodifiable.
1289 *
1290 * @return The set of attributes.
1291 * @since 1.7
1292 */
1293 public Set<String> getUnicodeLocaleAttributes() {
1294 if (!hasExtensions()) {
1295 return Collections.emptySet();
1296 }
1297 return localeExtensions.getUnicodeLocaleAttributes();
1298 }
1299
1300 /**
1301 * Returns the Unicode locale type associated with the specified Unicode locale key
1302 * for this locale. Returns the empty string for keys that are defined with no type.
1303 * Returns null if the key is not defined. Keys are case-insensitive. The key must
1304 * be two alphanumeric characters ([0-9a-zA-Z]), or an IllegalArgumentException is
1305 * thrown.
1306 *
1307 * @param key the Unicode locale key
1308 * @return The Unicode locale type associated with the key, or null if the
1309 * locale does not define the key.
1310 * @throws IllegalArgumentException if the key is not well-formed
1311 * @throws NullPointerException if <code>key</code> is null
1312 * @since 1.7
1313 */
1314 public String getUnicodeLocaleType(String key) {
1315 if (!isUnicodeExtensionKey(key)) {
1316 throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key);
1317 }
1318 return hasExtensions() ? localeExtensions.getUnicodeLocaleType(key) : null;
1319 }
1320
1321 /**
1322 * Returns the set of Unicode locale keys defined by this locale, or the empty set if
1323 * this locale has none. The returned set is immutable. Keys are all lower case.
1324 *
1325 * @return The set of Unicode locale keys, or the empty set if this locale has
1326 * no Unicode locale keywords.
1327 * @since 1.7
1328 */
1329 public Set<String> getUnicodeLocaleKeys() {
1330 if (localeExtensions == null) {
1331 return Collections.emptySet();
1332 }
1333 return localeExtensions.getUnicodeLocaleKeys();
1334 }
1335
1336 /**
1337 * Package locale method returning the Locale's BaseLocale,
1338 * used by ResourceBundle
1339 * @return base locale of this Locale
1340 */
1341 BaseLocale getBaseLocale() {
1342 return baseLocale;
1343 }
1344
1345 /**
1346 * Package private method returning the Locale's LocaleExtensions,
1347 * used by ResourceBundle.
1348 * @return locale extensions of this Locale,
1349 * or {@code null} if no extensions are defined
1350 */
1351 LocaleExtensions getLocaleExtensions() {
1352 return localeExtensions;
1353 }
1354
1355 /**
1356 * Returns a string representation of this <code>Locale</code>
1357 * object, consisting of language, country, variant, script,
1358 * and extensions as below:
1359 * <blockquote>
1360 * language + "_" + country + "_" + (variant + "_#" | "#") + script + "_" + extensions
1361 * </blockquote>
1362 *
1363 * Language is always lower case, country is always upper case, script is always title
1364 * case, and extensions are always lower case. Extensions and private use subtags
1365 * will be in canonical order as explained in {@link #toLanguageTag}.
1366 *
1367 * <p>When the locale has neither script nor extensions, the result is the same as in
1368 * Java 6 and prior.
1369 *
1370 * <p>If both the language and country fields are missing, this function will return
1371 * the empty string, even if the variant, script, or extensions field is present (you
1372 * can't have a locale with just a variant, the variant must accompany a well-formed
1373 * language or country code).
1374 *
1375 * <p>If script or extensions are present and variant is missing, no underscore is
1376 * added before the "#".
1377 *
1378 * <p>This behavior is designed to support debugging and to be compatible with
1379 * previous uses of <code>toString</code> that expected language, country, and variant
1380 * fields only. To represent a Locale as a String for interchange purposes, use
1381 * {@link #toLanguageTag}.
1382 *
1383 * <p>Examples: <ul>
1384 * <li>{@code en}</li>
1385 * <li>{@code de_DE}</li>
1386 * <li>{@code _GB}</li>
1387 * <li>{@code en_US_WIN}</li>
1388 * <li>{@code de__POSIX}</li>
1389 * <li>{@code zh_CN_#Hans}</li>
1390 * <li>{@code zh_TW_#Hant_x-java}</li>
1391 * <li>{@code th_TH_TH_#u-nu-thai}</li></ul>
1392 *
1393 * @return A string representation of the Locale, for debugging.
1394 * @see #getDisplayName
1395 * @see #toLanguageTag
1396 */
1397 @Override
1398 public final String toString() {
1399 boolean l = !baseLocale.getLanguage().isEmpty();
1400 boolean s = !baseLocale.getScript().isEmpty();
1401 boolean r = !baseLocale.getRegion().isEmpty();
1402 boolean v = !baseLocale.getVariant().isEmpty();
1403 boolean e = localeExtensions != null && !localeExtensions.getID().isEmpty();
1404
1405 StringBuilder result = new StringBuilder(baseLocale.getLanguage());
1406 if (r || (l && (v || s || e))) {
1407 result.append('_')
1408 .append(baseLocale.getRegion()); // This may just append '_'
1409 }
1410 if (v && (l || r)) {
1411 result.append('_')
1412 .append(baseLocale.getVariant());
1413 }
1414
1415 if (s && (l || r)) {
1416 result.append("_#")
1417 .append(baseLocale.getScript());
1418 }
1419
1420 if (e && (l || r)) {
1421 result.append('_');
1422 if (!s) {
1423 result.append('#');
1424 }
1425 result.append(localeExtensions.getID());
1426 }
1427
1428 return result.toString();
1429 }
1430
1431 /**
1432 * Returns a well-formed IETF BCP 47 language tag representing
1433 * this locale.
1434 *
1435 * <p>If this <code>Locale</code> has a language, country, or
1436 * variant that does not satisfy the IETF BCP 47 language tag
1437 * syntax requirements, this method handles these fields as
1438 * described below:
1439 *
1440 * <p><b>Language:</b> If language is empty, or not <a
1441 * href="#def_language" >well-formed</a> (for example "a" or
1442 * "e2"), it will be emitted as "und" (Undetermined).
1443 *
1444 * <p><b>Country:</b> If country is not <a
1445 * href="#def_region">well-formed</a> (for example "12" or "USA"),
1446 * it will be omitted.
1447 *
1448 * <p><b>Variant:</b> If variant <b>is</b> <a
1449 * href="#def_variant">well-formed</a>, each sub-segment
1450 * (delimited by '-' or '_') is emitted as a subtag. Otherwise:
1451 * <ul>
1452 *
1453 * <li>if all sub-segments match <code>[0-9a-zA-Z]{1,8}</code>
1454 * (for example "WIN" or "Oracle_JDK_Standard_Edition"), the first
1455 * ill-formed sub-segment and all following will be appended to
1456 * the private use subtag. The first appended subtag will be
1457 * "lvariant", followed by the sub-segments in order, separated by
1458 * hyphen. For example, "x-lvariant-WIN",
1459 * "Oracle-x-lvariant-JDK-Standard-Edition".
1460 *
1461 * <li>if any sub-segment does not match
1462 * <code>[0-9a-zA-Z]{1,8}</code>, the variant will be truncated
1463 * and the problematic sub-segment and all following sub-segments
1464 * will be omitted. If the remainder is non-empty, it will be
1465 * emitted as a private use subtag as above (even if the remainder
1466 * turns out to be well-formed). For example,
1467 * "Solaris_isjustthecoolestthing" is emitted as
1468 * "x-lvariant-Solaris", not as "solaris".</li></ul>
1469 *
1470 * <p><b>Special Conversions:</b> Java supports some old locale
1471 * representations, including deprecated ISO language codes,
1472 * for compatibility. This method performs the following
1473 * conversions:
1474 * <ul>
1475 *
1476 * <li>Deprecated ISO language codes "iw", "ji", and "in" are
1477 * converted to "he", "yi", and "id", respectively.
1478 *
1479 * <li>A locale with language "no", country "NO", and variant
1480 * "NY", representing Norwegian Nynorsk (Norway), is converted
1481 * to a language tag "nn-NO".</li></ul>
1482 *
1483 * <p><b>Note:</b> Although the language tag created by this
1484 * method is well-formed (satisfies the syntax requirements
1485 * defined by the IETF BCP 47 specification), it is not
1486 * necessarily a valid BCP 47 language tag. For example,
1487 * <pre>
1488 * new Locale("xx", "YY").toLanguageTag();</pre>
1489 *
1490 * will return "xx-YY", but the language subtag "xx" and the
1491 * region subtag "YY" are invalid because they are not registered
1492 * in the IANA Language Subtag Registry.
1493 *
1494 * @return a BCP47 language tag representing the locale
1495 * @see #forLanguageTag(String)
1496 * @since 1.7
1497 */
1498 public String toLanguageTag() {
1499 if (languageTag != null) {
1500 return languageTag;
1501 }
1502
1503 LanguageTag tag = LanguageTag.parseLocale(baseLocale, localeExtensions);
1504 StringBuilder buf = new StringBuilder();
1505
1506 String subtag = tag.getLanguage();
1507 if (!subtag.isEmpty()) {
1508 buf.append(LanguageTag.canonicalizeLanguage(subtag));
1509 }
1510
1511 subtag = tag.getScript();
1512 if (!subtag.isEmpty()) {
1513 buf.append(LanguageTag.SEP);
1514 buf.append(LanguageTag.canonicalizeScript(subtag));
1515 }
1516
1517 subtag = tag.getRegion();
1518 if (!subtag.isEmpty()) {
1519 buf.append(LanguageTag.SEP);
1520 buf.append(LanguageTag.canonicalizeRegion(subtag));
1521 }
1522
1523 List<String>subtags = tag.getVariants();
1524 for (String s : subtags) {
1525 buf.append(LanguageTag.SEP);
1526 // preserve casing
1527 buf.append(s);
1528 }
1529
1530 subtags = tag.getExtensions();
1531 for (String s : subtags) {
1532 buf.append(LanguageTag.SEP);
1533 buf.append(LanguageTag.canonicalizeExtension(s));
1534 }
1535
1536 subtag = tag.getPrivateuse();
1537 if (!subtag.isEmpty()) {
1538 if (buf.length() > 0) {
1539 buf.append(LanguageTag.SEP);
1540 }
1541 buf.append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP);
1542 // preserve casing
1543 buf.append(subtag);
1544 }
1545
1546 String langTag = buf.toString();
1547 synchronized (this) {
1548 if (languageTag == null) {
1549 languageTag = langTag;
1550 }
1551 }
1552 return languageTag;
1553 }
1554
1555 /**
1556 * Returns a locale for the specified IETF BCP 47 language tag string.
1557 *
1558 * <p>If the specified language tag contains any ill-formed subtags,
1559 * the first such subtag and all following subtags are ignored. Compare
1560 * to {@link Locale.Builder#setLanguageTag} which throws an exception
1561 * in this case.
1562 *
1563 * <p>The following <b>conversions</b> are performed:<ul>
1564 *
1565 * <li>The language code "und" is mapped to language "".
1566 *
1567 * <li>The language codes "he", "yi", and "id" are mapped to "iw",
1568 * "ji", and "in" respectively. (This is the same canonicalization
1569 * that's done in Locale's constructors.)
1570 *
1571 * <li>The portion of a private use subtag prefixed by "lvariant",
1572 * if any, is removed and appended to the variant field in the
1573 * result locale (without case normalization). If it is then
1574 * empty, the private use subtag is discarded:
1575 *
1576 * <pre>
1577 * Locale loc;
1578 * loc = Locale.forLanguageTag("en-US-x-lvariant-POSIX");
1579 * loc.getVariant(); // returns "POSIX"
1580 * loc.getExtension('x'); // returns null
1581 *
1582 * loc = Locale.forLanguageTag("de-POSIX-x-URP-lvariant-Abc-Def");
1583 * loc.getVariant(); // returns "POSIX_Abc_Def"
1584 * loc.getExtension('x'); // returns "urp"
1585 * </pre>
1586 *
1587 * <li>When the languageTag argument contains an extlang subtag,
1588 * the first such subtag is used as the language, and the primary
1589 * language subtag and other extlang subtags are ignored:
1590 *
1591 * <pre>
1592 * Locale.forLanguageTag("ar-aao").getLanguage(); // returns "aao"
1593 * Locale.forLanguageTag("en-abc-def-us").toString(); // returns "abc_US"
1594 * </pre>
1595 *
1596 * <li>Case is normalized except for variant tags, which are left
1597 * unchanged. Language is normalized to lower case, script to
1598 * title case, country to upper case, and extensions to lower
1599 * case.
1600 *
1601 * <li>If, after processing, the locale would exactly match either
1602 * ja_JP_JP or th_TH_TH with no extensions, the appropriate
1603 * extensions are added as though the constructor had been called:
1604 *
1605 * <pre>
1606 * Locale.forLanguageTag("ja-JP-x-lvariant-JP").toLanguageTag();
1607 * // returns "ja-JP-u-ca-japanese-x-lvariant-JP"
1608 * Locale.forLanguageTag("th-TH-x-lvariant-TH").toLanguageTag();
1609 * // returns "th-TH-u-nu-thai-x-lvariant-TH"
1610 * </pre></ul>
1611 *
1612 * <p>This implements the 'Language-Tag' production of BCP47, and
1613 * so supports grandfathered (regular and irregular) as well as
1614 * private use language tags. Stand alone private use tags are
1615 * represented as empty language and extension 'x-whatever',
1616 * and grandfathered tags are converted to their canonical replacements
1617 * where they exist.
1618 *
1619 * <p>Grandfathered tags with canonical replacements are as follows:
1620 *
1621 * <table class="striped">
1622 * <caption style="display:none">Grandfathered tags with canonical replacements</caption>
1623 * <thead style="text-align:center">
1624 * <tr><th scope="col" style="padding: 0 2px">grandfathered tag</th><th scope="col" style="padding: 0 2px">modern replacement</th></tr>
1625 * </thead>
1626 * <tbody style="text-align:center">
1627 * <tr><th scope="row">art-lojban</th><td>jbo</td></tr>
1628 * <tr><th scope="row">i-ami</th><td>ami</td></tr>
1629 * <tr><th scope="row">i-bnn</th><td>bnn</td></tr>
1630 * <tr><th scope="row">i-hak</th><td>hak</td></tr>
1631 * <tr><th scope="row">i-klingon</th><td>tlh</td></tr>
1632 * <tr><th scope="row">i-lux</th><td>lb</td></tr>
1633 * <tr><th scope="row">i-navajo</th><td>nv</td></tr>
1634 * <tr><th scope="row">i-pwn</th><td>pwn</td></tr>
1635 * <tr><th scope="row">i-tao</th><td>tao</td></tr>
1636 * <tr><th scope="row">i-tay</th><td>tay</td></tr>
1637 * <tr><th scope="row">i-tsu</th><td>tsu</td></tr>
1638 * <tr><th scope="row">no-bok</th><td>nb</td></tr>
1639 * <tr><th scope="row">no-nyn</th><td>nn</td></tr>
1640 * <tr><th scope="row">sgn-BE-FR</th><td>sfb</td></tr>
1641 * <tr><th scope="row">sgn-BE-NL</th><td>vgt</td></tr>
1642 * <tr><th scope="row">sgn-CH-DE</th><td>sgg</td></tr>
1643 * <tr><th scope="row">zh-guoyu</th><td>cmn</td></tr>
1644 * <tr><th scope="row">zh-hakka</th><td>hak</td></tr>
1645 * <tr><th scope="row">zh-min-nan</th><td>nan</td></tr>
1646 * <tr><th scope="row">zh-xiang</th><td>hsn</td></tr>
1647 * </tbody>
1648 * </table>
1649 *
1650 * <p>Grandfathered tags with no modern replacement will be
1651 * converted as follows:
1652 *
1653 * <table class="striped">
1654 * <caption style="display:none">Grandfathered tags with no modern replacement</caption>
1655 * <thead style="text-align:center">
1656 * <tr><th scope="col" style="padding: 0 2px">grandfathered tag</th><th scope="col" style="padding: 0 2px">converts to</th></tr>
1657 * </thead>
1658 * <tbody style="text-align:center">
1659 * <tr><th scope="row">cel-gaulish</th><td>xtg-x-cel-gaulish</td></tr>
1660 * <tr><th scope="row">en-GB-oed</th><td>en-GB-x-oed</td></tr>
1661 * <tr><th scope="row">i-default</th><td>en-x-i-default</td></tr>
1662 * <tr><th scope="row">i-enochian</th><td>und-x-i-enochian</td></tr>
1663 * <tr><th scope="row">i-mingo</th><td>see-x-i-mingo</td></tr>
1664 * <tr><th scope="row">zh-min</th><td>nan-x-zh-min</td></tr>
1665 * </tbody>
1666 * </table>
1667 *
1668 * <p>For a list of all grandfathered tags, see the
1669 * IANA Language Subtag Registry (search for "Type: grandfathered").
1670 *
1671 * <p><b>Note</b>: there is no guarantee that <code>toLanguageTag</code>
1672 * and <code>forLanguageTag</code> will round-trip.
1673 *
1674 * @param languageTag the language tag
1675 * @return The locale that best represents the language tag.
1676 * @throws NullPointerException if <code>languageTag</code> is <code>null</code>
1677 * @see #toLanguageTag()
1678 * @see java.util.Locale.Builder#setLanguageTag(String)
1679 * @since 1.7
1680 */
1681 public static Locale forLanguageTag(String languageTag) {
1682 LanguageTag tag = LanguageTag.parse(languageTag, null);
1683 InternalLocaleBuilder bldr = new InternalLocaleBuilder();
1684 bldr.setLanguageTag(tag);
1685 BaseLocale base = bldr.getBaseLocale();
1686 LocaleExtensions exts = bldr.getLocaleExtensions();
1687 if (exts == null && !base.getVariant().isEmpty()) {
1688 exts = getCompatibilityExtensions(base.getLanguage(), base.getScript(),
1689 base.getRegion(), base.getVariant());
1690 }
1691 return getInstance(base, exts);
1692 }
1693
1694 /**
1695 * Returns a three-letter abbreviation of this locale's language.
1696 * If the language matches an ISO 639-1 two-letter code, the
1697 * corresponding ISO 639-2/T three-letter lowercase code is
1698 * returned. The ISO 639-2 language codes can be found on-line,
1699 * see "Codes for the Representation of Names of Languages Part 2:
1700 * Alpha-3 Code". If the locale specifies a three-letter
1701 * language, the language is returned as is. If the locale does
1702 * not specify a language the empty string is returned.
1703 *
1704 * @return A three-letter abbreviation of this locale's language.
1705 * @exception MissingResourceException Throws MissingResourceException if
1706 * three-letter language abbreviation is not available for this locale.
1707 */
1708 public String getISO3Language() throws MissingResourceException {
1709 String lang = baseLocale.getLanguage();
1710 if (lang.length() == 3) {
1711 return lang;
1712 }
1713
1714 String language3 = getISO3Code(lang, LocaleISOData.isoLanguageTable);
1715 if (language3 == null) {
1716 throw new MissingResourceException("Couldn't find 3-letter language code for "
1717 + lang, "FormatData_" + toString(), "ShortLanguage");
1718 }
1719 return language3;
1720 }
1721
1722 /**
1723 * Returns a three-letter abbreviation for this locale's country.
1724 * If the country matches an ISO 3166-1 alpha-2 code, the
1725 * corresponding ISO 3166-1 alpha-3 uppercase code is returned.
1726 * If the locale doesn't specify a country, this will be the empty
1727 * string.
1728 *
1729 * <p>The ISO 3166-1 codes can be found on-line.
1730 *
1731 * @return A three-letter abbreviation of this locale's country.
1732 * @exception MissingResourceException Throws MissingResourceException if the
1733 * three-letter country abbreviation is not available for this locale.
1734 */
1735 public String getISO3Country() throws MissingResourceException {
1736 String country3 = getISO3Code(baseLocale.getRegion(), LocaleISOData.isoCountryTable);
1737 if (country3 == null) {
1738 throw new MissingResourceException("Couldn't find 3-letter country code for "
1739 + baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry");
1740 }
1741 return country3;
1742 }
1743
1744 private static String getISO3Code(String iso2Code, String table) {
1745 int codeLength = iso2Code.length();
1746 if (codeLength == 0) {
1747 return "";
1748 }
1749
1750 int tableLength = table.length();
1751 int index = tableLength;
1752 if (codeLength == 2) {
1753 char c1 = iso2Code.charAt(0);
1754 char c2 = iso2Code.charAt(1);
1755 for (index = 0; index < tableLength; index += 5) {
1756 if (table.charAt(index) == c1
1757 && table.charAt(index + 1) == c2) {
1758 break;
1759 }
1760 }
1761 }
1762 return index < tableLength ? table.substring(index + 2, index + 5) : null;
1763 }
1764
1765 /**
1766 * Returns a name for the locale's language that is appropriate for display to the
1767 * user.
1768 * If possible, the name returned will be localized for the default
1769 * {@link Locale.Category#DISPLAY DISPLAY} locale.
1770 * For example, if the locale is fr_FR and the default
1771 * {@link Locale.Category#DISPLAY DISPLAY} locale
1772 * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
1773 * the default {@link Locale.Category#DISPLAY DISPLAY} locale is fr_FR,
1774 * getDisplayLanguage() will return "anglais".
1775 * If the name returned cannot be localized for the default
1776 * {@link Locale.Category#DISPLAY DISPLAY} locale,
1777 * (say, we don't have a Japanese name for Croatian),
1778 * this function falls back on the English name, and uses the ISO code as a last-resort
1779 * value. If the locale doesn't specify a language, this function returns the empty string.
1780 *
1781 * @return The name of the display language.
1782 */
1783 public final String getDisplayLanguage() {
1784 return getDisplayLanguage(getDefault(Category.DISPLAY));
1785 }
1786
1787 /**
1788 * Returns a name for the locale's language that is appropriate for display to the
1789 * user.
1790 * If possible, the name returned will be localized according to inLocale.
1791 * For example, if the locale is fr_FR and inLocale
1792 * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
1793 * inLocale is fr_FR, getDisplayLanguage() will return "anglais".
1794 * If the name returned cannot be localized according to inLocale,
1795 * (say, we don't have a Japanese name for Croatian),
1796 * this function falls back on the English name, and finally
1797 * on the ISO code as a last-resort value. If the locale doesn't specify a language,
1798 * this function returns the empty string.
1799 *
1800 * @param inLocale The locale for which to retrieve the display language.
1801 * @return The name of the display language appropriate to the given locale.
1802 * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
1803 */
1804 public String getDisplayLanguage(Locale inLocale) {
1805 return getDisplayString(baseLocale.getLanguage(), null, inLocale, DISPLAY_LANGUAGE);
1806 }
1807
1808 /**
1809 * Returns a name for the locale's script that is appropriate for display to
1810 * the user. If possible, the name will be localized for the default
1811 * {@link Locale.Category#DISPLAY DISPLAY} locale. Returns
1812 * the empty string if this locale doesn't specify a script code.
1813 *
1814 * @return the display name of the script code for the current default
1815 * {@link Locale.Category#DISPLAY DISPLAY} locale
1816 * @since 1.7
1817 */
1818 public String getDisplayScript() {
1819 return getDisplayScript(getDefault(Category.DISPLAY));
1820 }
1821
1822 /**
1823 * Returns a name for the locale's script that is appropriate
1824 * for display to the user. If possible, the name will be
1825 * localized for the given locale. Returns the empty string if
1826 * this locale doesn't specify a script code.
1827 *
1828 * @param inLocale The locale for which to retrieve the display script.
1829 * @return the display name of the script code for the current default
1830 * {@link Locale.Category#DISPLAY DISPLAY} locale
1831 * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
1832 * @since 1.7
1833 */
1834 public String getDisplayScript(Locale inLocale) {
1835 return getDisplayString(baseLocale.getScript(), null, inLocale, DISPLAY_SCRIPT);
1836 }
1837
1838 /**
1839 * Returns a name for the locale's country that is appropriate for display to the
1840 * user.
1841 * If possible, the name returned will be localized for the default
1842 * {@link Locale.Category#DISPLAY DISPLAY} locale.
1843 * For example, if the locale is fr_FR and the default
1844 * {@link Locale.Category#DISPLAY DISPLAY} locale
1845 * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
1846 * the default {@link Locale.Category#DISPLAY DISPLAY} locale is fr_FR,
1847 * getDisplayCountry() will return "Etats-Unis".
1848 * If the name returned cannot be localized for the default
1849 * {@link Locale.Category#DISPLAY DISPLAY} locale,
1850 * (say, we don't have a Japanese name for Croatia),
1851 * this function falls back on the English name, and uses the ISO code as a last-resort
1852 * value. If the locale doesn't specify a country, this function returns the empty string.
1853 *
1854 * @return The name of the country appropriate to the locale.
1855 */
1856 public final String getDisplayCountry() {
1857 return getDisplayCountry(getDefault(Category.DISPLAY));
1858 }
1859
1860 /**
1861 * Returns a name for the locale's country that is appropriate for display to the
1862 * user.
1863 * If possible, the name returned will be localized according to inLocale.
1864 * For example, if the locale is fr_FR and inLocale
1865 * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
1866 * inLocale is fr_FR, getDisplayCountry() will return "Etats-Unis".
1867 * If the name returned cannot be localized according to inLocale.
1868 * (say, we don't have a Japanese name for Croatia),
1869 * this function falls back on the English name, and finally
1870 * on the ISO code as a last-resort value. If the locale doesn't specify a country,
1871 * this function returns the empty string.
1872 *
1873 * @param inLocale The locale for which to retrieve the display country.
1874 * @return The name of the country appropriate to the given locale.
1875 * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
1876 */
1877 public String getDisplayCountry(Locale inLocale) {
1878 return getDisplayString(baseLocale.getRegion(), null, inLocale, DISPLAY_COUNTRY);
1879 }
1880
1881 private String getDisplayString(String code, String cat, Locale inLocale, int type) {
1882 Objects.requireNonNull(inLocale);
1883 Objects.requireNonNull(code);
1884
1885 if (code.isEmpty()) {
1886 return "";
1887 }
1888
1889 LocaleServiceProviderPool pool =
1890 LocaleServiceProviderPool.getPool(LocaleNameProvider.class);
1891 String rbKey = (type == DISPLAY_VARIANT ? "%%"+code : code);
1892 String result = pool.getLocalizedObject(
1893 LocaleNameGetter.INSTANCE,
1894 inLocale, rbKey, type, code, cat);
1895 return result != null ? result : code;
1896 }
1897
1898 /**
1899 * Returns a name for the locale's variant code that is appropriate for display to the
1900 * user. If possible, the name will be localized for the default
1901 * {@link Locale.Category#DISPLAY DISPLAY} locale. If the locale
1902 * doesn't specify a variant code, this function returns the empty string.
1903 *
1904 * @return The name of the display variant code appropriate to the locale.
1905 */
1906 public final String getDisplayVariant() {
1907 return getDisplayVariant(getDefault(Category.DISPLAY));
1908 }
1909
1910 /**
1911 * Returns a name for the locale's variant code that is appropriate for display to the
1912 * user. If possible, the name will be localized for inLocale. If the locale
1913 * doesn't specify a variant code, this function returns the empty string.
1914 *
1915 * @param inLocale The locale for which to retrieve the display variant code.
1916 * @return The name of the display variant code appropriate to the given locale.
1917 * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
1918 */
1919 public String getDisplayVariant(Locale inLocale) {
1920 if (baseLocale.getVariant().isEmpty())
1921 return "";
1922
1923 LocaleResources lr = LocaleProviderAdapter
1924 .getResourceBundleBased()
1925 .getLocaleResources(inLocale);
1926
1927 String names[] = getDisplayVariantArray(inLocale);
1928
1929 // Get the localized patterns for formatting a list, and use
1930 // them to format the list.
1931 return formatList(names,
1932 lr.getLocaleName("ListCompositionPattern"));
1933 }
1934
1935 /**
1936 * Returns a name for the locale that is appropriate for display to the
1937 * user. This will be the values returned by getDisplayLanguage(),
1938 * getDisplayScript(), getDisplayCountry(), getDisplayVariant() and
1939 * optional <a href="./Locale.html#def_locale_extension">Unicode extensions</a>
1940 * assembled into a single string. The non-empty values are used in order, with
1941 * the second and subsequent names in parentheses. For example:
1942 * <blockquote>
1943 * language (script, country, variant(, extension)*)<br>
1944 * language (country(, extension)*)<br>
1945 * language (variant(, extension)*)<br>
1946 * script (country(, extension)*)<br>
1947 * country (extension)*<br>
1948 * </blockquote>
1949 * depending on which fields are specified in the locale. The field
1950 * separator in the above parentheses, denoted as a comma character, may
1951 * be localized depending on the locale. If the language, script, country,
1952 * and variant fields are all empty, this function returns the empty string.
1953 *
1954 * @return The name of the locale appropriate to display.
1955 */
1956 public final String getDisplayName() {
1957 return getDisplayName(getDefault(Category.DISPLAY));
1958 }
1959
1960 /**
1961 * Returns a name for the locale that is appropriate for display
1962 * to the user. This will be the values returned by
1963 * getDisplayLanguage(), getDisplayScript(),getDisplayCountry()
1964 * getDisplayVariant(), and optional <a href="./Locale.html#def_locale_extension">
1965 * Unicode extensions</a> assembled into a single string. The non-empty
1966 * values are used in order, with the second and subsequent names in
1967 * parentheses. For example:
1968 * <blockquote>
1969 * language (script, country, variant(, extension)*)<br>
1970 * language (country(, extension)*)<br>
1971 * language (variant(, extension)*)<br>
1972 * script (country(, extension)*)<br>
1973 * country (extension)*<br>
1974 * </blockquote>
1975 * depending on which fields are specified in the locale. The field
1976 * separator in the above parentheses, denoted as a comma character, may
1977 * be localized depending on the locale. If the language, script, country,
1978 * and variant fields are all empty, this function returns the empty string.
1979 *
1980 * @param inLocale The locale for which to retrieve the display name.
1981 * @return The name of the locale appropriate to display.
1982 * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
1983 */
1984 public String getDisplayName(Locale inLocale) {
1985 LocaleResources lr = LocaleProviderAdapter
1986 .getResourceBundleBased()
1987 .getLocaleResources(inLocale);
1988
1989 String languageName = getDisplayLanguage(inLocale);
1990 String scriptName = getDisplayScript(inLocale);
1991 String countryName = getDisplayCountry(inLocale);
1992 String[] variantNames = getDisplayVariantArray(inLocale);
1993
1994 // Get the localized patterns for formatting a display name.
1995 String displayNamePattern = lr.getLocaleName("DisplayNamePattern");
1996 String listCompositionPattern = lr.getLocaleName("ListCompositionPattern");
1997
1998 // The display name consists of a main name, followed by qualifiers.
1999 // Typically, the format is "MainName (Qualifier, Qualifier)" but this
2000 // depends on what pattern is stored in the display locale.
2001 String mainName;
2002 String[] qualifierNames;
2003
2004 // The main name is the language, or if there is no language, the script,
2005 // then if no script, the country. If there is no language/script/country
2006 // (an anomalous situation) then the display name is simply the variant's
2007 // display name.
2008 if (languageName.isEmpty() && scriptName.isEmpty() && countryName.isEmpty()) {
2009 if (variantNames.length == 0) {
2010 return "";
2011 } else {
2012 return formatList(variantNames, listCompositionPattern);
2013 }
2014 }
2015 ArrayList<String> names = new ArrayList<>(4);
2016 if (!languageName.isEmpty()) {
2017 names.add(languageName);
2018 }
2019 if (!scriptName.isEmpty()) {
2020 names.add(scriptName);
2021 }
2022 if (!countryName.isEmpty()) {
2023 names.add(countryName);
2024 }
2025 if (variantNames.length != 0) {
2026 names.addAll(Arrays.asList(variantNames));
2027 }
2028
2029 // add Unicode extensions
2030 if (localeExtensions != null) {
2031 localeExtensions.getUnicodeLocaleAttributes().stream()
2032 .map(key -> getDisplayString(key, null, inLocale, DISPLAY_UEXT_KEY))
2033 .forEach(names::add);
2034 localeExtensions.getUnicodeLocaleKeys().stream()
2035 .map(key -> getDisplayKeyTypeExtensionString(key, lr, inLocale))
2036 .forEach(names::add);
2037 }
2038
2039 // The first one in the main name
2040 mainName = names.get(0);
2041
2042 // Others are qualifiers
2043 int numNames = names.size();
2044 qualifierNames = (numNames > 1) ?
2045 names.subList(1, numNames).toArray(new String[numNames - 1]) : new String[0];
2046
2047 // Create an array whose first element is the number of remaining
2048 // elements. This serves as a selector into a ChoiceFormat pattern from
2049 // the resource. The second and third elements are the main name and
2050 // the qualifier; if there are no qualifiers, the third element is
2051 // unused by the format pattern.
2052 Object[] displayNames = {
2053 qualifierNames.length != 0 ? 2 : 1,
2054 mainName,
2055 // We could also just call formatList() and have it handle the empty
2056 // list case, but this is more efficient, and we want it to be
2057 // efficient since all the language-only locales will not have any
2058 // qualifiers.
2059 qualifierNames.length != 0 ? formatList(qualifierNames, listCompositionPattern) : null
2060 };
2061
2062 if (displayNamePattern != null) {
2063 return new MessageFormat(displayNamePattern).format(displayNames);
2064 }
2065 else {
2066 // If we cannot get the message format pattern, then we use a simple
2067 // hard-coded pattern. This should not occur in practice unless the
2068 // installation is missing some core files (FormatData etc.).
2069 StringBuilder result = new StringBuilder();
2070 result.append((String)displayNames[1]);
2071 if (displayNames.length > 2) {
2072 result.append(" (");
2073 result.append((String)displayNames[2]);
2074 result.append(')');
2075 }
2076 return result.toString();
2077 }
2078 }
2079
2080 /**
2081 * Overrides Cloneable.
2082 */
2083 @Override
2084 public Object clone()
2085 {
2086 try {
2087 Locale that = (Locale)super.clone();
2088 return that;
2089 } catch (CloneNotSupportedException e) {
2090 throw new InternalError(e);
2091 }
2092 }
2093
2094 /**
2095 * Override hashCode.
2096 * Since Locales are often used in hashtables, caches the value
2097 * for speed.
2098 */
2099 @Override
2100 public int hashCode() {
2101 int hc = hashCodeValue;
2102 if (hc == 0) {
2103 hc = baseLocale.hashCode();
2104 if (localeExtensions != null) {
2105 hc ^= localeExtensions.hashCode();
2106 }
2107 hashCodeValue = hc;
2108 }
2109 return hc;
2110 }
2111
2112 // Overrides
2113
2114 /**
2115 * Returns true if this Locale is equal to another object. A Locale is
2116 * deemed equal to another Locale with identical language, script, country,
2117 * variant and extensions, and unequal to all other objects.
2118 *
2119 * @return true if this Locale is equal to the specified object.
2120 */
2121 @Override
2122 public boolean equals(Object obj) {
2123 if (this == obj) // quick check
2124 return true;
2125 if (!(obj instanceof Locale))
2126 return false;
2127 BaseLocale otherBase = ((Locale)obj).baseLocale;
2128 if (!baseLocale.equals(otherBase)) {
2129 return false;
2130 }
2131 if (localeExtensions == null) {
2132 return ((Locale)obj).localeExtensions == null;
2133 }
2134 return localeExtensions.equals(((Locale)obj).localeExtensions);
2135 }
2136
2137 // ================= privates =====================================
2138
2139 private transient BaseLocale baseLocale;
2140 private transient LocaleExtensions localeExtensions;
2141
2142 /**
2143 * Calculated hashcode
2144 */
2145 private transient volatile int hashCodeValue;
2146
2147 private static volatile Locale defaultLocale = initDefault();
2148 private static volatile Locale defaultDisplayLocale;
2149 private static volatile Locale defaultFormatLocale;
2150
2151 private transient volatile String languageTag;
2152
2153 /**
2154 * Return an array of the display names of the variant.
2155 * @param bundle the ResourceBundle to use to get the display names
2156 * @return an array of display names, possible of zero length.
2157 */
2158 private String[] getDisplayVariantArray(Locale inLocale) {
2159 // Split the variant name into tokens separated by '_'.
2160 StringTokenizer tokenizer = new StringTokenizer(baseLocale.getVariant(), "_");
2161 String[] names = new String[tokenizer.countTokens()];
2162
2163 // For each variant token, lookup the display name. If
2164 // not found, use the variant name itself.
2165 for (int i=0; i<names.length; ++i) {
2166 names[i] = getDisplayString(tokenizer.nextToken(), null,
2167 inLocale, DISPLAY_VARIANT);
2168 }
2169
2170 return names;
2171 }
2172
2173 private String getDisplayKeyTypeExtensionString(String key, LocaleResources lr, Locale inLocale) {
2174 String type = localeExtensions.getUnicodeLocaleType(key);
2175 String ret = getDisplayString(type, key, inLocale, DISPLAY_UEXT_TYPE);
2176
2177 if (ret == null || ret.equals(type)) {
2178 // no localization for this type. try combining key/type separately
2179 String displayType = type;
2180 switch (key) {
2181 case "cu":
2182 displayType = lr.getCurrencyName(type.toLowerCase(Locale.ROOT));
2183 break;
2184 case "rg":
2185 if (type != null &&
2186 // UN M.49 code should not be allowed here
2187 type.matches("^[a-zA-Z]{2}[zZ]{4}$")) {
2188 displayType = lr.getLocaleName(type.substring(0, 2).toUpperCase(Locale.ROOT));
2189 }
2190 break;
2191 case "tz":
2192 displayType = TimeZoneNameUtility.convertLDMLShortID(type)
2193 .map(id -> TimeZoneNameUtility.retrieveGenericDisplayName(id, TimeZone.LONG, inLocale))
2194 .orElse(type);
2195 break;
2196 }
2197 ret = MessageFormat.format(lr.getLocaleName("ListKeyTypePattern"),
2198 getDisplayString(key, null, inLocale, DISPLAY_UEXT_KEY),
2199 Optional.ofNullable(displayType).orElse(type));
2200 }
2201
2202 return ret;
2203 }
2204
2205 /**
2206 * Format a list using given pattern strings.
2207 * If either of the patterns is null, then a the list is
2208 * formatted by concatenation with the delimiter ','.
2209 * @param stringList the list of strings to be formatted.
2210 * and formatting them into a list.
2211 * @param pattern should take 2 arguments for reduction
2212 * @return a string representing the list.
2213 */
2214 private static String formatList(String[] stringList, String pattern) {
2215 // If we have no list patterns, compose the list in a simple,
2216 // non-localized way.
2217 if (pattern == null) {
2218 return Arrays.stream(stringList).collect(Collectors.joining(","));
2219 }
2220
2221 switch (stringList.length) {
2222 case 0:
2223 return "";
2224 case 1:
2225 return stringList[0];
2226 default:
2227 return Arrays.stream(stringList).reduce("",
2228 (s1, s2) -> {
2229 if (s1.equals("")) {
2230 return s2;
2231 }
2232 if (s2.equals("")) {
2233 return s1;
2234 }
2235 return MessageFormat.format(pattern, s1, s2);
2236 });
2237 }
2238 }
2239
2240 // Duplicate of sun.util.locale.UnicodeLocaleExtension.isKey in order to
2241 // avoid its class loading.
2242 private static boolean isUnicodeExtensionKey(String s) {
2243 // 2alphanum
2244 return (s.length() == 2) && LocaleUtils.isAlphaNumericString(s);
2245 }
2246
2247 /**
2248 * @serialField language String
2249 * language subtag in lower case. (See <a href="java/util/Locale.html#getLanguage()">getLanguage()</a>)
2250 * @serialField country String
2251 * country subtag in upper case. (See <a href="java/util/Locale.html#getCountry()">getCountry()</a>)
2252 * @serialField variant String
2253 * variant subtags separated by LOWLINE characters. (See <a href="java/util/Locale.html#getVariant()">getVariant()</a>)
2254 * @serialField hashcode int
2255 * deprecated, for forward compatibility only
2256 * @serialField script String
2257 * script subtag in title case (See <a href="java/util/Locale.html#getScript()">getScript()</a>)
2258 * @serialField extensions String
2259 * canonical representation of extensions, that is,
2260 * BCP47 extensions in alphabetical order followed by
2261 * BCP47 private use subtags, all in lower case letters
2262 * separated by HYPHEN-MINUS characters.
2263 * (See <a href="java/util/Locale.html#getExtensionKeys()">getExtensionKeys()</a>,
2264 * <a href="java/util/Locale.html#getExtension(char)">getExtension(char)</a>)
2265 */
2266 private static final ObjectStreamField[] serialPersistentFields = {
2267 new ObjectStreamField("language", String.class),
2268 new ObjectStreamField("country", String.class),
2269 new ObjectStreamField("variant", String.class),
2270 new ObjectStreamField("hashcode", int.class),
2271 new ObjectStreamField("script", String.class),
2272 new ObjectStreamField("extensions", String.class),
2273 };
2274
2275 /**
2276 * Serializes this <code>Locale</code> to the specified <code>ObjectOutputStream</code>.
2277 * @param out the <code>ObjectOutputStream</code> to write
2278 * @throws IOException
2279 * @since 1.7
2280 */
2281 private void writeObject(ObjectOutputStream out) throws IOException {
2282 ObjectOutputStream.PutField fields = out.putFields();
2283 fields.put("language", baseLocale.getLanguage());
2284 fields.put("script", baseLocale.getScript());
2285 fields.put("country", baseLocale.getRegion());
2286 fields.put("variant", baseLocale.getVariant());
2287 fields.put("extensions", localeExtensions == null ? "" : localeExtensions.getID());
2288 fields.put("hashcode", -1); // place holder just for backward support
2289 out.writeFields();
2290 }
2291
2292 /**
2293 * Deserializes this <code>Locale</code>.
2294 * @param in the <code>ObjectInputStream</code> to read
2295 * @throws IOException
2296 * @throws ClassNotFoundException
2297 * @throws IllformedLocaleException
2298 * @since 1.7
2299 */
2300 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
2301 ObjectInputStream.GetField fields = in.readFields();
2302 String language = (String)fields.get("language", "");
2303 String script = (String)fields.get("script", "");
2304 String country = (String)fields.get("country", "");
2305 String variant = (String)fields.get("variant", "");
2306 String extStr = (String)fields.get("extensions", "");
2307 baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
2308 if (!extStr.isEmpty()) {
2309 try {
2310 InternalLocaleBuilder bldr = new InternalLocaleBuilder();
2311 bldr.setExtensions(extStr);
2312 localeExtensions = bldr.getLocaleExtensions();
2313 } catch (LocaleSyntaxException e) {
2314 throw new IllformedLocaleException(e.getMessage());
2315 }
2316 } else {
2317 localeExtensions = null;
2318 }
2319 }
2320
2321 /**
2322 * Returns a cached <code>Locale</code> instance equivalent to
2323 * the deserialized <code>Locale</code>. When serialized
2324 * language, country and variant fields read from the object data stream
2325 * are exactly "ja", "JP", "JP" or "th", "TH", "TH" and script/extensions
2326 * fields are empty, this method supplies <code>UNICODE_LOCALE_EXTENSION</code>
2327 * "ca"/"japanese" (calendar type is "japanese") or "nu"/"thai" (number script
2328 * type is "thai"). See <a href="Locale.html#special_cases_constructor">Special Cases</a>
2329 * for more information.
2330 *
2331 * @return an instance of <code>Locale</code> equivalent to
2332 * the deserialized <code>Locale</code>.
2333 * @throws java.io.ObjectStreamException
2334 */
2335 private Object readResolve() throws java.io.ObjectStreamException {
2336 return getInstance(baseLocale.getLanguage(), baseLocale.getScript(),
2337 baseLocale.getRegion(), baseLocale.getVariant(), localeExtensions);
2338 }
2339
2340 private static volatile String[] isoLanguages;
2341
2342 private static volatile String[] isoCountries;
2343
2344 private static String convertOldISOCodes(String language) {
2345 // we accept both the old and the new ISO codes for the languages whose ISO
2346 // codes have changed, but we always store the OLD code, for backward compatibility
2347 language = LocaleUtils.toLowerString(language).intern();
2348 if (language == "he") {
2349 return "iw";
2350 } else if (language == "yi") {
2351 return "ji";
2352 } else if (language == "id") {
2353 return "in";
2354 } else {
2355 return language;
2356 }
2357 }
2358
2359 private static LocaleExtensions getCompatibilityExtensions(String language,
2360 String script,
2361 String country,
2362 String variant) {
2363 LocaleExtensions extensions = null;
2364 // Special cases for backward compatibility support
2365 if (LocaleUtils.caseIgnoreMatch(language, "ja")
2366 && script.isEmpty()
2367 && LocaleUtils.caseIgnoreMatch(country, "jp")
2368 && "JP".equals(variant)) {
2369 // ja_JP_JP -> u-ca-japanese (calendar = japanese)
2370 extensions = LocaleExtensions.CALENDAR_JAPANESE;
2371 } else if (LocaleUtils.caseIgnoreMatch(language, "th")
2372 && script.isEmpty()
2373 && LocaleUtils.caseIgnoreMatch(country, "th")
2374 && "TH".equals(variant)) {
2375 // th_TH_TH -> u-nu-thai (numbersystem = thai)
2376 extensions = LocaleExtensions.NUMBER_THAI;
2377 }
2378 return extensions;
2379 }
2380
2381 /**
2382 * Obtains a localized locale names from a LocaleNameProvider
2383 * implementation.
2384 */
2385 private static class LocaleNameGetter
2386 implements LocaleServiceProviderPool.LocalizedObjectGetter<LocaleNameProvider, String> {
2387 private static final LocaleNameGetter INSTANCE = new LocaleNameGetter();
2388
2389 @Override
2390 public String getObject(LocaleNameProvider localeNameProvider,
2391 Locale locale,
2392 String key,
2393 Object... params) {
2394 assert params.length == 3;
2395 int type = (Integer)params[0];
2396 String code = (String)params[1];
2397 String cat = (String)params[2];
2398
2399 switch(type) {
2400 case DISPLAY_LANGUAGE:
2401 return localeNameProvider.getDisplayLanguage(code, locale);
2402 case DISPLAY_COUNTRY:
2403 return localeNameProvider.getDisplayCountry(code, locale);
2404 case DISPLAY_VARIANT:
2405 return localeNameProvider.getDisplayVariant(code, locale);
2406 case DISPLAY_SCRIPT:
2407 return localeNameProvider.getDisplayScript(code, locale);
2408 case DISPLAY_UEXT_KEY:
2409 return localeNameProvider.getDisplayUnicodeExtensionKey(code, locale);
2410 case DISPLAY_UEXT_TYPE:
2411 return localeNameProvider.getDisplayUnicodeExtensionType(code, cat, locale);
2412 default:
2413 assert false; // shouldn't happen
2414 }
2415
2416 return null;
2417 }
2418 }
2419
2420 /**
2421 * Enum for locale categories. These locale categories are used to get/set
2422 * the default locale for the specific functionality represented by the
2423 * category.
2424 *
2425 * @see #getDefault(Locale.Category)
2426 * @see #setDefault(Locale.Category, Locale)
2427 * @since 1.7
2428 */
2429 public enum Category {
2430
2431 /**
2432 * Category used to represent the default locale for
2433 * displaying user interfaces.
2434 */
2435 DISPLAY("user.language.display",
2436 "user.script.display",
2437 "user.country.display",
2438 "user.variant.display",
2439 "user.extensions.display"),
2440
2441 /**
2442 * Category used to represent the default locale for
2443 * formatting dates, numbers, and/or currencies.
2444 */
2445 FORMAT("user.language.format",
2446 "user.script.format",
2447 "user.country.format",
2448 "user.variant.format",
2449 "user.extensions.format");
2450
2451 Category(String languageKey, String scriptKey, String countryKey,
2452 String variantKey, String extensionsKey) {
2453 this.languageKey = languageKey;
2454 this.scriptKey = scriptKey;
2455 this.countryKey = countryKey;
2456 this.variantKey = variantKey;
2457 this.extensionsKey = extensionsKey;
2458 }
2459
2460 final String languageKey;
2461 final String scriptKey;
2462 final String countryKey;
2463 final String variantKey;
2464 final String extensionsKey;
2465 }
2466
2467 /**
2468 * <code>Builder</code> is used to build instances of <code>Locale</code>
2469 * from values configured by the setters. Unlike the <code>Locale</code>
2470 * constructors, the <code>Builder</code> checks if a value configured by a
2471 * setter satisfies the syntax requirements defined by the <code>Locale</code>
2472 * class. A <code>Locale</code> object created by a <code>Builder</code> is
2473 * well-formed and can be transformed to a well-formed IETF BCP 47 language tag
2474 * without losing information.
2475 *
2476 * <p><b>Note:</b> The <code>Locale</code> class does not provide any
2477 * syntactic restrictions on variant, while BCP 47 requires each variant
2478 * subtag to be 5 to 8 alphanumerics or a single numeric followed by 3
2479 * alphanumerics. The method <code>setVariant</code> throws
2480 * <code>IllformedLocaleException</code> for a variant that does not satisfy
2481 * this restriction. If it is necessary to support such a variant, use a
2482 * Locale constructor. However, keep in mind that a <code>Locale</code>
2483 * object created this way might lose the variant information when
2484 * transformed to a BCP 47 language tag.
2485 *
2486 * <p>The following example shows how to create a <code>Locale</code> object
2487 * with the <code>Builder</code>.
2488 * <blockquote>
2489 * <pre>
2490 * Locale aLocale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build();
2491 * </pre>
2492 * </blockquote>
2493 *
2494 * <p>Builders can be reused; <code>clear()</code> resets all
2495 * fields to their default values.
2496 *
2497 * @see Locale#forLanguageTag
2498 * @since 1.7
2499 */
2500 public static final class Builder {
2501 private final InternalLocaleBuilder localeBuilder;
2502
2503 /**
2504 * Constructs an empty Builder. The default value of all
2505 * fields, extensions, and private use information is the
2506 * empty string.
2507 */
2508 public Builder() {
2509 localeBuilder = new InternalLocaleBuilder();
2510 }
2511
2512 /**
2513 * Resets the <code>Builder</code> to match the provided
2514 * <code>locale</code>. Existing state is discarded.
2515 *
2516 * <p>All fields of the locale must be well-formed, see {@link Locale}.
2517 *
2518 * <p>Locales with any ill-formed fields cause
2519 * <code>IllformedLocaleException</code> to be thrown, except for the
2520 * following three cases which are accepted for compatibility
2521 * reasons:<ul>
2522 * <li>Locale("ja", "JP", "JP") is treated as "ja-JP-u-ca-japanese"
2523 * <li>Locale("th", "TH", "TH") is treated as "th-TH-u-nu-thai"
2524 * <li>Locale("no", "NO", "NY") is treated as "nn-NO"</ul>
2525 *
2526 * @param locale the locale
2527 * @return This builder.
2528 * @throws IllformedLocaleException if <code>locale</code> has
2529 * any ill-formed fields.
2530 * @throws NullPointerException if <code>locale</code> is null.
2531 */
2532 public Builder setLocale(Locale locale) {
2533 try {
2534 localeBuilder.setLocale(locale.baseLocale, locale.localeExtensions);
2535 } catch (LocaleSyntaxException e) {
2536 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2537 }
2538 return this;
2539 }
2540
2541 /**
2542 * Resets the Builder to match the provided IETF BCP 47
2543 * language tag. Discards the existing state. Null and the
2544 * empty string cause the builder to be reset, like {@link
2545 * #clear}. Grandfathered tags (see {@link
2546 * Locale#forLanguageTag}) are converted to their canonical
2547 * form before being processed. Otherwise, the language tag
2548 * must be well-formed (see {@link Locale}) or an exception is
2549 * thrown (unlike <code>Locale.forLanguageTag</code>, which
2550 * just discards ill-formed and following portions of the
2551 * tag).
2552 *
2553 * @param languageTag the language tag
2554 * @return This builder.
2555 * @throws IllformedLocaleException if <code>languageTag</code> is ill-formed
2556 * @see Locale#forLanguageTag(String)
2557 */
2558 public Builder setLanguageTag(String languageTag) {
2559 ParseStatus sts = new ParseStatus();
2560 LanguageTag tag = LanguageTag.parse(languageTag, sts);
2561 if (sts.isError()) {
2562 throw new IllformedLocaleException(sts.getErrorMessage(), sts.getErrorIndex());
2563 }
2564 localeBuilder.setLanguageTag(tag);
2565 return this;
2566 }
2567
2568 /**
2569 * Sets the language. If <code>language</code> is the empty string or
2570 * null, the language in this <code>Builder</code> is removed. Otherwise,
2571 * the language must be <a href="./Locale.html#def_language">well-formed</a>
2572 * or an exception is thrown.
2573 *
2574 * <p>The typical language value is a two or three-letter language
2575 * code as defined in ISO639.
2576 *
2577 * @param language the language
2578 * @return This builder.
2579 * @throws IllformedLocaleException if <code>language</code> is ill-formed
2580 */
2581 public Builder setLanguage(String language) {
2582 try {
2583 localeBuilder.setLanguage(language);
2584 } catch (LocaleSyntaxException e) {
2585 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2586 }
2587 return this;
2588 }
2589
2590 /**
2591 * Sets the script. If <code>script</code> is null or the empty string,
2592 * the script in this <code>Builder</code> is removed.
2593 * Otherwise, the script must be <a href="./Locale.html#def_script">well-formed</a> or an
2594 * exception is thrown.
2595 *
2596 * <p>The typical script value is a four-letter script code as defined by ISO 15924.
2597 *
2598 * @param script the script
2599 * @return This builder.
2600 * @throws IllformedLocaleException if <code>script</code> is ill-formed
2601 */
2602 public Builder setScript(String script) {
2603 try {
2604 localeBuilder.setScript(script);
2605 } catch (LocaleSyntaxException e) {
2606 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2607 }
2608 return this;
2609 }
2610
2611 /**
2612 * Sets the region. If region is null or the empty string, the region
2613 * in this <code>Builder</code> is removed. Otherwise,
2614 * the region must be <a href="./Locale.html#def_region">well-formed</a> or an
2615 * exception is thrown.
2616 *
2617 * <p>The typical region value is a two-letter ISO 3166 code or a
2618 * three-digit UN M.49 area code.
2619 *
2620 * <p>The country value in the <code>Locale</code> created by the
2621 * <code>Builder</code> is always normalized to upper case.
2622 *
2623 * @param region the region
2624 * @return This builder.
2625 * @throws IllformedLocaleException if <code>region</code> is ill-formed
2626 */
2627 public Builder setRegion(String region) {
2628 try {
2629 localeBuilder.setRegion(region);
2630 } catch (LocaleSyntaxException e) {
2631 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2632 }
2633 return this;
2634 }
2635
2636 /**
2637 * Sets the variant. If variant is null or the empty string, the
2638 * variant in this <code>Builder</code> is removed. Otherwise, it
2639 * must consist of one or more <a href="./Locale.html#def_variant">well-formed</a>
2640 * subtags, or an exception is thrown.
2641 *
2642 * <p><b>Note:</b> This method checks if <code>variant</code>
2643 * satisfies the IETF BCP 47 variant subtag's syntax requirements,
2644 * and normalizes the value to lowercase letters. However,
2645 * the <code>Locale</code> class does not impose any syntactic
2646 * restriction on variant, and the variant value in
2647 * <code>Locale</code> is case sensitive. To set such a variant,
2648 * use a Locale constructor.
2649 *
2650 * @param variant the variant
2651 * @return This builder.
2652 * @throws IllformedLocaleException if <code>variant</code> is ill-formed
2653 */
2654 public Builder setVariant(String variant) {
2655 try {
2656 localeBuilder.setVariant(variant);
2657 } catch (LocaleSyntaxException e) {
2658 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2659 }
2660 return this;
2661 }
2662
2663 /**
2664 * Sets the extension for the given key. If the value is null or the
2665 * empty string, the extension is removed. Otherwise, the extension
2666 * must be <a href="./Locale.html#def_extensions">well-formed</a> or an exception
2667 * is thrown.
2668 *
2669 * <p><b>Note:</b> The key {@link Locale#UNICODE_LOCALE_EXTENSION
2670 * UNICODE_LOCALE_EXTENSION} ('u') is used for the Unicode locale extension.
2671 * Setting a value for this key replaces any existing Unicode locale key/type
2672 * pairs with those defined in the extension.
2673 *
2674 * <p><b>Note:</b> The key {@link Locale#PRIVATE_USE_EXTENSION
2675 * PRIVATE_USE_EXTENSION} ('x') is used for the private use code. To be
2676 * well-formed, the value for this key needs only to have subtags of one to
2677 * eight alphanumeric characters, not two to eight as in the general case.
2678 *
2679 * @param key the extension key
2680 * @param value the extension value
2681 * @return This builder.
2682 * @throws IllformedLocaleException if <code>key</code> is illegal
2683 * or <code>value</code> is ill-formed
2684 * @see #setUnicodeLocaleKeyword(String, String)
2685 */
2686 public Builder setExtension(char key, String value) {
2687 try {
2688 localeBuilder.setExtension(key, value);
2689 } catch (LocaleSyntaxException e) {
2690 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2691 }
2692 return this;
2693 }
2694
2695 /**
2696 * Sets the Unicode locale keyword type for the given key. If the type
2697 * is null, the Unicode keyword is removed. Otherwise, the key must be
2698 * non-null and both key and type must be <a
2699 * href="./Locale.html#def_locale_extension">well-formed</a> or an exception
2700 * is thrown.
2701 *
2702 * <p>Keys and types are converted to lower case.
2703 *
2704 * <p><b>Note</b>:Setting the 'u' extension via {@link #setExtension}
2705 * replaces all Unicode locale keywords with those defined in the
2706 * extension.
2707 *
2708 * @param key the Unicode locale key
2709 * @param type the Unicode locale type
2710 * @return This builder.
2711 * @throws IllformedLocaleException if <code>key</code> or <code>type</code>
2712 * is ill-formed
2713 * @throws NullPointerException if <code>key</code> is null
2714 * @see #setExtension(char, String)
2715 */
2716 public Builder setUnicodeLocaleKeyword(String key, String type) {
2717 try {
2718 localeBuilder.setUnicodeLocaleKeyword(key, type);
2719 } catch (LocaleSyntaxException e) {
2720 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2721 }
2722 return this;
2723 }
2724
2725 /**
2726 * Adds a unicode locale attribute, if not already present, otherwise
2727 * has no effect. The attribute must not be null and must be <a
2728 * href="./Locale.html#def_locale_extension">well-formed</a> or an exception
2729 * is thrown.
2730 *
2731 * @param attribute the attribute
2732 * @return This builder.
2733 * @throws NullPointerException if <code>attribute</code> is null
2734 * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
2735 * @see #setExtension(char, String)
2736 */
2737 public Builder addUnicodeLocaleAttribute(String attribute) {
2738 try {
2739 localeBuilder.addUnicodeLocaleAttribute(attribute);
2740 } catch (LocaleSyntaxException e) {
2741 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2742 }
2743 return this;
2744 }
2745
2746 /**
2747 * Removes a unicode locale attribute, if present, otherwise has no
2748 * effect. The attribute must not be null and must be <a
2749 * href="./Locale.html#def_locale_extension">well-formed</a> or an exception
2750 * is thrown.
2751 *
2752 * <p>Attribute comparison for removal is case-insensitive.
2753 *
2754 * @param attribute the attribute
2755 * @return This builder.
2756 * @throws NullPointerException if <code>attribute</code> is null
2757 * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
2758 * @see #setExtension(char, String)
2759 */
2760 public Builder removeUnicodeLocaleAttribute(String attribute) {
2761 Objects.requireNonNull(attribute);
2762 try {
2763 localeBuilder.removeUnicodeLocaleAttribute(attribute);
2764 } catch (LocaleSyntaxException e) {
2765 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2766 }
2767 return this;
2768 }
2769
2770 /**
2771 * Resets the builder to its initial, empty state.
2772 *
2773 * @return This builder.
2774 */
2775 public Builder clear() {
2776 localeBuilder.clear();
2777 return this;
2778 }
2779
2780 /**
2781 * Resets the extensions to their initial, empty state.
2782 * Language, script, region and variant are unchanged.
2783 *
2784 * @return This builder.
2785 * @see #setExtension(char, String)
2786 */
2787 public Builder clearExtensions() {
2788 localeBuilder.clearExtensions();
2789 return this;
2790 }
2791
2792 /**
2793 * Returns an instance of <code>Locale</code> created from the fields set
2794 * on this builder.
2795 *
2796 * <p>This applies the conversions listed in {@link Locale#forLanguageTag}
2797 * when constructing a Locale. (Grandfathered tags are handled in
2798 * {@link #setLanguageTag}.)
2799 *
2800 * @return A Locale.
2801 */
2802 public Locale build() {
2803 BaseLocale baseloc = localeBuilder.getBaseLocale();
2804 LocaleExtensions extensions = localeBuilder.getLocaleExtensions();
2805 if (extensions == null && !baseloc.getVariant().isEmpty()) {
2806 extensions = getCompatibilityExtensions(baseloc.getLanguage(), baseloc.getScript(),
2807 baseloc.getRegion(), baseloc.getVariant());
2808 }
2809 return Locale.getInstance(baseloc, extensions);
2810 }
2811 }
2812
2813 /**
2814 * This enum provides constants to select a filtering mode for locale
2815 * matching. Refer to <a href="http://tools.ietf.org/html/rfc4647">RFC 4647
2816 * Matching of Language Tags</a> for details.
2817 *
2818 * <p>As an example, think of two Language Priority Lists each of which
2819 * includes only one language range and a set of following language tags:
2820 *
2821 * <pre>
2822 * de (German)
2823 * de-DE (German, Germany)
2824 * de-Deva (German, in Devanagari script)
2825 * de-Deva-DE (German, in Devanagari script, Germany)
2826 * de-DE-1996 (German, Germany, orthography of 1996)
2827 * de-Latn-DE (German, in Latin script, Germany)
2828 * de-Latn-DE-1996 (German, in Latin script, Germany, orthography of 1996)
2829 * </pre>
2830 *
2831 * The filtering method will behave as follows:
2832 *
2833 * <table class="striped">
2834 * <caption>Filtering method behavior</caption>
2835 * <thead>
2836 * <tr>
2837 * <th scope="col">Filtering Mode</th>
2838 * <th scope="col">Language Priority List: {@code "de-DE"}</th>
2839 * <th scope="col">Language Priority List: {@code "de-*-DE"}</th>
2840 * </tr>
2841 * </thead>
2842 * <tbody>
2843 * <tr>
2844 * <th scope="row" style="vertical-align:top">
2845 * {@link FilteringMode#AUTOSELECT_FILTERING AUTOSELECT_FILTERING}
2846 * </th>
2847 * <td style="vertical-align:top">
2848 * Performs <em>basic</em> filtering and returns {@code "de-DE"} and
2849 * {@code "de-DE-1996"}.
2850 * </td>
2851 * <td style="vertical-align:top">
2852 * Performs <em>extended</em> filtering and returns {@code "de-DE"},
2853 * {@code "de-Deva-DE"}, {@code "de-DE-1996"}, {@code "de-Latn-DE"}, and
2854 * {@code "de-Latn-DE-1996"}.
2855 * </td>
2856 * </tr>
2857 * <tr>
2858 * <th scope="row" style="vertical-align:top">
2859 * {@link FilteringMode#EXTENDED_FILTERING EXTENDED_FILTERING}
2860 * </th>
2861 * <td style="vertical-align:top">
2862 * Performs <em>extended</em> filtering and returns {@code "de-DE"},
2863 * {@code "de-Deva-DE"}, {@code "de-DE-1996"}, {@code "de-Latn-DE"}, and
2864 * {@code "de-Latn-DE-1996"}.
2865 * </td>
2866 * <td style="vertical-align:top">Same as above.</td>
2867 * </tr>
2868 * <tr>
2869 * <th scope="row" style="vertical-align:top">
2870 * {@link FilteringMode#IGNORE_EXTENDED_RANGES IGNORE_EXTENDED_RANGES}
2871 * </th>
2872 * <td style="vertical-align:top">
2873 * Performs <em>basic</em> filtering and returns {@code "de-DE"} and
2874 * {@code "de-DE-1996"}.
2875 * </td>
2876 * <td style="vertical-align:top">
2877 * Performs <em>basic</em> filtering and returns {@code null} because
2878 * nothing matches.
2879 * </td>
2880 * </tr>
2881 * <tr>
2882 * <th scope="row" style="vertical-align:top">
2883 * {@link FilteringMode#MAP_EXTENDED_RANGES MAP_EXTENDED_RANGES}
2884 * </th>
2885 * <td style="vertical-align:top">Same as above.</td>
2886 * <td style="vertical-align:top">
2887 * Performs <em>basic</em> filtering and returns {@code "de-DE"} and
2888 * {@code "de-DE-1996"} because {@code "de-*-DE"} is mapped to
2889 * {@code "de-DE"}.
2890 * </td>
2891 * </tr>
2892 * <tr>
2893 * <th scope="row" style="vertical-align:top">
2894 * {@link FilteringMode#REJECT_EXTENDED_RANGES REJECT_EXTENDED_RANGES}
2895 * </th>
2896 * <td style="vertical-align:top">Same as above.</td>
2897 * <td style="vertical-align:top">
2898 * Throws {@link IllegalArgumentException} because {@code "de-*-DE"} is
2899 * not a valid basic language range.
2900 * </td>
2901 * </tr>
2902 * </tbody>
2903 * </table>
2904 *
2905 * @see #filter(List, Collection, FilteringMode)
2906 * @see #filterTags(List, Collection, FilteringMode)
2907 *
2908 * @since 1.8
2909 */
2910 public static enum FilteringMode {
2911 /**
2912 * Specifies automatic filtering mode based on the given Language
2913 * Priority List consisting of language ranges. If all of the ranges
2914 * are basic, basic filtering is selected. Otherwise, extended
2915 * filtering is selected.
2916 */
2917 AUTOSELECT_FILTERING,
2918
2919 /**
2920 * Specifies extended filtering.
2921 */
2922 EXTENDED_FILTERING,
2923
2924 /**
2925 * Specifies basic filtering: Note that any extended language ranges
2926 * included in the given Language Priority List are ignored.
2927 */
2928 IGNORE_EXTENDED_RANGES,
2929
2930 /**
2931 * Specifies basic filtering: If any extended language ranges are
2932 * included in the given Language Priority List, they are mapped to the
2933 * basic language range. Specifically, a language range starting with a
2934 * subtag {@code "*"} is treated as a language range {@code "*"}. For
2935 * example, {@code "*-US"} is treated as {@code "*"}. If {@code "*"} is
2936 * not the first subtag, {@code "*"} and extra {@code "-"} are removed.
2937 * For example, {@code "ja-*-JP"} is mapped to {@code "ja-JP"}.
2938 */
2939 MAP_EXTENDED_RANGES,
2940
2941 /**
2942 * Specifies basic filtering: If any extended language ranges are
2943 * included in the given Language Priority List, the list is rejected
2944 * and the filtering method throws {@link IllegalArgumentException}.
2945 */
2946 REJECT_EXTENDED_RANGES
2947 };
2948
2949 /**
2950 * This class expresses a <em>Language Range</em> defined in
2951 * <a href="http://tools.ietf.org/html/rfc4647">RFC 4647 Matching of
2952 * Language Tags</a>. A language range is an identifier which is used to
2953 * select language tag(s) meeting specific requirements by using the
2954 * mechanisms described in <a href="Locale.html#LocaleMatching">Locale
2955 * Matching</a>. A list which represents a user's preferences and consists
2956 * of language ranges is called a <em>Language Priority List</em>.
2957 *
2958 * <p>There are two types of language ranges: basic and extended. In RFC
2959 * 4647, the syntax of language ranges is expressed in
2960 * <a href="http://tools.ietf.org/html/rfc4234">ABNF</a> as follows:
2961 * <blockquote>
2962 * <pre>
2963 * basic-language-range = (1*8ALPHA *("-" 1*8alphanum)) / "*"
2964 * extended-language-range = (1*8ALPHA / "*")
2965 * *("-" (1*8alphanum / "*"))
2966 * alphanum = ALPHA / DIGIT
2967 * </pre>
2968 * </blockquote>
2969 * For example, {@code "en"} (English), {@code "ja-JP"} (Japanese, Japan),
2970 * {@code "*"} (special language range which matches any language tag) are
2971 * basic language ranges, whereas {@code "*-CH"} (any languages,
2972 * Switzerland), {@code "es-*"} (Spanish, any regions), and
2973 * {@code "zh-Hant-*"} (Traditional Chinese, any regions) are extended
2974 * language ranges.
2975 *
2976 * @see #filter
2977 * @see #filterTags
2978 * @see #lookup
2979 * @see #lookupTag
2980 *
2981 * @since 1.8
2982 */
2983 public static final class LanguageRange {
2984
2985 /**
2986 * A constant holding the maximum value of weight, 1.0, which indicates
2987 * that the language range is a good fit for the user.
2988 */
2989 public static final double MAX_WEIGHT = 1.0;
2990
2991 /**
2992 * A constant holding the minimum value of weight, 0.0, which indicates
2993 * that the language range is not a good fit for the user.
2994 */
2995 public static final double MIN_WEIGHT = 0.0;
2996
2997 private final String range;
2998 private final double weight;
2999
3000 private volatile int hash;
3001
3002 /**
3003 * Constructs a {@code LanguageRange} using the given {@code range}.
3004 * Note that no validation is done against the IANA Language Subtag
3005 * Registry at time of construction.
3006 *
3007 * <p>This is equivalent to {@code LanguageRange(range, MAX_WEIGHT)}.
3008 *
3009 * @param range a language range
3010 * @throws NullPointerException if the given {@code range} is
3011 * {@code null}
3012 * @throws IllegalArgumentException if the given {@code range} does not
3013 * comply with the syntax of the language range mentioned in RFC 4647
3014 */
3015 public LanguageRange(String range) {
3016 this(range, MAX_WEIGHT);
3017 }
3018
3019 /**
3020 * Constructs a {@code LanguageRange} using the given {@code range} and
3021 * {@code weight}. Note that no validation is done against the IANA
3022 * Language Subtag Registry at time of construction.
3023 *
3024 * @param range a language range
3025 * @param weight a weight value between {@code MIN_WEIGHT} and
3026 * {@code MAX_WEIGHT}
3027 * @throws NullPointerException if the given {@code range} is
3028 * {@code null}
3029 * @throws IllegalArgumentException if the given {@code range} does not
3030 * comply with the syntax of the language range mentioned in RFC 4647
3031 * or if the given {@code weight} is less than {@code MIN_WEIGHT}
3032 * or greater than {@code MAX_WEIGHT}
3033 */
3034 public LanguageRange(String range, double weight) {
3035 if (range == null) {
3036 throw new NullPointerException();
3037 }
3038 if (weight < MIN_WEIGHT || weight > MAX_WEIGHT) {
3039 throw new IllegalArgumentException("weight=" + weight);
3040 }
3041
3042 range = range.toLowerCase(Locale.ROOT);
3043
3044 // Do syntax check.
3045 boolean isIllFormed = false;
3046 String[] subtags = range.split("-");
3047 if (isSubtagIllFormed(subtags[0], true)
3048 || range.endsWith("-")) {
3049 isIllFormed = true;
3050 } else {
3051 for (int i = 1; i < subtags.length; i++) {
3052 if (isSubtagIllFormed(subtags[i], false)) {
3053 isIllFormed = true;
3054 break;
3055 }
3056 }
3057 }
3058 if (isIllFormed) {
3059 throw new IllegalArgumentException("range=" + range);
3060 }
3061
3062 this.range = range;
3063 this.weight = weight;
3064 }
3065
3066 private static boolean isSubtagIllFormed(String subtag,
3067 boolean isFirstSubtag) {
3068 if (subtag.equals("") || subtag.length() > 8) {
3069 return true;
3070 } else if (subtag.equals("*")) {
3071 return false;
3072 }
3073 char[] charArray = subtag.toCharArray();
3074 if (isFirstSubtag) { // ALPHA
3075 for (char c : charArray) {
3076 if (c < 'a' || c > 'z') {
3077 return true;
3078 }
3079 }
3080 } else { // ALPHA / DIGIT
3081 for (char c : charArray) {
3082 if (c < '0' || (c > '9' && c < 'a') || c > 'z') {
3083 return true;
3084 }
3085 }
3086 }
3087 return false;
3088 }
3089
3090 /**
3091 * Returns the language range of this {@code LanguageRange}.
3092 *
3093 * @return the language range.
3094 */
3095 public String getRange() {
3096 return range;
3097 }
3098
3099 /**
3100 * Returns the weight of this {@code LanguageRange}.
3101 *
3102 * @return the weight value.
3103 */
3104 public double getWeight() {
3105 return weight;
3106 }
3107
3108 /**
3109 * Parses the given {@code ranges} to generate a Language Priority List.
3110 *
3111 * <p>This method performs a syntactic check for each language range in
3112 * the given {@code ranges} but doesn't do validation using the IANA
3113 * Language Subtag Registry.
3114 *
3115 * <p>The {@code ranges} to be given can take one of the following
3116 * forms:
3117 *
3118 * <pre>
3119 * "Accept-Language: ja,en;q=0.4" (weighted list with Accept-Language prefix)
3120 * "ja,en;q=0.4" (weighted list)
3121 * "ja,en" (prioritized list)
3122 * </pre>
3123 *
3124 * In a weighted list, each language range is given a weight value.
3125 * The weight value is identical to the "quality value" in
3126 * <a href="http://tools.ietf.org/html/rfc2616">RFC 2616</a>, and it
3127 * expresses how much the user prefers the language. A weight value is
3128 * specified after a corresponding language range followed by
3129 * {@code ";q="}, and the default weight value is {@code MAX_WEIGHT}
3130 * when it is omitted.
3131 *
3132 * <p>Unlike a weighted list, language ranges in a prioritized list
3133 * are sorted in the descending order based on its priority. The first
3134 * language range has the highest priority and meets the user's
3135 * preference most.
3136 *
3137 * <p>In either case, language ranges are sorted in descending order in
3138 * the Language Priority List based on priority or weight. If a
3139 * language range appears in the given {@code ranges} more than once,
3140 * only the first one is included on the Language Priority List.
3141 *
3142 * <p>The returned list consists of language ranges from the given
3143 * {@code ranges} and their equivalents found in the IANA Language
3144 * Subtag Registry. For example, if the given {@code ranges} is
3145 * {@code "Accept-Language: iw,en-us;q=0.7,en;q=0.3"}, the elements in
3146 * the list to be returned are:
3147 *
3148 * <pre>
3149 * <b>Range</b> <b>Weight</b>
3150 * "iw" (older tag for Hebrew) 1.0
3151 * "he" (new preferred code for Hebrew) 1.0
3152 * "en-us" (English, United States) 0.7
3153 * "en" (English) 0.3
3154 * </pre>
3155 *
3156 * Two language ranges, {@code "iw"} and {@code "he"}, have the same
3157 * highest priority in the list. By adding {@code "he"} to the user's
3158 * Language Priority List, locale-matching method can find Hebrew as a
3159 * matching locale (or language tag) even if the application or system
3160 * offers only {@code "he"} as a supported locale (or language tag).
3161 *
3162 * @param ranges a list of comma-separated language ranges or a list of
3163 * language ranges in the form of the "Accept-Language" header
3164 * defined in <a href="http://tools.ietf.org/html/rfc2616">RFC
3165 * 2616</a>
3166 * @return a Language Priority List consisting of language ranges
3167 * included in the given {@code ranges} and their equivalent
3168 * language ranges if available. The list is modifiable.
3169 * @throws NullPointerException if {@code ranges} is null
3170 * @throws IllegalArgumentException if a language range or a weight
3171 * found in the given {@code ranges} is ill-formed
3172 */
3173 public static List<LanguageRange> parse(String ranges) {
3174 return LocaleMatcher.parse(ranges);
3175 }
3176
3177 /**
3178 * Parses the given {@code ranges} to generate a Language Priority
3179 * List, and then customizes the list using the given {@code map}.
3180 * This method is equivalent to
3181 * {@code mapEquivalents(parse(ranges), map)}.
3182 *
3183 * @param ranges a list of comma-separated language ranges or a list
3184 * of language ranges in the form of the "Accept-Language" header
3185 * defined in <a href="http://tools.ietf.org/html/rfc2616">RFC
3186 * 2616</a>
3187 * @param map a map containing information to customize language ranges
3188 * @return a Language Priority List with customization. The list is
3189 * modifiable.
3190 * @throws NullPointerException if {@code ranges} is null
3191 * @throws IllegalArgumentException if a language range or a weight
3192 * found in the given {@code ranges} is ill-formed
3193 * @see #parse(String)
3194 * @see #mapEquivalents
3195 */
3196 public static List<LanguageRange> parse(String ranges,
3197 Map<String, List<String>> map) {
3198 return mapEquivalents(parse(ranges), map);
3199 }
3200
3201 /**
3202 * Generates a new customized Language Priority List using the given
3203 * {@code priorityList} and {@code map}. If the given {@code map} is
3204 * empty, this method returns a copy of the given {@code priorityList}.
3205 *
3206 * <p>In the map, a key represents a language range whereas a value is
3207 * a list of equivalents of it. {@code '*'} cannot be used in the map.
3208 * Each equivalent language range has the same weight value as its
3209 * original language range.
3210 *
3211 * <pre>
3212 * An example of map:
3213 * <b>Key</b> <b>Value</b>
3214 * "zh" (Chinese) "zh",
3215 * "zh-Hans"(Simplified Chinese)
3216 * "zh-HK" (Chinese, Hong Kong) "zh-HK"
3217 * "zh-TW" (Chinese, Taiwan) "zh-TW"
3218 * </pre>
3219 *
3220 * The customization is performed after modification using the IANA
3221 * Language Subtag Registry.
3222 *
3223 * <p>For example, if a user's Language Priority List consists of five
3224 * language ranges ({@code "zh"}, {@code "zh-CN"}, {@code "en"},
3225 * {@code "zh-TW"}, and {@code "zh-HK"}), the newly generated Language
3226 * Priority List which is customized using the above map example will
3227 * consists of {@code "zh"}, {@code "zh-Hans"}, {@code "zh-CN"},
3228 * {@code "zh-Hans-CN"}, {@code "en"}, {@code "zh-TW"}, and
3229 * {@code "zh-HK"}.
3230 *
3231 * <p>{@code "zh-HK"} and {@code "zh-TW"} aren't converted to
3232 * {@code "zh-Hans-HK"} nor {@code "zh-Hans-TW"} even if they are
3233 * included in the Language Priority List. In this example, mapping
3234 * is used to clearly distinguish Simplified Chinese and Traditional
3235 * Chinese.
3236 *
3237 * <p>If the {@code "zh"}-to-{@code "zh"} mapping isn't included in the
3238 * map, a simple replacement will be performed and the customized list
3239 * won't include {@code "zh"} and {@code "zh-CN"}.
3240 *
3241 * @param priorityList user's Language Priority List
3242 * @param map a map containing information to customize language ranges
3243 * @return a new Language Priority List with customization. The list is
3244 * modifiable.
3245 * @throws NullPointerException if {@code priorityList} is {@code null}
3246 * @see #parse(String, Map)
3247 */
3248 public static List<LanguageRange> mapEquivalents(
3249 List<LanguageRange>priorityList,
3250 Map<String, List<String>> map) {
3251 return LocaleMatcher.mapEquivalents(priorityList, map);
3252 }
3253
3254 /**
3255 * Returns a hash code value for the object.
3256 *
3257 * @return a hash code value for this object.
3258 */
3259 @Override
3260 public int hashCode() {
3261 int h = hash;
3262 if (h == 0) {
3263 h = 17;
3264 h = 37*h + range.hashCode();
3265 long bitsWeight = Double.doubleToLongBits(weight);
3266 h = 37*h + (int)(bitsWeight ^ (bitsWeight >>> 32));
3267 if (h != 0) {
3268 hash = h;
3269 }
3270 }
3271 return h;
3272 }
3273
3274 /**
3275 * Compares this object to the specified object. The result is true if
3276 * and only if the argument is not {@code null} and is a
3277 * {@code LanguageRange} object that contains the same {@code range}
3278 * and {@code weight} values as this object.
3279 *
3280 * @param obj the object to compare with
3281 * @return {@code true} if this object's {@code range} and
3282 * {@code weight} are the same as the {@code obj}'s; {@code false}
3283 * otherwise.
3284 */
3285 @Override
3286 public boolean equals(Object obj) {
3287 if (this == obj) {
3288 return true;
3289 }
3290 if (!(obj instanceof LanguageRange)) {
3291 return false;
3292 }
3293 LanguageRange other = (LanguageRange)obj;
3294 return hash == other.hash
3295 && range.equals(other.range)
3296 && weight == other.weight;
3297 }
3298
3299 /**
3300 * Returns an informative string representation of this {@code LanguageRange}
3301 * object, consisting of language range and weight if the range is
3302 * weighted and the weight is less than the max weight.
3303 *
3304 * @return a string representation of this {@code LanguageRange} object.
3305 */
3306 @Override
3307 public String toString() {
3308 return (weight == MAX_WEIGHT) ? range : range + ";q=" + weight;
3309 }
3310 }
3311
3312 /**
3313 * Returns a list of matching {@code Locale} instances using the filtering
3314 * mechanism defined in RFC 4647.
3315 *
3316 * This filter operation on the given {@code locales} ensures that only
3317 * unique matching locale(s) are returned.
3318 *
3319 * @param priorityList user's Language Priority List in which each language
3320 * tag is sorted in descending order based on priority or weight
3321 * @param locales {@code Locale} instances used for matching
3322 * @param mode filtering mode
3323 * @return a list of {@code Locale} instances for matching language tags
3324 * sorted in descending order based on priority or weight, or an empty
3325 * list if nothing matches. The list is modifiable.
3326 * @throws NullPointerException if {@code priorityList} or {@code locales}
3327 * is {@code null}
3328 * @throws IllegalArgumentException if one or more extended language ranges
3329 * are included in the given list when
3330 * {@link FilteringMode#REJECT_EXTENDED_RANGES} is specified
3331 *
3332 * @since 1.8
3333 */
3334 public static List<Locale> filter(List<LanguageRange> priorityList,
3335 Collection<Locale> locales,
3336 FilteringMode mode) {
3337 return LocaleMatcher.filter(priorityList, locales, mode);
3338 }
3339
3340 /**
3341 * Returns a list of matching {@code Locale} instances using the filtering
3342 * mechanism defined in RFC 4647. This is equivalent to
3343 * {@link #filter(List, Collection, FilteringMode)} when {@code mode} is
3344 * {@link FilteringMode#AUTOSELECT_FILTERING}.
3345 *
3346 * This filter operation on the given {@code locales} ensures that only
3347 * unique matching locale(s) are returned.
3348 *
3349 * @param priorityList user's Language Priority List in which each language
3350 * tag is sorted in descending order based on priority or weight
3351 * @param locales {@code Locale} instances used for matching
3352 * @return a list of {@code Locale} instances for matching language tags
3353 * sorted in descending order based on priority or weight, or an empty
3354 * list if nothing matches. The list is modifiable.
3355 * @throws NullPointerException if {@code priorityList} or {@code locales}
3356 * is {@code null}
3357 *
3358 * @since 1.8
3359 */
3360 public static List<Locale> filter(List<LanguageRange> priorityList,
3361 Collection<Locale> locales) {
3362 return filter(priorityList, locales, FilteringMode.AUTOSELECT_FILTERING);
3363 }
3364
3365 /**
3366 * Returns a list of matching languages tags using the basic filtering
3367 * mechanism defined in RFC 4647.
3368 *
3369 * This filter operation on the given {@code tags} ensures that only
3370 * unique matching tag(s) are returned with preserved case. In case of
3371 * duplicate matching tags with the case difference, the first matching
3372 * tag with preserved case is returned.
3373 * For example, "de-ch" is returned out of the duplicate matching tags
3374 * "de-ch" and "de-CH", if "de-ch" is checked first for matching in the
3375 * given {@code tags}. Note that if the given {@code tags} is an unordered
3376 * {@code Collection}, the returned matching tag out of duplicate tags is
3377 * subject to change, depending on the implementation of the
3378 * {@code Collection}.
3379 *
3380 * @param priorityList user's Language Priority List in which each language
3381 * tag is sorted in descending order based on priority or weight
3382 * @param tags language tags
3383 * @param mode filtering mode
3384 * @return a list of matching language tags sorted in descending order
3385 * based on priority or weight, or an empty list if nothing matches.
3386 * The list is modifiable.
3387 * @throws NullPointerException if {@code priorityList} or {@code tags} is
3388 * {@code null}
3389 * @throws IllegalArgumentException if one or more extended language ranges
3390 * are included in the given list when
3391 * {@link FilteringMode#REJECT_EXTENDED_RANGES} is specified
3392 *
3393 * @since 1.8
3394 */
3395 public static List<String> filterTags(List<LanguageRange> priorityList,
3396 Collection<String> tags,
3397 FilteringMode mode) {
3398 return LocaleMatcher.filterTags(priorityList, tags, mode);
3399 }
3400
3401 /**
3402 * Returns a list of matching languages tags using the basic filtering
3403 * mechanism defined in RFC 4647. This is equivalent to
3404 * {@link #filterTags(List, Collection, FilteringMode)} when {@code mode}
3405 * is {@link FilteringMode#AUTOSELECT_FILTERING}.
3406 *
3407 * This filter operation on the given {@code tags} ensures that only
3408 * unique matching tag(s) are returned with preserved case. In case of
3409 * duplicate matching tags with the case difference, the first matching
3410 * tag with preserved case is returned.
3411 * For example, "de-ch" is returned out of the duplicate matching tags
3412 * "de-ch" and "de-CH", if "de-ch" is checked first for matching in the
3413 * given {@code tags}. Note that if the given {@code tags} is an unordered
3414 * {@code Collection}, the returned matching tag out of duplicate tags is
3415 * subject to change, depending on the implementation of the
3416 * {@code Collection}.
3417 *
3418 * @param priorityList user's Language Priority List in which each language
3419 * tag is sorted in descending order based on priority or weight
3420 * @param tags language tags
3421 * @return a list of matching language tags sorted in descending order
3422 * based on priority or weight, or an empty list if nothing matches.
3423 * The list is modifiable.
3424 * @throws NullPointerException if {@code priorityList} or {@code tags} is
3425 * {@code null}
3426 *
3427 * @since 1.8
3428 */
3429 public static List<String> filterTags(List<LanguageRange> priorityList,
3430 Collection<String> tags) {
3431 return filterTags(priorityList, tags, FilteringMode.AUTOSELECT_FILTERING);
3432 }
3433
3434 /**
3435 * Returns a {@code Locale} instance for the best-matching language
3436 * tag using the lookup mechanism defined in RFC 4647.
3437 *
3438 * @param priorityList user's Language Priority List in which each language
3439 * tag is sorted in descending order based on priority or weight
3440 * @param locales {@code Locale} instances used for matching
3441 * @return the best matching <code>Locale</code> instance chosen based on
3442 * priority or weight, or {@code null} if nothing matches.
3443 * @throws NullPointerException if {@code priorityList} or {@code tags} is
3444 * {@code null}
3445 *
3446 * @since 1.8
3447 */
3448 public static Locale lookup(List<LanguageRange> priorityList,
3449 Collection<Locale> locales) {
3450 return LocaleMatcher.lookup(priorityList, locales);
3451 }
3452
3453 /**
3454 * Returns the best-matching language tag using the lookup mechanism
3455 * defined in RFC 4647.
3456 *
3457 * This lookup operation on the given {@code tags} ensures that the
3458 * first matching tag with preserved case is returned.
3459 *
3460 * @param priorityList user's Language Priority List in which each language
3461 * tag is sorted in descending order based on priority or weight
3462 * @param tags language tangs used for matching
3463 * @return the best matching language tag chosen based on priority or
3464 * weight, or {@code null} if nothing matches.
3465 * @throws NullPointerException if {@code priorityList} or {@code tags} is
3466 * {@code null}
3467 *
3468 * @since 1.8
3469 */
3470 public static String lookupTag(List<LanguageRange> priorityList,
3471 Collection<String> tags) {
3472 return LocaleMatcher.lookupTag(priorityList, tags);
3473 }
3474
3475 }
3476