diff --git a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/ICULocaleServiceProvider.java b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/ICULocaleServiceProvider.java index ea1738519a4..1f78a02e303 100644 --- a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/ICULocaleServiceProvider.java +++ b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/ICULocaleServiceProvider.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2008-2010, International Business Machines Corporation and * + * Copyright (C) 2008-2012, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -9,14 +9,17 @@ package com.ibm.icu.impl.javaspi; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Locale; +import java.util.Map; import java.util.Properties; import java.util.Set; import com.ibm.icu.impl.ICUResourceBundle; -import com.ibm.icu.text.DecimalFormatSymbols; import com.ibm.icu.util.ULocale; +import com.ibm.icu.util.ULocale.Builder; public class ICULocaleServiceProvider { private static final String SPI_PROP_FILE = "com/ibm/icu/impl/javaspi/ICULocaleServiceProviderConfig.properties"; @@ -28,7 +31,7 @@ public class ICULocaleServiceProvider { private static boolean configLoaded = false; - private static String suffix = "ICU"; + private static String suffix = "ICU4J"; private static boolean enableVariants = true; private static boolean enableIso3Lang = true; private static boolean useDecimalFormat = false; @@ -42,6 +45,8 @@ public class ICULocaleServiceProvider { new Locale("th", "TH", "TH"), }; + private static Map SPECIAL_LOCALES_MAP = null; + private static Locale[] LOCALES = null; public static Locale[] getAvailableLocales() { @@ -49,18 +54,53 @@ public class ICULocaleServiceProvider { return Arrays.copyOf(all, all.length); } - public static Locale canonicalize(Locale locale) { - Locale result = locale; - String variant = locale.getVariant(); - String suffix = getIcuSuffix(); - if (variant.equals(suffix)) { - result = new Locale(locale.getLanguage(), locale.getCountry()); - } else if (variant.endsWith(suffix) - && variant.charAt(variant.length() - suffix.length() - 1) == '_') { - variant = variant.substring(0, variant.length() - suffix.length() - 1); - result = new Locale(locale.getLanguage(), locale.getCountry(), variant); + public static ULocale toULocaleNoSpecialVariant(Locale locale) { + // If the given Locale has legacy ill-formed variant + // reserved by JDK, use the map to resolve the locale. + Locale spLoc = getSpecialLocalesMap().get(locale); + if (spLoc != null) { + return ULocale.forLocale(spLoc); } - return result; + + // The locale may have script field on Java 7+. + // So we once convert it to ULocale, then strip the ICU suffix off + // if necessary. + ULocale result = ULocale.forLocale(locale); + String variant = result.getVariant(); + String suffix = getIcuSuffix(); + String variantNoSuffix = null; + if (variant.equals(suffix)) { + variantNoSuffix = ""; + } else if (variant.endsWith(suffix) && variant.charAt(variant.length() - suffix.length() - 1) == '_') { + variantNoSuffix = variant.substring(0, variant.length() - suffix.length() - 1); + } + if (variantNoSuffix == null) { + return result; + } + + // Strip off ICU's special suffix - cannot use Builder because + // original locale may have ill-formed variant + StringBuilder id = new StringBuilder(result.getLanguage()); + String script = result.getScript(); + String country = result.getCountry(); + if (script.length() > 0) { + id.append('_'); + id.append(script); + } + if (country.length() > 0 || variantNoSuffix.length() > 0) { + id.append('_'); + id.append(country); + } + if (variantNoSuffix.length() > 0) { + id.append('_'); + id.append(variantNoSuffix); + } + String orgID = result.getName(); + int kwdIdx = orgID.indexOf('@'); + if (kwdIdx >= 0) { + id.append(orgID.substring(kwdIdx)); + } + return new ULocale(id.toString()); } public static boolean useDecimalFormat() { @@ -68,25 +108,20 @@ public class ICULocaleServiceProvider { return useDecimalFormat; } - private static final Locale THAI_NATIVE_DIGIT_LOCALE = new Locale("th", "TH", "TH"); - private static final char THAI_NATIVE_ZERO = '\u0E50'; - private static DecimalFormatSymbols THAI_NATIVE_DECIMAL_SYMBOLS = null; - - /* - * Returns a DecimalFormatSymbols if the given locale requires - * non-standard symbols, more specifically, native digits used - * by JDK Locale th_TH_TH. If the locale does not requre a special - * symbols, null is returned. - */ - public static synchronized DecimalFormatSymbols getDecimalFormatSymbolsForLocale(Locale loc) { - if (loc.equals(THAI_NATIVE_DIGIT_LOCALE)) { - if (THAI_NATIVE_DECIMAL_SYMBOLS == null) { - THAI_NATIVE_DECIMAL_SYMBOLS = new DecimalFormatSymbols(new ULocale("th_TH")); - THAI_NATIVE_DECIMAL_SYMBOLS.setDigit(THAI_NATIVE_ZERO); - } - return (DecimalFormatSymbols)THAI_NATIVE_DECIMAL_SYMBOLS.clone(); + private static synchronized Map getSpecialLocalesMap() { + if (SPECIAL_LOCALES_MAP != null) { + return SPECIAL_LOCALES_MAP; } - return null; + + Map splocs = new HashMap(); + for (Locale spLoc : SPECIAL_LOCALES) { + String var = spLoc.getVariant(); + if (var.length() > 0) { + splocs.put(new Locale(spLoc.getLanguage(), spLoc.getCountry(), var + "_" + getIcuSuffix()), spLoc); + } + } + SPECIAL_LOCALES_MAP = Collections.unmodifiableMap(splocs); + return SPECIAL_LOCALES_MAP; } private static synchronized Locale[] getLocales() { @@ -99,12 +134,24 @@ public class ICULocaleServiceProvider { for (ULocale uloc : icuLocales) { String language = uloc.getLanguage(); - String country = uloc.getCountry(); - String variant = uloc.getVariant(); if (language.length() >= 3 && !enableIso3Languages()) { continue; } - addLocale(new Locale(language, country, variant), localeSet); + addULocale(uloc, localeSet); + + if (uloc.getScript().length() > 0 && uloc.getCountry().length() > 0) { + // ICU's available locales do not contain language+country + // locales if script is available. Need to add them too. + Builder locBld = new Builder(); + try { + locBld.setLocale(uloc); + locBld.setScript(null); + ULocale ulocWithoutScript = locBld.build(); + addULocale(ulocWithoutScript, localeSet); + } catch (Exception e) { + // ignore + } + } } for (Locale l : SPECIAL_LOCALES) { @@ -133,6 +180,37 @@ public class ICULocaleServiceProvider { } } + private static void addULocale(ULocale uloc, Set locales) { + // special case - nn + // ULocale#toLocale on Java 6 maps "nn" to "no_NO_NY" + if (uloc.getLanguage().equals("nn") && uloc.getScript().length() == 0) { + Locale locNN = new Locale(uloc.getLanguage(), uloc.getCountry(), uloc.getVariant()); + addLocale(locNN, locales); + return; + } + + locales.add(uloc.toLocale()); + + if (enableIcuVariants()) { + // Add ICU variant + StringBuilder var = new StringBuilder(uloc.getVariant()); + if (var.length() != 0) { + var.append("_"); + } + var.append(getIcuSuffix()); + + Builder locBld = new Builder(); + try { + locBld.setLocale(uloc); + locBld.setVariant(var.toString()); + ULocale ulocWithVar = locBld.build(); + locales.add(ulocWithVar.toLocale()); + } catch (Exception e) { + // ignore + } + } + } + private static boolean enableIso3Languages() { return enableIso3Lang; } diff --git a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/ICULocaleServiceProviderConfig.properties b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/ICULocaleServiceProviderConfig.properties index 5103af271a3..ef2175064a7 100644 --- a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/ICULocaleServiceProviderConfig.properties +++ b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/ICULocaleServiceProviderConfig.properties @@ -1,6 +1,6 @@ #* #******************************************************************************* -#* Copyright (C) 2008, International Business Machines Corporation and * +#* Copyright (C) 2008-2012, International Business Machines Corporation and * #* others. All Rights Reserved. * #******************************************************************************* #* This is the properties is used for configuring ICU locale service provider @@ -12,8 +12,8 @@ com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.enableIcuVariants = true # Suffix string used in Locale's variant field to specify the ICU implementation. -# [default: ICU] -com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.icuVariantSuffix = ICU +# [default: ICU4J] +com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.icuVariantSuffix = ICU4J # Whether if 3-letter language Locales are included in getAvailabeLocales. # [default: true] diff --git a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/BreakIteratorProviderICU.java b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/BreakIteratorProviderICU.java index 15b87099662..adc3e647ab3 100644 --- a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/BreakIteratorProviderICU.java +++ b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/BreakIteratorProviderICU.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2008, International Business Machines Corporation and * + * Copyright (C) 2008-2012, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -18,28 +18,28 @@ public class BreakIteratorProviderICU extends BreakIteratorProvider { @Override public BreakIterator getCharacterInstance(Locale locale) { com.ibm.icu.text.BreakIterator icuBrkItr = com.ibm.icu.text.BreakIterator.getCharacterInstance( - ICULocaleServiceProvider.canonicalize(locale)); + ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale)); return BreakIteratorICU.wrap(icuBrkItr); } @Override public BreakIterator getLineInstance(Locale locale) { com.ibm.icu.text.BreakIterator icuBrkItr = com.ibm.icu.text.BreakIterator.getLineInstance( - ICULocaleServiceProvider.canonicalize(locale)); + ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale)); return BreakIteratorICU.wrap(icuBrkItr); } @Override public BreakIterator getSentenceInstance(Locale locale) { com.ibm.icu.text.BreakIterator icuBrkItr = com.ibm.icu.text.BreakIterator.getSentenceInstance( - ICULocaleServiceProvider.canonicalize(locale)); + ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale)); return BreakIteratorICU.wrap(icuBrkItr); } @Override public BreakIterator getWordInstance(Locale locale) { com.ibm.icu.text.BreakIterator icuBrkItr = com.ibm.icu.text.BreakIterator.getWordInstance( - ICULocaleServiceProvider.canonicalize(locale)); + ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale)); return BreakIteratorICU.wrap(icuBrkItr); } diff --git a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/CollatorProviderICU.java b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/CollatorProviderICU.java index 0f5195a3054..4767504369a 100644 --- a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/CollatorProviderICU.java +++ b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/CollatorProviderICU.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2008, International Business Machines Corporation and * + * Copyright (C) 2008-2012, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -18,7 +18,7 @@ public class CollatorProviderICU extends CollatorProvider { @Override public Collator getInstance(Locale locale) { com.ibm.icu.text.Collator icuCollator = com.ibm.icu.text.Collator.getInstance( - ICULocaleServiceProvider.canonicalize(locale)); + ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale)); return CollatorICU.wrap(icuCollator); } diff --git a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/DateFormatProviderICU.java b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/DateFormatProviderICU.java index 8971c57fdd0..4cf641470ef 100644 --- a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/DateFormatProviderICU.java +++ b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/DateFormatProviderICU.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2008, International Business Machines Corporation and * + * Copyright (C) 2008-2012, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -12,6 +12,7 @@ import java.util.Locale; import com.ibm.icu.impl.javaspi.ICULocaleServiceProvider; import com.ibm.icu.impl.jdkadapter.SimpleDateFormatICU; +import com.ibm.icu.util.ULocale; public class DateFormatProviderICU extends DateFormatProvider { @@ -39,7 +40,7 @@ public class DateFormatProviderICU extends DateFormatProvider { private DateFormat getInstance(int dstyle, int tstyle, Locale locale) { com.ibm.icu.text.DateFormat icuDfmt; - Locale actual = ICULocaleServiceProvider.canonicalize(locale); + ULocale actual = ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale); if (dstyle == NONE) { icuDfmt = com.ibm.icu.text.DateFormat.getTimeInstance(tstyle, actual); } else if (tstyle == NONE) { @@ -52,17 +53,6 @@ public class DateFormatProviderICU extends DateFormatProvider { return null; } - com.ibm.icu.text.DecimalFormatSymbols decfs = ICULocaleServiceProvider.getDecimalFormatSymbolsForLocale(actual); - if (decfs != null) { - com.ibm.icu.text.NumberFormat icuNfmt = icuDfmt.getNumberFormat(); - if (icuNfmt instanceof com.ibm.icu.text.DecimalFormat) { - ((com.ibm.icu.text.DecimalFormat)icuNfmt).setDecimalFormatSymbols(decfs); - } else if (icuNfmt instanceof com.ibm.icu.impl.DateNumberFormat) { - ((com.ibm.icu.impl.DateNumberFormat)icuNfmt).setZeroDigit(decfs.getDigit()); - } - icuDfmt.setNumberFormat(icuNfmt); - } - return SimpleDateFormatICU.wrap((com.ibm.icu.text.SimpleDateFormat)icuDfmt); } } diff --git a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/DateFormatSymbolsProviderICU.java b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/DateFormatSymbolsProviderICU.java index c1e1b79da59..db92f50072e 100644 --- a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/DateFormatSymbolsProviderICU.java +++ b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/DateFormatSymbolsProviderICU.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2008, International Business Machines Corporation and * + * Copyright (C) 2008-2012, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -18,7 +18,7 @@ public class DateFormatSymbolsProviderICU extends DateFormatSymbolsProvider { @Override public DateFormatSymbols getInstance(Locale locale) { com.ibm.icu.text.DateFormatSymbols icuDfs = com.ibm.icu.text.DateFormatSymbols.getInstance( - ICULocaleServiceProvider.canonicalize(locale)); + ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale)); return DateFormatSymbolsICU.wrap(icuDfs); } diff --git a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/DecimalFormatSymbolsProviderICU.java b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/DecimalFormatSymbolsProviderICU.java index 96c483dcd3c..2f2885d2b64 100644 --- a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/DecimalFormatSymbolsProviderICU.java +++ b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/DecimalFormatSymbolsProviderICU.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2008, International Business Machines Corporation and * + * Copyright (C) 2008-2012, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -19,7 +19,7 @@ public class DecimalFormatSymbolsProviderICU extends @Override public DecimalFormatSymbols getInstance(Locale locale) { com.ibm.icu.text.DecimalFormatSymbols icuDecfs = com.ibm.icu.text.DecimalFormatSymbols.getInstance( - ICULocaleServiceProvider.canonicalize(locale)); + ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale)); return DecimalFormatSymbolsICU.wrap(icuDecfs); } diff --git a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/NumberFormatProviderICU.java b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/NumberFormatProviderICU.java index 98e759bcd10..fad5c8788c2 100644 --- a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/NumberFormatProviderICU.java +++ b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/text/NumberFormatProviderICU.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2008-2011, International Business Machines Corporation and * + * Copyright (C) 2008-2012, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -13,6 +13,7 @@ import java.util.Locale; import com.ibm.icu.impl.javaspi.ICULocaleServiceProvider; import com.ibm.icu.impl.jdkadapter.DecimalFormatICU; import com.ibm.icu.impl.jdkadapter.NumberFormatICU; +import com.ibm.icu.util.ULocale; public class NumberFormatProviderICU extends NumberFormatProvider { @@ -48,7 +49,7 @@ public class NumberFormatProviderICU extends NumberFormatProvider { private NumberFormat getInstance(int type, Locale locale) { com.ibm.icu.text.NumberFormat icuNfmt; - Locale actual = ICULocaleServiceProvider.canonicalize(locale); + ULocale actual = ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale); switch (type) { case NUMBER: icuNfmt = com.ibm.icu.text.NumberFormat.getNumberInstance(actual); @@ -78,11 +79,6 @@ public class NumberFormatProviderICU extends NumberFormatProvider { nf = NumberFormatICU.wrap(icuNfmt); } - com.ibm.icu.text.DecimalFormatSymbols decfs = ICULocaleServiceProvider.getDecimalFormatSymbolsForLocale(actual); - if (decfs != null) { - ((com.ibm.icu.text.DecimalFormat)icuNfmt).setDecimalFormatSymbols(decfs); - } - return nf; } } diff --git a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/util/CurrencyNameProviderICU.java b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/util/CurrencyNameProviderICU.java index 06aeaf0018b..682a3466991 100644 --- a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/util/CurrencyNameProviderICU.java +++ b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/util/CurrencyNameProviderICU.java @@ -17,7 +17,7 @@ public class CurrencyNameProviderICU extends CurrencyNameProvider { @Override public String getSymbol(String currencyCode, Locale locale) { Currency cur = Currency.getInstance(currencyCode); - String sym = cur.getSymbol(ICULocaleServiceProvider.canonicalize(locale)); + String sym = cur.getSymbol(ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale)); if (sym.length() == 0 || sym.equals(currencyCode)) { return null; } diff --git a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/util/LocaleNameProviderICU.java b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/util/LocaleNameProviderICU.java index 8ab8b589827..6b86fa0b921 100644 --- a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/util/LocaleNameProviderICU.java +++ b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/util/LocaleNameProviderICU.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2008, International Business Machines Corporation and * + * Copyright (C) 2008-2012, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -17,7 +17,7 @@ public class LocaleNameProviderICU extends LocaleNameProvider { @Override public String getDisplayCountry(String countryCode, Locale locale) { String id = "und_" + countryCode; - String disp = ULocale.getDisplayCountry(id, ULocale.forLocale(ICULocaleServiceProvider.canonicalize(locale))); + String disp = ULocale.getDisplayCountry(id, ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale)); if (disp.length() == 0 || disp.equals(countryCode)) { return null; } @@ -26,7 +26,7 @@ public class LocaleNameProviderICU extends LocaleNameProvider { @Override public String getDisplayLanguage(String languageCode, Locale locale) { - String disp = ULocale.getDisplayLanguage(languageCode, ULocale.forLocale(ICULocaleServiceProvider.canonicalize(locale))); + String disp = ULocale.getDisplayLanguage(languageCode, ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale)); if (disp.length() == 0 || disp.equals(languageCode)) { return null; } diff --git a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/util/TimeZoneNameProviderICU.java b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/util/TimeZoneNameProviderICU.java index 640d6d3225c..2708e562f7d 100644 --- a/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/util/TimeZoneNameProviderICU.java +++ b/icu4j/main/classes/localespi/src/com/ibm/icu/impl/javaspi/util/TimeZoneNameProviderICU.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2008-2011, International Business Machines Corporation and * + * Copyright (C) 2008-2012, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -11,13 +11,14 @@ import java.util.Locale; import com.ibm.icu.impl.javaspi.ICULocaleServiceProvider; import com.ibm.icu.lang.UCharacter; import com.ibm.icu.util.TimeZone; +import com.ibm.icu.util.ULocale; public class TimeZoneNameProviderICU extends java.util.spi.TimeZoneNameProvider { @Override public String getDisplayName(String ID, boolean daylight, int style, Locale locale) { TimeZone tz = TimeZone.getFrozenTimeZone(ID); - Locale actualLocale = ICULocaleServiceProvider.canonicalize(locale); + ULocale actualLocale = ICULocaleServiceProvider.toULocaleNoSpecialVariant(locale); String disp = tz.getDisplayName(daylight, style, actualLocale); if (disp.length() == 0) { return null; diff --git a/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/CurrencyNameTest.java b/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/CurrencyNameTest.java index d93c94aa132..599e1e011c2 100644 --- a/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/CurrencyNameTest.java +++ b/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/CurrencyNameTest.java @@ -78,14 +78,8 @@ public class CurrencyNameTest extends TestFmwk { continue; } - // Note: Short term workaround for Java locale with script. - // Java Locale with non-empty script cannot have variant "ICU" - // because it's not well-formed as BCP 47. Because we cannot - // build such Locale, we skip the check below for now. - boolean ignoreErrorForNow = TestUtil.hasScript(loc); - if (TestUtil.isICUExtendedLocale(loc)) { - if (!curSymbol.equals(curSymbolIcu) && !ignoreErrorForNow) { + if (!curSymbol.equals(curSymbolIcu)) { errln("FAIL: Currency symbol for " + currencyCode + " by ICU is " + curSymbolIcu + ", but got " + curSymbol + " in locale " + loc); } @@ -97,7 +91,7 @@ public class CurrencyNameTest extends TestFmwk { // Try explicit ICU locale (xx_yy_ICU) Locale locIcu = TestUtil.toICUExtendedLocale(loc); curSymbol = currency.getSymbol(locIcu); - if (!curSymbol.equals(curSymbolIcu) && !ignoreErrorForNow) { + if (!curSymbol.equals(curSymbolIcu)) { errln("FAIL: Currency symbol for " + currencyCode + " by ICU is " + curSymbolIcu + ", but got " + curSymbol + " in locale " + locIcu); } @@ -140,14 +134,8 @@ public class CurrencyNameTest extends TestFmwk { continue; } - // Note: Short term workaround for Java locale with script. - // Java Locale with non-empty script cannot have variant "ICU" - // because it's not well-formed as BCP 47. Because we cannot - // build such Locale, we skip the check below for now. - boolean ignoreErrorForNow = TestUtil.hasScript(loc); - if (TestUtil.isICUExtendedLocale(loc)) { - if (!curName.equals(curNameIcu) && !ignoreErrorForNow) { + if (!curName.equals(curNameIcu)) { errln("FAIL: Currency display name for " + currencyCode + " by ICU is " + curNameIcu + ", but got " + curName + " in locale " + loc); } @@ -164,7 +152,7 @@ public class CurrencyNameTest extends TestFmwk { errln("FAIL: JDK Currency#getDisplayName(\"" + currency + "\", \"" + locIcu + "\") throws exception: " + e.getMessage()); continue; } - if (!curName.equals(curNameIcu) && !ignoreErrorForNow) { + if (!curName.equals(curNameIcu)) { errln("FAIL: Currency display name for " + currencyCode + " by ICU is " + curNameIcu + ", but got " + curName + " in locale " + locIcu); } diff --git a/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/DecimalFormatSymbolsTest.java b/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/DecimalFormatSymbolsTest.java index cbb51c39c52..fb7a09c5693 100644 --- a/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/DecimalFormatSymbolsTest.java +++ b/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/DecimalFormatSymbolsTest.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2008, International Business Machines Corporation and * + * Copyright (C) 2008-2012, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -108,7 +108,7 @@ public class DecimalFormatSymbolsTest extends TestFmwk { */ public void TestSetSymbols() { // ICU's JDK DecimalFormatSymbols implementation for de_DE locale - DecimalFormatSymbols decfs = DecimalFormatSymbols.getInstance(new Locale("de", "DE", "ICU")); + DecimalFormatSymbols decfs = DecimalFormatSymbols.getInstance(TestUtil.toICUExtendedLocale(new Locale("de", "DE"))); // en_US is supported by JDK, so this is the JDK's own DecimalFormatSymbols Locale loc = new Locale("en", "US"); diff --git a/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/LocaleNameTest.java b/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/LocaleNameTest.java index 0ba5eeff6e1..750670f2f55 100644 --- a/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/LocaleNameTest.java +++ b/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/LocaleNameTest.java @@ -54,15 +54,9 @@ public class LocaleNameTest extends TestFmwk { String name = forLocale.getDisplayLanguage(inLocale); - // Note: Short term workaround for Java locale with script. - // Java Locale with non-empty script cannot have variant "ICU" - // because it's not well-formed as BCP 47. Because we cannot - // build such Locale, we skip the check below for now. - boolean ignoreErrorForNow = TestUtil.hasScript(inLocale); - if (TestUtil.isICUExtendedLocale(inLocale)) { // The name should be taken from ICU - if (!name.equals(icuname) && !ignoreErrorForNow) { + if (!name.equals(icuname)) { errln("FAIL: Language name by ICU is " + icuname + ", but got " + name + " for locale " + forLocale + " in locale " + inLocale); } @@ -73,7 +67,7 @@ public class LocaleNameTest extends TestFmwk { } // Try explicit ICU locale (xx_yy_ICU) name = forLocale.getDisplayLanguage(inLocaleICU); - if (!name.equals(icuname) && !ignoreErrorForNow) { + if (!name.equals(icuname)) { errln("FAIL: Language name by ICU is " + icuname + ", but got " + name + " for locale " + forLocale + " in locale " + inLocaleICU); } @@ -98,7 +92,7 @@ public class LocaleNameTest extends TestFmwk { } // ULocale#forLocale preserves country always ULocale forULocale = ULocale.forLocale(forLocale); - String icuname = ULocale.getDisplayCountry(forULocale.getCountry(), inULocale); + String icuname = forULocale.getDisplayCountry(inULocale); if (icuname.equals(forULocale.getCountry()) || icuname.length() == 0) { continue; } @@ -127,7 +121,27 @@ public class LocaleNameTest extends TestFmwk { } } + public void TestVariantNames() { + // [Note] + // This test passed OK without any error for several reasons. + // When I changed ICU provider's special variant from "ICU" to + // "ICU4J" (#9155), this test started failing. The primary + // reason was mis-use of ULocale.getDisplayVariant(String, ULocale) + // in the test code below. The first argument should be complete + // locale ID, not variant only string. However, fixing this won't + // resolve the issue because of another ICU bug (multiple variant subtag + // issue #9160). + // + // Actually, we do not have LocaleNameProvider#getDisplayVariant + // implementation (#9161). The current implementation always returns + // null. So, the test case below happened to work, but it did not + // check anything meaningful. For now, the test case is disabled. + // We'll revisit this test case when #9160 and #9161 are resolved. + // 2012-03-01 yoshito + logln("ICU does not support LocaleNameProvider#getDisplayVariant"); + if (true) return; + Locale[] locales = Locale.getAvailableLocales(); StringBuffer icuid = new StringBuffer(); for (Locale inLocale : locales) { @@ -158,7 +172,8 @@ public class LocaleNameTest extends TestFmwk { icuid.append(variant); } ULocale forULocale = new ULocale(icuid.toString()); - String icuname = ULocale.getDisplayVariant(forULocale.getVariant(), inULocale); +// String icuname = ULocale.getDisplayVariant(forULocale.getVariant(), inULocale); + String icuname = forULocale.getDisplayVariant(inULocale); if (icuname.equals(forULocale.getVariant()) || icuname.length() == 0) { continue; } diff --git a/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/TestUtil.java b/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/TestUtil.java index 7bde2cf7a6a..ddfebb49fe7 100644 --- a/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/TestUtil.java +++ b/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/TestUtil.java @@ -9,19 +9,43 @@ package com.ibm.icu.dev.test.localespi; import java.util.Locale; import com.ibm.icu.util.ULocale; +import com.ibm.icu.util.ULocale.Builder; public class TestUtil { - private static final String ICU_VARIANT = "ICU"; - private static final String ICU_VARIANT_SUFFIX = "_ICU"; + private static final String ICU_VARIANT = "ICU4J"; + private static final String ICU_VARIANT_SUFFIX = "_ICU4J"; public static Locale toICUExtendedLocale(Locale locale) { if (isICUExtendedLocale(locale)) { return locale; } + String variant = locale.getVariant(); variant = variant.length() == 0 ? ICU_VARIANT : variant + ICU_VARIANT_SUFFIX; - return new Locale(locale.getLanguage(), locale.getCountry(), variant); + + // We once convert Locale to ULocale, then update variant + // field. We could do this using Locale APIs, but have to + // use a lot of reflections, because the test code should + // also run on JRE 6. + ULocale uloc = ULocale.forLocale(locale); + if (uloc.getScript().length() == 0) { + return new Locale(locale.getLanguage(), locale.getCountry(), variant); + } + + // For preserving JDK Locale's script, we cannot use + // the regular Locale constructor. + ULocale modUloc = null; + Builder locBld = new Builder(); + try { + locBld.setLocale(uloc); + locBld.setVariant(variant); + modUloc = locBld.build(); + return modUloc.toLocale(); + } catch (Exception e) { + // hmm, it should not happen + throw new RuntimeException(e); + } } public static boolean isICUExtendedLocale(Locale locale) { @@ -101,14 +125,4 @@ public class TestUtil { } return false; } - - /** - * Check if the given Locale has script field (Java 7+) - * @param locale the locale - * @return true if the given Locale has non-empty script - */ - public static boolean hasScript(Locale locale) { - ULocale uloc = ULocale.forLocale(locale); - return uloc.getScript().length() > 0; - } } diff --git a/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/TimeZoneNameTest.java b/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/TimeZoneNameTest.java index 19d2bbc2769..5052a4477aa 100644 --- a/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/TimeZoneNameTest.java +++ b/icu4j/main/tests/localespi/src/com/ibm/icu/dev/test/localespi/TimeZoneNameTest.java @@ -92,16 +92,10 @@ public class TimeZoneNameTest extends TestFmwk { String name = tz.getDisplayName(daylight, style, loc); - // Note: Short term workaround for Java locale with script. - // Java Locale with non-empty script cannot have variant "ICU" - // because it's not well-formed as BCP 47. Because we cannot - // build such Locale, we skip the check below for now. - boolean ignoreErrorForNow = TestUtil.hasScript(loc); - if (TestUtil.isICUExtendedLocale(loc)) { // The name should be taken from ICU if (!name.equals(icuname)) { - if (warnOnly || ignoreErrorForNow) { + if (warnOnly) { logln("WARNING: TimeZone name by ICU is " + icuname + ", but got " + name + " for time zone " + tz.getID() + " in locale " + loc + " (daylight=" + daylight + ", style=" + styleStr + ")"); @@ -122,7 +116,7 @@ public class TimeZoneNameTest extends TestFmwk { Locale icuLoc = TestUtil.toICUExtendedLocale(loc); name = tz.getDisplayName(daylight, style, icuLoc); if (!name.equals(icuname)) { - if (warnOnly || ignoreErrorForNow) { + if (warnOnly) { logln("WARNING: TimeZone name by ICU is " + icuname + ", but got " + name + " for time zone " + tz.getID() + " in locale " + icuLoc + " (daylight=" + daylight + ", style=" + styleStr + ")");