Использование локализаций и кодов локали во Flutter SDK

Почему это важно

Коды локалей используются, когда Adapty выбирает локализацию для флоу и когда вы читаете Remote Config для кастомного пейвола.

Коды локалей — штука непростая: они отличаются от платформы к платформе, поэтому Adapty использует единый внутренний стандарт для всех поддерживаемых платформ. Понимание этого стандарта поможет вам предсказать, какую локализацию получит пользователь.

Стандарт кодов локали в Adapty

Для кодов локали Adapty использует слегка модифицированный стандарт BCP 47: каждый код состоит из подтегов в нижнем регистре, разделённых дефисами. Примеры: en (английский), pt-br (португальский (Бразилия)), zh (упрощённый китайский), zh-hant (традиционный китайский).

Сопоставление кодов локали

Когда Adapty ищет локализацию, соответствующую языковому стандарту пользователя, происходит следующее:

  1. Строка локали преобразуется в нижний регистр, все символы подчёркивания (_) заменяются дефисами (-)
  2. Adapty ищет локализацию с полностью совпадающим кодом локали
  3. Если совпадение не найдено, Adapty берёт подстроку до первого дефиса (pt для pt-br) и ищет соответствующую локализацию
  4. Если совпадение снова не найдено, Adapty возвращает локализацию по умолчанию — en

Таким образом, 'pt_BR', pt-BR и pt-br — все они указывают на одну и ту же локализацию.

Реализация локализаций

В SDK v4 передавать код локали при получении флоу не нужно.

  • Пейволы из Flow Builder и Paywall Builder: Adapty автоматически определяет локализацию на основе настроек устройства и локализаций, заданных в билдере. Отображайте флоу через createFlowView — код локали не требуется.
  • Кастомные пейволы (Remote Config): getFlow возвращает все настроенные локализации в flow.remoteConfigs. Каждая запись содержит код локали locale и содержимое конфига (строка data или разобранный dictionary). Выберите нужную запись по настройкам пользователя, задав собственный фолбэк:

final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID');
final config = flow.remoteConfigs.firstWhereOrNull((c) => c.locale == 'en') ??
    flow.remoteConfig; // the first remote config, if present
// read your values from config?.dictionary

Правила сопоставления кодов локали, описанные выше, объясняют, как Adapty нормализует коды locale, хранящиеся в каждом Remote Config.

Почему это важно

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

Поскольку коды локалей бывают сложными и могут различаться в зависимости от платформы, мы используем внутренний стандарт для всех поддерживаемых платформ. Тем не менее именно из-за этой сложности важно чётко понимать, что именно вы отправляете на наш сервер для получения нужной локализации и что происходит дальше — чтобы вы всегда получали именно то, что ожидаете.

Стандарт кодов локалей в Adapty

Для кодов локалей Adapty использует немного изменённый стандарт BCP 47: каждый код состоит из подтегов в нижнем регистре, разделённых дефисами. Примеры: en (английский), pt-br (португальский (Бразилия)), zh (упрощённый китайский), zh-hant (традиционный китайский).

Сопоставление кода локали

Когда Adapty получает вызов от клиентского SDK с кодом локали и начинает искать соответствующую локализацию пейвола, происходит следующее:

  1. Входящая строка локали приводится к нижнему регистру, а все символы подчёркивания (_) заменяются дефисами (-)
  2. Затем выполняется поиск локализации с полностью совпадающим кодом локали
  3. Если совпадение не найдено, берётся подстрока до первого дефиса (pt для pt-br) и выполняется поиск подходящей локализации
  4. Если совпадение снова не найдено, возвращается локализация по умолчанию — en Таким образом, устройство iOS, отправившее 'pt_BR', устройство Android, отправившее pt-BR, и другое устройство, отправившее pt-br, получат одинаковый результат.

Если вы задаётесь вопросом о локализациях, скорее всего, вы уже работаете с файлами локализованных строк в своём проекте. В таком случае мы рекомендуем добавить в каждый файл пару ключ-значение с нужным кодом локали Adapty для соответствующей локализации. Затем при вызове SDK извлекайте значение по этому ключу, как показано ниже:

// 1. Modify your app_en.arb, app_es.arb, app_pt_br.arb files

/*
app_en.arb
*/
"adapty_paywalls_locale": "en",

/*
app_es.arb
*/
"adapty_paywalls_locale": "es",

/*
app_pt_br.arb
*/
"adapty_paywalls_locale": "pt-br",

// 2. Extract and use the locale code
final locale = AppLocalizations.of(context)!.adapty_paywalls_locale;
// pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method

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

Реализация локализаций: альтернативный способ

Похожего (но не идентичного) результата можно добиться без явного указания кодов локали для каждой локализации. Это означает извлечение кода локали из других объектов, предоставляемых вашей платформой, например:

final locale = Localizations.localeOf(context).languageCode;
// pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method

Обратите внимание, что мы не рекомендуем этот подход по нескольким причинам:

  1. На iOS предпочтительные языки и текущая локаль — не одно и то же. Чтобы локализация подбиралась корректно, придётся либо опираться на логику Apple (которая работает из коробки при рекомендованном подходе с локализованными строковыми файлами), либо реализовывать её самостоятельно.
  2. Сложно предсказать, что именно получит сервер Adapty. Например, на iOS устройство может вернуть локаль вида ar_OM@numbers='latn', которая будет отправлена на сервер. В ответ вы получите не локализацию ar-om, которую ожидали, а ar — что, скорее всего, не то, что нужно. Should you decide to use this approach anyway — make sure you’ve covered all the relevant use cases.