В переходе между i18next v20 и v21+ основная сложность миграции связана не с одной конкретной «ломающей» правкой, а с совокупностью изменений в типизации, модульной структуре, поведении загрузчиков и усилением строгих контрактов API. Переход следует рассматривать как эволюцию архитектуры интернационализации, где старые паттерны продолжают работать, но часть из них либо депрецируется, либо начинает требовать явного конфигурирования.
Ключевой принцип миграции: проверка всех точек инициализации i18next,
всех подключаемых плагинов и всех мест, где используются ресурсы
переводов вне стандартного flow
init → loadResources → t().
В v21+ заметно усиливается контроль за структурой объекта конфигурации:
Пример старого и нового подхода:
// v20
i18next.init({
lng: 'ru',
fallbackLng: 'en',
resources: {
ru: {
translation: {
hello: "Привет"
}
}
}
});
В v21+ при использовании TypeScript или строгих сборок:
i18next.init({
lng: 'ru',
fallbackLng: ['en'],
resources: {
ru: {
translation: {
hello: "Привет"
}
}
}
});
Изменение на массив fallbackLng становится
предпочтительным паттерном, особенно в сценариях с несколькими
резервными языками.
В новых версиях усиливается ориентация на ESM-экосистему:
import вместо requireРанее распространённый CommonJS-подход:
const i18next = require('i18next');
Современный ESM-подход:
import i18next from 'i18next';
При использовании плагинов важно проверять, что они также поддерживают ESM, иначе потребуется явный interop:
import Backend from 'i18next-http-backend';
i18next
.use(Backend)
.init({ /* config */ });
В v21+ более предсказуемой становится работа backend-плагинов. Основные изменения проявляются в следующих аспектах:
Старый callback-подход:
backend.load('ru', 'translation', (err, data) => {
// обработка
});
Современный подход:
backend.load('ru', 'translation')
.then(data => {
// обработка
})
.catch(err => {
// обработка ошибок
});
Интерполяция в i18next остаётся совместимой, однако в v21+ усиливается предсказуемость:
escapeValue требует явного контроляПример:
i18next.init({
interpolation: {
escapeValue: false
}
});
В миграции важно проверить все места, где ранее полагались на автоматическое экранирование.
Namespaces становятся более явно управляемыми сущностями:
t()Пример конфигурации:
i18next.init({
ns: ['common', 'auth'],
defaultNS: 'common',
fallbackNS: 'common'
});
Типовая проблема миграции: использование t() до полной
загрузки всех namespaces.
При использовании связки с React (через react-i18next) v21+ усиливает зависимость от корректной асинхронной модели.
Основные изменения:
Пример современного подхода:
import { useTranslation } from 'react-i18next';
function Header() {
const { t } = useTranslation('common');
return <h1>{t('title')}</h1>;
}
Важно учитывать, что в некоторых конфигурациях Suspense становится обязательным для корректной загрузки ресурсов:
i18next.init({
react: {
useSuspense: true
}
});
В v21+ усиливается типизация:
t()Типовая проблема миграции:
t('nonExistingKey')
Теперь может вызывать предупреждения при строгой конфигурации типов.
Решение:
t('known.key' as const)
или расширение деклараций:
declare module 'i18next' {
interface CustomTypeOptions {
resources: {
common: typeof resources.common;
};
}
}
В v21+ логика fallback становится менее «эвристической» и более явно заданной конфигурацией:
Пример:
i18next.init({
fallbackLng: ['en', 'de', 'ru']
});
При миграции важно проверить порядок языков, так как он начинает играть более критичную роль.
Часть устаревших API становится недоступной или требует включения совместимости:
Типовая проблема:
i18next.loadNamespaces('common', () => {});
Замена:
await i18next.loadNamespaces('common');
При использовании i18next-browser-languagedetector:
Пример:
i18next.init({
detection: {
order: ['querystring', 'cookie', 'localStorage', 'navigator'],
caches: ['localStorage']
}
});
Переход между версиями v20 и v21+ требует последовательной проверки:
t() в асинхронных контекстахКритическим этапом становится анализ зависимостей:
Несовместимость одного плагина часто проявляется не сразу, а в виде задержек загрузки переводов или отсутствующих fallback-значений.
Наиболее частые регрессии при миграции:
Lifecycle i18next становится ближе к модели:
Любое отклонение от этой последовательности теперь чаще приводит к явным ошибкам или пустым результатам, вместо «тихого деградационного поведения», характерного для v20.