How to get Locale from its String representation in Java?
JavaLocaleJava Problem Overview
Is there a neat way of getting a Locale instance from its "programmatic name" as returned by Locale's toString()
method? An obvious and ugly solution would be parsing the String and then constructing a new Locale instance according to that, but maybe there's a better way / ready solution for that?
The need is that I want to store some locale specific settings in a SQL database, including Locales themselves, but it would be ugly to put serialized Locale objects there. I would rather store their String representations, which seem to be quite adequate in detail.
Java Solutions
Solution 1 - Java
Method that returns locale from string exists in commons-lang library:
LocaleUtils.toLocale(localeAsString)
Solution 2 - Java
Since Java 7 there is factory method Locale.forLanguageTag
and instance method Locale.toLanguageTag
using IETF language tags.
Solution 3 - Java
-
Java provides lot of things with proper implementation lot of complexity can be avoided. This returns ms_MY.
String key = "ms-MY"; Locale locale = new Locale.Builder().setLanguageTag(key).build();
-
Apache Commons has
LocaleUtils
to help parse a string representation. This will return en_USString str = "en-US"; Locale locale = LocaleUtils.toLocale(str); System.out.println(locale.toString());
-
You can also use locale constructors.
// Construct a locale from a language code.(eg: en) new Locale(String language) // Construct a locale from language and country.(eg: en and US) new Locale(String language, String country) // Construct a locale from language, country and variant. new Locale(String language, String country, String variant)
Please check this LocaleUtils and this Locale to explore more methods.
Solution 4 - Java
See the Locale.getLanguage()
, Locale.getCountry()
... Store this combination in the database instead of the "programatic name"
...
When you want to build the Locale back, use public Locale(String language, String country)
Here is a sample code :)
// May contain simple syntax error, I don't have java right now to test..
// but this is a bigger picture for your algo...
public String localeToString(Locale l) {
return l.getLanguage() + "," + l.getCountry();
}
public Locale stringToLocale(String s) {
StringTokenizer tempStringTokenizer = new StringTokenizer(s,",");
if(tempStringTokenizer.hasMoreTokens())
String l = tempStringTokenizer.nextElement();
if(tempStringTokenizer.hasMoreTokens())
String c = tempStringTokenizer.nextElement();
return new Locale(l,c);
}
Solution 5 - Java
Option 1 :
org.apache.commons.lang3.LocaleUtils.toLocale("en_US")
Option 2 :
Locale.forLanguageTag("en-US")
Please note Option 1 is "underscore" between language and country , and Option 2 is "dash".
Solution 6 - Java
If you are using Spring framework in your project you can also use:
org.springframework.util.StringUtils.parseLocaleString("en_US");
> Parse the given String representation into a Locale
Solution 7 - Java
This answer may be a little late, but it turns out that parsing out the string is not as ugly as the OP assumed. I found it quite simple and concise:
public static Locale fromString(String locale) {
String parts[] = locale.split("_", -1);
if (parts.length == 1) return new Locale(parts[0]);
else if (parts.length == 2
|| (parts.length == 3 && parts[2].startsWith("#")))
return new Locale(parts[0], parts[1]);
else return new Locale(parts[0], parts[1], parts[2]);
}
I tested this (on Java 7) with all the examples given in the Locale.toString() documentation: "en", "de_DE", "GB", "en_US_WIN", "de__POSIX", "zh_CN#Hans", "zh_TW_#Hant-x-java", and "th_TH_TH_#u-nu-thai".
IMPORTANT UPDATE: This is not recommended for use in Java 7+ according to the documentation:
>In particular, clients who parse the output of toString into language, country, and variant fields can continue to do so (although this is strongly discouraged), although the variant field will have additional information in it if script or extensions are present.
Use Locale.forLanguageTag and Locale.toLanguageTag instead, or if you must, Locale.Builder.
Solution 8 - Java
Old question with plenty of answers, but here's more solutions:
Solution 9 - Java
There doesn't seem to be a static valueOf
method for this, which is a bit surprising.
One rather ugly, but simple, way, would be to iterate over Locale.getAvailableLocales()
, comparing their toString
values with your value.
Not very nice, but no string parsing required. You could pre-populate a Map
of Strings to Locales, and look up your database string in that Map.
Solution 10 - Java
You can use this on Android. Works fine for me.
private static final Pattern localeMatcher = Pattern.compile
("^([^_]*)(_([^_]*)(_#(.*))?)?$");
public static Locale parseLocale(String value) {
Matcher matcher = localeMatcher.matcher(value.replace('-', '_'));
return matcher.find()
? TextUtils.isEmpty(matcher.group(5))
? TextUtils.isEmpty(matcher.group(3))
? TextUtils.isEmpty(matcher.group(1))
? null
: new Locale(matcher.group(1))
: new Locale(matcher.group(1), matcher.group(3))
: new Locale(matcher.group(1), matcher.group(3),
matcher.group(5))
: null;
}
Solution 11 - Java
Well, I would store instead a string concatenation of Locale.getISO3Language()
, getISO3Country()
and Locale(String language, String country, String variant)
constructor.
indeed, relying of displayLanguage implies using the langage of locale to display it, which make it locale dependant, contrary to iso language code.
As an example, en locale key would be storable as
en_EN
en_US
and so on ...
Solution 12 - Java
Because I have just implemented it:
In Groovy
/Grails
it would be:
def locale = Locale.getAvailableLocales().find { availableLocale ->
return availableLocale.toString().equals(searchedLocale)
}