web-dev-qa-db-fra.com

Comment changer la langue de l'application Android O/Oreo/api 26

Je veux changer la langue de l'application et cela fonctionne bien jusqu'à l'API 26.

Pour api> 25, je mets Locale.setDefault(Locale.Category.DISPLAY, mynewlanglocale); avant setContentView(R.layout.activity_main); mais rien ne change.

Les docs n'expliquent pas trop ce sujet.

18

Oui, dans Android, la localisation avec Oreo ne fonctionne pas correctement avec la configuration de updateconfiguration. Mais il est déconseillé dans Android N lui-même. Au lieu de updateconfiguration, utilisez createconfiguration dans chaque contexte d'attachement. cela fonctionne bien pour moi. Essaye ça...

Dans votre activité, ajoutez ceci .. 

@Override
protected void attachBaseContext(Context newBase) {
    if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
        super.attachBaseContext(MyContextWrapper.wrap(newBase, "ta"));
    }
    else {
        super.attachBaseContext(newBase);
    }
}

Dans MyContextWrapper.Java

 public static ContextWrapper wrap(Context context, String language) {
    Resources res = context.getResources();
    Configuration configuration = res.getConfiguration();
    Locale newLocale = new Locale(language);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        configuration.setLocale(newLocale);
        LocaleList localeList = new LocaleList(newLocale);
        LocaleList.setDefault(localeList);
        configuration.setLocales(localeList);
        context = context.createConfigurationContext(configuration);

    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        configuration.setLocale(newLocale);
        context = context.createConfigurationContext(configuration);

    } else {
        configuration.locale = newLocale;
        res.updateConfiguration(configuration, res.getDisplayMetrics());
    }

    return new ContextWrapper(context);
}
14

J'ai eu le même problème: depuis Android 8.0+, certaines parties de mon application ne changent plus de langue. La mise à jour du contexte de l'application et de l'activité m'aide beaucoup. Voici un exemple de fonction MainActivity:

private void setApplicationLanguage(String newLanguage) {
    Resources activityRes = getResources();
    Configuration activityConf = activityRes.getConfiguration();
    Locale newLocale = new Locale(newLanguage);
    activityConf.setLocale(newLocale);
    activityRes.updateConfiguration(activityConf, activityRes.getDisplayMetrics());

    Resources applicationRes = getApplicationContext().getResources();
    Configuration applicationConf = applicationRes.getConfiguration();
    applicationConf.setLocale(newLocale);
    applicationRes.updateConfiguration(applicationConf, 
    applicationRes.getDisplayMetrics());
}
9
Skeptiker

updateConfiguration est obsolète et vous devriez utiliser createConfigurationContext. Je l'ai résolu de cette façon:

    @Override
    protected void attachBaseContext(Context newBase) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Configuration config = newBase.getResources().getConfiguration();
            //Update your config with the Locale i. e. saved in SharedPreferences
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(newBase);
            String language = prefs.getString(SP_KEY_LANGUAGE, "en_US");
            Locale.setDefault(locale);
            config.setLocale(new Locale(language));
            newBase = newBase.createConfigurationContext(config);
        }
        super.attachBaseContext(newBase);
    }
7
Luke

Mise à jour pour toutes les versions Android jusqu'à Oreo

Créer une classe comme celle-ci

public class LocaleUtils {

@Retention(RetentionPolicy.SOURCE)
@StringDef({ENGLISH, FRENCH, SPANISH})
public @interface LocaleDef {
    String[] SUPPORTED_LOCALES = {ENGLISH, FRENCH, SPANISH};
}

public static final String ENGLISH = "en";
public static final String FRENCH = "fr";
public static final String SPANISH = "es";


public static void initialize(Context context) {
    setLocale(context, ENGLISH);
}

public static void initialize(Context context, @LocaleDef String defaultLanguage) {
    setLocale(context, defaultLanguage);
}


public static boolean setLocale(Context context, @LocaleDef String language) {
    return updateResources(context, language);
}

private static boolean updateResources(Context context, String language) {
    Locale locale = new Locale(language);
    Locale.setDefault(locale);
    Resources resources = context.getResources();
    Configuration configuration = resources.getConfiguration();
    context.createConfigurationContext(configuration);
    configuration.locale = locale;
    resources.updateConfiguration(configuration, resources.getDisplayMetrics());
    return true;
}

}

Maintenant, lorsque vous sélectionnez la langue de votre application, enregistrez le code de langue dans les préférences partagées comme ci-dessous.

private static SharedPreferences getDefaultSharedPreference(Context context) {
    if (PreferenceManager.getDefaultSharedPreferences(Application.getInstance().getApplicationContext()) != null)
        return PreferenceManager.getDefaultSharedPreferences(Application.getInstance().getApplicationContext());
    else
        return null;
}

 public static void setSelectedLanguageId(String id){
    final SharedPreferences prefs = getDefaultSharedPreference(Application.getInstance().getApplicationContext());
    SharedPreferences.Editor editor = prefs.edit();
    editor.putString("app_language_id", id);
    editor.apply();
}

public static String getSelectedLanguageId(){
    return getDefaultSharedPreference(Application.getInstance().getApplicationContext())
            .getString("app_language_id", "en");
}

