Modifier la langue de l'application par programme dans Android


448

Est-il possible de changer la langue d'une application par programme tout en utilisant des ressources Android?

Sinon, est-il possible de demander une ressource dans une langue spécifique?

Je voudrais laisser l'utilisateur changer la langue de l'application depuis l'application.


4
Vous pouvez utiliser la bibliothèque suivante, qui fournit la liste des langues, la préférence pour votre écran de paramètres et remplace la langue dans votre application: github.com/delight-im/Android-Languages
caw

@MarcoW. Savez-vous si Android-Languages ​​fonctionne avec Android 5.0 Lollipop?
neu242

1
@ neu242 Oui, il fonctionne sans problème avec Android 5.0.
caw

1
Vous pouvez utiliser la bibliothèque suivante: github.com/zeugma-solutions/locale-helper-android
josue.0

1
@ josue.0 que la bibliothèque est vraiment la solution la plus propre pour cela
amitavk

Réponses:


376

C'est possible. Vous pouvez définir les paramètres régionaux. Cependant, je ne recommanderais pas cela. Nous l'avons essayé à un stade précoce, il s'agit essentiellement de combattre le système.

Nous avons la même exigence pour changer la langue, mais nous avons décidé de nous contenter du fait que l'interface utilisateur devrait être identique à l'interface utilisateur du téléphone. Cela fonctionnait via la définition des paramètres régionaux mais était trop bogué. Et vous devez le régler chaque fois que vous entrez dans une activité (chaque activité) d'après mon expérience. voici un code si vous en avez encore besoin (encore une fois, je ne le recommande pas)

Resources res = context.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.setLocale(new Locale(language_code.toLowerCase())); // API 17+ only.
// Use conf.locale = new Locale(...) if targeting lower versions
res.updateConfiguration(conf, dm);

Si vous avez un contenu spécifique à une langue, vous pouvez modifier cette base en fonction du paramètre.


mise à jour du 26 mars 2020

public static void setLocale(Activitycontext) {
        Locale locale;
        Sessions session = new Sessions(context);
        //Log.e("Lan",session.getLanguage());
            locale = new Locale(langCode);
        Configuration config = new Configuration(context.getResources().getConfiguration());
        Locale.setDefault(locale);
        config.setLocale(locale);

       context.getBaseContext().getResources().updateConfiguration(config,
              context.getBaseContext().getResources().getDisplayMetrics());
    }

328
Je ne peux pas croire qu'Android rend cela si difficile. Je ne vois pas vraiment pourquoi il devrait y avoir une association STRICTE entre les paramètres régionaux du téléphone et ceux de l'application. J'ai toujours mon téléphone en utilisant la langue anglaise bien que je ne sois pas natif anglais. La raison en est que les mots semi-techniques traduits deviennent trop bizarres dans ma propre langue, donc l'anglais est tellement plus facile. Cela me permet également de suivre plus facilement les conseils du Net. Mais cela ne signifie pas que je veux que CHAQUE application sur mon téléphone utilise l'anglais (bien que cela soit parfaitement correct par défaut). Je veux pouvoir choisir !!!
peterh

9
Oh, on dirait que l'API de niveau 17 a été introduite Context.createConfigurationContext(), qui peut être utilisée pour encapsuler le contexte par défaut avec une configuration spécifique aux paramètres régionaux, puis l'appeler getResourcessans avoir à mettre à jour la configuration sur les objets ressources eux-mêmes.
JAB

8
Vous devez mettre ceci dans onCreate () de chaque activité. Sinon, il peut être remplacé par le système - par exemple lorsque vous mettez votre appareil en mode paysage et que votre activité est recréée avec une nouvelle configuration (fournie par le système).
Zsolt Safrany

13
Dans le cas où vous définissez une locale RTL comme "ar" et souhaitez que vos dossiers de ressources -ldrtl fonctionnent également, appelez également conf.setLayoutDirection (locale);
Zsolt Safrany

3
@ZsoltSafrany - Plutôt que d'ajouter un appel à conf.setLayoutDirection(locale), vous pouvez le remplacer conf.locale = new Locale(...))par conf.setLocale(new Locale(...)). Il appellera en interne setLayoutDirection.
Ted Hopp du

179

Ce code fonctionne vraiment:

fa = persan, en = anglais

Entrez votre code de langue dans la languageToLoadvariable:

import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;

