アプリ別の言語設定

システム設定でのアプリ別の言語

多言語ユーザーは、多くの場合、特定のアプリに対してシステムに設定した言語(英語など)とは別の言語(オランダ語、中国語、ヒンディー語など)を選択します。Android 13 では、このようなユーザーのエクスペリエンスを改善するために、複数の言語をサポートするアプリ向けに以下の機能を導入しています。

  • システム設定: ユーザーがアプリごとに使用する言語を一元的に選択できる場所。

    アプリ別の言語設定のサポートとシステム設定への表示に必要なファイルを自動的に生成するようにアプリを構成できます。詳しくは、アプリ別の言語の自動サポートを有効にするをご覧ください。

  • その他の API: LocaleManagersetApplicationLocales() および getApplicationLocales() メソッドといった公開 API を使用すると、アプリは実行時にシステム言語とは異なる言語を設定できます。

    これらの API はシステム設定と自動的に同期されます。そのため、これらの API を使用してカスタムのアプリ内言語選択ツールを作成するアプリでは、言語設定の選択内容にかかわらず、一貫したユーザー エクスペリエンスを提供できます。公開 API を使用すると、ボイラープレート コードの量を減らし、分割 APK をサポートして、アプリの自動バックアップによってアプリレベルの言語設定を保存できるようになります。

    以前の Android バージョンとの下位互換性を維持するため、AndroidX でも等価の API を使用できます。ただし、Android 12(API レベル 32)以前の場合、下位互換性のある API は、アプリ コンテキストではなく AppCompatActivity コンテキストで動作します。下位互換性のある API にアクセスするには、Appcompat 1.6.0 以降が必要です。

この機能の実装の概要

次の表に、さまざまなユースケースに基づくおすすめの実装方法を示します。

ユースケース おすすめの実装方法
アプリにアプリ内言語選択ツールがない
  1. アプリ別の言語の自動サポートを有効にして、LocaleConfig ファイルを生成し、アプリの言語をシステム設定に追加します。
  2. アプリ内言語選択ツールを追加する場合: AndroidX ライブラリを使用して API 実装をオプトインし、autoStoreLocales によって下位互換性を確保します。
アプリにすでにアプリ内言語選択ツールがある
  1. アプリ別の言語の自動サポートを有効にして、LocaleConfig ファイルを生成し、アプリの言語をシステム設定に追加します。
  2. アプリのカスタム ロジックを移行し、公開 API を使用して、ユーザーに一貫したエクスペリエンスを提供します。
  3. 以下のような特殊なケースに対応する。
    1. Android 13 搭載デバイスで初めてアプリを実行するときに AppCompatDelegate.setApplicationLocales() を呼び出す。
    2. 以下の場合に、AppCompatDelegate.setApplicationLocales() を呼び出して既存のユーザー リクエスト ロケールをシステムに渡す。

ユーザーのためのシステム設定

Android 13 以降の Android では、アプリ別の言語設定を一元的に行う場所がシステム設定に用意されています。Android 13 以降を搭載したデバイスのシステム設定でアプリの言語を設定できるようにするには、アプリ別の言語の自動サポートを有効にするか(推奨)、手動でサポートを構成します。

アプリ別の言語の自動サポートを有効にする

Android Studio Giraffe と AGP 8.1 以降では、アプリで自動的にアプリ別の言語設定をサポートするように設定できます。AGP は、プロジェクト リソースに基づいて LocaleConfig ファイルを生成し、そのファイルへの参照を最終マニフェスト ファイルに追加します。そのため、手動で行う必要はありません。AGP は、アプリ モジュールの res フォルダ内のリソースと、ライブラリ モジュールの依存関係を使用して、LocaleConfig ファイルに含めるロケールを決定します。そのため、アプリに新しい言語のリソースを追加しても、LocaleConfig ファイルの更新を考慮する必要はありません。

