Tiempo para una debida actualización.
En primer lugar, la lista en desuso con la API en la que estaba en desuso:
configuration.locale
(API 17)
updateConfiguration(configuration, displaymetrics)
(API 17)
Lo que ninguna pregunta contestada recientemente ha sido correcta es el uso del nuevo método .
createConfigurationContext es el nuevo método para updateConfiguration.
Algunos lo han usado de forma independiente así:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);
... pero eso no funciona. ¿Por qué? El método devuelve un contexto, que luego se utiliza para manejar las traducciones de Strings.xml y otros recursos localizados (imágenes, diseños, lo que sea).
El uso adecuado es así:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
//the configuration can be used for other stuff as well
Context context = createConfigurationContext(overrideConfiguration);
Resources resources = context.getResources();
Si acaba de copiar y pegar eso en su IDE, puede ver una advertencia de que la API requiere que apunte a la API 17 o superior. Esto se puede solucionar poniéndolo en un método y agregando la anotación@TargetApi(17)
Pero espera. ¿Qué pasa con las API más antiguas?
Necesita crear otro método usando updateConfiguration sin la anotación TargetApi.
Resources res = YourApplication.getInstance().getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale("th");
res.updateConfiguration(conf, dm);
No necesita devolver un contexto aquí.
Ahora, gestionarlos puede ser difícil. En API 17+ necesita el contexto creado (o los recursos del contexto creado) para obtener los recursos apropiados basados en la localización. Como manejas esto?
Bueno, así es como lo hago:
/**
* Full locale list: /programming/7973023/what-is-the-list-of-supported-languages-locales-on-android
* @param lang language code (e.g. en_US)
* @return the context
* PLEASE READ: This method can be changed for usage outside an Activity. Simply add a COntext to the arguments
*/
public Context setLanguage(String lang/*, Context c*/){
Context c = AndroidLauncher.this;//remove if the context argument is passed. This is a utility line, can be removed totally by replacing calls to c with the activity (if argument Context isn't passed)
int API = Build.VERSION.SDK_INT;
if(API >= 17){
return setLanguage17(lang, c);
}else{
return setLanguageLegacy(lang, c);
}
}
/**
* Set language for API 17
* @param lang
* @param c
* @return
*/
@TargetApi(17)
public Context setLanguage17(String lang, Context c){
Configuration overrideConfiguration = c.getResources().getConfiguration();
Locale locale = new Locale(lang);
Locale.setDefault(locale);
overrideConfiguration.setLocale(locale);
//the configuration can be used for other stuff as well
Context context = createConfigurationContext(overrideConfiguration);//"local variable is redundant" if the below line is uncommented, it is needed
//Resources resources = context.getResources();//If you want to pass the resources instead of a Context, uncomment this line and put it somewhere useful
return context;
}
public Context setLanguageLegacy(String lang, Context c){
Resources res = c.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();//Utility line
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale(lang);//setLocale requires API 17+ - just like createConfigurationContext
Locale.setDefault(conf.locale);
res.updateConfiguration(conf, dm);
//Using this method you don't need to modify the Context itself. Setting it at the start of the app is enough. As you
//target both API's though, you want to return the context as you have no clue what is called. Now you can use the Context
//supplied for both things
return c;
}
Este código funciona al tener un método que realiza llamadas al método apropiado en función de qué API. Esto es algo que he hecho con muchas llamadas diferentes en desuso (incluido Html.fromHtml). Tiene un método que toma los argumentos necesarios, que luego lo divide en uno de dos (o tres o más) métodos y devuelve el resultado apropiado según el nivel de API. Es flexible ya que no tiene que verificarlo varias veces, el método de "entrada" lo hace por usted. El método de entrada aquí essetLanguage
POR FAVOR LEA ESTO ANTES DE USARLO
Debe usar el Contexto devuelto cuando obtiene recursos. ¿Por qué? He visto otras respuestas aquí que usan createConfigurationContext y no usan el contexto que devuelve. Para que funcione así, se debe llamar a updateConfiguration. Lo cual está en desuso. Use el contexto devuelto por el método para obtener recursos.
Ejemplo de uso :
Constructor o algún lugar similar:
ctx = getLanguage(lang);//lang is loaded or generated. How you get the String lang is not something this answer handles (nor will handle in the future)
Y luego, donde quieras obtener los recursos que haces:
String fromResources = ctx.getString(R.string.helloworld);
Usar cualquier otro contexto (en teoría) romperá esto.
AFAIK todavía tiene que usar un contexto de actividad para mostrar diálogos o tostadas. para eso puedes usar una instancia de una actividad (si estás afuera)
Y finalmente, use recreate()
en la actividad para actualizar el contenido. Atajo para no tener que crear una intención de actualizar.