Спросите свой вопрос и получите сводку документа, используя эту страницу и выбранного вами поставщика AI
Содержимое этой страницы было переведено с помощью ИИ.
Смотреть последнюю версию оригинального контента на английскомЕсли у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.
Ссылка на документацию GitHubКопировать Markdown документа в буфер обмена
next-intl VS Intlayer

next-intl - самая популярная библиотека i18n для Next.js. Intlayer - это альтернатива на основе компилятора с областью видимости компонента. Обе локализуют приложение App Router. Вопрос в том, какие затраты каждая из них влечет после сборки приложения.
Эта статья - не учебное пособие. Это сравнение, подкрепленное числами из Benchmark Bloom, открытого набора инструментов для тестирования, который создает одно и то же приложение с каждой библиотекой и измеряет то, что браузер фактически загружает и выполняет.
tl;dr: На одном и том же приложении Next.jsnext-intlдобавляет +12.6 KB gzip JavaScript на каждую страницу, против +0.3 KB для Intlayer. Без дополнительной работыnext-intlпоставляет ~90% строк иностранных страниц с каждой страницей. Чтобы достичь утечки 0% сnext-intl, требуется область видимости namespace и per-pagepick(messages, [...]). Intlayer достигает 0% по умолчанию, потому что его компилятор ограничивает контент для каждого компонента. Если вы хотите APInext-intlс выходом Intlayer, адаптер@intlayer/next-intlпоказал 147.5 KB на страницу против 153.6 KB с оригиналом.
Вкратце
- next-intl - Легковесная, хорошо документированная, поддержка ICU message format, встроенная поддержка App Router с middleware, форматировщиками и помощниками навигации. Контент хранится в централизованных JSON каталогах; оптимизация производительности (namespaces, выборка сообщений для каждой страницы, ленивая загрузка) - ваша ответственность.
- Intlayer - Компонентоцентричная модель контента. Словари
.content.tsнаходятся рядом с компонентом, который они обслуживают, compiler во время сборки выполняет tree-shaking и ленивую загрузку для каждого компонента и локали, строгие типы TypeScript генерируются из вашего контента, и отсутствующие переводы вызывают ошибку во время сборки. Поставляется с middleware, помощниками SEO, Visual Editor / CMS и переводом с поддержкой AI.
Открыть таблицу в модальном окне для четкого просмотра всех данных
Значки обновляются автоматически. Снимки экрана будут изменяться с течением времени.
Сравнение функций "рядом"
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Функция | next-intlayer (Intlayer) | next-intl |
|---|---|---|
| Переводы рядом с компонентами | ✅ Да, .content.ts расположен вместе с каждым компонентом | ❌ Нет, централизованный messages/{locale}.json |
| Интеграция TypeScript | ✅ Строгие типы автоматически генерируются из контента | ✅ Хорошо, типизация ключей через расширение global.d.ts |
| Обнаружение отсутствующих переводов | ✅ Ошибка TypeScript + ошибка/предупреждение на этапе сборки | ⚠️ Fallback во время выполнения + предупреждение консоли |
| Rich content (JSX / Markdown / components) | ✅ Прямая поддержка | ⚠️ t.rich() / t.markup() с заполнителями тегов |
| ICU support | ⚠️ WIP | ✅ Да |
| Formatting (dates, numbers, currencies) | ✅ useNumber, useDate, ... (Intl под капотом) | ✅ useFormatter() (Intl под капотом) |
| Локализованная маршрутизация и middleware | ✅ Встроенный прокси/middleware, getMultilingualUrls | ✅ Встроенный middleware, Link, redirect, usePathname |
| SEO помощники (hreflang, sitemap, robots) | ✅ Встроенные помощники | ⚠️ Ручной, на основе конфигурации маршрутизации |
| Синхронные серверные компоненты | ✅ useIntlayer из next-intlayer/server работает в любом дочернем серверном компоненте | ⚠️ getTranslations асинхронен; синхронные дочерние компоненты нуждаются в t переданном как props |
| Статический рендеринг | ✅ Не блокирует статический рендеринг | ⚠️ Требует setRequestLocale(); каталоги с пространствами имён по-прежнему исключали страницы из статического рендеринга в наших тестах |
| Tree-shaking (отправка только используемого контента) | ✅ По компоненту, по локали, автоматизировано компилятором | ⚠️ Ручная работа: пространства имён + pick(messages, [...]) на страницу |
| Lazy loading | ✅ importMode: 'dynamic' (одна строка конфигурации) | ⚠️ Ручной динамический импорт в getRequestConfig |
| Purge unused content | ✅ Dead dictionaries are dropped at build time | ❌ Not built-in |
| Testing missing translations (CLI / CI) | ✅ npx intlayer content test | ⚠️ Not built-in; docs suggest npx @lingual/i18n-check |
| AI-powered translation | ✅ Built-in, uses your own provider keys | ❌ No |
| Визуальный редактор / CMS | ✅ Бесплатный визуальный редактор + опциональная CMS | ❌ Нет (внешние платформы локализации) |
| MCP server & Agent Skills | ✅ Да | ❌ Нет |
| Экосистема / сообщество | ⚠️ Меньше, но быстро растет | ✅ Большое, справочный стандарт Next.js |
Бенчмарк
Что было измерено
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 | Все локали и все страницы объединены вместе | Быстрые прототипы, AI-generated код |
| dynamic | Загружается только активная локаль, но все страницы сразу | Большинство проектов |
| scoped-static | Пространства имён по маршрутам, без ленивой загрузки | Редкий случай |
| scoped-dynamic | Пространства имён по маршрутам + ленивая загрузка. Отправляется только текущая страница в текущей локали | Приложения с строгим бюджетом производительности |
Intlayer не имеет варианта "scoped": компилятор автоматически распределяет контент по компонентам, поэтому его строки static и dynamic уже распределены по области видимости.
Для каждой сборки набор тестов записывает:
- Lib size: gzip размер пустого компонента, который только импортирует i18n библиотеку. Фиксированная стоимость runtime.
- Page JS: gzip JavaScript, скачанный на страницу, усреднённый по всем страницам и локалям.
- Locale leak %: доля переведённых строк, найденных в скачанном JS, которые принадлежат локали, которую пользователь не просматривает (отпечатано на
enиfr, поэтому 50% означает "другая измеренная локаль полностью присутствует"; с 10 связанными локалями, реальные потери выше). - Page leak %: доля переведённых строк, найденных в скачанном JS, которые принадлежат странице, на которой пользователь не находится.
- Component avg: средний gzip размер каждого компонента, скомпилированного в изоляции. Показывает, сколько i18n runtime один компонент тянет за собой.
- E2E reactivity: время в реальном масштабе времени между выбором нового языка и обновлением
html[lang]в DOM (Playwright, 5 итераций). - Hydration: продолжительность фазы гидрации React.
Приведённые ниже числа получены из запуска от 2026-09-12 сnext-intl4.14.2,use-intl4.14.2 иintlayer9.5.1. Тестовое приложение намеренно небольшое (несколько десятков строк на язык), поэтому процентные значения утечек описывают паттерн: они растут вместе с вашим контентом, тогда как стоимость runtime остаётся постоянной.
Результаты на Next.js (App Router)
Выберите метрики и библиотеки, которые вас интересуют:
Метрика
Динамическая загрузка JSON
Ленивая загрузка переводов во время выполнения
Ограниченный JSON (пространства имен)
Пространства имен перевода для каждой страницы
Что это за метрика?
Общий размер пакета библиотеки интернационализации в формате gzip. Он включает в себя только провайдер и логику извлечения контента после tree-shaking и минификации.
Почему это важно?
Меньший размер библиотеки снижает начальную загрузку JavaScript, что ускоряет загрузку и выполнение кода на клиенте.
Вид
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Library | Strategy | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | E2E reactivity | Hydration |
|---|---|---|---|---|---|---|---|---|
| base (no i18n) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
next-intl | static | 14.7 KB | 153.6 KB | 4.2% | 89.8% | 21.8 KB | 16.0 ms | 14.7 ms |
next-intl | dynamic | 14.7 KB | 153.6 KB | 9.7% | 89.9% | 21.8 KB | 15.6 ms | 14.8 ms |
next-intl | scoped-static | 14.7 KB | 153.6 KB | 0.0% | 0.0% | 80.1 KB | 17.9 ms | 17.4 ms |
next-intl | scoped-dynamic | 14.7 KB | 153.6 KB | 0.0% | 0.0% | 22.9 KB | 17.8 ms | 16.8 ms |
next-intlayer | static | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 8.5 KB | 15.5 ms | 16.9 ms |
next-intlayer | dynamic | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 6.9 KB | 15.3 ms | 15.9 ms |
@intlayer/next-intl (compat) | static | 8.0 KB | 147.5 KB | 0.0% | 0.0% | 8.1 KB | 14.5 ms | 12.8 ms |
@intlayer/next-intl (compat) | dynamic | 8.0 KB | 148.7 KB | 0.0% | 0.0% | 8.1 KB | 11.7 ms | 12.8 ms |
Как это читать
- Стоимость runtime. Базовое приложение весит 141.0 KB на страницу.
next-intlдоводит это значение до 153.6 KB (+12.6 KB gzip на каждой странице), Intlayer до 141.3 KB (+0.3 KB). Этот разрыв не зависит от количества строк: это runtime библиотеки. - Leakage. В двух конфигурациях, которые большинство команд фактически используют (
staticиdynamic),next-intlдоставляет ~90% строк иностранных страниц на каждую страницу: весьen.jsonпопадает в клиентский провайдер. Чтобы достичь 0%, требуются конфигурацииscoped-*: разделить каталоги на namespaces, затем выбрать нужные с помощьюpick()на каждой странице. Intlayer находится на 0% в обоих случаях без всего этого. - JavaScript на странице не изменился для
next-intlмежду стратегиями. Тестовое содержимое небольшое, поэтому утечка ~90% составляет всего несколько KB здесь. В реальном приложении со сотнями строк на странице это соотношение становится доминирующей стоимостью. Тем временем +12.6 KB runtime оплачивается в каждой конфигурации. - Размер компонента. Компонент, который вызывает
useTranslations(), компилируется в среднем до 21.8 KB; тот же компонент сuseIntlayer()компилируется до 6.9 KB. В конфигурацииscoped-staticкомпонентыnext-intlувеличиваются до 80.1 KB, потому что каждый встраивает свой каталог пространства имен. - Реактивность и гидратация находятся в одном диапазоне для обеих библиотек на Next.js (15-18 мс). Ни одна из них не является узким местом здесь.
Полная таблица, каждая библиотека и каждая стратегия, в отчете о бенчмарке Next.js.
Результаты на TanStack Start (use-intl)
use-intl - это не зависящее от фреймворка ядро next-intl. Тот же API, тот же формат сообщений. Его сравнение с intlayer на TanStack Start исключает из уравнения части, специфичные для Next.js.
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Библиотека | Стратегия | Размер библиотеки (gz) | Среднее JS страницы (gz) | Утечка локали | Утечка страницы | Среднее размер компонента (gz) | E2E реактивность |
|---|---|---|---|---|---|---|---|
| base (без i18n) | - | 0.0 KB | 111.0 KB | 0.0% | 0.0% | 0.7 KB | 8.1 ms |
use-intl | static | 14.1 KB | 179.8 KB | 50.0% | 89.8% | 76.0 KB | 6.7 ms |
use-intl | dynamic | 14.1 KB | 119.4 KB | 0.0% | 89.8% | 75.9 KB | 7.0 ms |
use-intl | scoped-static | 14.1 KB | 128.7 KB | 0.0% | 0.0% | 87.1 KB | 20.9 ms |
use-intl | scoped-dynamic | 14.1 KB | 128.7 KB | 0.0% | 0.0% | 87.1 KB | 13.3 ms |
intlayer | static | 5.0 KB | 125.8 KB | 50.0% | 0.0% | 8.1 KB | 3.2 ms |
intlayer | dynamic | 5.0 KB | 118.6 KB | 0.0% | 0.0% | 6.3 KB | 3.6 ms |
@intlayer/use-intl (compat) | dynamic | 7.3 KB | 129.7 KB | 0.0% | 0.0% | 9.3 KB | 8.7 ms |
Как это читать
- Наивная конфигурация
use-intlдоставляет на 68.8 KB больше JS на страницу чем базовое приложение, причём половина строк принадлежит неправильной локали и 90% неправильной странице. use-intlв режимеdynamicдостигает 119.4 KB, близко к 118.6 KB Intlayer, но все еще несет 89.8% утечку страницы: строки всех страниц для активной локали загружаются на каждой странице. Их группировка по маршруту (scoped-*) устраняет утечку, но добавляет еще ~9 KB накладных расходов на chunk.- В Intlayer строка
staticуже имеет 0% утечку страницы: компилятор собирает только словари, используемые компонентами на странице. ВключениеimportMode: 'dynamic'(одна строка вintlayer.config.ts) также устраняет утечку локали. - Размер компонента показывает разницу в архитектуре: 76-87 KB на компонент с
use-intlпротив 6-8 KB с Intlayer.useTranslations()привязывает каждый компонент к глобальному дереву сообщений;useIntlayer()привязывает его к собственному словарю. - Переключение локали в 2-4 раза быстрее с Intlayer (3 мс против 7-21 мс).
Полная таблица в отчете о бенчмарке TanStack Start.
Почему такая разница? Централизованные каталоги vs скомпилированные словари

