Языковые настройки для каждого приложения

Языки для каждого приложения в настройках системы

Во многих случаях многоязычные пользователи устанавливают в своей системе один язык, например английский, но они хотят выбрать другие языки для конкретных приложений, например голландский, китайский или хинди. Чтобы приложения были более удобными для этих пользователей, в Android 13 представлены следующие функции для приложений, поддерживающих несколько языков:

  • Системные настройки : централизованное место, где пользователи могут выбрать предпочтительный язык для каждого приложения.

    Вы можете настроить свое приложение так, чтобы оно автоматически создавало файлы, необходимые для поддержки языковых настроек каждого приложения, и отображало их в настройках системы. Чтобы узнать больше, ознакомьтесь с инструкциями по включению автоматической поддержки языка для каждого приложения .

  • Дополнительные API . Эти общедоступные API, такие как методы setApplicationLocales() и getApplicationLocales() в LocaleManager , позволяют приложениям устанавливать язык, отличный от языка системы, во время выполнения.

    Эти API автоматически синхронизируются с настройками системы; поэтому приложения, которые используют эти API для создания пользовательских средств выбора языка в приложении, обеспечат своим пользователям единообразный пользовательский интерфейс независимо от того, где они выбирают свои языковые предпочтения. Публичные API также помогают сократить объем шаблонного кода, поддерживают разделенные APK-файлы и поддерживают автоматическое резервное копирование для приложений для хранения настроек языка пользователя на уровне приложения.

    Для обратной совместимости с предыдущими версиями Android в AndroidX также доступны эквивалентные API. Однако API-интерфейсы обратной совместимости работают с контекстом AppCompatActivity, а не с контекстом приложения для Android 12 (уровень API 32) и более ранних версий. Получите доступ к обратно совместимым API с помощью Appcompat 1.6.0 или более поздней версии.

Обзор реализации этой функции

В следующей таблице показаны рекомендуемые реализации, основанные на различных вариантах использования.

Вариант использования Рекомендуемая реализация
В вашем приложении нет встроенного средства выбора языка.
  1. Включите автоматическую поддержку языков для каждого приложения, чтобы создать файл LocaleConfig и добавить языки вашего приложения в настройки системы.
  2. При желании, если вы хотите добавить средство выбора языка в приложении: используйте библиотеку AndroidX и согласитесь на нашу реализацию API для поддержки обратной совместимости через autoStoreLocales .
В вашем приложении уже есть средство выбора языка.
  1. Включите автоматическую поддержку языков для каждого приложения, чтобы создать файл LocaleConfig и добавить языки вашего приложения в настройки системы.
  2. Перенесите пользовательскую логику вашего приложения на использование общедоступных API , чтобы пользователи видели единообразный интерфейс.
  3. Обработайте следующие угловые случаи:
    1. Вызовите AppCompatDelegate.setApplicationLocales() при первом запуске вашего приложения на устройстве под управлением Android 13.
    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. Чтобы включить эту функцию, используйте generateLocaleConfig в блоке androidResources {} файла build.gradle.kts уровня модуля (файл build.gradle , если вы используете Groovy). По умолчанию эта функция отключена.

    Котлин

        android {
          androidResources {
            generateLocaleConfig = true
          }
        }
        

    классный

        android {
          androidResources {
            generateLocaleConfig true
          }
        }
        
  2. Укажите локаль по умолчанию:
    1. В папке res модуля приложения создайте новый файл с именем resources.properties .
    2. В файле resources.properties установите языковой стандарт по умолчанию с меткой unqualifiedResLocale . Чтобы отформатировать имена локалей, см. раздел «Как сформировать имена локалей» .

AGP добавляет этот локаль по умолчанию и любые альтернативные локали, которые вы указали, используя каталоги values-* в папке res , в автоматически созданный файл LocaleConfig .

Как формировать названия локалей

Чтобы сформировать названия локалей, объедините код языка с необязательными кодами алфавита и региона, разделяя их тире:

  • Язык: используйте двух- или трехбуквенный код ISO 639-1 .
  • Сценарий (необязательно): используйте код ISO 15924 .
  • Регион (необязательно): используйте либо двухбуквенный код ISO 3166-1-alpha-2 , либо трехзначный код UN_M.49 .

Например, если вашим языком по умолчанию является американский английский:

unqualifiedResLocale=en-US

Используйте android:localeConfig , чтобы добавить поддерживаемые языки в настройки системы.

Вы можете вручную настроить свое приложение, чтобы его языки можно было настроить в настройках системы на устройствах под управлением Android 13 или более поздней версии. Для этого создайте XML-файл locales_config и добавьте его в манифест вашего приложения, используя атрибут 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>
    

Вы можете динамически обновлять localeConfig вашего приложения с помощью LocaleManager.setOverrideLocaleConfig , чтобы настроить набор языков, отображаемых в списке языков для каждого приложения в настройках Android. Это позволяет вам настраивать список языков для каждого региона, запускать эксперименты A/B и предоставлять обновленные языковые стандарты, если ваше приложение использует push-уведомления о локализации на стороне сервера, как показано в следующем примере:

