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

    Перекладіть свій вебсайт на Next.js із Page Router за допомогою Intlayer | Інтернаціоналізація (i18n)

    ide.intlayer.org

    Зміст

    Чому варто обрати Intlayer, а не альтернативи?

    Порівняно з основними рішеннями, такими як next-intl або i18next, Intlayer — це рішення, яке має такі інтегровані оптимізації, як:

    Intlayer оптимізовано для роботи з компонентами сервера для ефективного відтворення та повністю сумісно з Turbopack. Він не блокує статичний рендеринг і пропонує проміжне програмне забезпечення, а також усі функції, необхідні для інтернаціоналізації масштабування (i18n).

    Intlayer сумісний із Next.js 12, 13, 14, 15 і 16. Якщо ви використовуєте маршрутизатор сторінок Next.js, ви можете переглянути цей посібник. Локальна маршрутизація корисна для SEO, розміру пакета та продуктивності. Якщо він вам не потрібен, ви можете звернутися до цього посібника. Щодо Next.js 12, 13, 14 і 15 із маршрутизатором програм див. цей посібник.

    Замість того, щоб завантажувати великі файли JSON на свої сторінки, завантажуйте лише необхідний вміст. Intlayer допомагає зменшити розмір бандлу і сторінок до 50%.

    Організація вмісту за окремими областями (scoping) полегшує технічне обслуговування великомасштабних програм. Ви можете скопіювати або видалити окрему папку функцій без розумового навантаження перегляду всієї кодової бази вмісту. Крім того, Intlayer повністю типізований (fully typed), щоб забезпечити точність вашого вмісту.

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

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

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

    Більше ніж просто рішення i18n, Intlayer пропонує власний візуальний редактор і повний CMS, щоб допомогти вам керувати своїм багатомовним вмістом у реальному часі, спрощуючи співпрацю з перекладачами, копірайтерами та іншими членами команди. Контент можна зберігати локально та/або віддалено.


    Покроковий посібник щодо налаштування Intlayer у застосунку Next.js із Page Router

    1. Встановіть залежності

      Встановіть необхідні пакунки, використовуючи обраний менеджер пакетів:

      bash
      npm install intlayer next-intlayernpx intlayer init
      • intlayer

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

      • next-intlayer

      Пакет, що інтегрує Intlayer з Next.js. Забезпечує провайдери контексту та хуки для інтернаціоналізації у Next.js. Додатково містить плагін для Next.js для інтеграції Intlayer з Webpack або Turbopack, а також middleware для визначення переважної локалі користувача, керування cookie та обробки перенаправлення URL.

    2. Налаштуйте свій проєкт

      Створіть файл конфігурації, щоб визначити мови, які підтримує ваш застосунок:

      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, імена cookie, розташування та розширення файлів декларацій вмісту, вимкнути логи Intlayer у консолі тощо. Для повного переліку доступних параметрів зверніться до документації з конфігурації.
    3. Інтеграція Intlayer з конфігурацією Next.js

      Змініть конфігурацію Next.js, щоб інтегрувати Intlayer:

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

      Функція withIntlayer() повертає проміс. Якщо ви хочете використовувати її разом з іншими плагінами, ви можете дочекатися її виконання за допомогою await. Приклад:

      tsx
      const nextConfig = await withIntlayer(nextConfig);const nextConfigWithOtherPlugins = withOtherPlugins(nextConfig);export default nextConfigWithOtherPlugins;
    4. Налаштуйте middleware для визначення локалі

      Налаштуйте middleware для автоматичного визначення та обробки бажаної користувачем локалі:

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

      Реалізуйте динамічну маршрутизацію для подачі локалізованого контенту залежно від локалі користувача.

      1. Створіть сторінки для конкретної локалі:

        Перейменуйте головний файл сторінки, щоб додати динамічний сегмент [locale].

        bash
        mv src/pages/index.tsx src/pages/[locale]/index.tsx
      2. Оновіть _app.tsx, щоб обробляти локалізацію:

        Змініть свій _app.tsx, щоб включити провайдери Intlayer.

        src/pages/_app.tsx
        import type { FC } from "react";import type { AppProps } from "next/app";import { IntlayerClientProvider } from "next-intlayer";const App = FC<AppProps>({ Component, pageProps }) => {  const { locale } = pageProps;  return (    <IntlayerClientProvider locale={locale}>      <Component {...pageProps} />    </IntlayerClientProvider>  );}export default MyApp;
      3. Налаштуйте getStaticPaths та getStaticProps:

        У файлі [locale]/index.tsx визначте paths і props для обробки різних локалей.

        src/pages/[locale]/index.tsx
        import type { FC } from "react";import type { GetStaticPaths, GetStaticProps } from "next";import { type Locales, getConfiguration } from "intlayer";const HomePage: FC = () => <div>{/* Ваш контент тут */}</div>;export const getStaticPaths: GetStaticPaths = () => {  const { internationalization } = getConfiguration();  const { locales } = internationalization;  const paths = locales.map((locale) => ({    params: { locale },  }));  return { paths, fallback: false };};export const getStaticProps: GetStaticProps = ({ params }) => {  const locale = params?.locale as string;  return {    props: {      locale,    },  };};export default HomePage;
      getStaticPaths та getStaticProps гарантують, що ваш застосунок попередньо збудує необхідні сторінки для всіх локалей у Next.js Page Router. Такий підхід зменшує обчислення під час виконання і покращує взаємодію з користувачем. Для детальнішої інформації зверніться до документації Next.js щодо getStaticPaths та getStaticProps.
    6. Оголосіть свій контент

      Створіть та керуйте деклараціями контенту для зберігання перекладів.

      src/pages/[locale]/home.content.ts
      import { t, type Dictionary } from "intlayer";
      
      const homeContent = {
        key: "home",
        content: {
          title: t({
            uk: "Ласкаво просимо на мій вебсайт",
            en: "Welcome to My Website",
            fr: "Bienvenue sur mon site Web",
            es: "Bienvenido a mi sitio web",
          }),
          description: t({
            uk: "Почніть, редагуючи цю сторінку.",
            en: "Get started by editing this page.",
            fr: "Commencez par éditer cette page.",
            es: "Comience por editar esta página.",
          }),
        },
      } satisfies Dictionary;
      
      export default homeContent;

      Для отримання додаткової інформації про оголошення контенту зверніться до керівництва з оголошення контенту.

    7. Використання контенту у вашому коді

      Отримуйте доступ до словників контенту у всьому застосунку, щоб відображати перекладений вміст.

      src/pages/[locale]/index.tsx
      import type { FC } from "react";
      import { useIntlayer } from "next-intlayer";
      import { ComponentExample } from "@components/ComponentExample";
      
      const HomePage: FC = () => {
        const content = useIntlayer("home");
      
        return (
          <div>
            <h1>{content.title}</h1>
            <p>{content.description}</p>
            <ComponentExample />
            {/* Додаткові компоненти */}
          </div>
        );
      };
      
      // ... Решта коду, включаючи getStaticPaths та getStaticProps
      
      export default HomePage;
      src/components/ComponentExample.tsx
      import type { FC } from "react";
      import { useIntlayer } from "next-intlayer";
      
      export const ComponentExample: FC = () => {
        const content = useIntlayer("component-example"); // Переконайтесь, що у вас є відповідна декларація вмісту
      
        return (
          <div>
            <h2>{content.title}</h2>
            <p>{content.content}</p>
          </div>
        );
      };
      Коли ви використовуєте переклади в рядкових атрибутах (наприклад, 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. Інтернаціоналізація ваших метаданих

      Необов'язково

      Якщо ви хочете інтернаціоналізувати метадані, наприклад заголовок вашої сторінки, ви можете використовувати функцію getStaticProps, яку надає Next.js Page Router. Всередині ви можете отримати контент за допомогою функції getIntlayer, щоб перекласти ваші метадані.

      src/pages/[locale]/metadata.content.ts
      import { type Dictionary, t } from "intlayer";
      import { type Metadata } from "next";
      
      const metadataContent = {
        key: "page-metadata",
        content: {
          title: t({
            uk: "Створити додаток Next.js",
            en: "Create Next App",
            uk: "Створити додаток Next.js",
            fr: "Créer une application Next.js",
            es: "Crear una aplicación Next.js",
          }),
          description: t({
            uk: "Згенеровано за допомогою create next app",
            en: "Generated by create next app",
            fr: "Généré par create next app",
            es: "Generado por create next app",
          }),
        },
      } satisfies Dictionary<Metadata>;
      
      export default metadataContent;
      src/pages/[locale]/index.tsx
      import { GetStaticPaths, GetStaticProps } from "next";
      import { getIntlayer, getMultilingualUrls } from "intlayer";
      import { useIntlayer } from "next-intlayer";
      `
      import Head from "next/head";
      import type { FC } from "react";
      
      interface HomePageProps {
        locale: string;
        metadata: {
          title: string;
          description: string;
        };
        multilingualUrls: Record<string, string>;
      }
      
      const HomePage: FC<HomePageProps> = ({
        metadata,
        multilingualUrls,
        locale,
      }) => {
        const content = useIntlayer("page");
      
        return (
          <div>
            <Head>
              <title>{metadata.title}</title>
              <meta name="description" content={metadata.description} />
              {/* Генерує теги hreflang для SEO */}
              {Object.entries(multilingualUrls).map(([lang, url]) => (
                <link key={lang} rel="alternate" hrefLang={lang} href={url} />
              ))}
              <link rel="canonical" href={multilingualUrls[locale]} />
            </Head>
      
            {/* Вміст сторінки */}
            <main>{/* Ваш вміст сторінки тут */}</main>
          </div>
        );
      };
      
      export const getStaticProps: GetStaticProps<HomePageProps> = async ({
        params,
      }) => {
        const locale = params?.locale as string;
      
        const metadata = getIntlayer("page-metadata", locale);
      
        /**
         * Генерує об'єкт, що містить усі URL для кожної локалі.
         *
         * Приклад:
         * ```ts
         *  getMultilingualUrls('/about');
         *
         *  // Повертає
         *  // {
         *  //   en: '/about',
         *  //   fr: '/fr/about',
         *  //   es: '/es/about',
         *  // }
         * ```
         */
        const multilingualUrls = getMultilingualUrls("/");
      
        return {
          props: {
            locale,
            metadata,
            multilingualUrls,
          },
        };
      };
      
      export default HomePage;
      
      // ... Решта коду, включаючи getStaticPaths
      Зверніть увагу, що функція getIntlayer, імпортована з next-intlayer, повертає ваш контент, обгорнутий у IntlayerNode, що дозволяє інтеграцію з візуальним редактором. Натомість функція getIntlayer, імпортована з intlayer, повертає контент напряму без додаткових властивостей.

      Альтернативно, ви можете використовувати функцію getTranslation для декларації ваших метаданих. Проте рекомендовано використовувати файли декларації контенту, щоб автоматизувати переклад метаданих та винести контент у зовнішні файли.

      src/pages/[locale]/index.tsx
      import { GetStaticPaths, GetStaticProps } from "next";
      import {
        type IConfigLocales,
        getTranslation,
        getMultilingualUrls,
      } from "intlayer";
      import { useIntlayer } from "next-intlayer";
      import Head from "next/head";
      import type { FC } from "react";
      
      interface HomePageProps {
        locale: string;
        metadata: {
          title: string;
          description: string;
        };
        multilingualUrls: Record<string, string>;
      }
      
      const HomePage: FC<HomePageProps> = ({ metadata, multilingualUrls, locale }) => {
        const content = useIntlayer("page");
      
        return (
          <div>
            <Head>
              <title>{metadata.title}</title>
              <meta name="description" content={metadata.description} />
              {/* Згенерувати теги hreflang для SEO */}
              {Object.entries(multilingualUrls).map(([lang, url]) => (
                <link
                  key={lang}
                  rel="alternate"
                  hrefLang={lang}
                  href={url}
                />
              ))}
              <link rel="canonical" href={multilingualUrls[locale]} />
            </Head>
      
            {/* Вміст сторінки */}
            <main>
              {/* Ваш вміст сторінки тут */}
            </main>
          </div>
        );
      };
      
      export const getStaticProps: GetStaticProps<HomePageProps> = async ({
        params
      }) => {
        const locale = params?.locale as string;
        const t = <T>(content: IConfigLocales<T>) => getTranslation(content, locale);
      
        const metadata = {
          title: t<string>({
            uk: "Мій заголовок",
            en: "My title",
            fr: "Mon titre",
            es: "Mi título",
          }),
          description: t({
            uk: "Мій опис",
            en: "My description",
            fr: "Ma description",
            es: "Mi descripción",
          }),
        };
      
        const multilingualUrls = getMultilingualUrls("/");
      
        return {
          props: {
            locale,
            metadata,
            multilingualUrls,
          },
        };
      };
      
      export default HomePage;
      
      // ... Rest of the code including getStaticPaths
      Дізнайтеся більше про оптимізацію метаданих в офіційній документації Next.js.
    9. Змініть мову вашого вмісту

      Необов'язково

      Щоб змінити мову вашого вмісту в Next.js, рекомендовано використовувати компонент Link для перенаправлення користувачів на відповідну локалізовану сторінку. Компонент Link дає змогу передзавантажувати (prefetch) сторінку, що допомагає уникнути повного перезавантаження сторінки.

      src/components/LanguageSwitcher.tsx
      import {
        Locales,
        getHTMLTextDir,
        getLocaleName,
        getLocalizedUrl,
      } from "intlayer";
      import { useLocalePageRouter } from "next-intlayer";
      import { type FC } from "react";
      import Link from "next/link";
      
      const LocaleSwitcher: FC = () => {
        const { locale, pathWithoutLocale, availableLocales } = useLocalePageRouter();
      
        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>
        );
      };
      Альтернативний спосіб, використати функцію setLocale, яку надає хук useLocale. Ця функція не дозволяє попереднє завантаження (prefetch) сторінки і призведе до перезавантаження сторінки.
      У такому випадку, без перенаправлення через router.push, змінить локаль вмісту лише ваш серверний код.
      src/components/LocaleSwitcher.tsx
      "use client";import { useRouter } from "next/navigation";import { useLocale } from "next-intlayer";import { getLocalizedUrl } from "intlayer";// ... Решта кодуconst router = useRouter();const { setLocale } = useLocale({  onLocaleChange: (locale) => {    router.push(getLocalizedUrl(pathWithoutLocale, locale));  },});return (  <button onClick={() => setLocale(Locales.FRENCH)}>Change to French</button>);
      API useLocalePageRouter такий же, як useLocale. Щоб дізнатися більше про хук useLocale, зверніться до документації.

      Посилання на документацію:

    10. Необов'язково

      Щоб гарантувати, що навігація вашого застосунку враховує поточну локаль, ви можете створити кастомний компонент Link. Цей компонент автоматично додає префікс поточної мови до внутрішніх URL-адрес, так щоб, наприклад, коли франкомовний користувач натискає на посилання на сторінку "About", він буде перенаправлений на /fr/about замість /about.

      Ця поведінка корисна з кількох причин:

      • SEO та досвід користувача: локалізовані URL-адреси допомагають пошуковим системам правильно індексувати сторінки для конкретних мов і надають користувачам контент їхньою переважною мовою.
      • Послідовність: Використовуючи локалізоване посилання в усьому вашому застосунку, ви гарантуєте, що навігація залишатиметься в межах поточної локалі, запобігаючи несподіваним змінам мови.
      • Підтримуваність: Централізація логіки локалізації в одному компоненті спрощує управління URL-адресами, роблячи вашу codebase простішою для підтримки та розширення у міру зростання застосунку.

      Нижче наведено реалізацію локалізованого компонента 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 та зручності використання.

    11. Оптимізуйте розмір bundle

      Необов'язково

      Коли використовується next-intlayer, словники за замовчуванням включаються в бандл для кожної сторінки. Щоб оптимізувати розмір бандла, Intlayer надає опційний SWC-плагін, який розумно замінює виклики useIntlayer за допомогою макросів. Це гарантує, що словники включаються в бандли лише для сторінок, які дійсно їх використовують.

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

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

      Примітка: Цей пакет не встановлюється за замовчуванням, оскільки SWC-плагіни все ще є експериментальними в Next.js. Це може змінитися в майбутньому.

    Налаштування TypeScript

    Intlayer використовує module augmentation, щоб отримати переваги TypeScript і зробити вашу codebase більш надійною.

    Автозаповнення

    Помилка перекладу

    Переконайтеся, що у вашій конфігурації TypeScript включені автогенеровані типи.

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

    Налаштування Git

    Щоб зберегти репозиторій чистим і уникнути коміту згенерованих файлів, рекомендується ігнорувати файли, створені Intlayer.

    Додайте наступні рядки до вашого файлу .gitignore:

    .gitignore
    # Ігнорувати файли, згенеровані Intlayer.intlayer

    Розширення для VS Code

    Щоб покращити ваш досвід розробки з Intlayer, ви можете встановити офіційне Intlayer VS Code Extension.

    Встановити з VS Code Marketplace

    Це розширення надає:

    • Автодоповнення для ключів перекладу.
    • Виявлення помилок у реальному часі для відсутніх перекладів.
    • Вбудовані попередні перегляди перекладеного вмісту.
    • Швидкі дії для легкого створення та оновлення перекладів.

    Для детальнішої інформації про використання розширення див. Документація розширення Intlayer для VS Code.

    Додаткові ресурси

    Дотримуючись цього посібника, ви можете ефективно інтегрувати Intlayer у ваш Next.js застосунок, що використовує Page Router, забезпечивши надійну та масштабовану підтримку інтернаціоналізації для ваших веб‑проєктів.

    Далі

    Щоб піти далі, ви можете реалізувати візуальний редактор або винести свій контент за допомогою CMS.