Wie ändere ich die Sprache der App, wenn der Benutzer die Sprache auswählt?

106

Ich möchte, dass meine App drei Sprachen unterstützt: Spanisch, Portugiesisch und Englisch. Und geben Sie die Option, Sprache in App auszuwählen. Ich habe gemacht

1) 3 zeichnbare Ordner drawable-es, drawable-pt, drawable.

2) 3 Werte Ordnerwerte-es, Werte-pt, Werte. Ändern Sie die String.xml-Werte nach Sprachen.

Ich habe imageView, um die Sprache auszuwählen. Wenn Sie darauf klicken, öffnen Sie das Menü, das aus der Option Englisch, Spanisch, Portugiesisch besteht.

Ich habe das Gebietsschema in der App bei der Auswahl der Optionen anhand dieses Codes festgelegt

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.en:
             Locale locale = new Locale("en"); 
             Locale.setDefault(locale);
             Configuration config = new Configuration();
             config.locale = locale;
             getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
             Toast.makeText(this, "Locale in English !", Toast.LENGTH_LONG).show();
             break;

        case R.id.pt:
             Locale locale2 = new Locale("pt"); 
             Locale.setDefault(locale2);
             Configuration config2 = new Configuration();
             config2.locale = locale2;
             getBaseContext().getResources().updateConfiguration(config2, getBaseContext().getResources().getDisplayMetrics());

             Toast.makeText(this, "Locale in Portugal !", Toast.LENGTH_LONG).show();
             break;

        case R.id.es:
             Locale locale3 = new Locale("es"); 
             Locale.setDefault(locale3);
             Configuration config3 = new Configuration();
             config3.locale = locale3;
             getBaseContext().getResources().updateConfiguration(config3, getBaseContext().getResources().getDisplayMetrics());

             Toast.makeText(this, "Locale in Spain !", Toast.LENGTH_LONG).show();
             break;     
    }
    return super.onOptionsItemSelected(item);
}

Ich habe in Manifest- Android deklariert : configChanges = "locale"

Es funktioniert, aber es gibt ein Problem.

Problem:-

1) Wenn die Sprache ausgewählt ist, ändert sich der Bildschirm, der aus dem Bild der Sprachauswahl besteht, nicht, aber andere Bildschirme ändern sich.

2) Nach dem Ausrichten ändern Sie die App-Wiederherstellungssprache entsprechend dem Gebietsschema des Telefons.

Mukesh
quelle
1
Für das 2. Problem versuchen Sie hinzuzufügen: android:configChanges="locale"für Ihre Aktivität in der AndroidManifest.xml
Parth Doshi
Ich habe bereits jede Aktivität in meinem Manifest hinzugefügt.
Mukesh
Sie können die folgende Bibliothek verwenden, die die Sprachliste und die Einstellungen für Ihren Einstellungsbildschirm bereitstellt und die Sprache in Ihrer Anwendung überschreibt: github.com/delight-im/Android-Languages
caw

Antworten:

171

Es ist ein Auszug für die Webseite: http://android.programmerguru.com/android-localization-at-runtime/

Es ist einfach, die Sprache Ihrer App zu ändern, wenn der Benutzer sie aus der Liste der Sprachen auswählt. Verwenden Sie eine Methode wie die folgende, die das Gebietsschema als Zeichenfolge akzeptiert (z. B. 'en' für Englisch, 'hi' für Hindi), konfigurieren Sie das Gebietsschema für Ihre App und aktualisieren Sie Ihre aktuelle Aktivität, um die Änderung der Sprache widerzuspiegeln. Das von Ihnen angewendete Gebietsschema wird erst geändert, wenn Sie es erneut manuell ändern.

public void setLocale(String lang) { 
    Locale 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); 
    finish();
    startActivity(refresh); 
} 

Stellen Sie sicher, dass Sie folgende Pakete importiert haben:

import java.util.Locale; 
import android.os.Bundle; 
import android.app.Activity; 
import android.content.Intent; 
import android.content.res.Configuration; 
import android.content.res.Resources; 
import android.util.DisplayMetrics; 

