Спросите свой вопрос и получите сводку документа, используя эту страницу и выбранного вами поставщика AI
Содержимое этой страницы было переведено с помощью ИИ.
Смотреть последнюю версию оригинального контента на английскомЕсли у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.
Ссылка на документацию GitHubКопировать Markdown документа в буфер обмена
Lingui против Intlayer: Бенчмарк интернационализации (i18n) для React и Next.js
Lingui и Intlayer - единственные две библиотеки в этом сравнительном исследовании, которые опираются на компилятор, а не на обычный рантайм. Lingui извлекает сообщения из макросов во время сборки и компилирует каталоги под каждую локаль. Intlayer компилирует словари на уровне компонентов и применяет tree-shaking отдельно для каждого языка. В теории их показатели должны быть близки. Цифры показывают, в чем они существенно расходятся.
Данные получены с помощью Benchmark Bloom - открытого набора тестов, который собирает одно и то же приложение с каждой библиотекой и замеряет то, что браузер реально скачивает и исполняет.
Кратко (tl;dr): Lingui ближе всех подобрался к Intlayer по объему чистого JavaScript на страницу: 115-120 КБ против 118,6 КБ на TanStack Start при настроенной ленивой загрузке, и 148,6 КБ против 141,3 КБ на Next.js. Однако в остальных аспектах образуется значительный разрыв: изолированно скомпилированный компонент Lingui весит 58-153 КБ против 6-8 КБ у Intlayer, гидратация занимает 28-34 мс против 11-14 мс, запасной текст исходной локали дает утечку 3-15% английских строк на французские страницы даже в оптимизированных сборках, а достижение такой оптимизации требует ручного извлечения, сборки и маршрутного разделения каталогов. Intlayer обеспечивает наилучшие показатели без какой-либо ручной настройки.
Коротко о главном
- Lingui - работает на макросах (
t`...`,<Trans>,msg), поддерживает синтаксис ICU MessageFormat, каталоги в форматах.po/ JSON, пайплайнlingui extract+lingui compile. Компилирует идентификаторы в компактные хеши, поддерживает динамическую подгрузку каталогов по языкам. Зрелое, не привязанное к фреймворку решение с развитой инфраструктурой переводческих утилит вокруг формата.po. - Intlayer - компонентно-ориентированная модель контента. Словари
.content.tsрасполагаются прямо рядом с целевым компонентом; компилятор на этапе сборки выполняет tree-shaking и загружает переводы по требованию для каждого компонента и языка; генерирует строгие типы TypeScript на основе контента, а пропущенные переводы вызывают ошибку сборки. Содержит встроенные middleware, SEO-хелперы, Визуальный редактор / CMS и модуль автоперевода через ИИ.
Открыть таблицу в модальном окне для четкого просмотра всех данных
Значки обновляются автоматически. Актуальные значения меняются со временем.
Сопоставление функциональности
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Возможность | Intlayer (react-intlayer / next-intlayer) | Lingui (@lingui/core / @lingui/react) |
|---|---|---|
| Переводы рядом с компонентами | ✅ Да, файл .content.ts хранится в одной папке с компонентом | ⚠️ Исходные строки внутри JSX через макросы; переводы в централизованных .po каталогах |
| Интеграция с TypeScript | ✅ Строгая типизация автоматически генерируется из содержимого | ⚠️ Макросы типизированы; идентификаторы без типов, недостающие ключи не подсвечиваются |
| Поиск отсутствующих переводов | ✅ Ошибка TypeScript + предупреждение/ошибка во время сборки | ⚠️ lingui extract показывает статистику; в рантайме тихо откатывается на английский текст |
| Форматированный контент (JSX/Markdown/комп.) | ✅ Прямая встроенная поддержка | ✅ Компонент <Trans> со вложенными элементами |
| Поддержка ICU | ⚠️ В разработке | ✅ Да (макросы plural, select, selectOrdinal) |
| Форматирование (даты, числа, валюты) | ✅ useNumber, useDate, ... (на базе нативного Intl) | ✅ i18n.date(), i18n.number() |
| Локализованный роутинг и middleware | ✅ Встроенный прокси/middleware, метод getMultilingualUrls | ❌ Отсутствует в базовом пакете |
| Инструменты SEO (hreflang, sitemap...) | ✅ Встроенные хелперы | ❌ Требуется ручная реализация |
| Синхронные серверные компоненты (RSC) | ✅ useIntlayer из next-intlayer/server работает в любых дочерних серверных компонентах | ⚠️ Требуется экземпляр I18n на запрос, передаваемый вручную или через setI18n |
| Tree-shaking (поставка только нужного) | ✅ На уровне компонентов и языков, автоматически компилятором | ⚠️ По языкам через lingui compile; по маршрутам требует ручного разделения файлов каталога |
| Ленивая загрузка (Lazy loading) | ✅ importMode: 'dynamic' (одна строка в конфигурационном файле) | ⚠️ Ручной вызов import() скомпилированных каталогов + i18n.load() / i18n.activate() |
| Очистка неиспользуемого контента | ✅ Устаревшие словари удаляются во время сборки | ✅ lingui extract --clean удаляет неактуальные сообщения |
| Проверка отсутствующих строк (CLI / CI) | ✅ npx intlayer content test | ⚠️ Отчеты lingui extract (по умолчанию сборка не падает с ошибкой) |
| Сборочный процесс | ✅ Один плагин (@intlayer/swc / @intlayer/babel / vite-intlayer) | ⚠️ Плагин макросов (Babel или SWC) + раздельные шаги extract и compile |
| Перевод с помощью искусственного интеллекта | ✅ Встроен, использует ваши собственные ключи API | ❌ Нет |
| Визуальный редактор / CMS | ✅ Бесплатный Visual Editor + подключаемая CMS | ❌ Нет (формат .po интегрируется со сторонними TMS) |
| Сервер MCP и Agent Skills | ✅ Да | ❌ Нет |
| Экосистема и сообщество | ⚠️ Моложе, но стремительно развивается | ✅ Зрелое, независимое от конкретного фреймворка решение |
Сравнительное тестирование
Что исследовалось
Пакет Benchmark Bloom собирает абсолютно идентичное приложение на каждой библиотеке: 10 страниц (home, about, blog, careers, contact, FAQ, pricing, products, settings, team), 10 локалей (en, fr, es, de, it, pt, zh, ja, ko, ru), одинаковая верстка и контент. Замеры проводились на страницах en и fr. Каждая библиотека исследовалась в четырех стратегиях загрузки:
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Стратегия | Описание | Где применяется |
|---|---|---|
| static | Каталоги всех языков импортируются и загружаются целиком на старте | Быстрые прототипы, код от нейросетей |
| dynamic | Через import() подгружается каталог только активного языка, но для всего сайта сразу | Подавляющее большинство проектов |
| scoped-static | По каталогу на каждый маршрут, все каталоги упакованы в общий стартовый бандл | Встречается редко |
| scoped-dynamic | По каталогу на маршрут + динамический import(). Только активная страница и нужный язык | Проекты со строгим лимитом по весу |
У Intlayer отсутствует вариант "scoped": компилятор изолирует контент на уровне каждого компонента автоматически, поэтому режимы static и dynamic изначально работают максимально изолированно.
В ходе каждого теста замеряются:
- Lib size: вес gzip пустого компонента, подключающего исключительно библиотеку i18n (базовый оверхед рантайма).
- Page JS: средний вес gzip JavaScript, загружаемого на страницу (усреднено по всем страницам и локалям).
- Locale leak %: доля переведенных строк в загруженном JS, относящихся к языкам, которые пользователь не просматривает.
- Page leak %: доля строк в загруженном JS, относящихся к страницам, на которых пользователь не находится.
- Component avg: средний вес gzip отдельного компонента при изолированной сборке.
- E2E reactivity: чистое время от момента выбора нового языка до фактического обновления атрибута
html[lang]в DOM (Playwright, среднее по 5 прогонам). - Hydration: время завершения фазы гидратации React.
Значения зафиксированы в тестировании от 2026-09-12 на базе@lingui/react6.6.0 иintlayer9.5.1. Тестовое приложение намеренно сделано компактным (несколько десятков фраз на язык), поэтому утечки наглядно отражают системную проблему: по мере роста проекта они пропорционально увеличиваются.
Результаты на Next.js
Выберите интересующие вас метрики и библиотеки:
Метрика
Динамическая загрузка JSON
Ленивая загрузка переводов во время выполнения
Ограниченный JSON (пространства имен)
Пространства имен перевода для каждой страницы
Что это за метрика?
Общий размер пакета библиотеки интернационализации в формате gzip. Он включает в себя только провайдер и логику извлечения контента после tree-shaking и минификации.
Почему это важно?
Меньший размер библиотеки снижает начальную загрузку JavaScript, что ускоряет загрузку и выполнение кода на клиенте.
Вид
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Библиотека | Стратегия | Lib size (gz) | Page JS ср. (gz) | Утечка языка | Утечка страниц | Компонент ср. (gz) | E2E-реактивность | Гидратация |
|---|---|---|---|---|---|---|---|---|
| база (без i18n) | - | 0,0 КБ | 141,0 КБ | 0,0% | 0,0% | 0,9 КБ | 13,4 мс | 11,8 мс |
| Lingui | static | 11,9 КБ | 207,4 КБ | 50,0% | 90,0% | 73,3 КБ | 15,3 мс | 15,2 мс |
| Lingui | dynamic | 11,9 КБ | 145,4 КБ | 2,8% | 89,9% | 19,9 КБ | 15,7 мс | 12,7 мс |
| Lingui | scoped-static | 11,9 КБ | 148,2 КБ | 2,7% | 89,1% | 20,4 КБ | 15,1 мс | 13,1 мс |
| Lingui | scoped-dynamic | 11,9 КБ | 148,6 КБ | 14,8% | 0,0% | 152,6 КБ | 16,1 мс | 14,8 мс |
next-intlayer | static | 5,5 КБ | 141,3 КБ | 0,0% | 0,0% | 8,5 КБ | 15,5 мс | 16,9 мс |
next-intlayer | dynamic | 5,5 КБ | 141,3 КБ | 0,0% | 0,0% | 6,9 КБ | 15,3 мс | 15,9 мс |
Анализ данных
- Базовый вес рантайма. Пустой компонент с Lingui весит 11,9 КБ gzip против 5,5 КБ с Intlayer. В масштабе страницы лучшая сборка Lingui оказывается на +7,3 КБ тяжелее Intlayer (148,6 против 141,3 КБ); Intlayer добавляет всего +0,3 КБ к весу приложения без интернационализации.
- Простая сборка создает колоссальный оверхед. Загрузка всех каталогов сразу дает 207,4 КБ на страницу (+66 КБ к базовому весу). Половина строк относится к чужому языку, а 90% - к посторонним страницам сайта.
- Динамическая загрузка исправляет язык, но не маршруты. При наличии одного каталога на язык утечка страниц сохраняется на уровне ~90%: весь французский каталог отдается на каждой странице. Чтобы добиться 0% утечки страниц в Lingui, приходится настраивать
scoped-dynamic: собирать отдельный каталог на каждый маршрут и вручную подключать его в страницы. - Утечка оригинального текста. Даже в наиболее продуманных схемах от 3% до 15% английских строк попадают на страницы на французском языке. Макросы Lingui встраивают исходную строку для подстраховки в итоговый бандл. Intlayer разрешает фолбеки на этапе сборки и доставляет клиенту только целевой язык.
- Взрывной рост размера компонентов в
scoped-dynamic. Каждый изолированный компонент весит в среднем 152,6 КБ, поскольку через цепочку импортов в него попадают каталоги других маршрутов. Тот же компонент наuseIntlayer()занимает всего 6,9 КБ.
Полная таблица, каждая библиотека и стратегия в отчете о бенчмарке Next.js.
Результаты на TanStack Start
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Библиотека | Стратегия | Lib size (gz) | Page JS ср. (gz) | Утечка языка | Утечка страниц | Компонент ср. (gz) | E2E-реактивность | Гидратация |
|---|---|---|---|---|---|---|---|---|
| база (без i18n) | - | 0,0 КБ | 111,0 КБ | 0,0% | 0,0% | 0,7 КБ | 8,1 мс | 21,6 мс |
| Lingui | static | 11,2 КБ | 152,2 КБ | 50,0% | 90,0% | 58,0 КБ | 3,9 мс | 19,9 мс |
| Lingui | dynamic | 11,2 КБ | 115,2 КБ | 9,3% | 0,0% | 85,5 КБ | 5,9 мс | 28,0 мс |
| Lingui | scoped-static | 11,2 КБ | 120,8 КБ | 4,0% | 0,0% | 147,9 КБ | 7,1 мс | 33,9 мс |
| Lingui | scoped-dynamic | 11,2 КБ | 120,2 КБ | 8,6% | 0,0% | 83,7 КБ | 42,1 мс | 32,9 мс |
intlayer | static | 5,0 КБ | 125,8 КБ | 50,0% | 0,0% | 8,1 КБ | 3,2 мс | 11,5 мс |
intlayer | dynamic | 5,0 КБ | 118,6 КБ | 0,0% | 0,0% | 6,3 КБ | 3,6 мс | 14,1 мс |
@intlayer/lingui (адаптер) | dynamic | 10,3 КБ | 137,0 КБ | 9,9% | 0,0% | 12,8 КБ | 2,9 мс | 19,7 мс |
Анализ данных
- По объему JS на страницу Lingui незначительно выигрывает. Вариант Lingui
dynamicфиксирует 115,2 КБ, что на 3,4 КБ меньше, чем 118,6 КБ у Intlayer. Скомпилированные каталоги Lingui с хешированными ключами очень компактны, а роутер TanStack Start отлично разделяет код маршрутов, поэтому утечка страниц исчезает уже на шагеdynamic. - Все остальные метрики на стороне Intlayer. Гидратация с Lingui длится 28-34 мс против 11-14 мс с Intlayer: методы
i18n.load()+i18n.activate()обязаны отработать на клиенте до старта гидратации React. Отдельные компоненты весят 58-148 КБ вместо 6-8 КБ. Утечка исходного языка не обнуляется никогда (составляя 4-9%). - Смена языка в оптимизированном режиме заметно замедлена. Lingui в схеме
scoped-dynamicтратит 42 мс на сменуhtml[lang], поскольку браузер должен сначала запросить, получить и активировать новый каталог маршрута. Intlayer переключает язык за 3-4 мс в обоих сценариях. - Строка
staticу Intlayer сразу обеспечивает 0% утечки страниц, так как в бандл включаются исключительно словари, импортированные задействованными на странице компонентами. А параметрimportMode: 'dynamic'устраняет и языковую утечку. @intlayer/linguiсохраняет синтаксис макросов Lingui, связывая их со словарями Intlayer. Это решение жертвует небольшим объемом на страницу (137 КБ из-за присутствия макро-рантайма), взамен давая облегченные компоненты (12,8 КБ) и быструю гидратацию. Прекрасный вариант для плавного перехода.
Полная таблица в отчете о бенчмарке TanStack Start.
В чем фундаментальная причина? Два компилятора, две единицы деления

