Définir les paramètres régionaux par programme

139

Mon application prend en charge 3 (bientôt 4) langues. Étant donné que plusieurs paramètres régionaux sont assez similaires, j'aimerais donner à l'utilisateur la possibilité de modifier les paramètres régionaux dans mon application, par exemple, une personne italienne pourrait préférer l'espagnol à l'anglais.

Existe-t-il un moyen pour l'utilisateur de sélectionner parmi les paramètres régionaux disponibles pour l'application, puis de modifier les paramètres régionaux utilisés? Je ne vois pas cela comme un problème pour définir les paramètres régionaux pour chaque activité car c'est une tâche simple à effectuer dans une classe de base.

Roland
la source
Si vous avez besoin d'un moyen de restaurer les paramètres régionaux par défaut plus tard ou si vous avez besoin d'une préférence de langue contenant une liste de langues, et si vous souhaitez modifier les paramètres régionaux plus facilement, cela peut être utile: github.com/delight-im/Android -Langues
caw

Réponses:

114

Pour les personnes qui recherchent toujours cette réponse, étant donné qu'elle configuration.localeest obsolète depuis l'API 24, vous pouvez désormais utiliser:

configuration.setLocale(locale);

Tenez compte du fait que minSkdVersion pour cette méthode est l'API 17.

Exemple de code complet:

@SuppressWarnings("deprecation")
private void setLocale(Locale locale){
    SharedPrefUtils.saveLocale(locale); // optional - Helper method to save the selected language to SharedPreferences in case you might need to attach to activity context (you will need to code this)
    Resources resources = getResources();
    Configuration configuration = resources.getConfiguration();
    DisplayMetrics displayMetrics = resources.getDisplayMetrics();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
        configuration.setLocale(locale);
    } else{
        configuration.locale=locale;
    }
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N){
        getApplicationContext().createConfigurationContext(configuration);
    } else {
        resources.updateConfiguration(configuration,displayMetrics);
    }
}

N'oubliez pas que si vous modifiez les paramètres régionaux avec une activité en cours d'exécution, vous devrez la redémarrer pour que les modifications prennent effet.

EDIT 11 MAI 2018

Depuis le post de @ CookieMonster, vous pourriez avoir des problèmes pour conserver le changement de langue dans les versions d'API supérieures. Si tel est le cas, ajoutez le code suivant à votre activité de base afin de mettre à jour les paramètres régionaux de contexte à chaque création d'activité:

@Override
protected void attachBaseContext(Context base) {
     super.attachBaseContext(updateBaseContextLocale(base));
}

private Context updateBaseContextLocale(Context context) {
    String language = SharedPrefUtils.getSavedLanguage(); // Helper method to get saved language from SharedPreferences
    Locale locale = new Locale(language);
    Locale.setDefault(locale);

    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
        return updateResourcesLocale(context, locale);
    }

    return updateResourcesLocaleLegacy(context, locale);
}

@TargetApi(Build.VERSION_CODES.N_MR1)
private Context updateResourcesLocale(Context context, Locale locale) {
    Configuration configuration = new Configuration(context.getResources().getConfiguration())
    configuration.setLocale(locale);
    return context.createConfigurationContext(configuration);
}

@SuppressWarnings("deprecation")
private Context updateResourcesLocaleLegacy(Context context, Locale locale) {
    Resources resources = context.getResources();
    Configuration configuration = resources.getConfiguration();
    configuration.locale = locale;
    resources.updateConfiguration(configuration, resources.getDisplayMetrics());
    return context;
}

Si vous utilisez ceci, n'oubliez pas d'enregistrer la langue dans SharedPreferences lorsque vous définissez les paramètres régionaux avec setLocate(locale)

EDIT 7 AVRIL 2020

Vous rencontrez peut-être des problèmes sous Android 6 et 7, et cela est dû à un problème dans les bibliothèques androidx lors de la gestion du mode nuit. Pour cela, vous devrez également remplacer applyOverrideConfigurationvotre activité de base et mettre à jour les paramètres régionaux de la configuration au cas où un nouveau paramètre régional serait créé.