public class Main extends Activity {
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    String languageToLoad  = "fa"; // your language
    Locale locale = new Locale(languageToLoad); 
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    getBaseContext().getResources().updateConfiguration(config, 
      getBaseContext().getResources().getDisplayMetrics());
    this.setContentView(R.layout.main);
  }
}

2
Je veux changer les paramètres régionaux à l'exécution, dans votre code, vous mettez votre code avant la méthode setContentView (). Donc, votre code ne m'est pas utile, Alors, comment changer la langue au moment de l'exécution, Dans mon application, il y a deux boutons radio, pour l'anglais et un autre pour l'arabe,
Dwivedi Ji

2
@Buffalo, c'est juste le deuxième argument de la Resources.updateConfigurationméthode. J'ai mis en retrait le code pour le rendre plus clair.
Czechnology

5
Cela fonctionne bien pour toutes les activités lors de la définition de l'activité de lancement. Mais, le titre de la barre d'action ne semble pas affecté et continue d'afficher la langue par défaut. Une idée de ce que j'aurais pu manquer?
AndroidMechanic - Viral Patel

8
Config.locale est déprécié
Zoé

2
au lieu de "config.locale = locale;" utilisez "if (Build.VERSION.SDK_INT> = 17) {config.setLocale (locale);} else {config.locale = locale;}
roghayeh hosseini

36

Je cherchais un moyen de changer la langue du système par programme. Bien que je comprenne bien qu'une application normale ne devrait jamais faire cela et à la place:

  • l'utilisateur doit être dirigé (par une intention) vers les paramètres système pour le modifier manuellement
  • l'application doit gérer sa localisation de la même manière que celle décrite dans la réponse d'Alex

il fallait vraiment changer la langue du système par programme.

Il s'agit d'API non documentée et ne doit donc pas être utilisée pour les applications de marché / utilisateur final!

Quoi qu'il en soit, voici la solution que j'ai trouvée:

  Locale locale = new Locale(targetLocaleAsString);

  Class amnClass = Class.forName("android.app.ActivityManagerNative");
  Object amn = null;
  Configuration config = null;

  // amn = ActivityManagerNative.getDefault();
  Method methodGetDefault = amnClass.getMethod("getDefault");
  methodGetDefault.setAccessible(true);
  amn = methodGetDefault.invoke(amnClass);

  // config = amn.getConfiguration();
  Method methodGetConfiguration = amnClass.getMethod("getConfiguration");
  methodGetConfiguration.setAccessible(true);
  config = (Configuration) methodGetConfiguration.invoke(amn);

  // config.userSetLocale = true;
  Class configClass = config.getClass();
  Field f = configClass.getField("userSetLocale");
  f.setBoolean(config, true);

  // set the locale to the new value
  config.locale = locale;

  // amn.updateConfiguration(config);
  Method methodUpdateConfiguration = amnClass.getMethod("updateConfiguration", Configuration.class);
  methodUpdateConfiguration.setAccessible(true);
  methodUpdateConfiguration.invoke(amn, config);

2
donner une exception invocationtarget exception
Ravi

1
Cela dépend bien de l'endroit où l'invocationTargetException est levée. Ensuite, vous devez connaître la classe qui a été modifiée.
icyerasor

1
@ Rat-a-tat-a-tat Ratatouille, à partir d'Android 4.2, android.permission.CHANGE_CONFIGURATIONne peut être accordé que par une application signée avec la touche perform.
Yeung

3
J'ai mis mon application dans / system / priv-app pour contourner le problème Android 6.0. Détails ici .
weiyin

1
@Ravi J'ai dû déplacer mon application de / system / app vers / system / priv-app pour la faire fonctionner
alexislg

31

Si vous souhaitez conserver la langue modifiée dans toute votre application, vous devez faire deux choses.

Tout d'abord, créez une activité de base et étendez toutes vos activités à partir de cela:

public class BaseActivity extends AppCompatActivity {

    private Locale mCurrentLocale;

    @Override
    protected void onStart() {
        super.onStart();

        mCurrentLocale = getResources().getConfiguration().locale;
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Locale locale = getLocale(this);

        if (!locale.equals(mCurrentLocale)) {

            mCurrentLocale = locale;
            recreate();
        }
    }

    public static Locale getLocale(Context context){
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);

        String lang = sharedPreferences.getString("language", "en");
        switch (lang) {
            case "English":
                lang = "en";
                break;
            case "Spanish":
                lang = "es";
                break;
        }
        return new Locale(lang);
    }
}

Notez que j'enregistre la nouvelle langue dans une préférence partagée.