自動のアプリ別の言語機能は、Android 13(API レベル 33)以降を実行するアプリをサポートしています。この機能を使用するには、compileSdkVersion を 33 以上に設定する必要があります。以前のバージョンの Android のアプリ別の言語設定を設定するには、API とアプリ内言語選択ツールを使用する必要があります。

アプリ別の言語の自動サポートを有効にする手順は次のとおりです。

  1. この機能を有効にするには、モジュール レベルの build.gradle.kts ファイル(Groovy を使用している場合は build.gradle ファイル)の androidResources {} ブロックで generateLocaleConfig 設定を使用します。デフォルトでは無効になっています。

    Kotlin

        android {
          androidResources {
            generateLocaleConfig = true
          }
        }
        

    Groovy

        android {
          androidResources {
            generateLocaleConfig true
          }
        }
        
  2. デフォルトのロケールを指定します。
    1. アプリ モジュールの res フォルダに、resources.properties という名前の新しいファイルを作成します。
    2. resources.properties ファイルで、unqualifiedResLocale ラベルを使用してデフォルトのロケールを設定します。ロケール名をフォーマットするには、ロケール名を作成する方法をご覧ください。

AGP は、このデフォルトのロケールと、res フォルダの values-* ディレクトリを使用して指定した代替ロケールを、自動生成された LocaleConfig ファイルに追加します。

ロケール名を作成する方法

ロケール名を作成するには、言語コードをスクリプトや地域コード(省略可)と組み合わせ、それぞれをダッシュで区切ります。

  • 言語: 2 文字または 3 文字の ISO 639-1 コードを使用します。
  • スクリプト(省略可): ISO 15924 コードを使用します。
  • 地域(省略可): 2 文字の ISO 3166-1-alpha-2 コードまたは 3 桁の UN_M.49 コードを使用します。

たとえば、デフォルトのロケールがアメリカ英語である場合は次のとおりです。

unqualifiedResLocale=en-US

android:localeConfig を使用して対応言語をシステム設定に追加する

Android 13 以降を搭載したデバイスのシステム設定でアプリの言語を設定できるように、アプリを手動でセットアップできます。そのためには、locales_config XML ファイルを作成し、android:localeConfig 属性を使用してアプリのマニフェストに追加します。android:localeConfig マニフェスト エントリを省略すると、ユーザーはシステム設定で、システムの言語とは別にアプリの言語を設定できなくなります。

アプリの対応言語をユーザーのシステム設定に手動で追加するには:

  1. res/xml/locales_config.xml というファイルを作成し、アプリの言語を指定します。これにはアプリの最終的なフォールバック ロケールres/values/strings.xml で指定されるロケール)が含まれます。

    形式の要件については、ロケール名を作成する方法をご覧ください。よく使用されるロケールの一覧については、サンプル locale_config.xml ファイルもご覧ください。

    たとえば、次の言語をサポートするアプリでは、次のように locales_config.xml ファイルをフォーマットします。

    • 英語(米国)(最終的なフォールバック ロケール)
    • 英語(英国)
    • フランス語
    • 日本語
    • 中国語(簡体、マカオ)
    • 中国語(繁体、マカオ)
    <?xml version="1.0" encoding="utf-8"?>
    <locale-config xmlns:android="http://schemas.android.com/apk/res/android">
       <locale android:name="en-US"/>
       <locale android:name="en-GB"/>
       <locale android:name="fr"/>
       <locale android:name="ja"/>
       <locale android:name="zh-Hans-MO"/>
       <locale android:name="zh-Hant-MO"/>
    </locale-config>
    
  2. マニフェストにこの新しいファイルを指す行を追加します。

    <manifest>
        ...
        <application
            ...
            android:localeConfig="@xml/locales_config">
        </application>
    </manifest>
    

アプリの localeConfigLocaleManager.setOverrideLocaleConfig で動的に更新して、Android の設定にあるアプリ別の言語リストに表示する言語セットをカスタマイズできます。これにより、地域ごとに言語リストをカスタマイズしたり、A/B テストを実施したりできます。また、アプリがサーバーサイドのローカライズ プッシュを利用する場合は、次の例に示すように、更新されたロケールを提供できます。