Exemple de code:

@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) {
        // update overrideConfiguration with your locale  
        setLocale(overrideConfiguration) // you will need to implement this
    }
    super.applyOverrideConfiguration(overrideConfiguration);
} 
Ricardo
la source
2
Cela fonctionne pour les activités, mais existe-t-il un moyen de mettre à jour le contexte de l'application?
alekop le
2
Après avoir changé la androidx.appcompat:appcompat:version de 1.0.2à 1.1.0ne fonctionne pas sur Android 7, mais fonctionne sur Android 9.
Bek
4
Le même problème pour moi et 1.1.0androidx
Alexander Dadukin
2
Même problème pour moi. Après avoir changé pour androidx.appcompat: appcompat: 1.1.0 'lib
Rahul Jidge
4
Le problème appcompat:1.1.0peut être résolu avec appcompat:1.2.0-alpha02et le code à l' Set<Locale> set = new LinkedHashSet<>(); // bring the target locale to the front of the list set.add(locale); LocaleList all = LocaleList.getDefault(); for (int i = 0; i < all.size(); i++) { // append other locales supported by the user set.add(all.get(i)); } Locale[] locales = set.toArray(new Locale[0]); configuration.setLocales(new LocaleList(locales));intérieur@TargetApi(Build.VERSION_CODES.N) updateResourcesLocale()
Vojtech Pohl
178

J'espère que cette aide (dans onResume):

Locale locale = new Locale("ru");
Locale.setDefault(locale);
Configuration config = getBaseContext().getResources().getConfiguration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
      getBaseContext().getResources().getDisplayMetrics());
Rubycon
la source
2
Donc, cela doit être défini pour chaque activité?
Tobias
6
1. il est obligatoire d'utiliser getBaseContext () ou est-il préférable d'utiliser les contextes d'application? 2. ce code doit-il être appelé dans chaque activité? Merci.
Paul
10
J'ai placé ce code dans onCreate () de mon activité de lancement (et nulle part ailleurs) et j'ai été agréablement surpris de voir que les paramètres régionaux s'appliquaient à l'ensemble de l'application. Ceci est dans une application ciblant 4,3 avec un minSDK de 14 (ICS).
IAmKale
8
Il n'est pas nécessaire de créer un nouvel objet de configuration. Vous pouvez utiliser la configuration actuelle et la mettre à jour: getResources (). GetConfiguration ()
jmart
1
ne pas utiliser la nouvelle configuration () ;, il change textAppearance, fontSize
Jemshit Iskenderov
22

J'ai eu un problème avec la configuration des paramètres régionaux par programmation avec des appareils dotés d' Android OS N et supérieur . Pour moi, la solution était d'écrire ce code dans mon activité de base:

(si vous n'avez pas d'activité de base, vous devez effectuer ces changements dans toutes vos activités)

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(updateBaseContextLocale(base));
}

private Context updateBaseContextLocale(Context context) {
    String language = SharedPref.getInstance().getSavedLanguage();
    Locale locale = new Locale(language);
    Locale.setDefault(locale);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        return updateResourcesLocale(context, locale);
    }

    return updateResourcesLocaleLegacy(context, locale);
}

@TargetApi(Build.VERSION_CODES.N)
private Context updateResourcesLocale(Context context, Locale locale) {
    Configuration configuration = context.getResources().getConfiguration();
    configuration.setLocale(locale);
    return context.createConfigurationContext(configuration);
}

@SuppressWarnings("deprecation")
private Context updateResourcesLocaleLegacy(Context context, Locale locale) {
    Resources resources = context.getResources();
    Configuration configuration = resources.getConfiguration();
    configuration.locale = locale;
    resources.updateConfiguration(configuration, resources.getDisplayMetrics());
    return context;
}

notez qu'ici il ne suffit pas d'appeler

createConfigurationContext(configuration)

vous devez également obtenir le contexte renvoyé par cette méthode, puis définir ce contexte dans la attachBaseContextméthode.