next-intl следует классической модели: один JSON на локаль, загруженный в getRequestConfig, переданный в NextIntlClientProvider, доступный через t("namespace.key").
Копировать код в буфер обмена
Runtime не может знать, какие ключи будет использовать страница, поэтому безопасный стандарт - отправить весь каталог. Оптимизация означает, что вы разделяете каталог на пространства имён, вы решаете, какие пространства имён нужны каждой странице, и вы поддерживаете это соответствие в синхронизации при перемещении компонентов. Строка scoped-dynamic в тесте производительности - это награда за эту работу, и большинство команд туда никогда не доходят.
Цена недостижения этой цели растет сразу по двум осям, страницы и локали:

Intlayer переворачивает ответственность. Контент объявляется рядом с компонентом:
Копировать код в буфер обмена
При сборке компилятор (@intlayer/swc / @intlayer/babel) видит, какой компонент импортирует какой словарь. Он объединяет только те словари, только для активной локали, и удаляет те, которые ничто не импортирует. Паттерн "scoped-dynamic" становится результатом сборки вместо дисциплины, которую команда должна поддерживать.
Чтобы получить цифрыdynamicстроки, установитеdictionary.importMode: 'dynamic'вintlayer.config.ts. См. документацию по оптимизации bundle.
Опыт разработчика
Client компонент
Копировать код в буфер обмена
Копировать код в буфер обмена
Помните, что нужно включить пространство имёнcounterв сообщения, передаваемые вNextIntlClientProviderна каждой странице, которая отображает этот компонент.
Копировать код в буфер обмена
Копировать код в буфер обмена
Не требуется регистрировать на странице: компонент содержит свой собственный контент.
Синхронный серверный компонент
Компоненты системы проектирования (navbar, footer, карточки) часто являются серверными компонентами, отрендеренными как дочерние элементы клиентских компонентов, поэтому они не могут быть async.
Копировать код в буфер обмена
Страница должна await getTranslations("counter") и await getFormatter(), затем передать результаты вниз как props. Компонент больше не является самостоятельным.
Копировать код в буфер обмена
Метаданные
Копировать код в буфер обмена
Копировать код в буфер обмена
Сохраните API next-intl, получите вывод Intlayer
Вам не нужно переписывать компоненты, чтобы получить указанные выше числа производительности. @intlayer/next-intl - это готовый адаптер: он сохраняет useTranslations, getTranslations, useFormatter, t.rich(), ICU plurals и помощники next-intl/navigation, и предоставляет их из словарей Intlayer, скомпилированных компилятором Intlayer.
Копировать код в буфер обмена
В benchmark, compat-сборка того же приложения сократилась с 153.6 KB до 147.5 KB за страницу, с 21.8 KB до 8.1 KB за компонент, и с ~90% page leakage на 0%, при этом код приложения остался без изменений. Ваши существующие файлы messages/{locale}.json могут остаться источником истины благодаря JSON sync plugin.
Смотрите руководство миграции next-intl для пошагового процесса.
Когда выбрать что?
Вам нужен стандарт экосистемы для Next.js, вы полагаетесь на ICU MessageFormat, ваше приложение небольшое или среднего размера, либо вы интегрируетесь с платформой переводов (Crowdin, Phrase, Lokalise...), ожидающей централизованный JSON. Заложите время на разделение каталогов по пространствам имен и выборку сообщений через pick() на каждой странице, если важна производительность.
Вам нужен контент с областью видимости компонента, строгий TypeScript, ошибки отсутствующих ключей на этапе сборки, автоматический tree-shaking и ленивая загрузка, синхронные серверные компоненты и встроенные редакционные инструменты (Визуальный редактор, CMS, ИИ-перевод, MCP-сервер). Особенно актуально для крупных модульных кодовых баз и дизайн-систем.
Вы уже используете next-intl и хотите получить преимущества в размере бандла без полного переписывания. Адаптер совместимости сохраняет ваши импорты и файл messages/{locale}.json в качестве единого источника правды. Сравнение производительности в next-intl против @intlayer/next-intl.
Часто задаваемые вопросы
Не во время рендеринга. Разница в том, что передается клиенту: next-intl добавляет +12.6 KB gzip рантайма на каждой странице и в стандартных конфигурациях отправляет ~90% строк посторонних страниц с каждой страницей. Переключение локали и гидратация сопоставимы в Next.js (15-18 мс); в TanStack Start use-intl занимает 7-21 мс против 3-4 мс у Intlayer.
Да, с конфигурацией scoped-dynamic: разделите messages/{locale}.json на пространства имен для каждого маршрута, затем используйте pick(messages, [...]) на каждой странице и поддерживайте эту структуру при перемещении компонентов. Строки scoped-* бенчмарка как раз отражают эту работу. Intlayer достигает 0% по умолчанию без этого, так как компилятор изолирует контент по компонентам. См. оптимизация бандла.
Нет. @intlayer/next-intl сохраняет useTranslations, getTranslations, useFormatter, t.rich(), множественные формы ICU и хелперы навигации, предоставляя их из скомпилированных словарей. Достаточно одной строки плагина в next.config.ts. Пошаговое руководство в руководстве по миграции с next-intl.
Нативная поддержка ICU находится в разработке. Адаптеры совместимости (@intlayer/next-intl, @intlayer/use-intl) полностью поддерживают ICU: множественные формы, select, selectordinal, # и {ts, date, long} обрабатываются резолвером ICU от Intlayer. Подробнее читайте в формат сообщений ICU.
Да. Плагин синхронизации JSON читает их, разбивает ключи верхнего уровня на словари и перезаписывает переводы в те же файлы при обновлении через CLI или CMS. Рабочий процесс переводчиков не меняется.
Связанные сравнения
Тот же бенчмарк, другие библиотеки:
Подробнее о next-intl:
Справочная документация:
Чтобы понять, откуда взялись эти библиотеки, прочитайте историю i18n в JavaScript.
GitHub STARs
GitHub stars - это сильный индикатор популярности проекта, доверия сообщества и долгосрочной актуальности. Хотя это не прямая мера технического качества, они отражают, сколько разработчиков находят проект полезным, следят за его развитием и, вероятно, готовы его использовать.
Активность коммитов
Звёзды показывают популярность. Коммиты показывают, сколько работы вкладывается в проект. На момент написания у Intlayer около 7 500 коммитов: больше, чем у большинства сравниваемых здесь библиотек, и примерно в 5 раз больше, чем у next-intl или next-i18next.
- amannn/next-intl
- aymericzip/intlayer
Коммиты в основной ветке, источник: GitHub API.
Intlayer это монорепозиторий, поэтому в счёт входят все пакеты для фреймворков, CLI и документация. Считайте коммиты показателем активности, а не качества.
Загрузки npm
- next-intl
- next-intlayer
Источник: API загрузок реестра npm.
Число загрузок вознаграждает самые старые решения, а не лучшие. Библиотеку, выпущенную много лет назад, до сих пор устанавливает каждый проект, который выбрал её тогда, каждый запуск CI и каждый зависящий от неё пакет. Эта цифра измеряет инерцию, а не осознанный выбор.
ИИ-ассистенты усиливают этот эффект. next-intl, i18next и vue-i18n повсюду встречаются в коде, на котором они обучались, поэтому ассистенты предлагают их по умолчанию, не сравнивая альтернативы. Каждая подсказка добавляет загрузки, которые подпитывают следующую. Сравнивайте по бенчмарку, а не по числу загрузок.
Заключение
next-intl - это надежная, хорошо поддерживаемая библиотека, и benchmark подтверждает, что это далеко не худший вариант для Next.js. Однако её централизованная модель каталога возлагает все оптимизации на разработчика: наивная конфигурация пропускает ~90% контента иностранных страниц, а само runtime стоит +12,6 KB gzip на каждой странице.
Intlayer переносит эту работу в компилятор. Словари для каждого компонента, ленивая загрузка для каждого локала и очистка мертвого контента являются выходными данными сборки, а не соглашениями. Результат в том же приложении: +0.3 KB на страницу, 0% утечек, компоненты в 3 раза меньше и переключение локали в 2-4 раза быстрее на TanStack Start.
Все необработанные данные, тестовые приложения и скрипты находятся в репозитории Benchmark Bloom. Запустите его самостоятельно.
Обратитесь к документации 'Why Intlayer?' для получения дополнительных сведений.
Комментарии
Пока нет комментариев. Будьте первым, кто поделится своими мыслями.
