/* GENERATED SOURCE. DO NOT MODIFY. */ // © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html#License /* ********************************************************************** * Copyright (c) 2004-2016, International Business Machines * Corporation and others. All Rights Reserved. ********************************************************************** * Author: Alan Liu * Created: January 14 2004 * Since: ICU 2.8 ********************************************************************** */ package android.icu.dev.test.util; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import org.junit.Test; import android.icu.dev.test.TestFmwk; import android.icu.dev.test.TestUtil; import android.icu.dev.test.TestUtil.JavaVendor; import android.icu.lang.UCharacter; import android.icu.text.DateFormat; import android.icu.text.DecimalFormat; import android.icu.text.DisplayContext; import android.icu.text.LocaleDisplayNames; import android.icu.text.LocaleDisplayNames.DialectHandling; import android.icu.text.NumberFormat; import android.icu.text.NumberFormat.SimpleNumberFormatFactory; import android.icu.text.SimpleDateFormat; import android.icu.util.Calendar; import android.icu.util.IllformedLocaleException; import android.icu.util.LocaleData; import android.icu.util.ULocale; import android.icu.util.ULocale.Builder; import android.icu.util.ULocale.Category; import android.icu.util.ULocale.Minimize; import android.icu.util.UResourceBundle; import android.icu.util.VersionInfo; public class ULocaleTest extends TestFmwk { // Ticket #8078 and #11674 private static final boolean JAVA7_OR_LATER = TestUtil.getJavaVendor() == JavaVendor.Android || TestUtil.getJavaVersion() >= 7; @Test public void TestCalendar() { // TODO The CalendarFactory mechanism is not public, // so we can't test it yet. If it becomes public, // enable this code. // class CFactory implements CalendarFactory { // Locale loc; // Calendar proto; // public CFactory(Locale locale, Calendar prototype) { // loc = locale; // proto = prototype; // } // public Calendar create(TimeZone tz, Locale locale) { // // ignore tz -- not relevant to this test // return locale.equals(loc) ? // (Calendar) proto.clone() : null; // } // public String factoryName() { // return "CFactory"; // } // }; checkService("en_US_BROOKLYN", new ServiceFacade() { @Override public Object create(ULocale req) { return Calendar.getInstance(req); } // }, null, new Registrar() { // public Object register(ULocale loc, Object prototype) { // CFactory f = new CFactory(loc, (Calendar) prototype); // return Calendar.register(f, loc); // } // public boolean unregister(Object key) { // return Calendar.unregister(key); // } }); } // Currency getLocale API is obsolete in 3.2. Since it now returns ULocale.ROOT, // and this is not equal to the requested locale zh_TW_TAIPEI, the // checkService call would always fail. So we now omit the test. /* @Test public void TestCurrency() { checkService("zh_TW_TAIPEI", new ServiceFacade() { public Object create(ULocale req) { return Currency.getInstance(req); } }, null, new Registrar() { public Object register(ULocale loc, Object prototype) { return Currency.registerInstance((Currency) prototype, loc); } public boolean unregister(Object key) { return Currency.unregister(key); } }); } */ @Test public void TestDateFormat() { checkService("de_CH_ZURICH", new ServiceFacade() { @Override public Object create(ULocale req) { return DateFormat.getDateInstance(DateFormat.DEFAULT, req); } }, new Subobject() { @Override public Object get(Object parent) { return ((SimpleDateFormat) parent).getDateFormatSymbols(); } }, null); } @Test public void TestNumberFormat() { class NFactory extends SimpleNumberFormatFactory { NumberFormat proto; ULocale locale; public NFactory(ULocale loc, NumberFormat fmt) { super(loc); this.locale = loc; this.proto = fmt; } @Override public NumberFormat createFormat(ULocale loc, int formatType) { return (NumberFormat) (locale.equals(loc) ? proto.clone() : null); } } checkService("fr_FR_NICE", new ServiceFacade() { @Override public Object create(ULocale req) { return NumberFormat.getInstance(req); } }, new Subobject() { @Override public Object get(Object parent) { return ((DecimalFormat) parent).getDecimalFormatSymbols(); } }, new Registrar() { @Override public Object register(ULocale loc, Object prototype) { NFactory f = new NFactory(loc, (NumberFormat) prototype); return NumberFormat.registerFactory(f); } @Override public boolean unregister(Object key) { return NumberFormat.unregister(key); } }); } @Test public void TestSetULocaleKeywords() { ULocale uloc = new ULocale("en_Latn_US"); uloc = uloc.setKeywordValue("Foo", "FooValue"); if (!"en_Latn_US@foo=FooValue".equals(uloc.getName())) { errln("failed to add foo keyword, got: " + uloc.getName()); } uloc = uloc.setKeywordValue("Bar", "BarValue"); if (!"en_Latn_US@bar=BarValue;foo=FooValue".equals(uloc.getName())) { errln("failed to add bar keyword, got: " + uloc.getName()); } uloc = uloc.setKeywordValue("BAR", "NewBarValue"); if (!"en_Latn_US@bar=NewBarValue;foo=FooValue".equals(uloc.getName())) { errln("failed to change bar keyword, got: " + uloc.getName()); } uloc = uloc.setKeywordValue("BaR", null); if (!"en_Latn_US@foo=FooValue".equals(uloc.getName())) { errln("failed to delete bar keyword, got: " + uloc.getName()); } uloc = uloc.setKeywordValue(null, null); if (!"en_Latn_US".equals(uloc.getName())) { errln("failed to delete all keywords, got: " + uloc.getName()); } } /* * ticket#5060 */ @Test public void TestJavaLocaleCompatibility() { Locale backupDefault = Locale.getDefault(); ULocale orgUlocDefault = ULocale.getDefault(); // Java Locale for ja_JP with Japanese calendar Locale jaJPJP = new Locale("ja", "JP", "JP"); Locale jaJP = new Locale("ja", "JP"); // Java Locale for th_TH with Thai digits Locale thTHTH = new Locale("th", "TH", "TH"); Calendar cal = Calendar.getInstance(jaJPJP); String caltype = cal.getType(); if (!caltype.equals("japanese")) { errln("FAIL: Invalid calendar type: " + caltype + " /expected: japanese"); } cal = Calendar.getInstance(jaJP); caltype = cal.getType(); if (!caltype.equals("gregorian")) { errln("FAIL: Invalid calendar type: " + caltype + " /expected: gregorian"); } // Default locale Locale.setDefault(jaJPJP); ULocale defUloc = ULocale.getDefault(); if (JAVA7_OR_LATER) { if (!defUloc.toString().equals("ja_JP_JP@calendar=japanese")) { errln("FAIL: Invalid default ULocale: " + defUloc + " /expected: ja_JP_JP@calendar=japanese"); } } else { if (!defUloc.toString().equals("ja_JP@calendar=japanese")) { errln("FAIL: Invalid default ULocale: " + defUloc + " /expected: ja_JP@calendar=japanese"); } } // Check calendar type cal = Calendar.getInstance(); caltype = cal.getType(); if (!caltype.equals("japanese")) { errln("FAIL: Invalid calendar type: " + caltype + " /expected: japanese"); } Locale.setDefault(backupDefault); // Set default via ULocale ULocale ujaJP_calJP = new ULocale("ja_JP@calendar=japanese"); ULocale.setDefault(ujaJP_calJP); if (!JAVA7_OR_LATER && !Locale.getDefault().equals(jaJPJP)) { errln("FAIL: ULocale#setDefault failed to set Java Locale ja_JP_JP /actual: " + Locale.getDefault()); } // Ticket#6672 - missing keywords defUloc = ULocale.getDefault(); if (!defUloc.equals(ujaJP_calJP)) { errln("FAIL: ULocale#getDefault returned " + defUloc + " /expected: ja_JP@calendar=japanese"); } // Set a incompatible base locale via Locale#setDefault Locale.setDefault(Locale.US); defUloc = ULocale.getDefault(); if (defUloc.equals(ujaJP_calJP)) { errln("FAIL: ULocale#getDefault returned " + defUloc + " /expected: " + ULocale.forLocale(Locale.US)); } Locale.setDefault(backupDefault); // We also want to map ICU locale ja@calendar=japanese to Java ja_JP_JP ULocale.setDefault(new ULocale("ja@calendar=japanese")); if (!JAVA7_OR_LATER && !Locale.getDefault().equals(jaJPJP)) { errln("FAIL: ULocale#setDefault failed to set Java Locale ja_JP_JP /actual: " + Locale.getDefault()); } Locale.setDefault(backupDefault); // Java no_NO_NY Locale noNONY = new Locale("no", "NO", "NY"); Locale.setDefault(noNONY); defUloc = ULocale.getDefault(); if (!defUloc.toString().equals("nn_NO")) { errln("FAIL: Invalid default ULocale: " + defUloc + " /expected: nn_NO"); } Locale.setDefault(backupDefault); // Java th_TH_TH -> ICU th_TH@numbers=thai ULocale.setDefault(new ULocale("th@numbers=thai")); if (!JAVA7_OR_LATER && !Locale.getDefault().equals(thTHTH)) { errln("FAIL: ULocale#setDefault failed to set Java Locale th_TH_TH /actual: " + Locale.getDefault()); } Locale.setDefault(backupDefault); // Set default via ULocale ULocale.setDefault(new ULocale("nn_NO")); if (!JAVA7_OR_LATER && !Locale.getDefault().equals(noNONY)) { errln("FAIL: ULocale#setDefault failed to set Java Locale no_NO_NY /actual: " + Locale.getDefault()); } Locale.setDefault(backupDefault); // We also want to map ICU locale nn to Java no_NO_NY ULocale.setDefault(new ULocale("nn")); if (!JAVA7_OR_LATER && !Locale.getDefault().equals(noNONY)) { errln("FAIL: ULocale#setDefault failed to set Java Locale no_NO_NY /actual: " + Locale.getDefault()); } Locale.setDefault(backupDefault); // Make sure default ULocale is restored if (!ULocale.getDefault().equals(orgUlocDefault)) { errln("FAIL: Original default ULocale is not restored - " + ULocale.getDefault() + ", expected(orginal) - " + orgUlocDefault); } } // ================= Infrastructure ================= /** * Compare two locale IDs. If they are equal, return 0. If `string' * starts with `prefix' plus an additional element, that is, string == * prefix + '_' + x, then return 1. Otherwise return a value < 0. */ static int loccmp(String string, String prefix) { int slen = string.length(), plen = prefix.length(); /* 'root' is "less than" everything */ if (prefix.equals("root")) { return string.equals("root") ? 0 : 1; } // ON JAVA (only -- not on C -- someone correct me if I'm wrong) // consider "" to be an alternate name for "root". if (plen == 0) { return slen == 0 ? 0 : 1; } if (!string.startsWith(prefix)) return -1; /* mismatch */ if (slen == plen) return 0; if (string.charAt(plen) == '_') return 1; return -2; /* false match, e.g. "en_USX" cmp "en_US" */ } /** * Check the relationship between requested locales, and report problems. * The caller specifies the expected relationships between requested * and valid (expReqValid) and between valid and actual (expValidActual). * Possible values are: * "gt" strictly greater than, e.g., en_US > en * "ge" greater or equal, e.g., en >= en * "eq" equal, e.g., en == en */ void checklocs(String label, String req, Locale validLoc, Locale actualLoc, String expReqValid, String expValidActual) { String valid = validLoc.toString(); String actual = actualLoc.toString(); int reqValid = loccmp(req, valid); int validActual = loccmp(valid, actual); boolean reqOK = (expReqValid.equals("gt") && reqValid > 0) || (expReqValid.equals("ge") && reqValid >= 0) || (expReqValid.equals("eq") && reqValid == 0); boolean valOK = (expValidActual.equals("gt") && validActual > 0) || (expValidActual.equals("ge") && validActual >= 0) || (expValidActual.equals("eq") && validActual == 0); if (reqOK && valOK) { logln("Ok: " + label + "; req=" + req + ", valid=" + valid + ", actual=" + actual); } else { errln("FAIL: " + label + "; req=" + req + ", valid=" + valid + ", actual=" + actual + (reqOK ? "" : "\n req !" + expReqValid + " valid") + (valOK ? "" : "\n val !" + expValidActual + " actual")); } } /** * Interface used by checkService defining a protocol to create an * object, given a requested locale. */ interface ServiceFacade { Object create(ULocale requestedLocale); } /** * Interface used by checkService defining a protocol to get a * contained subobject, given its parent object. */ interface Subobject { Object get(Object parent); } /** * Interface used by checkService defining a protocol to register * and unregister a service object prototype. */ interface Registrar { Object register(ULocale loc, Object prototype); boolean unregister(Object key); } /** * Use reflection to call getLocale() on the given object to * determine both the valid and the actual locale. Verify these * for correctness. */ void checkObject(String requestedLocale, Object obj, String expReqValid, String expValidActual) { Class[] getLocaleParams = new Class[] { ULocale.Type.class }; try { Class cls = obj.getClass(); Method getLocale = cls.getMethod("getLocale", getLocaleParams); ULocale valid = (ULocale) getLocale.invoke(obj, new Object[] { ULocale.VALID_LOCALE }); ULocale actual = (ULocale) getLocale.invoke(obj, new Object[] { ULocale.ACTUAL_LOCALE }); checklocs(cls.getName(), requestedLocale, valid.toLocale(), actual.toLocale(), expReqValid, expValidActual); } // Make the following exceptions _specific_ -- do not // catch(Exception), since that will catch the exception // that errln throws. catch(NoSuchMethodException e1) { // no longer an error, Currency has no getLocale // errln("FAIL: reflection failed: " + e1); } catch(SecurityException e2) { errln("FAIL: reflection failed: " + e2); } catch(IllegalAccessException e3) { errln("FAIL: reflection failed: " + e3); } catch(IllegalArgumentException e4) { errln("FAIL: reflection failed: " + e4); } catch(InvocationTargetException e5) { // no longer an error, Currency has no getLocale // errln("FAIL: reflection failed: " + e5); } } /** * Verify the correct getLocale() behavior for the given service. * @param requestedLocale the locale to request. This MUST BE * FAKE. In other words, it should be something like * en_US_FAKEVARIANT so this method can verify correct fallback * behavior. * @param svc a factory object that can create the object to be * tested. This isn't necessary here (one could just pass in the * object) but is required for the overload of this method that * takes a Registrar. */ void checkService(String requestedLocale, ServiceFacade svc) { checkService(requestedLocale, svc, null, null); } /** * Verify the correct getLocale() behavior for the given service. * @param requestedLocale the locale to request. This MUST BE * FAKE. In other words, it should be something like * en_US_FAKEVARIANT so this method can verify correct fallback * behavior. * @param svc a factory object that can create the object to be * tested. * @param sub an object that can be used to retrieve a subobject * which should also be tested. May be null. * @param reg an object that supplies the registration and * unregistration functionality to be tested. May be null. */ void checkService(String requestedLocale, ServiceFacade svc, Subobject sub, Registrar reg) { ULocale req = new ULocale(requestedLocale); Object obj = svc.create(req); checkObject(requestedLocale, obj, "gt", "ge"); if (sub != null) { Object subobj = sub.get(obj); checkObject(requestedLocale, subobj, "gt", "ge"); } if (reg != null) { logln("Info: Registering service"); Object key = reg.register(req, obj); Object objReg = svc.create(req); checkObject(requestedLocale, objReg, "eq", "eq"); if (sub != null) { Object subobj = sub.get(obj); // Assume subobjects don't come from services, so // their metadata should be structured normally. checkObject(requestedLocale, subobj, "gt", "ge"); } logln("Info: Unregistering service"); if (!reg.unregister(key)) { errln("FAIL: unregister failed"); } Object objUnreg = svc.create(req); checkObject(requestedLocale, objUnreg, "gt", "ge"); } } private static final int LOCALE_SIZE = 9; private static final String[][] rawData2 = new String[][]{ /* language code */ { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" }, /* script code */ { "", "", "", "", "", "Hans", "", "", "" }, /* country code */ { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" }, /* variant code */ { "", "", "", "", "NY", "", "", "", "" }, /* full name */ { "en_US", "fr_FR", "ca_ES", "el_GR", "no_NO_NY", "zh_Hans_CN", "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" }, /* ISO-3 language */ { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" }, /* ISO-3 country */ { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" }, /* LCID */ { "409", "40c", "403", "408", "814", "804", "407", "a", "411" }, /* display language (English) */ { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" }, /* display script code (English) */ { "", "", "", "", "", "Simplified Han", "", "", "" }, /* display country (English) */ { "United States", "France", "Spain", "Greece", "Norway", "China", "Germany", "", "Japan" }, /* display variant (English) */ { "", "", "", "", "NY", "", "", "", "" }, /* display name (English) */ { "English (United States)", "French (France)", "Catalan (Spain)", "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese (Simplified Han, China)", "German (Germany, Collation=Phonebook Sort Order)", "Spanish (Collation=Traditional)", "Japanese (Japan, Calendar=Japanese Calendar)" }, /* display language (French) */ { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" }, /* display script code (French) */ { "", "", "", "", "", "Hans", "", "", "" }, /* display country (French) */ { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine", "Allemagne", "", "Japon" }, /* display variant (French) */ { "", "", "", "", "NY", "", "", "", "" }, /* display name (French) */ { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)", "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois (Hans, Chine)", "allemand (Allemagne, Ordonnancement=Ordre de l'annuaire)", "espagnol (Ordonnancement=Ordre traditionnel)", "japonais (Japon, Calendrier=Calendrier japonais)" }, /* display language (Catalan) */ { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E9s", "alemany", "espanyol", "japon\\u00E8s" }, /* display script code (Catalan) */ { "", "", "", "", "", "Hans", "", "", "" }, /* display country (Catalan) */ { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina", "Alemanya", "", "Jap\\u00F3" }, /* display variant (Catalan) */ { "", "", "", "", "NY", "", "", "", "" }, /* display name (Catalan) */ { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)", "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E9s (Hans, Xina)", "alemany (Alemanya, COLLATION=PHONEBOOK)", "espanyol (COLLATION=TRADITIONAL)", "japon\\u00E8s (Jap\\u00F3, CALENDAR=JAPANESE)" }, /* display language (Greek) */ { "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac", "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac", "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac", "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac", "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac", "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC", "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC", "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC", "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC" }, /* display script code (Greek) */ { "", "", "", "", "", "Hans", "", "", "" }, /* display country (Greek) */ { "\\u0397\\u03bd\\u03c9\\u03bc\\u03ad\\u03bd\\u03b5\\u03c2 \\u03a0\\u03bf\\u03bb\\u03b9\\u03c4\\u03b5\\u03af\\u03b5\\u03c2", "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1", "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1", "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1", "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1", "\\u039A\\u03AF\\u03BD\\u03B1", "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1", "", "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1" }, /* display variant (Greek) */ { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */ /* display name (Greek) */ { "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03bd\\u03c9\\u03bc\\u03ad\\u03bd\\u03b5\\u03c2 \\u03a0\\u03bf\\u03bb\\u03b9\\u03c4\\u03b5\\u03af\\u03b5\\u03c2)", "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)", "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)", "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)", "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)", "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (Hans, \\u039A\\u03AF\\u03BD\\u03B1)", "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1, COLLATION=PHONEBOOK)", "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (COLLATION=TRADITIONAL)", "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC (\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1, CALENDAR=JAPANESE)" } }; // private static final int ENGLISH = 0; // private static final int FRENCH = 1; // private static final int CATALAN = 2; // private static final int GREEK = 3; // private static final int NORWEGIAN = 4; private static final int LANG = 0; private static final int SCRIPT = 1; private static final int CTRY = 2; private static final int VAR = 3; private static final int NAME = 4; // private static final int LANG3 = 5; // private static final int CTRY3 = 6; // private static final int LCID = 7; // private static final int DLANG_EN = 8; // private static final int DSCRIPT_EN = 9; // private static final int DCTRY_EN = 10; // private static final int DVAR_EN = 11; // private static final int DNAME_EN = 12; // private static final int DLANG_FR = 13; // private static final int DSCRIPT_FR = 14; // private static final int DCTRY_FR = 15; // private static final int DVAR_FR = 16; // private static final int DNAME_FR = 17; // private static final int DLANG_CA = 18; // private static final int DSCRIPT_CA = 19; // private static final int DCTRY_CA = 20; // private static final int DVAR_CA = 21; // private static final int DNAME_CA = 22; // private static final int DLANG_EL = 23; // private static final int DSCRIPT_EL = 24; // private static final int DCTRY_EL = 25; // private static final int DVAR_EL = 26; // private static final int DNAME_EL = 27; @Test public void TestBasicGetters() { int i; logln("Testing Basic Getters\n"); for (i = 0; i < LOCALE_SIZE; i++) { String testLocale=(rawData2[NAME][i]); logln("Testing "+ testLocale+".....\n"); String lang =ULocale.getLanguage(testLocale); if (0 !=lang.compareTo(rawData2[LANG][i])) { errln(" Language code mismatch: "+lang+" versus "+ rawData2[LANG][i]); } String ctry=ULocale.getCountry(testLocale); if (0 !=ctry.compareTo(rawData2[CTRY][i])) { errln(" Country code mismatch: "+ctry+" versus "+ rawData2[CTRY][i]); } String var=ULocale.getVariant(testLocale); if (0 !=var.compareTo(rawData2[VAR][i])) { errln(" Variant code mismatch: "+var+" versus "+ rawData2[VAR][i]); } String name = ULocale.getName(testLocale); if (0 !=name.compareTo(rawData2[NAME][i])) { errln(" Name mismatch: "+name+" versus "+ rawData2[NAME][i]); } } } @Test public void TestPrefixes() { // POSIX ids are no longer handled by getName, so POSIX failures are ignored final String [][] testData = new String[][]{ /* null canonicalize() column means "expect same as getName()" */ {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", null}, {"en", "", "GB", "", "en-gb", "en_GB", null}, {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", null}, {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", null}, {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", null}, {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", null}, {"de", "", "", "1901", "de-1901", "de__1901", null}, {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"}, {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"}, {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */ {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"}, {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"}, {"no", "", "NO", "NY_B", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"}, {"no", "", "NO", "B", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"}, {"no", "", "", "NY", "no__ny", "no__NY", null}, {"no", "", "", "NY", "no@ny", "no@ny", "no__NY"}, {"el", "Latn", "", "", "el-latn", "el_Latn", null}, {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", null}, {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", "zh_Hant_TW@collation=stroke"}, {"zh", "Hant", "CN", "STROKE", "zh-hant_CN_STROKE", "zh_Hant_CN_STROKE", "zh_Hant_CN@collation=stroke"}, {"zh", "Hant", "TW", "PINYIN", "zh-hant_TW_PINYIN", "zh_Hant_TW_PINYIN", "zh_Hant_TW@collation=pinyin"}, {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", null}, {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", null}, {"ab", "Cdef", "GH", "IJ", "ab_cdef_gh_ij", "ab_Cdef_GH_IJ", null}, /* total garbage */ // odd cases {"", "", "", "", "@FOO=bar", "@foo=bar", null}, {"", "", "", "", "_@FOO=bar", "@foo=bar", null}, {"", "", "", "", "__@FOO=bar", "@foo=bar", null}, {"", "", "", "FOO", "__foo@FOO=bar", "__FOO@foo=bar", null}, // we have some of these prefixes }; String loc, buf,buf1; final String [] testTitles = { "ULocale.getLanguage()", "ULocale.getScript()", "ULocale.getCountry()", "ULocale.getVariant()", "name", "ULocale.getName()", "canonicalize()", }; ULocale uloc; for(int row=0;row ["+buf+"]"); String expected = testData[row][n]; if (expected == null && n == (NAME+2)) { expected = testData[row][NAME+1]; } // ignore POSIX failures in getName, we don't spec behavior in this case if (n == NAME+1 && (expected.indexOf('.') != -1 || expected.indexOf('@') != -1)) { continue; } if(buf.compareTo(expected)!=0) { errln("#"+row+": "+testTitles[n]+" on "+loc+": -> ["+buf+"] (expected '"+expected+"'!)"); } if(buf1.compareTo(expected)!=0) { errln("#"+row+": "+testTitles[n]+" on ULocale object "+loc+": -> ["+buf1+"] (expected '"+expected+"'!)"); } } } } @Test public void TestUldnWithGarbage(){ LocaleDisplayNames ldn = LocaleDisplayNames.getInstance(Locale.US, DisplayContext.DIALECT_NAMES); String badLocaleID = "english (United States) [w"; String expectedResult = "english [united states] [w"; // case changed from input String result = ldn.localeDisplayName(badLocaleID); if (result.compareTo(expectedResult) != 0) { errln("FAIL: LocaleDisplayNames.localeDisplayName(String) for bad locale ID \"" + badLocaleID + "\", expected \"" + expectedResult + "\", got \"" + result + "\""); } ULocale badLocale = new ULocale(badLocaleID); result = ldn.localeDisplayName(badLocale); if (result.compareTo(expectedResult) != 0) { errln("FAIL: LocaleDisplayNames.localeDisplayName(ULocale) for bad locale ID \"" + badLocaleID + "\", expected \"" + expectedResult + "\", got \"" + result + "\""); } } @Test public void TestObsoleteNames(){ final String[][] tests = new String[][]{ /* locale, language3, language2, Country3, country2 */ { "eng_USA", "eng", "en", "USA", "US" }, { "kok", "kok", "kok", "", "" }, { "in", "ind", "in", "", "" }, { "id", "ind", "id", "", "" }, /* NO aliasing */ { "sh", "srp", "sh", "", "" }, { "zz_CS", "", "zz", "SCG", "CS" }, { "zz_FX", "", "zz", "FXX", "FX" }, { "zz_RO", "", "zz", "ROU", "RO" }, { "zz_TP", "", "zz", "TMP", "TP" }, { "zz_TL", "", "zz", "TLS", "TL" }, { "zz_ZR", "", "zz", "ZAR", "ZR" }, { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */ { "zz_ROM", "", "zz", "ROU", "RO" }, { "zz_ROU", "", "zz", "ROU", "RO" }, { "zz_ZAR", "", "zz", "ZAR", "ZR" }, { "zz_TMP", "", "zz", "TMP", "TP" }, { "zz_TLS", "", "zz", "TLS", "TL" }, { "zz_YUG", "", "zz", "YUG", "YU" }, { "mlt_PSE", "mlt", "mt", "PSE", "PS" }, { "iw", "heb", "iw", "", "" }, { "ji", "yid", "ji", "", "" }, { "jw", "jaw", "jw", "", "" }, { "sh", "srp", "sh", "", "" }, { "", "", "", "", "" } }; for(int i=0;i " + name + ", " + l.getDisplayName(ULocale.GERMAN) + ", " + l.getDisplayName(ULocale.FRANCE)); String language = l.getDisplayLanguage(); String script = l.getDisplayScriptInContext(); String country = l.getDisplayCountry(); String variant = l.getDisplayVariant(); checkName(name, language, script, country, variant, ULocale.getDefault()); for (int j = 0; j < locales.length; ++j) { ULocale dl = locales[j]; name = l.getDisplayName(dl); language = l.getDisplayLanguage(dl); script = l.getDisplayScriptInContext(dl); country = l.getDisplayCountry(dl); variant = l.getDisplayVariant(dl); if (!checkName(name, language, script, country, variant, dl)) { break; } } } } // spot check { ULocale[] locales = { ULocale.US, ULocale.GERMANY, ULocale.FRANCE }; String[] names = { "Chinese (China)", "Chinesisch (China)", "chinois (Chine)" }; String[] names2 = { "Simplified Chinese (China)", "Chinesisch (vereinfacht) (China)", "chinois simplifi\u00E9 (Chine)" }; ULocale locale = new ULocale("zh_CN"); ULocale locale2 = new ULocale("zh_Hans_CN"); for (int i = 0; i < locales.length; ++i) { String name = locale.getDisplayName(locales[i]); if (!names[i].equals(name)) { errln("expected '" + names[i] + "' but got '" + name + "'"); } } for (int i = 0; i < locales.length; ++i) { String name = locale2.getDisplayNameWithDialect(locales[i]); if (!names2[i].equals(name)) { errln("expected '" + names2[i] + "' but got '" + name + "'"); } } } // test use of context { final DisplayContext NM_STD = DisplayContext.STANDARD_NAMES; final DisplayContext NM_DIA = DisplayContext.DIALECT_NAMES; final DisplayContext CAP_BEG = DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE; final DisplayContext CAP_MID = DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE; final DisplayContext CAP_UIL = DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU; final DisplayContext CAP_STA = DisplayContext.CAPITALIZATION_FOR_STANDALONE; final DisplayContext CAP_NON = DisplayContext.CAPITALIZATION_NONE; final DisplayContext LEN_FU = DisplayContext.LENGTH_FULL; final DisplayContext LEN_SH = DisplayContext.LENGTH_SHORT; final DisplayContext SUB_SU = DisplayContext.SUBSTITUTE; final DisplayContext SUB_NO = DisplayContext.NO_SUBSTITUTE; class Item { public String displayLocale; public DisplayContext dialectHandling; public DisplayContext capitalization; public DisplayContext nameLength; public DisplayContext substituteHandling; public String localeToBeNamed; public String result; public Item(String dLoc, DisplayContext dia, DisplayContext cap, DisplayContext nameLen, DisplayContext sub, String locToName, String res) { displayLocale = dLoc; dialectHandling = dia; capitalization = cap; nameLength = nameLen; substituteHandling = sub; localeToBeNamed = locToName; result = res; } }; final Item[] items = { new Item("da", NM_STD, CAP_MID, LEN_FU, SUB_SU, "en", "engelsk"), new Item("da", NM_STD, CAP_BEG, LEN_FU, SUB_SU, "en", "Engelsk"), new Item("da", NM_STD, CAP_UIL, LEN_FU, SUB_SU, "en", "Engelsk"), new Item("da", NM_STD, CAP_STA, LEN_FU, SUB_SU, "en", "engelsk"), new Item("da", NM_STD, CAP_MID, LEN_FU, SUB_SU, "en@calendar=buddhist", "engelsk (buddhistisk kalender)"), new Item("da", NM_STD, CAP_BEG, LEN_FU, SUB_SU, "en@calendar=buddhist", "Engelsk (buddhistisk kalender)"), new Item("da", NM_STD, CAP_UIL, LEN_FU, SUB_SU, "en@calendar=buddhist", "Engelsk (buddhistisk kalender)"), new Item("da", NM_STD, CAP_STA, LEN_FU, SUB_SU, "en@calendar=buddhist", "engelsk (buddhistisk kalender)"), new Item("da", NM_STD, CAP_MID, LEN_FU, SUB_SU, "en_GB", "engelsk (Storbritannien)"), new Item("da", NM_STD, CAP_BEG, LEN_FU, SUB_SU, "en_GB", "Engelsk (Storbritannien)"), new Item("da", NM_STD, CAP_UIL, LEN_FU, SUB_SU, "en_GB", "Engelsk (Storbritannien)"), new Item("da", NM_STD, CAP_STA, LEN_FU, SUB_SU, "en_GB", "engelsk (Storbritannien)"), new Item("da", NM_STD, CAP_MID, LEN_SH, SUB_SU, "en_GB", "engelsk (UK)"), new Item("da", NM_STD, CAP_BEG, LEN_SH, SUB_SU, "en_GB", "Engelsk (UK)"), new Item("da", NM_STD, CAP_UIL, LEN_SH, SUB_SU, "en_GB", "Engelsk (UK)"), new Item("da", NM_STD, CAP_STA, LEN_SH, SUB_SU, "en_GB", "engelsk (UK)"), new Item("da", NM_DIA, CAP_MID, LEN_FU, SUB_SU, "en_GB", "britisk engelsk"), new Item("da", NM_DIA, CAP_BEG, LEN_FU, SUB_SU, "en_GB", "Britisk engelsk"), new Item("da", NM_DIA, CAP_UIL, LEN_FU, SUB_SU, "en_GB", "Britisk engelsk"), new Item("da", NM_DIA, CAP_STA, LEN_FU, SUB_SU, "en_GB", "britisk engelsk"), new Item("es", NM_STD, CAP_MID, LEN_FU, SUB_SU, "en", "ingl\u00E9s"), new Item("es", NM_STD, CAP_BEG, LEN_FU, SUB_SU, "en", "Ingl\u00E9s"), new Item("es", NM_STD, CAP_UIL, LEN_FU, SUB_SU, "en", "Ingl\u00E9s"), new Item("es", NM_STD, CAP_STA, LEN_FU, SUB_SU, "en", "Ingl\u00E9s"), new Item("es", NM_STD, CAP_MID, LEN_FU, SUB_SU, "en_GB", "ingl\u00E9s (Reino Unido)"), new Item("es", NM_STD, CAP_BEG, LEN_FU, SUB_SU, "en_GB", "Ingl\u00E9s (Reino Unido)"), new Item("es", NM_STD, CAP_UIL, LEN_FU, SUB_SU, "en_GB", "Ingl\u00E9s (Reino Unido)"), new Item("es", NM_STD, CAP_STA, LEN_FU, SUB_SU, "en_GB", "Ingl\u00E9s (Reino Unido)"), new Item("es", NM_STD, CAP_MID, LEN_SH, SUB_SU, "en_GB", "ingl\u00E9s (RU)"), new Item("es", NM_STD, CAP_BEG, LEN_SH, SUB_SU, "en_GB", "Ingl\u00E9s (RU)"), new Item("es", NM_STD, CAP_UIL, LEN_SH, SUB_SU, "en_GB", "Ingl\u00E9s (RU)"), new Item("es", NM_STD, CAP_STA, LEN_SH, SUB_SU, "en_GB", "Ingl\u00E9s (RU)"), new Item("es", NM_DIA, CAP_MID, LEN_FU, SUB_SU, "en_GB", "ingl\u00E9s brit\u00E1nico"), new Item("es", NM_DIA, CAP_BEG, LEN_FU, SUB_SU, "en_GB", "Ingl\u00E9s brit\u00E1nico"), new Item("es", NM_DIA, CAP_UIL, LEN_FU, SUB_SU, "en_GB", "Ingl\u00E9s brit\u00E1nico"), new Item("es", NM_DIA, CAP_STA, LEN_FU, SUB_SU, "en_GB", "Ingl\u00E9s brit\u00E1nico"), new Item("ru", NM_STD, CAP_MID, LEN_FU, SUB_SU, "uz_Latn", "\u0443\u0437\u0431\u0435\u043A\u0441\u043A\u0438\u0439 (\u043B\u0430\u0442\u0438\u043D\u0438\u0446\u0430)"), new Item("ru", NM_STD, CAP_BEG, LEN_FU, SUB_SU, "uz_Latn", "\u0423\u0437\u0431\u0435\u043A\u0441\u043A\u0438\u0439 (\u043B\u0430\u0442\u0438\u043D\u0438\u0446\u0430)"), new Item("ru", NM_STD, CAP_UIL, LEN_FU, SUB_SU, "uz_Latn", "\u0423\u0437\u0431\u0435\u043A\u0441\u043A\u0438\u0439 (\u043B\u0430\u0442\u0438\u043D\u0438\u0446\u0430)"), new Item("ru", NM_STD, CAP_STA, LEN_FU, SUB_SU, "uz_Latn", "\u0423\u0437\u0431\u0435\u043A\u0441\u043A\u0438\u0439 (\u043B\u0430\u0442\u0438\u043D\u0438\u0446\u0430)"), new Item("en", NM_STD, CAP_MID, LEN_FU, SUB_SU, "ur@numbers=latn", "Urdu (Western Digits)"), new Item("en", NM_STD, CAP_MID, LEN_FU, SUB_SU, "ur@numbers=arabext", "Urdu (Extended Arabic-Indic Digits)"), new Item("en", NM_STD, CAP_MID, LEN_SH, SUB_SU, "ur@numbers=arabext", "Urdu (X Arabic-Indic Digits)"), new Item("af", NM_STD, CAP_NON, LEN_FU, SUB_NO, "aa", "Afar"), new Item("cs", NM_STD, CAP_NON, LEN_FU, SUB_NO, "vai", "vai"), }; for (Item item: items) { ULocale locale = new ULocale(item.displayLocale); LocaleDisplayNames ldn = LocaleDisplayNames.getInstance(locale, item.dialectHandling, item.capitalization, item.nameLength, item.substituteHandling); DisplayContext dialectHandling = ldn.getContext(DisplayContext.Type.DIALECT_HANDLING); assertEquals("consistent dialect handling", dialectHandling == DisplayContext.DIALECT_NAMES, ldn.getDialectHandling() == LocaleDisplayNames.DialectHandling.DIALECT_NAMES); DisplayContext capitalization = ldn.getContext(DisplayContext.Type.CAPITALIZATION); DisplayContext nameLength = ldn.getContext(DisplayContext.Type.DISPLAY_LENGTH); DisplayContext substituteHandling = ldn.getContext(DisplayContext.Type.SUBSTITUTE_HANDLING); if (dialectHandling != item.dialectHandling || capitalization != item.capitalization || nameLength != item.nameLength || substituteHandling != item.substituteHandling) { errln("FAIL: displayLoc: " + item.displayLocale + ", dialectNam?: " + item.dialectHandling + ", capitalize: " + item.capitalization + ", nameLen: " + item.nameLength + ", substituteHandling: " + item.substituteHandling + ", locToName: " + item.localeToBeNamed + ", => read back dialectNam?: " + dialectHandling + ", capitalize: " + capitalization + ", nameLen: " + nameLength + ", substituteHandling: " + substituteHandling); } else { String result = ldn.localeDisplayName(item.localeToBeNamed); if (!(item.result == null && result == null) && !(result != null && result.equals(item.result))) { errln("FAIL: displayLoc: " + item.displayLocale + ", dialectNam?: " + item.dialectHandling + ", capitalize: " + item.capitalization + ", nameLen: " + item.nameLength + ", substituteHandling: " + item.substituteHandling + ", locToName: " + item.localeToBeNamed + ", => expected result: " + item.result + ", got: " + result); } } } } } public void TestDisplayLanguageWithDialectCoverage() { // Coverage test. Implementation is in class LocaleDisplayNames. assertFalse("en in system default locale: anything but empty", ULocale.ENGLISH.getDisplayLanguageWithDialect().isEmpty()); assertEquals("en in de", "Englisch", ULocale.ENGLISH.getDisplayLanguageWithDialect(ULocale.GERMAN)); assertEquals("en (string) in de", "Englisch", ULocale.getDisplayLanguageWithDialect("en", ULocale.GERMAN)); assertEquals("en (string) in de (string)", "Englisch", ULocale.getDisplayLanguageWithDialect("en", "de")); } public void TestDisplayNameWithDialectCoverage() { // Coverage test. Implementation is in class LocaleDisplayNames. assertFalse("en-GB in system default locale: anything but empty", ULocale.UK.getDisplayNameWithDialect().isEmpty()); assertEquals("en-GB in de", "Britisches Englisch", ULocale.UK.getDisplayNameWithDialect(ULocale.GERMAN)); assertEquals("en-GB (string) in de", "Britisches Englisch", ULocale.getDisplayNameWithDialect("en-GB", ULocale.GERMAN)); assertEquals("en-GB (string) in de (string)", "Britisches Englisch", ULocale.getDisplayNameWithDialect("en-GB", "de")); } public void TestDisplayScriptCoverage() { // Coverage test. Implementation is in class LocaleDisplayNames. assertFalse("zh-Hans in system default locale: anything but empty", ULocale.SIMPLIFIED_CHINESE.getDisplayScript().isEmpty()); // Stand-alone script name, so not just "Vereinfacht". assertEquals("zh-Hans in de", "Vereinfachtes Chinesisch", ULocale.SIMPLIFIED_CHINESE.getDisplayScript(ULocale.GERMAN)); assertEquals("zh-Hans (string) in de", "Vereinfachtes Chinesisch", ULocale.getDisplayScript("zh-Hans", ULocale.GERMAN)); assertEquals("zh-Hans (string) in de (string)", "Vereinfachtes Chinesisch", ULocale.getDisplayScript("zh-Hans", "de")); } private boolean checkName(String name, String language, String script, String country, String variant, ULocale dl) { if (!checkInclusion(dl, name, language, "language")) { return false; } if (!checkInclusion(dl, name, script, "script")) { return false; } if (!checkInclusion(dl, name, country, "country")) { return false; } if (!checkInclusion(dl, name, variant, "variant")) { return false; } return true; } private boolean checkInclusion(ULocale dl, String name, String substring, String substringName) { if (substring.length() > 0 && name.indexOf(substring) == -1) { String country2 = substring.replace('(', '[').replace(')',']').replace('(', '[').replace(')',']'); if (name.indexOf(country2) == -1) { errln("loc: " + dl + " name '" + name + "' does not contain " + substringName + " '" + substring + "'"); return false; } } return true; } @Test public void TestCoverage() { { //Cover displayXXX int i, j; String localeID="zh_CN"; String name, language, script, country, variant; logln("Covering APIs with signature displayXXX(String, String)"); for (i = 0; i < LOCALE_SIZE; i++) { //localeID String String testLocale=(rawData2[NAME][i]); logln("Testing "+ testLocale+"....."); name = ULocale.getDisplayName(localeID, testLocale); language = ULocale.getDisplayLanguage(localeID, testLocale); script = ULocale.getDisplayScriptInContext(localeID, testLocale); country = ULocale.getDisplayCountry(localeID, testLocale); variant = ULocale.getDisplayVariant(localeID, testLocale); if (!checkName(name, language, script, country, variant, new ULocale(testLocale))) { break; } } logln("Covering APIs with signature displayXXX(String, ULocale)\n"); for (j = 0; j < LOCALE_SIZE; j++) { String testLocale=(rawData2[NAME][j]); ULocale loc = new ULocale(testLocale); logln("Testing "+ testLocale+"....."); name = ULocale.getDisplayName(localeID, loc); language = ULocale.getDisplayLanguage(localeID, loc); script = ULocale.getDisplayScriptInContext(localeID, loc); country = ULocale.getDisplayCountry(localeID, loc); variant = ULocale.getDisplayVariant(localeID, loc); if (!checkName(name, language, script, country, variant, loc)) { break; } } } ULocale loc1 = new ULocale("en_US_BROOKLYN"); ULocale loc2 = new ULocale("en","US","BROOKLYN"); if (!loc2.equals(loc1)){ errln("ULocale.ULocale(String a, String b, String c)"); } ULocale loc3 = new ULocale("en_US"); ULocale loc4 = new ULocale("en","US"); if (!loc4.equals(loc3)){ errln("ULocale.ULocale(String a, String b)"); } ULocale loc5 = (ULocale) loc4.clone(); if (!loc5.equals(loc4)){ errln("ULocale.clone should get the same ULocale"); } ULocale.getISOCountries(); // To check the result ?! } @Test public void TestBamBm() { // "bam" shouldn't be there since the official code is 'bm' String[] isoLanguages = ULocale.getISOLanguages(); for (int i = 0; i < isoLanguages.length; ++i) { if ("bam".equals(isoLanguages[i])) { errln("found bam"); } if (i > 0 && isoLanguages[i].compareTo(isoLanguages[i-1]) <= 0) { errln("language list out of order: '" + isoLanguages[i] + " <= " + isoLanguages[i-1]); } } } @Test public void TestDisplayKeyword() { //prepare testing data initHashtable(); String[] data = {"en_US@collation=phonebook;calendar=islamic-civil", "zh_Hans@collation=pinyin;calendar=chinese", "foo_Bar_BAZ@collation=traditional;calendar=buddhist"}; for (int i = 0; i < data.length; i++) { String localeID = data[i]; logln(""); logln("Testing locale " + localeID + " ..."); ULocale loc = new ULocale(localeID); Iterator it = loc.getKeywords(); Iterator it2 = ULocale.getKeywords(localeID); //it and it2 are not equal here. No way to verify their equivalence yet. while(it.hasNext()) { String key = (String)it.next(); String key2 = (String)it2.next(); if (!key.equals(key2)) { errln("FAIL: static and non-static getKeywords returned different results."); } //To verify display of Keyword // display the above key in English String s0 = ULocale.getDisplayKeyword(key); //display in default locale String s1 = ULocale.getDisplayKeyword(key, ULocale.US); String s2 = ULocale.getDisplayKeyword(key, "en_US"); if (!s1.equals(s2)) { errln ("FAIL: one of the getDisplayKeyword methods failed."); } if (ULocale.getDefault().equals(ULocale.US) && !s1.equals(s0)) { errln ("FAIL: getDisplayKeyword methods failed for the default locale."); } if (!s1.equals(h[0].get(key))) { errln("Locale " + localeID + " getDisplayKeyword for key: " + key + " in English expected \"" + h[0].get(key) + "\" saw \"" + s1 + "\" instead"); } else { logln("OK: getDisplayKeyword for key: " + key + " in English got " + s1); } // display the key in S-Chinese s1 = ULocale.getDisplayKeyword(key, ULocale.CHINA); s2 = ULocale.getDisplayKeyword(key, "zh_Hans"); if (!s1.equals(s2)) { errln ("one of the getDisplayKeyword methods failed."); } if (!s1.equals(h[1].get(key))) { errln("Locale " + localeID + " getDisplayKeyword for key: " + key + " in Chinese expected \"" + h[1].get(key) + "\" saw \"" + s1 + "\" instead"); } else { logln("OK: getDisplayKeyword for key: " + key + " in Chinese got " + s1); } //To verify display of Keyword values String type = loc.getKeywordValue(key); // display type in English String ss0 = loc.getDisplayKeywordValue(key); String ss1 = loc.getDisplayKeywordValue(key, ULocale.US); String ss2 = ULocale.getDisplayKeywordValue(localeID, key, "en_US"); String ss3 = ULocale.getDisplayKeywordValue(localeID, key, ULocale.US); if (!ss1.equals(ss2) || !ss1.equals(ss3)) { errln ("FAIL: one of the getDisplayKeywordValue methods failed."); } if (ULocale.getDefault().equals(ULocale.US) && !ss1.equals(ss0)) { errln ("FAIL: getDisplayKeyword methods failed for the default locale."); } if (!ss1.equals(h[0].get(type))) { errln(" Locale " + localeID + " getDisplayKeywordValue for key: " + key + " in English expected \"" + h[0].get(type) + "\" saw \"" + ss1 + "\" instead"); } else { logln("OK: getDisplayKeywordValue for key: " + key + " in English got " + ss1); } // display type in Chinese ss0 = loc.getDisplayKeywordValue(key); ss1 = loc.getDisplayKeywordValue(key, ULocale.CHINA); ss2 = ULocale.getDisplayKeywordValue(localeID, key, "zh_Hans"); ss3 = ULocale.getDisplayKeywordValue(localeID, key, ULocale.CHINA); if (!ss1.equals(ss2) || !ss1.equals(ss3)) { errln ("one of the getDisplayKeywordValue methods failed."); } if (!ss1.equals(h[1].get(type))) { errln("Locale " + localeID + " getDisplayKeywordValue for key: " + key + " in Chinese expected \"" + h[1].get(type) + "\" saw \"" + ss1 + "\" instead"); } else { logln("OK: getDisplayKeywordValue for key: " + key + " in Chinese got " + ss1); } } } } @Test public void TestDisplayWithKeyword() { // Note, this test depends on locale display data for the U.S. and Taiwan. // If the data changes (in particular, the keyTypePattern may change for Taiwan), // this test will break. LocaleDisplayNames dn = LocaleDisplayNames.getInstance(ULocale.US, DialectHandling.DIALECT_NAMES); LocaleDisplayNames tdn = LocaleDisplayNames.getInstance(ULocale.TAIWAN, DialectHandling.DIALECT_NAMES); String name = dn.localeDisplayName("de@collation=phonebook"); String target = "German (Phonebook Sort Order)"; assertEquals("collation", target, name); name = tdn.localeDisplayName("de@collation=phonebook"); target = "德文(電話簿排序)"; // \u5FB7\u6587\uFF08\u96FB\u8A71\u7C3F\u6392\u5E8F\uFF09 assertEquals("collation", target, name); name = dn.localeDisplayName("ja@currency=JPY"); target = "Japanese (Japanese Yen)"; assertEquals("currency (JPY)", target, name); name = tdn.localeDisplayName("ja@currency=JPY"); target = "日文(日圓)"; // \u65E5\u6587\uFF08\u65E5\u5713\uFF09 assertEquals("currency (JPY)", target, name); name = dn.localeDisplayName("de@currency=XYZ"); target = "German (Currency: XYZ)"; assertEquals("currency (XYZ)", target, name); name = dn.localeDisplayName("de@collation=phonebook;currency=XYZ"); target = "German (Phonebook Sort Order, Currency: XYZ)"; assertEquals("currency", target, name); name = dn.localeDisplayName("de_Latn_DE"); target = "German (Latin, Germany)"; assertEquals("currency", target, name); name = tdn.localeDisplayName("de@currency=XYZ"); target = "德文(貨幣:XYZ)"; // \u5FB7\u6587\uFF08\u8CA8\u5E63: XYZ\uFF09 assertEquals("currency", target, name); name = tdn.localeDisplayName("de@collation=phonebook;currency=XYZ"); target = "德文(電話簿排序,貨幣:XYZ)"; // \u5FB7\u6587\uFF08\u96FB\u8A71\u7C3F\u6392\u5E8F\uFF09,\u5FB7\u6587\uFF08\u8CA8\u5E63: XYZ\uFF09 assertEquals("collation", target, name); name = dn.localeDisplayName("de@foo=bar"); target = "German (foo=bar)"; assertEquals("foo", target, name); name = tdn.localeDisplayName("de@foo=bar"); target = "德文(foo=bar)"; // \u5FB7\u6587\uFF08foo=bar\uFF09 assertEquals("foo", target, name); ULocale locale = ULocale.forLanguageTag("de-x-foobar"); name = dn.localeDisplayName(locale); target = "German (Private-Use: foobar)"; assertEquals("foobar", target, name); name = tdn.localeDisplayName(locale); target = "德文(私人使用:foobar)"; // \u5FB7\u6587\uFF08\u79C1\u4EBA\u4F7F\u7528: foobar\uFF09 assertEquals("foobar", target, name); } private void initHashtable() { h[0] = new HashMap(); h[1] = new HashMap(); //display in English h[0].put("collation", "Sort Order"); h[0].put("calendar", "Calendar"); h[0].put("currency", "Currency"); h[0].put("phonebook", "Phonebook Sort Order"); h[0].put("pinyin", "Pinyin Sort Order"); h[0].put("traditional", "Traditional Sort Order"); h[0].put("stroke", "Stroke Order"); h[0].put("japanese", "Japanese Calendar"); h[0].put("buddhist", "Buddhist Calendar"); h[0].put("islamic", "Islamic Calendar"); h[0].put("islamic-civil", "Islamic Calendar (tabular, civil epoch)" ); h[0].put("hebrew", "Hebrew Calendar"); h[0].put("chinese", "Chinese Calendar"); h[0].put("gregorian", "Gregorian Calendar" ); //display in S-Chinese h[1].put("collation", "\u6392\u5E8F"); h[1].put("calendar", "\u65E5\u5386"); h[1].put("currency", "\u8D27\u5E01"); h[1].put("phonebook", "\u7535\u8BDD\u7C3F\u6392\u5E8F"); h[1].put("pinyin", "\u62FC\u97F3\u6392\u5E8F"); h[1].put("stroke", "\u7B14\u5212\u987A\u5E8F"); h[1].put("traditional", "\u4F20\u7EDF\u6392\u5E8F"); h[1].put("japanese", "\u65E5\u672C\u65E5\u5386"); h[1].put("buddhist", "\u4F5B\u5386"); h[1].put("islamic", "\u4F0A\u65AF\u5170\u65E5\u5386"); h[1].put("islamic-civil", "\u4F0A\u65AF\u5170\u5E0C\u5409\u6765\u65E5\u5386"); h[1].put("hebrew", "\u5E0C\u4F2F\u6765\u65E5\u5386"); h[1].put("chinese", "\u519C\u5386"); h[1].put("gregorian", "\u516C\u5386"); } //Hashtables for storing expected display of keys/types of locale in English and Chinese private static Map[] h = new Map[2]; private static final String ACCEPT_LANGUAGE_TESTS[][] = { /*# result fallback? */ /*0*/ { "mt_MT", "false" }, /*1*/ { "en", "false" }, /*2*/ { "en", "true" }, // fell back from en-zzz to en /*3*/ { null, "true" }, /*4*/ { "es", "false" }, /*5*/ { "de", "false" }, /*6*/ { "zh_TW", "false" }, /*7*/ { "zh", "true" }, }; private static final String ACCEPT_LANGUAGE_HTTP[] = { /*0*/ "mt-mt, ja;q=0.76, en-us;q=0.95, en;q=0.92, en-gb;q=0.89, fr;q=0.87, iu-ca;q=0.84, iu;q=0.82, ja-jp;q=0.79, mt;q=0.97, de-de;q=0.74, de;q=0.71, es;q=0.68, it-it;q=0.66, it;q=0.63, vi-vn;q=0.61, vi;q=0.58, nl-nl;q=0.55, nl;q=0.53, th-th-traditional;q=.01", /*1*/ "ja;q=0.5, en;q=0.8, tlh", /*2*/ "en-zzz, de-lx;q=0.8", /*3*/ "mga-ie;q=0.9, tlh", /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "+ "es", /*5*/ "de;q=.9, fr;q=.9, xxx-yyy, sr;q=.8", /*6*/ "zh-tw", /*7*/ "zh-hant-cn", }; @Test public void TestAcceptLanguage() { for(int i = 0 ; i < (ACCEPT_LANGUAGE_HTTP.length); i++) { Boolean expectBoolean = new Boolean(ACCEPT_LANGUAGE_TESTS[i][1]); String expectLocale=ACCEPT_LANGUAGE_TESTS[i][0]; logln("#" + i + ": expecting: " + expectLocale + " (" + expectBoolean + ")"); boolean r[] = { false }; ULocale n = ULocale.acceptLanguage(ACCEPT_LANGUAGE_HTTP[i], r); if((n==null)&&(expectLocale!=null)) { errln("result was null! line #" + i); continue; } if(((n==null)&&(expectLocale==null)) || (n.toString().equals(expectLocale))) { logln(" locale: OK." ); } else { errln("expected " + expectLocale + " but got " + n.toString()); } if(expectBoolean.equals(new Boolean(r[0]))) { logln(" bool: OK."); } else { errln("bool: not OK, was " + new Boolean(r[0]).toString() + " expected " + expectBoolean.toString()); } } } private ULocale[] StringToULocaleArray(String acceptLanguageList){ //following code is copied from //ULocale.acceptLanguage(String acceptLanguageList, ULocale[] availableLocales, boolean[] fallback) class ULocaleAcceptLanguageQ implements Comparable { private double q; private double serial; public ULocaleAcceptLanguageQ(double theq, int theserial) { q = theq; serial = theserial; } @Override public int compareTo(Object o) { ULocaleAcceptLanguageQ other = (ULocaleAcceptLanguageQ) o; if(q > other.q) { // reverse - to sort in descending order return -1; } else if(q < other.q) { return 1; } if(serial < other.serial) { return -1; } else if(serial > other.serial) { return 1; } else { return 0; // same object } } } // 1st: parse out the acceptLanguageList into an array TreeMap map = new TreeMap(); final int l = acceptLanguageList.length(); int n; for(n=0;n 0) { ULocale org = new ULocale(maximal); ULocale res = ULocale.minimizeSubtags(org); String exp = full_data[i][2]; if (exp.length() == 0) { if (!org.equals(res)) { errln("Original: " + full_data[i][1] + " expected: " + exp + " - but got " + res.toString()); } } else if (!res.toString().equals(exp)) { errln("Original: " + full_data[i][1] + " expected: " + exp + " - but got " + res.toString()); } } } } @Test public void TestCLDRVersion() { //VersionInfo zeroVersion = VersionInfo.getInstance(0, 0, 0, 0); VersionInfo testExpect; VersionInfo testCurrent; VersionInfo cldrVersion; cldrVersion = LocaleData.getCLDRVersion(); TestFmwk.logln("uloc_getCLDRVersion() returned: '"+cldrVersion+"'"); // why isn't this public for tests somewhere? final ClassLoader testLoader = ICUResourceBundleTest.class.getClassLoader(); UResourceBundle bundle = UResourceBundle.getBundleInstance("android/icu/dev/data/testdata", ULocale.ROOT, testLoader); testExpect = VersionInfo.getInstance(bundle.getString("ExpectCLDRVersionAtLeast")); testCurrent = VersionInfo.getInstance(bundle.getString("CurrentCLDRVersion")); logln("(data) ExpectCLDRVersionAtLeast { "+testExpect+""); if(cldrVersion.compareTo(testExpect)<0) { errln("CLDR version is too old, expect at least "+testExpect+"."); } int r = cldrVersion.compareTo(testCurrent); if ( r < 0 ) { logln("CLDR version is behind 'current' (for testdata/root.txt) "+testCurrent+". Some things may fail.\n"); } else if ( r > 0) { logln("CLDR version is ahead of 'current' (for testdata/root.txt) "+testCurrent+". Some things may fail.\n"); } else { // CLDR version is OK. } } @Test public void TestToLanguageTag() { final String[][] locale_to_langtag = { {"", "und"}, {"en", "en"}, {"en_US", "en-US"}, {"iw_IL", "he-IL"}, {"sr_Latn_SR", "sr-Latn-SR"}, {"en_US_POSIX@ca=japanese", "en-US-u-ca-japanese-va-posix"}, {"en__POSIX", "en-u-va-posix"}, {"en_US_POSIX_VAR", "en-US-posix-x-lvariant-var"}, // variant POSIX_VAR is processed as regular variant {"en_US_VAR_POSIX", "en-US-x-lvariant-var-posix"}, // variant VAR_POSIX is processed as regular variant {"en_US_POSIX@va=posix2", "en-US-u-va-posix2"}, // if keyword va=xxx already exists, variant POSIX is simply dropped {"und_555", "und-555"}, {"123", "und"}, {"%$#&", "und"}, {"_Latn", "und-Latn"}, {"_DE", "und-DE"}, {"und_FR", "und-FR"}, {"th_TH_TH", "th-TH-x-lvariant-th"}, {"bogus", "bogus"}, {"foooobarrr", "und"}, {"aa_BB_CYRL", "aa-BB-x-lvariant-cyrl"}, {"en_US_1234", "en-US-1234"}, {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb"}, {"en_US_VARIANTB_VARIANTA", "en-US-variantb-varianta"}, {"ja__9876_5432", "ja-9876-5432"}, {"zh_Hant__VAR", "zh-Hant-x-lvariant-var"}, {"es__BADVARIANT_GOODVAR", "es"}, {"es__GOODVAR_BAD_BADVARIANT", "es-goodvar-x-lvariant-bad"}, {"en@calendar=gregorian", "en-u-ca-gregory"}, {"de@collation=phonebook;calendar=gregorian", "de-u-ca-gregory-co-phonebk"}, {"th@numbers=thai;z=extz;x=priv-use;a=exta", "th-a-exta-u-nu-thai-z-extz-x-priv-use"}, {"en@timezone=America/New_York;calendar=japanese", "en-u-ca-japanese-tz-usnyc"}, {"en@timezone=US/Eastern", "en-u-tz-usnyc"}, {"en@x=x-y-z;a=a-b-c", "en-x-x-y-z"}, {"it@collation=badcollationtype;colStrength=identical;cu=usd-eur", "it-u-cu-usd-eur-ks-identic"}, {"en_US_POSIX", "en-US-u-va-posix"}, {"en_US_POSIX@calendar=japanese;currency=EUR","en-US-u-ca-japanese-cu-eur-va-posix"}, {"@x=elmer", "x-elmer"}, {"_US@x=elmer", "und-US-x-elmer"}, /* #12671 */ {"en@a=bar;attribute=baz", "en-a-bar-u-baz"}, {"en@a=bar;attribute=baz;x=u-foo", "en-a-bar-u-baz-x-u-foo"}, {"en@attribute=baz", "en-u-baz"}, {"en@attribute=baz;calendar=islamic-civil", "en-u-baz-ca-islamic-civil"}, {"en@a=bar;calendar=islamic-civil;x=u-foo", "en-a-bar-u-ca-islamic-civil-x-u-foo"}, {"en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo", "en-a-bar-u-baz-ca-islamic-civil-x-u-foo"}, }; for (int i = 0; i < locale_to_langtag.length; i++) { ULocale loc = new ULocale(locale_to_langtag[i][0]); String langtag = loc.toLanguageTag(); if (!langtag.equals(locale_to_langtag[i][1])) { errln("FAIL: toLanguageTag returned language tag [" + langtag + "] for locale [" + loc + "] - expected: [" + locale_to_langtag[i][1] + "]"); } } } @Test public void TestForLanguageTag() { final Integer NOERROR = Integer.valueOf(-1); final Object[][] langtag_to_locale = { {"en", "en", NOERROR}, {"en-us", "en_US", NOERROR}, {"und-us", "_US", NOERROR}, {"und-latn", "_Latn", NOERROR}, {"en-us-posix", "en_US_POSIX", NOERROR}, {"de-de_euro", "de", Integer.valueOf(3)}, {"kok-in", "kok_IN", NOERROR}, {"123", "", Integer.valueOf(0)}, {"en_us", "", Integer.valueOf(0)}, {"en-latn-x", "en_Latn", Integer.valueOf(8)}, {"art-lojban", "jbo", NOERROR}, {"zh-hakka", "hak", NOERROR}, {"zh-cmn-CH", "cmn_CH", NOERROR}, {"xxx-yy", "xxx_YY", NOERROR}, {"fr-234", "fr_234", NOERROR}, {"i-default", "en@x=i-default", NOERROR}, {"i-test", "", Integer.valueOf(0)}, {"ja-jp-jp", "ja_JP", Integer.valueOf(6)}, {"bogus", "bogus", NOERROR}, {"boguslang", "", Integer.valueOf(0)}, {"EN-lATN-us", "en_Latn_US", NOERROR}, {"und-variant-1234", "__VARIANT_1234", NOERROR}, {"und-varzero-var1-vartwo", "__VARZERO", Integer.valueOf(12)}, {"en-u-ca-gregory", "en@calendar=gregorian", NOERROR}, {"en-U-cu-USD", "en@currency=usd", NOERROR}, {"en-us-u-va-posix", "en_US_POSIX", NOERROR}, {"en-us-u-ca-gregory-va-posix", "en_US_POSIX@calendar=gregorian", NOERROR}, {"en-us-posix-u-va-posix", "en_US_POSIX@va=posix", NOERROR}, {"en-us-u-va-posix2", "en_US@va=posix2", NOERROR}, {"en-us-vari1-u-va-posix", "en_US_VARI1@va=posix", NOERROR}, {"ar-x-1-2-3", "ar@x=1-2-3", NOERROR}, {"fr-u-nu-latn-cu-eur", "fr@currency=eur;numbers=latn", NOERROR}, {"de-k-kext-u-co-phonebk-nu-latn", "de@collation=phonebook;k=kext;numbers=latn", NOERROR}, {"ja-u-cu-jpy-ca-jp", "ja@calendar=yes;currency=jpy;jp=yes", NOERROR}, {"en-us-u-tz-usnyc", "en_US@timezone=America/New_York", NOERROR}, {"und-a-abc-def", "@a=abc-def", NOERROR}, {"zh-u-ca-chinese-x-u-ca-chinese", "zh@calendar=chinese;x=u-ca-chinese", NOERROR}, {"fr--FR", "fr", Integer.valueOf(3)}, {"fr-", "fr", Integer.valueOf(3)}, {"x-elmer", "@x=elmer", NOERROR}, {"en-US-u-attr1-attr2-ca-gregory", "en_US@attribute=attr1-attr2;calendar=gregorian", NOERROR}, {"sr-u-kn", "sr@colnumeric=yes", NOERROR}, {"de-u-kn-co-phonebk", "de@collation=phonebook;colnumeric=yes", NOERROR}, {"en-u-attr2-attr1-kn-kb", "en@attribute=attr1-attr2;colbackwards=yes;colnumeric=yes", NOERROR}, {"ja-u-ijkl-efgh-abcd-ca-japanese-xx-yyy-zzz-kn", "ja@attribute=abcd-efgh-ijkl;calendar=japanese;colnumeric=yes;xx=yyy-zzz", NOERROR}, {"de-u-xc-xphonebk-co-phonebk-ca-buddhist-mo-very-lo-extensi-xd-that-de-should-vc-probably-xz-killthebuffer", "de@calendar=buddhist;collation=phonebook;de=should;lo=extensi;mo=very;vc=probably;xc=xphonebk;xd=that;xz=yes", Integer.valueOf(92)}, /* #12761 */ {"en-a-bar-u-baz", "en@a=bar;attribute=baz", NOERROR}, {"en-a-bar-u-baz-x-u-foo", "en@a=bar;attribute=baz;x=u-foo", NOERROR}, {"en-u-baz", "en@attribute=baz", NOERROR}, {"en-u-baz-ca-islamic-civil", "en@attribute=baz;calendar=islamic-civil", NOERROR}, {"en-a-bar-u-ca-islamic-civil-x-u-foo", "en@a=bar;calendar=islamic-civil;x=u-foo", NOERROR}, {"en-a-bar-u-baz-ca-islamic-civil-x-u-foo", "en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo", NOERROR}, }; for (int i = 0; i < langtag_to_locale.length; i++) { String tag = (String)langtag_to_locale[i][0]; ULocale expected = new ULocale((String)langtag_to_locale[i][1]); ULocale loc = ULocale.forLanguageTag(tag); if (!loc.equals(expected)) { errln("FAIL: forLanguageTag returned locale [" + loc + "] for language tag [" + tag + "] - expected: [" + expected + "]"); } } // Use locale builder to check errors for (int i = 0; i < langtag_to_locale.length; i++) { String tag = (String)langtag_to_locale[i][0]; ULocale expected = new ULocale((String)langtag_to_locale[i][1]); int errorIdx = ((Integer)langtag_to_locale[i][2]).intValue(); try { Builder bld = new Builder(); bld.setLanguageTag(tag); ULocale loc = bld.build(); if (!loc.equals(expected)) { errln("FAIL: forLanguageTag returned locale [" + loc + "] for language tag [" + tag + "] - expected: [" + expected + "]"); } if (errorIdx != NOERROR.intValue()) { errln("FAIL: Builder.setLanguageTag should throw an exception for input tag [" + tag + "]"); } } catch (IllformedLocaleException ifle) { if (ifle.getErrorIndex() != errorIdx) { errln("FAIL: Builder.setLanguageTag returned error index " + ifle.getErrorIndex() + " for input language tag [" + tag + "] expected: " + errorIdx); } } } } /* * Test that if you use any locale without keyword that you will get a NULL * string returned and not throw and exception. */ @Test public void Test4735() { try { new ULocale("und").getDisplayKeywordValue("calendar",ULocale.GERMAN); new ULocale("en").getDisplayKeywordValue("calendar",ULocale.GERMAN); } catch (Exception e) { errln("Unexpected exception: " + e.getMessage()); } } @Test public void TestGetFallback() { // Testing static String getFallback(String) final String[][] TESTIDS = { {"en_US", "en", "", ""}, // ULocale.getFallback("") should return "" {"EN_us_Var", "en_US", "en", ""}, // Case is always normalized {"de_DE@collation=phonebook", "de@collation=phonebook", "@collation=phonebook", "@collation=phonebook"}, // Keyword is preserved {"en__POSIX", "en", ""}, // Trailing empty segment should be truncated {"_US_POSIX", "_US", ""}, // Same as above {"root", ""}, // No canonicalization }; for (String[] chain : TESTIDS) { for (int i = 1; i < chain.length; i++) { String fallback = ULocale.getFallback(chain[i-1]); assertEquals("getFallback(\"" + chain[i-1] + "\")", chain[i], fallback); } } // Testing ULocale getFallback() final ULocale[][] TESTLOCALES = { {new ULocale("en_US"), new ULocale("en"), ULocale.ROOT, null}, {new ULocale("en__POSIX"), new ULocale("en"), ULocale.ROOT, null}, {new ULocale("de_DE@collation=phonebook"), new ULocale("de@collation=phonebook"), new ULocale("@collation=phonebook"), null}, {new ULocale("_US_POSIX"), new ULocale("_US"), ULocale.ROOT, null}, {new ULocale("root"), ULocale.ROOT, null}, }; for(ULocale[] chain : TESTLOCALES) { for (int i = 1; i < chain.length; i++) { ULocale fallback = chain[i-1].getFallback(); assertEquals("ULocale(" + chain[i-1] + ").getFallback()", chain[i], fallback); } } } @Test public void TestExtension() { String[][] TESTCASES = { // {"", "", "", "", "", ....}, {"en"}, {"en-a-exta-b-extb", "a", "exta", "b", "extb"}, {"en-b-extb-a-exta", "a", "exta", "b", "extb"}, {"de-x-a-bc-def", "x", "a-bc-def"}, {"ja-JP-u-cu-jpy-ca-japanese-x-java", "u", "ca-japanese-cu-jpy", "x", "java"}, }; for (String[] testcase : TESTCASES) { ULocale loc = ULocale.forLanguageTag(testcase[0]); int nExtensions = (testcase.length - 1) / 2; Set keys = loc.getExtensionKeys(); if (keys.size() != nExtensions) { errln("Incorrect number of extensions: returned=" + keys.size() + ", expected=" + nExtensions + ", locale=" + testcase[0]); } for (int i = 0; i < nExtensions; i++) { String kstr = testcase[i/2 + 1]; String ext = loc.getExtension(Character.valueOf(kstr.charAt(0))); if (ext == null || !ext.equals(testcase[i/2 + 2])) { errln("Incorrect extension value: key=" + kstr + ", returned=" + ext + ", expected=" + testcase[i/2 + 2] + ", locale=" + testcase[0]); } } } // Exception handling boolean sawException = false; try { ULocale l = ULocale.forLanguageTag("en-US-a-exta"); l.getExtension('$'); } catch (IllegalArgumentException e) { sawException = true; } if (!sawException) { errln("getExtension must throw an exception on illegal input key"); } } @Test public void TestUnicodeLocaleExtension() { String[][] TESTCASES = { //"", ",,...", ",,...", "", "", ...}, {"en", null, null}, {"en-a-ext1-x-privuse", null, null}, {"en-u-attr1-attr2", "attr1,attr2", null}, {"ja-u-ca-japanese-cu-jpy", null, "ca,cu", "japanese", "jpy"}, {"th-TH-u-number-attr-nu-thai-ca-buddhist", "attr,number", "ca,nu", "buddhist", "thai"}, }; for (String[] testcase : TESTCASES) { ULocale loc = ULocale.forLanguageTag(testcase[0]); Set expectedAttributes = new HashSet(); if (testcase[1] != null) { String[] attrs = testcase[1].split(","); for (String s : attrs) { expectedAttributes.add(s); } } Map expectedKeywords = new HashMap(); if (testcase[2] != null) { String[] ukeys = testcase[2].split(","); for (int i = 0; i < ukeys.length; i++) { expectedKeywords.put(ukeys[i], testcase[i + 3]); } } // Check attributes Set attributes = loc.getUnicodeLocaleAttributes(); if (attributes.size() != expectedAttributes.size()) { errln("Incorrect number for Unicode locale attributes: returned=" + attributes.size() + ", expected=" + expectedAttributes.size() + ", locale=" + testcase[0]); } if (!attributes.containsAll(expectedAttributes) || !expectedAttributes.containsAll(attributes)) { errln("Incorrect set of attributes for locale " + testcase[0]); } // Check keywords Set keys = loc.getUnicodeLocaleKeys(); Set expectedKeys = expectedKeywords.keySet(); if (keys.size() != expectedKeys.size()) { errln("Incorrect number for Unicode locale keys: returned=" + keys.size() + ", expected=" + expectedKeys.size() + ", locale=" + testcase[0]); } for (String expKey : expectedKeys) { String type = loc.getUnicodeLocaleType(expKey); String expType = expectedKeywords.get(expKey); if (type == null || !expType.equals(type)) { errln("Incorrect Unicode locale type: key=" + expKey + ", returned=" + type + ", expected=" + expType + ", locale=" + testcase[0]); } } } // Exception handling boolean sawException = false; try { ULocale l = ULocale.forLanguageTag("en-US-u-ca-gregory"); l.getUnicodeLocaleType("$%"); } catch (IllegalArgumentException e) { sawException = true; } if (!sawException) { errln("getUnicodeLocaleType must throw an exception on illegal input key"); } } @Test public void TestForLocale() { Object[][] DATA = { {new Locale(""), ""}, {new Locale("en", "US"), "en_US"}, {new Locale("en", "US", "POSIX"), "en_US_POSIX"}, {new Locale("", "US"), "_US"}, {new Locale("en", "", "POSIX"), "en__POSIX"}, {new Locale("no", "NO", "NY"), "nn_NO"}, {new Locale("en", "BOGUS"), "en__BOGUS"}, // ill-formed country is mapped to variant - see #8383 and #8384 }; for (int i = 0; i < DATA.length; i++) { ULocale uloc = ULocale.forLocale((Locale) DATA[i][0]); assertEquals("forLocale with " + DATA[i][0], DATA[i][1], uloc.getName()); } if (JAVA7_OR_LATER) { Object[][] DATA7 = { {new Locale("ja", "JP", "JP"), "ja_JP_JP@calendar=japanese"}, {new Locale("th", "TH", "TH"), "th_TH_TH@numbers=thai"}, }; for (int i = 0; i < DATA7.length; i++) { ULocale uloc = ULocale.forLocale((Locale) DATA7[i][0]); assertEquals("forLocale with " + DATA7[i][0], DATA7[i][1], uloc.getName()); } try { Method localeForLanguageTag = Locale.class.getMethod("forLanguageTag", String.class); String[][] DATA7EXT = { {"en-Latn-US", "en_Latn_US"}, {"zh-Hant-TW", "zh_Hant_TW"}, {"und-US-u-cu-usd", "_US@currency=usd"}, {"th-TH-u-ca-buddhist-nu-thai", "th_TH@calendar=buddhist;numbers=thai"}, {"en-US-u-va-POSIX", "en_US_POSIX"}, {"de-DE-u-co-phonebk", "de_DE@collation=phonebook"}, {"en-a-exta-b-extb-x-privu", "en@a=exta;b=extb;x=privu"}, {"fr-u-attr1-attr2-cu-eur", "fr@attribute=attr1-attr2;currency=eur"}, }; for (int i = 0; i < DATA7EXT.length; i++) { Locale loc = (Locale) localeForLanguageTag.invoke(null, DATA7EXT[i][0]); ULocale uloc = ULocale.forLocale(loc); assertEquals("forLocale with " + loc, DATA7EXT[i][1], uloc.getName()); } } catch (Exception e) { throw new RuntimeException(e); } } else { Object[][] DATA6 = { {new Locale("ja", "JP", "JP"), "ja_JP@calendar=japanese"}, {new Locale("th", "TH", "TH"), "th_TH@numbers=thai"}, }; for (int i = 0; i < DATA6.length; i++) { ULocale uloc = ULocale.forLocale((Locale) DATA6[i][0]); assertEquals("forLocale with " + DATA6[i][0], DATA6[i][1], uloc.getName()); } } } @Test public void TestToLocale() { Object[][] DATA = { {"", new Locale("")}, {"en_US", new Locale("en", "US")}, {"_US", new Locale("", "US")}, {"en__POSIX", new Locale("en", "", "POSIX")}, }; for (int i = 0; i < DATA.length; i++) { Locale loc = new ULocale((String) DATA[i][0]).toLocale(); assertEquals("toLocale with " + DATA[i][0], DATA[i][1], loc); } if (JAVA7_OR_LATER) { Object[][] DATA7 = { {"nn_NO", new Locale("nn", "NO")}, {"no_NO_NY", new Locale("no", "NO", "NY")}, }; for (int i = 0; i < DATA7.length; i++) { Locale loc = new ULocale((String) DATA7[i][0]).toLocale(); assertEquals("toLocale with " + DATA7[i][0], DATA7[i][1], loc); } try { Method localeForLanguageTag = Locale.class.getMethod("forLanguageTag", String.class); String[][] DATA7EXT = { {"en_Latn_US", "en-Latn-US"}, {"zh_Hant_TW", "zh-Hant-TW"}, {"ja_JP@calendar=japanese", "ja-JP-u-ca-japanese"}, {"ja_JP_JP@calendar=japanese", "ja-JP-u-ca-japanese-x-lvariant-JP"}, {"th_TH@numbers=thai", "th-TH-u-nu-thai"}, {"th_TH_TH@numbers=thai", "th-TH-u-nu-thai-x-lvariant-TH"}, {"de@collation=phonebook", "de-u-co-phonebk"}, {"en@a=exta;b=extb;x=privu", "en-a-exta-b-extb-x-privu"}, {"fr@attribute=attr1-attr2;currency=eur", "fr-u-attr1-attr2-cu-eur"}, }; for (int i = 0; i < DATA7EXT.length; i++) { Locale loc = new ULocale(DATA7EXT[i][0]).toLocale(); Locale expected = (Locale) localeForLanguageTag.invoke(null, DATA7EXT[i][1]); assertEquals("toLocale with " + DATA7EXT[i][0], expected, loc); } } catch (Exception e) { throw new RuntimeException(e); } } else { Object[][] DATA6 = { {"nn_NO", new Locale("no", "NO", "NY")}, {"no_NO_NY", new Locale("no", "NO", "NY")}, {"ja_JP@calendar=japanese", new Locale("ja", "JP", "JP")}, {"th_TH@numbers=thai", new Locale("th", "TH", "TH")}, }; for (int i = 0; i < DATA6.length; i++) { Locale loc = new ULocale((String) DATA6[i][0]).toLocale(); assertEquals("toLocale with " + DATA6[i][0], DATA6[i][1], loc); } } } @Test public void TestCategoryDefault() { Locale backupDefault = Locale.getDefault(); ULocale orgDefault = ULocale.getDefault(); // Setting a category default won't change default ULocale ULocale uJaJp = new ULocale("ja_JP"); ULocale uDeDePhonebook = new ULocale("de_DE@collation=phonebook"); ULocale.setDefault(Category.DISPLAY, uJaJp); ULocale.setDefault(Category.FORMAT, uDeDePhonebook); if (!ULocale.getDefault().equals(orgDefault)) { errln("FAIL: Default ULocale is " + ULocale.getDefault() + ", expected: " + orgDefault); } if (!ULocale.getDefault(Category.DISPLAY).equals(uJaJp)) { errln("FAIL: DISPLAY ULocale is " + ULocale.getDefault(Category.DISPLAY) + ", expected: " + uJaJp); } if (!ULocale.getDefault(Category.FORMAT).equals(uDeDePhonebook)) { errln("FAIL: FORMAT ULocale is " + ULocale.getDefault(Category.FORMAT) + ", expected: " + uDeDePhonebook); } // Setting ULocale default will overrides category defaults ULocale uFrFr = new ULocale("fr_FR"); ULocale.setDefault(uFrFr); if (!ULocale.getDefault(Category.DISPLAY).equals(uFrFr)) { errln("FAIL: DISPLAY ULocale is " + ULocale.getDefault(Category.DISPLAY) + ", expected: " + uFrFr); } if (!ULocale.getDefault(Category.FORMAT).equals(uFrFr)) { errln("FAIL: FORMAT ULocale is " + ULocale.getDefault(Category.FORMAT) + ", expected: " + uFrFr); } // Setting Locale default will updates ULocale default and category defaults Locale arEg = new Locale("ar", "EG"); ULocale uArEg = ULocale.forLocale(arEg); Locale.setDefault(arEg); if (!ULocale.getDefault().equals(uArEg)) { errln("FAIL: Default ULocale is " + ULocale.getDefault() + ", expected: " + uArEg); } if (!ULocale.getDefault(Category.DISPLAY).equals(uArEg)) { errln("FAIL: DISPLAY ULocale is " + ULocale.getDefault(Category.DISPLAY) + ", expected: " + uArEg); } if (!ULocale.getDefault(Category.FORMAT).equals(uArEg)) { errln("FAIL: FORMAT ULocale is " + ULocale.getDefault(Category.FORMAT) + ", expected: " + uArEg); } // Restore back up Locale.setDefault(backupDefault); } // // Test case for the behavior of Comparable implementation. // @Test public void TestComparable() { // Test strings used for creating ULocale objects. // This list contains multiple different strings creating // multiple equivalent locales. final String[] localeStrings = { "en", "EN", "en_US", "en_GB", "en_US_POSIX", "en_us_posix", "ar_EG", "zh_Hans_CN", "zh_Hant_TW", "zh_Hans", "zh_CN", "zh_TW", "th_TH@calendar=buddhist;numbers=thai", "TH_TH@NUMBERS=thai;CALENDAR=buddhist", "th_TH@calendar=buddhist", "th_TH@calendar=gergorian", "th_TH@numbers=latn", "abc_def_ghi_jkl_opq", "abc_DEF_ghi_JKL_opq", "", "und", "This is a bogus locale ID", "This is a BOGUS locale ID", "en_POSIX", "en__POSIX", }; ULocale[] locales = new ULocale[localeStrings.length]; for (int i = 0; i < locales.length; i++) { locales[i] = new ULocale(localeStrings[i]); } // compares all permutations for (int i = 0; i < locales.length; i++) { for (int j = i /* including the locale itself */; j < locales.length; j++) { boolean eqls1 = locales[i].equals(locales[j]); boolean eqls2 = locales[i].equals(locales[j]); if (eqls1 != eqls2) { errln("FAILED: loc1.equals(loc2) and loc2.equals(loc1) return different results: loc1=" + locales[i] + ", loc2=" + locales[j]); } int cmp1 = locales[i].compareTo(locales[j]); int cmp2 = locales[j].compareTo(locales[i]); if ((cmp1 == 0) != eqls1) { errln("FAILED: inconsistent equals and compareTo: loc1=" + locales[i] + ", loc2=" + locales[j]); } if (cmp1 < 0 && cmp2 <= 0 || cmp1 > 0 && cmp2 >= 0 || cmp1 == 0 && cmp2 != 0) { errln("FAILED: loc1.compareTo(loc2) is inconsistent with loc2.compareTo(loc1): loc1=" + locales[i] + ", loc2=" + locales[j]); } } } // Make sure ULocale objects can be sorted by the Java collection // framework class without providing a Comparator, and equals/compareTo // are consistent. // The sorted locale list created from localeStrings above. // Duplicated locales are removed and locale string is normalized // (by the ULocale constructor). final String[] sortedLocaleStrings = { "", "abc_DEF_GHI_JKL_OPQ", "ar_EG", "en", "en__POSIX", "en_GB", "en_US", "en_US_POSIX", "th_TH@calendar=buddhist", "th_TH@calendar=buddhist;numbers=thai", "th_TH@calendar=gergorian", "th_TH@numbers=latn", "this is a bogus locale id", "und", "zh_CN", "zh_TW", "zh_Hans", "zh_Hans_CN", "zh_Hant_TW", }; TreeSet sortedLocales = new TreeSet(); for (ULocale locale : locales) { sortedLocales.add(locale); } // Check the number of unique locales if (sortedLocales.size() != sortedLocaleStrings.length) { errln("FAILED: Number of unique locales: " + sortedLocales.size() + ", expected: " + sortedLocaleStrings.length); } // Check the order int i = 0; for (ULocale loc : sortedLocales) { if (!loc.toString().equals(sortedLocaleStrings[i++])) { errln("FAILED: Sort order is incorrect for " + loc.toString()); break; } } } @Test public void TestToUnicodeLocaleKey() { String[][] DATA = { {"calendar", "ca"}, {"CALEndar", "ca"}, // difference casing {"ca", "ca"}, // bcp key itself {"kv", "kv"}, // no difference between legacy and bcp {"foo", null}, // unknown, bcp ill-formed {"ZZ", "zz"}, // unknown, bcp well-formed }; for (String[] d : DATA) { String keyword = d[0]; String expected = d[1]; String bcpKey = ULocale.toUnicodeLocaleKey(keyword); assertEquals("keyword=" + keyword, expected, bcpKey); } } @Test public void TestToLegacyKey() { String[][] DATA = { {"kb", "colbackwards"}, {"kB", "colbackwards"}, // different casing {"Collation", "collation"}, // keyword itself with different casing {"kv", "kv"}, // no difference between legacy and bcp {"foo", "foo"}, // unknown, bcp ill-formed {"ZZ", "zz"}, // unknown, bcp well-formed {"e=mc2", null}, // unknown, bcp/legacy ill-formed }; for (String[] d : DATA) { String keyword = d[0]; String expected = d[1]; String legacyKey = ULocale.toLegacyKey(keyword); assertEquals("bcpKey=" + keyword, expected, legacyKey); } } @Test public void TestToUnicodeLocaleType() { String[][] DATA = { {"tz", "Asia/Kolkata", "inccu"}, {"calendar", "gregorian", "gregory"}, {"ca", "gregorian", "gregory"}, {"ca", "Gregorian", "gregory"}, {"ca", "buddhist", "buddhist"}, {"Calendar", "Japanese", "japanese"}, {"calendar", "Islamic-Civil", "islamic-civil"}, {"calendar", "islamicc", "islamic-civil"}, // bcp type alias {"colalternate", "NON-IGNORABLE", "noignore"}, {"colcaselevel", "yes", "true"}, {"rg", "GBzzzz", "gbzzzz"}, {"tz", "america/new_york", "usnyc"}, {"tz", "Asia/Kolkata", "inccu"}, {"timezone", "navajo", "usden"}, {"ca", "aaaa", "aaaa"}, // unknown type, well-formed type {"ca", "gregory-japanese-islamic", "gregory-japanese-islamic"}, // unknown type, well-formed type {"zz", "gregorian", null}, // unknown key, ill-formed type {"co", "foo-", null}, // unknown type, ill-formed type {"variableTop", "00A0", "00a0"}, // valid codepoints type {"variableTop", "wxyz", "wxyz"}, // invalid codepoints type - return as is for now {"kr", "space-punct", "space-punct"}, // valid reordercode type {"kr", "digit-spacepunct", null}, // invalid reordercode type }; for (String[] d : DATA) { String keyword = d[0]; String value = d[1]; String expected = d[2]; String bcpType = ULocale.toUnicodeLocaleType(keyword, value); assertEquals("keyword=" + keyword + ", value=" + value, expected, bcpType); } } @Test public void TestToLegacyType() { String[][] DATA = { {"calendar", "gregory", "gregorian"}, {"ca", "gregory", "gregorian"}, {"ca", "Gregory", "gregorian"}, {"ca", "buddhist", "buddhist"}, {"Calendar", "Japanese", "japanese"}, {"calendar", "Islamic-Civil", "islamic-civil"}, {"calendar", "islamicc", "islamic-civil"}, // bcp type alias {"colalternate", "noignore", "non-ignorable"}, {"colcaselevel", "true", "yes"}, {"rg", "gbzzzz", "gbzzzz"}, {"tz", "usnyc", "America/New_York"}, {"tz", "inccu", "Asia/Calcutta"}, {"timezone", "usden", "America/Denver"}, {"timezone", "usnavajo", "America/Denver"}, // bcp type alias {"colstrength", "quarternary", "quaternary"}, // type alias {"ca", "aaaa", "aaaa"}, // unknown type {"calendar", "gregory-japanese-islamic", "gregory-japanese-islamic"}, // unknown type, well-formed type {"zz", "gregorian", "gregorian"}, // unknown key, bcp ill-formed type {"ca", "gregorian-calendar", "gregorian-calendar"}, // known key, bcp ill-formed type {"co", "e=mc2", null}, // known key, ill-formed bcp/legacy type {"variableTop", "00A0", "00a0"}, // valid codepoints type {"variableTop", "wxyz", "wxyz"}, // invalid codepoints type - return as is for now {"kr", "space-punct", "space-punct"}, // valid reordercode type {"kr", "digit-spacepunct", "digit-spacepunct"}, // invalid reordercode type, but ok for legacy syntax }; for (String[] d : DATA) { String keyword = d[0]; String value = d[1]; String expected = d[2]; String legacyType = ULocale.toLegacyType(keyword, value); assertEquals("keyword=" + keyword + ", value=" + value, expected, legacyType); } } @Test public void TestIsRightToLeft() { assertFalse("root LTR", ULocale.ROOT.isRightToLeft()); assertFalse("zh LTR", ULocale.CHINESE.isRightToLeft()); assertTrue("ar RTL", new ULocale("ar").isRightToLeft()); assertTrue("und-EG RTL", new ULocale("und-EG").isRightToLeft()); assertFalse("fa-Cyrl LTR", new ULocale("fa-Cyrl").isRightToLeft()); assertTrue("en-Hebr RTL", new ULocale("en-Hebr").isRightToLeft()); assertTrue("ckb RTL", new ULocale("ckb").isRightToLeft()); // Sorani Kurdish assertFalse("fil LTR", new ULocale("fil").isRightToLeft()); assertFalse("he-Zyxw LTR", new ULocale("he-Zyxw").isRightToLeft()); } @Test public void TestChineseToLocale() { final ULocale[][] LOCALES = { {ULocale.CHINESE, new ULocale("zh")}, {ULocale.SIMPLIFIED_CHINESE, new ULocale("zh_Hans")}, {ULocale.TRADITIONAL_CHINESE, new ULocale("zh_Hant")}, {ULocale.CHINA, new ULocale("zh_Hans_CN")}, {ULocale.PRC, new ULocale("zh_Hans_CN")}, {ULocale.TAIWAN, new ULocale("zh_Hant_TW")}, }; // When two ULocales are equal, results of ULocale#toLocale() must be // also equal. for (ULocale[] pair : LOCALES) { if (pair[0].equals(pair[1])) { assertEquals(pair[0].toString(), pair[0].toLocale(), pair[1].toLocale()); } else { // This could happen when the definition of ULocale constant is changed. // When it happens, it could be a mistake. So we use errln below. // If we change the definitioin for a legitimate reason, then the hardcoded // test data above should be reviewed and updated. errln("Error: " + pair[0] + " is not equal to " + pair[1]); } } } }