Kotlin

//For setOverrideLocaleConfig
val localeManager = applicationContext
    .getSystemService(LocaleManager::class.java)
localeManager.overrideLocaleConfig = LocaleConfig(
LocaleList.forLanguageTags("en-US,ja-JP,zh-Hans-SG")
)

//For getOverrideLocaleConfig
// The app calls the API to get the override LocaleConfig
val overrideLocaleConfig = localeManager.overrideLocaleConfig
// If the returned overrideLocaleConfig isn't equal to NULL, then the app calls the API to get the supported Locales
val supportedLocales = overrideLocaleConfig.supportedLocales()

Java

//For setOverrideLocaleConfig
mContext.getSystemService(LocaleManager.class).setOverrideLocaleConfig(new LocaleConfig(LocaleList.forLanguageTags("en-US,ja-JP,zh-Hans-SG")));

//For getOverrideLocaleConfig
// The app calls the API to get the override LocaleConfig
LocaleConfig overrideLocaleConfig = mContext.getSystemService(LocaleManager.class).getOverrideLocaleConfig();
// If the returned overrideLocaleConfig isn't equal to NULL, then the app calls the API to get the supported Locales
LocaleList supportedLocales = overrideLocaleConfig.getSupportedLocales();

さらに、IME は LocaleManager.getApplicationLocales を使用して現在のアプリの UI 言語を認識し、次に示すようにキーボード言語を更新できるようになりました。

Kotlin

val currentAppLocales: LocaleList = applicationContext.getSystemService(LocaleManager::class.java).getApplicationLocales(appPackageName)

Java

LocaleList currentAppLocales =
    mContext.getSystemService(LocaleManager.class).getApplicationLocales(appPackageName);

Gradle でサポートされる言語を指定する

まだ存在しない場合は、アプリのモジュール レベルの build.gradle ファイルの resourceConfigurations プロパティを使用して同じ言語を指定します。

android {
  ...
  defaultConfig {
    resourceConfigurations += ["en", "en-rGB", "fr", "ja", "b+zh+Hans+MO", "b+zh+Hant+MO"]
  }
}

resourceConfigurations プロパティが存在する場合、ビルドシステムは、これらの指定された言語の APK の言語リソースのみを使用します。そのため、アプリでサポートされていない言語をサポートしている可能性がある他のライブラリから翻訳済み文字列が読み込まれることはありません。詳細については、アプリがサポートする言語を指定するをご覧ください。

ユーザーがシステム設定でアプリの言語を選択する方法

ユーザーは、システム設定を使用してアプリごとの使用言語を選択できます。この設定にアクセスするには、次の 2 つの方法があります。

  • システム設定からアクセスする

    [設定] > [システム] > [言語と入力] > [アプリの言語] >(アプリを選択)

  • アプリ設定からアクセスする

    [設定] > [アプリ] >(アプリを選択)> [言語]

アプリ内言語選択ツールを処理する

アプリ内言語選択ツールをすでに備えているか使用する予定があるアプリの場合、アプリにおけるユーザーの使用言語の設定と取得を処理するには、アプリのカスタム ロジックの代わりに公開 API を使用してください。アプリ内言語選択ツールに公開 API を使用する場合、ユーザーがアプリ内エクスペリエンスで選択した言語に一致するように、デバイスのシステム設定が自動的に更新されます。

以前の Android バージョンとの下位互換性を維持するため、アプリ内言語選択ツールを実装する際に AndroidX サポート ライブラリを使用することを強くおすすめします。ただし必要に応じて、フレームワーク API を直接実装することもできます。

AndroidX サポート ライブラリを使用して実装する

Appcompat 1.6.0 以降の場合は、setApplicationLocales() メソッドと getApplicationLocales() メソッドを使用します。Android 12(API レベル 32)以前の場合、下位互換性のある API は、アプリ コンテキストではなく AppCompatActivity コンテキストで動作します。

