Автор:
    Создание:2024-03-07Последнее обновление:2026-09-27

    Переведите ваш сайт Astro с помощью Intlayer

    ide.intlayer.org
    intlayer-astro-template.vercel.app

    Содержание

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

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

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

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

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

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

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

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

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

    Пошаговое руководство по настройке Intlayer в Astro

    Посмотреть Шаблон приложения на GitHub.

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

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

      bash
      npx intlayer init --interactive
      
      флаг --interactive необязателен. Используйте intlayer-cli init, если вы AI-агент.
      Эта команда обнаружит вашу среду и установит необходимые пакеты. Например:
      bash
      npm install intlayer astro-intlayer
      
      • intlayer Основной пакет, предоставляющий инструменты интернационализации для управления конфигурацией, переводами, объявлением контента, транспиляцией и командами CLI.

      • astro-intlayer Включает плагин интеграции Astro для интеграции Intlayer с бандлером Vite, middleware, разрешающее локаль каждого запроса в Astro.locals.intlayer, и хуки useIntlayer / useDictionary / useLocale. Тот же путь импорта разрешается в серверную реализацию во фронтматтере .astro и в клиентскую (на базе vanilla-intlayer) в блоках <script>.

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

      Архитектура

      В этой архитектуре интеграция intlayer(), зарегистрированная в astro.config.ts, собирает ваши словари и добавляет middleware, который определяет локаль каждого запроса и предоставляет её в Astro.locals.intlayer. Страницы располагаются в сегменте rest src/pages/[...locale]/, благодаря чему локаль по умолчанию отдается без префикса, а каждая другая локаль получает собственный выделенный URL. Файлы .astro читают контент с помощью хуков useIntlayer / useLocale из astro-intlayer, а объявления контента размещаются рядом с вашими компонентами в src/.

      bash
      .
      ├── src
      │   ├── app.content.tsx               # App content declaration
      │   ├── components
      │   │   └── LocaleSwitcher.astro      # Locale switcher component
      │   └── pages
      │       ├── [...locale]
      │       │   └── index.astro           # Localized page (rest param also serves the default locale)
      │       ├── robots.txt.ts             # robots.txt endpoint
      │       └── sitemap.xml.ts            # Localized sitemap endpoint
      ├── astro.config.ts                   # Astro config with the intlayer() integration
      ├── intlayer.config.ts
      ├── package.json
      └── tsconfig.json
      

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

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

      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, названия куки, расположение и расширение ваших объявлений контента, отключить логи Intlayer в консоли и многое другое. Полный список доступных параметров см. в документации по конфигурации.
    3. Интеграция Intlayer в конфигурацию Astro

      Добавьте плагин intlayer в вашу конфигурацию.

      astro.config.ts
      // @ts-check
      
      import { intlayer } from "astro-intlayer";
      import { defineConfig } from "astro/config";
      
      // https://astro.build/config
      export default defineConfig({
        integrations: [intlayer()],
      });
      
      Плагин интеграции intlayer() используется для интеграции Intlayer с Astro. Он обеспечивает сборку файлов объявления контента и отслеживает их изменения в режиме разработки. Он определяет переменные окружения Intlayer внутри приложения Astro. Кроме того, он предоставляет псевдонимы (aliases) для оптимизации производительности.
    4. Объявление контента

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

      src/app.content.tsx
      import { t, type Dictionary } from "intlayer";
      import type { ReactNode } from "react";
      
      const appContent = {
        key: "app",
        content: {
          title: t({
            en: "Hello World",
            fr: "Bonjour le monde",
            es: "Hola mundo",
            ru: "Привет, мир",
          }),
        },
      } satisfies Dictionary;
      
      export default appContent;
      
      Ваши объявления контента могут быть определены в любом месте вашего приложения, если они включены в каталог contentDir (по умолчанию ./src) и соответствуют расширению файла объявления контента (по умолчанию .content.{json,ts,tsx,js,jsx,mjs,cjs,md,mdx,yaml,yml}).
      Более подробную информацию см. в документации по объявлению контента.
    5. Использование контента в Astro

      Используйте ваши словари в файлах .astro с помощью хуков, экспортируемых astro-intlayer. Они имеют те же сигнатуры, что и react-intlayer: useIntlayer("key") возвращает содержимое словаря, а useLocale() текущую локаль, без необходимости передавать аргументы.

      Локаль поступает из middleware astro-intlayer, которое интеграция регистрирует автоматически перед вашим собственным src/middleware.ts. Оно разрешает ее для каждого запроса, на основе префикса URL, затем сохраненной клиентом локали (cookie или заголовок), затем Accept-Language, и сохраняет в Astro.locals.intlayer. Предварительно отрендеренные страницы используют только URL, так как рендерятся один раз для каждого посетителя.

      Вам также следует добавить SEO-метаданные, такие как hreflang и канонические ссылки, на каждую страницу и включить переключатель языков, чтобы пользователи могли менять язык.

      src/pages/index.astro
      ---
      import { useIntlayer, useLocale } from "astro-intlayer";
      import {
        getLocalizedUrl,
        defaultLocale,
        localeMap,
        getHTMLTextDir,
      } from "intlayer";
      import LocaleSwitcher from "../components/LocaleSwitcher.astro";
      
      // Локаль, разрешенная middleware (напр. /ru/about -> 'ru')
      const { locale } = useLocale();
      
      // Содержимое словаря 'app' для этой локали
      const { title } = useIntlayer("app");
      ---
      
      <!doctype html>
      <html lang={locale} dir={getHTMLTextDir(locale)}>
        <head>
          <meta charset="utf-8" />
          <meta name="viewport" content="width=device-width" />
          <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
          <title>{title}</title>
      
          <!-- Canonical link: Tells search engines which is the primary version of this page -->
          <link
            rel="canonical"
            href={new URL(getLocalizedUrl(Astro.url.pathname, locale), Astro.site)}
          />
      
          <!-- Hreflang: Tell Google about all localized versions -->
          {
            localeMap(({ locale: mapLocale }) => (
              <link
                rel="alternate"
                hreflang={mapLocale}
                href={new URL(
                  getLocalizedUrl(Astro.url.pathname, mapLocale),
                  Astro.site
                )}
              />
            ))
          }
      
          <!-- x-default: Fallback for users in unmatched languages -->
          <link
            rel="alternate"
            hreflang="x-default"
            href={new URL(
              getLocalizedUrl(Astro.url.pathname, defaultLocale),
              Astro.site
            )}
          />
        </head>
        <body>
          <header>
            <LocaleSwitcher />
          </header>
          <main>
            <h1>{title}</h1>
          </main>
        </body>
      </html>
      
      Astro.locals.intlayer также предоставляет доступ к locale, defaultLocale и availableLocales в ваших собственных middleware и эндпоинтах. Передайте локаль или селектор вторым аргументом (useIntlayer("app", "fr"), useIntlayer("faq", { item: 2 })), чтобы переопределить локаль запроса для одного вызова.
    6. Локализованная маршрутизация

      Создайте динамический сегмент маршрута для обслуживания локализованных страниц, например src/pages/[locale]/index.astro:

      src/pages/[locale]/index.astro
      <!-- astro -->
      ---
      import { getIntlayer } from "intlayer";
      
      const { title } = getIntlayer('app');
      ---
      
      <h1>{title}</h1>
      

      Интеграция Astro добавляет middleware Vite во время разработки, которое помогает с маршрутизацией, учитывающей язык, и определениями окружения. Вы по-прежнему можете создавать ссылки между языками, используя собственную логику или вспомогательные функции, такие как getLocalizedUrl из intlayer.

    7. Добавление переключателя языков

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

      src/components/LocaleSwitcher.astro
      ---
      import { useLocale } from "astro-intlayer";
      import { getLocaleName, getLocalizedUrl, getPathWithoutLocale } from "intlayer";
      
      const { locale, availableLocales } = useLocale();
      const pathWithoutLocale = getPathWithoutLocale(Astro.url.pathname);
      ---
      
      <nav aria-label="Languages">
        <ul>
          {
            availableLocales.map((localeItem) => (
              <li key={localeItem} class="p-1">
                <a
                  href={getLocalizedUrl(pathWithoutLocale, localeItem)}
                  data-locale={localeItem}
                  aria-current={localeItem === locale ? "page" : undefined}
                >
                  {getLocaleName(localeItem)}
                </a>
              </li>
            ))
          }
        </ul>
      </nav>
      
      <script>
        // В браузере тот же импорт разрешается в клиентскую реализацию
        import { useLocale } from "astro-intlayer";
        import { getLocalizedUrl, type LocalesValues } from "intlayer";
      
        // Сохраняет выбор в cookie локали, затем переходит на локализованный URL
        const { setLocale } = useLocale({
          onLocaleChange: (newLocale) => {
            window.location.href = getLocalizedUrl(window.location.pathname, newLocale);
          },
        });
      
        const localeLinks = document.querySelectorAll("[data-locale]");
      
        localeLinks.forEach((link) => {
          link.addEventListener("click", (event) => {
            const locale = link.getAttribute("data-locale") as LocalesValues;
      
            event.preventDefault();
            setLocale(locale);
          });
        });
      </script>
      
      <style>
        nav {
          display: flex;
          gap: 1rem;
        }
        ul {
          display: flex;
          list-style: none;
          padding: 0;
          margin: 0;
          gap: 0.5rem;
        }
        a[aria-current="page"] {
          font-weight: bold;
          text-decoration: underline;
        }
      </style>
      

      Примечание о сохранении состояния: setLocale из клиентского useLocale сохраняет языковые предпочтения пользователя в cookie. Это позволяет Intlayer запоминать выбор и автоматически перенаправлять пользователя на предпочитаемый язык при будущих посещениях: страницы, рендерируемые по требованию (адаптер с output: 'server' или prerender = false), перенаправляются middleware Intlayer до отправки какого-либо HTML, в то время как предварительно отрендеренные страницы, предоставляемые как статические файлы, перенаправляются небольшим скриптом, который интеграция внедряет на каждую страницу. Установите routing.enableProxy в false, чтобы отключить оба варианта. В astro dev cookie игнорируется как источник перенаправления, если только routing.enableProxy не установлен в true, поэтому устаревший cookie не сможет перехватить страницы, над которыми вы работаете.

      Взаимосовместимость сервера и клиента: astro-intlayer разрешается в серверные хуки во фронтматтере (считывая Astro.locals) и в клиентские хуки vanilla-intlayer в блоках <script> и островах (islands), с теми же именами и структурой данных. setLocale и onChange действуют только на клиенте, вызовите installIntlayer() один раз для инициализации клиентского хранилища. astro-intlayer/client экспортирует клиентскую точку входа явно.

    8. Sitemap и Robots.txt

      Intlayer предоставляет утилиты для динамического создания локализованных карт сайта и файлов robots.txt.

      Sitemap

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

      Создаваемая Intlayer карта сайта поддерживает пространство имен xhtml:link (Hreflang XML Extensions). В отличие от стандартных генераторов карт сайта, которые просто перечисляют прямые URL-адреса, Intlayer автоматически создает необходимые двусторонние связи между всеми языковыми версиями страницы (например, /about, /about?lang=fr и /about?lang=es). Это гарантирует, что поисковые системы будут правильно индексировать и показывать нужную языковую версию соответствующей аудитории.

      Создайте src/pages/sitemap.xml.ts для генерации карты сайта, включающей все ваши локализованные маршруты.

      src/pages/sitemap.xml.ts
      import type { APIRoute } from "astro";
      import { generateSitemap, type SitemapUrlEntry } from "intlayer";
      
      const pathList: SitemapUrlEntry[] = [
        { path: "/", changefreq: "daily", priority: 1.0 },
        { path: "/about", changefreq: "monthly", priority: 0.7 },
      ];
      
      export const GET: APIRoute = async ({ site }) => {
        const xmlOutput = generateSitemap(pathList, {
          siteUrl: "https://example.com",
        });
      
        return new Response(xmlOutput, {
          headers: { "Content-Type": "application/xml" },
        });
      };
      

      Robots.txt

      Создайте src/pages/robots.txt.ts для управления сканированием поисковыми системами.

      src/pages/robots.txt.ts
      import type { APIRoute } from "astro";
      import { getMultilingualUrls } from "intlayer";
      
      const getAllMultilingualUrls = (urls: string[]) =>
        urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);
      
      const disallowedPaths = getAllMultilingualUrls(["/admin", "/private"]);
      
      export const GET: APIRoute = ({ site }) => {
        const robotsTxt = [
          "User-agent: *",
          "Allow: /",
          ...disallowedPaths.map((path) => `Disallow: ${path}`),
          "",
          `Sitemap: ${new URL("/sitemap.xml", site).href}`,
        ].join("\n");
      
        return new Response(robotsTxt, {
          headers: { "Content-Type": "text/plain" },
        });
      };
      
    9. Продолжайте использовать ваш любимый фреймворк

      Продолжайте использовать ваш любимый фреймворк для создания вашего приложения.

    10. Извлечение содержимого ваших компонентов

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

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

      Чтобы упростить этот процесс, Intlayer предлагает компилятор / экстрактор для преобразования ваших компонентов и извлечения содержимого.

      Чтобы настроить его, вы можете добавить раздел compiler в ваш файл intlayer.config.ts:

      intlayer.config.ts
      import { type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        // ... Остальная часть вашей конфигурации
        compiler: {
          /**
           * Указывает, должен ли быть включен компилятор.
           */
          enabled: true,
      
          /**
           * Определяет путь к выходным файлам
           */
          output: ({ fileName, extension }) => `./${fileName}${extension}`,
      
          /**
           * Указывает, должны ли компоненты сохраняться после преобразования. Таким образом, компилятор можно запустить только один раз для преобразования приложения, а затем удалить.
           */
          saveComponents: false,
      
          /**
           * Префикс ключа словаря
           */
          dictionaryKeyPrefix: "",
        },
      };
      
      export default config;
      

      Запустите экстрактор для преобразования компонентов и извлечения содержимого

      bash
      npx intlayer extract
      

      Соберите приложение, чтобы преобразовать ваши компоненты и извлечь контент

      bash
      npm run build # Или npm run dev
      

    Настройка TypeScript

    Intlayer использует расширение модулей (module augmentation), чтобы воспользоваться преимуществами TypeScript и сделать вашу кодовую базу более надежной.

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

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

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

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

    Настройка Git

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

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

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

    Расширение для VS Code

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

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

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

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

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

    Вы также можете внедрить визуальный редактор или вынести ваш контент во внешнюю CMS.

    Часто задаваемые вопросы

    Astro поставляется с опцией i18n на уровне маршрутизации, которая обрабатывает префиксы локалей и редиректы, но не управляет самим контентом, поэтому вам всё ещё нужен слой сообщений:

    • Встроенная i18n Astro плюс написанные вручную словари JSON или TypeScript: без зависимостей, но без типизации, без правил множественного числа и без инструментов.
    • i18next или vue-i18n / svelte-i18n внутри островов: полноценная библиотека для каждого островного фреймворка, у каждой свой каталог.
    • Intlayer: один слой контента, общий для страниц Astro и всех островных фреймворков, скомпилированный во время сборки, полностью типизированный, с ИИ-переводом, визуальным редактором и CMS.

    Специфичный для Astro выигрыш в том, что один и тот же словарь обслуживает страницу .astro и остров React, Vue, Svelte, Solid, Preact или Lit, вместо одной библиотеки i18n на каждую островную среду выполнения. См. почему Intlayer.

    Гораздо меньше, чем при подходе на основе пространств имён, потому что страница никогда не загружает каталог, который не отображает. Страницы Astro рендерятся во время сборки, поэтому они поставляют переведённый HTML и вообще никакого словаря; словарь получают только острова. Компилятор во время сборки разрешает вызовы контента в точные записи, которые использует компонент, а динамические словари разделяют остальное по локалям. По сравнению с обычными альтернативами Intlayer сокращает размер бандла и страницы до 50%. См. оптимизацию бандла и бенчмарк.

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

    Да. Плагин синхронизации JSON сохраняет ваши файлы /messages/{locale}/{namespace}.json как источник истины и генерирует из них словари Intlayer, в обоих направлениях. Плагин синхронизации PO делает то же самое для каталогов gettext, а файлы по локали позволяют разделить контент по языкам вместо группировки локалей в одном файле.

    Нет. Запустите npx intlayer extract, и Intlayer прочитает ваши компоненты, извлечёт строки, видимые пользователю, и запишет файл .content рядом с каждым из них, так что вы просматриваете diff вместо копирования строк в каталог по одной. Шаг 15 этого руководства проводит вас через это.

    Для полностью автоматизированного конвейера Компилятор Intlayer делает то же самое во время сборки: он сканирует исходный код JSX, TSX, Vue и Svelte при каждом изменении, генерирует словари и поддерживает их синхронизацию через горячую замену модулей, поэтому вручную поддерживать ключи вообще не нужно.

    Стоит знать о двух ограничениях, прежде чем включать компилятор. Он работает через статический анализ, поэтому строки, существующие только во время выполнения, такие как коды ошибок API или поля CMS, остаются недоступными. И ему нужно отличать текст, видимый пользователю, от логики приложения вроде className="active" или кода статуса, что требует нескольких аннотаций в большой кодовой базе. Команда extract избегает обоих ограничений, оставляя вас в процессе.

    Пять компонентов, все опциональные:

    • Расширение для VS Code: переход от ключа useIntlayer к файлу контента, который его объявляет, извлечение контента из компонента и запуск build, fill, test, push и pull из палитры команд или отдельной вкладки Intlayer.
    • LSP-сервер: та же осведомлённость в любом редакторе, который говорит на LSP, с переходом к определению, поиском всех ссылок, предпросмотром переведённого значения при наведении, автодополнением ключей и полей и предупреждением, когда ключ нигде не объявлен. Он также разрешает вызовы i18next, react-i18next, next-intl и use-intl, что помогает при миграции.
    • MCP-сервер: предоставляет документацию и CLI Intlayer для Cursor, VS Code, Claude Desktop, Claude Code и ChatGPT, чтобы ассистент отвечал по актуальной документации, а не гадал, и мог сам запускать команды вроде intlayer fill.
    • Навыки агентов: сфокусированные навыки, такие как intlayer-config, intlayer-cli и intlayer-content, плюс по одному на фреймворк, которые обучают агента вашей настройке маршрутизации и типам узлов контента.
    • Плагин ESLint: no-raw-text помечает жёстко закодированные строки, с дополнительными правилами для статических ключей словаря и неиспользуемого контента.