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
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— 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 ,
0 commit comments