Задайте питання та отримайте підсумок документа, вказавши цю сторінку та обраного вами постачальника штучного інтелекту
Вміст цієї сторінки перекладено за допомогою штучного інтелекту.
Переглянути останню версію оригінального вмісту англійськоюЯкщо у вас є ідея щодо покращення цієї документації, будь ласка, долучіться, надіславши pull request на GitHub.
Посилання на документацію на GitHubСкопіювати документацію у форматі Markdown в буфер обміну
next-intl проти Intlayer | Бенчмарк інтернаціоналізації (i18n) у React та Next.js
next-intl на сьогодні є стандартним вибором для i18n у Next.js App Router: тісна інтеграція з маршрутизацією, повна підтримка ICU MessageFormat та звичний досвід розробника для всіх, хто працював із класичними системами i18n.
Intlayer повністю переосмислює цей підхід: жодних централізованих словників, жодної потреби вручну прив'язувати простори імен (namespaces) до маршрутів. Контент оголошується безпосередньо поруч із кожним компонентом, а компілятор часу збирання пакує лише те, що дійсно потрібно кожній окремій сторінці.
У цій статті порівнюються дві бібліотеки на основі даних із Benchmark Bloom, відкритого набору тестів, який збирає однаковий додаток з кожною бібліотекою та фіксує те, що браузер насправді завантажує і виконує.
Коротко (tl;dr):next-intlдодає щонайменше +12.6 КБ gzip на кожній сторінці лише через свій runtime і призводить до витоку ~90% рядків з інших сторінок у стандартних конфігураціях (staticтаdynamic). Щоб усунути цей витік, потрібно вручну розбивати каталоги на простори імен та підключати їх окремо для кожної сторінки. Натомість компіляторIntlayerгарантує 0% витоку, втричі менші компоненти та лише +0.3 КБ понад базовий додаток без будь-яких ручних налаштувань.
Короткий огляд
- next-intl - Стандарт спільноти Next.js. Централізовані словники JSON для кожної мови, повна підтримка ICU MessageFormat і глибока інтеграція з обробкою запитів та маршрутизацією Next.js.
- Intlayer - Модель контенту, орієнтована на компоненти. Файли
.content.tsрозташовані поруч із компонентами, компілятор часу збирання автоматично виконує tree-shaking та ліниве завантаження для кожного компонента і локалі, а також генерує суворі типи TypeScript.
Відкрийте таблицю в модальному вікні, щоб чітко переглянути всі дані
Значки оновлюються автоматично.
Порівняння функціональності
Відкрийте таблицю в модальному вікні, щоб чітко переглянути всі дані
| Функція | Intlayer (react-intlayer / next-intlayer) | next-intl (next-intl / use-intl) |
|---|---|---|
| Переклади поруч із компонентами | ✅ Так, .content.ts поруч із кожним компонентом | ❌ Централізовані словники JSON у папці messages/ |
| Інтеграція з TypeScript | ✅ Суворі типи генеруються автоматично з контенту | ⚠️ Підтримується через ручне налаштування global.d.ts |
| Виявлення відсутніх перекладів | ✅ Помилка TypeScript + помилка/попередження під час збирання | ⚠️ У runtime повертає ключ або генерує помилку залежно від налаштувань |
| Багатий контент (JSX / Markdown / компоненти) | ✅ Пряма підтримка | ⚠️ Через t.rich() з передачею компонентів зіставлення |
| Підтримка ICU MessageFormat | ⚠️ У розробці | ✅ Так, повна підтримка ICU |
| Синхронні серверні компоненти | ✅ useIntlayer з next-intlayer/server працює у будь-якому дочірньому компоненті | ❌ Вимагає передачі перекладів через props від асинхронного предка |
| Tree-shaking | ✅ Автоматично для кожного компонента і локалі | ⚠️ Вимагає ручного поділу на простори імен та використання pick() |
| Ліниве завантаження (Lazy loading) | ✅ Один рядок конфігурації (importMode: 'dynamic') | ⚠️ Вимагає ручного динамічного імпорту в getRequestConfig |
| Візуальний редактор / CMS | ✅ Безкоштовний Візуальний редактор + додаткова CMS | ❌ Немає |
| Переклад за допомогою ШІ | ✅ Вбудовано, використовує ваші власні API-ключі | ❌ Немає |
| Сервер MCP та навички агентів | ✅ Так | ❌ Немає |
Бенчмарк
Що вимірювалося
Набір тестів 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 | Завантажується лише активна локаль, але відразу для всіх сторінок | Більшість проєктів |
| scoped-static | Простори імен на кожен маршрут, без лінивого завантаження | Рідко |
| scoped-dynamic | Простори імен на кожен маршрут + ліниве завантаження. Лише поточна сторінка поточної мови | Додатки з суворим бюджетом продуктивності |
Intlayer не має варіанта "scoped": компілятор автоматично обмежує контекст контенту для кожного компонента, тому рядки static і dynamic уже оптимізовані за маршрутами.
Для кожного збирання фіксувалося:
- Розмір бібліотеки (Lib size): розмір gzip порожнього компонента, який імпортує лише бібліотеку i18n.
- JS сторінки (Page JS): кількість стиснутого gzip JavaScript на сторінку.
- % витоку локалі (Locale leak %): частка рядків мови, яку користувач не переглядає.
- % витоку сторінки (Page leak %): частка рядків сторінки, на якій користувач не перебуває.
- Середній розмір компонента (Component avg): середній розмір gzip кожного компонента, скомпільованого окремо.
- Реактивність E2E: час між перемиканням мови та оновленням
html[lang]у DOM. - Гідратація: тривалість фази гідратації React.
Наведені дані отримані під час тестування від 2026-09-12 зnext-intl4.14.2 таintlayer9.5.1.
Результати на Next.js (App Router)
Відкрийте таблицю в модальному вікні, щоб чітко переглянути всі дані
| Бібліотека | Стратегія | Розмір Lib (gz) | Сер. JS сторінки (gz) | Витік локалі | Витік сторінки | Сер. компонента (gz) | Реактивність E2E | Гідратація |
|---|---|---|---|---|---|---|---|---|
| Базовий додаток (без 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 (сумісн.) | static | 8.0 KB | 147.5 KB | 0.0% | 0.0% | 8.1 KB | 14.5 ms | 12.8 ms |
@intlayer/next-intl (сумісн.) | dynamic | 8.0 KB | 148.7 KB | 0.0% | 0.0% | 8.1 KB | 11.7 ms | 12.8 ms |
Як інтерпретувати результати
- Витрати runtime. Базовий додаток важить 141.0 КБ на сторінку.
next-intlзбільшує це значення до 153.6 КБ (+12.6 КБ gzip на кожній сторінці), тоді як Intlayer додає лише 141.3 КБ (+0.3 КБ). - Витік контенту. У найпоширеніших конфігураціях (
staticтаdynamic)next-intlвідправляє на кожну сторінку ~90% рядків з інших сторінок, оскільки весь файлen.jsonпотрапляє до клієнтського провайдера. Щоб зменшити цей показник до 0%, потрібен складний ручний поділ на простори імен, тоді як в Intlayer це працює за замовчуванням. - Розмір компонента. Компонент із
useTranslations()важить у середньому 21.8 КБ; той самий компонент зuseIntlayer()важить лише 6.9 КБ.
Результати на TanStack Start (use-intl)
Відкрийте таблицю в модальному вікні, щоб чітко переглянути всі дані
| Бібліотека | Стратегія | Розмір Lib (gz) | Сер. JS сторінки (gz) | Витік локалі | Витік сторінки | Сер. компонента (gz) | Реактивність E2E |
|---|---|---|---|---|---|---|---|
| Базовий додаток (без 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 (сумісн.) | dynamic | 7.3 KB | 129.7 KB | 0.0% | 0.0% | 9.3 KB | 8.7 ms |
Як інтерпретувати результати
- Просте налаштування
use-intlпередає на 68.8 КБ більше JS на сторінку, ніж базовий додаток. - У режимі
dynamicuse-intlдосягає 119.4 КБ, але все одно зберігає 89.8% витоку сторінок. - Архітектурна різниця особливо помітна у розмірі компонентів: 76-87 КБ у
use-intlпроти 6-8 КБ в Intlayer. - Перемикання локалі відбувається у 2-4 рази швидше з Intlayer (3 мс проти 7-21 мс).
Чому виникає різниця? Централізовані каталоги проти скомпільованих словників
next-intl слідує класичній моделі: один JSON для кожної мови, завантажується в getRequestConfig, передається в NextIntlClientProvider і зчитується через t("namespace.key").
Скопіюйте код у буфер обміну
Runtime не може передбачити, які саме ключі знадобляться сторінці, тому відправка всього каталогу є єдиним безпечним варіантом.
Intlayer змінює цей підхід. Контент декларується безпосередньо поруч із компонентом:
Скопіюйте код у буфер обміну
Під час збирання компілятор визначає, який компонент імпортує конкретний словник, і пакує тільки ці словники для активної локалі.
Щоб отримати показники рядкаdynamic, встановітьdictionary.importMode: 'dynamic'уintlayer.config.ts. Дивіться документацію з оптимізації бандла.
Досвід розробника
Клієнтський компонент
next-intl
Скопіюйте код у буфер обміну
Скопіюйте код у буфер обміну
Intlayer
Скопіюйте код у буфер обміну
Скопіюйте код у буфер обміну
Синхронні серверні компоненти
Елементи дизайн-системи (навігаційні панелі, підвали, картки) часто є серверними компонентами, що відображаються всередині клієнтських компонентів, тому вони не можуть бути async.
next-intl
Скопіюйте код у буфер обміну
Intlayer
Скопіюйте код у буфер обміну
Метадані
next-intl
Скопіюйте код у буфер обміну
Intlayer
Скопіюйте код у буфер обміну
Збережіть API next-intl, отримайте оптимізований вихід Intlayer
Вам не потрібно переписувати компоненти, щоб отримати наведені вище результати продуктивності. Пакет @intlayer/next-intl є сумісним адаптером: він зберігає useTranslations, getTranslations, useFormatter, t.rich() та множинні форми ICU, обслуговуючи їх зі словників, скомпільованих компілятором Intlayer.
Скопіюйте код у буфер обміну
У бенчмарку сумісна збірка того самого додатка зменшила розмір сторінки з 153.6 КБ до 147.5 КБ, розмір компонентів з 21.8 КБ до 8.1 КБ, а витік сторінки знизився з ~90% до 0% без внесення змін у код самого додатка. Ваші наявні файли messages/{locale}.json можуть залишатися основним джерелом даних завдяки плагіну синхронізації JSON.
Дивіться посібник із міграції з next-intl для отримання покрокових інструкцій.
Що і коли обрати?
- Обирайте next-intl, якщо вам потрібен стандарт спільноти Next.js, ви повністю спираєтесь на ICU MessageFormat, ваш проєкт невеликий або середній, або ви використовуєте платформи перекладу з централізованими JSON (Crowdin, Phrase, Lokalise...).
- Обирайте Intlayer, якщо вам потрібен контент з прив'язкою до компонентів, суворий TypeScript, помилки про відсутні ключі під час збирання, автоматичний tree-shaking та ліниве завантаження, синхронні серверні компоненти та вбудовані інструменти редагування (Візуальний редактор, CMS, переклад за допомогою ШІ, сервер MCP).
- Обирайте
@intlayer/next-intl, якщо ви вже використовуєтеnext-intlі бажаєте отримати переваги в оптимізації бандла без переписування коду.
Схожі порівняння
- i18next проти Intlayer (той самий бенчмарк)
- Lingui проти Intlayer (той самий бенчмарк)
- Бенчмарк vue-i18n проти Intlayer (той самий бенчмарк)
- next-i18next проти next-intl проти Intlayer
- Чи застарів next-intl?
Зірки GitHub
Зірки на GitHub є важливим показником популярності проєкту, довіри спільноти та його довгострокової актуальності.
Висновок
next-intl - це надійна, перевірена часом бібліотека, і бенчмарк підтверджує, що вона залишається хорошим вибором для Next.js. Проте централізована модель каталогів перекладає всю оптимізацію на розробника: стандартне налаштування призводить до витоку близько 90% вмісту інших сторінок, а сам runtime коштує +12.6 КБ gzip на кожній сторінці.
Intlayer переносить усю цю роботу до компілятора. Словники для кожного компонента, ліниве завантаження для кожної мови та очищення невикористаного контенту стають автоматичними результатами збирання. Результат на тому ж додатку: +0.3 КБ на сторінку, 0% витоку, компоненти втричі менші, а перемикання мови у 2-4 рази швидше на TanStack Start.
Усі вихідні дані, тестові додатки та скрипти доступні у репозиторії Benchmark Bloom.
Зверніться до документа 'Чому Intlayer?' для отримання детальнішої інформації.
Коментарі
Поки що немає коментарів. Будьте першим, хто поділиться своїми думками.
