When instantiating a Locale
object with either one of the following language codes: he
, yi
and id
it doesn't preserve their value.
For example:
Locale locale = new Locale("he", "il");
locale.getLanguage(); // -> "iw"
What is causing this and is there any way to work around this?
ISO 639 is a standardized nomenclature used to classify languages. Each language is assigned a two-letter (639-1) and three-letter (639-2 and 639-3) lowercase abbreviation, amended in later versions of the nomenclature.
The Locale class does not impose any checks on what you feed in it, but it swaps out certain language codes for their old values. From the documentation:
ISO 639 is not a stable standard; some of the language codes it defines (specifically "iw", "ji", and "in") have changed. This constructor accepts both the old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other API on Locale will return only the OLD codes.
Here's the constructor:
public Locale(String language, String country, String variant) {
this.language = convertOldISOCodes(language);
this.country = toUpperCase(country).intern();
this.variant = variant.intern();
}
And here's the magic method:
private 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 OLD code, for backward compatibility
language = toLowerCase(language).intern();
if (language == "he") {
return "iw";
} else if (language == "yi") {
return "ji";
} else if (language == "id") {
return "in";
} else {
return language;
}
}
The objects it creates are immutable, so there's no working around this. The class is also final
, so you can't extend it and it has no specific interface to implement. One way to make it preserve those language codes would be to create a wrapper around this class and use that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With