In Manifest zur Aktivität hinzufügen Android: configChanges = "Gebietsschema | Orientierung"

Udhay
quelle
2
Ja sicher. Ich kann den Auszug der Webseite zur Verfügung stellen. Wo ich angeben muss, lassen Sie es mich bitte wissen. Vielen Dank.
Udhay
3
Stellen Sie sicher, dass Sie finish () hinzufügen, damit Sie nicht zwei Kopien Ihrer Aktivität im Navigationsstapel haben.
Joel Teply
6
finish()muss vorher angerufen werden startActivity(refresh). Andernfalls wird die App möglicherweise beendet, anstatt dass die Aktivität neu gestartet wird.
Mohammed Ali
10
Hallo, ich habe es getan, es funktioniert, aber wenn ich die App neu
starte
5
Konfiguration config = neue Konfiguration (newConfig); config.locale = locale; In meinem Fall bekomme ich diese Nachricht. Gebietsschema in API-Level 25
Milon
9

Gute Lösungen werden hier ziemlich gut erklärt. Aber hier ist noch einer.

Erstellen Sie eine eigene CustomContextWrapperKlassenerweiterung ContextWrapperund ändern Sie damit die Gebietsschemaeinstellung für die gesamte Anwendung. Hier ist ein GIST mit Verwendung.

Rufen Sie dann die CustomContextWrappermit gespeicherte Gebietsschema-ID auf, z. B. 'hi'für die Hindi-Sprache in der Aktivitätslebenszyklusmethode attachBaseContext. Verwendung hier:

@Override
protected void attachBaseContext(Context newBase) {
    // fetch from shared preference also save the same when applying. Default here is en = English
    String language = MyPreferenceUtil.getInstance().getString("saved_locale", "en");
    super.attachBaseContext(MyContextWrapper.wrap(newBase, language));
}
sud007
quelle
Vielen Dank für den Link, der funktioniert, aber ich habe ein paar Dinge nicht verstanden. Ich habe nur das MyContextWrapper.warpIn onAttachvon nur einem Fragment meiner App aufgerufen, aber die Sprache wurde für die gesamte App geändert, aber die Aktivitätstitel wurden nicht geändert, glaube ich Das liegt daran, dass die Manifesttitel Vorrang haben, aber wenn ich dieselbe Methode in onAttachBaseContexmeiner Unterklasse der Anwendung aufrufe, ändern sich die Aktivitätstitel auch in die ausgewählte Sprache, aber dann werden die Änderungen nur auf das Fragment angewendet, das ich in der Warp-Methode aufgerufen habe. Warum ist das so? ?
Abhinav Chauhan
@AbhinavChauhan Ich bin mir nicht sicher, ob dies wahr ist. Ich muss das überprüfen. Ich habe dieses Problem bei der Implementierung dieser Lösung noch nie gesehen. Es ist jedoch lange her und es kann einige Änderungen in der Android-Implementierung für neuere Versionen geben. Alternativ können Sie einige der neuesten Antworten in diesem Beitrag ausprobieren.
sud007
Ich habe viele Lösungen ausprobiert, aber keine von ihnen hat funktioniert oder ich habe sie falsch implementiert. Vielleicht funktioniert Ihre Klasse gut mit Aktivitäten. Ich verwende die warpMethode in onAttachdem Fragment. Zuvor habe ich gesagt, ich muss sie nur mit dem Hauptaktivitätsfragment und der geänderten Sprache ausführen Die gesamte App ist wahr, aber für alle anderen Fragmente ändert sich die Sprache bei Konfigurationsänderungen in Englisch, sodass ich onattachalle Fragmente einfügen muss. Statt zu manifestieren, setze ich die Titel der Aktionsleiste in Code. Jetzt funktioniert die App wie erwartet. danke
Abhinav Chauhan
In Ordnung! Ich bin sicher, dass Sie dies nicht für jeden Bildschirm tun müssen, sondern nur für die erste Aktivität, die gestartet wird, und attachBaseContextnur für die Funktion. Und das für alle Bildschirme. Haben Sie eine "BaseActivity" für alle Aktivitäten in Ihrer App erstellt?
sud007
Nein, ich habe versucht, dies in meiner Unterklasse der Anwendung zu tun, da ich dachte, dass es auf die gesamte Anwendung und dann auf alle Fragmente angewendet wird, aber es stellt sich heraus, dass der wrap()Code bei jeder Konfigurationsänderung ausgeführt werden muss, also habe ich ihn in die Abstrakte Aktivität, von der sich alle anderen Aktivitäten erstrecken, jetzt funktioniert sie
Abhinav Chauhan
6

