アプリ別の言語設定

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

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

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

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

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

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

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

この機能の実装の概要

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

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

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

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

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

XML を変更する必要がないため、アプリにアプリ別の言語サポートを追加するには、この方法をおすすめします。

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
    }
  }
  1. デフォルトのロケールを指定します。
    1. アプリ モジュールの res フォルダに、新しいファイルを作成します resources.properties
    2. resources.properties ファイルで、unqualifiedResLocale ラベルを使用してデフォルトのロケールを設定します。ロケール名をフォーマットするには、ロケール名を作成する方法をご覧ください。

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

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

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

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

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

unqualifiedResLocale=en-US

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

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

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

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

    形式の要件については、ロケール名を作成する方法をご覧ください。よく使用される 言語 / 地域の一覧については、 サンプル 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="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/locale_config">
        </application>
    </manifest>
    

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

//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()

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

val currentAppLocales: LocaleList = applicationContext.getSystemService(LocaleManager::class.java).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 を使用する場合、ユーザーがアプリ内エクスペリエンスで選択した言語に一致するように、デバイスのシステム設定が自動的に更新されます。

Jetpack Compose を使用して実装する

Jetpack Compose で完全に構築されたアプリの場合、アプリのロケールが変更されると、UI の更新が自動的に処理されます。新しい言語を設定する API を呼び出すと、構成の変更がトリガーされます。Compose は、UI を再コンポーズし、新しいロケールを使用して stringResource 呼び出しを自動的に解決します。

Android 12(API レベル 32)以下との下位互換性を維持するため、アプリ内言語選択ツールを実装する際に AndroidX サポート ライブラリ(AppCompatDelegate)を使用することを強くおすすめします。この方法を使用する場合、Compose UI をホストするアクティビティは AppCompatActivity を拡張する必要があります。ただし必要に応じて、フレームワーク API を直接 実装することもできます。

次のコード スニペットは、コンポーズ可能な関数内で現在のアプリの言語 / 地域を読み取り、新しい言語 / 地域を設定する方法の例を示しています。

import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.core.os.LocaleListCompat

@Composable
fun LanguageSelector() {
    // Retrieve the currently configured app locale.
    // If no app-specific locale is set, LocaleListCompat.get(0) returns null,
    // so we safely fall back to a default (e.g., "en").
    val appLocales = AppCompatDelegate.getApplicationLocales()
    val currentLocaleTag = appLocales.get(0)?.toLanguageTag() ?: "en"

    // Example UI: A button to toggle between English and Spanish
    Button(
        onClick = {
            val newLanguageTag = if (currentLocaleTag == "en") "es" else "en"
            val localeList = LocaleListCompat.forLanguageTags(newLanguageTag)

            // Setting the locale re-creates the Activity by default,
            // which automatically applies the new configuration to Compose.
            AppCompatDelegate.setApplicationLocales(localeList)
        }
    ) {
        Text(
            text = if (currentLocaleTag == "en") "Switch to Spanish" else "Switch to English"
        )
    }
}

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

val appLocale: LocaleListCompat = 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 フレームワーク内で setApplicationLocalesgetApplicationLocales メソッドを使用することもできます。

次のコード スニペットは、LocaleManager システム サービスを使用して、ユーザーの使用言語を設定して取得する方法を示しています。

import android.app.LocaleManager
import android.content.Context
import android.os.Build
import android.os.LocaleList
import androidx.annotation.RequiresApi
import java.util.Locale

@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun setAppLanguage(context: Context, languageTag: String) {
    // 1. Retrieve the system service
    val localeManager = context.getSystemService(LocaleManager::class.java)

    // 2. Create a LocaleList from the language tag (e.g., "es-ES" or "ja")
    val localeList = LocaleList(Locale.forLanguageTag(languageTag))

    // 3. Set the locale. The system automatically updates the locale and
    // restarts the app, including any necessary configuration updates.
    localeManager.applicationLocales = localeList
}

@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun getAppLanguage(context: Context): String {
    val localeManager = context.getSystemService(LocaleManager::class.java)
    val currentLocales = localeManager.applicationLocales

    // Return the primary app locale, or fall back to the system default
    return if (!currentLocales.isEmpty) {
        currentLocales.get(0).toLanguageTag()
    } else {
        Locale.getDefault().toLanguageTag()
    }
}

その他のベスト プラクティス

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

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

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

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

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

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

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

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

// 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()

サンプル 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="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="fil"/> <!-- Filipino -->
   <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="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="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-Hans"/> <!-- Chinese (Simplified) -->
   <locale android:name="zh-Hant"/> <!-- Chinese (Traditional) -->
   <locale android:name="zu"/> <!-- Zulu -->
</locale-config>

参考情報

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