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.

458voto

Alex Volovoy Punkte 66760

Das ist möglich. Sie können das Gebietsschema einstellen. Ich würde das aber nicht empfehlen. Wir haben es in frühen Stadien ausprobiert, es ist im Grunde ein Kampf gegen das System.

Wir haben die gleiche Anforderung, die Sprache zu ändern, haben uns aber dafür entschieden, dass die Benutzeroberfläche mit der des Telefons übereinstimmen sollte. Es funktionierte über die Einstellung des Gebietsschemas, war aber zu fehleranfällig. Außerdem muss man es meiner Erfahrung nach jedes Mal einstellen, wenn man eine Aktivität aufruft (jede Aktivität).

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

Wenn Sie sprachspezifische Inhalte haben, können Sie diese anhand der Einstellungen ändern.


Aktualisierung am 26. März 2020

    public static void setLocale(Activity activity, String languageCode) {
        Locale locale = new Locale(languageCode);
        Locale.setDefault(locale);
        Resources resources = activity.getResources();
        Configuration config = resources.getConfiguration();
        config.setLocale(locale);
        resources.updateConfiguration(config, resources.getDisplayMetrics());
    }
  • HINWEISE: Der Sprachcode darf kein '-' enthalten und darf nur aus 2 Kleinbuchstaben bestehen.

228voto

AliSh Punkte 9539

Dieser Code funktioniert wirklich:

fa = Persisch, en = Englisch

  • ANMERKUNGEN: Der Sprachcode darf kein '-' enthalten und darf nur aus 2 Kleinbuchstaben bestehen.

Geben Sie Ihren Sprachcode in languageToLoad variabel:

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

UPDATE am Juni 2021(Kotlin):

class Main : Activity() {
    // Called when the activity is first created.
    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val config = resources.configuration
        val lang = "fa" // your language code
        val locale = Locale(lang)
        Locale.setDefault(locale)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
            config.setLocale(locale)
        else
            config.locale = locale

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
            createConfigurationContext(config)
        resources.updateConfiguration(config, resources.displayMetrics)

        this.setContentView(R.layout.main)
    }
}

39voto

icyerasor Punkte 4583

Ich war auf der Suche nach einer Möglichkeit, die Systemsprache programmatisch zu ändern. Während ich völlig verstehen, dass eine normale Anwendung sollte nie tun, und stattdessen entweder:

  • der Benutzer sollte (über eine Absichtserklärung) auf die Systemeinstellungen verwiesen werden, um sie manuell zu ändern
  • die Anwendung sollte die Lokalisierung selbst übernehmen, so wie in der Antwort von Alex beschrieben

Es bestand die Notwendigkeit, die Sprache des Systems programmtechnisch zu ändern.

Dies ist eine undokumentierte API und sollte daher nicht für Markt-/Endbenutzeranwendungen verwendet werden!

Wie auch immer, hier ist die Lösung, die ich gefunden habe:

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

36voto

Daniel S. Punkte 2469

Wenn Sie die geänderte Sprache in Ihrer gesamten Anwendung beibehalten wollen, müssen Sie zwei Dinge tun.

Erstellen Sie zunächst eine Basisaktivität und lassen Sie alle Ihre Aktivitäten von dieser ausgehen:

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

Beachten Sie, dass ich die neue Sprache in einer sharedPreference speichere.

Zweitens: Erstellen Sie eine Erweiterung von Application wie diese:

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

Beachten Sie, dass getLocale() dasselbe ist wie oben.

Das war's schon! Ich hoffe, das kann jemandem helfen.

27voto

Khaled Lela Punkte 6697

Nach Angaben von dieser Artikel . Sie müssen Folgendes herunterladen LocaleHelper.java auf die in diesem Artikel verwiesen wird.

  1. erstellen. MyApplication Klasse, die die Application

  2. Überschreiben Sie attachBaseContext() um die Sprache zu aktualisieren.

  3. Registrieren Sie diese Klasse in manifest.

    public class MyApplication extends Application {
       @Override
       protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
       }
    }
    
    <application
         android:name="com.package.MyApplication"
         .../>
  4. erstellen. BaseActivity und außer Kraft setzen onAttach() um die Sprache zu aktualisieren. Benötigt für Android 6+

    public class BaseActivity extends Activity {
      @Override
      protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base));
      }
    }
  5. Alle Aktivitäten auf Ihrer App erstrecken sich von 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;
    }
    }

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