CookieMonster
la source
C'est la solution la plus simple et la plus efficace! Cela devrait être la réponse acceptée.
Prasad Pawar
3
Ce code fonctionne énormément sur Android supérieur à 7 mais dans les versions inférieures à N ne fonctionne pas. Avez-vous des solutions?
Matin Ashtiani
Je ne sais pas car cela fonctionne pour moi. Voulez-vous m'envoyer votre implémentation afin que je puisse y jeter un coup d'œil?
CookieMonster
2
Ne fonctionne pas dans les versions sous Android N car resources.updateConfiguration doit être appelé dans onCreate () au lieu de attachBaseContext ()
Chandler
@Chandler a raison. Pour Android 6-, appelez la updateBaseContextLocaleméthode onCreatede votre activité parent / base.
Azizjon Kholmatov le
22

Comme aucune réponse n'est complète pour la manière actuelle de résoudre ce problème, j'essaie de donner des instructions pour une solution complète. Veuillez commenter si quelque chose manque ou pourrait être amélioré.

informations générales

Premièrement, il existe des bibliothèques qui veulent résoudre le problème mais elles semblent toutes obsolètes ou manquent de certaines fonctionnalités:

De plus, je pense qu'écrire une bibliothèque n'est peut-être pas un moyen simple / bon de résoudre ce problème car il n'y a pas grand chose à faire, et ce qu'il faut faire est plutôt de changer le code existant que d'utiliser quelque chose de complètement découplé. C'est pourquoi j'ai rédigé les instructions suivantes qui devraient être complètes.

Ma solution est principalement basée sur https://github.com/gunhansancar/ChangeLanguageExample (comme déjà lié par localhost ). C'est le meilleur code que j'ai trouvé pour m'orienter. Quelques remarques:

  • Si nécessaire, il fournit différentes implémentations pour modifier les paramètres régionaux pour Android N (et supérieur) et inférieur
  • Il utilise une méthode updateViews()dans chaque activité pour mettre à jour manuellement toutes les chaînes après avoir changé les paramètres régionaux (en utilisant l'habituel getString(id)), ce qui n'est pas nécessaire dans l'approche ci-dessous
  • Il ne prend en charge que les langues et non les paramètres régionaux complets (qui incluent également les codes de région (pays) et de variante)

Je l'ai un peu changé, découplant la partie qui persiste dans la locale choisie (car on pourrait vouloir le faire séparément, comme suggéré ci-dessous).

Solution

La solution comprend les deux étapes suivantes:

  • Modifier définitivement les paramètres régionaux à utiliser par l'application
  • Faire en sorte que l'application utilise l'ensemble de paramètres régionaux personnalisés, sans redémarrer

Étape 1: modifier les paramètres régionaux

Utilisez la classe LocaleHelper, basée sur LocaleHelper de gunhansancar :

  • Ajouter un ListPreferencedans un PreferenceFragmentavec les langues disponibles (doit être conservé lorsque des langues doivent être ajoutées ultérieurement)
import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.preference.PreferenceManager;

import java.util.Locale;

import mypackage.SettingsFragment;

/**
 * Manages setting of the app's locale.
 */
public class LocaleHelper {

    public static Context onAttach(Context context) {
        String locale = getPersistedLocale(context);
        return setLocale(context, locale);
    }

    public static String getPersistedLocale(Context context) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getString(SettingsFragment.KEY_PREF_LANGUAGE, "");
    }

    /**
     * Set the app's locale to the one specified by the given String.
     *
     * @param context
     * @param localeSpec a locale specification as used for Android resources (NOTE: does not
     *                   support country and variant codes so far); the special string "system" sets
     *                   the locale to the locale specified in system settings
     * @return
     */
    public static Context setLocale(Context context, String localeSpec) {
        Locale locale;
        if (localeSpec.equals("system")) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                locale = Resources.getSystem().getConfiguration().getLocales().get(0);
            } else {
                //noinspection deprecation
                locale = Resources.getSystem().getConfiguration().locale;
            }
        } else {
            locale = new Locale(localeSpec);
        }
        Locale.setDefault(locale);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return updateResources(context, locale);
        } else {
            return updateResourcesLegacy(context, locale);
        }
    }

    @TargetApi(Build.VERSION_CODES.N)
    private static Context updateResources(Context context, Locale locale) {
        Configuration configuration = context.getResources().getConfiguration();
        configuration.setLocale(locale);
        configuration.setLayoutDirection(locale);

        return context.createConfigurationContext(configuration);
    }

    @SuppressWarnings("deprecation")
    private static Context updateResourcesLegacy(Context context, Locale locale) {
        Resources resources = context.getResources();

        Configuration configuration = resources.getConfiguration();
        configuration.locale = locale;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLayoutDirection(locale);
        }

        resources.updateConfiguration(configuration, resources.getDisplayMetrics());

        return context;
    }
}