たとえば、ユーザーの使用言語を設定するには、言語選択ツールでロケールを選択するようユーザーにリクエストし、その値をシステムに設定します。

Kotlin

val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags("xx-YY")
// Call this on the main thread as it may require Activity.restart()
AppCompatDelegate.setApplicationLocales(appLocale)

Java

LocaleListCompat appLocale = LocaleListCompat.forLanguageTags("xx-YY");
// Call this on the main thread as it may require Activity.restart()
AppCompatDelegate.setApplicationLocales(appLocale);

setApplicationLocales() を呼び出すと、Activity が再作成されます。ただし、アプリ自体がロケール設定の変更を処理する場合を除きます。

AppCompatDelegate.getApplicationLocales() を使用して、ユーザーの希望する言語 / 地域を取得します。ユーザーはシステム設定またはアプリ内言語選択ツールでアプリの言語 / 地域を選択している場合もあります。

Android 12 以下をサポートする

Android 12(API レベル 32)以下を搭載するデバイスをサポートするには、autoStoreLocales の値を true に設定し、android:enabledfalse に設定してロケールの保存を処理するよう AndroidX に指示します。これは次のコード スニペットに示すように、アプリの AppLocalesMetadataHolderService サービスのマニフェスト エントリ内で行います。

<application
  ...
  <service
    android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
    android:enabled="false"
    android:exported="false">
    <meta-data
      android:name="autoStoreLocales"
      android:value="true" />
  </service>
  ...
</application>

autoStoreLocales の値を true に設定すると、メインスレッドでのブロック読み取りの原因になります。スレッド違反をログに記録している場合は、StrictMode diskRead および diskWrite 違反になる可能性があります。詳しくは、AppCompatDelegate.setApplicationLocales() をご覧ください。

カスタム ストレージの取り扱い

マニフェスト エントリを省略するか、autoStoreLocalesfalse に設定すると、独自のストレージを扱っていると示すことになります。その場合、Android 12(API レベル 32)以下では、アクティビティのライフサイクルで onCreate の前に保存済みのロケールを指定し、AppCompatDelegate.setApplicationLocales() への呼び出しを制御します。

アプリにカスタムのロケールの保存場所がある場合は、カスタム ロケール ストレージ ソリューションと autoStoreLocales 間で 1 回限りのハンドオフを使用し、ユーザーが任意の言語で引き続きアプリを使用できるようにすることをおすすめします。これは特に、デバイスが Android 13 にアップグレードされた後に初めてアプリを実行する場合に当てはまります。その場合は、カスタム ストレージからロケールを取得して AppCompatDelegate.setApplicationLocales() に渡すことで、ユーザーがリクエストした既存のロケールを指定できます。

Android フレームワーク API を使用して実装する

AndroidX サポート ライブラリを使用してアプリ内言語選択ツールを実装することを強くおすすめしますが、Android 13 を搭載したデバイスでは、Android フレームワーク内で setApplicationLocales() メソッドと getApplicationLocales() メソッドを使用することもできます。

たとえば、ユーザーの使用言語を設定するには、言語選択ツールでロケールを選択するようユーザーにリクエストし、その値をシステムに設定します。

// 1. Inside an activity, in-app language picker gets an input locale "xx-YY"
// 2. App calls the API to set its locale
mContext.getSystemService(LocaleManager.class
    ).setApplicationLocales(new LocaleList(Locale.forLanguageTag("xx-YY")));
// 3. The system updates the locale and restarts the app, including any configuration updates
// 4. The app is now displayed in "xx-YY" language

ユーザー指定の言語を取得して言語選択ツールで表示する場合、システムからその値を取得します。

// 1. App calls the API to get the preferred locale
LocaleList currentAppLocales =
    mContext.getSystemService(LocaleManager.class).getApplicationLocales();
// 2. App uses the returned LocaleList to display languages to the user

その他のおすすめの方法

次のおすすめの方法を考慮してください。

別のアプリからインテントを呼び出す場合は言語を指定する

