Автор:
    Создание:2026-09-02Последнее обновление:2026-09-28

    Устарел ли next-intl в 2026 году?

    Когда Vercel представил App Router и убрал встроенную i18n из Pages Router, next-intl оперативно занял освободившуюся нишу. Качественная документация Яна Аманна и своевременная поддержка App Router сделали эту библиотеку выбором по умолчанию для многих разработчиков.

    Почему же сегодня возникает вопрос о ее актуальности?

    Архитектура веба за последние три года сделала большой шаг вперед, тогда как концептуальная модель next-intl осталась на месте.

    Пока Next.js развивал React Server Components (RSC), потоковый рендеринг и оптимизации на уровне компилятора, next-intl продолжает решать интернационализацию во время выполнения: передает тяжелые JSON-объекты клиентским провайдерам, выполняет ICU-форматтеры в браузере и полагается на ручную разбивку по неймспейсам для контроля веса бандла.

    Главные выводы

    Снижение темпов развития:

    За последние 12 месяцев в next-intl добавлено ~187 коммитов, преимущественно связанных с адаптацией к релизам Next.js и мелкими исправлениями.

    Клиентский оверхед в runtime:

    Подключение NextIntlClientProvider с useTranslations() добавляет ~12.8 КБ gzipped (51 КБ minified) еще до вывода текста, что примерно втрое превышает вес next-intlayer (4.3 КБ).

    Утечка 90% переводов:

    В типичных конфигурациях 89.8% объема переводов, передаваемых на страницу, принадлежит другим маршрутам. При переходе на /contact попутно загружаются тексты /pricing и личного кабинета.

    Ручное управление неймспейсами:

    Чтобы избежать раздувания бандла, приходится вручную делить и связывать неймспейсы с маршрутами, что повышает риск пропустить переводы в продакшене.

    Коммерческое партнерство:

    Будучи официальным партнером Crowdin, проект имеет мало причин разрабатывать бесплатную локальную утилиту ИИ-перевода прямо в CLI.

    Поддержка vs. современные инструменты

    Активность коммитов за последние 12 месяцев:

    РепозиторийЗвездыВсего коммитовКоммитов / годПоследний коммит
    amannn/next-intlstarscommitsyearlylast
    aymericzip/intlayerstarscommitsyearlylast

    Показатели за прошедший год:

    • amannn/next-intl: 187 коммитов (обновления зависимостей и небольшие патчи).
    • aymericzip/intlayer: 4 343 коммита (активная работа над компилятором, плагинами для IDE, MCP-серверами и алгоритмами перевода).

    Star History Chart

    • amannn/next-intl
    • aymericzip/intlayer

    Коммиты в основной ветке, источник: GitHub API.

    Стабильная библиотека полезна, но подходы к i18n изменились: компиляторы удаляют неиспользуемые строки при сборке, нейросети переводят тексты в CI, а среды разработки подключают LSP и ИИ-помощников. Архитектура, сосредоточенная на времени выполнения, с трудом использует эти возможности.

    Чтобы понять, откуда взялись эти библиотеки, прочитайте историю i18n в JavaScript.

    Загрузки npm

    • next-intl
    • next-intlayer

    Источник: API загрузок реестра npm.

    Число загрузок вознаграждает самые старые решения, а не лучшие. Библиотеку, выпущенную много лет назад, до сих пор устанавливает каждый проект, который выбрал её тогда, каждый запуск CI и каждый зависящий от неё пакет. Эта цифра измеряет инерцию, а не осознанный выбор.

    ИИ-ассистенты усиливают этот эффект. next-intl, i18next и vue-i18n повсюду встречаются в коде, на котором они обучались, поэтому ассистенты предлагают их по умолчанию, не сравнивая альтернативы. Каждая подсказка добавляет загрузки, которые подпитывают следующую. Сравнивайте по бенчмарку, а не по числу загрузок.

    Тестирование в Next.js 16 App Router

    Бенчмарк проведен на стандартном приложении App Router с 10 маршрутами и 10 языками:

    Метрика

    Динамическая загрузка JSON

    Ленивая загрузка переводов во время выполнения

    Ограниченный JSON (пространства имен)

    Пространства имен перевода для каждой страницы

    Что это за метрика?

    Общий размер пакета библиотеки интернационализации в формате gzip. Он включает в себя только провайдер и логику извлечения контента после tree-shaking и минификации.

    Почему это важно?

    Меньший размер библиотеки снижает начальную загрузку JavaScript, что ускоряет загрузку и выполнение кода на клиенте.

    Вид

    Измерения в реальных браузерах с gzip-сжатием. Все подробности в отчете о бенчмарке Next.js.

    Базовый размер библиотек

    Вес клиентской части до добавления текстов:

    БиблиотекаGzippedMinified
    next-intl@4.9.112.8 КБ51.0 КБ
    next-intlayer@8.7.124.3 КБ13.3 КБ

    Вес страниц и утечки контента

    КонфигурацияСр. JS / стр. (gz)Утечка языковУтечка др. страницСр. компонент (gz)
    База (без i18n)150.8 КБ0.0%0.0%0.7 КБ
    next-intl (статика)163.5 КБ4.2%89.8%20.5 КБ
    next-intl (динамика)163.4 КБ9.7%89.9%20.5 КБ
    next-intlayer152.1 КБ0.0%0.0%7.2 КБ

    Причина утечек между страницами

    В классических проектах с next-intl корневой layout загружает весь объем переводов сразу:

    app/[locale]/layout.tsx
    export default async function RootLayout({ children, params }) {
      const messages = await getMessages();
    
      return (
        <html>
          <body>
            <NextIntlClientProvider messages={messages}>
              {children}
            </NextIntlClientProvider>
          </body>
        </html>
      );
    }
    

    Поскольку messages попадает в клиентский провайдер в самом верху дерева, браузер скачивает весь словарь на каждой странице. Посетитель страницы /login загружает описания функций, разделы помощи и интерфейс личного кабинета.

    Частично это решается делением на неймспейсы. Но ручное отслеживание привязки текстов к маршрутам трудоемко и часто приводит к сбоям.

    График ниже оценивает объём контента для теоретического приложения, в котором от 1 до 10 страниц и от 1 до 10 языков, примерно по 30 КБ текста на страницу. Динамическая загрузка по локали убирает ось языков, ограничение контента компонентом или маршрутом убирает ось страниц, и только их сочетание сохраняет объём стабильным.

    Теоретическая утечка контента по архитектуре

    Intlayer решает эту задачу с помощью статического анализа: компилятор Intlayer бандлит исключительно те строки, которые задействованы на конкретном маршруте, снижая утечку до 0.0%.

    Почему next-intl не поддается tree-shaking

    Интерфейс библиотеки опирается на строковые вызовы ключей во время выполнения:

    UserProfile.tsx
    "use client";
    
    import { useTranslations } from "next-intl";
    
    export function UserProfile() {
      const t = useTranslations("UserProfile");
    
      return <h2>{t("heading")}</h2>;
    }
    
    UserProfile.tsx
    "use client";
    
    import { useIntlayer } from "next-intlayer";
    
    export function UserProfile() {
      const { heading } = useIntlayer("user-profile");
    
      return <h2>{heading}</h2>;
    }
    

    Turbopack и Webpack не могут предсказать, какие именно ключи из UserProfile будут вызваны. Чтобы не допустить падения приложения, бандлер включает весь неймспейс целиком в клиентский чанк. Деструктурированные свойства в Intlayer позволяют компилятору четко видеть зависимости и вырезать ненужные поля. Подробнее в оптимизации бандла.

    Опыт разработки

    Внешний JSON против совместного размещения

    В next-intl тексты хранятся в отдельных JSON-файлах в папке messages/. Intlayer располагает файлы контента рядом с компонентами:

    messages/en.json
    {
      "authModal": {
        "title": "Sign in to your account",
        "submitButton": "Continue"
      }
    }
    
    messages/ru.json
    {
      "authModal": {
        "title": "Войдите в аккаунт",
        "submitButton": "Продолжить"
      }
    }
    
    AuthModal.tsx
    import { useTranslations } from "next-intl";
    
    export const AuthModal = () => {
      const t = useTranslations("authModal");
      return (
        <form>
          <h2>{t("title")}</h2>
          <button type="submit">{t("submitButton")}</button>
        </form>
      );
    };
    
    AuthModal.content.ts
    import { t, type Dictionary } from "intlayer";
    
    export default {
      key: "auth-modal",
      content: {
        title: t({
          en: "Sign in to your account",
          ru: "Войдите в аккаунт",
        }),
        submitButton: t({
          en: "Continue",
          ru: "Продолжить",
        }),
      },
    } satisfies Dictionary;
    
    AuthModal.tsx
    import { useIntlayer } from "next-intlayer";
    
    export const AuthModal = () => {
      const { title, submitButton } = useIntlayer("auth-modal");
      return (
        <form>
          <h2>{title}</h2>
          <button type="submit">{submitButton}</button>
        </form>
      );
    };
    

    При удалении или рефакторинге AuthModal.tsx его переводы перемещаются или удаляются вместе с ним.

    Автодополнение против строгой проверки полноты

    Расширение IntlMessages в next-intl обеспечивает автодополнение в редакторе по основному языковому файлу:

    global.d.ts
    import en from "./messages/en.json";
    
    type Messages = typeof en;
    
    declare global {
      interface IntlMessages extends Messages {}
    }
    

    Однако контроль распространяется лишь на базовый язык. Если ключ пропадет из ru.json, TypeScript не выдаст ошибок, CI останется успешным, а пользователи увидят пустые места.

    Intlayer генерирует типы на основе всех файлов контента. Активация режима strictMode останавливает сборку при отсутствии перевода в любой из указанных локалей.

    Сравнение инструментария и поддержка ИИ

    Возможностьnext-intlIntlayer
    Расширение VS Code❌ Нет✅ Официальное расширение
    Language Server (LSP)❌ Нет✅ Встроенный LSP
    MCP Server (для ИИ-агентов)❌ Нет✅ Готовый MCP-сервер
    Навыки агентов (Skills)❌ Нет✅ Доступные навыки
    Визуальная CMS❌ Нет✅ Бесплатно и Open Source

    Собственные серверы LSP и MCP дают ИИ-ассистентам возможность анализировать структуру контента и точно предлагать или актуализировать переводы.

    Связь с Crowdin и развитие продукта

    next-intl является официальным партнером Crowdin. Спонсорство помогает развивать проект, однако задает приоритеты: ориентируясь на сторонние TMS-платформы, библиотека не ставит целью создание встроенной бесплатной локальной ИИ-утилиты для перевода.

    Intlayer предлагает эти решения из коробки:

    Локальный ИИ-перевод (intlayer fill):

    Находит и переводит недостающие строки через ваши личные API-ключи OpenAI, Anthropic, Mistral или Gemini.

    Автономная визуальная CMS:

    Используйте Intlayer CMS для визуального редактирования с сохранением изменений напрямую в Git.

    Лицензия Apache 2.0:

    Все компоненты экосистемы полностью открыты.

    Где next-intl все еще удобен?

    Если в приложении активно применяются специфические конструкции порядковых и множественных форм, ICU-движок next-intl полностью справляется с задачей.

    Для команд, чья инфраструктура переводов уже плотно интегрирована с Crowdin, библиотека подходит органично.

    Если приложение отвечает всем требованиям, а размер бандла устраивает команду, миграция не является критичной.

    Как улучшить текущую конфигурацию next-intl?

    Intlayer предоставляет готовый пакет совместимости, который точно повторяет сигнатуры функций и хуков next-intl (такие как useTranslations, getTranslations и утилиты маршрутизации). Вам не нужно переписывать компоненты или страницы, чтобы получить оптимизацию на уровне компилятора.

    Настройка выполняется одной командой:

    bash
    npx intlayer init --interactive
    

    Интерактивный интерфейс командной строки:

    1. Устанавливает пакет совместимости @intlayer/next-intl.
    2. Настраивает алиасы сборщика, чтобы привычные импорты (next-intl, next-intl/server) прозрачно вели на Intlayer, позволяя удалить старую библиотеку из package.json.
    3. Сразу активирует поддержку языкового сервера (LSP), исключает перекрестные утечки переводов между страницами (полный tree-shaking) и включает локальные процессы ИИ-перевода без масштабного рефакторинга.

    Подробные инструкции можно найти в наших руководствах:

    • Прямая совместимость: Сохраняйте вызовы useTranslations, используя адаптер совместимости с next-intl.
    • Руководство по миграции: Преобразуйте существующие JSON-файлы в типизированные словари с помощью инструкции по миграции.
    • Гибридный вариант: Оставьте next-intl для вывода интерфейса, подключив Intlayer к next-intl для локального перевода через ИИ.

    Оцените вес и утечки вашего проекта с помощью бесплатного SEO-сканера i18n:

    Дополнительные материалы

    Комментарии

    Пока нет комментариев. Будьте первым, кто поделится своими мыслями.

    Похожие сообщения

    Последние сообщения