web-dev-qa-db-ja.com

Androidの異なるロケールから文字列を取得する方法は?

そのため、デバイス/アプリの現在のロケール設定に関係なく、いくつかのロケールで文字列の値を取得したいと思います。どうすればいいですか?

基本的に必要なのは、getString(int id, String locale)ではなくgetString(int id)という関数です

どうすればそれができますか?

ありがとう

58
cheng yang

[〜#〜] note [〜#〜]最小APIが17+の場合、この回答の一番下に直接進んでください。それ以外の場合は、続きを読む...

異なるロケール用のさまざまなresフォルダーがある場合、次のようなことができます。

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

または、@ jyotiprakashが指すメソッドを使用してアクティビティを再起動することもできます。

[〜#〜] note [〜#〜]このようにResourcesコンストラクターを呼び出すと、Androidの内部で何かが変更されます。元のロケールでコンストラクターを呼び出して、元の状態に戻す必要があります。

[〜#〜] edit [〜#〜]特定のロケールからリソースを取得するためのわずかに異なる(ややクリーンな)レシピは次のとおりです。

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

APIレベル17では、_conf.locale_を直接設定する代わりに、conf.setLocale()を使用する必要があります。これにより、右から左のロケールと左から右のロケールを切り替える場合に、構成のレイアウト方向が正しく更新されます。 (レイアウト方向は17で導入されました。)

Configurationを呼び出すと、res.getConfiguration()を呼び出して取得した元の設定が変更されるため、新しいupdateConfigurationオブジェクトを作成しても意味がありません(@Nulanoがコメントで示唆しているとおり)。

ロケールに複数の文字列リソースをロードする場合、これをgetString(int id, String locale)メソッドにバンドルすることをheします。ロケールの変更(いずれかのレシピを使用)は、すべてのリソースを再バインドするために多くの作業を行うためにフレームワークを必要とします。一度ロケールを更新し、必要なものをすべて取得してから、ロケールを設定し直すことをお勧めします。

[〜#〜] edit [〜#〜](@Mygodに感謝):

最小APIレベルが17+の場合、別のスレッドの この回答 に示すように、はるかに優れたアプローチがあります。たとえば、必要なロケールごとに1つ、複数のResourceオブジェクトを作成できます。

_@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();
}
_

次に、このメソッドによって返されるローカライズされたResourceオブジェクトから好きなリソースを取得します。リソースを取得したら、何もリセットする必要はありません。

119
Ted Hopp

Ted Hopp で記述されたアプローチを組み合わせたバージョンを次に示します。このように、コードはすべてのAndroidバージョン:

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

使用例:

String englishName = getLocaleStringResource(new Locale("en"), R.string.name, context);

元の回答で既に述べたように、上記のコードの複数の呼び出しを、単一の構成変更と複数のresources.getString()呼び出しで置き換える方が効率的かもしれません。

19
Johnson_145