I am trying to get all the locales from the JVM to populate a Country drop down. The first item is an empty not null object. It isn't null because I am using a TreeMap Collection to add the country Abbreviations and (Displayable) Names. Look below to see what the collection is.
{=, AE=United Arab Emirates, AL=Albania, AR=Argentina, AT=Austria, AU=Australia, BA=Bosnia and Herzegovina, BE=Belgium, BG=Bulgaria, BH=Bahrain, BO=Bolivia, BR=Brazil,....
Here's the code. I remove that empty object to make sure the first value is not empty.
public Map<String, String> countries(Locale currentLocale) {
Map<String, String> countries = new TreeMap<String, String>();
for (Locale locale : Locale.getAvailableLocales()) {
countries.put(locale.getCountry(),
locale.getDisplayCountry(currentLocale));
}
countries.remove("");
return countries;
}
JVM version - (build 1.7.0_09-b05)
The javadocs basically cover this.
For locale.getCountry()
you find:
Returns the country/region code for this locale, which should either be the empty string, an uppercase ISO 3166 2-letter code, or a UN M.49 3-digit code.
And for locale.getDisplayCountry()
you find:
Returns a name for the locale's country that is appropriate for display to the user. If possible, the name returned will be localized for the default locale. For example, if the locale is fr_FR and the default locale is en_US, getDisplayCountry() will return "France"; if the locale is en_US and the default locale is fr_FR, getDisplayCountry() will return "Etats-Unis". If the name returned cannot be localized for the default locale, (say, we don't have a Japanese name for Croatia), this function falls back on the English name, and uses the ISO code as a last-resort value. If the locale doesn't specify a country, this function returns the empty string.
The one you can't "see" doesn't have an ISO code and is falling back to that because it can't be localized to your locale and doesn't have an english name either (or, doesn't have a country specified). It is perfectly valid for you to wind up with empty strings for both (though, fairly useless).
The locale in question is none other than Locale.ROOT. locale == Locale.ROOT
on my end, and I assume that the same will be true for you.
Why does Locale.ROOT
exist? According to http://www.oracle.com/technetwork/java/javase/java8locales-2095355.html:
The default “JRE” locale provider’s resources for the Locale.ROOT locale are used if none of the specified locale providers support the requested locale. For example, if only “CLDR” is specified in “java.locale.providers” system property, Collator works as if requested for the ROOT locale because “CLDR” locale provider does not provide Collator locale data. Specifying “CLDR,JRE” supplements the “JRE” locale provider’s Collator functionality, as well as preferring “CLDR” locale provider’s other locale data to “JRE”’s ones.
try
for (Locale locale : Locale.getAvailableLocales()) {
System.out.println(locale.getLanguage() + " " + locale.getCountry());
}
you will see that some Locales have only language and no country
ms MY
ar QA
is IS
fi FI
pl
en MT
...