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