Спросите свой вопрос и получите сводку документа, используя эту страницу и выбранного вами поставщика AI
Содержимое этой страницы было переведено с помощью ИИ.
Смотреть последнюю версию оригинального контента на английскомЕсли у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.
Ссылка на документацию GitHubКопировать Markdown документа в буфер обмена
i18next VS @intlayer/i18next: Тот же API, другой бандл

@intlayer/i18next, @intlayer/react-i18next и @intlayer/next-i18next - это адаптеры совместимости. Они предоставляют API i18next, который уже использует ваш код (useTranslation, t(), <Trans>, i18n.changeLanguage(), getFixedT, serverSideTranslations...), и передают данные из словарей, скомпилированных Intlayer. Компоненты не меняются. Меняется среда выполнения (runtime) под ними.
В этой статье измеряется эффект от этой замены на одном и том же приложении Next.js, собранном сначала с next-i18next, а затем с @intlayer/next-i18next. Исходные цифры взяты из Benchmark Bloom. Если вас интересует сравнение i18next и Intlayer как отдельных библиотек, прочтите i18next vs Intlayer. Этот материал посвящен тому, что именно меняет адаптер, если вы оставляете свой код в исходном виде.
tl;dr: В одном и том же приложении Next.js заменаnext-i18nextна@intlayer/next-i18nextуменьшила объем JavaScript на страницу с 218.5 КБ до 150.7 КБ gzip (базовая конфигурация) и превзошла полностью оптимизированную конфигурациюnext-i18next(163.4 КБ) на 12.7 КБ. Средний компонент уменьшился с 78.5 КБ до 9.7 КБ, утечка строк других страниц упала с ~90% до 0%, гидратация ускорилась с 15.6 мс до 11.3 мс, а runtime сократился с 19.7 КБ до 9.4 КБ. Ни один компонент не редактировался; изменился только файл провайдера. Плагиныi18next(бэкенды, детекторы языка) принимаются, но ничего не делают: во время выполнения больше нечего загружать или определять.
Что такое @intlayer/i18next
i18next - это рантайм. Вызов i18n.init({ resources }) или бэкенд-плагин загружает locales/{lng}/{ns}.json в глобальный экземпляр; вызов useTranslation("about") подписывает компонент на него; t("title") ищет ключ во время рендеринга. Пространства имен (namespaces), ленивая загрузка, списки пространств имен для каждой страницы и строгая типизация полностью остаются на вашей стороне для настройки и поддержки.
Адаптеры сохраняют API и заменяют глобальный экземпляр:
- Алиасы импорта. Функция
createNextI18nPlugin()из@intlayer/next-i18next/plugin(илиwithI18next) оборачиваетwithIntlayerи добавляет алиасы Webpack / Turbopack, благодаря чемуnext-i18next,react-i18nextиi18nextразрешаются в соответствующие пакеты@intlayer/*. В VitereactI18nextVitePlugin()из@intlayer/react-i18next/pluginвыполняет ту же задачу. Ни один импорт не переименовывается. - JSON как единственный источник истины. Плагин
syncJSONсчитывает существующие файлыlocales/{lng}/{ns}.jsonс параметромformat: "i18next"(поэтому{{name}}, вложенность$t(), суффиксы_one/_otherи контекстные суффиксы разбираются корректно) и записывает переводы обратно, когда CLI или CMS обновляют их. - Связывание на месте вызова. Этап оптимизации Intlayer переписывает
useTranslation("about")в вызов, который напрямую получает словарьaboutв активной локали. Компонент больше не обращается к глобальному хранилищу.
Копировать код в буфер обмена
Копировать код в буфер обмена
Именно эта перезапись обеспечивает колоссальное уменьшение размера компонентов и ликвидацию утечек контента в таблице ниже.
Что адаптеры сохраняют, игнорируют и не заменяют
Открыть таблицу в модальном окне для четкого просмотра всех данных
API i18next | С @intlayer/* |
|---|---|
useTranslation("ns"), useTranslation("ns", { keyPrefix }) | ✅ Сохранено. Привязывается к словарю ns во время сборки; ключи типизированы по вашему контенту |
t("key", { name }), {{interpolation}}, вложенность $t(key) | ✅ Сохранено |
Формы множественного числа key_one / key_other, контекст key_male, returnObjects | ✅ Сохранено. Множественные числа рассчитываются через Intl.PluralRules |
<Trans> с components, нумерованными тегами <1>...</1>, values | ✅ Сохранено |
withTranslation, Translation, I18nContext | ✅ Сохранено |
i18n.changeLanguage(), i18n.language, i18n.dir(), on("languageChanged") | ✅ Сохранено. changeLanguage управляет локалью Intlayer |
getFixedT(lng, ns, keyPrefix), i18n.exists(), hasLoadedNamespace() | ✅ Сохранено |
i18n.use(Backend).use(LanguageDetector).init({...}) | ⚠️ use() вызывает init плагина и завершает работу; бэкендам и детекторам нечего загружать или определять |
init({ resources }), addResourceBundle() | ⚠️ resources игнорируется с предупреждением в dev-режиме; удалите импорты JSON для снижения веса бандла |
I18nextProvider i18n={i18n} | ⚠️ Рендерит IntlayerProvider; проп i18n игнорируется. В App Router передайте локаль (см. ниже) |
serverSideTranslations(locale, ["common"]) (next-i18next) | ⚠️ Возвращает ожидаемую структуру и ничего не загружает. Безопасно оставить, безопасно удалить |
appWithTranslation(App) (next-i18next) | ✅ Сохранено |
next-i18next.config.js | ⚠️ Не считывается. Локали берутся из intlayer.config.ts |
Простой useTranslation() без пространства имен | ✅ Работает со словарем translation всего файла целиком (splitKeys: false) |
Бенчмарк
Что измерялось
Тестовый набор Benchmark Bloom собирает одно и то же приложение в каждой конфигурации: 10 страниц (главная, о нас, блог, карьера, контакты, FAQ, цены, продукты, настройки, команда), 10 локалей (en, fr, es, de, it, pt, zh, ja, ko, ru), идентичные компоненты и контент. Страницы тестируются в en и fr.
Сборка next-i18next тестировалась по четырем стратегиям: от импорта всех JSON в resources (static) до отдельного пространства имен на маршрут с ленивой загрузкой через бэкенд (scoped-dynamic). Адаптер тестировался на тех же компонентах, что и базовая сборка, с изменениями только в next.config.ts, intlayer.config.ts и файле провайдера. У него нет ручного режима "scoped": компилятор изолирует контент для каждого компонента автоматически.
Для каждой сборки фиксируются показатели:
- Размер библиотеки: gzip-размер пустого компонента, который импортирует только библиотеку i18n.
- JS на страницу: средний объем gzip JavaScript, загружаемый на страницу по всем маршрутам и локалям.
- % утечки локали: доля строк в загруженном JS, относящаяся к языку, который пользователь в данный момент не просматривает.
- % утечки страницы: доля строк в загруженном JS, относящаяся к странице, на которой пользователь в данный момент не находится.
- Средний вес компонента: средний gzip-размер каждого изолированно скомпилированного компонента.
- E2E-реактивность: реальное время между выбором новой локали и обновлением атрибута
html[lang]в DOM (Playwright, 5 итераций). - Гидратация: продолжительность фазы гидратации React.
Приведенные ниже цифры получены в прогоне от 12.09.2026 с версиямиnext-i18next16.3.0 (react-i18next17.0.13,i18next26.4.2) и@intlayer/next-i18next9.5.1. Тестовое приложение намеренно компактное (несколько десятков строк на локаль), поэтому проценты утечки отражают тенденцию: они масштабируются вместе с вашим контентом, тогда как стоимость рантайма остается неизменной.
Результаты на Next.js
Выберите метрики и библиотеки, которые вас интересуют:
Метрика
Динамическая загрузка JSON
Ленивая загрузка переводов во время выполнения
Ограниченный JSON (пространства имен)
Пространства имен перевода для каждой страницы
Что это за метрика?
Общий размер пакета библиотеки интернационализации в формате gzip. Он включает в себя только провайдер и логику извлечения контента после tree-shaking и минификации.
Почему это важно?
Меньший размер библиотеки снижает начальную загрузку JavaScript, что ускоряет загрузку и выполнение кода на клиенте.
Вид
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Конфигурация | Стратегия | Размер либы (gz) | JS стр сред (gz) | Утечка локали | Утечка стр | Комп сред (gz) | E2E-реактивность | Гидратация |
|---|---|---|---|---|---|---|---|---|
| base (без i18n) | - | 0.0 КБ | 141.0 КБ | 0.0% | 0.0% | 0.9 КБ | 13.4 мс | 11.8 мс |
next-i18next | static | 19.7 КБ | 218.5 КБ | 0.0% | 89.8% | 78.5 КБ | 16.4 мс | 15.6 мс |
next-i18next | dynamic | 19.7 КБ | 169.5 КБ | 50.0% | 89.8% | 26.1 КБ | 15.4 мс | 27.7 мс |
next-i18next | scoped-static | 19.7 КБ | 220.1 КБ | 0.0% | 89.8% | 78.9 КБ | 16.4 мс | 14.7 мс |
next-i18next | scoped-dynamic | 19.7 КБ | 163.4 КБ | 0.0% | 0.0% | 27.1 КБ | 15.9 мс | 15.1 мс |
@intlayer/next-i18next | static | 9.4 КБ | 150.7 КБ | 0.0% | 0.0% | 9.7 КБ | 10.7 мс | 11.3 мс |
@intlayer/next-i18next | dynamic | 9.4 КБ | 150.7 КБ | 0.0% | 0.0% | 9.7 КБ | 11.9 мс | 10.6 мс |
next-intlayer (native) | static | 5.5 КБ | 141.3 КБ | 0.0% | 0.0% | 8.5 КБ | 15.5 мс | 16.9 мс |
next-intlayer (native) | dynamic | 5.5 КБ | 141.3 КБ | 0.0% | 0.0% | 6.9 КБ | 15.3 мс | 15.9 мс |
Как читать эти данные
- На 68 КБ меньше на страницу по сравнению с базовым подходом. Подход
resources: { en, fr, ... }отправляет каждую локаль и каждое пространство имен на каждую страницу: 218.5 КБ. Сборка с адаптером для тех же компонентов составляет 150.7 КБ. Она также обходит лучшую конфигурациюnext-i18next(163.4 КБ, одно пространство имен на маршрут с ленивой загрузкой) на 12.7 КБ, поскольку только рантаймi18nextвесит 19.7 КБ против 9.4 КБ. - Утечка снижается до 0% без правки компонентов. Любая конфигурация
next-i18next, кроме полностью изолированной вручную, отправляет ~90% строк посторонних страниц. Строкаdynamicна практике проигрывает: она не устраняет утечку страниц и добавляет 50% утечки локалей, так как бэкенд для локали вытягивает всё пространство именtranslation. Адаптер обеспечивает 0% / 0% сразу на исходном коде. - Компоненты легче в 8 раз. Компонент с
useTranslation(), скомпилированный изолированно, весит в среднем 78.5 КБ с инлайновымиresourcesи 26-27 КБ с бэкендом, так какtжестко связан с глобальным хранилищем. С адаптером его вес падает до 9.7 КБ. - Быстрее гидратация и переключение локали. Гидратация ускоряется с 15.6 мс до 11.3 мс (и с 27.7 мс в конфигурации
dynamic, где запрос бэкенда блокирует критический путь). Переключение языка ускоряется с 15-16 мс до 11-12 мс. - Адаптер не равен нативному рантайму.
next-intlayerвесит 141.3 КБ, всего на +0.3 КБ больше базового приложения без i18n. Адаптер несет поверх ядра Intlayer всю поверхность APIi18next(синтаксис интерполяции, суффиксы чисел и контекста, разбор тегов<Trans>): 9.4 КБ и +9.4 КБ на страницу относительно нативного решения. Это промежуточный мост, а не конечная точка.
Полная таблица, каждая библиотека и каждая стратегия, в отчете о бенчмарке Next.js.
Результаты на TanStack Start (react-i18next)
Для Vite и TanStack Start бенчмарк сравнивает обычный react-i18next с intlayer:
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Библиотека | Стратегия | Размер либы (gz) | JS стр сред (gz) | Утечка локали | Утечка стр | Комп сред (gz) | E2E-реактивность | Гидратация |
|---|---|---|---|---|---|---|---|---|
| base (без i18n) | - | 0.0 КБ | 111.0 КБ | 0.0% | 0.0% | 0.7 КБ | 8.1 мс | 21.6 мс |
react-i18next | dynamic | 18.4 КБ | 136.4 КБ | 23.1% | 89.8% | 24.8 КБ | 123.1 мс | 32.9 мс |
intlayer | dynamic | 5.0 КБ | 118.6 КБ | 0.0% | 0.0% | 6.3 КБ | 3.6 мс | 14.1 мс |
Полная таблица в отчете о бенчмарке TanStack Start.
Адаптерreact-i18nextна Vite / TanStack Start не входил в этот тестовый прогон. Базовые замеры дляreact-i18nextна TanStack Start можно найти в статье i18next vs Intlayer: 127-184 КБ на страницу и 123-185 мс задержки переключения языка при отложенном бэкенде.
Почему изменяются показатели

В директории components/ ничего не менялось, поэтому весь выигрыш достигается за счет того, к чему привязан useTranslation.
В случае i18next привязка идет к глобальному экземпляру. Все, что было в него загружено (все языки в static, всё пространство имен активного языка в dynamic), доступно из любого компонента, вызывающего useTranslation(). Бандлер не может разделить код тоньше того, что удерживает экземпляр, а среда выполнения не знает, какие ключи понадобятся при рендеринге.
Копировать код в буфер обмена
Все, что содержит экземпляр, отправляется на каждую страницу, и утечки растут по двум осям, страницы и локали:

В случае @intlayer/next-i18next связывание идет напрямую со словарем. Плагин syncJSON превращает каждый файл пространства имен в словарь; оптимизатор передает компоненту только запрошенный словарь в виде импорта, который сборщик может отследить и разделить по страницам и локалям.
Копировать код в буфер обмена
Файл i18n/i18n.ts и импорт resources превращаются в мертвый код. Именно отсюда берется экономия в 68 КБ.
Миграция в три шага
Установка
bashКопировать кодКопировать код в буфер обмена
Команда распознает
i18next/react-i18next/next-i18next, установитintlayer, пакет фреймворка (next-intlayerилиreact-intlayer), соответствующий адаптер@intlayer/*и@intlayer/sync-json-plugin, а также сгенерируетintlayer.config.ts. Оставьте исходные библиотеки установленными: они выступают peer dependencies и предоставляют типы.Настройка путей к файлам локалей
intlayer.config.tsКопировать кодКопировать код в буфер обмена
Если у вас один файл
translation.jsonна локаль (дефолтный namespace в i18next), установитеsplitKeys: false, чтобы весь файл оставался единым словарем и прямой вызовuseTranslation()продолжал корректно работать.Подключение плагина
next.config.tsКопировать кодКопировать код в буфер обмена
В App Router клиентские компоненты получают локаль из сегмента
[locale]. АдаптерI18nextProviderне принимает проп локали, поэтому замените его единожды в файле провайдера:components/AppProviders.tsxКопировать кодКопировать код в буфер обмена
Все компоненты ниже по дереву продолжают вызывать
useTranslation()без правок.vite.config.tsКопировать кодКопировать код в буфер обмена
Плагин
reactI18nextVitePlugin()оборачиваетvite-intlayerи настраивает алиасы дляreact-i18nextиi18next. Для проекта без React плагинi18nextVitePlugin()из@intlayer/i18next/pluginалиасит толькоi18next.
Что можно удалить после перехода
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Файл / шаблон | Причина |
|---|---|
resources: { en, fr, ... } и импорты JSON | Игнорируются адаптером. Именно здесь крылись 68 КБ |
i18next-http-backend, i18next-resources-to-backend | В рантайме больше нечего запрашивать по сети |
i18next-browser-languagedetector | Определение языка выполняет маршрутизация Intlayer (префикс URL, cookie, заголовок) |
serverSideTranslations() в getStaticProps | Возвращает пустую структуру; безвредно, но не нужно |
next-i18next.config.js | Не считывается. Локали настраиваются в intlayer.config.ts |
Списки ns: [...] для каждой страницы | Компилятор связывает пространства имен с каждым компонентом автоматически |
Что вы получаете помимо байтов
- Типизированные ключи.
useTranslation("about")типизируется по скомпилированному словарюabout; опечатка вродеt("does.not.exist")вызывает ошибку TypeScript, а не возврат строки ключа. npx intlayer testпрерывает CI при отсутствии перевода в любой локали.npx intlayer fillпереводит недостающие ключи через ваш API-ключ (OpenAI, Anthropic, Mistral, Gemini...) и записывает их обратно вlocales/{lng}/{ns}.json.- Визуальный редактор и CMS работают с тем же JSON, позволяя переводчикам вносить правки через UI с фиксацией в Git.
- Постепенный переход на
.content.ts. Любой компонент можно переключить сuseTranslation("about")наuseIntlayer("about")с изолированным файлом контента. Словари JSON и.content.tsсосуществуют без проблем.
Ограничения, о которых важно знать
i18n.use(HttpBackend) вызывает init плагина и ничего больше. Если ваше приложение полагалось на получение переводов из CMS во время выполнения, этот процесс больше не работает; используйте Intlayer CMS или команды intlayer pull / push. Определение локали становится конфигурацией маршрутизации Intlayer (префикс URL, cookie, заголовок).
В отличие от некоторых других адаптеров, @intlayer/i18next не использует встроенные resources в качестве резервного варианта. Каждый ключ должен существовать в синхронизированных словарях, что проверяет intlayer test.
Один файл, показанный выше. Pages Router с appWithTranslation не требует никаких изменений.
localePath, fallbackLng, reloadOnPrerender и аналоги не имеют эквивалентов; локали и резервные варианты берутся из intlayer.config.ts.
9.4 КБ рантайма и +9.4 КБ на страницу по сравнению с next-intlayer. Как только каждый компонент перейдет на useIntlayer, удалите его.
Сравнение возможностей
Помимо байтов, что дает каждый вариант:
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Возможность | i18next / react-i18next / next-i18next | Адаптеры @intlayer/* | Нативный Intlayer |
|---|---|---|---|
Ваши вызовы t(), useTranslation, <Trans> | ✅ | ✅ Без изменений | ❌ Перенесены на useIntlayer |
| Размер runtime (gzip, Next.js) | 19.7 КБ | 9.4 КБ | 5.5 КБ |
| Утечка строк других страниц без ручных namespaces | ~90% | 0% | 0% |
| Типизированные ключи | ⚠️ Ручное объявление | ✅ Из скомпилированных словарей | ✅ Генерируются автоматически |
| Runtime-бэкенды и плагины | ✅ Полная экосистема плагинов | ❌ Неактивны | ❌ Не применимо, используйте CMS |
| Контент рядом с компонентами | ❌ Централизованный JSON | ⚠️ JSON, .content.ts может сосуществовать | ✅ .content.ts рядом с каждым компонентом |
| Отсутствующие переводы в CI | ⚠️ Нет из коробки | ✅ npx intlayer test | ✅ npx intlayer test |
| AI-перевод | ❌ Нет | ✅ npx intlayer fill | ✅ npx intlayer fill |
| Визуальный редактор / CMS | ❌ Через внешние платформы | ✅ На том же JSON | ✅ Да |
| Экосистема / сообщество | ✅ Очень большое | ⚠️ Меньше, быстро растет | ⚠️ Меньше, быстро растет |
Размеры runtime взяты из прогона на Next.js, описанного выше.
Когда что выбирать?
Ваше приложение зависит от бэкендов времени выполнения (переводы, предоставляемые CMS во время запроса), от экосистемы плагинов или от платформы без React, которую адаптеры не поддерживают.
Вы используете react-i18next / next-i18next и хотите получить экономию 68 КБ, в 8 раз меньшие компоненты, 0% утечек, типизированные ключи и проверки CI без переписывания кода. Это точка входа для существующей кодовой базы i18next.
Для новых проектов или когда адаптер выполнил свою задачу. Он имеет самый легкий рантайм (5.5 КБ, +0.3 КБ на страницу) и открывает доступ к синхронным серверным компонентам и файлам .content.ts для каждого компонента. Начните с Intlayer с Next.js или с Vite и React.
Часто задаваемые вопросы
Из resources: { en, fr, ... }. Стандартная настройка next-i18next импортирует JSON каждой локали в init(), поэтому каждая страница несет в себе каждое пространство имен на каждом языке: 218.5 КБ на страницу. Адаптер никогда не включает этот блок целиком; он передает каждому компоненту только названный словарь на активном языке.
Да, с components, нумерованными тегами <1>...</1> и values. Также поддерживаются {{interpolation}}, вложенность $t(key), формы множественного числа key_one / key_other (вычисляемые с помощью Intl.PluralRules), суффиксы контекста и returnObjects.
Установите splitKeys: false в плагине syncJSON. Весь файл останется одним словарем, и обычный вызов useTranslation() продолжит разрешаться относительно него.
Нет, это мост. Адаптер сохраняет API i18next и требует 9.4 КБ рантайма; нативный next-intlayer весит 5.5 КБ и добавляет синхронные серверные компоненты и файлы .content.ts рядом с компонентами. Вы можете мигрировать покомпонентно, так как словари JSON и .content.ts сосуществуют.
Да. locales/{lng}/{ns}.json остается источником истины: syncJSON считывает его с диалектом i18next и записывает переводы обратно при обновлении через CLI или CMS.
Связанные сравнения
Та же серия адаптеров:
Прямое сравнение библиотек:
Справочная документация:
Compat adapters:
Migration guides:
Чтобы понять, откуда взялись эти библиотеки, прочитайте историю i18n в JavaScript.
Заключение
i18next оказался самым тяжелым рантаймом в этом бенчмарке, а адаптеры снимают подавляющую часть его нагрузки, сохраняя привычный API. На одном и том же приложении Next.js это дает на 68 КБ меньше на страницу по сравнению с наивной настройкой, на 12.7 КБ меньше, чем в самой оптимизированной ручной сборке, в 8 раз более компактные компоненты, 0% утечек и на 4 мс более быструю гидратацию ценой одного конфига, одной строки плагина и замены провайдера. Бэкенды и детекторы становятся неактивными, resources игнорируется, а нативный next-intlayer остается еще на 9 КБ легче.
Все сырые данные, тестовые приложения и скрипты опубликованы в репозитории Benchmark Bloom.
Подробности смотрите в документе Почему Intlayer?.
Комментарии
Пока нет комментариев. Будьте первым, кто поделится своими мыслями.
