src/share/classes/java/util/Locale.java

Print this page
rev 5696 : 6336885: RFE: Locale Data Deployment Enhancements
4609153: Provide locale data for Indic locales
5104387: Support for gl_ES locale (galician language)
6337471: desktop/system locale preferences support
7056139: (cal) SPI support for locale-dependent Calendar parameters
7058206: Provide CalendarData SPI for week params and display field value names
7073852: Support multiple scripts for digits and decimal symbols per locale
7079560: [Fmt-Da] Context dependent month names support in SimpleDateFormat
7171324: getAvailableLocales() of locale sensitive services should return the actual availability of locales
7151414: (cal) Support calendar type identification
7168528: LocaleServiceProvider needs to be aware of Locale extensions
7171372: (cal) locale's default Calendar should be created if unknown calendar is specified
Summary: JEP 127: Improve Locale Data Packaging and Adopt Unicode CLDR Data (part 1 w/o packaging changes. by Naoto Sato and Masayoshi Okutsu)

*** 1,7 **** /* ! * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 48,68 **** import java.security.AccessController; import java.text.MessageFormat; import java.util.spi.LocaleNameProvider; import sun.security.action.GetPropertyAction; ! import sun.util.LocaleServiceProviderPool; import sun.util.locale.BaseLocale; import sun.util.locale.InternalLocaleBuilder; import sun.util.locale.LanguageTag; import sun.util.locale.LocaleExtensions; import sun.util.locale.LocaleObjectCache; import sun.util.locale.LocaleSyntaxException; import sun.util.locale.LocaleUtils; import sun.util.locale.ParseStatus; ! import sun.util.locale.UnicodeLocaleExtension; ! import sun.util.resources.LocaleData; import sun.util.resources.OpenListResourceBundle; /** * A <code>Locale</code> object represents a specific geographical, political, * or cultural region. An operation that requires a <code>Locale</code> to perform --- 48,67 ---- import java.security.AccessController; import java.text.MessageFormat; import java.util.spi.LocaleNameProvider; import sun.security.action.GetPropertyAction; ! import sun.util.locale.provider.LocaleServiceProviderPool; import sun.util.locale.BaseLocale; import sun.util.locale.InternalLocaleBuilder; import sun.util.locale.LanguageTag; import sun.util.locale.LocaleExtensions; import sun.util.locale.LocaleObjectCache; import sun.util.locale.LocaleSyntaxException; import sun.util.locale.LocaleUtils; import sun.util.locale.ParseStatus; ! import sun.util.locale.provider.LocaleProviderAdapter; import sun.util.resources.OpenListResourceBundle; /** * A <code>Locale</code> object represents a specific geographical, political, * or cultural region. An operation that requires a <code>Locale</code> to perform
*** 963,973 **** String[] result = new String[isoLanguages.length]; System.arraycopy(isoLanguages, 0, result, 0, isoLanguages.length); return result; } ! private static final String[] getISO2Table(String table) { int len = table.length() / 5; String[] isoTable = new String[len]; for (int i = 0, j = 0; i < len; i++, j += 5) { isoTable[i] = table.substring(j, j + 2); } --- 962,972 ---- String[] result = new String[isoLanguages.length]; System.arraycopy(isoLanguages, 0, result, 0, isoLanguages.length); return result; } ! private static String[] getISO2Table(String table) { int len = table.length() / 5; String[] isoTable = new String[len]; for (int i = 0, j = 0; i < len; i++, j += 5) { isoTable[i] = table.substring(j, j + 2); }
*** 1032,1041 **** --- 1031,1064 ---- public String getVariant() { return baseLocale.getVariant(); } /** + * Returns {@code true} if this {@code Locale} has any <a href="#def_extensions"> + * extensions</a>. + * + * @return {@code true} if this {@code Locale} has any extensions + * @since 1.8 + */ + public boolean hasExtensions() { + return localeExtensions != null; + } + + /** + * Returns a copy of this {@code Locale} with no <a href="#def_extensions"> + * extensions</a>. If this {@code Locale} has no extensions, this {@code Locale} + * is returned. + * + * @return a copy of this {@code Locale} with no extensions, or {@code this} + * if {@code this} has no extensions + * @since 1.8 + */ + public Locale stripExtensions() { + return hasExtensions() ? Locale.getInstance(baseLocale, null) : this; + } + + /** * Returns the extension (or private use) value associated with * the specified key, or null if there is no extension * associated with the key. To be well-formed, the key must be one * of <code>[0-9A-Za-z]</code>. Keys are case-insensitive, so * for example 'z' and 'Z' represent the same extension.
*** 1050,1060 **** */ public String getExtension(char key) { if (!LocaleExtensions.isValidKey(key)) { throw new IllegalArgumentException("Ill-formed extension key: " + key); } ! return (localeExtensions == null) ? null : localeExtensions.getExtensionValue(key); } /** * Returns the set of extension keys associated with this locale, or the * empty set if it has no extensions. The returned set is unmodifiable. --- 1073,1083 ---- */ public String getExtension(char key) { if (!LocaleExtensions.isValidKey(key)) { throw new IllegalArgumentException("Ill-formed extension key: " + key); } ! return hasExtensions() ? localeExtensions.getExtensionValue(key) : null; } /** * Returns the set of extension keys associated with this locale, or the * empty set if it has no extensions. The returned set is unmodifiable.
*** 1063,1073 **** * @return The set of extension keys, or the empty set if this locale has * no extensions. * @since 1.7 */ public Set<Character> getExtensionKeys() { ! if (localeExtensions == null) { return Collections.emptySet(); } return localeExtensions.getKeys(); } --- 1086,1096 ---- * @return The set of extension keys, or the empty set if this locale has * no extensions. * @since 1.7 */ public Set<Character> getExtensionKeys() { ! if (!hasExtensions()) { return Collections.emptySet(); } return localeExtensions.getKeys(); }
*** 1078,1088 **** * * @return The set of attributes. * @since 1.7 */ public Set<String> getUnicodeLocaleAttributes() { ! if (localeExtensions == null) { return Collections.emptySet(); } return localeExtensions.getUnicodeLocaleAttributes(); } --- 1101,1111 ---- * * @return The set of attributes. * @since 1.7 */ public Set<String> getUnicodeLocaleAttributes() { ! if (!hasExtensions()) { return Collections.emptySet(); } return localeExtensions.getUnicodeLocaleAttributes(); }
*** 1099,1112 **** * @throws IllegalArgumentException if the key is not well-formed * @throws NullPointerException if <code>key</code> is null * @since 1.7 */ public String getUnicodeLocaleType(String key) { ! if (!UnicodeLocaleExtension.isKey(key)) { throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key); } ! return (localeExtensions == null) ? null : localeExtensions.getUnicodeLocaleType(key); } /** * Returns the set of Unicode locale keys defined by this locale, or the empty set if * this locale has none. The returned set is immutable. Keys are all lower case. --- 1122,1135 ---- * @throws IllegalArgumentException if the key is not well-formed * @throws NullPointerException if <code>key</code> is null * @since 1.7 */ public String getUnicodeLocaleType(String key) { ! if (!isUnicodeExtensionKey(key)) { throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key); } ! return hasExtensions() ? localeExtensions.getUnicodeLocaleType(key) : null; } /** * Returns the set of Unicode locale keys defined by this locale, or the empty set if * this locale has none. The returned set is immutable. Keys are all lower case.
*** 1283,1292 **** --- 1306,1319 ---- * @return a BCP47 language tag representing the locale * @see #forLanguageTag(String) * @since 1.7 */ public String toLanguageTag() { + if (languageTag != null) { + return languageTag; + } + LanguageTag tag = LanguageTag.parseLocale(baseLocale, localeExtensions); StringBuilder buf = new StringBuilder(); String subtag = tag.getLanguage(); if (subtag.length() > 0) {
*** 1326,1337 **** buf.append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP); // preserve casing buf.append(subtag); } ! return buf.toString(); } /** * Returns a locale for the specified IETF BCP 47 language tag string. * * <p>If the specified language tag contains any ill-formed subtags, --- 1353,1370 ---- buf.append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP); // preserve casing buf.append(subtag); } ! String langTag = buf.toString(); ! synchronized (this) { ! if (languageTag == null) { ! languageTag = langTag; } + } + return languageTag; + } /** * Returns a locale for the specified IETF BCP 47 language tag string. * * <p>If the specified language tag contains any ill-formed subtags,
*** 1512,1522 **** + baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry"); } return country3; } ! private static final String getISO3Code(String iso2Code, String table) { int codeLength = iso2Code.length(); if (codeLength == 0) { return ""; } --- 1545,1555 ---- + baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry"); } return country3; } ! private static String getISO3Code(String iso2Code, String table) { int codeLength = iso2Code.length(); if (codeLength == 0) { return ""; }
*** 1638,1674 **** if (inLocale == null) { throw new NullPointerException(); } - try { - OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale); - String key = (type == DISPLAY_VARIANT ? "%%"+code : code); - String result = null; - - // Check whether a provider can provide an implementation that's closer - // to the requested locale than what the Java runtime itself can provide. LocaleServiceProviderPool pool = LocaleServiceProviderPool.getPool(LocaleNameProvider.class); ! if (pool.hasProviders()) { ! result = pool.getLocalizedObject( LocaleNameGetter.INSTANCE, ! inLocale, bundle, key, ! type, code); ! } ! ! if (result == null) { ! result = bundle.getString(key); ! } ! if (result != null) { return result; } ! } ! catch (Exception e) { ! // just fall through ! } return code; } /** * Returns a name for the locale's variant code that is appropriate for display to the --- 1671,1690 ---- if (inLocale == null) { throw new NullPointerException(); } LocaleServiceProviderPool pool = LocaleServiceProviderPool.getPool(LocaleNameProvider.class); ! String key = (type == DISPLAY_VARIANT ? "%%"+code : code); ! String result = pool.getLocalizedObject( LocaleNameGetter.INSTANCE, ! inLocale, key, type, code); if (result != null) { return result; } ! return code; } /** * Returns a name for the locale's variant code that is appropriate for display to the
*** 1688,1698 **** */ public String getDisplayVariant(Locale inLocale) { if (baseLocale.getVariant().length() == 0) return ""; ! OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale); String names[] = getDisplayVariantArray(bundle, inLocale); // Get the localized patterns for formatting a list, and use // them to format the list. --- 1704,1714 ---- */ public String getDisplayVariant(Locale inLocale) { if (baseLocale.getVariant().length() == 0) return ""; ! OpenListResourceBundle bundle = LocaleProviderAdapter.forJRE().getLocaleData().getLocaleNames(inLocale); String names[] = getDisplayVariantArray(bundle, inLocale); // Get the localized patterns for formatting a list, and use // them to format the list.
*** 1746,1756 **** * this function returns the empty string. * * @throws NullPointerException if <code>inLocale</code> is <code>null</code> */ public String getDisplayName(Locale inLocale) { ! OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale); String languageName = getDisplayLanguage(inLocale); String scriptName = getDisplayScript(inLocale); String countryName = getDisplayCountry(inLocale); String[] variantNames = getDisplayVariantArray(bundle, inLocale); --- 1762,1772 ---- * this function returns the empty string. * * @throws NullPointerException if <code>inLocale</code> is <code>null</code> */ public String getDisplayName(Locale inLocale) { ! OpenListResourceBundle bundle = LocaleProviderAdapter.forJRE().getLocaleData().getLocaleNames(inLocale); String languageName = getDisplayLanguage(inLocale); String scriptName = getDisplayScript(inLocale); String countryName = getDisplayCountry(inLocale); String[] variantNames = getDisplayVariantArray(bundle, inLocale);
*** 1792,1805 **** } if (countryName.length() != 0) { names.add(countryName); } if (variantNames.length != 0) { ! for (String var : variantNames) { ! names.add(var); } - } // The first one in the main name mainName = names.get(0); // Others are qualifiers --- 1808,1819 ---- } if (countryName.length() != 0) { names.add(countryName); } if (variantNames.length != 0) { ! names.addAll(Arrays.asList(variantNames)); } // The first one in the main name mainName = names.get(0); // Others are qualifiers
*** 1841,1850 **** --- 1855,1865 ---- } /** * Overrides Cloneable. */ + @Override public Object clone() { try { Locale that = (Locale)super.clone(); return that;
*** 1908,1917 **** --- 1923,1934 ---- private volatile static Locale defaultLocale = initDefault(); private volatile static Locale defaultDisplayLocale = null; private volatile static Locale defaultFormatLocale = null; + private transient volatile String languageTag; + /** * Return an array of the display names of the variant. * @param bundle the ResourceBundle to use to get the display names * @return an array of display names, possible of zero length. */
*** 1943,1955 **** */ private static String formatList(String[] stringList, String listPattern, String listCompositionPattern) { // If we have no list patterns, compose the list in a simple, // non-localized way. if (listPattern == null || listCompositionPattern == null) { ! StringBuffer result = new StringBuffer(); ! for (int i=0; i<stringList.length; ++i) { ! if (i>0) result.append(','); result.append(stringList[i]); } return result.toString(); } --- 1960,1974 ---- */ private static String formatList(String[] stringList, String listPattern, String listCompositionPattern) { // If we have no list patterns, compose the list in a simple, // non-localized way. if (listPattern == null || listCompositionPattern == null) { ! StringBuilder result = new StringBuilder(); ! for (int i = 0; i < stringList.length; ++i) { ! if (i > 0) { ! result.append(','); ! } result.append(stringList[i]); } return result.toString(); }
*** 1992,2001 **** --- 2011,2027 ---- // Recurse return composeList(format, newList); } + // Duplicate of sun.util.locale.UnicodeLocaleExtension.isKey in order to + // avoid its class loading. + private static boolean isUnicodeExtensionKey(String s) { + // 2alphanum + return (s.length() == 2) && LocaleUtils.isAlphaNumericString(s); + } + /** * @serialField language String * language subtag in lower case. (See <a href="java/util/Locale.html#getLanguage()">getLanguage()</a>) * @serialField country String * country subtag in upper case. (See <a href="java/util/Locale.html#getCountry()">getCountry()</a>)
*** 2134,2143 **** --- 2160,2170 ---- */ private static class LocaleNameGetter implements LocaleServiceProviderPool.LocalizedObjectGetter<LocaleNameProvider, String> { private static final LocaleNameGetter INSTANCE = new LocaleNameGetter(); + @Override public String getObject(LocaleNameProvider localeNameProvider, Locale locale, String key, Object... params) { assert params.length == 2;