1. ホーム
  2. android

[解決済み] プログラムによるロケールの設定

2022-04-24 19:02:33

質問

私のアプリは3カ国語(近々4カ国語)に対応しています。いくつかのロケールは非常によく似ているので、アプリケーション内でロケールを変更するオプションをユーザーに提供したいと思います。例えば、イタリア人は英語よりもスペイン語を好むかもしれません。

アプリケーションで利用可能なロケールの中からユーザーが選択し、使用するロケールを変更する方法はありますか?Activityごとにロケールを設定するのは、ベースクラスで行う簡単な作業なので、問題ないと思います。

どのように解決するのですか?

この答えをまだ探している人のために configuration.locale がAPI 24から非推奨になったので、使えるようになった。

configuration.setLocale(locale);

このメソッドのminSkdVersionはAPI 17であることを考慮に入れてください。

完全なサンプルコードです。

@SuppressWarnings("deprecation")
private void setLocale(Locale locale){
    SharedPrefUtils.saveLocale(locale); // optional - Helper method to save the selected language to SharedPreferences in case you might need to attach to activity context (you will need to code this)
    Resources resources = getResources();
    Configuration configuration = resources.getConfiguration();
    DisplayMetrics displayMetrics = resources.getDisplayMetrics();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
        configuration.setLocale(locale);
    } else{
        configuration.locale=locale;
    }
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N){
        getApplicationContext().createConfigurationContext(configuration);
    } else {
        resources.updateConfiguration(configuration,displayMetrics);
    }
}

実行中のActivityでロケールを変更した場合、変更を反映させるためにActivityを再起動する必要があることを忘れないでください。

EDIT 11th MAY 2018

CookieMonster さんの投稿にあるように、高い API バージョンでロケールの変更を維持するのに問題があるかもしれません。その場合は、以下のコードを Base Activity (BaseActivity extends AppCompatActivity / other activities) に追加して、Activity を作成するたびにコンテキストのロケールを更新するようにします。

@Override
protected void attachBaseContext(Context base) {
     super.attachBaseContext(updateBaseContextLocale(base));
}

private Context updateBaseContextLocale(Context context) {
    String language = SharedPrefUtils.getSavedLanguage(); // Helper method to get saved language from SharedPreferences
    Locale locale = new Locale(language);
    Locale.setDefault(locale);

    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
        return updateResourcesLocale(context, locale);
    }

    return updateResourcesLocaleLegacy(context, locale);
}

@TargetApi(Build.VERSION_CODES.N_MR1)
private Context updateResourcesLocale(Context context, Locale locale) {
    Configuration configuration = new Configuration(context.getResources().getConfiguration());
    configuration.setLocale(locale);
    return context.createConfigurationContext(configuration);
}

@SuppressWarnings("deprecation")
private Context updateResourcesLocaleLegacy(Context context, Locale locale) {
    Resources resources = context.getResources();
    Configuration configuration = resources.getConfiguration();
    configuration.locale = locale;
    resources.updateConfiguration(configuration, resources.getDisplayMetrics());
    return context;
}

これを使う場合、ロケールを設定するときにSharedPreferencesに言語を保存することを忘れないでください。 setLocale(locale)

EDIT 7th APRIL 2020

Android 6および7で問題が発生する可能性があります。これは、androidxライブラリでナイトモードを処理する際に問題が発生するためです。このため applyOverrideConfiguration をベースアクティビティに追加し、新しいロケールが作成された場合に設定のロケールを更新してください。

サンプルコードです。

@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) {
        // update overrideConfiguration with your locale  
        setLocale(overrideConfiguration) // you will need to implement this
    }
    super.applyOverrideConfiguration(overrideConfiguration);
}