Котлин

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

Ява

//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 чтобы узнать язык пользовательского интерфейса текущего приложения и обновить язык клавиатуры, как показано:

Котлин

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

Ява

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

Укажите поддерживаемые языки в Gradle

Если они еще не указаны, укажите те же языки, используя свойство resourceConfigurations в файле build.gradle уровня модуля вашего приложения:

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

Если свойство resourceConfigurations присутствует, система сборки включает в APK языковой ресурс только для этих указанных языков, предотвращая включение переведенных строк из других библиотек, которые могут поддерживать языки, которые не поддерживаются вашим приложением. Дополнительную информацию см . в разделе «Укажите языки, которые поддерживает ваше приложение» .

Как пользователи выбирают язык приложения в настройках системы

Пользователи могут выбрать предпочитаемый язык для каждого приложения через настройки системы. Они могут получить доступ к этим настройкам двумя разными способами:

  • Доступ через настройки системы

    Настройки > Система > Языки и ввод > Языки приложений > (выберите приложение)

  • Доступ через настройки приложений

    Настройки > Приложения > (выберите приложение) > Язык.

Управление средствами выбора языка в приложении

Для приложений, которые уже имеют средство выбора языка в приложении или хотят его использовать, используйте общедоступные API вместо пользовательской логики приложения для обработки настройки и получения предпочтительного языка пользователя для вашего приложения. Если вы используете общедоступные API для выбора языка в приложении, системные настройки устройства автоматически обновляются в соответствии с тем языком, который пользователь выбирает в приложении.

Для обеспечения обратной совместимости с предыдущими версиями Android мы настоятельно рекомендуем использовать библиотеку поддержки AndroidX при реализации средства выбора языка в приложении. Однако при необходимости вы также можете реализовать API-интерфейсы платформы напрямую .

Реализация с использованием библиотеки поддержки AndroidX.

Используйте методы setApplicationLocales() и getApplicationLocales() в Appcompat 1.6.0 или более поздней версии. Обратите внимание, что API-интерфейсы обратной совместимости работают с контекстом AppCompatActivity, а не с контекстом приложения для Android 12 (уровень API 32) и более ранних версий.

Например, чтобы установить предпочтительный язык пользователя, вы должны попросить пользователя выбрать языковой стандарт в средстве выбора языка, а затем установить это значение в системе:

Котлин

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

Ява

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) и ниже сообщите AndroidX обрабатывать хранилище локали, установив для параметра autoStoreLocales значение true и android:enabled значение false в записи манифеста для службы 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() .

Индивидуальная обработка склада

Пропуск записи манифеста или установка autoStoreLocales false сигналов о том, что вы обрабатываете собственное хранилище. В этом случае вы должны предоставить сохраненные локали перед onCreate в жизненном цикле действия и вызовами шлюза AppCompatDelegate.setApplicationLocales() в Android 12 (уровень API 32) или ниже.

Если у вашего приложения есть собственное место хранения языковых стандартов, мы рекомендуем использовать однократную передачу между вашим пользовательским решением для хранения языковых стандартов и autoStoreLocales , чтобы пользователи продолжали пользоваться вашим приложением на том языке, который они предпочитают. Это особенно применимо в тех случаях, когда ваше приложение запускается впервые после обновления устройства до Android 13. В этом случае вы можете предоставить уже существующие локали, запрошенные пользователем, извлекая локали из своего пользовательского хранилища и передавая их в AppCompatDelegate.setApplicationLocales() .

Реализация с использованием API-интерфейсов платформы Android.

Хотя мы настоятельно рекомендуем вам использовать библиотеку поддержки AndroidX для реализации средств выбора языка в приложении, вы также можете использовать методы setApplicationLocales() и getApplicationLocales() в платформе Android для устройств под управлением Android 13.

Например, чтобы установить предпочтительный язык пользователя, вы должны попросить пользователя выбрать языковой стандарт в средстве выбора языка, а затем установить это значение в системе:

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

Дополнительные рекомендации

Обратите внимание на следующие рекомендации.

Учитывайте язык при вызове намерения в другом приложении

Намерения, ориентированные на язык, могут позволить вам указать язык, на котором вы хотите использовать вызываемое приложение. Одним из примеров является функция EXTRA_LANGUAGE из API распознавания речи.

Рассмотрим заголовок Accept-Language для вкладки Chrome Custom.

Рассмотрите возможность добавления заголовка Accept-Language через Browser.EXTRA_HEADERS , чтобы открывать веб-страницу на языке вашего приложения при вызове пользовательской вкладки Chrome.

Если вы удалите языковые настройки для каждого приложения в настройках системы, сбросьте языковой стандарт вашего приложения на языковой стандарт системы.

Если вы удалите языковые настройки вашего приложения из настроек системы (удалив android:localeConfig из AndroidManifest.xml вашего приложения), пользователи не смогут легко сбросить язык своего приложения обратно к системному языку по умолчанию.

По этой причине, если вы удалите 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()

Ява

// 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 Open Source Project (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>