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

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

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

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

Стандарт кодов локалей в 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 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);
  };
};

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

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

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


const getLocaleCode = () => {
  if (Capacitor.getPlatform() === 'ios') {
    return navigator.language || 'en';
  } else {
    return navigator.language || 'en';
  }
};

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

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

  1. На iOS предпочтительные языки и текущая локаль — не одно и то же. Чтобы локализация определялась корректно, придётся либо полагаться на логику Apple (которая работает «из коробки» при использовании рекомендованного подхода с локализованными строковыми файлами), либо воссоздавать её самостоятельно.
  2. Сложно предсказать, что именно получит сервер Adapty. Например, на iOS устройство может вернуть локаль вида ar_OM@numbers='latn', которая отправится на наш сервер. В ответ на такой запрос вы получите не локализацию ar-om, на которую рассчитывали, а ar — что, скорее всего, не то, что ожидалось.

Если вы всё же решите использовать этот подход — убедитесь, что охватили все возможные сценарии.