Deuxièmement, créez une extension de l'application comme celle-ci:

    public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        setLocale();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        setLocale();
    }

    private void setLocale() {

        final Resources resources = getResources();
        final Configuration configuration = resources.getConfiguration();
        final Locale locale = getLocale(this);
        if (!configuration.locale.equals(locale)) {
            configuration.setLocale(locale);
            resources.updateConfiguration(configuration, null);
        }
    }
}

Notez que getLocale () est la même que ci-dessus.

C'est tout! J'espère que cela peut aider quelqu'un.


L'activité de l'application est une activité principale, comme une activité principale? par exemple, je peux résoudre ce problème dans setLocale () dans ma méthode onCreate ()?
Morozov

L'application est une extension de l'application, ce n'est pas une activité. Je ne comprends pas ce dont vous avez besoin, désolé. Vous pouvez peut-être essayer de m'expliquer à nouveau :)
Daniel S.

1
pour ces noobs Android comme moi, venez ici pour savoir ce que Applicationc'est et comment l'utiliser. mobomo.com/2011/05/how-to-use-application-object-of-android
Siwei Shen 申思维

2
configuration.locateest obsolète, setLocale nécessite l'API 17+ et updateConfiguration est obsolète
Zoé

19

Selon cet article . Vous devrez télécharger LocaleHelper.javaréférencé dans cet article.

  1. Créer une MyApplicationclasse qui s'étendraApplication
  2. Remplacez attachBaseContext()pour mettre à jour la langue.
  3. Enregistrez cette classe dans le manifeste.

    public class MyApplication extends Application {
       @Override
       protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
       }
    }
    
    <application
         android:name="com.package.MyApplication"
         .../>
  4. Créez BaseActivityet remplacez onAttach()pour mettre à jour la langue. Nécessaire pour Android 6+

    public class BaseActivity extends Activity {
      @Override
      protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base));
      }
    }
  5. Faites en sorte que toutes les activités de votre application s'étendent de BaseActivity.

    public class LocaleHelper {
    
    private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
    
    public static Context onAttach(Context context) {
        String lang = getPersistedData(context, Locale.getDefault().getLanguage());
        return setLocale(context, lang);
    }
    
    public static Context onAttach(Context context, String defaultLanguage) {
        String lang = getPersistedData(context, defaultLanguage);
        return setLocale(context, lang);
    }
    
    public static String getLanguage(Context context) {
        return getPersistedData(context, Locale.getDefault().getLanguage());
    }
    
    public static Context setLocale(Context context, String language) {
        persist(context, language);
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return updateResources(context, language);
        }
    
        return updateResourcesLegacy(context, language);
    }
    
    private static String getPersistedData(Context context, String defaultLanguage) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
    }
    
    private static void persist(Context context, String language) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = preferences.edit();
    
        editor.putString(SELECTED_LANGUAGE, language);
        editor.apply();
    }
    
    @TargetApi(Build.VERSION_CODES.N)
    private static Context updateResources(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
    
        Configuration configuration = context.getResources().getConfiguration();
        configuration.setLocale(locale);
        configuration.setLayoutDirection(locale);
    
        return context.createConfigurationContext(configuration);
    }
    
    @SuppressWarnings("deprecation")
    private static Context updateResourcesLegacy(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(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;
    }
    }

ne peut pas utiliser super.attachBaseContext (LocaleHelper.onAttach (newBase)) car j'utilise déjà super.attachBaseContext (CalligraphyContextWrapper.wrap (newBase))
Rasel

1
vous pouvez envelopper les uns avec les autres. super.attachBaseContext (CalligraphyContextWrapper.wrap (LocaleHelper.onAttach (newBase)))
Yeahia2508

15

Ajouter juste un morceau supplémentaire qui m'a fait trébucher.

Alors que les autres réponses fonctionnent bien avec "de" par exemple

String lang = "de";
Locale locale = new Locale(lang); 
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, 
    getBaseContext().getResources().getDisplayMetrics());

Ce qui précède ne fonctionnera pas avec, par exemple, les "fr_BE"paramètres régionaux de sorte qu'il utiliserait levalues-fr-rBE dossier ou similaire.

Nécessite le léger changement suivant pour fonctionner avec "fr_BE"

String lang = "fr";

//create a string for country
String country = "BE";
//use constructor with country
Locale locale = new Locale(lang, country);

Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, 
    getBaseContext().getResources().getDisplayMetrics());

1
si vous souhaitez appliquer le changement de paramètres régionaux à l'appel d'activité ouvert en coursactivity.recreate()
À Kra

