2010-03-26 9 views
78

Esiste un modo semplice per ottenere un'istanza Locale dal suo "nome programmatico" come restituito dal metodo Locale toString()? Una soluzione ovvia e brutta dovrebbe essere l'analisi della stringa e quindi la costruzione di una nuova istanza di Locale in base a quello, ma forse c'è un modo migliore/soluzione pronta per questo?Come ottenere le impostazioni locali dalla rappresentazione delle stringhe in Java?

L'esigenza è che voglio memorizzare alcune impostazioni locali specifiche in un database SQL, incluse le Locales stesse, ma sarebbe brutto mettere lì gli oggetti locali serializzati. Preferirei archiviare le loro rappresentazioni di stringa, che sembrano essere abbastanza adeguate nei dettagli.

risposta

29

Vedere il Locale.getLanguage(), Locale.getCountry() ... Negozio questa combinazione nel database invece del "programatic name" ...
Quando si vuole costruire l'Locale schiena, utilizzare public Locale(String language, String country)

Questo vuole essere un esempio di codice :)

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

Ottimo pensiero, grazie! –

+2

Questo non sarebbe nemmeno compilato. – Adrian

+1

@raj perché usare il tokenizzatore, se Java ti offre metodi pronti? ad esempio toLocale (String str). Vedere esempi nella risposta – VedX

3

Non sembra esserci un metodo statico valueOf per questo, che è un po 'sorprendente.

Un modo piuttosto brutto, ma semplice, sarebbe quello di iterare su Locale.getAvailableLocales(), confrontando i valori toString con il valore.

Non molto bello, ma non richiede l'analisi delle stringhe. È possibile pre-compilare uno Map di Strings su Local e cercare la stringa del database in quella Mappa.

+0

Ah, l'iterazione potrebbe essere una soluzione abbastanza ragionevole. In effetti è sorprendente che Locale non abbia un metodo statico per questo. –

+0

Le istanze 'Locale' predeterminate rappresentano un sottoinsieme molto piccolo di sole localizzazioni valide. Non è affatto completo. – BetaRide

1

Beh, vorrei conservare invece una concatenazione di stringhe di Locale.getISO3Language(), getISO3Country() e getVariant() come la chiave, che mi permetterebbe di quest'ultima chiamata Locale(String language, String country, String variant) costruttore.

infatti, l'utilizzo di displayLanguage implica l'uso del linguaggio locale per visualizzarlo, il che lo rende dipendente dalle impostazioni internazionali, in contrasto con il codice della lingua iso.

A titolo di esempio, en chiave locale sarebbe immagazzinabile come

en_EN 
en_US 

e così via ...

103

metodo che restituisce locale da stringa esiste in commons-lang libreria: LocaleUtils.toLocale(localeAsString)

+2

LocaleUtils.toLocale non supporta stringhe come 'zh-Hans', 'pt-PT', ecc. –

+7

Se si dispone di un trattino '-' tra le parti locali che si trovano con un tag IETF BCP 47, se si utilizza Java 7 è possibile utilizzare' Locale.forLanguageTag'. –

1

perché ho appena messo in atto:

In Groovy/Grails sarebbe:

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

Dal Java 7 c'è il metodo di fabbrica Locale.forLanguageTag e il metodo di istanza Locale.toLanguageTag utilizzando IETF language tags.

12

Questa risposta potrebbe essere un po 'in ritardo, ma si scopre che l'analisi della stringa non è così brutta come presupponeva l'OP. L'ho trovato abbastanza semplice e concisa:

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

Ho provato questo (su Java 7) con tutti gli esempi riportati nella Locale.toString() documentazione: "en", "de_DE", "_GB", " en_US_WIN "," de__POSIX "," zh_CN_ # Hans "," zh_TW_ # Hant-x-java "e" th_TH_TH_ # u-nu-thai ".

AGGIORNAMENTO IMPORTANTE: Questo non è raccomandato per l'uso in Java 7+ secondo le documentation:

In particolare, i clienti che analizzano l'output di toString nella lingua, paese, e campi variante può continuare per farlo (sebbene questo sia fortemente sconsigliato), anche se il campo della variante avrà informazioni aggiuntive in esso se lo script o le estensioni sono presenti.

Utilizzare Locale.forLanguageTag e Locale.toLanguageTag invece o, se necessario, Locale.Builder.

+4

Java 7 'Locale.forLanguageTag' si applica solo per tag di linguaggio codificati come indicato nel BCP 47 di IETF, con un trattino (' -'), non un carattere di sottolineatura ('_') come nel ritorno di' Locale' su 'toString 'metodo –

+0

Hai ragione. È ancora necessario un modo per convertire le rappresentazioni locali esistenti nel formato BCP47. La mia intenzione era quella di suggerire che andando avanti, 'Locale's non dovrebbe essere memorizzato nel loro formato' toString', ma nel loro modulo 'toLanguageTag', che è riconvertibile in un' Locale' in modo più semplice e accurato. – andy

+0

Questo metodo non ha un numero di casi limite che potrebbero causare l'indice fuori limite? – user2524908

3

È possibile utilizzare questo su Android. Funziona bene per 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; 
} 
21

Java fornisce sacco di cose con una corretta applicazione sacco di complessità possono essere evitati:

Esempi:

  1. Ciò restituisce ms_MY.

    String key = ms-MY; 
    Locale locale = new Locale.Builder().setLanguageTag(key).build(); 
    
  2. Ciò restituirà it_IT

    String str = "en-US"; 
    Locale locale = LocaleUtils.toLocale(str); 
    System.out.println(locale.toString()); 
    
  3. È inoltre possibile utilizzare costruttori di 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) 
    

prega di consultare questo LocaleUtils e questo Locale per esplorare più metodi.

+1

LocaleUtils.toLocale (localeStringRepresentation) esegue correttamente il lavoro. Anche se vedi l'implementazione di questo metodo, è abbastanza completo! – Dish

6

Opzione 1:

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

Opzione 2:

Locale.forLanguageTag("en-US") 

Si prega di notare Opzione 1 è "underscore" tra la lingua e il paese, e opzione 2 è " trattino".

Problemi correlati