Ces trois fonctions doivent être écrites dans une classe Utiltiy (votre préférence). Ensuite, lorsque vous sélectionnez la langue de l'application depuis l'application, appelez la fonction setSelectedLanguageId () et transmettez l'ID de langue en tant que paramètre.

De cette façon, vous avez enregistré la langue sélectionnée dans votre application. Maintenant, dans votre classe d'application, écrivez une fonction comme celle-ci 

public void initAppLanguage(Context context){
    LocaleUtils.initialize(context, PreferenceUtil.getSelectedLanguageId() );
}

Ici, le PreferenceUtil est ma classe Utiltiy. Vous devriez le remplacer par votre fonction de classe d'utilitaire. 

Vous devriez également créer une variable dans votre classe d'application

private static Application applicationInstance;

et dans la méthode onCreate de votre classe Application, initialisez applicationInstance pour être le contexte d'applications comme celui-ci

applicationInstance = this; 

Maintenant, écrivez une fonction de lecture dans votre classe d'application

public static synchronized Application getInstance() {
    return applicationInstance;
}

Et maintenant, lorsque vous démarrez votre première activité, appelez cette méthode dans onCreate de votre activité. 

Application.getInstance().initAppLanguage(this);

N'oubliez pas que nous transmettons le contexte de l'activité à la fonction initAppLanguage (), pas le contexte de l'application. Passer le contexte de l'application ne le fera pas fonctionner à Oreo (du moins pour moi). 

Donc, lorsque vous sélectionnez la langue, essayez de redémarrer complètement votre application . Vous pouvez y parvenir en 

Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());

startActivity (i);

J'espère que cela vous aide!

3
emilpmp

Il est possible, cependant, je ne recommanderais pas de définir la langue par programmation

Android est conçu pour que le System UI et votre application utilisent le même langage. Si vous le modifiez par programme, vous vous opposeriez au système.

Au lieu de cela, vous pouvez activer le support multilingue en ajoutant différentes langues strings.xml, cela changera automatiquement la langue.

Je recommande de lire cet article Google Developers:

Soutenir différentes langues et cultures

Si vous avez vraiment besoin de le changer par programme, vous pouvez procéder comme suit:

Locale locale = new Locale("en");
Locale.setDefault(locale);

Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());

Sur le SDK> = 21, vous devez appeler 'Resources.updateConfiguration ()', sinon les ressources ne seront pas mises à jour.

J'espère que ça aide.

1
Andre Breton

Voici une solution complète travaillée pour KitKat, Lollipop, Marshmallow, Nougat et Oreo aussi. Il suffit de suivre toutes les étapes ci-dessous.

Commencez par créer une classe Java comme ci-dessous

import Android.content.Context;
import Android.content.res.Configuration;
import Java.util.Locale;
public class LocaleUtils {
public static void updateConfig(Context mContext, String sLocale) {
    Locale locale = new Locale(sLocale);
    Locale.setDefault(locale);
    Configuration config = mContext.getResources().getConfiguration();
    config.locale = locale;
    mContext.getResources().updateConfiguration(config,
            mContext.getResources().getDisplayMetrics());
  }
}

Maintenant, ajoutez cet extrait au clic du bouton où vous souhaitez modifier les paramètres régionaux.

String lang="hi";//pass your language here
SharedPreferences preferences =  PreferenceManager.getDefaultSharedPreferences(mContext);
                        SharedPreferences.Editor editor = preferences.edit();
                        editor.clear();
                        editor.putString("lang", lang");
                        editor.putBoolean("langSelected", true);
                        editor.apply();
                        LocaleUtils.updateConfig(mContext,lang);
                        Intent intent = mContext.getIntent();
                        mContext.overridePendingTransition(0, 0);
                        mContext.finish();
                        intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
                        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        mContext.overridePendingTransition(0, 0);
                        mContext.startActivity(intent);

Enfin, collez le code ci-dessous dans l'activité Splash ou dans l'activité de lancement.

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
    String lang = preferences.getString("lang", "");
    boolean langSelected = preferences.getBoolean("langSelected", false);
    SharedPreferences.Editor editor = preferences.edit();
    if (langSelected) {
        editor.clear();
        editor.putString("lang", lang);
        editor.putBoolean("langSelected", true);
        editor.apply();
        LocaleUtils.updateConfig(this,lang);
    } else {
        LocaleUtils.updateConfig(this, Locale.getDefault().getLanguage());
        editor.clear();
        editor.putString("lang", Locale.getDefault().getLanguage());
        editor.putBoolean("langSelected", false);
        editor.apply();
    }
1
Ness Tyagi

Vous devez utiliser getApplicationContext() au lieu de getContext()

0

Après utilisation de toutes les solutions dans toutes les sources, j'ai finalement trouvé mon problème. Cela me met en colère pendant 2 jours.

Tout le monde sait que dans Android Oreo (API 26), nous devons utiliser createConfigurationContext, mais mon problème est d'utiliser le nom de pays avec local. 

Remplacer 

en_US avec en

ar_AE avec ar

fa_IR avec fa

Et mon problème résolu.

J'espère aider quelqu'un

0
Radesh