Sie sollten entweder android:configChanges="locale"aus dem Manifest entfernen , wodurch die Aktivität neu geladen wird, oder die onConfigurationChangedMethode überschreiben :

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
    // your code here, you can use newConfig.locale if you need to check the language
    // or just re-set all the labels to desired string resource
}
Frane Poljak
quelle
Das Entfernen von android: configChanges = "locale" aus dem Manifest verhindert nicht, dass die App neu gestartet wird. Es wird neu gestartet, unabhängig davon, ob dies zum Manifest hinzugefügt wurde oder nicht.
Portfoliobuilder
Ich sage nicht, dass das Entfernen von android: configChanges = "locale" aus dem Manifest den Neustart der App verhindert. Ich sage genau das Gegenteil. Für den Fall, dass wir android: configChanges = "locale" im Manifest haben, um zu verhindern, dass die App zum Zeitpunkt des Schreibens dieser Antwort neu geladen wird, kann ich nicht sicher sagen, dass dies jetzt der Fall ist.
Frane Poljak
6

Der gesamte obige Code ist perfekt, aber nur einer, der fehlt, funktionierte nicht, nur weil die Sprache in der Konfigurationsdatei nicht erwähnt wurde

 defaultConfig {

    resConfigs "en", "hi", "kn"

}

Danach wurden alle Sprachen ausgeführt

Lokesh Tiwari
quelle
3
es funktioniert nicht
Krunal Shah
Wird es wirklich gebraucht?
JCarlosR
3

Diejenigen, die das Versionsproblem bekommen, versuchen diesen Code.

public static void switchLocal(Context context, String lcode, Activity activity) {
        if (lcode.equalsIgnoreCase(""))
            return;
        Resources resources = context.getResources();
        Locale locale = new Locale(lcode);
        Locale.setDefault(locale);
        android.content.res.Configuration config = new 
        android.content.res.Configuration();
        config.locale = locale;
        resources.updateConfiguration(config, resources.getDisplayMetrics());
        //restart base activity 
        activity.finish();
        activity.startActivity(activity.getIntent());
    }
Wahab Khan Jadon
quelle
2

Udhays Beispielcode funktioniert gut. Mit Ausnahme der Frage von Sofiane Hassaini und Chirag SolankI, für den Wiedereintritt, funktioniert es nicht. Ich versuche, Udhays Code aufzurufen, ohne die Aktivität in onCreate () vor super.onCreate (savedInstanceState); neu zu starten. Dann ist es OK! Nur ein kleines Problem, die Menüzeichenfolgen wurden immer noch nicht in das eingestellte Gebietsschema geändert.

    public void setLocale(String lang) { //call this in onCreate()
      Locale 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); 
      //finish();
    } 
Fischer
quelle
gleiches Problem mit Menüzeichenfolgen. Lösen Sie das Problem?
AlexS
@AlexS, ich habe keine Möglichkeit gefunden, das Problem in der Menüzeichenfolge zu beheben. Wenn Sie jedoch feststellen, dass Sie die App beenden und dann erneut eingeben, können die Menüzeichenfolgen normalerweise in das neue Gebietsschema geändert werden.
Fisher
Sie bedeuten Intent refresh = new Intent(this, ThisActivity.class); startActivity(refresh); ?
AlexS
2
@AlexS, nein! Durch Hinzufügen von Intent () und startActivity () wird möglicherweise die Standardsprache wiederhergestellt, wenn die App neu gestartet wird. Ich meine, wenn Benutzer die App verlassen und die App erneut aufrufen, können die Menüzeichenfolgen in das neue Gebietsschema geändert werden.
Fisher