Créez un SettingsFragmentcomme celui-ci:

import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import mypackage.LocaleHelper;
import mypackage.R;

/**
 * Fragment containing the app's main settings.
 */
public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
    public static final String KEY_PREF_LANGUAGE = "pref_key_language";

    public SettingsFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_settings, container, false);
        return view;
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        switch (key) {
            case KEY_PREF_LANGUAGE:
                LocaleHelper.setLocale(getContext(), PreferenceManager.getDefaultSharedPreferences(getContext()).getString(key, ""));
                getActivity().recreate(); // necessary here because this Activity is currently running and thus a recreate() in onResume() would be too late
                break;
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        // documentation requires that a reference to the listener is kept as long as it may be called, which is the case as it can only be called from this Fragment
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
    }
}

Créez une ressource locales.xmlrépertoriant tous les paramètres régionaux avec les traductions disponibles de la manière suivante ( liste des codes de paramètres régionaux ):

<!-- Lists available locales used for setting the locale manually.
     For now only language codes (locale codes without country and variant) are supported.
     Has to be in sync with "settings_language_values" in strings.xml (the entries must correspond).
  -->
<resources>
    <string name="system_locale" translatable="false">system</string>
    <string name="default_locale" translatable="false"></string>
    <string-array name="locales">
        <item>@string/system_locale</item> <!-- system setting -->
        <item>@string/default_locale</item> <!-- default locale -->
        <item>de</item>
    </string-array>
</resources>

Dans votre, PreferenceScreenvous pouvez utiliser la section suivante pour permettre à l'utilisateur de sélectionner les langues disponibles:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:title="@string/preferences_category_general">
        <ListPreference
            android:key="pref_key_language"
            android:title="@string/preferences_language"
            android:dialogTitle="@string/preferences_language"
            android:entries="@array/settings_language_values"
            android:entryValues="@array/locales"
            android:defaultValue="@string/system_locale"
            android:summary="%s">
        </ListPreference>
    </PreferenceCategory>
</PreferenceScreen>

qui utilise les chaînes suivantes de strings.xml:

<string name="preferences_category_general">General</string>
<string name="preferences_language">Language</string>
<!-- NOTE: Has to correspond to array "locales" in locales.xml (elements in same orderwith) -->
<string-array name="settings_language_values">
    <item>Default (System setting)</item>
    <item>English</item>
    <item>German</item>
</string-array>

Étape 2: faire en sorte que l'application utilise les paramètres régionaux personnalisés

Configurez maintenant chaque activité pour utiliser l'ensemble de paramètres régionaux personnalisés. Le moyen le plus simple d'y parvenir est d'avoir une classe de base commune pour toutes les activités avec le code suivant (où se trouve le code important attachBaseContext(Context base)et onResume()):

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

import mypackage.LocaleHelper;
import mypackage.R;

/**
 * {@link AppCompatActivity} with main menu in the action bar. Automatically recreates
 * the activity when the locale has changed.
 */
public class MenuAppCompatActivity extends AppCompatActivity {
    private String initialLocale;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initialLocale = LocaleHelper.getPersistedLocale(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_settings:
                Intent intent = new Intent(this, SettingsActivity.class);
                startActivity(intent);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base));
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (initialLocale != null && !initialLocale.equals(LocaleHelper.getPersistedLocale(this))) {
            recreate();
        }
    }
}

