Daher möchte ich den Wert eines Strings in mehreren Gebietsschemas unabhängig von der aktuellen Gebietsschemaeinstellung des Geräts / der App abrufen. Wie soll ich das machen
Grundsätzlich brauche ich getString(int id, String locale)
eher eine Funktion alsgetString(int id)
Wie könnte ich das machen?
Vielen Dank
android
locale
android-resources
Cheng Yang
quelle
quelle
ResourceBundle
sollen Vermögenswerte beziehen ?? oder können sie auf unseren res-Ordner zugreifen?getString(R.strings.text)
die Zeichenfolge in der Benutzersprache (oder in der Standardeinstellung, wenn die Benutzersprache keinen Ordner hat)Antworten:
HINWEIS Wenn Ihre Mindest-API 17+ ist, gehen Sie direkt zum Ende dieser Antwort. Ansonsten lesen Sie weiter ...
HINWEIS Wenn Sie App-Bundles verwenden, müssen Sie sicherstellen, dass Sie entweder die Sprachaufteilung deaktivieren oder die andere Sprache dynamisch installieren. Siehe dazu https://stackoverflow.com/a/51054393 . Wenn Sie dies nicht tun, wird immer der Fallback verwendet.
Wenn Sie verschiedene Res-Ordner für verschiedene Gebietsschemas haben, können Sie Folgendes tun:
Configuration conf = getResources().getConfiguration(); conf.locale = new Locale("pl"); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); Resources resources = new Resources(getAssets(), metrics, conf); String str = resources.getString(id);
Alternativ können Sie Ihre Aktivität einfach mit der von @jyotiprakash angegebenen Methode neu starten.
HINWEIS Wenn Sie den
Resources
Konstruktor so aufrufen, ändert sich intern etwas in Android. Sie müssen den Konstruktor mit Ihrem ursprünglichen Gebietsschema aufrufen, um die Dinge wieder so zu erhalten, wie sie waren.BEARBEITEN Ein etwas anderes (und etwas saubereres) Rezept zum Abrufen von Ressourcen aus einem bestimmten Gebietsschema lautet:
Resources res = getResources(); Configuration conf = res.getConfiguration(); Locale savedLocale = conf.locale; conf.locale = desiredLocale; // whatever you want here res.updateConfiguration(conf, null); // second arg null means don't change // retrieve resources from desired locale String str = res.getString(id); // restore original locale conf.locale = savedLocale; res.updateConfiguration(conf, null);
Ab API-Stufe 17 sollten Sie
conf.setLocale()
anstelle der direkten Einstellung verwendenconf.locale
. Dadurch wird die Layoutrichtung der Konfiguration korrekt aktualisiert, wenn Sie zufällig zwischen Gebietsschemas von rechts nach links und von links nach rechts wechseln. (Layoutrichtung wurde in 17 eingeführt.)Es macht keinen Sinn, ein neues
Configuration
Objekt zu erstellen (wie @Nulano in einem Kommentar vorschlägt), da durch das AufrufenupdateConfiguration
die ursprüngliche Konfiguration geändert wird, die durch das Aufrufen erhalten wurderes.getConfiguration()
.Ich würde zögern, dies in eine
getString(int id, String locale)
Methode zu bündeln , wenn Sie mehrere Zeichenfolgenressourcen für ein Gebietsschema laden möchten . Das Ändern der Gebietsschemas (unter Verwendung eines der beiden Rezepte) erfordert, dass das Framework viel Arbeit leistet, um alle Ressourcen neu zu binden. Es ist viel besser, Gebietsschemas einmal zu aktualisieren, alles abzurufen, was Sie benötigen, und dann das Gebietsschema zurückzusetzen.EDIT (Danke an @Mygod):
Wenn Ihre Mindest-API-Stufe 17+ ist, gibt es einen viel besseren Ansatz, wie in dieser Antwort in einem anderen Thread gezeigt. Sie können beispielsweise mehrere
Resource
Objekte erstellen , eines für jedes Gebietsschema, das Sie benötigen:@NonNull Resources getLocalizedResources(Context context, Locale desiredLocale) { Configuration conf = context.getResources().getConfiguration(); conf = new Configuration(conf); conf.setLocale(desiredLocale); Context localizedContext = context.createConfigurationContext(conf); return localizedContext.getResources(); }
Rufen Sie dann einfach die gewünschten Ressourcen aus dem lokalisierten
Resource
Objekt ab, das von dieser Methode zurückgegeben wird. Sie müssen nichts zurücksetzen, sobald Sie die Ressourcen abgerufen haben.quelle
getResources().getConfiguration()
? Laut GrepCode wird eine lokale Instanz zurückgegeben, die in den Ressourcen gespeichert ist. Das spätere Ändern des Gebietsschemafelds ist wahrscheinlich der wahre Grund, warum Android verwirrt ist. Sie sollten wahrscheinlichconf = new Configuration(conf);
(um die zurückgegebene Konfiguration zu klonen) zwischen der ersten und der zweiten Zeile tun .Resources
Konstruktor an und Sie werden sehen, dass das Erstellen eines neuenResources
Objekts wie dieses die Dinge tief in den Assets des Prozesses verändert (anscheinend ein Singleton). Als ich merkte, dass die Dinge zurückgesetzt werden mussten, machte ich mir nicht die Mühe, genau herauszufinden, warum. Ein alternativer (möglicherweise sauberer) Ansatz zum Erstellen eines neuenResources
Objekts besteht darin,resources.updateConfiguration(conf, null)
nach dem Ändern der Gebietsschemas aufzurufen .Hier ist eine kombinierte Version der von Ted Hopp beschriebenen Ansätze . Auf diese Weise funktioniert der Code für jede Android-Version:
public static String getLocaleStringResource(Locale requestedLocale, int resourceId, Context context) { String result; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // use latest api Configuration config = new Configuration(context.getResources().getConfiguration()); config.setLocale(requestedLocale); result = context.createConfigurationContext(config).getText(resourceId).toString(); } else { // support older android versions Resources resources = context.getResources(); Configuration conf = resources.getConfiguration(); Locale savedLocale = conf.locale; conf.locale = requestedLocale; resources.updateConfiguration(conf, null); // retrieve resources from desired locale result = resources.getString(resourceId); // restore original locale conf.locale = savedLocale; resources.updateConfiguration(conf, null); } return result; }
Anwendungsbeispiel:
String englishName = getLocaleStringResource(new Locale("en"), R.string.name, context);
Hinweis
Wie bereits in der ursprünglichen Antwort angegeben, ist es möglicherweise effizienter, mehrere Aufrufe des obigen Codes durch eine einzige Konfigurationsänderung und mehrere Aufrufe von resources.getString () zu ersetzen.
quelle
Basierend auf den obigen Antworten, die fantastisch, aber ein wenig komplex sind. Probieren Sie diese einfache Funktion aus:
public String getResStringLanguage(int id, String lang){ //Get default locale to back it Resources res = getResources(); Configuration conf = res.getConfiguration(); Locale savedLocale = conf.locale; //Retrieve resources from desired locale Configuration confAr = getResources().getConfiguration(); confAr.locale = new Locale(lang); DisplayMetrics metrics = new DisplayMetrics(); Resources resources = new Resources(getAssets(), metrics, confAr); //Get string which you want String string = resources.getString(id); //Restore default locale conf.locale = savedLocale; res.updateConfiguration(conf, null); //return the string that you want return string; }
Dann nenne es einfach:
String str = getResStringLanguage(R.string.any_string, "en");
Glücklicher Code :)
quelle