Je sais que je suis en retard à la fête, mais la nouvelle Locale (lang, country) était tout ce dont j'avais besoin!
Jacob Holloway

activity.recreate () comment cela fonctionne ou si nous l'appelons alors String lang = "fr"; String country = "BE";
n'écrasera

Que diriez-vous d'utiliser android.content.res.Configuration conf = res.getConfiguration();au lieu de créer une nouvelle Configurationinstance? Y a-t-il un avantage à en utiliser un nouveau?
Bianca Daniciuc

14

J'ai changé de langue allemande pour que mon application démarre elle-même.

Voici mon bon code. Tout le monde veut utiliser la même chose pour moi .. (Comment changer la langue dans Android par programme)

mon code:

Configuration config ; // variable declaration in globally

// this part is given inside onCreate Method starting and before setContentView()

public void onCreate(Bundle icic) 
{
    super.onCreate(icic);
    config = new Configuration(getResources().getConfiguration());
    config.locale = Locale.GERMAN ;
    getResources().updateConfiguration(config,getResources().getDisplayMetrics());

    setContentView(R.layout.newdesign);
}

1
@harikrishnan Cela ne fonctionne pas pour moi et le clavier ne change pas la langue spécifiée. Comment avez-vous déclaré l'activité dans le manifeste?
Avadhani Y

13

Je sais qu'il est tard pour répondre mais j'ai trouvé cet article ici . Ce qui explique très bien l'ensemble du processus et vous fournit un code bien structuré.

Classe d'aide locale:

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;

/**
 * This class is used to change your application locale and persist this change for the next time
 * that your app is going to be used.
 * <p/>
 * You can also change the locale of your application on the fly by using the setLocale method.
 * <p/>
 * Created by gunhansancar on 07/10/15.
 */
public class LocaleHelper {

    private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";

    public static Context onAttach(Context context) {
        String lang = getPersistedData(context, Locale.getDefault().getLanguage());
        return setLocale(context, lang);
    }

    public static Context onAttach(Context context, String defaultLanguage) {
        String lang = getPersistedData(context, defaultLanguage);
        return setLocale(context, lang);
    }

    public static String getLanguage(Context context) {
        return getPersistedData(context, Locale.getDefault().getLanguage());
    }

    public static Context setLocale(Context context, String language) {
        persist(context, language);

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

        return updateResourcesLegacy(context, language);
    }

    private static String getPersistedData(Context context, String defaultLanguage) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
    }

    private static void persist(Context context, String language) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = preferences.edit();

        editor.putString(SELECTED_LANGUAGE, language);
        editor.apply();
    }

    @TargetApi(Build.VERSION_CODES.N)
    private static Context updateResources(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        Configuration configuration = context.getResources().getConfiguration();
        configuration.setLocale(locale);
        configuration.setLayoutDirection(locale);

        return context.createConfigurationContext(configuration);
    }

    @SuppressWarnings("deprecation")
    private static Context updateResourcesLegacy(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(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;
    }
}

Vous devez remplacer attachBaseContext et appeler LocaleHelper.onAttach () pour initialiser les paramètres régionaux dans votre application.

import android.app.Application;
import android.content.Context;

import com.gunhansancar.changelanguageexample.helper.LocaleHelper;

public class MainApplication extends Application {
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
    }
}

Tout ce que vous avez à faire est d'ajouter

LocaleHelper.onCreate(this, "en");

où vous voulez changer les paramètres régionaux.


LocaleHelper est une classe de l'article. Tous les liens risquent d'être supprimés. Veuillez ajouter le code dans votre réponse.
Zoé

Je ne veux pas redémarrer mon application car l'application fait une tâche comme l'écran d'enregistrement. donc sans redémarrer l'application, existe-t-il une solution pour Android 7.0
PriyankaChauhan

1
@PriyankaChauhan Je pense que l'article couvre ce cas: Vous avez deux options pour mettre à jour la mise en page actuellement visible: Tout d'abord , vous pouvez simplement mettre à jour le texte ou toute autre ressource dépendante de la langue une par une.
Maksim Turaev

merci d'avoir ajouté le nouveau createConfigurationContext, cela a été utile
jacoballenwood

1
onCreate ou onAttach pour appeler?
vanste25

12

Créer une classe Étend Applicationet crée une méthode statique. Vous pouvez ensuite appeler cette méthode dans toutes les activités précédentes setContentView().