Обе библиотеки компилируют код, но принципиально отличается объект компиляции.
Lingui компилирует каталоги. Макросы в коде извлекаются в единый файл .po на язык, а затем компилируются в модуль JS на язык. Главная единица деления - локаль. Чтобы разделить данные глубже (по маршрутам или компонентам), вам придется заводить отдельные каталоги, прописывать правила в lingui.config.ts и вручную настраивать их загрузку. Экземпляр I18n глобален, и каждый useLingui() подключает компонент ко всему его содержимому.
Копировать код в буфер обмена
Intlayer компилирует словари. Каждый файл .content.ts - это изолированный словарь под определенным ключом; компилятор выясняет, какой компонент использует какой ключ, и формирует компактный JSON строго для этого компонента и языка. Главная единица деления - компонент. Привязка к маршрутам происходит автоматически: страница скачивает словари только тех компонентов, которые выводятся на экран.
Копировать код в буфер обмена
Именно поэтому архитектура scoped-dynamic формируется в Intlayer автоматически на этапе сборки, тогда как в Lingui это требует масштабной ручной настройки. Разрыв увеличивается сразу по двум осям, страницы и локали:

Чтобы повторить показатели строкиdynamic, активируйтеdictionary.importMode: 'dynamic'вintlayer.config.ts. Подробнее в документации по оптимизации бандла.
Опыт разработки (Developer Experience)
Настройка
Копировать код в буфер обмена
Копировать код в буфер обмена
Затем в сборщик добавляется плагин @lingui/babel-plugin-lingui-macro (или @lingui/swc-plugin), после правок выполняется lingui extract, перед сборкой - lingui compile, а приложение оборачивается в <I18nProvider i18n={i18n}>.
Копировать код в буфер обмена
Добавьте плагин intlayer() в vite.config.ts (или withIntlayer() в next.config.ts) и оберните дерево компонентов в <IntlayerProvider>. Никаких ручных команд извлечения или сборки: словари компилируются автоматически бандлером.
Компоненты
Копировать код в буфер обмена
Английский текст пишется прямо в компоненте; перевод на французский хранится в src/locales/fr/messages.po под сгенерированным хеш-идентификатором после выполнения lingui extract. Если забыть запустить команду извлечения или сборки, на экране незаметно останется английский текст.
Копировать код в буфер обмена
Копировать код в буфер обмена
Оба языка находятся в одном файле рядом с компонентом. Отсутствие перевода для fr приведет к ошибке сборщика, а опечатка в имени ключа будет немедленно подсвечена TypeScript.
Вне компонентов React
Метаданные, функции загрузки данных (loaders), серверные функции: в любом контексте без дерева React.
Копировать код в буфер обмена
Создание нового экземпляра I18n на каждый вызов, ручной импорт конкретного каталога и использование msg + i18n._() вместо привычного t. Как отмечается в примечаниях к бенчмарку, постоянный выбор между t, t` ` , i18n.t(), msg или <Trans> часто сбивает с толку.
Копировать код в буфер обмена
Использование макросов Lingui со словарями Intlayer
@intlayer/lingui работает как прозрачный адаптер для @lingui/core и @lingui/react. Макросы компилируются в прежнем режиме; генерируемые вызовы i18n._() берут данные из словарей Intlayer, а плагины синхронизации сохраняют файлы .po в качестве источника данных. Формы множественного числа и условия ICU отображаются абсолютно идентично.
Копировать код в буфер обмена
Оставьте @lingui/babel-plugin-lingui-macro или @lingui/swc-plugin в конфигурации сборщика перед компилятором Intlayer. См. документацию по совместимости с Lingui.
Что выбрать для вашего проекта?
Вам нужен ICU MessageFormat с типизированными макросами, ваши переводчики работают в .po с существующим пайплайном TMS, вы предпочитаете исходные строки инлайн в JSX, и вашей команде удобно управлять извлечением, компиляцией и разделением каталогов. Его JS на страницу вполне конкурентоспособен после настройки lazy loading.
Вам нужен контент с областью видимости на уровне компонентов, строгий TypeScript, ошибки отсутствующих ключей во время сборки, tree-shaking и lazy loading без усилий, компактные компоненты, быстрая гидратация, мгновенное переключение локалей и встроенные инструменты редактирования (Визуальный редактор, CMS, ИИ-перевод, MCP-сервер). Особенно актуально для крупных модульных кодовых баз и дизайн-систем.
Вы уже используете Lingui и хотите постепенно перейти на словари Intlayer, не трогая макросы. Ваши каталоги .po остаются источником истины благодаря плагину синхронизации PO. Измерено бок о бок в Lingui vs @intlayer/lingui.
FAQ
Потому что единица компиляции различается. Lingui компилирует один каталог на локаль: всё, что ниже этого (каталоги по маршрутам, lazy loading, исключение fallback из бандла), требует ручной конфигурации. Intlayer компилирует один словарь на компонент, поэтому разделение по маршрутам происходит автоматически во время сборки. Вот почему изолированно скомпилированный компонент Lingui весит 58-153 KB против 6-8 KB у Intlayer.
Макросы сохраняют исходное сообщение доступным в рантайме в качестве фоллбэка, поэтому английская строка отправляется вместе с переводом. Бенчмарк фиксирует 3-15% строк en внутри страниц fr в каждой оптимизированной конфигурации. Intlayer разрешает фоллбэки во время сборки и отправляет только активную локаль.
Да, а на TanStack Start он даже чуть впереди: 115.2 KB в режиме dynamic против 118.6 KB у Intlayer. Скомпилированные каталоги с хэшированными ID компактны. Однако цена проявляется в других аспектах: гидратация за 28-34 мс против 11-14 мс и переключение локали за 42 мс в конфигурации scoped-dynamic.
Нет. @intlayer/lingui сохраняет компиляцию t`...` , <Trans>, msg, plural, select и selectOrdinal как раньше; меняется только то, относительно чего резолвит i18n._(). Сохраните @lingui/babel-plugin-lingui-macro или @lingui/swc-plugin в сборке. См. документацию по совместимости с Lingui.
Они остаются для макросов и исчезают для собственного контента Intlayer. Словари .content.ts собираются при запуске бандлера без отдельного шага CLI, а intlayer test прерывает CI при отсутствии ключа вместо тихого отката к исходной строке.
Похожие сравнения

