Locale.java revision 576d068c35ff06115b74d26ce726ea141ba8f5f1
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27/* 28 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved 29 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved 30 * 31 * The original version of this source code and documentation 32 * is copyrighted and owned by Taligent, Inc., a wholly-owned 33 * subsidiary of IBM. These materials are provided under terms 34 * of a License Agreement between Taligent and Sun. This technology 35 * is protected by multiple US and International patents. 36 * 37 * This notice and attribution to Taligent may not be removed. 38 * Taligent is a registered trademark of Taligent, Inc. 39 * 40 */ 41 42package java.util; 43 44import java.io.IOException; 45import java.io.ObjectInputStream; 46import java.io.ObjectOutputStream; 47import java.io.ObjectStreamField; 48import java.io.Serializable; 49import java.security.AccessController; 50import java.text.MessageFormat; 51import java.util.spi.LocaleNameProvider; 52import libcore.icu.ICU; 53 54import sun.security.action.GetPropertyAction; 55import sun.util.LocaleServiceProviderPool; 56import sun.util.locale.BaseLocale; 57import sun.util.locale.InternalLocaleBuilder; 58import sun.util.locale.LanguageTag; 59import sun.util.locale.LocaleExtensions; 60import sun.util.locale.LocaleObjectCache; 61import sun.util.locale.LocaleSyntaxException; 62import sun.util.locale.LocaleUtils; 63import sun.util.locale.ParseStatus; 64import sun.util.locale.UnicodeLocaleExtension; 65 66/** 67 * A <code>Locale</code> object represents a specific geographical, political, 68 * or cultural region. An operation that requires a <code>Locale</code> to perform 69 * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code> 70 * to tailor information for the user. For example, displaying a number 71 * is a locale-sensitive operation— the number should be formatted 72 * according to the customs and conventions of the user's native country, 73 * region, or culture. 74 * 75 * <p> The <code>Locale</code> class implements identifiers 76 * interchangeable with BCP 47 (IETF BCP 47, "Tags for Identifying 77 * Languages"), with support for the LDML (UTS#35, "Unicode Locale 78 * Data Markup Language") BCP 47-compatible extensions for locale data 79 * exchange. 80 * 81 * <p> A <code>Locale</code> object logically consists of the fields 82 * described below. 83 * 84 * <dl> 85 * <dt><a name="def_language"><b>language</b></a></dt> 86 * 87 * <dd>ISO 639 alpha-2 or alpha-3 language code, or registered 88 * language subtags up to 8 alpha letters (for future enhancements). 89 * When a language has both an alpha-2 code and an alpha-3 code, the 90 * alpha-2 code must be used. You can find a full list of valid 91 * language codes in the IANA Language Subtag Registry (search for 92 * "Type: language"). The language field is case insensitive, but 93 * <code>Locale</code> always canonicalizes to lower case.</dd> 94 * 95 * <dd>Well-formed language values have the form 96 * <code>[a-zA-Z]{2,8}</code>. Note that this is not the the full 97 * BCP47 language production, since it excludes extlang. They are 98 * not needed since modern three-letter language codes replace 99 * them.</dd> 100 * 101 * <dd>Example: "en" (English), "ja" (Japanese), "kok" (Konkani)</dd> 102 * 103 * <dt><a name="def_script"><b>script</b></a></dt> 104 * 105 * <dd>ISO 15924 alpha-4 script code. You can find a full list of 106 * valid script codes in the IANA Language Subtag Registry (search 107 * for "Type: script"). The script field is case insensitive, but 108 * <code>Locale</code> always canonicalizes to title case (the first 109 * letter is upper case and the rest of the letters are lower 110 * case).</dd> 111 * 112 * <dd>Well-formed script values have the form 113 * <code>[a-zA-Z]{4}</code></dd> 114 * 115 * <dd>Example: "Latn" (Latin), "Cyrl" (Cyrillic)</dd> 116 * 117 * <dt><a name="def_region"><b>country (region)</b></a></dt> 118 * 119 * <dd>ISO 3166 alpha-2 country code or UN M.49 numeric-3 area code. 120 * You can find a full list of valid country and region codes in the 121 * IANA Language Subtag Registry (search for "Type: region"). The 122 * country (region) field is case insensitive, but 123 * <code>Locale</code> always canonicalizes to upper case.</dd> 124 * 125 * <dd>Well-formed country/region values have 126 * the form <code>[a-zA-Z]{2} | [0-9]{3}</code></dd> 127 * 128 * <dd>Example: "US" (United States), "FR" (France), "029" 129 * (Caribbean)</dd> 130 * 131 * <dt><a name="def_variant"><b>variant</b></a></dt> 132 * 133 * <dd>Any arbitrary value used to indicate a variation of a 134 * <code>Locale</code>. Where there are two or more variant values 135 * each indicating its own semantics, these values should be ordered 136 * by importance, with most important first, separated by 137 * underscore('_'). The variant field is case sensitive.</dd> 138 * 139 * <dd>Note: IETF BCP 47 places syntactic restrictions on variant 140 * subtags. Also BCP 47 subtags are strictly used to indicate 141 * additional variations that define a language or its dialects that 142 * are not covered by any combinations of language, script and 143 * region subtags. You can find a full list of valid variant codes 144 * in the IANA Language Subtag Registry (search for "Type: variant"). 145 * 146 * <p>However, the variant field in <code>Locale</code> has 147 * historically been used for any kind of variation, not just 148 * language variations. For example, some supported variants 149 * available in Java SE Runtime Environments indicate alternative 150 * cultural behaviors such as calendar type or number script. In 151 * BCP 47 this kind of information, which does not identify the 152 * language, is supported by extension subtags or private use 153 * subtags.</dd> 154 * 155 * <dd>Well-formed variant values have the form <code>SUBTAG 156 * (('_'|'-') SUBTAG)*</code> where <code>SUBTAG = 157 * [0-9][0-9a-zA-Z]{3} | [0-9a-zA-Z]{5,8}</code>. (Note: BCP 47 only 158 * uses hyphen ('-') as a delimiter, this is more lenient).</dd> 159 * 160 * <dd>Example: "polyton" (Polytonic Greek), "POSIX"</dd> 161 * 162 * <dt><a name="def_extensions"><b>extensions</b></a></dt> 163 * 164 * <dd>A map from single character keys to string values, indicating 165 * extensions apart from language identification. The extensions in 166 * <code>Locale</code> implement the semantics and syntax of BCP 47 167 * extension subtags and private use subtags. The extensions are 168 * case insensitive, but <code>Locale</code> canonicalizes all 169 * extension keys and values to lower case. Note that extensions 170 * cannot have empty values.</dd> 171 * 172 * <dd>Well-formed keys are single characters from the set 173 * <code>[0-9a-zA-Z]</code>. Well-formed values have the form 174 * <code>SUBTAG ('-' SUBTAG)*</code> where for the key 'x' 175 * <code>SUBTAG = [0-9a-zA-Z]{1,8}</code> and for other keys 176 * <code>SUBTAG = [0-9a-zA-Z]{2,8}</code> (that is, 'x' allows 177 * single-character subtags).</dd> 178 * 179 * <dd>Example: key="u"/value="ca-japanese" (Japanese Calendar), 180 * key="x"/value="java-1-7"</dd> 181 * </dl> 182 * 183 * <b>Note:</b> Although BCP 47 requires field values to be registered 184 * in the IANA Language Subtag Registry, the <code>Locale</code> class 185 * does not provide any validation features. The <code>Builder</code> 186 * only checks if an individual field satisfies the syntactic 187 * requirement (is well-formed), but does not validate the value 188 * itself. See {@link Builder} for details. 189 * 190 * <h3><a name="def_locale_extension">Unicode locale/language extension</a></h3> 191 * 192 * <p>UTS#35, "Unicode Locale Data Markup Language" defines optional 193 * attributes and keywords to override or refine the default behavior 194 * associated with a locale. A keyword is represented by a pair of 195 * key and type. For example, "nu-thai" indicates that Thai local 196 * digits (value:"thai") should be used for formatting numbers 197 * (key:"nu"). 198 * 199 * <p>The keywords are mapped to a BCP 47 extension value using the 200 * extension key 'u' ({@link #UNICODE_LOCALE_EXTENSION}). The above 201 * example, "nu-thai", becomes the extension "u-nu-thai".code 202 * 203 * <p>Thus, when a <code>Locale</code> object contains Unicode locale 204 * attributes and keywords, 205 * <code>getExtension(UNICODE_LOCALE_EXTENSION)</code> will return a 206 * String representing this information, for example, "nu-thai". The 207 * <code>Locale</code> class also provides {@link 208 * #getUnicodeLocaleAttributes}, {@link #getUnicodeLocaleKeys}, and 209 * {@link #getUnicodeLocaleType} which allow you to access Unicode 210 * locale attributes and key/type pairs directly. When represented as 211 * a string, the Unicode Locale Extension lists attributes 212 * alphabetically, followed by key/type sequences with keys listed 213 * alphabetically (the order of subtags comprising a key's type is 214 * fixed when the type is defined) 215 * 216 * <p>A well-formed locale key has the form 217 * <code>[0-9a-zA-Z]{2}</code>. A well-formed locale type has the 218 * form <code>"" | [0-9a-zA-Z]{3,8} ('-' [0-9a-zA-Z]{3,8})*</code> (it 219 * can be empty, or a series of subtags 3-8 alphanums in length). A 220 * well-formed locale attribute has the form 221 * <code>[0-9a-zA-Z]{3,8}</code> (it is a single subtag with the same 222 * form as a locale type subtag). 223 * 224 * <p>The Unicode locale extension specifies optional behavior in 225 * locale-sensitive services. Although the LDML specification defines 226 * various keys and values, actual locale-sensitive service 227 * implementations in a Java Runtime Environment might not support any 228 * particular Unicode locale attributes or key/type pairs. 229 * 230 * <h4>Creating a Locale</h4> 231 * 232 * <p>There are several different ways to create a <code>Locale</code> 233 * object. 234 * 235 * <h5>Builder</h5> 236 * 237 * <p>Using {@link Builder} you can construct a <code>Locale</code> object 238 * that conforms to BCP 47 syntax. 239 * 240 * <h5>Constructors</h5> 241 * 242 * <p>The <code>Locale</code> class provides three constructors: 243 * <blockquote> 244 * <pre> 245 * {@link #Locale(String language)} 246 * {@link #Locale(String language, String country)} 247 * {@link #Locale(String language, String country, String variant)} 248 * </pre> 249 * </blockquote> 250 * These constructors allow you to create a <code>Locale</code> object 251 * with language, country and variant, but you cannot specify 252 * script or extensions. 253 * 254 * <h5>Factory Methods</h5> 255 * 256 * <p>The method {@link #forLanguageTag} creates a <code>Locale</code> 257 * object for a well-formed BCP 47 language tag. 258 * 259 * <h5>Locale Constants</h5> 260 * 261 * <p>The <code>Locale</code> class provides a number of convenient constants 262 * that you can use to create <code>Locale</code> objects for commonly used 263 * locales. For example, the following creates a <code>Locale</code> object 264 * for the United States: 265 * <blockquote> 266 * <pre> 267 * Locale.US 268 * </pre> 269 * </blockquote> 270 * 271 * <h4>Use of Locale</h4> 272 * 273 * <p>Once you've created a <code>Locale</code> you can query it for information 274 * about itself. Use <code>getCountry</code> to get the country (or region) 275 * code and <code>getLanguage</code> to get the language code. 276 * You can use <code>getDisplayCountry</code> to get the 277 * name of the country suitable for displaying to the user. Similarly, 278 * you can use <code>getDisplayLanguage</code> to get the name of 279 * the language suitable for displaying to the user. Interestingly, 280 * the <code>getDisplayXXX</code> methods are themselves locale-sensitive 281 * and have two versions: one that uses the default 282 * {@link Locale.Category#DISPLAY DISPLAY} locale and one 283 * that uses the locale specified as an argument. 284 * 285 * <p>The Java Platform provides a number of classes that perform locale-sensitive 286 * operations. For example, the <code>NumberFormat</code> class formats 287 * numbers, currency, and percentages in a locale-sensitive manner. Classes 288 * such as <code>NumberFormat</code> have several convenience methods 289 * for creating a default object of that type. For example, the 290 * <code>NumberFormat</code> class provides these three convenience methods 291 * for creating a default <code>NumberFormat</code> object: 292 * <blockquote> 293 * <pre> 294 * NumberFormat.getInstance() 295 * NumberFormat.getCurrencyInstance() 296 * NumberFormat.getPercentInstance() 297 * </pre> 298 * </blockquote> 299 * Each of these methods has two variants; one with an explicit locale 300 * and one without; the latter uses the default 301 * {@link Locale.Category#FORMAT FORMAT} locale: 302 * <blockquote> 303 * <pre> 304 * NumberFormat.getInstance(myLocale) 305 * NumberFormat.getCurrencyInstance(myLocale) 306 * NumberFormat.getPercentInstance(myLocale) 307 * </pre> 308 * </blockquote> 309 * A <code>Locale</code> is the mechanism for identifying the kind of object 310 * (<code>NumberFormat</code>) that you would like to get. The locale is 311 * <STRONG>just</STRONG> a mechanism for identifying objects, 312 * <STRONG>not</STRONG> a container for the objects themselves. 313 * 314 * <h4>Compatibility</h4> 315 * 316 * <p>In order to maintain compatibility with existing usage, Locale's 317 * constructors retain their behavior prior to the Java Runtime 318 * Environment version 1.7. The same is largely true for the 319 * <code>toString</code> method. Thus Locale objects can continue to 320 * be used as they were. In particular, clients who parse the output 321 * of toString into language, country, and variant fields can continue 322 * to do so (although this is strongly discouraged), although the 323 * variant field will have additional information in it if script or 324 * extensions are present. 325 * 326 * <p>In addition, BCP 47 imposes syntax restrictions that are not 327 * imposed by Locale's constructors. This means that conversions 328 * between some Locales and BCP 47 language tags cannot be made without 329 * losing information. Thus <code>toLanguageTag</code> cannot 330 * represent the state of locales whose language, country, or variant 331 * do not conform to BCP 47. 332 * 333 * <p>Because of these issues, it is recommended that clients migrate 334 * away from constructing non-conforming locales and use the 335 * <code>forLanguageTag</code> and <code>Locale.Builder</code> APIs instead. 336 * Clients desiring a string representation of the complete locale can 337 * then always rely on <code>toLanguageTag</code> for this purpose. 338 * 339 * <h5><a name="special_cases_constructor">Special cases</a></h5> 340 * 341 * <p>For compatibility reasons, two 342 * non-conforming locales are treated as special cases. These are 343 * <b><tt>ja_JP_JP</tt></b> and <b><tt>th_TH_TH</tt></b>. These are ill-formed 344 * in BCP 47 since the variants are too short. To ease migration to BCP 47, 345 * these are treated specially during construction. These two cases (and only 346 * these) cause a constructor to generate an extension, all other values behave 347 * exactly as they did prior to Java 7. 348 * 349 * <p>Java has used <tt>ja_JP_JP</tt> to represent Japanese as used in 350 * Japan together with the Japanese Imperial calendar. This is now 351 * representable using a Unicode locale extension, by specifying the 352 * Unicode locale key <tt>ca</tt> (for "calendar") and type 353 * <tt>japanese</tt>. When the Locale constructor is called with the 354 * arguments "ja", "JP", "JP", the extension "u-ca-japanese" is 355 * automatically added. 356 * 357 * <p>Java has used <tt>th_TH_TH</tt> to represent Thai as used in 358 * Thailand together with Thai digits. This is also now representable using 359 * a Unicode locale extension, by specifying the Unicode locale key 360 * <tt>nu</tt> (for "number") and value <tt>thai</tt>. When the Locale 361 * constructor is called with the arguments "th", "TH", "TH", the 362 * extension "u-nu-thai" is automatically added. 363 * 364 * <h5>Serialization</h5> 365 * 366 * <p>During serialization, writeObject writes all fields to the output 367 * stream, including extensions. 368 * 369 * <p>During deserialization, readResolve adds extensions as described 370 * in <a href="#special_cases_constructor">Special Cases</a>, only 371 * for the two cases th_TH_TH and ja_JP_JP. 372 * 373 * <h5>Legacy language codes</h5> 374 * 375 * <p>Locale's constructor has always converted three language codes to 376 * their earlier, obsoleted forms: <tt>he</tt> maps to <tt>iw</tt>, 377 * <tt>yi</tt> maps to <tt>ji</tt>, and <tt>id</tt> maps to 378 * <tt>in</tt>. This continues to be the case, in order to not break 379 * backwards compatibility. 380 * 381 * <p>The APIs added in 1.7 map between the old and new language codes, 382 * maintaining the old codes internal to Locale (so that 383 * <code>getLanguage</code> and <code>toString</code> reflect the old 384 * code), but using the new codes in the BCP 47 language tag APIs (so 385 * that <code>toLanguageTag</code> reflects the new one). This 386 * preserves the equivalence between Locales no matter which code or 387 * API is used to construct them. Java's default resource bundle 388 * lookup mechanism also implements this mapping, so that resources 389 * can be named using either convention, see {@link ResourceBundle.Control}. 390 * 391 * <h5>Three-letter language/country(region) codes</h5> 392 * 393 * <p>The Locale constructors have always specified that the language 394 * and the country param be two characters in length, although in 395 * practice they have accepted any length. The specification has now 396 * been relaxed to allow language codes of two to eight characters and 397 * country (region) codes of two to three characters, and in 398 * particular, three-letter language codes and three-digit region 399 * codes as specified in the IANA Language Subtag Registry. For 400 * compatibility, the implementation still does not impose a length 401 * constraint. 402 * 403 * <a name="locale_data"></a><h4>Locale data</h4> 404 * <p>Note that locale data comes solely from ICU. User-supplied locale service providers (using 405 * the {@code java.text.spi} or {@code java.util.spi} mechanisms) are not supported. 406 * 407 * <p>Here are the versions of ICU (and the corresponding CLDR and Unicode versions) used in 408 * various Android releases: 409 * <table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY=""> 410 * <tr><td>Android 1.5 (Cupcake)/Android 1.6 (Donut)/Android 2.0 (Eclair)</td> 411 * <td>ICU 3.8</td> 412 * <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-5">CLDR 1.5</a></td> 413 * <td><a href="http://www.unicode.org/versions/Unicode5.0.0/">Unicode 5.0</a></td></tr> 414 * <tr><td>Android 2.2 (Froyo)</td> 415 * <td>ICU 4.2</td> 416 * <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-7">CLDR 1.7</a></td> 417 * <td><a href="http://www.unicode.org/versions/Unicode5.1.0/">Unicode 5.1</a></td></tr> 418 * <tr><td>Android 2.3 (Gingerbread)/Android 3.0 (Honeycomb)</td> 419 * <td>ICU 4.4</td> 420 * <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-8">CLDR 1.8</a></td> 421 * <td><a href="http://www.unicode.org/versions/Unicode5.2.0/">Unicode 5.2</a></td></tr> 422 * <tr><td>Android 4.0 (Ice Cream Sandwich)</td> 423 * <td><a href="http://site.icu-project.org/download/46">ICU 4.6</a></td> 424 * <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-9">CLDR 1.9</a></td> 425 * <td><a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode 6.0</a></td></tr> 426 * <tr><td>Android 4.1 (Jelly Bean)</td> 427 * <td><a href="http://site.icu-project.org/download/48">ICU 4.8</a></td> 428 * <td><a href="http://cldr.unicode.org/index/downloads/cldr-2-0">CLDR 2.0</a></td> 429 * <td><a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode 6.0</a></td></tr> 430 * <tr><td>Android 4.3 (Jelly Bean MR2)</td> 431 * <td><a href="http://site.icu-project.org/download/50">ICU 50</a></td> 432 * <td><a href="http://cldr.unicode.org/index/downloads/cldr-22-1">CLDR 22.1</a></td> 433 * <td><a href="http://www.unicode.org/versions/Unicode6.2.0/">Unicode 6.2</a></td></tr> 434 * <tr><td>Android 4.4 (KitKat)</td> 435 * <td><a href="http://site.icu-project.org/download/51">ICU 51</a></td> 436 * <td><a href="http://cldr.unicode.org/index/downloads/cldr-23">CLDR 23</a></td> 437 * <td><a href="http://www.unicode.org/versions/Unicode6.2.0/">Unicode 6.2</a></td></tr> 438 * <tr><td>Android 5.0 (Lollipop)</td> 439 * <td><a href="http://site.icu-project.org/download/53">ICU 53</a></td> 440 * <td><a href="http://cldr.unicode.org/index/downloads/cldr-25">CLDR 25</a></td> 441 * <td><a href="http://www.unicode.org/versions/Unicode6.3.0/">Unicode 6.3</a></td></tr> 442 * <tr><td>Android 6.0 (Marshmallow)</td> 443 * <td><a href="http://site.icu-project.org/download/55">ICU 55.1</a></td> 444 * <td><a href="http://cldr.unicode.org/index/downloads/cldr-27">CLDR 27.0.1</a></td> 445 * <td><a href="http://www.unicode.org/versions/Unicode7.0.0/">Unicode 7.0</a></td></tr> 446 * </table> 447 * 448 * <a name="default_locale"></a><h4>Be wary of the default locale</h3> 449 * <p>Note that there are many convenience methods that automatically use the default locale, but 450 * using them may lead to subtle bugs. 451 * 452 * <p>The default locale is appropriate for tasks that involve presenting data to the user. In 453 * this case, you want to use the user's date/time formats, number 454 * formats, rules for conversion to lowercase, and so on. In this case, it's safe to use the 455 * convenience methods. 456 * 457 * <p>The default locale is <i>not</i> appropriate for machine-readable output. The best choice 458 * there is usually {@code Locale.US} – this locale is guaranteed to be available on all 459 * devices, and the fact that it has no surprising special cases and is frequently used (especially 460 * for computer-computer communication) means that it tends to be the most efficient choice too. 461 * 462 * <p>A common mistake is to implicitly use the default locale when producing output meant to be 463 * machine-readable. This tends to work on the developer's test devices (especially because so many 464 * developers use en_US), but fails when run on a device whose user is in a more complex locale. 465 * 466 * <p>For example, if you're formatting integers some locales will use non-ASCII decimal 467 * digits. As another example, if you're formatting floating-point numbers some locales will use 468 * {@code ','} as the decimal point and {@code '.'} for digit grouping. That's correct for 469 * human-readable output, but likely to cause problems if presented to another 470 * computer ({@link Double#parseDouble} can't parse such a number, for example). 471 * You should also be wary of the {@link String#toLowerCase} and 472 * {@link String#toUpperCase} overloads that don't take a {@code Locale}: in Turkey, for example, 473 * the characters {@code 'i'} and {@code 'I'} won't be converted to {@code 'I'} and {@code 'i'}. 474 * This is the correct behavior for Turkish text (such as user input), but inappropriate for, say, 475 * HTTP headers. 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 */ 485public final class Locale implements Cloneable, Serializable { 486 487 static private final Cache LOCALECACHE = new Cache(); 488 489 /** Useful constant for language. 490 */ 491 static public final Locale ENGLISH = createConstant("en", ""); 492 493 /** Useful constant for language. 494 */ 495 static public final Locale FRENCH = createConstant("fr", ""); 496 497 /** Useful constant for language. 498 */ 499 static public final Locale GERMAN = createConstant("de", ""); 500 501 /** Useful constant for language. 502 */ 503 static public final Locale ITALIAN = createConstant("it", ""); 504 505 /** Useful constant for language. 506 */ 507 static public final Locale JAPANESE = createConstant("ja", ""); 508 509 /** Useful constant for language. 510 */ 511 static public final Locale KOREAN = createConstant("ko", ""); 512 513 /** Useful constant for language. 514 */ 515 static public final Locale CHINESE = createConstant("zh", ""); 516 517 /** Useful constant for language. 518 */ 519 static public final Locale SIMPLIFIED_CHINESE = createConstant("zh", "CN"); 520 521 /** Useful constant for language. 522 */ 523 static public final Locale TRADITIONAL_CHINESE = createConstant("zh", "TW"); 524 525 /** Useful constant for country. 526 */ 527 static public final Locale FRANCE = createConstant("fr", "FR"); 528 529 /** Useful constant for country. 530 */ 531 static public final Locale GERMANY = createConstant("de", "DE"); 532 533 /** Useful constant for country. 534 */ 535 static public final Locale ITALY = createConstant("it", "IT"); 536 537 /** Useful constant for country. 538 */ 539 static public final Locale JAPAN = createConstant("ja", "JP"); 540 541 /** Useful constant for country. 542 */ 543 static public final Locale KOREA = createConstant("ko", "KR"); 544 545 /** Useful constant for country. 546 */ 547 static public final Locale CHINA = SIMPLIFIED_CHINESE; 548 549 /** Useful constant for country. 550 */ 551 static public final Locale PRC = SIMPLIFIED_CHINESE; 552 553 /** Useful constant for country. 554 */ 555 static public final Locale TAIWAN = TRADITIONAL_CHINESE; 556 557 /** Useful constant for country. 558 */ 559 static public final Locale UK = createConstant("en", "GB"); 560 561 /** Useful constant for country. 562 */ 563 static public final Locale US = createConstant("en", "US"); 564 565 /** Useful constant for country. 566 */ 567 static public final Locale CANADA = createConstant("en", "CA"); 568 569 /** Useful constant for country. 570 */ 571 static public final Locale CANADA_FRENCH = createConstant("fr", "CA"); 572 573 /** 574 * ISO 639-3 generic code for undetermined languages. 575 */ 576 private static final String UNDETERMINED_LANGUAGE = "und"; 577 578 /** 579 * Useful constant for the root locale. The root locale is the locale whose 580 * language, country, and variant are empty ("") strings. This is regarded 581 * as the base locale of all locales, and is used as the language/country 582 * neutral locale for the locale sensitive operations. 583 * 584 * @since 1.6 585 */ 586 static public final Locale ROOT = createConstant("", ""); 587 588 /** 589 * The key for the private use extension ('x'). 590 * 591 * @see #getExtension(char) 592 * @see Builder#setExtension(char, String) 593 * @since 1.7 594 */ 595 static public final char PRIVATE_USE_EXTENSION = 'x'; 596 597 /** 598 * The key for Unicode locale extension ('u'). 599 * 600 * @see #getExtension(char) 601 * @see Builder#setExtension(char, String) 602 * @since 1.7 603 */ 604 static public final char UNICODE_LOCALE_EXTENSION = 'u'; 605 606 /** serialization ID 607 */ 608 static final long serialVersionUID = 9149081749638150636L; 609 610 /** 611 * Display types for retrieving localized names from the name providers. 612 */ 613 private static final int DISPLAY_LANGUAGE = 0; 614 private static final int DISPLAY_COUNTRY = 1; 615 private static final int DISPLAY_VARIANT = 2; 616 private static final int DISPLAY_SCRIPT = 3; 617 618 /** 619 * Private constructor used by getInstance method 620 */ 621 private Locale(BaseLocale baseLocale, LocaleExtensions extensions) { 622 this.baseLocale = baseLocale; 623 this.localeExtensions = extensions; 624 } 625 626 /** 627 * Construct a locale from language, country and variant. 628 * This constructor normalizes the language value to lowercase and 629 * the country value to uppercase. 630 * <p> 631 * <b>Note:</b> 632 * <ul> 633 * <li>ISO 639 is not a stable standard; some of the language codes it defines 634 * (specifically "iw", "ji", and "in") have changed. This constructor accepts both the 635 * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other 636 * API on Locale will return only the OLD codes. 637 * <li>For backward compatibility reasons, this constructor does not make 638 * any syntactic checks on the input. 639 * <li>The two cases ("ja", "JP", "JP") and ("th", "TH", "TH") are handled specially, 640 * see <a href="#special_cases_constructor">Special Cases</a> for more information. 641 * </ul> 642 * 643 * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag 644 * up to 8 characters in length. See the <code>Locale</code> class description about 645 * valid language values. 646 * @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code. 647 * See the <code>Locale</code> class description about valid country values. 648 * @param variant Any arbitrary value used to indicate a variation of a <code>Locale</code>. 649 * See the <code>Locale</code> class description for the details. 650 * @exception NullPointerException thrown if any argument is null. 651 */ 652 public Locale(String language, String country, String variant) { 653 if (language== null || country == null || variant == null) { 654 throw new NullPointerException(); 655 } 656 baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant); 657 localeExtensions = getCompatibilityExtensions(language, "", country, variant); 658 } 659 660 /** 661 * Construct a locale from language and country. 662 * This constructor normalizes the language value to lowercase and 663 * the country value to uppercase. 664 * <p> 665 * <b>Note:</b> 666 * <ul> 667 * <li>ISO 639 is not a stable standard; some of the language codes it defines 668 * (specifically "iw", "ji", and "in") have changed. This constructor accepts both the 669 * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other 670 * API on Locale will return only the OLD codes. 671 * <li>For backward compatibility reasons, this constructor does not make 672 * any syntactic checks on the input. 673 * </ul> 674 * 675 * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag 676 * up to 8 characters in length. See the <code>Locale</code> class description about 677 * valid language values. 678 * @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code. 679 * See the <code>Locale</code> class description about valid country values. 680 * @exception NullPointerException thrown if either argument is null. 681 */ 682 public Locale(String language, String country) { 683 this(language, country, ""); 684 } 685 686 /** 687 * Construct a locale from a language code. 688 * This constructor normalizes the language value to lowercase. 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 * </ul> 699 * 700 * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag 701 * up to 8 characters in length. See the <code>Locale</code> class description about 702 * valid language values. 703 * @exception NullPointerException thrown if argument is null. 704 * @since 1.4 705 */ 706 public Locale(String language) { 707 this(language, "", ""); 708 } 709 710 /** 711 * This method must be called only for creating the Locale.* 712 * constants due to making shortcuts. 713 */ 714 private static Locale createConstant(String lang, String country) { 715 BaseLocale base = BaseLocale.createInstance(lang, country); 716 return getInstance(base, null); 717 } 718 719 /** 720 * Returns a <code>Locale</code> constructed from the given 721 * <code>language</code>, <code>country</code> and 722 * <code>variant</code>. If the same <code>Locale</code> instance 723 * is available in the cache, then that instance is 724 * returned. Otherwise, a new <code>Locale</code> instance is 725 * created and cached. 726 * 727 * @param language lowercase 2 to 8 language code. 728 * @param country uppercase two-letter ISO-3166 code and numric-3 UN M.49 area code. 729 * @param variant vendor and browser specific code. See class description. 730 * @return the <code>Locale</code> instance requested 731 * @exception NullPointerException if any argument is null. 732 */ 733 static Locale getInstance(String language, String country, String variant) { 734 return getInstance(language, "", country, variant, null); 735 } 736 737 static Locale getInstance(String language, String script, String country, 738 String variant, LocaleExtensions extensions) { 739 if (language== null || script == null || country == null || variant == null) { 740 throw new NullPointerException(); 741 } 742 743 if (extensions == null) { 744 extensions = getCompatibilityExtensions(language, script, country, variant); 745 } 746 747 BaseLocale baseloc = BaseLocale.getInstance(language, script, country, variant); 748 return getInstance(baseloc, extensions); 749 } 750 751 static Locale getInstance(BaseLocale baseloc, LocaleExtensions extensions) { 752 LocaleKey key = new LocaleKey(baseloc, extensions); 753 return LOCALECACHE.get(key); 754 } 755 756 private static class Cache extends LocaleObjectCache<LocaleKey, Locale> { 757 private Cache() { 758 } 759 760 @Override 761 protected Locale createObject(LocaleKey key) { 762 return new Locale(key.base, key.exts); 763 } 764 } 765 766 private static final class LocaleKey { 767 private final BaseLocale base; 768 private final LocaleExtensions exts; 769 private final int hash; 770 771 private LocaleKey(BaseLocale baseLocale, LocaleExtensions extensions) { 772 base = baseLocale; 773 exts = extensions; 774 775 // Calculate the hash value here because it's always used. 776 int h = base.hashCode(); 777 if (exts != null) { 778 h ^= exts.hashCode(); 779 } 780 hash = h; 781 } 782 783 @Override 784 public boolean equals(Object obj) { 785 if (this == obj) { 786 return true; 787 } 788 if (!(obj instanceof LocaleKey)) { 789 return false; 790 } 791 LocaleKey other = (LocaleKey)obj; 792 if (hash != other.hash || !base.equals(other.base)) { 793 return false; 794 } 795 if (exts == null) { 796 return other.exts == null; 797 } 798 return exts.equals(other.exts); 799 } 800 801 @Override 802 public int hashCode() { 803 return hash; 804 } 805 } 806 807 /** 808 * Gets the current value of the default locale for this instance 809 * of the Java Virtual Machine. 810 * <p> 811 * The Java Virtual Machine sets the default locale during startup 812 * based on the host environment. It is used by many locale-sensitive 813 * methods if no locale is explicitly specified. 814 * It can be changed using the 815 * {@link #setDefault(java.util.Locale) setDefault} method. 816 * 817 * @return the default locale for this instance of the Java Virtual Machine 818 */ 819 public static Locale getDefault() { 820 // do not synchronize this method - see 4071298 821 return defaultLocale; 822 } 823 824 /** 825 * Gets the current value of the default locale for the specified Category 826 * for this instance of the Java Virtual Machine. 827 * <p> 828 * The Java Virtual Machine sets the default locale during startup based 829 * on the host environment. It is used by many locale-sensitive methods 830 * if no locale is explicitly specified. It can be changed using the 831 * setDefault(Locale.Category, Locale) method. 832 * 833 * @param category - the specified category to get the default locale 834 * @throws NullPointerException - if category is null 835 * @return the default locale for the specified Category for this instance 836 * of the Java Virtual Machine 837 * @see #setDefault(Locale.Category, Locale) 838 * @since 1.7 839 */ 840 public static Locale getDefault(Locale.Category category) { 841 // do not synchronize this method - see 4071298 842 switch (category) { 843 case DISPLAY: 844 if (defaultDisplayLocale == null) { 845 synchronized(Locale.class) { 846 if (defaultDisplayLocale == null) { 847 defaultDisplayLocale = initDefault(category); 848 } 849 } 850 } 851 return defaultDisplayLocale; 852 case FORMAT: 853 if (defaultFormatLocale == null) { 854 synchronized(Locale.class) { 855 if (defaultFormatLocale == null) { 856 defaultFormatLocale = initDefault(category); 857 } 858 } 859 } 860 return defaultFormatLocale; 861 default: 862 assert false: "Unknown Category"; 863 } 864 return getDefault(); 865 } 866 867 // Android-changed BEGIN: 868 // 1.) In initDefault(), user.locale gets priority 869 // 2.) In both initDefault methods, use System.getProperty() instead 870 // of legacy AccessController / GetPropertyAction security code. 871 /** 872 * @hide visible for testing. 873 */ 874 public static Locale initDefault() { 875 // user.locale gets priority 876 final String languageTag = System.getProperty("user.locale", ""); 877 if (!languageTag.isEmpty()) { 878 return Locale.forLanguageTag(languageTag); 879 } 880 881 // user.locale is empty 882 String language, region, script, country, variant; 883 language = System.getProperty("user.language", "en"); 884 // for compatibility, check for old user.region property 885 region = System.getProperty("user.region"); 886 if (region != null) { 887 // region can be of form country, country_variant, or _variant 888 int i = region.indexOf('_'); 889 if (i >= 0) { 890 country = region.substring(0, i); 891 variant = region.substring(i + 1); 892 } else { 893 country = region; 894 variant = ""; 895 } 896 script = ""; 897 } else { 898 script = System.getProperty("user.script", ""); 899 country = System.getProperty("user.country", ""); 900 variant = System.getProperty("user.variant", ""); 901 } 902 903 return getInstance(language, script, country, variant, null); 904 } 905 906 private static Locale initDefault(Locale.Category category) { 907 return getInstance( 908 System.getProperty(category.languageKey, defaultLocale.getLanguage()), 909 System.getProperty(category.scriptKey, defaultLocale.getScript()), 910 System.getProperty(category.countryKey, defaultLocale.getCountry()), 911 System.getProperty(category.variantKey, defaultLocale.getVariant()), 912 null); 913 } 914 // Android-changed END 915 916 /** 917 * Sets the default locale for this instance of the Java Virtual Machine. 918 * This does not affect the host locale. 919 * <p> 920 * If there is a security manager, its <code>checkPermission</code> 921 * method is called with a <code>PropertyPermission("user.language", "write")</code> 922 * permission before the default locale is changed. 923 * <p> 924 * The Java Virtual Machine sets the default locale during startup 925 * based on the host environment. It is used by many locale-sensitive 926 * methods if no locale is explicitly specified. 927 * <p> 928 * Since changing the default locale may affect many different areas 929 * of functionality, this method should only be used if the caller 930 * is prepared to reinitialize locale-sensitive code running 931 * within the same Java Virtual Machine. 932 * <p> 933 * By setting the default locale with this method, all of the default 934 * locales for each Category are also set to the specified default locale. 935 * 936 * @throws SecurityException 937 * if a security manager exists and its 938 * <code>checkPermission</code> method doesn't allow the operation. 939 * @throws NullPointerException if <code>newLocale</code> is null 940 * @param newLocale the new default locale 941 * @see SecurityManager#checkPermission 942 * @see java.util.PropertyPermission 943 */ 944 public static synchronized void setDefault(Locale newLocale) { 945 setDefault(Category.DISPLAY, newLocale); 946 setDefault(Category.FORMAT, newLocale); 947 defaultLocale = newLocale; 948 // Android-added 949 ICU.setDefaultLocale(newLocale.toLanguageTag()); 950 } 951 952 /** 953 * Sets the default locale for the specified Category for this instance 954 * of the Java Virtual Machine. This does not affect the host locale. 955 * <p> 956 * If there is a security manager, its checkPermission method is called 957 * with a PropertyPermission("user.language", "write") permission before 958 * the default locale is changed. 959 * <p> 960 * The Java Virtual Machine sets the default locale during startup based 961 * on the host environment. It is used by many locale-sensitive methods 962 * if no locale is explicitly specified. 963 * <p> 964 * Since changing the default locale may affect many different areas of 965 * functionality, this method should only be used if the caller is 966 * prepared to reinitialize locale-sensitive code running within the 967 * same Java Virtual Machine. 968 * <p> 969 * 970 * @param category - the specified category to set the default locale 971 * @param newLocale - the new default locale 972 * @throws SecurityException - if a security manager exists and its 973 * checkPermission method doesn't allow the operation. 974 * @throws NullPointerException - if category and/or newLocale is null 975 * @see SecurityManager#checkPermission(java.security.Permission) 976 * @see PropertyPermission 977 * @see #getDefault(Locale.Category) 978 * @since 1.7 979 */ 980 public static synchronized void setDefault(Locale.Category category, 981 Locale newLocale) { 982 if (category == null) 983 throw new NullPointerException("Category cannot be NULL"); 984 if (newLocale == null) 985 throw new NullPointerException("Can't set default locale to NULL"); 986 987 SecurityManager sm = System.getSecurityManager(); 988 if (sm != null) sm.checkPermission(new PropertyPermission 989 ("user.language", "write")); 990 switch (category) { 991 case DISPLAY: 992 defaultDisplayLocale = newLocale; 993 break; 994 case FORMAT: 995 defaultFormatLocale = newLocale; 996 break; 997 default: 998 assert false: "Unknown Category"; 999 } 1000 } 1001 1002 /** 1003 * Returns an array of all installed locales. 1004 * The returned array represents the union of locales supported 1005 * by the Java runtime environment and by installed 1006 * {@link java.util.spi.LocaleServiceProvider LocaleServiceProvider} 1007 * implementations. It must contain at least a <code>Locale</code> 1008 * instance equal to {@link java.util.Locale#US Locale.US}. 1009 * 1010 * @return An array of installed locales. 1011 */ 1012 public static Locale[] getAvailableLocales() { 1013 return LocaleServiceProviderPool.getAllAvailableLocales(); 1014 } 1015 1016 /** 1017 * Returns a list of all 2-letter country codes defined in ISO 3166. 1018 * Can be used to create Locales. 1019 * <p> 1020 * <b>Note:</b> The <code>Locale</code> class also supports other codes for 1021 * country (region), such as 3-letter numeric UN M.49 area codes. 1022 * Therefore, the list returned by this method does not contain ALL valid 1023 * codes that can be used to create Locales. 1024 * 1025 * @return An array of ISO 3166 two-letter country codes. 1026 */ 1027 public static String[] getISOCountries() { 1028 // Android-changed: Use ICU. 1029 return ICU.getISOCountries(); 1030 } 1031 1032 /** 1033 * Returns a list of all 2-letter language codes defined in ISO 639. 1034 * Can be used to create Locales. 1035 * <p> 1036 * <b>Note:</b> 1037 * <ul> 1038 * <li>ISO 639 is not a stable standard— some languages' codes have changed. 1039 * The list this function returns includes both the new and the old codes for the 1040 * languages whose codes have changed. 1041 * <li>The <code>Locale</code> class also supports language codes up to 1042 * 8 characters in length. Therefore, the list returned by this method does 1043 * not contain ALL valid codes that can be used to create Locales. 1044 * </ul> 1045 * 1046 * @return Am array of ISO 639 two-letter language codes. 1047 */ 1048 public static String[] getISOLanguages() { 1049 // Android-changed: Use ICU. 1050 return ICU.getISOLanguages(); 1051 } 1052 1053 /** 1054 * Returns the language code of this Locale. 1055 * 1056 * <p><b>Note:</b> ISO 639 is not a stable standard— some languages' codes have changed. 1057 * Locale's constructor recognizes both the new and the old codes for the languages 1058 * whose codes have changed, but this function always returns the old code. If you 1059 * want to check for a specific language whose code has changed, don't do 1060 * <pre> 1061 * if (locale.getLanguage().equals("he")) // BAD! 1062 * ... 1063 * </pre> 1064 * Instead, do 1065 * <pre> 1066 * if (locale.getLanguage().equals(new Locale("he").getLanguage())) 1067 * ... 1068 * </pre> 1069 * @return The language code, or the empty string if none is defined. 1070 * @see #getDisplayLanguage 1071 */ 1072 public String getLanguage() { 1073 return baseLocale.getLanguage(); 1074 } 1075 1076 /** 1077 * Returns the script for this locale, which should 1078 * either be the empty string or an ISO 15924 4-letter script 1079 * code. The first letter is uppercase and the rest are 1080 * lowercase, for example, 'Latn', 'Cyrl'. 1081 * 1082 * @return The script code, or the empty string if none is defined. 1083 * @see #getDisplayScript 1084 * @since 1.7 1085 */ 1086 public String getScript() { 1087 return baseLocale.getScript(); 1088 } 1089 1090 /** 1091 * Returns the country/region code for this locale, which should 1092 * either be the empty string, an uppercase ISO 3166 2-letter code, 1093 * or a UN M.49 3-digit code. 1094 * 1095 * @return The country/region code, or the empty string if none is defined. 1096 * @see #getDisplayCountry 1097 */ 1098 public String getCountry() { 1099 return baseLocale.getRegion(); 1100 } 1101 1102 /** 1103 * Returns the variant code for this locale. 1104 * 1105 * @return The variant code, or the empty string if none is defined. 1106 * @see #getDisplayVariant 1107 */ 1108 public String getVariant() { 1109 return baseLocale.getVariant(); 1110 } 1111 1112 /** 1113 * Returns {@code true} if this {@code Locale} has any <a href="#def_extensions"> 1114 * extensions</a>. 1115 * 1116 * @return {@code true} if this {@code Locale} has any extensions 1117 * @since 1.8 1118 */ 1119 public boolean hasExtensions() { 1120 return localeExtensions != null; 1121 } 1122 1123 /** 1124 * Returns a copy of this {@code Locale} with no <a href="#def_extensions"> 1125 * extensions</a>. If this {@code Locale} has no extensions, this {@code Locale} 1126 * is returned. 1127 * 1128 * @return a copy of this {@code Locale} with no extensions, or {@code this} 1129 * if {@code this} has no extensions 1130 * @since 1.8 1131 */ 1132 public Locale stripExtensions() { 1133 return hasExtensions() ? Locale.getInstance(baseLocale, null) : this; 1134 } 1135 1136 /** 1137 * Returns the extension (or private use) value associated with 1138 * the specified key, or null if there is no extension 1139 * associated with the key. To be well-formed, the key must be one 1140 * of <code>[0-9A-Za-z]</code>. Keys are case-insensitive, so 1141 * for example 'z' and 'Z' represent the same extension. 1142 * 1143 * @param key the extension key 1144 * @return The extension, or null if this locale defines no 1145 * extension for the specified key. 1146 * @throws IllegalArgumentException if key is not well-formed 1147 * @see #PRIVATE_USE_EXTENSION 1148 * @see #UNICODE_LOCALE_EXTENSION 1149 * @since 1.7 1150 */ 1151 public String getExtension(char key) { 1152 if (!LocaleExtensions.isValidKey(key)) { 1153 throw new IllegalArgumentException("Ill-formed extension key: " + key); 1154 } 1155 return hasExtensions() ? localeExtensions.getExtensionValue(key) : null; 1156 } 1157 1158 /** 1159 * Returns the set of extension keys associated with this locale, or the 1160 * empty set if it has no extensions. The returned set is unmodifiable. 1161 * The keys will all be lower-case. 1162 * 1163 * @return The set of extension keys, or the empty set if this locale has 1164 * no extensions. 1165 * @since 1.7 1166 */ 1167 public Set<Character> getExtensionKeys() { 1168 if (!hasExtensions()) { 1169 return Collections.emptySet(); 1170 } 1171 return localeExtensions.getKeys(); 1172 } 1173 1174 /** 1175 * Returns the set of unicode locale attributes associated with 1176 * this locale, or the empty set if it has no attributes. The 1177 * returned set is unmodifiable. 1178 * 1179 * @return The set of attributes. 1180 * @since 1.7 1181 */ 1182 public Set<String> getUnicodeLocaleAttributes() { 1183 if (!hasExtensions()) { 1184 return Collections.emptySet(); 1185 } 1186 return localeExtensions.getUnicodeLocaleAttributes(); 1187 } 1188 1189 /** 1190 * Returns the Unicode locale type associated with the specified Unicode locale key 1191 * for this locale. Returns the empty string for keys that are defined with no type. 1192 * Returns null if the key is not defined. Keys are case-insensitive. The key must 1193 * be two alphanumeric characters ([0-9a-zA-Z]), or an IllegalArgumentException is 1194 * thrown. 1195 * 1196 * @param key the Unicode locale key 1197 * @return The Unicode locale type associated with the key, or null if the 1198 * locale does not define the key. 1199 * @throws IllegalArgumentException if the key is not well-formed 1200 * @throws NullPointerException if <code>key</code> is null 1201 * @since 1.7 1202 */ 1203 public String getUnicodeLocaleType(String key) { 1204 if (!isUnicodeExtensionKey(key)) { 1205 throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key); 1206 } 1207 return hasExtensions() ? localeExtensions.getUnicodeLocaleType(key) : null; 1208 } 1209 1210 /** 1211 * Returns the set of Unicode locale keys defined by this locale, or the empty set if 1212 * this locale has none. The returned set is immutable. Keys are all lower case. 1213 * 1214 * @return The set of Unicode locale keys, or the empty set if this locale has 1215 * no Unicode locale keywords. 1216 * @since 1.7 1217 */ 1218 public Set<String> getUnicodeLocaleKeys() { 1219 if (localeExtensions == null) { 1220 return Collections.emptySet(); 1221 } 1222 return localeExtensions.getUnicodeLocaleKeys(); 1223 } 1224 1225 /** 1226 * Package locale method returning the Locale's BaseLocale, 1227 * used by ResourceBundle 1228 * @return base locale of this Locale 1229 */ 1230 BaseLocale getBaseLocale() { 1231 return baseLocale; 1232 } 1233 1234 /** 1235 * Package private method returning the Locale's LocaleExtensions, 1236 * used by ResourceBundle. 1237 * @return locale exnteions of this Locale, 1238 * or {@code null} if no extensions are defined 1239 */ 1240 LocaleExtensions getLocaleExtensions() { 1241 return localeExtensions; 1242 } 1243 1244 /** 1245 * Returns a string representation of this <code>Locale</code> 1246 * object, consisting of language, country, variant, script, 1247 * and extensions as below: 1248 * <blockquote> 1249 * language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions 1250 * </blockquote> 1251 * 1252 * Language is always lower case, country is always upper case, script is always title 1253 * case, and extensions are always lower case. Extensions and private use subtags 1254 * will be in canonical order as explained in {@link #toLanguageTag}. 1255 * 1256 * <p>When the locale has neither script nor extensions, the result is the same as in 1257 * Java 6 and prior. 1258 * 1259 * <p>If both the language and country fields are missing, this function will return 1260 * the empty string, even if the variant, script, or extensions field is present (you 1261 * can't have a locale with just a variant, the variant must accompany a well-formed 1262 * language or country code). 1263 * 1264 * <p>If script or extensions are present and variant is missing, no underscore is 1265 * added before the "#". 1266 * 1267 * <p>This behavior is designed to support debugging and to be compatible with 1268 * previous uses of <code>toString</code> that expected language, country, and variant 1269 * fields only. To represent a Locale as a String for interchange purposes, use 1270 * {@link #toLanguageTag}. 1271 * 1272 * <p>Examples: <ul> 1273 * <li><tt>en</tt></li> 1274 * <li><tt>de_DE</tt></li> 1275 * <li><tt>_GB</tt></li> 1276 * <li><tt>en_US_WIN</tt></li> 1277 * <li><tt>de__POSIX</tt></li> 1278 * <li><tt>zh_CN_#Hans</tt></li> 1279 * <li><tt>zh_TW_#Hant-x-java</tt></li> 1280 * <li><tt>th_TH_TH_#u-nu-thai</tt></li></ul> 1281 * 1282 * @return A string representation of the Locale, for debugging. 1283 * @see #getDisplayName 1284 * @see #toLanguageTag 1285 */ 1286 @Override 1287 public final String toString() { 1288 boolean l = (baseLocale.getLanguage().length() != 0); 1289 boolean s = (baseLocale.getScript().length() != 0); 1290 boolean r = (baseLocale.getRegion().length() != 0); 1291 boolean v = (baseLocale.getVariant().length() != 0); 1292 boolean e = (localeExtensions != null && localeExtensions.getID().length() != 0); 1293 1294 StringBuilder result = new StringBuilder(baseLocale.getLanguage()); 1295 if (r || (l && (v || s || e))) { 1296 result.append('_') 1297 .append(baseLocale.getRegion()); // This may just append '_' 1298 } 1299 if (v && (l || r)) { 1300 result.append('_') 1301 .append(baseLocale.getVariant()); 1302 } 1303 1304 if (s && (l || r)) { 1305 result.append("_#") 1306 .append(baseLocale.getScript()); 1307 } 1308 1309 if (e && (l || r)) { 1310 result.append('_'); 1311 if (!s) { 1312 result.append('#'); 1313 } 1314 result.append(localeExtensions.getID()); 1315 } 1316 1317 return result.toString(); 1318 } 1319 1320 /** 1321 * Returns a well-formed IETF BCP 47 language tag representing 1322 * this locale. 1323 * 1324 * <p>If this <code>Locale</code> has a language, country, or 1325 * variant that does not satisfy the IETF BCP 47 language tag 1326 * syntax requirements, this method handles these fields as 1327 * described below: 1328 * 1329 * <p><b>Language:</b> If language is empty, or not <a 1330 * href="#def_language" >well-formed</a> (for example "a" or 1331 * "e2"), it will be emitted as "und" (Undetermined). 1332 * 1333 * <p><b>Country:</b> If country is not <a 1334 * href="#def_region">well-formed</a> (for example "12" or "USA"), 1335 * it will be omitted. 1336 * 1337 * <p><b>Variant:</b> If variant <b>is</b> <a 1338 * href="#def_variant">well-formed</a>, each sub-segment 1339 * (delimited by '-' or '_') is emitted as a subtag. Otherwise: 1340 * <ul> 1341 * 1342 * <li>if all sub-segments match <code>[0-9a-zA-Z]{1,8}</code> 1343 * (for example "WIN" or "Oracle_JDK_Standard_Edition"), the first 1344 * ill-formed sub-segment and all following will be appended to 1345 * the private use subtag. The first appended subtag will be 1346 * "lvariant", followed by the sub-segments in order, separated by 1347 * hyphen. For example, "x-lvariant-WIN", 1348 * "Oracle-x-lvariant-JDK-Standard-Edition". 1349 * 1350 * <li>if any sub-segment does not match 1351 * <code>[0-9a-zA-Z]{1,8}</code>, the variant will be truncated 1352 * and the problematic sub-segment and all following sub-segments 1353 * will be omitted. If the remainder is non-empty, it will be 1354 * emitted as a private use subtag as above (even if the remainder 1355 * turns out to be well-formed). For example, 1356 * "Solaris_isjustthecoolestthing" is emitted as 1357 * "x-lvariant-Solaris", not as "solaris".</li></ul> 1358 * 1359 * <p><b>Special Conversions:</b> Java supports some old locale 1360 * representations, including deprecated ISO language codes, 1361 * for compatibility. This method performs the following 1362 * conversions: 1363 * <ul> 1364 * 1365 * <li>Deprecated ISO language codes "iw", "ji", and "in" are 1366 * converted to "he", "yi", and "id", respectively. 1367 * 1368 * <li>A locale with language "no", country "NO", and variant 1369 * "NY", representing Norwegian Nynorsk (Norway), is converted 1370 * to a language tag "nn-NO".</li></ul> 1371 * 1372 * <p><b>Note:</b> Although the language tag created by this 1373 * method is well-formed (satisfies the syntax requirements 1374 * defined by the IETF BCP 47 specification), it is not 1375 * necessarily a valid BCP 47 language tag. For example, 1376 * <pre> 1377 * new Locale("xx", "YY").toLanguageTag();</pre> 1378 * 1379 * will return "xx-YY", but the language subtag "xx" and the 1380 * region subtag "YY" are invalid because they are not registered 1381 * in the IANA Language Subtag Registry. 1382 * 1383 * @return a BCP47 language tag representing the locale 1384 * @see #forLanguageTag(String) 1385 * @since 1.7 1386 */ 1387 public String toLanguageTag() { 1388 if (languageTag != null) { 1389 return languageTag; 1390 } 1391 1392 LanguageTag tag = LanguageTag.parseLocale(baseLocale, localeExtensions); 1393 StringBuilder buf = new StringBuilder(); 1394 1395 String subtag = tag.getLanguage(); 1396 if (subtag.length() > 0) { 1397 buf.append(LanguageTag.canonicalizeLanguage(subtag)); 1398 } 1399 1400 subtag = tag.getScript(); 1401 if (subtag.length() > 0) { 1402 buf.append(LanguageTag.SEP); 1403 buf.append(LanguageTag.canonicalizeScript(subtag)); 1404 } 1405 1406 subtag = tag.getRegion(); 1407 if (subtag.length() > 0) { 1408 buf.append(LanguageTag.SEP); 1409 buf.append(LanguageTag.canonicalizeRegion(subtag)); 1410 } 1411 1412 List<String>subtags = tag.getVariants(); 1413 for (String s : subtags) { 1414 buf.append(LanguageTag.SEP); 1415 // preserve casing 1416 buf.append(s); 1417 } 1418 1419 subtags = tag.getExtensions(); 1420 for (String s : subtags) { 1421 buf.append(LanguageTag.SEP); 1422 buf.append(LanguageTag.canonicalizeExtension(s)); 1423 } 1424 1425 subtag = tag.getPrivateuse(); 1426 if (subtag.length() > 0) { 1427 if (buf.length() > 0) { 1428 buf.append(LanguageTag.SEP); 1429 } 1430 buf.append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP); 1431 // preserve casing 1432 buf.append(subtag); 1433 } 1434 1435 String langTag = buf.toString(); 1436 synchronized (this) { 1437 if (languageTag == null) { 1438 languageTag = langTag; 1439 } 1440 } 1441 return languageTag; 1442 } 1443 1444 /** 1445 * Returns a locale for the specified IETF BCP 47 language tag string. 1446 * 1447 * <p>If the specified language tag contains any ill-formed subtags, 1448 * the first such subtag and all following subtags are ignored. Compare 1449 * to {@link Locale.Builder#setLanguageTag} which throws an exception 1450 * in this case. 1451 * 1452 * <p>The following <b>conversions</b> are performed:<ul> 1453 * 1454 * <li>The language code "und" is mapped to language "". 1455 * 1456 * <li>The language codes "he", "yi", and "id" are mapped to "iw", 1457 * "ji", and "in" respectively. (This is the same canonicalization 1458 * that's done in Locale's constructors.) 1459 * 1460 * <li>The portion of a private use subtag prefixed by "lvariant", 1461 * if any, is removed and appended to the variant field in the 1462 * result locale (without case normalization). If it is then 1463 * empty, the private use subtag is discarded: 1464 * 1465 * <pre> 1466 * Locale loc; 1467 * loc = Locale.forLanguageTag("en-US-x-lvariant-POSIX"); 1468 * loc.getVariant(); // returns "POSIX" 1469 * loc.getExtension('x'); // returns null 1470 * 1471 * loc = Locale.forLanguageTag("de-POSIX-x-URP-lvariant-Abc-Def"); 1472 * loc.getVariant(); // returns "POSIX_Abc_Def" 1473 * loc.getExtension('x'); // returns "urp" 1474 * </pre> 1475 * 1476 * <li>When the languageTag argument contains an extlang subtag, 1477 * the first such subtag is used as the language, and the primary 1478 * language subtag and other extlang subtags are ignored: 1479 * 1480 * <pre> 1481 * Locale.forLanguageTag("ar-aao").getLanguage(); // returns "aao" 1482 * Locale.forLanguageTag("en-abc-def-us").toString(); // returns "abc_US" 1483 * </pre> 1484 * 1485 * <li>Case is normalized except for variant tags, which are left 1486 * unchanged. Language is normalized to lower case, script to 1487 * title case, country to upper case, and extensions to lower 1488 * case. 1489 * 1490 * <li>If, after processing, the locale would exactly match either 1491 * ja_JP_JP or th_TH_TH with no extensions, the appropriate 1492 * extensions are added as though the constructor had been called: 1493 * 1494 * <pre> 1495 * Locale.forLanguageTag("ja-JP-x-lvariant-JP").toLanguageTag(); 1496 * // returns "ja-JP-u-ca-japanese-x-lvariant-JP" 1497 * Locale.forLanguageTag("th-TH-x-lvariant-TH").toLanguageTag(); 1498 * // returns "th-TH-u-nu-thai-x-lvariant-TH" 1499 * </pre></ul> 1500 * 1501 * <p>This implements the 'Language-Tag' production of BCP47, and 1502 * so supports grandfathered (regular and irregular) as well as 1503 * private use language tags. Stand alone private use tags are 1504 * represented as empty language and extension 'x-whatever', 1505 * and grandfathered tags are converted to their canonical replacements 1506 * where they exist. 1507 * 1508 * <p>Grandfathered tags with canonical replacements are as follows: 1509 * 1510 * <table summary="Grandfathered tags with canonical replacements"> 1511 * <tbody align="center"> 1512 * <tr><th>grandfathered tag</th><th> </th><th>modern replacement</th></tr> 1513 * <tr><td>art-lojban</td><td> </td><td>jbo</td></tr> 1514 * <tr><td>i-ami</td><td> </td><td>ami</td></tr> 1515 * <tr><td>i-bnn</td><td> </td><td>bnn</td></tr> 1516 * <tr><td>i-hak</td><td> </td><td>hak</td></tr> 1517 * <tr><td>i-klingon</td><td> </td><td>tlh</td></tr> 1518 * <tr><td>i-lux</td><td> </td><td>lb</td></tr> 1519 * <tr><td>i-navajo</td><td> </td><td>nv</td></tr> 1520 * <tr><td>i-pwn</td><td> </td><td>pwn</td></tr> 1521 * <tr><td>i-tao</td><td> </td><td>tao</td></tr> 1522 * <tr><td>i-tay</td><td> </td><td>tay</td></tr> 1523 * <tr><td>i-tsu</td><td> </td><td>tsu</td></tr> 1524 * <tr><td>no-bok</td><td> </td><td>nb</td></tr> 1525 * <tr><td>no-nyn</td><td> </td><td>nn</td></tr> 1526 * <tr><td>sgn-BE-FR</td><td> </td><td>sfb</td></tr> 1527 * <tr><td>sgn-BE-NL</td><td> </td><td>vgt</td></tr> 1528 * <tr><td>sgn-CH-DE</td><td> </td><td>sgg</td></tr> 1529 * <tr><td>zh-guoyu</td><td> </td><td>cmn</td></tr> 1530 * <tr><td>zh-hakka</td><td> </td><td>hak</td></tr> 1531 * <tr><td>zh-min-nan</td><td> </td><td>nan</td></tr> 1532 * <tr><td>zh-xiang</td><td> </td><td>hsn</td></tr> 1533 * </tbody> 1534 * </table> 1535 * 1536 * <p>Grandfathered tags with no modern replacement will be 1537 * converted as follows: 1538 * 1539 * <table summary="Grandfathered tags with no modern replacement"> 1540 * <tbody align="center"> 1541 * <tr><th>grandfathered tag</th><th> </th><th>converts to</th></tr> 1542 * <tr><td>cel-gaulish</td><td> </td><td>xtg-x-cel-gaulish</td></tr> 1543 * <tr><td>en-GB-oed</td><td> </td><td>en-GB-x-oed</td></tr> 1544 * <tr><td>i-default</td><td> </td><td>en-x-i-default</td></tr> 1545 * <tr><td>i-enochian</td><td> </td><td>und-x-i-enochian</td></tr> 1546 * <tr><td>i-mingo</td><td> </td><td>see-x-i-mingo</td></tr> 1547 * <tr><td>zh-min</td><td> </td><td>nan-x-zh-min</td></tr> 1548 * </tbody> 1549 * </table> 1550 * 1551 * <p>For a list of all grandfathered tags, see the 1552 * IANA Language Subtag Registry (search for "Type: grandfathered"). 1553 * 1554 * <p><b>Note</b>: there is no guarantee that <code>toLanguageTag</code> 1555 * and <code>forLanguageTag</code> will round-trip. 1556 * 1557 * @param languageTag the language tag 1558 * @return The locale that best represents the language tag. 1559 * @throws NullPointerException if <code>languageTag</code> is <code>null</code> 1560 * @see #toLanguageTag() 1561 * @see java.util.Locale.Builder#setLanguageTag(String) 1562 * @since 1.7 1563 */ 1564 public static Locale forLanguageTag(String languageTag) { 1565 LanguageTag tag = LanguageTag.parse(languageTag, null); 1566 InternalLocaleBuilder bldr = new InternalLocaleBuilder(); 1567 bldr.setLanguageTag(tag); 1568 BaseLocale base = bldr.getBaseLocale(); 1569 LocaleExtensions exts = bldr.getLocaleExtensions(); 1570 if (exts == null && base.getVariant().length() > 0) { 1571 exts = getCompatibilityExtensions(base.getLanguage(), base.getScript(), 1572 base.getRegion(), base.getVariant()); 1573 } 1574 return getInstance(base, exts); 1575 } 1576 1577 /** 1578 * Returns a three-letter abbreviation of this locale's language. 1579 * If the language matches an ISO 639-1 two-letter code, the 1580 * corresponding ISO 639-2/T three-letter lowercase code is 1581 * returned. The ISO 639-2 language codes can be found on-line, 1582 * see "Codes for the Representation of Names of Languages Part 2: 1583 * Alpha-3 Code". If the locale specifies a three-letter 1584 * language, the language is returned as is. If the locale does 1585 * not specify a language the empty string is returned. 1586 * 1587 * @return A three-letter abbreviation of this locale's language. 1588 * @exception MissingResourceException Throws MissingResourceException if 1589 * three-letter language abbreviation is not available for this locale. 1590 */ 1591 public String getISO3Language() throws MissingResourceException { 1592 String lang = baseLocale.getLanguage(); 1593 if (lang.length() == 3) { 1594 return lang; 1595 } 1596 // Android-added BEGIN 1597 // return "" for empty languages for the sake of backwards compatibility. 1598 else if (lang.isEmpty()) { 1599 return ""; 1600 } 1601 // Android-added END 1602 1603 // Android-changed BEGIN: Use ICU. 1604 // String language3 = getISO3Code(lang, LocaleISOData.isoLanguageTable); 1605 // if (language3 == null) { 1606 String language3 = ICU.getISO3Language(lang); 1607 if (!lang.isEmpty() && language3.isEmpty()) { 1608 // Android-changed END 1609 throw new MissingResourceException("Couldn't find 3-letter language code for " 1610 + lang, "FormatData_" + toString(), "ShortLanguage"); 1611 } 1612 return language3; 1613 } 1614 1615 /** 1616 * Returns a three-letter abbreviation for this locale's country. 1617 * If the country matches an ISO 3166-1 alpha-2 code, the 1618 * corresponding ISO 3166-1 alpha-3 uppercase code is returned. 1619 * If the locale doesn't specify a country, this will be the empty 1620 * string. 1621 * 1622 * <p>The ISO 3166-1 codes can be found on-line. 1623 * 1624 * @return A three-letter abbreviation of this locale's country. 1625 * @exception MissingResourceException Throws MissingResourceException if the 1626 * three-letter country abbreviation is not available for this locale. 1627 */ 1628 public String getISO3Country() throws MissingResourceException { 1629 // Android-changed BEGIN: Use ICU. Also return "" for missing regions. 1630 final String region = baseLocale.getRegion(); 1631 // Note that this will return an UN.M49 region code 1632 if (region.length() == 3) { 1633 return baseLocale.getRegion(); 1634 } else if (region.isEmpty()) { 1635 return ""; 1636 } 1637 1638 // Prefix "en-" because ICU doesn't really care about what the language is. 1639 String country3 = ICU.getISO3Country("en-" + region); 1640 if (!region.isEmpty() && country3.isEmpty()) { 1641 throw new MissingResourceException("Couldn't find 3-letter country code for " 1642 + baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry"); 1643 } 1644 // Android-changed END 1645 return country3; 1646 } 1647 1648 /** 1649 * Returns a name for the locale's language that is appropriate for display to the 1650 * user. 1651 * If possible, the name returned will be localized for the default 1652 * {@link Locale.Category#DISPLAY DISPLAY} locale. 1653 * For example, if the locale is fr_FR and the default 1654 * {@link Locale.Category#DISPLAY DISPLAY} locale 1655 * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and 1656 * the default {@link Locale.Category#DISPLAY DISPLAY} locale is fr_FR, 1657 * getDisplayLanguage() will return "anglais". 1658 * If the name returned cannot be localized for the default 1659 * {@link Locale.Category#DISPLAY DISPLAY} locale, 1660 * (say, we don't have a Japanese name for Croatian), 1661 * this function falls back on the English name, and uses the ISO code as a last-resort 1662 * value. If the locale doesn't specify a language, this function returns the empty string. 1663 * 1664 * @return The name of the display language. 1665 */ 1666 public final String getDisplayLanguage() { 1667 return getDisplayLanguage(getDefault(Category.DISPLAY)); 1668 } 1669 1670 // Android-changed BEGIN: Use ICU; documentation; backwards compatibility hacks; 1671 // added private helper methods. 1672 /** 1673 * Returns the name of this locale's language, localized to {@code locale}. 1674 * If the language name is unknown, the language code is returned. 1675 */ 1676 public String getDisplayLanguage(Locale locale) { 1677 String languageCode = baseLocale.getLanguage(); 1678 if (languageCode.isEmpty()) { 1679 return ""; 1680 } 1681 1682 // Hacks for backward compatibility. 1683 // 1684 // Our language tag will contain "und" if the languageCode is invalid 1685 // or missing. ICU will then return "langue indéterminée" or the equivalent 1686 // display language for the indeterminate language code. 1687 // 1688 // Sigh... ugh... and what not. 1689 final String normalizedLanguage = normalizeAndValidateLanguage( 1690 languageCode, false /* strict */); 1691 if (UNDETERMINED_LANGUAGE.equals(normalizedLanguage)) { 1692 return languageCode; 1693 } 1694 1695 // TODO: We need a new hack or a complete fix for http://b/8049507 --- We would 1696 // cover the frameworks' tracks when they were using "tl" instead of "fil". 1697 String result = ICU.getDisplayLanguage(this, locale); 1698 if (result == null) { // TODO: do we need to do this, or does ICU do it for us? 1699 result = ICU.getDisplayLanguage(this, Locale.getDefault()); 1700 } 1701 return result; 1702 } 1703 1704 private static String normalizeAndValidateLanguage(String language, boolean strict) { 1705 if (language == null || language.isEmpty()) { 1706 return ""; 1707 } 1708 1709 final String lowercaseLanguage = language.toLowerCase(Locale.ROOT); 1710 if (!isValidBcp47Alpha(lowercaseLanguage, 2, 3)) { 1711 if (strict) { 1712 throw new IllformedLocaleException("Invalid language: " + language); 1713 } else { 1714 return UNDETERMINED_LANGUAGE; 1715 } 1716 } 1717 1718 return lowercaseLanguage; 1719 } 1720 1721 /* 1722 * Checks whether a given string is an ASCII alphanumeric string. 1723 */ 1724 private static boolean isAsciiAlphaNum(String string) { 1725 for (int i = 0; i < string.length(); i++) { 1726 final char character = string.charAt(i); 1727 if (!(character >= 'a' && character <= 'z' || 1728 character >= 'A' && character <= 'Z' || 1729 character >= '0' && character <= '9')) { 1730 return false; 1731 } 1732 } 1733 1734 return true; 1735 } 1736 // Android-changed END 1737 1738 /** 1739 * Returns a name for the the locale's script that is appropriate for display to 1740 * the user. If possible, the name will be localized for the default locale. Returns 1741 * the empty string if this locale doesn't specify a script code. 1742 * 1743 * @return the display name of the script code for the current default locale 1744 * @since 1.7 1745 */ 1746 public String getDisplayScript() { 1747 return getDisplayScript(getDefault()); 1748 } 1749 1750 /** 1751 * Returns the name of this locale's script code, localized to {@link Locale}. If the 1752 * script code is unknown, the return value of this method is the same as that of 1753 * {@link #getScript()}. 1754 * 1755 * @since 1.7 1756 */ 1757 public String getDisplayScript(Locale locale) { 1758 // Android-changed BEGIN: Use ICU. 1759 String scriptCode = baseLocale.getScript(); 1760 if (scriptCode.isEmpty()) { 1761 return ""; 1762 } 1763 1764 String result = ICU.getDisplayScript(this, locale); 1765 if (result == null) { // TODO: do we need to do this, or does ICU do it for us? 1766 result = ICU.getDisplayScript(this, Locale.getDefault()); 1767 } 1768 1769 return result; 1770 // Android-changed END 1771 } 1772 1773 /** 1774 * Returns a name for the locale's country that is appropriate for display to the 1775 * user. 1776 * If possible, the name returned will be localized for the default 1777 * {@link Locale.Category#DISPLAY DISPLAY} locale. 1778 * For example, if the locale is fr_FR and the default 1779 * {@link Locale.Category#DISPLAY DISPLAY} locale 1780 * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and 1781 * the default {@link Locale.Category#DISPLAY DISPLAY} locale is fr_FR, 1782 * getDisplayCountry() will return "Etats-Unis". 1783 * If the name returned cannot be localized for the default 1784 * {@link Locale.Category#DISPLAY DISPLAY} locale, 1785 * (say, we don't have a Japanese name for Croatia), 1786 * this function falls back on the English name, and uses the ISO code as a last-resort 1787 * value. If the locale doesn't specify a country, this function returns the empty string. 1788 * 1789 * @return The name of the country appropriate to the locale. 1790 */ 1791 public final String getDisplayCountry() { 1792 return getDisplayCountry(getDefault(Category.DISPLAY)); 1793 } 1794 1795 // Android-changed BEGIN: Use ICU; documentation; added private helper methods. 1796 /** 1797 * Returns the name of this locale's country, localized to {@code locale}. 1798 * Returns the empty string if this locale does not correspond to a specific 1799 * country. 1800 */ 1801 public String getDisplayCountry(Locale locale) { 1802 String countryCode = baseLocale.getRegion(); 1803 if (countryCode.isEmpty()) { 1804 return ""; 1805 } 1806 1807 final String normalizedRegion = normalizeAndValidateRegion( 1808 countryCode, false /* strict */); 1809 if (normalizedRegion.isEmpty()) { 1810 return countryCode; 1811 } 1812 1813 String result = ICU.getDisplayCountry(this, locale); 1814 if (result == null) { // TODO: do we need to do this, or does ICU do it for us? 1815 result = ICU.getDisplayCountry(this, Locale.getDefault()); 1816 } 1817 return result; 1818 } 1819 1820 private static String normalizeAndValidateRegion(String region, boolean strict) { 1821 if (region == null || region.isEmpty()) { 1822 return ""; 1823 } 1824 1825 final String uppercaseRegion = region.toUpperCase(Locale.ROOT); 1826 if (!isValidBcp47Alpha(uppercaseRegion, 2, 2) && 1827 !isUnM49AreaCode(uppercaseRegion)) { 1828 if (strict) { 1829 throw new IllformedLocaleException("Invalid region: " + region); 1830 } else { 1831 return ""; 1832 } 1833 } 1834 1835 return uppercaseRegion; 1836 } 1837 1838 private static boolean isValidBcp47Alpha(String string, int lowerBound, int upperBound) { 1839 final int length = string.length(); 1840 if (length < lowerBound || length > upperBound) { 1841 return false; 1842 } 1843 1844 for (int i = 0; i < length; ++i) { 1845 final char character = string.charAt(i); 1846 if (!(character >= 'a' && character <= 'z' || 1847 character >= 'A' && character <= 'Z')) { 1848 return false; 1849 } 1850 } 1851 1852 return true; 1853 } 1854 1855 /** 1856 * A UN M.49 is a 3 digit numeric code. 1857 */ 1858 private static boolean isUnM49AreaCode(String code) { 1859 if (code.length() != 3) { 1860 return false; 1861 } 1862 1863 for (int i = 0; i < 3; ++i) { 1864 final char character = code.charAt(i); 1865 if (!(character >= '0' && character <= '9')) { 1866 return false; 1867 } 1868 } 1869 1870 return true; 1871 } 1872 // Android-changed END 1873 1874 /** 1875 * Returns a name for the locale's variant code that is appropriate for display to the 1876 * user. If possible, the name will be localized for the default 1877 * {@link Locale.Category#DISPLAY DISPLAY} locale. If the locale 1878 * doesn't specify a variant code, this function returns the empty string. 1879 * 1880 * @return The name of the display variant code appropriate to the locale. 1881 */ 1882 public final String getDisplayVariant() { 1883 return getDisplayVariant(getDefault(Category.DISPLAY)); 1884 } 1885 1886 /** 1887 * Returns a name for the locale's variant code that is appropriate for display to the 1888 * user. If possible, the name will be localized for inLocale. If the locale 1889 * doesn't specify a variant code, this function returns the empty string. 1890 * 1891 * @param inLocale The locale for which to retrieve the display variant code. 1892 * @return The name of the display variant code appropriate to the given locale. 1893 * @exception NullPointerException if <code>inLocale</code> is <code>null</code> 1894 */ 1895 // Android-changed BEGIN: Use ICU; added private helper methods. 1896 public String getDisplayVariant(Locale inLocale) { 1897 String variantCode = baseLocale.getVariant(); 1898 if (variantCode.isEmpty()) { 1899 return ""; 1900 } 1901 1902 try { 1903 normalizeAndValidateVariant(variantCode); 1904 } catch (IllformedLocaleException ilfe) { 1905 return variantCode; 1906 } 1907 1908 String result = ICU.getDisplayVariant(this, inLocale); 1909 if (result == null) { // TODO: do we need to do this, or does ICU do it for us? 1910 result = ICU.getDisplayVariant(this, Locale.getDefault()); 1911 } 1912 1913 // The "old style" locale constructors allow us to pass in variants that aren't 1914 // valid BCP-47 variant subtags. When that happens, toLanguageTag will not emit 1915 // them. Note that we know variantCode.length() > 0 due to the isEmpty check at 1916 // the beginning of this function. 1917 if (result.isEmpty()) { 1918 return variantCode; 1919 } 1920 return result; 1921 } 1922 1923 private static String normalizeAndValidateVariant(String variant) { 1924 if (variant == null || variant.isEmpty()) { 1925 return ""; 1926 } 1927 1928 // Note that unlike extensions, we canonicalize to lower case alphabets 1929 // and underscores instead of hyphens. 1930 final String normalizedVariant = variant.replace('-', '_'); 1931 String[] subTags = normalizedVariant.split("_"); 1932 1933 for (String subTag : subTags) { 1934 if (!isValidVariantSubtag(subTag)) { 1935 throw new IllformedLocaleException("Invalid variant: " + variant); 1936 } 1937 } 1938 1939 return normalizedVariant; 1940 } 1941 1942 private static boolean isValidVariantSubtag(String subTag) { 1943 // The BCP-47 spec states that : 1944 // - Subtags can be between [5, 8] alphanumeric chars in length. 1945 // - Subtags that start with a number are allowed to be 4 chars in length. 1946 if (subTag.length() >= 5 && subTag.length() <= 8) { 1947 if (isAsciiAlphaNum(subTag)) { 1948 return true; 1949 } 1950 } else if (subTag.length() == 4) { 1951 final char firstChar = subTag.charAt(0); 1952 if ((firstChar >= '0' && firstChar <= '9') && isAsciiAlphaNum(subTag)) { 1953 return true; 1954 } 1955 } 1956 1957 return false; 1958 } 1959 // Android-changed END 1960 1961 /** 1962 * Returns a name for the locale that is appropriate for display to the 1963 * user. This will be the values returned by getDisplayLanguage(), 1964 * getDisplayScript(), getDisplayCountry(), and getDisplayVariant() assembled 1965 * into a single string. The the non-empty values are used in order, 1966 * with the second and subsequent names in parentheses. For example: 1967 * <blockquote> 1968 * language (script, country, variant)<br> 1969 * language (country)<br> 1970 * language (variant)<br> 1971 * script (country)<br> 1972 * country<br> 1973 * </blockquote> 1974 * depending on which fields are specified in the locale. If the 1975 * language, script, country, and variant fields are all empty, 1976 * this function returns the empty string. 1977 * 1978 * @return The name of the locale appropriate to display. 1979 */ 1980 public final String getDisplayName() { 1981 return getDisplayName(getDefault(Category.DISPLAY)); 1982 } 1983 1984 // Android-changed BEGIN: Use ICU. 1985 /** 1986 * Returns this locale's language name, country name, and variant, localized 1987 * to {@code locale}. The exact output form depends on whether this locale 1988 * corresponds to a specific language, script, country and variant. 1989 * 1990 * <p>For example: 1991 * <ul> 1992 * <li>{@code new Locale("en").getDisplayName(Locale.US)} -> {@code English} 1993 * <li>{@code new Locale("en", "US").getDisplayName(Locale.US)} -> {@code English (United States)} 1994 * <li>{@code new Locale("en", "US", "POSIX").getDisplayName(Locale.US)} -> {@code English (United States,Computer)} 1995 * <li>{@code Locale.fromLanguageTag("zh-Hant-CN").getDisplayName(Locale.US)} -> {@code Chinese (Traditional Han,China)} 1996 * <li>{@code new Locale("en").getDisplayName(Locale.FRANCE)} -> {@code anglais} 1997 * <li>{@code new Locale("en", "US").getDisplayName(Locale.FRANCE)} -> {@code anglais (États-Unis)} 1998 * <li>{@code new Locale("en", "US", "POSIX").getDisplayName(Locale.FRANCE)} -> {@code anglais (États-Unis,informatique)}. 1999 * </ul> 2000 */ 2001 public String getDisplayName(Locale locale) { 2002 int count = 0; 2003 StringBuilder buffer = new StringBuilder(); 2004 String languageCode = baseLocale.getLanguage(); 2005 if (!languageCode.isEmpty()) { 2006 String displayLanguage = getDisplayLanguage(locale); 2007 buffer.append(displayLanguage.isEmpty() ? languageCode : displayLanguage); 2008 ++count; 2009 } 2010 String scriptCode = baseLocale.getScript(); 2011 if (!scriptCode.isEmpty()) { 2012 if (count == 1) { 2013 buffer.append(" ("); 2014 } 2015 String displayScript = getDisplayScript(locale); 2016 buffer.append(displayScript.isEmpty() ? scriptCode : displayScript); 2017 ++count; 2018 } 2019 String countryCode = baseLocale.getRegion(); 2020 if (!countryCode.isEmpty()) { 2021 if (count == 1) { 2022 buffer.append(" ("); 2023 } else if (count == 2) { 2024 buffer.append(","); 2025 } 2026 String displayCountry = getDisplayCountry(locale); 2027 buffer.append(displayCountry.isEmpty() ? countryCode : displayCountry); 2028 ++count; 2029 } 2030 String variantCode = baseLocale.getVariant(); 2031 if (!variantCode.isEmpty()) { 2032 if (count == 1) { 2033 buffer.append(" ("); 2034 } else if (count == 2 || count == 3) { 2035 buffer.append(","); 2036 } 2037 String displayVariant = getDisplayVariant(locale); 2038 buffer.append(displayVariant.isEmpty() ? variantCode : displayVariant); 2039 ++count; 2040 } 2041 if (count > 1) { 2042 buffer.append(")"); 2043 } 2044 return buffer.toString(); 2045 } 2046 // Android-changed END 2047 2048 /** 2049 * Overrides Cloneable. 2050 */ 2051 @Override 2052 public Object clone() 2053 { 2054 try { 2055 Locale that = (Locale)super.clone(); 2056 return that; 2057 } catch (CloneNotSupportedException e) { 2058 throw new InternalError(e); 2059 } 2060 } 2061 2062 /** 2063 * Override hashCode. 2064 * Since Locales are often used in hashtables, caches the value 2065 * for speed. 2066 */ 2067 @Override 2068 public int hashCode() { 2069 int hc = hashCodeValue; 2070 if (hc == 0) { 2071 hc = baseLocale.hashCode(); 2072 if (localeExtensions != null) { 2073 hc ^= localeExtensions.hashCode(); 2074 } 2075 hashCodeValue = hc; 2076 } 2077 return hc; 2078 } 2079 2080 // Overrides 2081 2082 /** 2083 * Returns true if this Locale is equal to another object. A Locale is 2084 * deemed equal to another Locale with identical language, script, country, 2085 * variant and extensions, and unequal to all other objects. 2086 * 2087 * @return true if this Locale is equal to the specified object. 2088 */ 2089 @Override 2090 public boolean equals(Object obj) { 2091 if (this == obj) // quick check 2092 return true; 2093 if (!(obj instanceof Locale)) 2094 return false; 2095 BaseLocale otherBase = ((Locale)obj).baseLocale; 2096 if (!baseLocale.equals(otherBase)) { 2097 return false; 2098 } 2099 if (localeExtensions == null) { 2100 return ((Locale)obj).localeExtensions == null; 2101 } 2102 return localeExtensions.equals(((Locale)obj).localeExtensions); 2103 } 2104 2105 // ================= privates ===================================== 2106 2107 private transient BaseLocale baseLocale; 2108 private transient LocaleExtensions localeExtensions; 2109 2110 /** 2111 * Calculated hashcode 2112 */ 2113 private transient volatile int hashCodeValue = 0; 2114 2115 private volatile static Locale defaultLocale = initDefault(); 2116 private volatile static Locale defaultDisplayLocale = null; 2117 private volatile static Locale defaultFormatLocale = null; 2118 2119 private transient volatile String languageTag; 2120 2121 /** 2122 * Format a list using given pattern strings. 2123 * If either of the patterns is null, then a the list is 2124 * formatted by concatenation with the delimiter ','. 2125 * @param stringList the list of strings to be formatted. 2126 * @param listPattern should create a MessageFormat taking 0-3 arguments 2127 * and formatting them into a list. 2128 * @param listCompositionPattern should take 2 arguments 2129 * and is used by composeList. 2130 * @return a string representing the list. 2131 */ 2132 private static String formatList(String[] stringList, String listPattern, String listCompositionPattern) { 2133 // If we have no list patterns, compose the list in a simple, 2134 // non-localized way. 2135 if (listPattern == null || listCompositionPattern == null) { 2136 StringBuilder result = new StringBuilder(); 2137 for (int i = 0; i < stringList.length; ++i) { 2138 if (i > 0) { 2139 result.append(','); 2140 } 2141 result.append(stringList[i]); 2142 } 2143 return result.toString(); 2144 } 2145 2146 // Compose the list down to three elements if necessary 2147 if (stringList.length > 3) { 2148 MessageFormat format = new MessageFormat(listCompositionPattern); 2149 stringList = composeList(format, stringList); 2150 } 2151 2152 // Rebuild the argument list with the list length as the first element 2153 Object[] args = new Object[stringList.length + 1]; 2154 System.arraycopy(stringList, 0, args, 1, stringList.length); 2155 args[0] = new Integer(stringList.length); 2156 2157 // Format it using the pattern in the resource 2158 MessageFormat format = new MessageFormat(listPattern); 2159 return format.format(args); 2160 } 2161 2162 /** 2163 * Given a list of strings, return a list shortened to three elements. 2164 * Shorten it by applying the given format to the first two elements 2165 * recursively. 2166 * @param format a format which takes two arguments 2167 * @param list a list of strings 2168 * @return if the list is three elements or shorter, the same list; 2169 * otherwise, a new list of three elements. 2170 */ 2171 private static String[] composeList(MessageFormat format, String[] list) { 2172 if (list.length <= 3) return list; 2173 2174 // Use the given format to compose the first two elements into one 2175 String[] listItems = { list[0], list[1] }; 2176 String newItem = format.format(listItems); 2177 2178 // Form a new list one element shorter 2179 String[] newList = new String[list.length-1]; 2180 System.arraycopy(list, 2, newList, 1, newList.length-1); 2181 newList[0] = newItem; 2182 2183 // Recurse 2184 return composeList(format, newList); 2185 } 2186 2187 // Duplicate of sun.util.locale.UnicodeLocaleExtension.isKey in order to 2188 // avoid its class loading. 2189 private static boolean isUnicodeExtensionKey(String s) { 2190 // 2alphanum 2191 return (s.length() == 2) && LocaleUtils.isAlphaNumericString(s); 2192 } 2193 2194 /** 2195 * @serialField language String 2196 * language subtag in lower case. (See <a href="java/util/Locale.html#getLanguage()">getLanguage()</a>) 2197 * @serialField country String 2198 * country subtag in upper case. (See <a href="java/util/Locale.html#getCountry()">getCountry()</a>) 2199 * @serialField variant String 2200 * variant subtags separated by LOWLINE characters. (See <a href="java/util/Locale.html#getVariant()">getVariant()</a>) 2201 * @serialField hashcode int 2202 * deprecated, for forward compatibility only 2203 * @serialField script String 2204 * script subtag in title case (See <a href="java/util/Locale.html#getScript()">getScript()</a>) 2205 * @serialField extensions String 2206 * canonical representation of extensions, that is, 2207 * BCP47 extensions in alphabetical order followed by 2208 * BCP47 private use subtags, all in lower case letters 2209 * separated by HYPHEN-MINUS characters. 2210 * (See <a href="java/util/Locale.html#getExtensionKeys()">getExtensionKeys()</a>, 2211 * <a href="java/util/Locale.html#getExtension(char)">getExtension(char)</a>) 2212 */ 2213 private static final ObjectStreamField[] serialPersistentFields = { 2214 new ObjectStreamField("language", String.class), 2215 new ObjectStreamField("country", String.class), 2216 new ObjectStreamField("variant", String.class), 2217 new ObjectStreamField("hashcode", int.class), 2218 new ObjectStreamField("script", String.class), 2219 new ObjectStreamField("extensions", String.class), 2220 }; 2221 2222 /** 2223 * Serializes this <code>Locale</code> to the specified <code>ObjectOutputStream</code>. 2224 * @param out the <code>ObjectOutputStream</code> to write 2225 * @throws IOException 2226 * @since 1.7 2227 */ 2228 private void writeObject(ObjectOutputStream out) throws IOException { 2229 ObjectOutputStream.PutField fields = out.putFields(); 2230 fields.put("language", baseLocale.getLanguage()); 2231 fields.put("script", baseLocale.getScript()); 2232 fields.put("country", baseLocale.getRegion()); 2233 fields.put("variant", baseLocale.getVariant()); 2234 fields.put("extensions", localeExtensions == null ? "" : localeExtensions.getID()); 2235 fields.put("hashcode", -1); // place holder just for backward support 2236 out.writeFields(); 2237 } 2238 2239 /** 2240 * Deserializes this <code>Locale</code>. 2241 * @param in the <code>ObjectInputStream</code> to read 2242 * @throws IOException 2243 * @throws ClassNotFoundException 2244 * @throws IllformedLocaleException 2245 * @since 1.7 2246 */ 2247 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 2248 ObjectInputStream.GetField fields = in.readFields(); 2249 String language = (String)fields.get("language", ""); 2250 String script = (String)fields.get("script", ""); 2251 String country = (String)fields.get("country", ""); 2252 String variant = (String)fields.get("variant", ""); 2253 String extStr = (String)fields.get("extensions", ""); 2254 baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant); 2255 // Android-changed: Handle null for backwards compatible deserialization. http://b/26387905 2256 // was: if (extStr.length() > 0) { 2257 if (extStr != null && extStr.length() > 0) { 2258 try { 2259 InternalLocaleBuilder bldr = new InternalLocaleBuilder(); 2260 bldr.setExtensions(extStr); 2261 localeExtensions = bldr.getLocaleExtensions(); 2262 } catch (LocaleSyntaxException e) { 2263 throw new IllformedLocaleException(e.getMessage()); 2264 } 2265 } else { 2266 localeExtensions = null; 2267 } 2268 } 2269 2270 /** 2271 * Returns a cached <code>Locale</code> instance equivalent to 2272 * the deserialized <code>Locale</code>. When serialized 2273 * language, country and variant fields read from the object data stream 2274 * are exactly "ja", "JP", "JP" or "th", "TH", "TH" and script/extensions 2275 * fields are empty, this method supplies <code>UNICODE_LOCALE_EXTENSION</code> 2276 * "ca"/"japanese" (calendar type is "japanese") or "nu"/"thai" (number script 2277 * type is "thai"). See <a href="Locale.html#special_cases_constructor">Special Cases</a> 2278 * for more information. 2279 * 2280 * @return an instance of <code>Locale</code> equivalent to 2281 * the deserialized <code>Locale</code>. 2282 * @throws java.io.ObjectStreamException 2283 */ 2284 private Object readResolve() throws java.io.ObjectStreamException { 2285 return getInstance(baseLocale.getLanguage(), baseLocale.getScript(), 2286 baseLocale.getRegion(), baseLocale.getVariant(), localeExtensions); 2287 } 2288 2289 private static volatile String[] isoLanguages = null; 2290 2291 private static volatile String[] isoCountries = null; 2292 2293 private static String convertOldISOCodes(String language) { 2294 // we accept both the old and the new ISO codes for the languages whose ISO 2295 // codes have changed, but we always store the OLD code, for backward compatibility 2296 language = LocaleUtils.toLowerString(language).intern(); 2297 if (language == "he") { 2298 return "iw"; 2299 } else if (language == "yi") { 2300 return "ji"; 2301 } else if (language == "id") { 2302 return "in"; 2303 } else { 2304 return language; 2305 } 2306 } 2307 2308 private static LocaleExtensions getCompatibilityExtensions(String language, 2309 String script, 2310 String country, 2311 String variant) { 2312 LocaleExtensions extensions = null; 2313 // Special cases for backward compatibility support 2314 if (LocaleUtils.caseIgnoreMatch(language, "ja") 2315 && script.length() == 0 2316 && LocaleUtils.caseIgnoreMatch(country, "jp") 2317 && "JP".equals(variant)) { 2318 // ja_JP_JP -> u-ca-japanese (calendar = japanese) 2319 extensions = LocaleExtensions.CALENDAR_JAPANESE; 2320 } else if (LocaleUtils.caseIgnoreMatch(language, "th") 2321 && script.length() == 0 2322 && LocaleUtils.caseIgnoreMatch(country, "th") 2323 && "TH".equals(variant)) { 2324 // th_TH_TH -> u-nu-thai (numbersystem = thai) 2325 extensions = LocaleExtensions.NUMBER_THAI; 2326 } 2327 return extensions; 2328 } 2329 2330 // Android-removed: Drop nested private class LocaleNameGetter. 2331 // Android-added BEGIN: Add adjustLanguageCode(); for internal use only. 2332 /** @hide for internal use only. */ 2333 public static String adjustLanguageCode(String languageCode) { 2334 String adjusted = languageCode.toLowerCase(Locale.US); 2335 // Map new language codes to the obsolete language 2336 // codes so the correct resource bundles will be used. 2337 if (languageCode.equals("he")) { 2338 adjusted = "iw"; 2339 } else if (languageCode.equals("id")) { 2340 adjusted = "in"; 2341 } else if (languageCode.equals("yi")) { 2342 adjusted = "ji"; 2343 } 2344 2345 return adjusted; 2346 } 2347 // Android-added END 2348 2349 /** 2350 * Enum for locale categories. These locale categories are used to get/set 2351 * the default locale for the specific functionality represented by the 2352 * category. 2353 * 2354 * @see #getDefault(Locale.Category) 2355 * @see #setDefault(Locale.Category, Locale) 2356 * @since 1.7 2357 */ 2358 public enum Category { 2359 2360 /** 2361 * Category used to represent the default locale for 2362 * displaying user interfaces. 2363 */ 2364 DISPLAY("user.language.display", 2365 "user.script.display", 2366 "user.country.display", 2367 "user.variant.display"), 2368 2369 /** 2370 * Category used to represent the default locale for 2371 * formatting dates, numbers, and/or currencies. 2372 */ 2373 FORMAT("user.language.format", 2374 "user.script.format", 2375 "user.country.format", 2376 "user.variant.format"); 2377 2378 Category(String languageKey, String scriptKey, String countryKey, String variantKey) { 2379 this.languageKey = languageKey; 2380 this.scriptKey = scriptKey; 2381 this.countryKey = countryKey; 2382 this.variantKey = variantKey; 2383 } 2384 2385 final String languageKey; 2386 final String scriptKey; 2387 final String countryKey; 2388 final String variantKey; 2389 } 2390 2391 /** 2392 * <code>Builder</code> is used to build instances of <code>Locale</code> 2393 * from values configured by the setters. Unlike the <code>Locale</code> 2394 * constructors, the <code>Builder</code> checks if a value configured by a 2395 * setter satisfies the syntax requirements defined by the <code>Locale</code> 2396 * class. A <code>Locale</code> object created by a <code>Builder</code> is 2397 * well-formed and can be transformed to a well-formed IETF BCP 47 language tag 2398 * without losing information. 2399 * 2400 * <p><b>Note:</b> The <code>Locale</code> class does not provide any 2401 * syntactic restrictions on variant, while BCP 47 requires each variant 2402 * subtag to be 5 to 8 alphanumerics or a single numeric followed by 3 2403 * alphanumerics. The method <code>setVariant</code> throws 2404 * <code>IllformedLocaleException</code> for a variant that does not satisfy 2405 * this restriction. If it is necessary to support such a variant, use a 2406 * Locale constructor. However, keep in mind that a <code>Locale</code> 2407 * object created this way might lose the variant information when 2408 * transformed to a BCP 47 language tag. 2409 * 2410 * <p>The following example shows how to create a <code>Locale</code> object 2411 * with the <code>Builder</code>. 2412 * <blockquote> 2413 * <pre> 2414 * Locale aLocale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build(); 2415 * </pre> 2416 * </blockquote> 2417 * 2418 * <p>Builders can be reused; <code>clear()</code> resets all 2419 * fields to their default values. 2420 * 2421 * @see Locale#forLanguageTag 2422 * @since 1.7 2423 */ 2424 public static final class Builder { 2425 private final InternalLocaleBuilder localeBuilder; 2426 2427 /** 2428 * Constructs an empty Builder. The default value of all 2429 * fields, extensions, and private use information is the 2430 * empty string. 2431 */ 2432 public Builder() { 2433 localeBuilder = new InternalLocaleBuilder(); 2434 } 2435 2436 /** 2437 * Resets the <code>Builder</code> to match the provided 2438 * <code>locale</code>. Existing state is discarded. 2439 * 2440 * <p>All fields of the locale must be well-formed, see {@link Locale}. 2441 * 2442 * <p>Locales with any ill-formed fields cause 2443 * <code>IllformedLocaleException</code> to be thrown, except for the 2444 * following three cases which are accepted for compatibility 2445 * reasons:<ul> 2446 * <li>Locale("ja", "JP", "JP") is treated as "ja-JP-u-ca-japanese" 2447 * <li>Locale("th", "TH", "TH") is treated as "th-TH-u-nu-thai" 2448 * <li>Locale("no", "NO", "NY") is treated as "nn-NO"</ul> 2449 * 2450 * @param locale the locale 2451 * @return This builder. 2452 * @throws IllformedLocaleException if <code>locale</code> has 2453 * any ill-formed fields. 2454 * @throws NullPointerException if <code>locale</code> is null. 2455 */ 2456 public Builder setLocale(Locale locale) { 2457 try { 2458 localeBuilder.setLocale(locale.baseLocale, locale.localeExtensions); 2459 } catch (LocaleSyntaxException e) { 2460 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex()); 2461 } 2462 return this; 2463 } 2464 2465 /** 2466 * Resets the Builder to match the provided IETF BCP 47 2467 * language tag. Discards the existing state. Null and the 2468 * empty string cause the builder to be reset, like {@link 2469 * #clear}. Grandfathered tags (see {@link 2470 * Locale#forLanguageTag}) are converted to their canonical 2471 * form before being processed. Otherwise, the language tag 2472 * must be well-formed (see {@link Locale}) or an exception is 2473 * thrown (unlike <code>Locale.forLanguageTag</code>, which 2474 * just discards ill-formed and following portions of the 2475 * tag). 2476 * 2477 * @param languageTag the language tag 2478 * @return This builder. 2479 * @throws IllformedLocaleException if <code>languageTag</code> is ill-formed 2480 * @see Locale#forLanguageTag(String) 2481 */ 2482 public Builder setLanguageTag(String languageTag) { 2483 ParseStatus sts = new ParseStatus(); 2484 LanguageTag tag = LanguageTag.parse(languageTag, sts); 2485 if (sts.isError()) { 2486 throw new IllformedLocaleException(sts.getErrorMessage(), sts.getErrorIndex()); 2487 } 2488 localeBuilder.setLanguageTag(tag); 2489 return this; 2490 } 2491 2492 /** 2493 * Sets the language. If <code>language</code> is the empty string or 2494 * null, the language in this <code>Builder</code> is removed. Otherwise, 2495 * the language must be <a href="./Locale.html#def_language">well-formed</a> 2496 * or an exception is thrown. 2497 * 2498 * <p>The typical language value is a two or three-letter language 2499 * code as defined in ISO639. 2500 * 2501 * @param language the language 2502 * @return This builder. 2503 * @throws IllformedLocaleException if <code>language</code> is ill-formed 2504 */ 2505 public Builder setLanguage(String language) { 2506 try { 2507 localeBuilder.setLanguage(language); 2508 } catch (LocaleSyntaxException e) { 2509 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex()); 2510 } 2511 return this; 2512 } 2513 2514 /** 2515 * Sets the script. If <code>script</code> is null or the empty string, 2516 * the script in this <code>Builder</code> is removed. 2517 * Otherwise, the script must be <a href="./Locale.html#def_script">well-formed</a> or an 2518 * exception is thrown. 2519 * 2520 * <p>The typical script value is a four-letter script code as defined by ISO 15924. 2521 * 2522 * @param script the script 2523 * @return This builder. 2524 * @throws IllformedLocaleException if <code>script</code> is ill-formed 2525 */ 2526 public Builder setScript(String script) { 2527 try { 2528 localeBuilder.setScript(script); 2529 } catch (LocaleSyntaxException e) { 2530 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex()); 2531 } 2532 return this; 2533 } 2534 2535 /** 2536 * Sets the region. If region is null or the empty string, the region 2537 * in this <code>Builder</code> is removed. Otherwise, 2538 * the region must be <a href="./Locale.html#def_region">well-formed</a> or an 2539 * exception is thrown. 2540 * 2541 * <p>The typical region value is a two-letter ISO 3166 code or a 2542 * three-digit UN M.49 area code. 2543 * 2544 * <p>The country value in the <code>Locale</code> created by the 2545 * <code>Builder</code> is always normalized to upper case. 2546 * 2547 * @param region the region 2548 * @return This builder. 2549 * @throws IllformedLocaleException if <code>region</code> is ill-formed 2550 */ 2551 public Builder setRegion(String region) { 2552 try { 2553 localeBuilder.setRegion(region); 2554 } catch (LocaleSyntaxException e) { 2555 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex()); 2556 } 2557 return this; 2558 } 2559 2560 /** 2561 * Sets the variant. If variant is null or the empty string, the 2562 * variant in this <code>Builder</code> is removed. Otherwise, it 2563 * must consist of one or more <a href="./Locale.html#def_variant">well-formed</a> 2564 * subtags, or an exception is thrown. 2565 * 2566 * <p><b>Note:</b> This method checks if <code>variant</code> 2567 * satisfies the IETF BCP 47 variant subtag's syntax requirements, 2568 * and normalizes the value to lowercase letters. However, 2569 * the <code>Locale</code> class does not impose any syntactic 2570 * restriction on variant, and the variant value in 2571 * <code>Locale</code> is case sensitive. To set such a variant, 2572 * use a Locale constructor. 2573 * 2574 * @param variant the variant 2575 * @return This builder. 2576 * @throws IllformedLocaleException if <code>variant</code> is ill-formed 2577 */ 2578 public Builder setVariant(String variant) { 2579 try { 2580 localeBuilder.setVariant(variant); 2581 } catch (LocaleSyntaxException e) { 2582 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex()); 2583 } 2584 return this; 2585 } 2586 2587 /** 2588 * Sets the extension for the given key. If the value is null or the 2589 * empty string, the extension is removed. Otherwise, the extension 2590 * must be <a href="./Locale.html#def_extensions">well-formed</a> or an exception 2591 * is thrown. 2592 * 2593 * <p><b>Note:</b> The key {@link Locale#UNICODE_LOCALE_EXTENSION 2594 * UNICODE_LOCALE_EXTENSION} ('u') is used for the Unicode locale extension. 2595 * Setting a value for this key replaces any existing Unicode locale key/type 2596 * pairs with those defined in the extension. 2597 * 2598 * <p><b>Note:</b> The key {@link Locale#PRIVATE_USE_EXTENSION 2599 * PRIVATE_USE_EXTENSION} ('x') is used for the private use code. To be 2600 * well-formed, the value for this key needs only to have subtags of one to 2601 * eight alphanumeric characters, not two to eight as in the general case. 2602 * 2603 * @param key the extension key 2604 * @param value the extension value 2605 * @return This builder. 2606 * @throws IllformedLocaleException if <code>key</code> is illegal 2607 * or <code>value</code> is ill-formed 2608 * @see #setUnicodeLocaleKeyword(String, String) 2609 */ 2610 public Builder setExtension(char key, String value) { 2611 try { 2612 localeBuilder.setExtension(key, value); 2613 } catch (LocaleSyntaxException e) { 2614 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex()); 2615 } 2616 return this; 2617 } 2618 2619 /** 2620 * Sets the Unicode locale keyword type for the given key. If the type 2621 * is null, the Unicode keyword is removed. Otherwise, the key must be 2622 * non-null and both key and type must be <a 2623 * href="./Locale.html#def_locale_extension">well-formed</a> or an exception 2624 * is thrown. 2625 * 2626 * <p>Keys and types are converted to lower case. 2627 * 2628 * <p><b>Note</b>:Setting the 'u' extension via {@link #setExtension} 2629 * replaces all Unicode locale keywords with those defined in the 2630 * extension. 2631 * 2632 * @param key the Unicode locale key 2633 * @param type the Unicode locale type 2634 * @return This builder. 2635 * @throws IllformedLocaleException if <code>key</code> or <code>type</code> 2636 * is ill-formed 2637 * @throws NullPointerException if <code>key</code> is null 2638 * @see #setExtension(char, String) 2639 */ 2640 public Builder setUnicodeLocaleKeyword(String key, String type) { 2641 try { 2642 localeBuilder.setUnicodeLocaleKeyword(key, type); 2643 } catch (LocaleSyntaxException e) { 2644 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex()); 2645 } 2646 return this; 2647 } 2648 2649 /** 2650 * Adds a unicode locale attribute, if not already present, otherwise 2651 * has no effect. The attribute must not be null and must be <a 2652 * href="./Locale.html#def_locale_extension">well-formed</a> or an exception 2653 * is thrown. 2654 * 2655 * @param attribute the attribute 2656 * @return This builder. 2657 * @throws NullPointerException if <code>attribute</code> is null 2658 * @throws IllformedLocaleException if <code>attribute</code> is ill-formed 2659 * @see #setExtension(char, String) 2660 */ 2661 public Builder addUnicodeLocaleAttribute(String attribute) { 2662 try { 2663 localeBuilder.addUnicodeLocaleAttribute(attribute); 2664 } catch (LocaleSyntaxException e) { 2665 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex()); 2666 } 2667 return this; 2668 } 2669 2670 /** 2671 * Removes a unicode locale attribute, if present, otherwise has no 2672 * effect. The attribute must not be null and must be <a 2673 * href="./Locale.html#def_locale_extension">well-formed</a> or an exception 2674 * is thrown. 2675 * 2676 * <p>Attribute comparision for removal is case-insensitive. 2677 * 2678 * @param attribute the attribute 2679 * @return This builder. 2680 * @throws NullPointerException if <code>attribute</code> is null 2681 * @throws IllformedLocaleException if <code>attribute</code> is ill-formed 2682 * @see #setExtension(char, String) 2683 */ 2684 public Builder removeUnicodeLocaleAttribute(String attribute) { 2685 // Android-added BEGIN 2686 if (attribute == null) { 2687 throw new NullPointerException("attribute == null"); 2688 } 2689 // Android-added END 2690 2691 try { 2692 localeBuilder.removeUnicodeLocaleAttribute(attribute); 2693 } catch (LocaleSyntaxException e) { 2694 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex()); 2695 } 2696 return this; 2697 } 2698 2699 /** 2700 * Resets the builder to its initial, empty state. 2701 * 2702 * @return This builder. 2703 */ 2704 public Builder clear() { 2705 localeBuilder.clear(); 2706 return this; 2707 } 2708 2709 /** 2710 * Resets the extensions to their initial, empty state. 2711 * Language, script, region and variant are unchanged. 2712 * 2713 * @return This builder. 2714 * @see #setExtension(char, String) 2715 */ 2716 public Builder clearExtensions() { 2717 localeBuilder.clearExtensions(); 2718 return this; 2719 } 2720 2721 /** 2722 * Returns an instance of <code>Locale</code> created from the fields set 2723 * on this builder. 2724 * 2725 * <p>This applies the conversions listed in {@link Locale#forLanguageTag} 2726 * when constructing a Locale. (Grandfathered tags are handled in 2727 * {@link #setLanguageTag}.) 2728 * 2729 * @return A Locale. 2730 */ 2731 public Locale build() { 2732 BaseLocale baseloc = localeBuilder.getBaseLocale(); 2733 LocaleExtensions extensions = localeBuilder.getLocaleExtensions(); 2734 if (extensions == null && baseloc.getVariant().length() > 0) { 2735 extensions = getCompatibilityExtensions(baseloc.getLanguage(), baseloc.getScript(), 2736 baseloc.getRegion(), baseloc.getVariant()); 2737 } 2738 return Locale.getInstance(baseloc, extensions); 2739 } 2740 } 2741} 2742