public class MyApp extends Application {

@Override
public void onCreate() {
    super.onCreate();
}

public static void setLocaleFa (Context context){
    Locale locale = new Locale("fa"); 
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    context.getApplicationContext().getResources().updateConfiguration(config, null);
}

public static void setLocaleEn (Context context){
    Locale locale = new Locale("en_US"); 
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    context.getApplicationContext().getResources().updateConfiguration(config, null);
}

}

Utilisation dans les activités:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MyApp.setLocaleFa(MainActivity.this);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_main);
}

10

Pour Android 7.0 Nougat (et inférieur), suivez cet article:

Changer la langue par programme dans Android

Ancienne réponse
Cela inclut le support RTL / LTR:

public static void changeLocale(Context context, Locale locale) {
    Configuration conf = context.getResources().getConfiguration();
    conf.locale = locale;
    Locale.setDefault(locale);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
       conf.setLayoutDirection(conf.locale);
    }

    context.getResources().updateConfiguration(conf, context.getResources().getDisplayMetrics());
}

1
updateConfiguration est obsolète. Le lien est utile, veuillez l'ajouter à votre réponse. (Les réponses de lien uniquement ne sont pas bonnes, car le lien peut être supprimé. Si cela se produit, cette réponse est inutile)
Zoé

8

La seule solution qui fonctionne parfaitement pour moi est une combinaison du code d'Alex Volovoy avec le mécanisme de redémarrage de l'application:

void restartApplication() {
    Intent i = new Intent(MainTabActivity.context, MagicAppRestart.class);
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    MainTabActivity.context.startActivity(i);
}


/** This activity shows nothing; instead, it restarts the android process */
public class MagicAppRestart extends Activity {
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        finish();
    }

    protected void onResume() {
        super.onResume();
        startActivityForResult(new Intent(this, MainTabActivity.class), 0);         
    }
}

2
après le changement de lieu, vous pouvez également appeleractivity.recreate()
Pour Kra

1
Je ne veux pas redémarrer mon application car l'application fait une tâche comme l'écran d'enregistrement. donc sans redémarrer l'application, existe-t-il une solution pour Android 7.0
PriyankaChauhan

7

J'étais confronté au même problème. Sur GitHub, j'ai trouvé la bibliothèque Android-LocalizationActivity .

Cette bibliothèque facilite le changement de la langue de votre application au moment de l'exécution, comme vous pouvez le voir dans l'exemple de code ci-dessous. Un exemple de projet comprenant l'exemple de code ci-dessous et plus d'informations peuvent être trouvés sur la page github.

LocalizationActivity étend AppCompatActivity, vous pouvez donc également l'utiliser lorsque vous utilisez des fragments.

public class MainActivity extends LocalizationActivity implements View.OnClickListener {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);

        findViewById(R.id.btn_th).setOnClickListener(this);
        findViewById(R.id.btn_en).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_en) {
            setLanguage("en");
        } else if (id == R.id.btn_th) {
            setLanguage("th");
        }
    }
}

7

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.


1
Certains peuvent se demander si le contexte créé coûtera votre mémoire. Cependant, selon la documentation officielle Android: "Chaque appel à cette méthode renvoie une nouvelle instance d'un objet Context; les objets Context ne sont pas partagés, mais l'état commun (ClassLoader, d'autres ressources pour la même configuration) peut l'être afin que le contexte lui-même puisse être assez poids léger." Je pense donc qu'Android s'attend à ce que vous utilisiez un objet de contexte séparé pour les choses locales.
Sira Lam

7

Si vous écrivez

android:configChanges="locale"

Dans chaque activité (dans le fichier manifeste), pas besoin de le définir à chaque fois que vous entrez Activity.


11
Si c'est dans le manifeste, comment cela constitue-t-il un changement à l'exécution, qui semblait être ce que l'OP voulait?
user316117

1
@ user316117 Cela indique à Android que l'application traitera toutes les questions concernant la configuration locale en interne, et non que les paramètres régionaux sont statiques. Je ne sais pas si cela empêcherait Android de définir les paramètres régionaux lors du changement entre les activités, car je n'ai vu que configChangesutilisé pour un piratage pour préserver l'état d'activité lors des rotations / etc.
JAB

comment définir la langue uniquement pour l'anglais spécifique?
Kaveesh Kanwal

1
... jusqu'à ce qu'Android tue votre activité car elle a besoin de plus de RAM
Louis CAD

