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

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

Необходимо, чтобы я хотел сохранить некоторые специфические для локали настройки в базе данных SQL, включая сами Locales, но было бы уродливо размещать в нем сериализованные объекты Locale. Я предпочел бы хранить их представления String, которые, как представляется, достаточно адекватны.

Ответ 1

Смотрите Locale.getLanguage(), Locale.getCountry()... Сохраните эту комбинацию в базе данных вместо "programatic name"...
Когда вы хотите построить Locale назад, используйте 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);
}

Ответ 2

Метод, который возвращает языковой стандарт из строки, существует в библиотеке commons-lang: LocaleUtils.toLocale(localeAsString)

Ответ 3

Так как Java 7 существует factory метод Locale.forLanguageTag и метод экземпляра Locale.toLanguageTag, используя теги языка IETF.

Ответ 4

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

Примеры:

  • Это возвращает ms_MY.

    String key = ms-MY;
    Locale locale = new Locale.Builder().setLanguageTag(key).build();
    
  • Это вернет en_US

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

    // 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 изучить дополнительные методы.

Ответ 5

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

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) со всеми примерами, приведенными в документации Locale.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 в языке, стране и вариантах, могут продолжать делать это (хотя это сильно обескуражено), хотя поле варианта будет содержать дополнительную информацию в он, если присутствует script или расширения.

Вместо этого используйте Locale.forLanguageTag и Locale.toLanguageTag, или, если необходимо, Locale.Builder.

Ответ 7

Вариант 1:

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

Вариант 2:

Locale.forLanguageTag("en-US")

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

Ответ 8

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

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

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

Ответ 9

Вы можете использовать это на 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;
}

Ответ 10

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

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

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

en_EN
en_US

и т.д.

Ответ 11

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

В Groovy/Grails это будет:

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