From 85d8adfb5c4e69b379aedd99a9664f7eed701045 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Mon, 21 Jul 2025 11:40:07 -0700 Subject: [PATCH 1/4] initial commit --- .../share/classes/java/util/Locale.java | 28 ++----------- .../jdk/internal/util/StaticProperty.java | 9 ---- .../classes/sun/util/locale/BaseLocale.java | 21 ++++------ .../util/locale/provider/LocaleResources.java | 11 ----- test/jdk/java/util/Locale/LocaleTest.java | 42 ++++++------------- .../java/util/Locale/UseOldISOCodesTest.java | 13 +++--- 6 files changed, 32 insertions(+), 92 deletions(-) diff --git a/src/java.base/share/classes/java/util/Locale.java b/src/java.base/share/classes/java/util/Locale.java index eb69d1dfc2f8f..1a3a9e8372d9f 100644 --- a/src/java.base/share/classes/java/util/Locale.java +++ b/src/java.base/share/classes/java/util/Locale.java @@ -534,28 +534,9 @@ * {@code in}. Since Java SE 17, this is no longer the case. Each * language maps to its new form; {@code iw} maps to {@code he}, {@code ji} * maps to {@code yi}, and {@code in} maps to {@code id}. - * - *

For backwards compatible behavior, the system property - * {@systemProperty java.locale.useOldISOCodes} reverts the behavior - * back to that of before Java SE 17. If the system property is set to - * {@code true}, those three current language codes are mapped to their - * backward compatible forms. The property is only read at Java runtime - * startup and subsequent calls to {@code System.setProperty()} will - * have no effect. As of Java SE 25, the use of the - * {@code java.locale.useOldISOCodes} system property is deprecated. - * This backwards compatible behavior will be removed in a future release - * of the JDK. - * - *

The APIs added in Java SE 7 map between the old and new language codes, - * maintaining the mapped codes internal to Locale (so that - * {@code getLanguage} and {@code toString} reflect the mapped - * code, which depends on the {@code java.locale.useOldISOCodes} system - * property), but using the new codes in the BCP 47 language tag APIs (so - * that {@code toLanguageTag} reflects the new one). This - * preserves the equivalence between Locales no matter which code or - * API is used to construct them. Java's default resource bundle - * lookup mechanism also implements this mapping, so that resources - * can be named using either convention, see {@link ResourceBundle.Control}. + *