@Brijesh Si nous avons changé la langue de l'application, alors si nous avons une option de recherche dans l'application, et si nous recherchons dans cela, comment l'application affichera les données, devrions-nous développer une base de données différente pour chaque langue ou un paramètre de code Android est-il là pour cette application pourrait afficher des données en fonction de la recherche?
Vishwa Pratap

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

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

Mise à jour importante:

context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());

Notez que sur SDK> = 21, vous devez appeler «Resources.updateConfiguration ()» , sinon les ressources ne seront pas mises à jour.


updateConfiguration est obsolète. AFAIK vous utilisez createConfigurationContext et appliquez le contexte dont vous disposez ( Context ctx = createConfigurationContext(args);et obtenez des ressources de cela
Zoe

Je sais que c'est obsolète. Mais de toute façon, je ne connais aucune solution qui puisse fonctionner sur Android 5 et supérieur.
Максим Петлюк

Ensuite, vous n'avez clairement pas vérifié le javadoc. vous appelez le contexte créé à partir de createConfigurationContext
Zoé

D'accord, mais de toute façon, nous devrions appeler updateConfiguration (), non?
Максим Петлюк

1
N'utilisez pas l'appel obsolète. Signification pas de mise à jour d'appelConfiguration
Zoe

4
/*change language at Run-time*/
//use method like that:
//setLocale("en");
 public void setLocale(String lang) { 
  myLocale = new Locale(lang);         
  Resources res = getResources();         
  DisplayMetrics dm = res.getDisplayMetrics();         
  Configuration conf = res.getConfiguration();         
  conf.locale = myLocale;         
  res.updateConfiguration(conf, dm);         
  Intent refresh = new Intent(this, AndroidLocalize.class);         
  startActivity(refresh); 
 }

5
pas besoin de commencer une nouvelle activité, il suffit de rafraîchir l'actuelactivity.recreate()
Pour Kra

4

Locale configurationdoit être défini dans chacun activityavant de définir le contenu -this.setContentView(R.layout.main);


Mais que faire si vous souhaitez le basculer à la volée, après l'appel de setContentView ()?
IgorGanapolsky

2
après le changement de lieu, vous pouvez également appeleractivity.recreate()
Pour Kra

4

Créez d'abord multi string.xml pour différentes langues; puis utilisez ce bloc de code dans la onCreate()méthode:

super.onCreate(savedInstanceState);
String languageToLoad  = "fr"; // change your language here
Locale locale = new Locale(languageToLoad); 
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, 
  getBaseContext().getResources().getDisplayMetrics());
this.setContentView(R.layout.main);

Merci, ce code fonctionne très bien, j'ai testé sur Android 5.x et 6.x sans aucun problème
innovaciones

4

Voici un code qui fonctionne pour moi:

public class  MainActivity extends AppCompatActivity {
    public static String storeLang;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        SharedPreferences shp = PreferenceManager.getDefaultSharedPreferences(this);
        storeLang = shp.getString(getString(R.string.key_lang), "");

        // Create a new Locale object
        Locale locale = new Locale(storeLang);

        // Create a new configuration object
        Configuration config = new Configuration();
        // Set the locale of the new configuration
        config.locale = locale;
        // Update the configuration of the Accplication context
        getResources().updateConfiguration(
                config,
                getResources().getDisplayMetrics()
        );

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

Source: ici


3

Aucune des solutions énumérées ici ne m'a aidé.

La langue n'a pas activé Android> = 7.0 si AppCompatDelegate.setDefaultNightMode (AppCompatDelegate.MODE_NIGHT_YES)

Ce LocaleUtils fonctionne très bien: https://gist.github.com/GigigoGreenLabs/7d555c762ba2d3a810fe

LocaleUtils

public class LocaleUtils {

public static final String LAN_SPANISH      = "es";
public static final String LAN_PORTUGUESE   = "pt";
public static final String LAN_ENGLISH      = "en";

private static Locale sLocale;

public static void setLocale(Locale locale) {
    sLocale = locale;
    if(sLocale != null) {
        Locale.setDefault(sLocale);
    }
}

public static void updateConfig(ContextThemeWrapper wrapper) {
    if(sLocale != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        Configuration configuration = new Configuration();
        configuration.setLocale(sLocale);
        wrapper.applyOverrideConfiguration(configuration);
    }
}

public static void updateConfig(Application app, Configuration configuration) {
    if(sLocale != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
        //Wrapping the configuration to avoid Activity endless loop
        Configuration config = new Configuration(configuration);
        config.locale = sLocale;
        Resources res = app.getBaseContext().getResources();
        res.updateConfiguration(config, res.getDisplayMetrics());
    }
}
}

Ajout de ce code à l'application

public class App extends Application {
public void onCreate(){
    super.onCreate();

    LocaleUtils.setLocale(new Locale("iw"));
    LocaleUtils.updateConfig(this, getBaseContext().getResources().getConfiguration());
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    LocaleUtils.updateConfig(this, newConfig);
}
}

Code en activité

public class BaseActivity extends AppCompatActivity {
    public BaseActivity() {
        LocaleUtils.updateConfig(this);
    }
}

2

La réponse d'Alex Volovoy ne fonctionne pour moi que si elle est dans la méthode onCreate de l'activité.

La réponse qui fonctionne dans toutes les méthodes est dans un autre thread

Changer la langue par programme dans Android

Voici l'adaptation du code



