Использование локализаций и кодов локали в React Native 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 возвращает контент для локали флоу по умолчанию

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

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

В SDK v4 вам не нужно передавать код локали при получении флоу — getFlow возвращает флоу со всеми его локализациями, а Adapty применяет нужную при построении представления флоу.

  • Флоу, созданные в билдере: SDK не считывает локаль устройства, поэтому определите её в своём приложении и передайте как параметр locale в createFlowView или в проп params встроенного компонента AdaptyFlowView. Параметр необязательный — если его не передать, флоу отображается на en либо в своей локали по умолчанию, если локализация en отсутствует. Если запросить локализацию, которой у флоу нет, отображение без ошибки переключится на дефолтную локаль флоу, а строки, отсутствующие в выбранной локализации, будут взяты из неё.

    import { createFlowView } from 'react-native-adapty';
    
    const view = await createFlowView(flow, { locale: 'es' });

view.locale сообщает, с какой локализацией был фактически собран экран — это запрошенная локаль, если такая локализация существует, или локаль по умолчанию для флоу в противном случае. Параметр locale и view.locale требуют React Native SDK 4.0.2 или более новой версии; в более ранних версиях view.locale равно undefined.

  • Кастомные пейволы (Remote Config): getFlow возвращает все настроенные локализации в flow.remoteConfigs. Каждая запись содержит код lang и объект data. Выберите запись, соответствующую пользователю, реализовав собственный фолбэк:

const flow = await adapty.getFlow('placement_id');
const config = flow.remoteConfigs?.find((c) => c.lang === 'en') ?? flow.remoteConfigs?.[0];
// read your values from config?.data

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

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

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

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

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

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

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

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

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

Таким образом, устройство iOS, отправившее 'pt_BR', устройство Android, отправившее pt-BR, и другое устройство, отправившее pt-br, получат одинаковый результат.

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

// 1. Modify your localization files (e.g., using react-i18next)

/*
en.json
*/
{
  "adapty_paywalls_locale": "en"
}

/*
es.json
*/
{
  "adapty_paywalls_locale": "es"
}

/*
pt-BR.json
*/
{
  "adapty_paywalls_locale": "pt-br"
}

// 2. Extract and use the locale code

const MyComponent = () => {
  const { t } = useTranslation();
  
  const fetchPaywall = async () => {
    const locale = t('adapty_paywalls_locale');
    // pass locale code to adapty.getPaywall or adapty.getPaywallForDefaultAudience method
    const paywall = await adapty.getPaywallForDefaultAudience('placement_id', locale);
  };
};

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

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

Можно получить похожий (но не идентичный) результат, не прописывая явно коды локалей для каждой локализации. Для этого нужно извлечь код локали из устройства — например, с помощью react-native-localize:


const fetchPaywall = async () => {
  // getLocales() returns the user's preferred locales in BCP-47 format (e.g., 'en-US', 'pt-BR')
  const locale = RNLocalize.getLocales()[0].languageTag;
  // pass locale code to adapty.getPaywall or adapty.getPaywallForDefaultAudience method
  const paywall = await adapty.getPaywallForDefaultAudience('placement_id', locale);
};

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

  1. На iOS предпочитаемые языки и текущая региональная локаль — это не одно и то же. Чтобы локализация определялась корректно, нужно либо положиться на логику Apple — она работает из коробки при рекомендуемом подходе с локализованными строковыми файлами — либо реализовать аналогичную логику самостоятельно.
  2. Локаль устройства может не совпадать ни с одной из локализаций, настроенных в Adapty. В таком случае SDK откатывается к совпадению по первому субтегу или, в крайнем случае, к en — что может оказаться не тем языком, который вы хотели бы показать этому пользователю по умолчанию. Should you decide to use this approach anyway — make sure you’ve covered all the relevant use cases.