アプリ別の言語設定

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

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

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

    アプリはマニフェストで android:localeConfig 属性を宣言して、複数の言語に対応するようにシステムに指示する必要があります。詳しくは、リソース ファイルを作成してアプリのマニフェスト ファイルで宣言する手順をご覧ください。

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

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

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

この機能の実装の概要

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

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

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

Android 13 以降の Android では、アプリ別の言語設定を一元的に行う場所がシステム設定に用意されています。Android 13 以降を搭載するデバイスのシステム設定でアプリの言語を設定できるようにするには、locales_config XML ファイルを作成し、android:localeConfig 属性を使用してアプリのマニフェストを追加します。android:localeConfig マニフェスト エントリを省略すると、ユーザーはシステム設定で、システムの言語とは別にアプリの言語を設定できなくなります。

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

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

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

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

    • 言語: 2 文字または 3 文字の ISO 639-1 コードを使用します。

    • スクリプト(省略可): ISO 15924 コードを使用します。

    • 地域(省略可): 2 文字の ISO 3166-1-alpha-2 コードまたは 3 桁の UN_M.49 コードを使用します。

    よく使用されるロケールの一覧については、サンプル 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"/>
       <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>
    

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_HEADERS によって Accept-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>