    Resources standardResources = getBaseContext().getResources();

    AssetManager assets = standardResources.getAssets();

    DisplayMetrics metrics = standardResources.getDisplayMetrics();

    Configuration config = new Configuration(standardResources.getConfiguration());

    config.locale = new Locale(languageToLoad);

    Resources defaultResources = new Resources(assets, metrics, config);

J'espère que ça aide.


19
Vous avez dit "La réponse qui fonctionne dans toutes les méthodes est dans un autre fil" mais votre lien pointe vers CE fil! "
user316117

1
config.locale est obsolète
Zoé

2
réponse récursive, possible de StackOverflow
tamtom

2

Notez que cette solution utilisant updateConfiguration ne fonctionnera plus avec la sortie d' Android M dans quelques semaines. La nouvelle façon de procéder consiste maintenant à utiliser la applyOverrideConfigurationméthodeContextThemeWrapper voir le document API

Vous pouvez trouver ma solution complète ici puisque j'ai moi-même fait face au problème: https://stackoverflow.com/a/31787201/2776572


J'essaie le code updateConfiguration sur Android 6.0.1 et cela fonctionne bien, je ne sais pas si Google a corrigé cela mais je peux l'utiliser sans problème
innovaciones

1
@innovaciones méthodes obsolètes existent depuis un certain temps. Finalement, il sera supprimé. Cela prend beaucoup de temps, mais il est préférable de passer aux nouvelles API dès que possible pour éviter les problèmes sur le long terme
Zoe

1

Il y a quelques étapes que vous devez implémenter

Tout d'abord, vous devez modifier les paramètres régionaux de votre configuration

Resources resources = context.getResources();

Configuration configuration = resources.getConfiguration();
configuration.locale = new Locale(language);

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

Deuxièmement, si vous souhaitez que vos modifications s'appliquent directement à la présentation visible, vous pouvez soit mettre à jour les vues directement, soit appeler simplement activity.recreate () pour redémarrer l'activité en cours.

Et vous devez également persister vos modifications car après que l'utilisateur ferme votre application, vous perdriez le changement de langue.

J'ai expliqué la solution plus détaillée sur mon article de blog Changer de langue par programme dans Android

Fondamentalement, vous appelez simplement LocaleHelper.onCreate () sur votre classe d'application et si vous souhaitez modifier les paramètres régionaux à la volée, vous pouvez appeler LocaleHelper.setLocale ()


@LunarWatcher Oui, si vous vérifiez réellement le code sur github ou gist, il est déjà géré.
Gunhan

1

Cela fonctionne lorsque j'appuie sur le bouton pour changer la langue du texte de mon TextView. (Strings.xml dans le dossier values-de)

String languageToLoad = "de"; // your language
Configuration config = getBaseContext().getResources().getConfiguration();
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
recreate();

1

Ajouter une classe LocaleHelper

public class LocaleHelper{ 
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) {
    String lang = getPersistedData(context, Locale.getDefault().getLanguage());
    return setLocale(context, lang);
}

public static Context onAttach(Context context, String defaultLanguage) {
    String lang = getPersistedData(context, defaultLanguage);
    return setLocale(context, lang);
}

public static String getLanguage(Context context) {
    return getPersistedData(context, Locale.getDefault().getLanguage());
}
public static Context setLocale(Context context, String language) {
    persist(context, language);

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

    return updateResourcesLegacy(context, language);
}

private static String getPersistedData(Context context, String defaultLanguage) {
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
    return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}

private static void persist(Context context, String language) {
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
    SharedPreferences.Editor editor = preferences.edit();

    editor.putString(SELECTED_LANGUAGE, language);
    editor.apply();
}

@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
    Locale locale = new Locale(language);
    Locale.setDefault(locale);