言語中心のインテントでは、呼び出すアプリの言語を指定できる場合があります。一例として、Speech Recognizer API の EXTRA_LANGUAGE 機能があります。

Chrome カスタムタブで Accept-Language ヘッダーを使用する

Chrome カスタムタブを呼び出すときに、Browser.EXTRA_HEADERSAccept-Language ヘッダーを追加して、アプリで設定した言語でウェブページを開くことを検討してください。

システム設定でアプリ別の言語設定を削除する場合にはアプリの言語 / 地域をシステム ロケールにリセットする

システム設定からアプリの言語設定を削除する場合(アプリの AndroidManifest.xml から android:localeConfig を削除する場合)、ユーザーがアプリの言語をシステムのデフォルトにリセットするのは簡単ではありません。

このような理由から、android:localeConfig を削除する場合は、LocaleListCompat.getEmptyLocaleList() または LocaleList.getEmptyLocaleList() を使用して、アプリの言語 / 地域をシステム ロケールにリセットすることを検討してください。次のコード スニペットに例を示します。

Kotlin

// Use the AndroidX APIs to reset to the system locale for backward and forward compatibility
AppCompatDelegate.setApplicationLocales(
  LocaleListCompat.getEmptyLocaleList()
)

// Or use the Framework APIs for Android 13 and above to reset to the system locale
val context = LocalContext.current
context.getSystemService(LocaleManager::class.java)
  .applicationLocales = LocaleList.getEmptyLocaleList()

Java

// Use the AndroidX APIs to reset to the system locale for backward and forward compatibility
AppCompatDelegate.setApplicationLocales(
  LocaleListCompat.getEmptyLocaleList()
);

// Or use the Framework APIs for Android 13 and above to reset to the system locale
mContext.getSystemService(LocaleManager.class)
  .setApplicationLocales(LocaleList.getEmptyLocaleList());

参考情報

詳しくは、コードサンプル、ブログ記事、動画をご覧ください。

サンプル locale_config.xml ファイル

Android には、よく使用されるロケールの標準セットに対して、デフォルトで Android オープンソース プロジェクト(AOSP)のシステムレベルの翻訳が用意されています。このセクションに含まれるサンプル locale_config.xml ファイルでは、各ロケールで推奨される形式が示されています。このサンプル ファイルを参照すれば、アプリがサポートする言語セット用に独自の locale_config.xml ファイルを作成できます。