Тот же бенчмарк, другие библиотеки:
Подробнее:
Справочная документация:
Чтобы понять, откуда взялись эти библиотеки, прочитайте историю i18n в JavaScript.
Звезды на GitHub
Количество звезд на GitHub отражает интерес индустрии, уровень доверия сообщества и перспективность развития проекта. Это наглядно показывает, сколько разработчиков находят библиотеку полезной в реальной работе.
Активность коммитов
Звёзды показывают популярность. Коммиты показывают, сколько работы вкладывается в проект. На момент написания у Intlayer около 7 500 коммитов: больше, чем у большинства сравниваемых здесь библиотек, и примерно в 5 раз больше, чем у next-intl или next-i18next.
- lingui/js-lingui
- aymericzip/intlayer
Коммиты в основной ветке, источник: GitHub API.
Intlayer это монорепозиторий, поэтому в счёт входят все пакеты для фреймворков, CLI и документация. Считайте коммиты показателем активности, а не качества.
Загрузки npm
- @lingui/core
- intlayer
Источник: API загрузок реестра npm.
Число загрузок вознаграждает самые старые решения, а не лучшие. Библиотеку, выпущенную много лет назад, до сих пор устанавливает каждый проект, который выбрал её тогда, каждый запуск CI и каждый зависящий от неё пакет. Эта цифра измеряет инерцию, а не осознанный выбор.
ИИ-ассистенты усиливают этот эффект. next-intl, i18next и vue-i18n повсюду встречаются в коде, на котором они обучались, поэтому ассистенты предлагают их по умолчанию, не сравнивая альтернативы. Каждая подсказка добавляет загрузки, которые подпитывают следующую. Сравнивайте по бенчмарку, а не по числу загрузок.
Заключение
Lingui - сильнейшая гибридная библиотека в данном бенчмарке. Ее скомпилированные и хешированные каталоги дают размер JavaScript на страницу, практически равный показателям Intlayer, а на TanStack Start даже слегка превосходящий его. Если бы единственным критерием были килобайты на страницу, результатом стала бы боевая ничья.
Но это не единственный показатель. Компилятор Lingui ограничен границами локали; все, что лежит ниже (каталоги маршрутов, ленивая загрузка, очистка запасного текста), требует ручного труда разработчика. Бенчмарк демонстрирует цену этого ограничения: компоненты в 10-20 раз тяжелее, гидратация в 2-3 раза медленнее, постоянная утечка 3-15% исходных текстов и пауза в 42 мс при переключении языка в оптимизированной сборке. Компилятор Intlayer работает на уровне каждого компонента, обеспечивая 6-8 КБ, 11-14 мс, 0% и 3-4 мс из коробки без лишней настройки.
Все первичные данные, тестовые приложения и скрипты опубликованы в репозитории Benchmark Bloom. Вы можете повторить эти тесты самостоятельно.
Подробнее читайте в материале 'Почему Intlayer?'.
Комментарии
Пока нет комментариев. Будьте первым, кто поделится своими мыслями.