    Configuration configuration = context.getResources().getConfiguration();
    configuration.setLocale(locale);
    configuration.setLayoutDirection(locale);

    return context.createConfigurationContext(configuration);
}

@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
    Locale locale = new Locale(language);
    Locale.setDefault(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;
}
}

En activité ou fragment

Context context = LocaleHelper.setLocale(this, App.getSharedPre().getLanguage());
Resource resources = context.getResources();

Maintenant, placezText sur chaque texte

TextView tv = findViewById(R.id.tv);
tv.setText(resources.getString(R.string.tv));

0

similaire à la version acceptée, mais avec réponse 2017 et redémarrage ajouté (sans redémarrage, parfois la prochaine activité s'affiche toujours en anglais):

// Inside some activity...
private void changeDisplayLanguage(String langCode) {
// Step 1. Change the locale in the app's configuration
    Resources res = getResources();
    android.content.res.Configuration conf = res.getConfiguration();
    conf.setLocale(currentLocale);
    createConfigurationContext(conf);
// Step 2. IMPORTANT! you must restart the app to make sure it works 100%
    restart();
}
private void restart() {
    PackageManager packageManager = getPackageManager();
    Intent intent = packageManager.getLaunchIntentForPackage(getPackageName());
    ComponentName componentName = intent.getComponent();
    Intent mainIntent = IntentCompat.makeRestartActivityTask(componentName);
    mainIntent.putExtra("app_restarting", true);
    PrefUtils.putBoolean("app_restarting", true);
    startActivity(mainIntent);
    System.exit(0);
}

1) utilisez finish () à la place 2) pour redémarrer l'application que vous pouvez utiliser activity.recreate()3) le contexte retourné doit être utilisé pour obtenir les ressources
Zoe

Je ne veux pas redémarrer mon application car l'application fait une tâche comme l'écran d'enregistrement. donc sans redémarrer l'application existe-t-il une solution pour Android 7.0
PriyankaChauhan

0

D'abord, vous créez des valeurs de nom de répertoire - "Nom de langue" comme hindi que vous écrivez "salut" et la même copie de nom de fichier de chaîne dans ce répertoire et changez la valeur ne changez pas le paramètre après avoir défini le code ci-dessous dans votre action comme le bouton, etc.

Locale myLocale = new Locale("hi");
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
Intent refresh = new Intent(Home.this, Home.class);
startActivity(refresh);
finish(); 

1
conf.localeest obsolète
Zoé

0
private void setLanguage(String language) {
    Locale locale = new Locale(language);
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        config.setLocale(locale);
    } else {
        config.locale = locale;
    }
    getResources().updateConfiguration(config,
            getResources().getDisplayMetrics());

}

1
Je ne veux pas redémarrer mon application car l'application fait une tâche comme l'écran d'enregistrement. donc sans redémarrer l'application, existe-t-il une solution pour Android 7.0
PriyankaChauhan

oui sur 6.0 cela fonctionne bien pour moi, sans redémarrer l'application, la langue a changé, mais je n'ai pas testé sur 7.0
Adeeb karim

0

Dans l'exemple, nous définissons la langue anglaise:

 Configuration config = GetBaseContext().getResources().getConfiguration();
 Locale locale = new Locale("en");
 Locale.setDefault(locale);
 config.locale = locale;
 GetBaseContext().getResources().updateConfiguration(config, 
            GetBaseContext().getResources().getDisplayMetrics());

N'oubliez pas que cela ne fonctionne que si la langue se trouve également dans le système de l'appareil, pas seulement dans l'application


0

Pour la prise en charge de l'arabe / RTL

  1. Vous devez mettre à jour vos paramètres de langue via - attachBaseContext ()
  2. Pour la version Android N et supérieure, vous devez utiliser createConfigurationContext () & updateConfiguration () - sinon la disposition RTL ne fonctionne pas correctement

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

    public Context updateBaseContextLocale(Context context) {
        String language = SharedPreference.getInstance().getValue(context, "lan");//it return "en", "ar" like this
        if (language == null || language.isEmpty()) {
            //when first time enter into app (get the device language and set it
            language = Locale.getDefault().getLanguage();
            if (language.equals("ar")) {
                SharedPreference.getInstance().save(mContext, "lan", "ar");
            }
        }
        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            updateResourcesLocale(context, locale);
            return  updateResourcesLocaleLegacy(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;
    }

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.