572 Stimmen

App-Sprache in Android programmatisch ändern

Ist es möglich, die Sprache einer App programmatisch zu ändern und dabei weiterhin Android-Ressourcen zu verwenden?

Wenn nicht, ist es möglich, eine Ressource in einer bestimmten Sprache anzufordern?

Ich möchte, dass der Benutzer die Sprache der App von der App aus ändern kann.

16voto

triggs Punkte 5730

Ich füge nur ein zusätzliches Element hinzu, das mich gestört hat.

Während die anderen Antworten mit "de" gut funktionieren, zum Beispiel

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());

Das obige funktioniert zum Beispiel nicht mit "fr_BE" Gebietsschema, so dass es die values-fr-rBE Ordner oder ähnliches.

Die folgende kleine Änderung ist erforderlich, um mit "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());

16voto

Behzad Taghipour Punkte 151

Eine Klasse erstellen Erweitert Application und erstellen Sie eine statische Methode. Dann können Sie diese Methode in allen Aktivitäten aufrufen, bevor 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);
}

}

Verwendung bei Aktivitäten:

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

15voto

harikrishnan Punkte 2135

Ich habe die deutsche Sprache für meinen App-Start selbst geändert.

Hier ist mein korrekter Code. Möchte jemand das gleiche für mich verwenden (Wie man die Sprache in Android programmatisch ändert)

mein 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);
}

14voto

Anirudh Sharma Punkte 7918

Ich weiß, es ist spät für eine Antwort, aber ich fand dieser Artikel hier . Das erklärt den gesamten Prozess sehr gut und liefert Ihnen einen gut strukturierten Code.

Locale Helper Klasse:

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;
    }
}

Sie müssen attachBaseContext außer Kraft setzen und LocaleHelper.onAttach() aufrufen, um die Gebietsschemaeinstellungen in Ihrer Anwendung zu initialisieren.

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"));
    }
}

Alles, was Sie tun müssen, ist Folgendes hinzuzufügen

LocaleHelper.onCreate(this, "en");

wo immer Sie das Gebietsschema ändern möchten.

12voto

Zeit für ein fälliges Update.

Zunächst einmal die Liste der veralteten Produkte mit der API, in der sie veraltet sind:

  • configuration.locale (API 17)
  • updateConfiguration(configuration, displaymetrics) (API 17)

Was in keiner der kürzlich beantworteten Fragen richtig beantwortet wurde, ist die Anwendung der neuen Methode .

createConfigurationContext ist die neue Methode für updateConfiguration.

Einige haben es als eigenständiges Produkt verwendet:

Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);

... aber das funktioniert nicht. Und warum? Die Methode gibt einen Kontext zurück, der dann verwendet wird, um Strings.xml-Übersetzungen und andere lokalisierte Ressourcen (Bilder, Layouts, was auch immer) zu behandeln.

Die korrekte Verwendung ist wie folgt:

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();

Wenn Sie das einfach in Ihre IDE kopieren, sehen Sie möglicherweise eine Warnung, dass die API API 17 oder höher erfordert. Dies kann umgangen werden, indem man es in eine Methode einfügt und die Anmerkung hinzufügt @TargetApi(17)

Aber halt. Was ist mit den älteren APIs?

Sie müssen eine andere Methode mit updateConfiguration ohne die TargetApi-Annotation erstellen.

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);

Sie müssen hier keinen Kontext zurückgeben.

Diese zu verwalten, kann schwierig sein. In API 17+ benötigen Sie den erstellten Kontext (oder die Ressourcen aus dem erstellten Kontext), um die entsprechenden Ressourcen auf der Grundlage der Lokalisierung zu erhalten. Wie handhaben Sie das?

Nun, ich mache es folgendermaßen:

/**
 * Full locale list: https://stackoverflow.com/questions/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;
}

Dieser Code funktioniert mit einer Methode, die je nach API die entsprechende Methode aufruft. Dies ist etwas, das ich mit vielen verschiedenen veralteten Aufrufen gemacht habe (einschließlich Html.fromHtml). Sie haben eine Methode, die die benötigten Argumente aufnimmt, die dann in eine von zwei (oder drei oder mehr) Methoden aufgeteilt wird und das entsprechende Ergebnis auf der Grundlage der API-Ebene zurückgibt. Es ist flexibel, da Sie nicht mehrfach prüfen müssen, sondern die "entry"-Methode dies für Sie erledigt. Die "entry"-Methode ist hier setLanguage

BITTE LESEN SIE DIES, BEVOR SIE ES BENUTZEN

Sie müssen den zurückgegebenen Kontext verwenden, wenn Sie Ressourcen erhalten. Warum? Ich habe hier andere Antworten gesehen, die createConfigurationContext verwenden und den zurückgegebenen Kontext nicht nutzen. Damit es so funktioniert, muss updateConfiguration aufgerufen werden. Das ist veraltet. Verwenden Sie den von der Methode zurückgegebenen Kontext, um Ressourcen zu erhalten.

Beispiel für die Verwendung :

Constructor oder etwas Ähnliches:

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)

Und dann, wo immer Sie Ressourcen erhalten wollen, tun Sie es:

String fromResources = ctx.getString(R.string.helloworld);

Die Verwendung eines anderen Kontextes würde dies (theoretisch) zunichte machen.

AFAIK müssen Sie immer noch einen Aktivitätskontext verwenden, um Dialoge oder Toasts anzuzeigen. dafür können Sie eine Instanz einer Aktivität verwenden (wenn Sie außerhalb sind)


Und schließlich, verwenden Sie recreate() auf die Aktivität, um den Inhalt zu aktualisieren. Abkürzung, um keine Absicht zur Aktualisierung erstellen zu müssen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X