Спросите свой вопрос и получите сводку документа, используя эту страницу и выбранного вами поставщика 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
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Конфигурация | Стратегия | Размер либы (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 КБ на страницу относительно нативного решения. Это промежуточный мост, а не конечная точка.
Адаптер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 при каждом запросе, эта схема больше не работает; используйте CMS Intlayer или командыintlayer pull/push. resourcesигнорируется, а не объединяется. В отличие от некоторых адаптеров,@intlayer/i18nextне использует инлайновыеresourcesкак запасной вариант. Каждый ключ обязан существовать в синхронизированных словарях, что проверяется командойintlayer test.- App Router требует правки провайдера. Всего один файл, показанный выше. Pages Router с
appWithTranslationне требует никаких правок. next-i18next.config.jsигнорируется. НастройкиlocalePath,fallbackLng,reloadOnPrerenderи аналогичные не действуют; локали и запасные варианты берутся изintlayer.config.ts.- Адаптер не бесплатный. 9.4 КБ в рантайме и +9.4 КБ на страницу относительно
next-intlayer. Когда все компоненты мигрируют наuseIntlayer, адаптер можно отключить.
Когда что выбирать?
- Оставайтесь на
i18next, если приложение жестко зависит от сетевых бэкендов в рантайме (раздача переводов из CMS по запросу), экосистемы сторонних плагинов или окружения вне React, которое адаптеры не поддерживают. - Используйте
@intlayer/*, если вы работаете сreact-i18next/next-i18nextи хотите выиграть 68 КБ, сделать компоненты в 8 раз легче, устранить утечки (0%), получить типизацию ключей и проверки в CI без переписывания кодовой базы. Это лучший путь модернизации существующего проекта наi18next. - Переходите на нативный
next-intlayer/react-intlayerдля новых проектов или после завершения этапа адаптера. Это самое быстрое и легкое решение (5.5 КБ, +0.3 КБ на страницу), открывающее синхронные серверные компоненты и изолированные файлы контента.content.ts.
Связанные сравнения
- i18next vs Intlayer (сравнение библиотек, тот же бенчмарк)
- next-intl vs @intlayer/next-intl (та же серия адаптеров)
- Lingui vs @intlayer/lingui (та же серия адаптеров)
- vue-i18n vs @intlayer/vue-i18n (та же серия адаптеров)
- Руководства по миграции: i18next, react-i18next, next-i18next
- Документация адаптеров: i18next, react-i18next, next-i18next
Заключение
i18next оказался самым тяжелым рантаймом в этом бенчмарке, а адаптеры снимают подавляющую часть его нагрузки, сохраняя привычный API. На одном и том же приложении Next.js это дает на 68 КБ меньше на страницу по сравнению с наивной настройкой, на 12.7 КБ меньше, чем в самой оптимизированной ручной сборке, в 8 раз более компактные компоненты, 0% утечек и на 4 мс более быструю гидратацию ценой одного конфига, одной строки плагина и замены провайдера. Бэкенды и детекторы становятся неактивными, resources игнорируется, а нативный next-intlayer остается еще на 9 КБ легче.
Все сырые данные, тестовые приложения и скрипты опубликованы в репозитории Benchmark Bloom.
Подробности смотрите в документе Почему Intlayer?.
Комментарии
Пока нет комментариев. Будьте первым, кто поделится своими мыслями.
