2010-03-26 5 views
78

Existe-t-il une manière intéressante d'obtenir une instance Locale à partir de son "nom de programme" renvoyé par la méthode toString() de Locale? Une solution évidente et moche serait l'analyse de la chaîne, puis la construction d'une nouvelle instance Locale en fonction de cela, mais peut-être qu'il existe une meilleure solution pour cela? Le besoin est que je veux stocker certains paramètres régionaux dans une base de données SQL, y compris les Locales eux-mêmes, mais il serait moche de mettre des objets Locale sérialisés là. Je préfère stocker leurs représentations de cordes, qui semblent être assez adéquates dans le détail.Comment obtenir Locale à partir de sa représentation de chaîne en Java?

Répondre

29

Voir la Locale.getLanguage(), Locale.getCountry() ... Stocker cette combinaison dans la base de données au lieu du "programatic name" ...
Lorsque vous voulez reconstruire une version localisée, 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); 
} 
+0

Très bonne réflexion, merci! –

+2

Cela ne compilerait même pas. – Adrian

+1

@raj pourquoi utiliser tokenizer, Si Java vous donne des méthodes prêtes? par exemple toLocale (String str). S'il vous plaît voir des exemples dans la réponse – VedX

3

Il ne semble pas y avoir de méthode statique valueOf pour cela, ce qui est un peu surprenant. Un moyen plutôt moche, mais simple, serait de parcourir Locale.getAvailableLocales(), en comparant leurs valeurs toString avec votre valeur.

Pas très sympa, mais pas d'analyse de chaîne requise. Vous pouvez pré-remplir un Map de chaînes de caractères vers des paramètres régionaux et rechercher votre chaîne de base de données dans cette carte.

+0

Ah, l'itération pourrait être une solution assez raisonnable. En effet, il est surprenant que Locale n'ait pas de méthode statique pour cela. –

+0

Les instances 'Locale' prédisposées représentent un très petit sous-ensemble de paramètres régionaux valides uniquement. Ce n'est en aucun cas complet. – BetaRide

1

Eh bien, je stocker plutôt une concaténation de chaîne de Locale.getISO3Language(), getISO3Country() et getVariant() comme la clé, ce qui me permettrait de ce dernier appel Locale(String language, String country, String variant) constructeur. En effet, s'appuyer sur displayLanguage implique d'utiliser le langage des paramètres régionaux pour l'afficher, ce qui le rend dépendant des paramètres régionaux, contrairement au code de langage iso.

À titre d'exemple, en clé locale serait stockable comme

en_EN 
en_US 

et ainsi de suite ...

7

question ancienne avec beaucoup de réponses, mais voici plus de solutions:

+0

L'exemple de java2s est assez bon et comprend également la variante de manipulation –

+0

La première URL est tout ce que je voulais .. Merci –

103

méthode qui retourne locale de la chaîne existe dans la bibliothèque commons-lang: LocaleUtils.toLocale(localeAsString)

+2

LocaleUtils.toLocale ne supporte pas les chaînes comme 'zh-Hans', 'pt-PT', etc. –

+7

Si vous avez un tiret '-' entre les parties locales, vous avez affaire à une balise IETF BCP 47, si vous utilisez Java 7, vous pouvez utiliser' Locale.forLanguageTag' –

1

Parce que je viens implémenté:

Dans Groovy/Grails il serait:

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

Depuis Java 7 il y a la méthode d'usine Locale.forLanguageTag et la méthode d'instance Locale.toLanguageTag en utilisant IETF language tags.

12

Cette réponse peut être un peu en retard, mais il s'avère que l'analyse de la chaîne n'est pas aussi laide que l'OP supposait. 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é ce (sur Java 7) avec tous les exemples donnés dans la documentation Locale.toString(): "en", "de_DE", "_FR", " en_US_WIN "," de__POSIX "," zh_CN_ # Hans "," zh_TW_ # Hant-x-java "et" th_TH_TH_ # u-nu-thai ".

MISE À JOUR IMPORTANTE: Ce n'est pas recommandé pour une utilisation en Java 7+ selon les documentation:

En particulier, les clients qui analysent la sortie de toString dans la langue, le pays et les champs de variantes peut continuer pour ce faire (bien que ce soit fortement déconseillé), bien que le champ variant contienne des informations supplémentaires si le script ou les extensions sont présents.

Utilisez plutôt Locale.forLanguageTag et Locale.toLanguageTag, ou si vous le souhaitez, Locale.Builder.

+4

Java 7 'Locale.forLanguageTag' ne s'applique qu'aux balises de langage codées comme indiqué dans le BCP 47 de l'IETF, avec un trait d'union (' -'), pas un trait de soulignement ('_') comme dans le retour de' Locale' 'toString 'méthode –

+0

Vous avez raison. Il doit encore y avoir un moyen de convertir les représentations Locale existantes au format BCP47. Mon intention était de suggérer qu'à l'avenir, 'Locale's ne devrait pas être stocké dans leur formulaire' toString', mais dans leur forme 'toLanguageTag', qui est convertible en' Locale' plus facilement et plus précisément. – andy

+0

Cette méthode ne possède-t-elle pas un certain nombre de cas de bords qui pourraient causer un dépassement d'index? – user2524908

3

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

Java fournit beaucoup de choses avec beaucoup de bonne mise en œuvre de la complexité peut être évité:

Exemples:

  1. Ce retourne ms_MY.

    String key = ms-MY; 
    Locale locale = new Locale.Builder().setLanguageTag(key).build(); 
    
  2. Cela renverra en_US

    String str = "en-US"; 
    Locale locale = LocaleUtils.toLocale(str); 
    System.out.println(locale.toString()); 
    
  3. Vous pouvez également utiliser les constructeurs 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) 
    

S'il vous plaît vérifier ce LocaleUtils et ce Locale d'explorer plusieurs méthodes.

+1

LocaleUtils.toLocale (localeStringRepresentation) effectue le travail proprement. Aussi, si vous voyez la mise en œuvre de cette méthode, c'est assez complet! – Dish

6

Option 1:

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

Option 2:

Locale.forLanguageTag("en-US") 

S'il vous plaît noter Option 1 est "underscore" entre la langue et le pays, et Option 2 est " tiret".

Questions connexes