8355522: Remove the java.locale.useOldISOCodes system property

Reviewed-by: jlu, joehw
This commit is contained in:
Naoto Sato 2025-12-09 18:21:12 +00:00
parent b99be505a5
commit b2daf9de30
6 changed files with 38 additions and 104 deletions

View File

@ -535,34 +535,13 @@ import sun.util.locale.provider.TimeZoneNameUtility;
*
* <h3><a id="legacy_language_codes">Legacy language codes</a></h3>
*
* <p>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}.
*
* <p>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. <b>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.</b>
*
* <p>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}.
* <p>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.
* <p>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
@ -2527,8 +2506,7 @@ public final class Locale implements Cloneable, Serializable {
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());
}

View File

@ -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 @@ public final class 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 final class StaticProperty {
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}
*/

View File

@ -34,7 +34,6 @@ package sun.util.locale;
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 final class BaseLocale {
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") != null) {
System.err.println("WARNING: The system property" +
" \"java.locale.useOldISOCodes\" is no longer supported." +
" Any specified value will be ignored.");
}
}
@ -166,7 +163,8 @@ public final class BaseLocale {
}
}
// 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);
}
@ -183,9 +181,9 @@ public final class BaseLocale {
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;
};
}

View File

@ -62,7 +62,6 @@ import java.util.concurrent.ConcurrentMap;
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 class LocaleResources {
}
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;

View File

@ -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
@ -703,40 +703,21 @@ test commented out pending API-change approval
@Test
public void TestChangedISO639Codes() {
Locale hebrewOld = Locale.of("iw", "IL");
Locale hebrewNew = Locale.of("he", "IL");
Locale yiddishOld = Locale.of("ji", "IL");
Locale yiddishNew = Locale.of("yi", "IL");
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 \""
+ hebrewOld.getLanguage() + "\"");
}
if (!yiddishOld.getLanguage().equals("yi")) {
fail("Got back wrong language code for old Yiddish: expected \"yi\", got \""
+ yiddishOld.getLanguage() + "\"");
}
if (!indonesianOld.getLanguage().equals("id")) {
fail("Got back wrong language code for old Indonesian: expected \"id\", got \""
+ indonesianOld.getLanguage() + "\"");
}
}
/**

View File

@ -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 jdk.test.lib.process.ProcessTools;
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 class UseOldISOCodesTest {
.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,9 @@ public class UseOldISOCodesTest {
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
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");
// Ensure java.locale.useOldISOCodes should have no effect
assertNotEquals(obsoleteCode, Locale.of(newCode).getLanguage(),
"newCode 'he' was mapped to 'iw' with useOldISOCodes=true");
}
}
}