Temps pour une mise à jour due.
Tout d'abord, la liste déconseillée avec l'API dans laquelle elle a été déconseillée:
configuration.locale
(API 17)
updateConfiguration(configuration, displaymetrics)
(API 17)
La chose à laquelle aucune question n'a été répondue récemment est devenue correcte, c'est l'utilisation de la nouvelle méthode .
createConfigurationContext est la nouvelle méthode pour updateConfiguration.
Certains l'ont utilisé de manière autonome comme ceci:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);
... mais ça ne marche pas. Pourquoi? La méthode renvoie un contexte, qui est ensuite utilisé pour gérer les traductions Strings.xml et d'autres ressources localisées (images, mises en page, etc.).
L'utilisation appropriée est comme ceci:
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 vous venez de copier-coller cela dans votre IDE, vous pouvez voir un avertissement que l'API vous oblige à cibler l'API 17 ou supérieure. Cela peut être contourné en le mettant dans une méthode et en ajoutant l'annotation@TargetApi(17)
Mais attendez. Qu'en est-il des anciennes API?
Vous devez créer une autre méthode à l'aide de updateConfiguration sans l'annotation 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);
Vous n'avez pas besoin de renvoyer un contexte ici.
Maintenant, leur gestion peut être difficile. Dans l'API 17+, vous avez besoin du contexte créé (ou des ressources du contexte créé) pour obtenir les ressources appropriées en fonction de la localisation. Comment gérez-vous cela?
Eh bien, c'est comme ça que je le fais:
/**
* 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;
}
Ce code fonctionne en ayant une méthode qui appelle la méthode appropriée en fonction de quelle API. C'est quelque chose que j'ai fait avec beaucoup d'appels obsolètes différents (y compris Html.fromHtml). Vous avez une méthode qui prend les arguments nécessaires, qui la divise ensuite en l'une des deux (ou trois ou plus) méthodes et renvoie le résultat approprié en fonction du niveau de l'API. Il est flexible car vous n'avez pas à vérifier plusieurs fois, la méthode "entrée" le fait pour vous. La méthode d'entrée ici estsetLanguage
VEUILLEZ LIRE CECI AVANT DE L'UTILISER
Vous devez utiliser le contexte renvoyé lorsque vous obtenez des ressources. Pourquoi? J'ai vu d'autres réponses ici qui utilisent createConfigurationContext et n'utilisent pas le contexte qu'il renvoie. Pour que cela fonctionne comme ça, updateConfiguration doit être appelé. Ce qui est obsolète. Utilisez le contexte renvoyé par la méthode pour obtenir des ressources.
Exemple d'utilisation :
Constructeur ou quelque part similaire:
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)
Et puis, partout où vous voulez obtenir des ressources, vous le faites:
String fromResources = ctx.getString(R.string.helloworld);
L'utilisation de tout autre contexte rompra (en théorie) cela.
AFAIK, vous devez toujours utiliser un contexte d'activité pour afficher les boîtes de dialogue ou les toasts. pour cela vous pouvez utiliser une instance d'une activité (si vous êtes à l'extérieur)
Et enfin, utilisez recreate()
l'activité pour actualiser le contenu. Raccourci pour ne pas avoir à créer une intention de rafraîchissement.