Как получить Locale из его строкового представления в Java?

есть ли аккуратный способ получить язык экземпляр из его "программного имени", возвращаемогоtoString() способ? Очевидным и уродливым решением будет разбор строки, а затем построение нового экземпляра Locale в соответствии с этим, но, возможно, есть лучший способ / готовое решение для этого?

необходимость в том, что я хочу сохранить некоторые параметры локали в базе данных SQL, включая сами локали, но было бы некрасиво помещать сериализованные Объекты локали там. Я бы предпочел сохранить их строковые представления, которые кажутся вполне адекватными в деталях.

12 ответов


посмотреть Locale.getLanguage(), Locale.getCountry()... Сохраните эту комбинацию в базе данных вместо "programatic name"...
Если вы хотите построить Локаль обратно, используйте public Locale(String language, String country)

вот пример кода :)

// 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);
}

метод, возвращающий локаль из строки, существует в библиотеке commons-lang: LocaleUtils.toLocale(localeAsString)


С Java 7 есть заводской метод Locale.forLanguageTag и метод экземпляра Locale.toLanguageTag С помощью языковые теги IETF.


Java предоставляет много вещей с правильной реализацией много сложности можно избежать:

примеры:

  1. возвращает ms_MY.

    String key = ms-MY;
    Locale locale = new Locale.Builder().setLanguageTag(key).build();
    
  2. вернет язык

    String str = "en-US";
    Locale locale =  LocaleUtils.toLocale(str);
    System.out.println(locale.toString());
    
  3. вы также можете использовать конструкторы язык.

    // 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)
    

пожалуйста, проверьте это LocaleUtils и Locale to узнать больше методов.


этот ответ может быть немного запоздалым, но оказывается, что разбор строки не так уродлив, как предполагал ОП. Я нашел его довольно простым и лаконичным:

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]);
}

я протестировал это (на Java 7) со всеми примерами, приведенными в локали.документация по toString (): "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "zh_CN_#Hans", "zh_TW_#Hant-x-java"и" th_TH_TH_#u-nu-thai".

ВАЖНОЕ ОБНОВЛЕНИЕ: это не рекомендуется для использования в Java 7+ по к документация:

в частности, клиенты, которые анализируют вывод toString в поля языка, страны и варианта, могут продолжать делать это (хотя это приветствуется), хотя поле variant будет иметь дополнительную информацию в нем, если присутствует скрипт или расширения.

Использовать Языковой Стандарт.forLanguageTag и Locale.вместо этого toLanguageTag или, если необходимо, Locale.Строитель.


Вариант 1 :

org.apache.commons.lang3.LocaleUtils.toLocale("en_US")

Вариант 2 :

Locale.forLanguageTag("en-US")

обратите внимание 1 "подчеркивание" между языком и страной, и 2 "дефис".


старый вопрос с большим количеством ответов, но вот еще решения:


кажется, нет статического valueOf способ для этого, что немного удивительно.

один довольно уродливый, но простой способ-перебрать Locale.getAvailableLocales(), сравнивая их toString значения со значением.

не очень хорошо, но не требуется синтаксический анализ строк. Вы можете предварительно заполнить Map строк в локали и найдите строку базы данных на этой карте.


вы можете использовать это на Android. Мне подходит.

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;
}

Ну, я бы сохранил вместо этого конкатенацию строк Locale.getISO3Language(), getISO3Country() и getVariant () в качестве ключа, который позволит мне последний вызов Locale(String language, String country, String variant) конструктор.

действительно, опора displayLanguage подразумевает использование языка locale для его отображения, что делает его зависимым от языка, в отличие от кода языка iso.

в качестве примера ключ локали en будет храниться как

en_EN
en_US

и так далее ...


потому что я только что реализовал его:

на Groovy/Grails что будет:

def locale = Locale.getAvailableLocales().find { availableLocale ->
      return availableLocale.toString().equals(searchedLocale)
}

Если вы используете Spring framework в своем проекте, вы также можете использовать:

org.springframework.util.StringUtils.parseLocaleString("en_US");

документация:

проанализируйте данное строковое представление в Locale