diff --git a/src/share/classes/java/util/Locale.java b/src/share/classes/java/util/Locale.java index 1f0fbba1eaea8214b94ade566cddc02b94b0830b..efe200ed0dbad1eedbd14e5471626ace75b9252a 100644 --- a/src/share/classes/java/util/Locale.java +++ b/src/share/classes/java/util/Locale.java @@ -1265,7 +1265,9 @@ public final class Locale implements Cloneable, Serializable { StringBuilder buf = new StringBuilder(); String subtag = tag.getLanguage(); - buf.append(LanguageTag.canonicalizeLanguage(subtag)); + if (subtag.length() > 0) { + buf.append(LanguageTag.canonicalizeLanguage(subtag)); + } subtag = tag.getScript(); if (subtag.length() > 0) { @@ -1294,7 +1296,10 @@ public final class Locale implements Cloneable, Serializable { subtag = tag.getPrivateuse(); if (subtag.length() > 0) { - buf.append(LanguageTag.SEP).append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP); + if (buf.length() > 0) { + buf.append(LanguageTag.SEP); + } + buf.append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP); // preserve casing buf.append(subtag); } diff --git a/src/share/classes/sun/util/locale/LanguageTag.java b/src/share/classes/sun/util/locale/LanguageTag.java index 653bb8e05fb27d650602fa28f3853ac3894ce11a..cf35e18e144f89b4c875f363edbb290c4eda7758 100644 --- a/src/share/classes/sun/util/locale/LanguageTag.java +++ b/src/share/classes/sun/util/locale/LanguageTag.java @@ -421,11 +421,11 @@ public class LanguageTag { String region = baseLocale.getRegion(); String variant = baseLocale.getVariant(); + boolean hasSubtag = false; + String privuseVar = null; // store ill-formed variant subtags - if (language.length() == 0 || !isLanguage(language)) { - tag._language = UNDETERMINED; - } else { + if (language.length() > 0 && isLanguage(language)) { // Convert a deprecated language code used by Java to // a new code if (language.equals("iw")) { @@ -440,10 +440,12 @@ public class LanguageTag { if (script.length() > 0 && isScript(script)) { tag._script = canonicalizeScript(script); + hasSubtag = true; } if (region.length() > 0 && isRegion(region)) { tag._region = canonicalizeRegion(region); + hasSubtag = true; } // Special handling for no_NO_NY - use nn_NO for language tag @@ -468,6 +470,7 @@ public class LanguageTag { } if (variants != null) { tag._variants = variants; + hasSubtag = true; } if (!varitr.isDone()) { // ill-formed variant subtags @@ -508,6 +511,7 @@ public class LanguageTag { if (extensions != null) { tag._extensions = extensions; + hasSubtag = true; } // append ill-formed variant subtags to private use @@ -521,8 +525,12 @@ public class LanguageTag { if (privateuse != null) { tag._privateuse = privateuse; - } else if (tag._language.length() == 0) { - // use "und" if neither language nor privateuse is available + } + + if (tag._language.length() == 0 && (hasSubtag || privateuse == null)) { + // use lang "und" when 1) no language is available AND + // 2) any of other subtags other than private use are available or + // no private use tag is available tag._language = UNDETERMINED; } diff --git a/test/java/util/Locale/LocaleEnhanceTest.java b/test/java/util/Locale/LocaleEnhanceTest.java index f7ed5ab3dfb5f183e25587d44d581d2b39299614..5d816bc2eee9b8e7473a44e4b5d5d3eae6b93ee8 100644 --- a/test/java/util/Locale/LocaleEnhanceTest.java +++ b/test/java/util/Locale/LocaleEnhanceTest.java @@ -478,6 +478,23 @@ public class LocaleEnhanceTest extends LocaleTestFmwk { Locale locale = new Locale(test[0], test[1], test[2]); assertEquals("case " + i, test[3], locale.toLanguageTag()); } + + // test locales created from forLanguageTag + String[][] tests1 = { + // case is normalized during the round trip + { "EN-us", "en-US" }, + { "en-Latn-US", "en-Latn-US" }, + // reordering Unicode locale extensions + { "de-u-co-phonebk-ca-gregory", "de-u-ca-gregory-co-phonebk" }, + // private use only language tag is preserved (no extra "und") + { "x-elmer", "x-elmer" }, + { "x-lvariant-JP", "x-lvariant-JP" }, + }; + for (String[] test : tests1) { + Locale locale = Locale.forLanguageTag(test[0]); + assertEquals("case " + test[0], test[1], locale.toLanguageTag()); + } + } public void testForLanguageTag() { @@ -488,9 +505,9 @@ public class LocaleEnhanceTest extends LocaleTestFmwk { String[][] tests = { // private use tags only - { "x-abc", "und-x-abc" }, - { "x-a-b-c", "und-x-a-b-c" }, - { "x-a-12345678", "und-x-a-12345678" }, + { "x-abc", "x-abc" }, + { "x-a-b-c", "x-a-b-c" }, + { "x-a-12345678", "x-a-12345678" }, // grandfathered tags with preferred mappings { "i-ami", "ami" }, @@ -517,7 +534,7 @@ public class LocaleEnhanceTest extends LocaleTestFmwk { // grandfathered irregular tags, no preferred mappings, drop illegal fields // from end. If no subtag is mappable, fallback to 'und' { "i-default", "en-x-i-default" }, - { "i-enochian", "und-x-i-enochian" }, + { "i-enochian", "x-i-enochian" }, { "i-mingo", "see-x-i-mingo" }, { "en-GB-oed", "en-GB-x-oed" }, { "zh-min", "nan-x-zh-min" },