195 votes

Changer de localité dans l'application elle-même

Mes utilisateurs peuvent changer de localité dans l'application (ils peuvent vouloir conserver les paramètres de leur téléphone en anglais mais lire le contenu de mon application en français, en néerlandais ou dans une autre langue...).

Pourquoi cela fonctionne-t-il parfaitement bien dans les versions 1.5/1.6 mais PAS dans la version 2.0 ?

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch(item.getItemId()) {
    case 201:
        Locale locale2 = new Locale("fr"); 
        Locale.setDefault(locale2);
        Configuration config2 = new Configuration();
        config2.locale = locale2;
        getBaseContext().getResources().updateConfiguration(
            config2, getBaseContext().getResources().getDisplayMetrics());
        // loading data ...
        refresh();
        // refresh the tabs and their content
        refresh_Tab ();   
     break;
     case 201: etc...

Le problème est que le MENU "rétrécit" de plus en plus à chaque fois que l'utilisateur parcourt les lignes de code ci-dessus ...

C'est le menu qui se rétrécit :

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    menu.add(0, 100, 1, "REFRESH").setIcon(android.R.drawable.ic_menu_compass);
    SubMenu langMenu = menu.addSubMenu(0, 200, 2, "NL-FR").setIcon(android.R.drawable.ic_menu_rotate);
        langMenu.add(1, 201, 0, "Nederlands");
        langMenu.add(1, 202, 0, "Français");
    menu.add(0, 250, 4, R.string.OptionMenu2).setIcon(android.R.drawable.ic_menu_send);
    menu.add(0, 300, 5, R.string.OptionMenu3).setIcon(android.R.drawable.ic_menu_preferences);
    menu.add(0, 350, 3, R.string.OptionMenu4).setIcon(android.R.drawable.ic_menu_more);
    menu.add(0, 400, 6, "Exit").setIcon(android.R.drawable.ic_menu_delete);

    return super.onCreateOptionsMenu(menu);
}

Que dois-je faire dans l'API Level 5 pour que cela fonctionne à nouveau ?

VOICI LE CODE COMPLET SI VOUS VOULEZ LE TESTER :

import java.util.Locale;

import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.widget.Toast;

public class Main extends Activity {
    /** Called when the activity is first created. */

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

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        SubMenu langMenu = menu.addSubMenu(0, 200, 2, "NL-FR").setIcon(android.R.drawable.ic_menu_rotate);
            langMenu.add(1, 201, 0, "Nederlands");
            langMenu.add(1, 202, 0, "Français");

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()){

        case 201:

            Locale locale = new Locale("nl"); 
            Locale.setDefault(locale);
            Configuration config = new Configuration();
            config.locale = locale;
            getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
            Toast.makeText(this, "Locale in Nederlands !", Toast.LENGTH_LONG).show();
            break;

        case 202:

            Locale locale2 = new Locale("fr"); 
            Locale.setDefault(locale2);
            Configuration config2 = new Configuration();
            config2.locale = locale2;
            getBaseContext().getResources().updateConfiguration(config2, getBaseContext().getResources().getDisplayMetrics());

            Toast.makeText(this, "Locale en Français !", Toast.LENGTH_LONG).show();
            break;  

        }
        return super.onOptionsItemSelected(item);
    }
}

ET VOICI LE MANIFESTE :

<?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.cousinHub.ChangeLocale"
          android:versionCode="1"
          android:versionName="1.0">
        <application android:icon="@drawable/icon" android:label="@string/app_name">
            <activity android:name=".Main"
                      android:label="@string/app_name">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
        <uses-sdk android:minSdkVersion="3" /> 
    </manifest>

C'EST CE QUE J'AI TROUVÉ :

<uses-sdk android:minSdkVersion="5" />

\=> CELA FONCTIONNE TRÈS BIEN ...

<uses-sdk android:minSdkVersion="3" />

\=> Le menu rétrécit à chaque fois que l'on change de locale ! !!

Comme je veux garder mon application accessible aux utilisateurs de la version 1.5, que dois-je faire ?

148voto

Andrey Novikov Points 2607

