Skip to content

Commit a4c46e1

Browse files
committed
8263202: Update Hebrew/Indonesian/Yiddish ISO 639 language codes to current
Reviewed-by: joehw
1 parent 9c346a1 commit a4c46e1

File tree

35 files changed

+345
-146
lines changed

35 files changed

+345
-146
lines changed

make/jdk/src/classes/build/tools/cldrconverter/Bundle.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -156,13 +156,6 @@ String getID() {
156156
return id;
157157
}
158158

159-
String getJavaID() {
160-
// Tweak ISO compatibility for bundle generation
161-
return id.replaceFirst("^he", "iw")
162-
.replaceFirst("^id", "in")
163-
.replaceFirst("^yi", "ji");
164-
}
165-
166159
boolean isRoot() {
167160
return "root".equals(id);
168161
}

make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,6 @@ private static void convertBundles(List<Bundle> bundles) throws Exception {
536536
Map<String, Object> targetMap = bundle.getTargetMap();
537537
EnumSet<Bundle.Type> bundleTypes = bundle.getBundleTypes();
538538
var id = bundle.getID();
539-
var javaId = bundle.getJavaID();
540539

541540
if (bundle.isRoot()) {
542541
// Add DateTimePatternChars because CLDR no longer supports localized patterns.
@@ -548,31 +547,31 @@ private static void convertBundles(List<Bundle> bundles) throws Exception {
548547
if (bundleTypes.contains(Bundle.Type.LOCALENAMES)) {
549548
Map<String, Object> localeNamesMap = extractLocaleNames(targetMap, id);
550549
if (!localeNamesMap.isEmpty() || bundle.isRoot()) {
551-
bundleGenerator.generateBundle("util", "LocaleNames", javaId, true, localeNamesMap, BundleType.OPEN);
550+
bundleGenerator.generateBundle("util", "LocaleNames", id, true, localeNamesMap, BundleType.OPEN);
552551
}
553552
}
554553
if (bundleTypes.contains(Bundle.Type.CURRENCYNAMES)) {
555554
Map<String, Object> currencyNamesMap = extractCurrencyNames(targetMap, id, bundle.getCurrencies());
556555
if (!currencyNamesMap.isEmpty() || bundle.isRoot()) {
557-
bundleGenerator.generateBundle("util", "CurrencyNames", javaId, true, currencyNamesMap, BundleType.OPEN);
556+
bundleGenerator.generateBundle("util", "CurrencyNames", id, true, currencyNamesMap, BundleType.OPEN);
558557
}
559558
}
560559
if (bundleTypes.contains(Bundle.Type.TIMEZONENAMES)) {
561560
Map<String, Object> zoneNamesMap = extractZoneNames(targetMap, id);
562561
if (!zoneNamesMap.isEmpty() || bundle.isRoot()) {
563-
bundleGenerator.generateBundle("util", "TimeZoneNames", javaId, true, zoneNamesMap, BundleType.TIMEZONE);
562+
bundleGenerator.generateBundle("util", "TimeZoneNames", id, true, zoneNamesMap, BundleType.TIMEZONE);
564563
}
565564
}
566565
if (bundleTypes.contains(Bundle.Type.CALENDARDATA)) {
567566
Map<String, Object> calendarDataMap = extractCalendarData(targetMap, id);
568567
if (!calendarDataMap.isEmpty() || bundle.isRoot()) {
569-
bundleGenerator.generateBundle("util", "CalendarData", javaId, true, calendarDataMap, BundleType.PLAIN);
568+
bundleGenerator.generateBundle("util", "CalendarData", id, true, calendarDataMap, BundleType.PLAIN);
570569
}
571570
}
572571
if (bundleTypes.contains(Bundle.Type.FORMATDATA)) {
573572
Map<String, Object> formatDataMap = extractFormatData(targetMap, id);
574573
if (!formatDataMap.isEmpty() || bundle.isRoot()) {
575-
bundleGenerator.generateBundle("text", "FormatData", javaId, true, formatDataMap, BundleType.PLAIN);
574+
bundleGenerator.generateBundle("text", "FormatData", id, true, formatDataMap, BundleType.PLAIN);
576575
}
577576
}
578577

src/java.base/share/classes/java/util/Locale.java

Lines changed: 39 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -444,18 +444,26 @@
444444
* in <a href="#special_cases_constructor">Special Cases</a>, only
445445
* for the two cases th_TH_TH and ja_JP_JP.
446446
*
447-
* <h4>Legacy language codes</h4>
447+
* <h4><a id="legacy_language_codes">Legacy language codes</a></h4>
448448
*
449449
* <p>Locale's constructor has always converted three language codes to
450450
* their earlier, obsoleted forms: {@code he} maps to {@code iw},
451451
* {@code yi} maps to {@code ji}, and {@code id} maps to
452-
* {@code in}. This continues to be the case, in order to not break
453-
* backwards compatibility.
452+
* {@code in}. Since Java SE 17, this is no longer the case. Each
453+
* language maps to its new form; {@code iw} maps to {@code he}, {@code ji}
454+
* maps to {@code yi}, and {@code in} maps to {@code id}.
455+
*
456+
* <p>For the backward compatible behavior, the system property
457+
* {@systemProperty java.locale.useOldISOCodes} reverts the behavior
458+
* back to prior to Java SE 17 one. If the system property is set
459+
* to {@code true}, those three current language codes are mapped to their
460+
* backward compatible forms.
454461
*
455462
* <p>The APIs added in 1.7 map between the old and new language codes,
456-
* maintaining the old codes internal to Locale (so that
457-
* {@code getLanguage} and {@code toString} reflect the old
458-
* code), but using the new codes in the BCP 47 language tag APIs (so
463+
* maintaining the mapped codes internal to Locale (so that
464+
* {@code getLanguage} and {@code toString} reflect the mapped
465+
* code, which depends on the {@code java.locale.useOldISOCodes} system
466+
* property), but using the new codes in the BCP 47 language tag APIs (so
459467
* that {@code toLanguageTag} reflects the new one). This
460468
* preserves the equivalence between Locales no matter which code or
461469
* API is used to construct them. Java's default resource bundle
@@ -720,13 +728,11 @@ private Locale(BaseLocale baseLocale, LocaleExtensions extensions) {
720728
* Construct a locale from language, country and variant.
721729
* This constructor normalizes the language value to lowercase and
722730
* the country value to uppercase.
723-
* <p>
724-
* <b>Note:</b>
731+
* @implNote
725732
* <ul>
726-
* <li>ISO 639 is not a stable standard; some of the language codes it defines
727-
* (specifically "iw", "ji", and "in") have changed. This constructor accepts both the
728-
* old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
729-
* API on Locale will return only the OLD codes.
733+
* <li>Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to
734+
* their current forms. See <a href="#legacy_language_codes">Legacy language
735+
* codes</a> for more information.
730736
* <li>For backward compatibility reasons, this constructor does not make
731737
* any syntactic checks on the input.
732738
* <li>The two cases ("ja", "JP", "JP") and ("th", "TH", "TH") are handled specially,
@@ -754,13 +760,11 @@ public Locale(String language, String country, String variant) {
754760
* Construct a locale from language and country.
755761
* This constructor normalizes the language value to lowercase and
756762
* the country value to uppercase.
757-
* <p>
758-
* <b>Note:</b>
763+
* @implNote
759764
* <ul>
760-
* <li>ISO 639 is not a stable standard; some of the language codes it defines
761-
* (specifically "iw", "ji", and "in") have changed. This constructor accepts both the
762-
* old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
763-
* API on Locale will return only the OLD codes.
765+
* <li>Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to
766+
* their current forms. See <a href="#legacy_language_codes">Legacy language
767+
* codes</a> for more information.
764768
* <li>For backward compatibility reasons, this constructor does not make
765769
* any syntactic checks on the input.
766770
* </ul>
@@ -779,13 +783,11 @@ public Locale(String language, String country) {
779783
/**
780784
* Construct a locale from a language code.
781785
* This constructor normalizes the language value to lowercase.
782-
* <p>
783-
* <b>Note:</b>
786+
* @implNote
784787
* <ul>
785-
* <li>ISO 639 is not a stable standard; some of the language codes it defines
786-
* (specifically "iw", "ji", and "in") have changed. This constructor accepts both the
787-
* old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
788-
* API on Locale will return only the OLD codes.
788+
* <li>Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to
789+
* their current forms. See <a href="#legacy_language_codes">Legacy language
790+
* codes</a> for more information.
789791
* <li>For backward compatibility reasons, this constructor does not make
790792
* any syntactic checks on the input.
791793
* </ul>
@@ -1207,19 +1209,10 @@ private static String[] getISO2Table(String table) {
12071209
/**
12081210
* Returns the language code of this Locale.
12091211
*
1210-
* <p><b>Note:</b> ISO 639 is not a stable standard&mdash; some languages' codes have changed.
1211-
* Locale's constructor recognizes both the new and the old codes for the languages
1212-
* whose codes have changed, but this function always returns the old code. If you
1213-
* want to check for a specific language whose code has changed, don't do
1214-
* <pre>
1215-
* if (locale.getLanguage().equals("he")) // BAD!
1216-
* ...
1217-
* </pre>
1218-
* Instead, do
1219-
* <pre>
1220-
* if (locale.getLanguage().equals(new Locale("he").getLanguage()))
1221-
* ...
1222-
* </pre>
1212+
* @implNote This method returns the new forms for the obsolete ISO 639
1213+
* codes ("iw", "ji", and "in"). See <a href="#legacy_language_codes">
1214+
* Legacy language codes</a> for more information.
1215+
*
12231216
* @return The language code, or the empty string if none is defined.
12241217
* @see #getDisplayLanguage
12251218
*/
@@ -1607,9 +1600,11 @@ public String toLanguageTag() {
16071600
*
16081601
* <li>The language code "und" is mapped to language "".
16091602
*
1610-
* <li>The language codes "he", "yi", and "id" are mapped to "iw",
1611-
* "ji", and "in" respectively. (This is the same canonicalization
1612-
* that's done in Locale's constructors.)
1603+
* <li>The language codes "iw", "ji", and "in" are mapped to "he",
1604+
* "yi", and "id" respectively. (This is the same canonicalization
1605+
* that's done in Locale's constructors.) See
1606+
* <a href="#legacy_language_codes">Legacy language codes</a>
1607+
* for more information.
16131608
*
16141609
* <li>The portion of a private use subtag prefixed by "lvariant",
16151610
* if any, is removed and appended to the variant field in the
@@ -2396,17 +2391,9 @@ private Object readResolve() throws java.io.ObjectStreamException {
23962391

23972392
private static String convertOldISOCodes(String language) {
23982393
// we accept both the old and the new ISO codes for the languages whose ISO
2399-
// codes have changed, but we always store the OLD code, for backward compatibility
2400-
language = LocaleUtils.toLowerString(language).intern();
2401-
if (language == "he") {
2402-
return "iw";
2403-
} else if (language == "yi") {
2404-
return "ji";
2405-
} else if (language == "id") {
2406-
return "in";
2407-
} else {
2408-
return language;
2409-
}
2394+
// codes have changed, but we always store the NEW code, unless the property
2395+
// java.locale.useOldISOCodes is set to "true"
2396+
return BaseLocale.convertOldISOCodes(LocaleUtils.toLowerString(language).intern());
24102397
}
24112398

24122399
private static LocaleExtensions getCompatibilityExtensions(String language,

src/java.base/share/classes/java/util/ResourceBundle.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
import sun.security.action.GetPropertyAction;
7373
import sun.util.locale.BaseLocale;
7474
import sun.util.locale.LocaleObjectCache;
75+
import sun.util.resources.Bundles;
76+
7577
import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION;
7678

7779

@@ -3098,6 +3100,12 @@ public Locale getFallbackLocale(String baseName, Locale locale) {
30983100
* nor {@code "java.properties"}, an
30993101
* {@code IllegalArgumentException} is thrown.</li>
31003102
*
3103+
* <li>If the {@code locale}'s language is one of the
3104+
* <a href="./Locale.html#legacy_language_codes">Legacy language
3105+
* codes</a>, either old or new, then repeat the loading process
3106+
* if needed, with the bundle name with the other language.
3107+
* For example, "iw" for "he" and vice versa.
3108+
*
31013109
* </ul>
31023110
*
31033111
* @param baseName
@@ -3152,6 +3160,21 @@ public ResourceBundle newBundle(String baseName, Locale locale, String format,
31523160
* that is visible to the given loader and accessible to the given caller.
31533161
*/
31543162
String bundleName = toBundleName(baseName, locale);
3163+
var bundle = newBundle0(bundleName, format, loader, reload);
3164+
if (bundle == null) {
3165+
// Try loading legacy ISO language's other bundles
3166+
var otherBundleName = Bundles.toOtherBundleName(baseName, bundleName, locale);
3167+
if (!bundleName.equals(otherBundleName)) {
3168+
bundle = newBundle0(otherBundleName, format, loader, reload);
3169+
}
3170+
}
3171+
3172+
return bundle;
3173+
}
3174+
3175+
private ResourceBundle newBundle0(String bundleName, String format,
3176+
ClassLoader loader, boolean reload)
3177+
throws IllegalAccessException, InstantiationException, IOException {
31553178
ResourceBundle bundle = null;
31563179
if (format.equals("java.class")) {
31573180
try {

src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
2727

2828
import jdk.internal.access.JavaUtilResourceBundleAccess;
2929
import jdk.internal.access.SharedSecrets;
30+
import sun.util.resources.Bundles;
3031

3132
import java.io.IOException;
3233
import java.io.InputStream;
@@ -187,6 +188,17 @@ protected String toBundleName(String baseName, Locale locale) {
187188
public ResourceBundle getBundle(String baseName, Locale locale) {
188189
Module module = this.getClass().getModule();
189190
String bundleName = toBundleName(baseName, locale);
191+
var bundle = getBundle0(module, bundleName);
192+
if (bundle == null) {
193+
var otherBundleName = Bundles.toOtherBundleName(baseName, bundleName, locale);
194+
if (!bundleName.equals(otherBundleName)) {
195+
bundle = getBundle0(module, Bundles.toOtherBundleName(baseName, bundleName, locale));
196+
}
197+
}
198+
return bundle;
199+
}
200+
201+
private ResourceBundle getBundle0(Module module, String bundleName) {
190202
ResourceBundle bundle = null;
191203

192204
for (String format : formats) {

src/java.base/share/classes/sun/util/locale/BaseLocale.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
import jdk.internal.misc.CDS;
3636
import jdk.internal.vm.annotation.Stable;
37+
import sun.security.action.GetPropertyAction;
3738

3839
import java.lang.ref.SoftReference;
3940
import java.util.StringJoiner;
@@ -98,6 +99,13 @@ public final class BaseLocale {
9899

99100
private volatile int hash;
100101

102+
/**
103+
* Boolean for the old ISO language code compatibility.
104+
*/
105+
private static final boolean OLD_ISO_CODES = GetPropertyAction.privilegedGetProperties()
106+
.getProperty("java.locale.useOldISOCodes", "false")
107+
.equalsIgnoreCase("true");
108+
101109
// This method must be called with normalize = false only when creating the
102110
// Locale.* constants and non-normalized BaseLocale$Keys used for lookup.
103111
private BaseLocale(String language, String script, String region, String variant,
@@ -153,19 +161,22 @@ public static BaseLocale getInstance(String language, String script,
153161

154162
// JDK uses deprecated ISO639.1 language codes for he, yi and id
155163
if (!language.isEmpty()) {
156-
if (language.equals("he")) {
157-
language = "iw";
158-
} else if (language.equals("yi")) {
159-
language = "ji";
160-
} else if (language.equals("id")) {
161-
language = "in";
162-
}
164+
language = convertOldISOCodes(language);
163165
}
164166

165167
Key key = new Key(language, script, region, variant, false);
166168
return Cache.CACHE.get(key);
167169
}
168170

171+
public static String convertOldISOCodes(String language) {
172+
return switch (language) {
173+
case "he", "iw" -> OLD_ISO_CODES ? "iw" : "he";
174+
case "id", "in" -> OLD_ISO_CODES ? "in" : "id";
175+
case "yi", "ji" -> OLD_ISO_CODES ? "ji" : "yi";
176+
default -> language;
177+
};
178+
}
179+
169180
public String getLanguage() {
170181
return language;
171182
}

0 commit comments

Comments
 (0)