Поддержка региональных вариантов в i18next основана на работе с языковыми тегами стандарта BCP 47, где язык и регион кодируются в одном идентификаторе. Такой подход позволяет разделять не только разные языки, но и локализованные формы одного языка: различия в орфографии, форматах дат, числах, падежах и терминологии.
Типичный формат идентификатора:
en — английский язык без уточнения регионаen-US — английский (США)en-GB — английский (Великобритания)ru — русский языкru-RU — русский (Россия)pt — португальскийpt-BR — бразильский португальскийzh — китайский (обобщённый)zh-CN, zh-TW — упрощённый и традиционный
вариантыi18next трактует такие идентификаторы как иерархию, где региональный вариант может наследовать базовый язык.
Основой работы региональных вариантов является механизм fallback. Если перевод для регионального кода отсутствует, используется более общий язык.
Пример иерархии:
en-US → en → fallbackLng
ru-KZ → ru → fallbackLng
pt-BR → pt → fallbackLng
Конфигурация fallback задаётся через fallbackLng:
import i18n from 'i18next';
i18n.init({
lng: 'en-US',
fallbackLng: 'en',
resources: {
en: {
translation: {
greeting: "Hello"
}
},
en-US: {
translation: {
greeting: "Howdy"
}
}
}
});
В этом примере при запросе en-US используется
специфичная строка "Howdy", а при отсутствии ключа —
значение из en.
Организация ресурсов напрямую влияет на масштабируемость поддержки регионов. Варианты структурирования:
locales/
en/
translation.json
en-US/
translation.json
en-GB/
translation.json
ru/
translation.json
ru-RU/
translation.json
Пример содержимого:
// locales/en/translation.json
{
"currency": "USD",
"dateFormat": "MM/DD/YYYY"
}
// locales/en-GB/translation.json
{
"currency": "GBP",
"dateFormat": "DD/MM/YYYY"
}
При отсутствии полного набора региональных файлов используется минимальный набор различий:
i18n.init({
fallbackLng: 'en',
resources: {
en: {
translation: {
currency: "USD",
greeting: "Hello"
}
},
"en-GB": {
translation: {
currency: "GBP"
}
}
}
});
Значение greeting для en-GB будет взято из
en.
i18next позволяет задавать каскад fallback-локалей:
i18n.init({
fallbackLng: {
'en-GB': ['en-GB', 'en', 'default'],
'ru-KZ': ['ru-KZ', 'ru', 'default']
}
});
Такая структура полезна при частичном перекрытии региональных различий.
Модуль i18next-browser-languagedetector позволяет
извлекать регион из окружения пользователя:
import i18n from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
i18n
.use(LanguageDetector)
.init({
fallbackLng: 'en',
detection: {
order: ['navigator', 'htmlTag', 'cookie', 'localStorage']
}
});
Если браузер возвращает en-US, библиотека попытается
использовать именно этот вариант.
i18next приводит к единому формату:
EN-us → en-USru_ru → ru-RUpt_br → pt-BRЭто позволяет избегать дублирования ресурсов из-за различий в написании.
Хотя i18next отвечает за перевод строк, интеграция с
Intl API обеспечивает локализацию форматов.
const value = 123456.78;
new Intl.NumberFormat('en-US').format(value); // 123,456.78
new Intl.NumberFormat('de-DE').format(value); // 123.456,78
В связке с i18next региональный код используется как единый источник локали.
new Intl.DateTimeFormat('en-GB').format(new Date());
new Intl.DateTimeFormat('en-US').format(new Date());
Разделение локалей в i18next часто синхронизируется с форматированием дат через пользовательские хелперы:
i18n.services.formatter.add('date', (value, lng) => {
return new Intl.DateTimeFormat(lng).format(new Date(value));
});
Различия между региональными вариантами часто касаются:
Пример:
const resources = {
en: {
translation: {
"payment": "Payment"
}
},
"en-US": {
translation: {
"payment": "Checkout"
}
},
"en-GB": {
translation: {
"payment": "Payment"
}
}
};
Региональные изменения могут быть минимальными, но важными для UX.
i18next поддерживает разделение по namespace, что позволяет комбинировать региональные вариации и модули приложения.
en-US:
common.json
checkout.json
profile.json
i18n.init({
ns: ['common', 'checkout', 'profile'],
defaultNS: 'common',
resources: {
"en-US": {
common: {
title: "Dashboard"
},
checkout: {
button: "Pay now"
}
}
}
});
Региональные различия могут быть точечными, без дублирования всей локали.
{
"en": {
"button.save": "Save"
},
"en-US": {
"button.save": "Save changes"
}
}
Такая структура снижает объём повторяющихся переводов.
Для языков с множеством регионов применяется группировка:
i18n.init({
fallbackLng: 'en',
load: 'languageOnly'
});
Режим languageOnly отключает строгую привязку к
региону:
en-US → enen-GB → enЭто упрощает поддержку при отсутствии значимых региональных отличий.
При масштабировании приложения региональные переводы часто загружаются отдельно:
i18n.init({
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json'
}
});
Запросы могут выглядеть так:
/locales/en-US/common.json
/locales/ru-RU/common.json
Это позволяет минимизировать объём загружаемых данных.
Некоторые языки используют разные правила множественного числа в зависимости от региона.
i18next подключает ICU или встроенные правила:
i18n.init({
compatibilityJSON: 'v3',
returnObjects: true
});
Пример:
{
"item": "{{count}} item",
"item_plural": "{{count}} items"
}
Регион может влиять на отображение форм через кастомные правила.
При сложной конфигурации выбирается приоритет:
i18n.init({
lng: 'ru-KZ',
fallbackLng: 'ru'
});
Если ru-KZ отсутствует, используется
ru.
Конфликты возникают при:
Пример проблемной структуры:
ru/
ru-RU/
ru-KZ/
без чёткой стратегии наследования приводит к неоднозначности выбора ресурса.