web-dev-qa-db-fra.com

Comment obtenir Locale à partir de sa représentation String en Java?

Existe-t-il un moyen astucieux d’obtenir une instance Locale à partir de son "nom de programme" renvoyée par la méthode toString() de Locale? Une solution évidente et laide consisterait à analyser la chaîne, puis à créer une nouvelle instance de paramètres régionaux en fonction de cela, mais peut-être qu'il existe une meilleure solution/solution prête pour cela?

Le besoin est que je veuille stocker certains paramètres spécifiques à une locale dans une base de données SQL, y compris les locales, mais il serait déplaisant d'y placer des objets localisés sérialisés. Je préférerais stocker leurs représentations String, qui semblent être tout à fait adéquates en détail.

97
Joonas Pulakka

Voir le Locale.getLanguage(), Locale.getCountry()... Stockez cette combinaison dans la base de données à la place du "programatic name" ...
Lorsque vous souhaitez reconstituer les paramètres régionaux, utilisez public Locale(String language, String country)

Voici un exemple de 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);
}
32
raj

La méthode qui retourne les paramètres régionaux de la chaîne existe dans la bibliothèque commons-lang: LocaleUtils.toLocale(localeAsString)

119
yurilo

Depuis Java 7, il existe une méthode de fabrique Locale.forLanguageTag et méthode d'instance Locale.toLanguageTag utilisant balises de langue IETF .

56
nilskp
  1. Java fournit beaucoup de choses avec une implémentation correcte, beaucoup de complexité peut être évitée. Ceci retourne ms_MY .

    String key = "ms-MY";
    Locale locale = new Locale.Builder().setLanguageTag(key).build();
    
  2. Apache Commons a LocaleUtils pour aider à analyser une représentation de chaîne. Cela retournera en_US

    String str = "en-US";
    Locale locale =  LocaleUtils.toLocale(str);
    System.out.println(locale.toString());
    
  3. Vous pouvez également utiliser des constructeurs de paramètres régionaux.

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

Veuillez vérifier ceci LocaleUtils et ceci Locale pour explorer plus de méthodes.

28
VdeX

Option 1:

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

Option 2:

Locale.forLanguageTag("en-US")

Veuillez noter que Option 1 est un "trait de soulignement" entre la langue et le pays et Option 2 est un "tiret".

12
junjun

Cette réponse est peut-être un peu tardive, mais il s'avère que l'analyse de la chaîne n'est pas aussi laide que le supposait le PO. Je l'ai trouvé assez simple et concis:

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

J'ai testé cela (on Java 7) avec tous les exemples donnés dans la documentation de Locale.toString (): "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX" , "zh_CN_ # Hans", "zh_TW_ # Hant-x-Java" et "th_TH_TH_ # u-nu-thai".

IMPORTANT UPDATE : son utilisation est déconseillée dans Java 7+ selon le documentation =:

En particulier, les clients qui analysent la sortie de toString dans les champs language, country et variant peuvent continuer à le faire (bien que cela soit fortement déconseillé ), bien que le champ variant contiendra des informations supplémentaires si un script ou des extensions sont présents.

Utilisez Locale.forLanguageTag et Locale.toLanguageTag à la place, ou si vous devez, Locale.Builder.

12
andy

Ancienne question avec beaucoup de réponses, mais voici d'autres solutions:

8
Tauren

Si vous utilisez le framework Spring dans votre projet, vous pouvez également utiliser:

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

Documentation :

Analyser la représentation de chaîne donnée dans un paramètre régional

5
Javad Alimohammadi

Vous pouvez l'utiliser sur Android. Fonctionne bien pour moi.

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

Il ne semble pas y avoir de méthode statique valueOf pour cela, ce qui est un peu surprenant.

Une façon plutôt laide, mais simple, serait de parcourir Locale.getAvailableLocales(), en comparant leurs valeurs toString à votre valeur.

Pas très gentil, mais aucune analyse de chaîne n'est requise. Vous pouvez pré-renseigner un Map de chaînes de caractères vers des locales et rechercher votre chaîne de base de données dans cette carte.

3
skaffman

Parce que je viens de l'implémenter:

Dans Groovy/Grails ce serait:

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

Eh bien, je stockerais plutôt une concaténation de chaîne de Locale.getISO3Language(), getISO3Country() et getVariant () comme clé, ce qui me permettrait d'appeler plus tard Locale(String language, String country, String variant) constructeur.

en effet, l'utilisation de displayLanguage implique l'utilisation du langage de la locale pour l'afficher, ce qui la rend dépendante de la locale, contrairement au code de langue iso.

Par exemple, la clé en locale serait stockable de la manière suivante:

en_EN
en_US

etc ...

1
Riduidel