The default resource bundle lookup mechanism also implements + * this mapping, so that resources can be named using either convention, + * see {@link ResourceBundle.Control}. * * @spec https://www.rfc-editor.org/info/rfc4647 * RFC 4647: Matching of Language Tags @@ -2517,8 +2498,7 @@ private Object readResolve() throws java.io.ObjectStreamException { private static String convertOldISOCodes(String language) { // we accept both the old and the new ISO codes for the languages whose ISO - // codes have changed, but we always store the NEW code, unless the property - // java.locale.useOldISOCodes is set to "true" + // codes have changed, but we always store the NEW code return BaseLocale.convertOldISOCodes(LocaleUtils.toLowerString(language).intern()); } diff --git a/src/java.base/share/classes/jdk/internal/util/StaticProperty.java b/src/java.base/share/classes/jdk/internal/util/StaticProperty.java index 4fb3ae7a184ee..4740062dcde46 100644 --- a/src/java.base/share/classes/jdk/internal/util/StaticProperty.java +++ b/src/java.base/share/classes/jdk/internal/util/StaticProperty.java @@ -53,7 +53,6 @@ public final class StaticProperty { private static final String STDOUT_ENCODING; private static final String SUN_JNU_ENCODING; private static final String JAVA_PROPERTIES_DATE; - private static final String JAVA_LOCALE_USE_OLD_ISO_CODES; private static final String OS_NAME; private static final String OS_ARCH; private static final String OS_VERSION; @@ -94,7 +93,6 @@ private StaticProperty() {} STDOUT_ENCODING = getProperty(props, "stdout.encoding"); SUN_JNU_ENCODING = getProperty(props, "sun.jnu.encoding"); JAVA_PROPERTIES_DATE = getProperty(props, "java.properties.date", null); - JAVA_LOCALE_USE_OLD_ISO_CODES = getProperty(props, "java.locale.useOldISOCodes", ""); OS_NAME = getProperty(props, "os.name"); OS_ARCH = getProperty(props, "os.arch"); OS_VERSION = getProperty(props, "os.version"); @@ -258,13 +256,6 @@ public static String javaPropertiesDate() { return JAVA_PROPERTIES_DATE; } - /** - * {@return the {@code java.locale.useOldISOCodes} system property} - */ - public static String javaLocaleUseOldISOCodes() { - return JAVA_LOCALE_USE_OLD_ISO_CODES; - } - /** * {@return the {@code os.name} system property} */ diff --git a/src/java.base/share/classes/sun/util/locale/BaseLocale.java b/src/java.base/share/classes/sun/util/locale/BaseLocale.java index 529ca1b0c1310..897d6a7d226e2 100644 --- a/src/java.base/share/classes/sun/util/locale/BaseLocale.java +++ b/src/java.base/share/classes/sun/util/locale/BaseLocale.java @@ -34,7 +34,6 @@ import jdk.internal.misc.CDS; import jdk.internal.util.ReferencedKeySet; -import jdk.internal.util.StaticProperty; import jdk.internal.vm.annotation.Stable; import java.util.StringJoiner; @@ -110,16 +109,14 @@ public ReferencedKeySet get() { private @Stable int hash; /** - * Boolean for the old ISO language code compatibility. - * The system property "java.locale.useOldISOCodes" is not security sensitive, - * so no need to ensure privileged access here. + * Emit the warning message if the system property "java.locale.useOldISOCodes" is + * specified. */ - private static final boolean OLD_ISO_CODES = StaticProperty.javaLocaleUseOldISOCodes() - .equalsIgnoreCase("true"); static { - if (OLD_ISO_CODES) { - System.err.println("WARNING: The use of the system property \"java.locale.useOldISOCodes\"" + - " is deprecated. It will be removed in a future release of the JDK."); + if (!System.getProperty("java.locale.useOldISOCodes", "").isEmpty()) { + System.err.println("WARNING: The system property" + + " \"java.locale.useOldISOCodes\" is no longer supported." + + " Any specified value will be ignored."); } } @@ -183,9 +180,9 @@ public static BaseLocale getInstance(String language, String script, public static String convertOldISOCodes(String language) { return switch (language) { - case "he", "iw" -> OLD_ISO_CODES ? "iw" : "he"; - case "id", "in" -> OLD_ISO_CODES ? "in" : "id"; - case "yi", "ji" -> OLD_ISO_CODES ? "ji" : "yi"; + case "iw" -> "he"; + case "in" -> "id"; + case "ji" -> "yi"; default -> language; }; } diff --git a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java index c539f57141e6e..ac43b22a3bd78 100644 --- a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java +++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java @@ -62,7 +62,6 @@ import java.util.regex.Pattern; import java.util.stream.Stream; -import jdk.internal.util.StaticProperty; import sun.util.resources.LocaleData; import sun.util.resources.OpenListResourceBundle; import sun.util.resources.TimeZoneNamesBundle; @@ -288,16 +287,6 @@ public String getCurrencyName(String key) { } public String getLocaleName(String key) { - // Get names for old ISO codes with new ISO code resources - if (StaticProperty.javaLocaleUseOldISOCodes().equalsIgnoreCase("true")) { - key = switch (key) { - case "iw" -> "he"; - case "in" -> "id"; - case "ji" -> "yi"; - default -> key; - }; - } - Object localeName = null; String cacheKey = LOCALE_NAMES + key; diff --git a/test/jdk/java/util/Locale/LocaleTest.java b/test/jdk/java/util/Locale/LocaleTest.java index 0cf272f20a0d2..a901ac42de9d0 100644 --- a/test/jdk/java/util/Locale/LocaleTest.java +++ b/test/jdk/java/util/Locale/LocaleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * 4118587 4118595 4122371 4126371 4126880 4135316 4135752 4139504 4139940 4143951 * 4147315 4147317 4147552 4335196 4778440 4940539 5010672 6475525 6544471 6627549 * 6786276 7066203 7085757 8008577 8030696 8170840 8174269 8255086 8263202 8287868 - * 8337603 + * 8337603 8355522 * @summary test Locales * @modules jdk.localedata * @run junit LocaleTest @@ -709,34 +709,18 @@ public void TestChangedISO639Codes() { Locale indonesianOld = Locale.of("in"); Locale indonesianNew = Locale.of("id"); - if ("true".equalsIgnoreCase(System.getProperty("java.locale.useOldISOCodes"))) { - if (!hebrewNew.getLanguage().equals("iw")) { - fail("Got back wrong language code for new Hebrew: expected \"iw\", got \"" - + hebrewNew.getLanguage() + "\""); - } - if (!yiddishNew.getLanguage().equals("ji")) { - fail("Got back wrong language code for new Yiddish: expected \"ji\", got \"" - + yiddishNew.getLanguage() + "\""); - } - if (!indonesianNew.getLanguage().equals("in")) { - fail("Got back wrong language code for new Indonesian: expected \"in\", got \"" - + indonesianNew.getLanguage() + "\""); - } - } else { - if (!hebrewOld.getLanguage().equals("he")) { - fail("Got back wrong language code for old Hebrew: expected \"he\", got \"" - + hebrewNew.getLanguage() + "\""); - } - if (!yiddishOld.getLanguage().equals("yi")) { - fail("Got back wrong language code for old Yiddish: expected \"yi\", got \"" - + yiddishNew.getLanguage() + "\""); - } - if (!indonesianOld.getLanguage().equals("id")) { - fail("Got back wrong language code for old Indonesian: expected \"id\", got \"" - + indonesianNew.getLanguage() + "\""); - } + if (!hebrewOld.getLanguage().equals("he")) { + fail("Got back wrong language code for old Hebrew: expected \"he\", got \"" + + hebrewNew.getLanguage() + "\""); + } + if (!yiddishOld.getLanguage().equals("yi")) { + fail("Got back wrong language code for old Yiddish: expected \"yi\", got \"" + + yiddishNew.getLanguage() + "\""); + } + if (!indonesianOld.getLanguage().equals("id")) { + fail("Got back wrong language code for old Indonesian: expected \"id\", got \"" + + indonesianNew.getLanguage() + "\""); } - } /** diff --git a/test/jdk/java/util/Locale/UseOldISOCodesTest.java b/test/jdk/java/util/Locale/UseOldISOCodesTest.java index 1909497535ca9..78a39145ee147 100644 --- a/test/jdk/java/util/Locale/UseOldISOCodesTest.java +++ b/test/jdk/java/util/Locale/UseOldISOCodesTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8295232 8353118 + * @bug 8295232 8353118 8355522 * @summary Tests for the "java.locale.useOldISOCodes" system property * @library /test/lib * @run junit UseOldISOCodesTest @@ -34,7 +34,7 @@ import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; public class UseOldISOCodesTest { @@ -44,7 +44,7 @@ public void testUseOldISOCodes() throws Exception { .outputTo(System.out) .errorTo(System.err); oa.shouldHaveExitValue(0); - oa.stderrShouldMatch("WARNING: The use of the system property \"java.locale.useOldISOCodes\" is deprecated. It will be removed in a future release of the JDK."); + oa.stderrShouldMatch("WARNING: The system property \"java.locale.useOldISOCodes\" is no longer supported. Any specified value will be ignored."); } static class Runner { @@ -52,12 +52,11 @@ static class Runner { private static final String newCode = "he"; public static void main(String[] args) { - // Ensure java.locale.useOldISOCodes is only interpreted at runtime startup - // Should have no effect + // Ensure java.locale.useOldISOCodes should have no effect System.setProperty("java.locale.useOldISOCodes", "false"); Locale locale = Locale.of(newCode); - assertEquals(obsoleteCode, locale.getLanguage(), - "newCode 'he' was not mapped to 'iw' with useOldISOCodes=true"); + assertNotEquals(obsoleteCode, locale.getLanguage(), + "newCode 'he' was mapped to 'iw' with useOldISOCodes=true"); } } } From bcfd8a7ea42cd5072174c0f600c35efc91a8b090 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Tue, 22 Jul 2025 14:58:01 -0700 Subject: [PATCH 2/4] Reflects review comments --- test/jdk/java/util/Locale/UseOldISOCodesTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/jdk/java/util/Locale/UseOldISOCodesTest.java b/test/jdk/java/util/Locale/UseOldISOCodesTest.java index 78a39145ee147..3e836782fc319 100644 --- a/test/jdk/java/util/Locale/UseOldISOCodesTest.java +++ b/test/jdk/java/util/Locale/UseOldISOCodesTest.java @@ -53,9 +53,7 @@ static class Runner { public static void main(String[] args) { // Ensure java.locale.useOldISOCodes should have no effect - System.setProperty("java.locale.useOldISOCodes", "false"); - Locale locale = Locale.of(newCode); - assertNotEquals(obsoleteCode, locale.getLanguage(), + assertNotEquals(obsoleteCode, Locale.of(newCode).getLanguage(), "newCode 'he' was mapped to 'iw' with useOldISOCodes=true"); } } From 93f3a8b340b68e182f0ad909018844dcb6d41d9e Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Tue, 22 Jul 2025 15:18:24 -0700 Subject: [PATCH 3/4] Obsolete comment correction --- src/java.base/share/classes/sun/util/locale/BaseLocale.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/sun/util/locale/BaseLocale.java b/src/java.base/share/classes/sun/util/locale/BaseLocale.java index 897d6a7d226e2..0ec9c7edb11bf 100644 --- a/src/java.base/share/classes/sun/util/locale/BaseLocale.java +++ b/src/java.base/share/classes/sun/util/locale/BaseLocale.java @@ -163,7 +163,8 @@ public static BaseLocale getInstance(String language, String script, } } - // JDK uses deprecated ISO639.1 language codes for he, yi and id + // Normalize deprecated ISO 639-1 language codes for Hebrew, Yiddish, + // and Indonesian to their current standard forms. if (!language.isEmpty()) { language = convertOldISOCodes(language); } From c68a63beb3a0941eb6f1bc94c988fcfa1ce2cce8 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Wed, 23 Jul 2025 10:34:17 -0700 Subject: [PATCH 4/4] Further wording refinement --- src/java.base/share/classes/java/util/Locale.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/java/util/Locale.java b/src/java.base/share/classes/java/util/Locale.java index 1a3a9e8372d9f..7832ab51e3343 100644 --- a/src/java.base/share/classes/java/util/Locale.java +++ b/src/java.base/share/classes/java/util/Locale.java @@ -528,12 +528,10 @@ * *

Legacy language codes

* - *

Locale's constructors have always converted three language codes to - * their earlier, obsoleted forms: {@code he} maps to {@code iw}, - * {@code yi} maps to {@code ji}, and {@code id} maps to - * {@code in}. Since Java SE 17, this is no longer the case. Each - * language maps to its new form; {@code iw} maps to {@code he}, {@code ji} - * maps to {@code yi}, and {@code in} maps to {@code id}. + *

For compatibility, a {@code Locale} created with one of the + * three obsolete language codes, {@code iw}, {@code ji}, or {@code in}, + * will map the language to its modern equivalent, {@code he}, {@code yi}, + * or {@code id}, respectively. *

The default resource bundle lookup mechanism also implements * this mapping, so that resources can be named using either convention, * see {@link ResourceBundle.Control}.