Ce que ça fait c'est

  • Remplacer attachBaseContext(Context base)pour utiliser les paramètres régionaux précédemment conservés avecLocaleHelper
  • Détecter un changement de paramètres régionaux et recréer l'activité pour mettre à jour ses chaînes

Remarques sur cette solution

  • La recréation d'une activité ne met pas à jour le titre de l'ActionBar (comme déjà observé ici: https://github.com/gunhansancar/ChangeLanguageExample/issues/1 ).

    • Ceci peut être réalisé en ayant simplement un setTitle(R.string.mytitle)dans la onCreate()méthode de chaque activité.
  • Il permet à l'utilisateur de choisir les paramètres régionaux par défaut du système, ainsi que les paramètres régionaux par défaut de l'application (qui peuvent être nommés, dans ce cas, «anglais»).

  • Seuls les codes de langue, aucune région (pays) et codes de variante (comme fr-rCA) sont pris en charge jusqu'à présent. Pour prendre en charge les spécifications régionales complètes, un analyseur similaire à celui de la bibliothèque Android-Languages peut être utilisé (qui prend en charge la région mais pas les codes de variante).

    • Si quelqu'un trouve ou a écrit un bon analyseur, ajoutez un commentaire afin que je puisse l'inclure dans la solution.
user905686
la source
1
Excellent mais roi du cauchemar
Odys
1
Bon sang non, mon application est déjà trop complexe, cette approche serait un cauchemar à maintenir dans le futur.
Josh
@Josh Pouvez-vous expliquer cela un peu plus? En fait, seules quelques lignes doivent être ajoutées à chaque classe de base d'activité que vous utilisez. Je vois qu'il n'est peut-être pas possible d'utiliser la même classe de base pour toutes les activités, mais même des projets plus importants devraient pouvoir s'entendre avec quelques-uns. La programmation orientée aspect pourrait aider ici, mais la composition (déplacer le code depuis attachBaseContext(Context base)et onResume()vers une classe séparée) peut faire l'affaire. Ensuite, tout ce que vous avez à faire est de déclarer un objet dans chaque classe de base d'activité et de déléguer ces deux appels.
user905686
Si l'utilisateur modifie ses paramètres régionaux, les paramètres régionaux de toutes les pages d'activité précédentes peuvent-ils également être modifiés?
Raju yourPepe
C'est la meilleure réponse à ce problème. Merci mon frère, ça marche
Alok Gupta
16
@SuppressWarnings("deprecation")
public static void forceLocale(Context context, String localeCode) {
    String localeCodeLowerCase = localeCode.toLowerCase();

    Resources resources = context.getApplicationContext().getResources();
    Configuration overrideConfiguration = resources.getConfiguration();
    Locale overrideLocale = new Locale(localeCodeLowerCase);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        overrideConfiguration.setLocale(overrideLocale);
    } else {
        overrideConfiguration.locale = overrideLocale;
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        context.getApplicationContext().createConfigurationContext(overrideConfiguration);
    } else {
        resources.updateConfiguration(overrideConfiguration, null);
    }
}

Utilisez simplement cette méthode d'assistance pour forcer des paramètres régionaux spécifiques.

UDPATE 22 AOÛT 2017. Mieux vaut utiliser cette approche .

localhost
la source
4

Ajoutez une classe d'assistance avec la méthode suivante:

public class LanguageHelper {
    public static final void setAppLocale(String language, Activity activity) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Resources resources = activity.getResources();
            Configuration configuration = resources.getConfiguration();
            configuration.setLocale(new Locale(language));
            activity.getApplicationContext().createConfigurationContext(configuration);
        } else {
            Locale locale = new Locale(language);
            Locale.setDefault(locale);
            Configuration config = activity.getResources().getConfiguration();
            config.locale = locale;
            activity.getResources().updateConfiguration(config,
                    activity.getResources().getDisplayMetrics());
        }

    }
}

Et appelez-le dans votre activité de démarrage, comme MainActivity.java:

