2010-03-26 11 views
78

¿Existe una manera ordenada de obtener una instancia Locale de su "nombre de programa" como la devuelve el método toString() de Locale? Una solución obvia y fea sería analizar el String y luego construir una nueva instancia de Locale de acuerdo con eso, pero tal vez hay una mejor solución de manera/listo para eso.¿Cómo obtener Locale desde su representación de Cadena en Java?

La necesidad es que quiero almacenar algunos ajustes específicos de configuración regional en una base de datos SQL, incluidos los Locales mismos, pero sería feo poner allí los objetos Locale serializados. Prefiero almacenar sus representaciones de String, que parecen ser bastante adecuadas en detalle.

Respuesta

29

Véase el Locale.getLanguage(), Locale.getCountry() ... Almacenar esta combinación en la base de datos en lugar de la "programatic name" ...
cuando se quiere construir el Locale atrás, use public Locale(String language, String country)

que aquí hay una muestra de código :)

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

¡Muy bien pensado, gracias! –

+2

Esto ni siquiera compilaría. – Adrian

+1

@raj por qué usar tokenizer, si Java le da los métodos listos? por ejemplo, toLocale (String str). Consulte ejemplos en la respuesta – VedX

3

No parece haber un método estático valueOf para esto, lo cual es un poco sorprendente.

Una manera bastante fea, pero simple, sería iterar sobre Locale.getAvailableLocales(), comparando sus valores toString con su valor.

No muy agradable, pero no se requiere el análisis de cadenas. Puede rellenar previamente un Map de Strings to Locales y buscar la cadena de su base de datos en ese mapa.

+0

Ah, la iteración podría ser una solución bastante razonable. De hecho, es sorprendente que Locale no tenga un método estático para esto. –

+0

Las instancias 'Locale' predefinidas representan un subconjunto muy pequeño de configuraciones regionales válidas solamente. De ninguna manera está completo. – BetaRide

1

Bueno, me gustaría almacenar en su lugar una concatenación de cadenas de Locale.getISO3Language(), getISO3Country() y getVariant() como la clave, lo que me permitiría a esta última llamada Locale(String language, String country, String variant) constructor.

de hecho, depender de displayLanguage implica utilizar el idioma de la configuración regional para mostrarlo, lo que hace que dependa de la configuración regional, a diferencia del código de idioma ISO.

A modo de ejemplo, en clave local sería almacenable como

en_EN 
en_US 

y así sucesivamente ...

7

pregunta de siempre con un montón de respuestas, pero aquí hay más soluciones:

biblioteca
+0

El ejemplo de java2s es bastante bueno y también incluye la administración de la variante –

+0

La primera URL es todo lo que quería .. Gracias –

103

Método que devuelve la configuración regional de la cadena existe en commons-lang: LocaleUtils.toLocale(localeAsString)

+2

LocaleUtils.toLocale no admite cadenas como 'zh-Hans', 'pt-PT', etc. –

+7

Si tiene un guión '-' entre partes locales, está tratando con una etiqueta IETF BCP 47, si está utilizando Java 7 puede usar' Locale.forLanguageTag' –

1

Porque acabo lo han implantado:

En Groovy/Grails sería:

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

Desde Java 7 existe el método de fábrica Locale.forLanguageTag y el método de instancia Locale.toLanguageTag usando IETF language tags.

12

Esta respuesta puede ser un poco tarde, pero resulta que analizar el string no es tan feo como el OP asumió. Me pareció bastante simple y 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]); 
} 

He probado esto (en Java 7) con todos los ejemplos dados en la Locale.toString() Documentación: "en", "es_ES", "_GB", " en_US_WIN "," de__POSIX "," zh_CN_ # Hans "," zh_TW_ # Hant-x-java "y" th_TH_TH_ # u-nu-thai ".

ACTUALIZACIÓN IMPORTANTE: Esto no está recomendado para uso en Java 7+ acuerdo con las documentation:

En particular, los clientes que analizar la salida de toString en idioma y el país, y los campos variantes puede continuar para hacerlo (aunque esto es fuertemente desaconsejado), aunque el campo de variante tendrá información adicional si el script o las extensiones están presentes.

Use Locale.forLanguageTag y Locale.toLanguageTag en su lugar, o si debe, Locale.Builder.

+4

Java 7 'Locale.forLanguageTag' se aplica solo a las etiquetas de idioma codificadas como se indica en BCP 47 de IETF, con un guión (' -'), no un guión bajo ('_') como en el retorno de' Locale''s 'toString 'método –

+0

Tienes razón. Todavía debe haber alguna forma de convertir las representaciones Locale existentes al formato BCP47. Mi intención era sugerir que, en adelante, 'Locale's no debería almacenarse en su forma' toString', sino en su forma 'toLanguageTag', que es convertible de nuevo a 'Locale' con mayor facilidad y precisión. – andy

+0

¿Este método no tiene una serie de casos extremos que podrían causar que el índice se salga de los límites? – user2524908

3

Puede usar esto en Android. Funciona bien para mí

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 proporciona muchas cosas con mucha aplicación adecuada de complejidad se pueden evitar:

Ejemplos:

  1. Esto devuelve ms_MY.

    String key = ms-MY; 
    Locale locale = new Locale.Builder().setLanguageTag(key).build(); 
    
  2. Esto devolverá en_US

    String str = "en-US"; 
    Locale locale = LocaleUtils.toLocale(str); 
    System.out.println(locale.toString()); 
    
  3. También puede utilizar constructores de localización.

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

Selecciona esta LocaleUtils y esto Locale para explorar más métodos.

+1

LocaleUtils.toLocale (localeStringRepresentation) hace el trabajo ordenadamente. ¡También si ves la implementación de este método, es bastante completo! – Dish

6

Opción 1:

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

Opción 2:

Locale.forLanguageTag("en-US") 

Atención: Opción 1 es "subrayado" entre el idioma y el país, y Opción 2 es " guión".

Cuestiones relacionadas