Получайте уведомления о предстоящих релизах Intlayer
    Создание:2026-01-10Последнее обновление:2026-01-10

    Переведите ваш сайт Next.js 16 (без [locale] в пути страницы) с помощью Intlayer | Интернационализация (i18n)

    Смотрите шаблон приложения на GitHub.

    Содержание

    Что такое Intlayer?

    Intlayer — это инновационная, открытая библиотека для интернационализации (i18n), созданная для упрощения поддержки нескольких языков в современных веб-приложениях. Intlayer бесшовно интегрируется с последним фреймворком Next.js 16, включая его мощный App Router. Он оптимизирован для работы с Server Components для эффективного рендеринга и полностью совместим с Turbopack.

    С Intlayer вы можете:

    • Легко управлять переводами с помощью декларативных словарей на уровне компонентов.
    • Динамически локализовать метаданные, маршруты и контент.
    • Получать доступ к переводам как в клиентских, так и в серверных компонентах.
    • Обеспечить поддержку TypeScript с автогенерируемыми типами, улучшающими автодополнение и обнаружение ошибок.
    • Воспользуйтесь продвинутыми возможностями, такими как динамическое определение локали и её переключение.
    Intlayer совместим с Next.js 12, 13, 14 и 16. Если вы используете Next.js Page Router, вы можете обратиться к этому руководству. Для Next.js 12, 13, 14 с App Router — см. это руководство.

    Пошаговое руководство по настройке Intlayer в приложении Next.js

    Шаг 1: Установка зависимостей

    Установите необходимые пакеты с помощью npm:

    bash
    npm install intlayer next-intlayernpx intlayer init
    • intlayer

      Основной пакет, предоставляющий инструменты интернационализации для управления конфигурацией, переводов, декларации контента, транспиляции и команд CLI.

    • next-intlayer

    Пакет, который интегрирует Intlayer с Next.js. Он предоставляет context providers и хуки для интернационализации в Next.js. Дополнительно он включает плагин Next.js для интеграции Intlayer с Webpack или Turbopack, а также прокси для определения предпочтительной локали пользователя, управления cookies и обработки перенаправлений URL.

    Шаг 2: Настройка вашего проекта

    Ниже приведена итоговая структура, которую мы получим:

    .├── src│   ├── app│   │   ├── layout.tsx│   │   ├── page.content.ts│   │   └── page.tsx│   ├── components│   │   ├── clientComponentExample│   │   │   ├── client-component-example.content.ts│   │   │   └── ClientComponentExample.tsx│   │   ├── localeSwitcher│   │   │   ├── localeSwitcher.content.ts│   │   │   └── LocaleSwitcher.tsx│   │   └── serverComponentExample│   │       ├── server-component-example.content.ts│   │       └── ServerComponentExample.tsx│   └── proxy.ts├── intlayer.config.ts├── next.config.ts├── package.json└── tsconfig.json
    Если вы не хотите маршрутизацию по локалям, intlayer можно использовать как простой provider / hook. См. это руководство для получения дополнительных сведений.

    Создайте файл конфигурации для настройки языков вашего приложения:

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [      Locales.ENGLISH,      Locales.FRENCH,      Locales.SPANISH,      // Ваши другие локали    ],    defaultLocale: Locales.ENGLISH,  },  routing: {    mode: "search-params", // или `no-prefix` — полезно для обнаружения в middleware  },};export default config;
    С помощью этого файла конфигурации вы можете настроить локализованные URL, перенаправление через прокси, имена cookie, расположение и расширение ваших деклараций контента, отключить логи Intlayer в консоли и многое другое. Для полного списка доступных параметров см. документацию по конфигурации.

    Шаг 3: Интеграция Intlayer в конфигурацию Next.js

    Настройте ваш проект Next.js для использования Intlayer:

    next.config.ts
    import type { NextConfig } from "next";import { withIntlayer } from "next-intlayer/server";const nextConfig: NextConfig = {  /* параметры конфигурации здесь */};export default withIntlayer(nextConfig);

    Плагин Next.js withIntlayer() используется для интеграции Intlayer с Next.js. Он обеспечивает генерацию файлов декларации контента и их отслеживание в режиме разработки. Он определяет переменные окружения Intlayer внутри сред Webpack или Turbopack. Дополнительно он предоставляет алиасы для оптимизации производительности и обеспечивает совместимость с серверными компонентами.

    Функция withIntlayer() возвращает Promise. Она позволяет подготовить словари intlayer перед началом сборки. Если вы хотите использовать её вместе с другими плагинами, вы можете дождаться её выполнения с помощью await. Пример:

    const nextConfig = await withIntlayer(nextConfig);const nextConfigWithOtherPlugins = withOtherPlugins(nextConfig);export default nextConfigWithOtherPlugins;

    Если вы хотите использовать его синхронно, вы можете воспользоваться функцией withIntlayerSync(). Пример:

    const nextConfig = withIntlayerSync(nextConfig);const nextConfigWithOtherPlugins = withOtherPlugins(nextConfig);export default nextConfigWithOtherPlugins;

    Intlayer автоматически определяет, использует ли ваш проект webpack или Turbopack на основе флагов командной строки --webpack, --turbo или --turbopack, а также вашей текущей версии Next.js.

    Поскольку next>=16, если вы используете Rspack, вы должны явно заставить Intlayer использовать конфигурацию webpack, отключив Turbopack:

    withRspack(withIntlayer(nextConfig, { enableTurbopack: false }));

    Шаг 4: Определение динамических маршрутов локализации

    Удалите всё из RootLayout и замените его следующим кодом:

    src/app/layout.tsx
    import type { Metadata } from "next";import type { ReactNode } from "react";import "./globals.css";import { IntlayerClientProvider, LocalPromiseParams } from "next-intlayer";import { getHTMLTextDir, getIntlayer } from "intlayer";import { getLocale } from "next-intlayer/server";export { generateStaticParams } from "next-intlayer";export const generateMetadata = async ({  params,}: LocalPromiseParams): Promise<Metadata> => {  const { locale } = await params;  const { title, description, keywords } = getIntlayer("metadata", locale);  return {    title,    description,    keywords,  };};const RootLayout = async ({  children,}: Readonly<{  children: ReactNode;}>) => {  const locale = await getLocale();  return (    <html lang={locale} dir={getHTMLTextDir(locale)}>      <IntlayerClientProvider defaultLocale={locale}>        <body>{children}</body>      </IntlayerClientProvider>    </html>  );};export default RootLayout;

    Шаг 5: Объявите ваш контент

    Создавайте и управляйте вашими объявлениями контента для хранения переводов:

    src/app/metadata.content.ts
    import { t, type Dictionary } from "intlayer";import { Metadata } from "next";const metadataContent = {  key: "metadata",  content: {    title: t({      ru: "Заголовок моего проекта",      en: "My Project Title",      fr: "Le Titre de mon Projet",      es: "El Título de mi Proyecto",    }),    description: t({      ru: "Ознакомьтесь с нашей инновационной платформой, созданной для оптимизации рабочего процесса и повышения продуктивности.",      en: "Discover our innovative platform designed to streamline your workflow and boost productivity.",      ru: "Откройте для себя нашу инновационную платформу, созданную для оптимизации рабочего процесса и повышения продуктивности.",      fr: "Découvrez notre plateforme innovante conçue pour simplifier votre flux de travail et booster votre productivité.",      es: "Descubra su plataforma innovadora diseñada para simplificar su flujo de trabajo y aumentar su productividad.",    }),    keywords: t({      ru: ["инновации", "продуктивность", "рабочий процесс", "SaaS"],      en: ["innovation", "productivity", "workflow", "SaaS"],      fr: ["innovation", "productivité", "flux de travail", "SaaS"],      es: ["innovación", "productividad", "flujo de trabajo", "SaaS"],    }),  },} as Dictionary<Metadata>;export default metadataContent;
    src/app/metadata.content.mjs
    import { t, type Dictionary } from "intlayer";/** @type {import('intlayer').Dictionary<import('next').Metadata>} */const metadataContent = {  key: "metadata",  content: {    title: t({      ru: "Название моего проекта",      en: "My Project Title",      fr: "Le Titre de mon Projet",      es: "El Título de mi Proyecto",    }),    description: t({      ru: "Ознакомьтесь с нашей инновационной платформой, созданной для оптимизации рабочего процесса и повышения продуктивности.",      en: "Discover our innovative platform designed to streamline your workflow and boost productivity.",      fr: "Découvrez notre plateforme innovante conçue pour simplifier votre flux de travail et booster votre productivité.",      es: "Descubra nuestra plataforma innovadora diseñada para simplificar su flujo de trabajo y aumentar su productividad.",    }),    keywords: t({      ru: ["инновации", "продуктивность", "рабочий процесс", "SaaS"],      en: ["innovation", "productivity", "workflow", "SaaS"],      fr: ["innovation", "productivité", "flux de travail", "SaaS"],      es: ["innovación", "productividad", "flujo de trabajo", "SaaS"],    }),  },};export default metadataContent;
    src/app/page.content.ts
    import { t, type Dictionary } from "intlayer";const pageContent = {  key: "page",  content: {    getStarted: {      main: t({        ru: "Начните с редактирования",        en: "Get started by editing",        fr: "Commencez par éditer",        es: "Comience por editar",      }),      pageLink: "src/app/page.tsx",    },  },} satisfies Dictionary;export default pageContent;
    Ваши объявления контента могут быть определены в любом месте вашего приложения, при условии что они включены в директорию contentDir (по умолчанию ./src). И соответствуют расширению файла объявления контента (по умолчанию .content.{json,ts,tsx,js,jsx,mjs,mjx,cjs,cjx}).
    Для получения подробной информации обратитесь к документации по объявлениям контента.

    Шаг 6: Использование контента в коде

    Получайте доступ к словарям контента по всему приложению:

    src/app/page.tsx
    import type { FC } from "react";import { ClientComponentExample } from "@components/clientComponentExample/ClientComponentExample";import { ServerComponentExample } from "@components/serverComponentExample/ServerComponentExample";import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";import { NextPage } from "next";import { getLocale } from "intlayer";import { headers, cookies } from "next/headers";const PageContent: FC = () => {  const content = useIntlayer("page");  return (    <>      <p>{content.getStarted.main}</p>      <code>{content.getStarted.pageLink}</code>    </>  );};const Page: NextPage = async () => {  // Ожидайте headers и cookies в Next.js 15+  const headerList = await headers();  const cookieList = await cookies();  const locale = await getLocale({    // Сначала проверьте cookie intlayer (по умолчанию: 'INTLAYER_LOCALE')    getCookie: (name) => cookieList.get(name)?.value,    // Затем проверяем заголовок intlayer (по умолчанию: 'x-intlayer-locale')    // И, наконец, проверяем заголовок accept-language ('accept-language')    getHeader: (name) => headerList.get(name),  });  return (    <IntlayerServerProvider locale={locale}>      <PageContent />      <ServerComponentExample />      <ClientComponentExample />    </IntlayerServerProvider>  );};export default Page;
    • IntlayerClientProvider используется для предоставления locale клиентским компонентам. Его можно разместить в любом родительском компоненте, включая layout. Однако рекомендуется помещать его в layout, потому что Next.js использует общий код layout между страницами, что делает это более эффективным. Используя IntlayerClientProvider в layout, вы избегаете повторной инициализации на каждой странице, повышаете производительность и поддерживаете единый контекст локализации во всём приложении.
    • IntlayerServerProvider используется для предоставления locale серверным дочерним компонентам. Его нельзя установить в layout.
    Layout и page не могут разделять общий server context, потому что система server context основана на хранилище данных, привязанном к каждому запросу (через механизм React's cache), из‑за чего каждый «context» воссоздаётся для разных сегментов приложения. Размещение provider в общем layout нарушит эту изоляцию и помешает корректной передаче значений server context в ваши server components.
    src/components/clientComponentExample/ClientComponentExample.tsx
    "use client";import type { FC } from "react";import { useIntlayer } from "next-intlayer";export const ClientComponentExample: FC = () => {  const content = useIntlayer("client-component-example"); // Создаёт соответствующее объявление контента  return (    <div>      <h2>{content.title}</h2>      <p>{content.content}</p>    </div>  );};
    src/components/serverComponentExample/ServerComponentExample.tsx
    import type { FC } from "react";import { useIntlayer } from "next-intlayer/server";export const ServerComponentExample: FC = () => {  const content = useIntlayer("server-component-example"); // Создать декларацию связанного контента  return (    <div>      <h2>{content.title}</h2>      <p>{content.content}</p>    </div>  );};
    Если вы хотите использовать содержимое в строковом атрибуте, таком как alt, title, href, aria-label и т.д., вы должны вызвать значение функции, например:
    <img src={content.image.src.value} alt={content.image.value} />
    Чтобы узнать больше о хуке useIntlayer, см. документацию.

    (Опционально) Шаг 7: Настройка прокси для определения локали

    Настройте прокси для определения предпочитаемой пользователем локали:

    src/proxy.ts
    export { intlayerProxy as proxy } from "next-intlayer/proxy";export const config = {  matcher:    "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",};
    Прокси intlayerProxy используется для определения предпочитаемой локали пользователя и перенаправления его на соответствующий URL, как указано в конфигурации. Кроме того, он позволяет сохранять предпочитаемую локаль пользователя в cookie.
    Если требуется связать несколько прокси вместе (например, intlayerProxy с прокси авторизации или пользовательскими прокси), Intlayer предоставляет вспомогательную функцию multipleProxies.
    import { multipleProxies, intlayerProxy } from "next-intlayer/proxy";import { customProxy } from "@utils/customProxy";export const proxy = multipleProxies([intlayerProxy, customProxy]);

    (Необязательно) Шаг 8: Изменение языка вашего контента

    Чтобы изменить язык содержимого в Next.js, рекомендуется использовать компонент Link, чтобы перенаправлять пользователей на соответствующую локализованную страницу. Компонент Link поддерживает предзагрузку страницы (prefetch), что помогает избежать полной перезагрузки страницы.

    src/components/localeSwitcher/LocaleSwitcher.tsx
    "use client";import type { FC } from "react";import { Locales, getHTMLTextDir, getLocaleName } from "intlayer";import { useLocale } from "next-intlayer";export const LocaleSwitcher: FC = () => {  const { locale, availableLocales, setLocale } = useLocale({    onChange: () => window.location.reload(),  });  return (    <div>      <button popoverTarget="localePopover">{getLocaleName(locale)}</button>      <div id="localePopover" popover="auto">        {availableLocales.map((localeItem) => (          <button            key={localeItem}            aria-current={locale === localeItem ? "page" : undefined}            onClick={() => setLocale(localeItem)}          >            <span>              {/* Локаль — например FR */}              {localeItem}            </span>            <span>              {/* Название языка в своей локали — например Français */}              {getLocaleName(localeItem, locale)}            </span>            <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>              {/* Название языка в текущей локали — например Francés при текущей локали Locales.SPANISH */}              {getLocaleName(localeItem)}            </span>            <span dir="ltr" lang={Locales.ENGLISH}>              {/* Название языка на английском — напр., French */}              {getLocaleName(localeItem, Locales.ENGLISH)}            </span>          </button>        ))}      </div>    </div>  );};
    Альтернативный способ — использовать функцию setLocale, предоставляемую хуком useLocale. Эта функция не будет позволять предзагружать страницу. См. документацию по хуку useLocale для получения дополнительных сведений.

    Ссылки в документации:

    (Необязательно) Шаг 9: Получить текущую локаль в Server Actions

    Если вам нужна активная локаль внутри Server Action (например, чтобы локализовать письма или выполнить логику, зависящую от локали), вызовите getLocale из next-intlayer/server:

    src/app/actions/getLocale.ts
    "use server";import { getLocale } from "next-intlayer/server";export const myServerAction = async () => {  const locale = await getLocale();  // Выполните действия с локалью};

    Функция getLocale использует каскадную стратегию для определения локали пользователя:

    1. Сначала она проверяет заголовки запроса на наличие значения локали, которое могло быть установлено proxy
    2. Если в заголовках локаль не найдена, она ищет локаль в cookies
    3. Если cookies не найдено, она пытается определить предпочитаемый язык пользователя из настроек браузера
    4. В крайнем случае используется локаль по умолчанию, настроенная в приложении

    Это гарантирует выбор наиболее подходящей локали на основе доступного контекста.

    (Необязательно) Шаг 10: Оптимизируйте размер бандла

    При использовании next-intlayer словари по умолчанию включаются в бандл для каждой страницы. Чтобы оптимизировать размер бандла, Intlayer предоставляет опциональный SWC-плагин, который интеллектуально заменяет вызовы useIntlayer с помощью макросов. Это гарантирует, что словари будут включаться в бандлы только для тех страниц, которые действительно их используют.

    Чтобы включить эту оптимизацию, установите пакет @intlayer/swc. После установки next-intlayer автоматически обнаружит и начнёт использовать плагин:

    bash
    npm install @intlayer/swc --save-devnpx intlayer init
    Примечание: Эта оптимизация доступна только для Next.js 13 и выше.
    Примечание: Этот пакет не устанавливается по умолчанию, поскольку SWC-плагины в Next.js всё ещё экспериментальны. Это может измениться в будущем.
    Примечание: Если установить опцию как importMode: 'dynamic' или importMode: 'live', будет полагаться на Suspense, поэтому вам придётся оборачивать вызовы useIntlayer в границу Suspense. Это означает, что вы не сможете использовать useIntlayer прямо на верхнем уровне вашего компонента Page / Layout.

    Отслеживание изменений словарей в Turbopack

    Когда вы используете Turbopack в качестве сервера разработки с командой next dev, изменения словарей по умолчанию не будут автоматически обнаруживаться.

    Это ограничение возникает из-за того, что Turbopack не может параллельно запускать плагины webpack для отслеживания изменений в ваших файлах с содержимым. Чтобы обойти это, вам нужно использовать команду intlayer watch, чтобы одновременно запустить сервер разработки и наблюдатель сборки Intlayer.

    package.json
    {  // ... Ваши существующие настройки package.json  "scripts": {    // ... Ваши существующие конфигурации скриптов    "dev": "intlayer watch --with 'next dev'",  },}
    Если вы используете next-intlayer@<=6.x.x, необходимо сохранять флаг --turbopack, чтобы приложение Next.js 16 корректно работало с Turbopack. Рекомендуем использовать next-intlayer@>=7.x.x, чтобы избежать этого ограничения.

    Настройка TypeScript

    Intlayer использует module augmentation, чтобы получить преимущества TypeScript и укрепить вашу codebase.

    Автодополнение

    Ошибка перевода

    Убедитесь, что конфигурация TypeScript включает автогенерируемые типы.

    tsconfig.json
    {  // ... Ваши существующие конфигурации TypeScript  "include": [    // ... Ваши существующие конфигурации TypeScript    ".intlayer/**/*.ts", // Включить автоматически сгенерированные типы  ],}

    Конфигурация Git

    Рекомендуется игнорировать файлы, сгенерированные Intlayer. Это позволяет избежать их добавления в ваш Git-репозиторий.

    Для этого вы можете добавить следующие инструкции в файл .gitignore:

    .gitignore
    # Игнорировать файлы, сгенерированные Intlayer.intlayer

    Расширение VS Code

    Чтобы улучшить опыт разработки с Intlayer, вы можете установить официальное Intlayer VS Code Extension.

    Установить из VS Code Marketplace

    Это расширение предоставляет:

    • Автодополнение для ключей переводов.
    • Обнаружение ошибок в реальном времени для отсутствующих переводов.
    • Встроенные превью переведённого контента.
    • Быстрые действия для простого создания и обновления переводов.

    Для получения подробной информации о том, как использовать расширение, обратитесь к документации Intlayer VS Code Extension.

    Продвинутые возможности

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

    Получайте уведомления о предстоящих релизах Intlayer