Creation:2026-03-23Last update:2026-05-06

    Переведите ваш веб-сайт на Vite и Lit с помощью Intlayer | Интернационализация (i18n)

    ide.intlayer.org

    Содержание

    Что такое Intlayer?

    Intlayer - это инновационная библиотека интернационализации (i18n) с открытым исходным кодом, разработанная для упрощения многоязычной поддержки в современных веб-приложениях.

    С помощью Intlayer вы можете:

    • Легко управлять переводами, используя декларативные словари на уровне компонентов.
    • Динамически локализовать метаданные, маршруты и контент.
    • Обеспечить поддержку TypeScript с помощью автогенерируемых типов, что улучшает автодополнение и обнаружение ошибок.
    • Пользоваться расширенными функциями, такими как динамическое определение и переключение языка.

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

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

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

    bash
    npm install intlayer lit-intlayernpm install vite-intlayer --save-devnpx intlayer init
    • intlayer

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

    • lit-intlayer Пакет, интегрирующий Intlayer с приложениями на Lit. Он предоставляет хуки на основе ReactiveController (useIntlayer, useLocale и т. д.), чтобы LitElement автоматически перерисовывались при смене языка.

    • vite-intlayer Включает плагин Vite для интеграции Intlayer с бандлером Vite, а также промежуточное ПО (middleware) для определения предпочтительного языка пользователя, управления куки и обработки перенаправления 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, имена куки, местоположение и расширение ваших деклараций контента, отключить логи Intlayer в консоли и многое другое. Полный список доступных параметров см. в документации по конфигурации.

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

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

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

    Шаг 4: Инициализация Intlayer в вашей точке входа

    Вызовите installIntlayer() перед регистрацией любых кастомных элементов, чтобы глобальный синглтон локали был готов к моменту подключения первого элемента.

    src/main.ts
    import { installIntlayer } from "lit-intlayer";// Должно быть вызвано до того, как любой LitElement будет подключен к DOM.installIntlayer();// Импорт и регистрация ваших кастомных элементов.import "./my-element.js";

    Если вы также используете декларации контента md() (Markdown), установите также рендерер макдауна:

    src/main.ts
    import { installIntlayer, installIntlayerMarkdown } from "lit-intlayer";installIntlayer();installIntlayerMarkdown();import "./my-element.js";

    Шаг 5: Декларация вашего контента

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

    src/app.content.ts
    import { t, type Dictionary } from "intlayer";
    
    const appContent = {
      key: "app",
      content: {
        title: "Vite + Lit",
    
        viteLogo: t({
          en: "Vite logo",
          fr: "Logo Vite",
          es: "Logo Vite",
        }),
        litLogo: t({
          en: "Lit logo",
          fr: "Logo Lit",
          es: "Logo Lit",
        }),
    
        count: t({
          en: "count is {{count}}",
          fr: "le compte est {{count}}",
          es: "el recuento es {{count}}",
        }),
    
        readTheDocs: t({
          en: "Click on the Vite and Lit logos to learn more",
          fr: "Cliqueз sur les logos Vite et Lit pour en savoir plus",
          es: "Haga clic en los logotipos de Vite y Lit para obtener más información",
        }),
      },
    } satisfies Dictionary;
    
    export default appContent;

    Декларации контента могут быть определены в любом месте вашего приложения, если они включены в директорию contentDir (по умолчанию ./src) и соответствуют расширению файлов декларации контента (по умолчанию .content.{json,ts,tsx,js,jsx,mjs,cjs}).

    Подробнее см. в документации по декларации контента.

    Шаг 6: Использование Intlayer в вашем LitElement

    Используйте useIntlayer внутри LitElement. Он возвращает прокси ReactiveController, который автоматически вызывает перерисовку при изменении активного языка - никакой дополнительной настройки не требуется.

    src/my-element.ts
    import { LitElement, html } from "lit";import { customElement, property } from "lit/decorators.js";import { useIntlayer } from "lit-intlayer";@customElement("my-element")export class MyElement extends LitElement {  @property({ type: Number })  count = 0;  // useIntlayer регистрирует себя как ReactiveController.  // Элемент перерисовывается автоматически при смене языка.  private content = useIntlayer(this, "app");  override render() {    const { content } = this;    return html`      <h1>${content.title}</h1>      <img src="/vite.svg" alt=${content.viteLogo.value} />      <img src="/lit.svg" alt=${content.litLogo.value} />      <button @click=${() => this.count++}>        ${content.count({ count: this.count })}      </button>      <p>${content.readTheDocs}</p>    `;  }}

    Если вам нужна переведенная строка в нативном HTML-атрибуте (например, alt, aria-label, title), вызовите .value на конечном узле:

    typescript
    html`<img alt=${content.viteLogo.value} />`;html`<img alt=${content.viteLogo.toString()} />`;html`<img alt=${String(content.viteLogo)} />`;

    (Опционально) Шаг 7: Изменение языка вашего контента

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

    src/locale-switcher.ts
    import { LitElement, html } from "lit";import { customElement } from "lit/decorators.js";import { getLocaleName } from "intlayer";import { useLocale } from "lit-intlayer";@customElement("locale-switcher")export class LocaleSwitcher extends LitElement {  private locale = useLocale(this);  private _onChange(e: Event) {    const select = e.target as HTMLSelectElement;    this.locale.setLocale(select.value as any);  }  override render() {    return html`      <select @change=${this._onChange}>        ${this.locale.availableLocales.map(          (loc) => html`            <option value=${loc} ?selected=${loc === this.locale.locale}>              ${getLocaleName(loc)}            </option>          `        )}      </select>    `;  }}

    (Опционально) Шаг 8: Рендеринг Markdown и HTML контента

    Intlayer поддерживает декларации контента md() и html(). В Lit скомпилированный результат вставляется как необработанный HTML через директиву unsafeHTML.

    Рендеринг скомпилированного HTML в вашем элементе:

    src/my-element.ts
    import { LitElement, html } from "lit";import { customElement } from "lit/decorators.js";import { unsafeHTML } from "lit/directives/unsafe-html.js";import { useIntlayer } from "lit-intlayer";import { compileMarkdown } from "lit-intlayer/markdown";@customElement("my-element")export class MyElement extends LitElement {  private content = useIntlayer(this, "app");  override render() {    return html`      <div class="edit-note">        ${unsafeHTML(compileMarkdown(String(this.content.editNote)))}      </div>    `;  }}
    TIP
    String(content.editNote) вызывает toString() на IntlayerNode, который возвращает необработанную строку Markdown. Передайте ее в compileMarkdown, чтобы получить HTML-строку, а затем отрендерите ее с помощью директивы unsafeHTML от Lit.

    (Опционально) Шаг 9: Добавление локализованной маршрутизации (Routing)

    Чтобы создать уникальные маршруты для каждого языка (полезно для SEO), вы можете использовать клиентский роутер вместе с помощниками Intlayer localeMap / localeFlatMap и плагином Vite intlayerProxy для определения языка на стороне сервера.

    Сначала добавьте intlayerProxy в конфигурацию Vite:

    Обратите внимание, что для использования intlayerProxy в продакшене вам нужно переместить vite-intlayer из devDependencies в dependencies.
    vite.config.ts
    import { defineConfig } from "vite";
    import { intlayer, intlayerProxy } from "vite-intlayer";
    
    export default defineConfig({
      plugins: [
        intlayerProxy(), // should be placed first
        intlayer(),
      ],
    });

    (Опционально) Шаг 10: Изменение URL при смене языка

    Чтобы обновлять URL браузера при смене языка, используйте useRewriteURL вместе с переключателем языка:

    src/locale-switcher.ts
    import { LitElement, html } from "lit";import { customElement } from "lit/decorators.js";import { getLocaleName, getLocalizedUrl } from "intlayer";import { useLocale, useRewriteURL } from "lit-intlayer";@customElement("locale-switcher")export class LocaleSwitcher extends LitElement {  private locale = useLocale(this);  // Автоматически перезаписывает текущий URL при смене языка.  private _rewriteURL = useRewriteURL(this);  private _onChange(e: Event) {    const select = e.target as HTMLSelectElement;    this.locale.setLocale(select.value as any);  }  override render() {    return html`      <select @change=${this._onChange}>        ${this.locale.availableLocales.map(          (loc) => html`            <option value=${loc} ?selected=${loc === this.locale.locale}>              ${getLocaleName(loc)}            </option>          `        )}      </select>    `;  }}

    (Опционально) Шаг 11: Переключение атрибутов языка и направления текста в HTML

    Обновляйте атрибуты lang и dir тега <html> в соответствии с текущим языком для обеспечения доступности и SEO.

    src/my-element.ts
    import { LitElement, html } from "lit";import { customElement } from "lit/decorators.js";import { getHTMLTextDir } from "intlayer";import { useLocale } from "lit-intlayer";@customElement("my-element")export class MyElement extends LitElement {  private locale = useLocale(this, {    onLocaleChange: (loc) => {      document.documentElement.lang = loc;      document.documentElement.dir = getHTMLTextDir(loc);    },  });  override render() {    return html`<!-- ваш контент -->`;  }}

    (Опционально) Шаг 12: Извлечение контента из ваших компонентов

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

    Чтобы облегчить этот процесс, 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;

    (Опционально) Sitemap и robots.txt (генерация на сборке)

    Intlayer предоставляет generateSitemap и getMultilingualUrls - утилиты, которые формируют многоязычные sitemap.xml и robots.txt для краулеров и позволяют автоматически записать их в public/. Обычно запускают небольшой Node-скрипт до Vite (например, npm-хуки predev / prebuild).

    Sitemap

    Генератор sitemap учитывает локали и добавляет нужные метаданные.

    Поддерживается пространство имён xhtml:link (hreflang). Вместо плоского списка URL Intlayer связывает все языковые версии страницы в обе стороны (например /about, /fr/about или /about?lang=fr в зависимости от режима маршрутизации).

    Robots.txt

    Используйте getMultilingualUrls, чтобы правила Disallow покрывали все локализованные варианты путей.

    1. Файл generate-seo.mjs в корне проекта

    generate-seo.mjs
    import fs from "fs";import path from "path";import { fileURLToPath } from "url";import { generateSitemap, getMultilingualUrls } from "intlayer";const __dirname = path.dirname(fileURLToPath(import.meta.url));const SITE_URL = (process.env.SITE_URL || "http://localhost:5173").replace(  /\/$/,  "");const pathList = [  { path: "/", changefreq: "daily", priority: 1.0 },  { path: "/about", changefreq: "monthly", priority: 0.7 },];const sitemapXml = generateSitemap(pathList, { siteUrl: SITE_URL });fs.writeFileSync(path.join(__dirname, "public", "sitemap.xml"), sitemapXml);const getAllMultilingualUrls = (urls) =>  urls.flatMap((url) => Object.values(getMultilingualUrls(url)));const disallowedPaths = getAllMultilingualUrls(["/admin", "/private"]);const robotsTxt = [  "User-agent: *",  "Allow: /",  ...disallowedPaths.map((path) => `Disallow: ${path}`),  "",  `Sitemap: ${SITE_URL}/sitemap.xml`,].join("\n");fs.writeFileSync(path.join(__dirname, "public", "robots.txt"), robotsTxt);console.log("SEO files generated successfully.");

    Пакет intlayer должен быть установлен. Для продакшена задайте SITE_URL в окружении (например в CI).

    Для Node ESM предпочтительно generate-seo.mjs. Для generate-seo.js укажите "type": "module" в package.json или включите ESM иначе.

    2. Запуск скрипта до Vite

    package.json
    {  "scripts": {    "dev": "vite",    "prebuild": "node generate-seo.mjs",    "build": "vite build",    "preview": "vite preview"  }}

    Подстройте команды для pnpm или yarn. Скрипт можно вызывать из CI или другого шага.

    Настройка TypeScript

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

    tsconfig.json
    {  "compilerOptions": {    // ...    "experimentalDecorators": true,    "useDefineForClassFields": false,  },  "include": ["src", ".intlayer/**/*.ts"],}
    experimentalDecorators и useDefineForClassFields: false требуются Lit для поддержки декораторов.

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

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

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

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

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

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

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

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

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

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


    Идти дальше

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