Creation:2024-12-06Last update:2026-05-31

    Переведите ваш Next.js 14 and App Router с Intlayer | Интернационализация (i18n)

    ide.intlayer.org

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

    Почему Intlayer лучше альтернатив?

    По сравнению с основными решениями, такими как next-intl или i18next, Intlayer представляет собой решение со встроенными оптимизациями, такими как:

    Intlayer оптимизирован для работы с Серверными компонентами для эффективного рендеринга и полностью совместим с Turbopack. Он не блокирует статический рендеринг и предлагает промежуточное программное обеспечение, а также все функции, необходимые для масштабирования интернационализации (i18n).

    Intlayer совместим с Next.js 12, 13, 14, 15 и 16. Если вы используете маршрутизатор страниц Next.js, вы можете обратиться к этому [руководству] (/ru/doc/environment/nextjs/next-with-page-router). Маршрутизация локали полезна для SEO, размера пакета и производительности. Если вам это не нужно, вы можете обратиться к этому [руководству] (/ru/doc/environment/nextjs/no-locale-path). Для Next.js 12, 13, 14 и 15 с App Router обратитесь к этому [руководству] (/ru/doc/environment/nextjs/14).

    Вместо загрузки огромных файлов JSON на свои страницы загружайте только необходимый контент. Intlayer помогает уменьшить размер бандла и страниц до 50 %.

    Определение области содержимого вашего приложения облегчает обслуживание крупномасштабных приложений. Вы можете дублировать или удалить отдельную папку функций, не утруждав себя мысленным бременем проверки всей кодовой базы контента. Кроме того, Intlayer полностью типизирован, что обеспечивает точность вашего контента.

    Совместное размещение контента уменьшает контекст, необходимый для моделей большого языка (LLM). Intlayer также поставляется с набором инструментов, таких как CLI для проверки отсутствия переводов,LSP, MCP, и навыки агента, чтобы сделать работу разработчика (DX) еще более удобной для агентов ИИ.

    Используйте автоматизацию для перевода в своем конвейере CI/CD, используя LLM по вашему выбору за счет вашего поставщика ИИ. Intlayer также предлагает компилятор для автоматизации извлечения контента, а также веб-платформу, которая помогает переводить в фоновом режиме.

    Подключение больших файлов JSON к компонентам может привести к проблемам с производительностью и реактивностью. Intlayer оптимизирует загрузку контента во время сборки (build time).

    Intlayer — это больше, чем просто решение i18n. Он предоставляет автономный визуальный редактор и полный CMS, чтобы помочь вам управлять многоязычным контентом в реальном времени, упрощая сотрудничество с переводчиками, копирайтерами и другими членами команды. Контент может храниться локально и/или удаленно.


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

    1. Установите зависимости

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

      bash
      npm install intlayer next-intlayernpx intlayer init
      • intlayer

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

      • next-intlayer

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

    2. Настройте ваш проект

      Here is the final structure that we will make:

      bash
      .├── src│   ├── app│   │   ├── [locale]│   │   │   ├── layout.tsx            # Locale layout for the Intlayer provider│   │   │   ├── page.content.ts│   │   │   └── page.tsx│   │   └── layout.tsx                # Root layout for style and global providers│   ├── components│   │   ├── client-component-example.content.ts│   │   ├── ClientComponentExample.tsx│   │   ├── LocaleSwitcher│   │   │   ├── localeSwitcher.content.ts│   │   │   └── LocaleSwitcher.tsx│   │   ├── server-component-example.content.ts│   │   └── ServerComponentExample.tsx│   └── middleware.ts├── intlayer.config.ts├── next.config.ts├── package.json└── tsconfig.json
      If you don't want locale routing, intlayer can be used as a simple provider / hook. See this guide for more details.

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

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

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

      next.config.mjs
      import { withIntlayer } from "next-intlayer/server";/** @type {import('next').NextConfig} */const nextConfig = {};export default withIntlayer(nextConfig);
      Плагин withIntlayer() для Next.js используется для интеграции Intlayer с Next.js. Он обеспечивает создание файлов декларации контента и их мониторинг в режиме разработки. Он определяет переменные окружения Intlayer в средах Webpack или Turbopack. Кроме того, он предоставляет алиасы для оптимизации производительности и обеспечивает совместимость с серверными компонентами.
    4. Настройка Middleware для определения локали

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

      src/middleware.ts
      export { intlayerMiddleware as middleware } from "next-intlayer/middleware";
      
      export const config = {
        matcher:
          "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
      };
      intlayerMiddleware используется для определения предпочтительной локали пользователя и перенаправления его на соответствующий URL, как указано в конфигурации. Кроме того, он позволяет сохранять предпочтительную локаль пользователя в cookie.
      Адаптируйте параметр matcher для соответствия маршрутам вашего приложения. Для получения дополнительной информации обратитесь к документации Next.js по настройке matcher.
    5. Определите динамические маршруты локали

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

      src/app/layout.tsx
      import type { PropsWithChildren, FC } from "react";
      import "./globals.css";
      
      const RootLayout: FC<PropsWithChildren> = ({ children }) => children;
      
      export default RootLayout;
      Оставляя компонент RootLayout пустым, вы можете установить атрибуты lang и dir для тега <html>.

      Для реализации динамической маршрутизации укажите путь для локали, добавив новый layout в вашу директорию [locale]:

      src/app/[locale]/layout.tsx
      import {
        type Next14LayoutIntlayer,
        IntlayerClientProvider,
      } from "next-intlayer";
      import { Inter } from "next/font/google";
      import { getHTMLTextDir } from "intlayer";
      
      const inter = Inter({ subsets: ["latin"] });
      
      const LocaleLayout: Next14LayoutIntlayer = ({
        children,
        params: { locale },
      }) => (
        <html lang={locale} dir={getHTMLTextDir(locale)}>
          <body className={inter.className}>
            <IntlayerClientProvider locale={locale}>
              {children}
            </IntlayerClientProvider>
          </body>
        </html>
      );
      Сегмент пути [locale] используется для определения локали. Пример: /en-US/about будет относиться к en-US, а /fr/about к fr.
      На этом этапе вы столкнетесь с ошибкой: Ошибка: Отсутствуют теги <html> и <body> в корневом макете.. Это ожидаемо, так как файл /app/page.tsx больше не используется и может быть удален. Вместо этого сегмент пути [locale] активирует страницу /app/[locale]/page.tsx. Таким образом, страницы будут доступны по путям, таким как /en, /fr, /es в вашем браузере. Чтобы установить локаль по умолчанию в качестве корневой страницы, обратитесь к настройке middleware на шаге 4.

      Затем реализуйте функцию generateStaticParams в вашем приложении Layout.

      src/app/[locale]/layout.tsx
      export { generateStaticParams } from "next-intlayer"; // Строка для вставки
      
      const LocaleLayout: Next14LayoutIntlayer = ({
        children,
        params: { locale },
      }) => {
        /*... Остальной код*/
      };
      
      export default LocaleLayout;
      generateStaticParams гарантирует, что ваше приложение предварительно создает необходимые страницы для всех локалей, уменьшая вычисления во время выполнения и улучшая пользовательский опыт. Для получения дополнительной информации обратитесь к документации Next.js о generateStaticParams.
    6. Объявите ваш контент

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

      src/app/[locale]/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,cjs}). Для получения дополнительной информации обратитесь к документации по декларации контента.
    7. Используйте контент в вашем коде

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

      src/app/[locale]/page.tsx
      import { ClientComponentExample } from "@components/ClientComponentExample";
      import { ServerComponentExample } from "@components/ServerComponentExample";
      import { type Next14PageIntlayer } from "next-intlayer";
      import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";
      
      const Page: Next14PageIntlayer = ({ params: { locale } }) => {
        const content = useIntlayer("page", locale);
      
        return (
          <>
            <p>
              {content.getStarted.main}
              <code>{content.getStarted.pageLink}</code>
            </p>
      
            <IntlayerServerProvider locale={locale}>
              <ServerComponentExample />
              <ClientComponentExample />
            </IntlayerServerProvider>
          </>
        );
      };
      
      export default Page;
      • IntlayerClientProvider используется для предоставления локали клиентским компонентам. Он может быть размещен в любом родительском компоненте, включая layout. Однако рекомендуется размещать его в layout, так как Next.js использует общий код layout для страниц, что делает его более эффективным. Используя IntlayerClientProvider в layout, вы избегаете его повторной инициализации для каждой страницы, улучшая производительность и поддерживая единый контекст локализации во всем приложении.
      • IntlayerServerProvider используется для предоставления локали серверным дочерним элементам. Он не может быть установлен в layout.
      src/components/ClientComponentExample.tsx
      "use client";
      
      import type { FC } from "react";
      import { useIntlayer } from "next-intlayer";
      
      const ClientComponentExample: FC = () => {
        const content = useIntlayer("client-component-example"); // Создание связанной декларации контента
      
        return (
          <div>
            <h2>{content.title}</h2>
            <p>{content.content}</p>
          </div>
        );
      };
      src/components/ServerComponentExample.tsx
      import type { FC } from "react";
      import { useIntlayer } from "next-intlayer/server";
      
      const ServerComponentExample: FC = () => {
        const content = useIntlayer("server-component-example"); // Создание связанной декларации контента
      
        return (
          <div>
            <h2>{content.title}</h2>
            <p>{content.content}</p>
          </div>
        );
      };
      Если вы хотите использовать ваш контент в атрибуте string, таком как alt, title, href, aria-label и т.д., вы должны вызвать значение функции, например:
      html
      <img src="{content.image.src.value}" alt="{content.image.value}" /><img src="{content.image.src.toString()}" alt="{content.image.toString()}" /><img src="{String(content.image.src)}" alt="{String(content.image)}" />
      Чтобы узнать больше о хуке useIntlayer, обратитесь к документации.
    8. Интернационализация ваших метаданных

      Необязательно

      Если вы хотите интернационализировать ваши метаданные, такие как заголовок вашей страницы, вы можете использовать функцию generateMetadata, предоставляемую Next.js. Внутри функции используйте функцию getTranslation для перевода ваших метаданных.

      src/app/[locale]/layout.tsx or src/app/[locale]/page.tsx
      import {  type IConfigLocales,  getTranslation,  getMultilingualUrls,} from "intlayer";import type { Metadata } from "next";import type { LocalParams } from "next-intlayer";export const generateMetadata = ({  params: { locale },}: LocalParams): Metadata => {  const t = <T>(content: IConfigLocales<T>) => getTranslation(content, locale);  /**   * Генерирует объект, содержащий все URL для каждого локаля.   *   * Пример:   * ```ts   *  getMultilingualUrls('/about');   *   *  // Возвращает   *  // {   *  //   en: '/about',   *  //   fr: '/fr/about',   *  //   es: '/es/about',   *  // }   * ```   */  const multilingualUrls = getMultilingualUrls("/");  return {    title: t<string>({      ru: "Мой заголовок",      en: "My title",      fr: "Mon titre",      es: "Mi título",    }),    description: t({      ru: "Мое описание",      en: "My description",      fr: "Ma description",      es: "Mi descripción",    }),    alternates: {      canonical: multilingualUrls[locale as keyof typeof multilingualUrls],      languages: { ...multilingualUrls, "x-default": "/" },    },    openGraph: {      url: multilingualUrls[locale],    },  };};// ... Остальной код
      Узнайте больше об оптимизации метаданных в официальной документации Next.js.
    9. Интернационализация вашего sitemap.xml и robots.txt

      Необязательно

      Для интернационализации вашего sitemap.xml и robots.txt вы можете использовать функцию getMultilingualUrls, предоставляемую Intlayer. Эта функция позволяет генерировать мультиязычные URL для вашего sitemap.

      src/app/sitemap.ts
      import { getMultilingualUrls } from "intlayer";import type { MetadataRoute } from "next";const sitemap = (): MetadataRoute.Sitemap => [  {    url: "https://example.com",    alternates: {      languages: getMultilingualUrls("https://example.com"),    },  },  {    url: "https://example.com/login",    alternates: {      languages: getMultilingualUrls("https://example.com/login"),    },  },  {    url: "https://example.com/register",    alternates: {      languages: getMultilingualUrls("https://example.com/register"),    },  },];export default sitemap;import { getMultilingualUrls } from "intlayer";const sitemap = () => [  {    url: "https://example.com",    alternates: {      languages: getMultilingualUrls("https://example.com"),    },  },  {    url: "https://example.com/login",    alternates: {      languages: getMultilingualUrls("https://example.com/login"),    },  },  {    url: "https://example.com/register",    alternates: {      languages: getMultilingualUrls("https://example.com/register"),    },  },];export default sitemap;
      src/app/robots.ts
      import type { MetadataRoute } from "next";
      import { getMultilingualUrls } from "intlayer";
      
      const getAllMultilingualUrls = (urls: string[]) =>
        urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);
      
      const robots = (): MetadataRoute.Robots => ({
        rules: {
          userAgent: "*",
          allow: ["/"],
          disallow: getAllMultilingualUrls(["/login", "/register"]),
        },
        host: "https://example.com",
        sitemap: `https://example.com/sitemap.xml`,
      });
      
      export default robots;
      Узнайте больше об оптимизации карты сайта в официальной документации Next.js. Узнайте больше об оптимизации robots.txt в официальной документации Next.js.
    10. Изменение языка вашего контента

      Необязательно

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

      src/components/LocaleSwitcher.tsx
      "use client";
      
      import {
        Locales,
        getHTMLTextDir,
        getLocaleName,
        getLocalizedUrl,
      } from "intlayer";
      import { useLocale } from "next-intlayer";
      import { type FC } from "react";
      import Link from "next/link";
      
      const LocaleSwitcher: FC = () => {
        const { locale, pathWithoutLocale, availableLocales, setLocale } =
          useLocale();
      
        return (
          <div>
            <button popoverTarget="localePopover">{getLocaleName(locale)}</button>
            <div id="localePopover" popover="auto">
              {availableLocales.map((localeItem) => (
                <Link
                  href={getLocalizedUrl(pathWithoutLocale, localeItem)}
                  hrefLang={localeItem}
                  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>
                </Link>
              ))}
            </div>
          </div>
        );
      };

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

    11. Создание локализованного компонента ссылки

      Необязательно

      Чтобы обеспечить, что навигация вашего приложения учитывает текущую локаль, вы можете создать пользовательский компонент Link. Этот компонент автоматически добавляет префикс к внутренним URL-адресам с текущим языком. Например, когда пользователь, говорящий на французском, нажимает на ссылку на страницу "О нас", он перенаправляется на /fr/about вместо /about.

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

      • SEO и пользовательский опыт: Локализованные URL-адреса помогают поисковым системам правильно индексировать страницы на разных языках и предоставляют пользователям контент на их предпочтительном языке.
      • Согласованность: Используя локализованную ссылку по всему приложению, вы гарантируете, что навигация остается в текущей локали, предотвращая неожиданные переключения языка.
      • Удобство поддержки: Централизация логики локализации в одном компоненте упрощает управление URL-адресами, делая ваш код более удобным для поддержки и расширения по мере роста приложения.

      Ниже представлена реализация локализованного компонента Link на TypeScript:

      src/components/Link.tsx
      "use client";
      
      import { getLocalizedUrl } from "intlayer";
      import NextLink, { type LinkProps as NextLinkProps } from "next/link";
      import { useLocale } from "next-intlayer";
      import { forwardRef, PropsWithChildren, type ForwardedRef } from "react";
      
      /**
       * Утилита для проверки, является ли данный URL внешним.
       * Если URL начинается с http:// или https://, он считается внешним.
       */
      export const checkIsExternalLink = (href?: string): boolean =>
        /^https?:\/\//.test(href ?? "");
      
      /**
       * Пользовательский компонент Link, который адаптирует атрибут href в зависимости от текущей локали.
       * Для внутренних ссылок используется `getLocalizedUrl`, чтобы добавить префикс локали к URL (например, /fr/about).
       * Это гарантирует, что навигация остается в контексте текущей локали.
       */
      export const Link = forwardRef<
        HTMLAnchorElement,
        PropsWithChildren<NextLinkProps>
      >(({ href, children, ...props }, ref: ForwardedRef<HTMLAnchorElement>) => {
        const { locale } = useLocale();
        const isExternalLink = checkIsExternalLink(href.toString());
      
        // Если ссылка внутренняя и предоставлен корректный href, получить локализованный URL.
        const hrefI18n: NextLinkProps["href"] =
          href && !isExternalLink ? getLocalizedUrl(href.toString(), locale) : href;
      
        return (
          <NextLink href={hrefI18n} ref={ref} {...props}>
            {children}
          </NextLink>
        );
      });
      
      Link.displayName = "Link";

      Как это работает

      • Определение внешних ссылок:
        Вспомогательная функция checkIsExternalLink определяет, является ли URL внешним. Внешние ссылки остаются неизменными, так как они не требуют локализации.

      • Получение текущей локали:
        Хук useLocale предоставляет текущую локаль (например, fr для французского).

      • Локализация URL:
        Для внутренних ссылок (т.е. не внешних) используется getLocalizedUrl, чтобы автоматически добавить префикс локали к URL. Это означает, что если ваш пользователь находится на французском языке, передача /about в качестве href преобразуется в /fr/about.

      • Возврат ссылки:
        Компонент возвращает элемент <a> с локализованным URL, обеспечивая согласованную навигацию в рамках локали.

      Интегрируя этот компонент Link в ваше приложение, вы поддерживаете согласованный и языково-осведомленный пользовательский опыт, а также улучшаете SEO и удобство использования.

    12. Оптимизация размера вашего бандла

      Необязательно

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

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

      bash
      npm install @intlayer/swc --save-dev
      Примечание: Эта оптимизация доступна только в Next.js 13 и выше.

      Примечание: Этот пакет не устанавливается по умолчанию, потому что плагин SWC еще находится на этапе экспериментального использования в Next.js. Это может измениться в будущем.

    Настройка TypeScript

    Intlayer использует расширение модулей для получения преимуществ TypeScript и усиления вашего кода.

    Autocompletion

    Translation error

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

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

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

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

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

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

    Дальнейшие шаги