public void onCreate(Bundle savedInstanceState) {
    ...
    LanguageHelper.setAppLocale("fa", this);
    ...
}
Graphiques Hadid
la source
3

simple et facile

Locale locale = new Locale("en", "US");
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = locale;
res.updateConfiguration(conf, dm);

où "en" est le code de la langue et "US" est le code du pays.

Makvin
la source
Comme indiqué dans mon message, il conf.locale=locale;est obsolète et l'est également updateConfiguration.
Ricardo
très simple et moins compliqué :)
Ramkesh Yadav
2

Valable pour API16 à API28 Il suffit de placer cette méthode là où:

    Context newContext = context;

        Locale locale = new Locale(languageCode);
        Locale.setDefault(locale);

        Resources resources = context.getResources();
        Configuration config = new Configuration(resources.getConfiguration());

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {

        config.setLocale(locale);
                newContext = context.createConfigurationContext(config);

        } else {

        config.locale = locale;
                resources.updateConfiguration(config, resources.getDisplayMetrics());
        }

    return newContext;
}

Insérez ce code dans toutes vos activités en utilisant:

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(localeUpdateResources(base, "<-- language code -->"));
    }

ou appelez localeUpdateResources sur des fragments, des adaptateurs, etc. où vous avez besoin du nouveau contexte.

Crédits: Yaroslav Berezanskyi

nnyerges
la source
2

Il existe un moyen très simple.

dans BaseActivity, Activity ou Fragment override attachBaseContext

 override fun attachBaseContext(context: Context) {
    super.attachBaseContext(context.changeLocale("tr"))
}

extension

fun Context.changeLocale(language:String): Context {
    val locale = Locale(language)
    Locale.setDefault(locale)
    val config = this.resources.configuration
    config.setLocale(locale)
    return createConfigurationContext(config)
}
Burak Dizlek
la source
2

J'ai trouvé le androidx.appcompat:appcompat:1.1.0bogue peut également être fixé en appelant simplement getResources()enapplyOverrideConfiguration()

@Override public void
applyOverrideConfiguration(Configuration cfgOverride)
{
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
      Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
    // add this to fix androidx.appcompat:appcompat 1.1.0 bug
    // which happens on Android 6.x ~ 7.x
    getResources();
  }

  super.applyOverrideConfiguration(cfgOverride);
}
Sam Lu
la source
1
 /**
 * Requests the system to update the list of system locales.
 * Note that the system looks halted for a while during the Locale migration,
 * so the caller need to take care of it.
 */
public static void updateLocales(LocaleList locales) {
    try {
        final IActivityManager am = ActivityManager.getService();
        final Configuration config = am.getConfiguration();

        config.setLocales(locales);
        config.userSetLocale = true;

        am.updatePersistentConfiguration(config);
    } catch (RemoteException e) {
        // Intentionally left blank
    }
}
Zbigniew Mazur
la source
1

Pour ceux qui ont tout essayé mais qui ne fonctionnent pas . Veuillez vérifier que si vous définissez darkmodeavec AppCompatDelegate.setDefaultNightModeet que le système n'est pas sombre, Configuration.setLocalecela ne fonctionnera pas au-dessus d' Andorid 7.0 .

Ajoutez ce code dans chacune de vos activités pour résoudre ce problème:

override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
  if (overrideConfiguration != null) {
    val uiMode = overrideConfiguration.uiMode
    overrideConfiguration.setTo(baseContext.resources.configuration)
    overrideConfiguration.uiMode = uiMode
  }
  super.applyOverrideConfiguration(overrideConfiguration)
}
Ouaisia2508
la source
-1

Mettez ce code dans votre activité

 if (id==R.id.uz)
    {
        LocaleHelper.setLocale(MainActivity.this, mLanguageCode);

        //It is required to recreate the activity to reflect the change in UI.
        recreate();
        return true;
    }
    if (id == R.id.ru) {

        LocaleHelper.setLocale(MainActivity.this, mLanguageCode);

        //It is required to recreate the activity to reflect the change in UI.
        recreate();
    }
Xurshid Raxmatov
la source