Bien que la question originale ne concerne pas exactement la locale elle-même, toutes les autres questions relatives à la locale font référence à celle-ci. C'est pourquoi je voulais clarifier le problème ici. J'ai utilisé cette question comme point de départ pour mon propre code de changement de locale et j'ai découvert que la méthode n'est pas exactement correcte. Elle fonctionne, mais seulement jusqu'à un changement de configuration (par exemple, la rotation de l'écran) et seulement dans cette activité particulière. En jouant avec un code pendant un certain temps, j'ai fini par adopter l'approche suivante :

J'ai étendu Android.app.Application et ajouté le code suivant :

public class MyApplication extends Application
{
    private Locale locale = null;

    @Override
    public void onConfigurationChanged(Configuration newConfig)
    {
        super.onConfigurationChanged(newConfig);
        if (locale != null)
        {
            newConfig.locale = locale;
            Locale.setDefault(locale);
            getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics());
        }
    }

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

        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);

        Configuration config = getBaseContext().getResources().getConfiguration();

        String lang = settings.getString(getString(R.string.pref_locale), "");
        if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang))
        {
            locale = new Locale(lang);
            Locale.setDefault(locale);
            config.locale = locale;
            getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
        }
    }
}

Ce code garantit que chaque activité aura une locale personnalisée et qu'elle ne sera pas réinitialisée lors de la rotation et d'autres événements.

J'ai également passé beaucoup de temps à essayer de faire en sorte que le changement de préférence soit appliqué immédiatement, mais sans succès : la langue a changé correctement au redémarrage de l'activité, mais les formats de chiffres et les autres propriétés de la locale n'ont pas été appliqués avant le redémarrage complet de l'application.

Changements apportés à AndroidManifest.xml

N'oubliez pas d'ajouter android:configChanges="layoutDirection|locale" à chaque activité d'AndroidManifest, ainsi que la android:name=".MyApplication" à la <application> élément.

61voto

Hubert Points 3461

Après une bonne nuit de sommeil, j'ai trouvé la réponse sur le Web (une simple recherche Google sur la ligne suivante " getBaseContext().getResources().updateConfiguration(mConfig, getBaseContext().getResources().getDisplayMetrics()); "), le voici :

texte du lien \=> ce lien montre également screenshots de ce qui se passe !

La densité était le problème ici j'avais besoin d'avoir ceci dans le AndroidManifest.xml

<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true"
/>

Le plus important est le Android:anyDensity =" true " .

N'oubliez pas d'ajouter les éléments suivants dans le fichier AndroidManifest.xml pour chaque activité (pour Android 4.1 et inférieur) :

android:configChanges="locale"

Cette version est nécessaire lorsque vous construisez pour Android 4.2 (niveau 17 de l'API). explication ici :

android:configChanges="locale|layoutDirection"

10voto

trgraglia Points 3196

C'est pour mon commentaire sur la réponse d'Andrey mais je ne peux pas inclure le code dans les commentaires.

Votre activité préférée est-elle appelée à partir de votre activité principale ? Vous pourriez placer cette activité dans le...

@Override
protected void onResume() {
    if (!(PreferenceManager.getDefaultSharedPreferences(
            getApplicationContext()).getString("listLanguage", "en")
            .equals(langPreference))) {
        refresh();
    }
    super.onResume();
}

private void refresh() {
    finish();
    Intent myIntent = new Intent(Main.this, Main.class);
    startActivity(myIntent);
}

6voto

kape123 Points 6369

Je ne pouvais pas utiliser Android:anyDensity="true" car les objets de mon jeu auraient été positionnés de manière complètement différente... il semble que cela fasse également l'affaire :

// creating locale
Locale locale2 = new Locale(loc); 
Locale.setDefault(locale2);
Configuration config2 = new Configuration();
config2.locale = locale2;

// updating locale
mContext.getResources().updateConfiguration(config2, null);

1voto

Ramesh Points 3483

Si vous souhaitez que les options du menu vous permettent de modifier immédiatement la langue, vous devez procéder comme suit.

//onCreate method calls only once when menu is called first time.
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    //1.Here you can add your  locale settings . 
    //2.Your menu declaration.
}
//This method is called when your menu is opend to again....
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
    menu.clear();
    onCreateOptionsMenu(menu);
    return super.onMenuOpened(featureId, menu);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X