2012-02-28 14 views
41

Así que quiero obtener el valor de una Cadena en varias configuraciones regionales, independientemente de la configuración regional actual del dispositivo/aplicación. ¿Cómo debo hacer eso?cómo obtener cadenas de diferentes configuraciones regionales en Android?

Básicamente lo que necesito es una función getString(int id, String locale) en lugar de getString(int id)

¿Cómo podría hacer eso?

Gracias

+1

¿cómo implementaron esto realmente? Por favor responda :) –

+0

como la respuesta aceptada –

+0

se supone que 'ResourceBundle' se refiere a los activos ?? o pueden acceder a nuestra carpeta res? –

Respuesta

80

NOTA Si su API mínima es de 17+, ir directamente a la parte inferior de esta respuesta. De lo contrario, siga leyendo ...

Si tiene varias carpetas res para distintos lugares, se puede hacer algo como esto:

Configuration conf = getResources().getConfiguration(); 
conf.locale = new Locale("pl"); 
DisplayMetrics metrics = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(metrics); 
Resources resources = new Resources(getAssets(), metrics, conf); 
String str = resources.getString(id); 

Alternativamente, usted puede reiniciar su actividad utilizando el método apuntado por @ jyotiprakash.

NOTA Llamar al constructor Resources de esta manera cambia algo internamente en Android. Deberá invocar al constructor con su configuración original para que las cosas vuelvan a estar como estaban.

EDITAR Una receta ligeramente diferente (y algo más limpia) para la recuperación de los recursos de un lugar específico es:

Resources res = getResources(); 
Configuration conf = res.getConfiguration(); 
Locale savedLocale = conf.locale; 
conf.locale = desiredLocale; // whatever you want here 
res.updateConfiguration(conf, null); // second arg null means don't change 

// retrieve resources from desired locale 
String str = res.getString(id); 

// restore original locale 
conf.locale = savedLocale; 
res.updateConfiguration(conf, null); 

A partir del nivel de la API 17, se debe utilizar conf.setLocale() en lugar de fijar directamente conf.locale. Esto actualizará correctamente la dirección del diseño de la configuración si está cambiando entre las configuraciones regionales de derecha a izquierda y de izquierda a derecha. (Dirección Layout se introdujo en 17.)

No hay ningún punto en la creación de un nuevo Configuration objeto (como @Nulano sugiere en un comentario) porque llamando updateConfiguration va a cambiar la configuración original obtenida llamando res.getConfiguration().

No me gustaría incluir esto en un método getString(int id, String locale) si va a cargar varios recursos de cadena para una configuración regional. Cambiar las configuraciones regionales (usando cualquiera de las recetas) requiere que el marco haga mucho trabajo para volver a enlazar todos los recursos. Es mucho mejor actualizar las configuraciones regionales una vez, recuperar todo lo que necesita y luego restablecer la configuración regional.

EDITAR (Gracias a @Mygod):

Si su nivel de API mínima es de 17+, hay un enfoque mucho mejor, como se muestra en this answer en otro hilo. Por ejemplo, puede crear múltiples Resource objetos, uno para cada lugar que necesita, con:

@NonNull Resources getLocalizedResources(Context context, Locale desiredLocale) { 
    Configuration conf = context.getResources().getConfiguration(); 
    conf = new Configuration(conf); 
    conf.setLocale(desiredLocale); 
    Context localizedContext = context.createConfigurationContext(conf); 
    return localizedContext.getResources(); 
} 

A continuación, sólo recuperar los recursos que le gusten de la Resource objeto localizado devuelto por este método. No es necesario restablecer nada una vez que haya recuperado los recursos.

+1

¿No debería hacer una nueva configuración a partir de la que devuelve 'getResources(). GetConfiguration()'? De acuerdo con GrepCode, devuelve una instancia local almacenada dentro de los Recursos. Cambiar el campo de configuración regional después es probablemente la verdadera razón por la que Android está confundido. Probablemente debería hacer 'conf = new Configuration (conf);' (para clonar la configuración devuelta) entre la primera y la segunda línea. – Nulano

+0

@Nulano - Vale la pena intentarlo, pero no creo que esa sea la fuente de por qué Android está "confundido" (como usted dice). Mire la fuente del constructor 'Resources' y verá que la creación de un nuevo objeto' Resources' como este cambia profundamente las cosas en los activos del proceso (aparentemente un singleton). Una vez que me di cuenta de que las cosas tendrían que reiniciarse, no me molesté en buscar exactamente por qué. Un enfoque alternativo (quizás más limpio) para construir un nuevo objeto 'Resources' es llamar a' resources.updateConfiguration (conf, null) 'después de cambiar las configuraciones regionales. –

+0

@TedHopp: Hola, señor, eche un vistazo a mi [pregunta] (http://stackoverflow.com/q/40398528). Realmente apreciaría si pudieras ayudar. Gracias ... :) –

-9

Lo que estamos buscando se llama la clase ResourceBundle. Aquí está el enlace:

Google Docs for ResourceBundle

+6

-1, sin explicación –

+0

Esta respuesta no tiene sentido porque mezcla manzanas y naranjas. Cuando coloca una cadena en 'res/values ​​/ strings.xml' como sugiere esta respuesta, el valor es ** no ** al que se accede mediante un' ResourceBundle'. En cambio, se accede a través de un objeto 'Recursos' específico de Android obtenido de un' Contexto'. 'ResourceBundle' es irrelevante para esta operación. Además, el campo 'R.string.my_message' es un valor' int', y el método 'ResourceBundle.getString()' toma un argumento 'String', por lo que el ejemplo de código es engañoso en el mejor de los casos. Finalmente, no hay ningún rol para un 'Locale' en esta respuesta (la cuestión central). –

+0

@TedHopp - tienes razón, fue un pedo cerebral. Se eliminó la información conflictiva. – BitBank

8

Aquí hay una versión combinada de los enfoques descritos por Ted Hopp. De esta manera, el código funciona para cualquier versión de Android: ejemplo

public static String getLocaleStringResource(Locale requestedLocale, int resourceId, Context context) { 
    String result; 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // use latest api 
     Configuration config = new Configuration(context.getResources().getConfiguration()); 
     config.setLocale(requestedLocale); 
     result = context.createConfigurationContext(config).getText(resourceId).toString(); 
    } 
    else { // support older android versions 
     Resources resources = context.getResources(); 
     Configuration conf = resources.getConfiguration(); 
     Locale savedLocale = conf.locale; 
     conf.locale = requestedLocale; 
     resources.updateConfiguration(conf, null); 

     // retrieve resources from desired locale 
     result = resources.getString(resourceId); 

     // restore original locale 
     conf.locale = savedLocale; 
     resources.updateConfiguration(conf, null); 
    } 

    return result; 
} 

Uso:

String englishName = getLocaleStringResource(new Locale("en"), id, R.string.name); 

Nota

Como ya se indicó en la respuesta original, que podría ser más eficiente para reemplazar llamada múltiple del código anterior con un solo cambio de configuración y múltiples llamadas a resources.getString().

Cuestiones relacionadas