<?xml version="1.0" encoding="utf-8"?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
   <locale android:name="af"/> <!-- Afrikaans -->
   <locale android:name="am"/> <!-- Amharic -->
   <locale android:name="ar"/> <!-- Arabic -->
   <locale android:name="as"/> <!-- Assamese -->
   <locale android:name="az"/> <!-- Azerbaijani -->
   <locale android:name="be"/> <!-- Belarusian -->
   <locale android:name="bg"/> <!-- Bulgarian -->
   <locale android:name="bn"/> <!-- Bengali -->
   <locale android:name="bs"/> <!-- Bosnian -->
   <locale android:name="ca"/> <!-- Catalan -->
   <locale android:name="cs"/> <!-- Czech -->
   <locale android:name="da"/> <!-- Danish -->
   <locale android:name="de"/> <!-- German -->
   <locale android:name="el"/> <!-- Greek -->
   <locale android:name="en-AU"/> <!-- English (Australia) -->
   <locale android:name="en-CA"/> <!-- English (Canada) -->
   <locale android:name="en-GB"/> <!-- English (United Kingdom) -->
   <locale android:name="en-IN"/> <!-- English (India) -->
   <locale android:name="en-US"/> <!-- English (United States) -->
   <locale android:name="en-XA"/> <!-- English (Pseudo-Accents) -->
   <locale android:name="es"/> <!-- Spanish (Spain) -->
   <locale android:name="es-US"/> <!-- Spanish (United States) -->
   <locale android:name="et"/> <!-- Estonian -->
   <locale android:name="eu"/> <!-- Basque -->
   <locale android:name="fa"/> <!-- Farsi -->
   <locale android:name="fi"/> <!-- Finnish -->
   <locale android:name="fr"/> <!-- French (France) -->
   <locale android:name="fr-CA"/> <!-- French (Canada) -->
   <locale android:name="gl"/> <!-- Galician -->
   <locale android:name="gu"/> <!-- Gujarati -->
   <locale android:name="hi"/> <!-- Hindi -->
   <locale android:name="hr"/> <!-- Croatian -->
   <locale android:name="hu"/> <!-- Hungarian -->
   <locale android:name="hy"/> <!-- Armenian -->
   <locale android:name="in"/> <!-- Indonesian -->
   <locale android:name="is"/> <!-- Icelandic -->
   <locale android:name="it"/> <!-- Italian -->
   <locale android:name="iw"/> <!-- Hebrew -->
   <locale android:name="ja"/> <!-- Japanese -->
   <locale android:name="ka"/> <!-- Georgian -->
   <locale android:name="kk"/> <!-- Kazakh -->
   <locale android:name="km"/> <!-- Khmer -->
   <locale android:name="kn"/> <!-- Kannada -->
   <locale android:name="ko"/> <!-- Korean -->
   <locale android:name="ky"/> <!-- Kyrgyz -->
   <locale android:name="lo"/> <!-- Lao -->
   <locale android:name="lt"/> <!-- Lithuanian -->
   <locale android:name="lv"/> <!-- Latvian -->
   <locale android:name="mk"/> <!-- Macedonian -->
   <locale android:name="ml"/> <!-- Malayalam -->
   <locale android:name="mn"/> <!-- Mongolian -->
   <locale android:name="mr"/> <!-- Marathi -->
   <locale android:name="ms"/> <!-- Malay -->
   <locale android:name="my"/> <!-- Burmese -->
   <locale android:name="my-MM"/> <!-- Burmese (Myanmar) -->
   <locale android:name="nb"/> <!-- Norwegian -->
   <locale android:name="ne"/> <!-- Nepali -->
   <locale android:name="nl"/> <!-- Dutch -->
   <locale android:name="or"/> <!-- Odia -->
   <locale android:name="pa"/> <!-- Punjabi -->
   <locale android:name="pl"/> <!-- Polish -->
   <locale android:name="pt-BR"/> <!-- Portuguese (Brazil) -->
   <locale android:name="pt-PT"/> <!-- Portuguese (Portugal) -->
   <locale android:name="ro"/> <!-- Romanian -->
   <locale android:name="ru"/> <!-- Russian -->
   <locale android:name="si"/> <!-- Sinhala -->
   <locale android:name="sk"/> <!-- Slovak -->
   <locale android:name="sl"/> <!-- Slovenian -->
   <locale android:name="sq"/> <!-- Albanian -->
   <locale android:name="sr"/> <!-- Serbian (Cyrillic) -->
   <locale android:name="sr-Latn"/> <!-- Serbian (Latin) -->
   <locale android:name="sv"/> <!-- Swedish -->
   <locale android:name="sw"/> <!-- Swahili -->
   <locale android:name="ta"/> <!-- Tamil -->
   <locale android:name="te"/> <!-- Telugu -->
   <locale android:name="th"/> <!-- Thai -->
   <locale android:name="tl"/> <!-- Filipino -->
   <locale android:name="tr"/> <!-- Turkish -->
   <locale android:name="uk"/> <!-- Ukrainian -->
   <locale android:name="ur"/> <!-- Urdu -->
   <locale android:name="uz"/> <!-- Uzbek -->
   <locale android:name="vi"/> <!-- Vietnamese -->
   <locale android:name="zh-CN"/> <!-- Chinese (Simplified) -->
   <locale android:name="zh-HK"/> <!-- Chinese (Hong Kong) -->
   <locale android:name="zh-TW"/> <!-- Chinese (Traditional) -->
   <locale android:name="zu"/> <!-- Zulu -->
</locale-config>