Автор:
    Создание:2026-06-14Последнее обновление:2026-06-30

    Новый Intlayer v9 — Что нового?

    Добро пожаловать в Intlayer v9! Этот мажорный релиз знаменует собой важную веху в упрощении миграции на Intlayer благодаря пакетам адаптеров совместимости (Compat Adapter Packages) для популярных библиотек i18n (react-i18next, next-intl, vue-i18n и др.), а также добавляет поддержку сложных структур контента: Collections (Коллекции) и Variants (Варианты).

    Содержание


    Пакеты адаптеров совместимости (Compat Adapter Packages)

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

    Тот же публичный API со строгой типизацией

    Просто заменив импорты, вы получаете все преимущества Intlayer (включая безопасность типов на этапе компиляции на основе ваших реальных словарей) с минимальными изменениями в коде:

    • @intlayer/i18next
    • @intlayer/react-i18next
    • @intlayer/next-intl
    • @intlayer/react-intl
    • @intlayer/next-i18next
    • @intlayer/vue-i18n
    • @intlayer/lingui

    Например, просто замените:

    ts
    import { useTranslation } from "react-i18next";

    на:

    ts
    import { useTranslation } from "@intlayer/react-i18next";

    Теперь ваши ключи будут строго типизированы на основе словарей Intlayer, обеспечивая автодополнение путей через точку (dot-path) в вашей IDE!

    Плагины-алиасы для сборщиков (Vite, Next.js, Turbopack)

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

    Эти плагины автоматически перезаписывают существующие импорты (например, react-i18next или next-intl) на их эквиваленты @intlayer/* во время сборки.

    Пример для Next.js (Webpack / Turbopack)

    Вместо withIntlayer оберните вашу конфигурацию Next.js плагином совместимости:

    next.config.ts
    import { createNextI18nPlugin } from "@intlayer/next-i18next/plugin";import type { NextConfig } from "next";const withIntlayer = createNextI18nPlugin();const nextConfig: NextConfig = {};export default withIntlayer(nextConfig);

    Пример для Vite (React, Vue, Solid, Svelte)

    vite.config.ts
    import vueI18nVitePlugin from "@intlayer/vue-i18n/plugin";export default defineConfig({  plugins: [vueI18nVitePlugin()],});

    Единый резолвер рантайма (Mutualized Runtime Resolver)

    Все адаптеры совместимости теперь направляют разрешение переводов через единый, высокооптимизированный парсер рантайма: @intlayer/core/messageFormat.

    • Интерполяция сообщений (Interpolate Message): Разрешает стандартные шаблоны {{var}} (с пробелами и путями через точку), аргументы в формате ICU ({v, number, percent} и т. д.) и простые шаблоны {var}.
    • Резолвер узлов сообщений (Message Node Resolver): Разрешает вложенные узлы: insert(), plural() (плюрализация по правилам CLDR), enu() (перечисление), gender() (род), HTML-теги, массивы и вызываемые функции-узлы.
    • Токенизированный парсер тегов (Tokenized Tag Parser): Поддерживает встроенные XML/HTML-теги и нумерованные теги (например, <1>children</1>) для рендеринга форматированного текста (rich-text) из коробки.

    Спецификация функций: Collections и Variants

    Intlayer v9 выходит за рамки статических объектов типа ключ-значение, позволяя словарям объявлять динамические структуры макетов со сквозной типизацией.

    1. Коллекции (Collections)

    Определяйте управляемый CMS упорядоченный список элементов (например, FAQ, товары или списки блогов):

    faq.1.content.ts
    import { t, type Dictionary } from "intlayer";export default {  key: "faq",  item: 1,  content: {    question: t({ en: "What is Intlayer?", fr: "Qu'est-ce qu'Intlayer ?" }),    answer: t({ en: "An i18n toolkit.", fr: "Une boîte à outils i18n." }),  },} satisfies Dictionary;
    faq.2.content.ts
    import { t, type Dictionary } from "intlayer";export default {  key: "faq",  item: 2,  content: {    question: t({ en: "Is it free?", fr: "Est-ce gratuit ?" }),    answer: t({ en: "Yes, open-source.", fr: "Oui, open-source." }),  },} satisfies Dictionary;

    Использование:

    ts
    // Fetch all items as an arrayconst allFaqs = useIntlayer("faq"); // -> { question: string, answer: string }[]// Fetch a single item by indexconst faq = useIntlayer("faq", { item: 2 }); // -> { question: string, answer: string }

    2. Варианты (Variants)

    Используйте для A/B-тестирования, сезонных заголовков, фича-флагов или кастомных целевых страниц:

    Строковые варианты (например, A/B-тестирование)

    hero.content.ts
    import { t, type Dictionary } from "intlayer";export default {  key: "hero-banner",  variant: "default",  content: {    control: t({ ru: "Добро пожаловать", en: "Welcome", fr: "Bienvenue" }),    black_friday: t({      ru: "Купить сейчас",      en: "Shop now",      fr: "Acheter maintenant",    }),  },} satisfies Dictionary;

    Использование:

    ts
    const banner = useIntlayer("hero-banner", { variant: "black_friday" });

    Объектные варианты (например, динамические записи)

    product.content.ts
    import { t, type Dictionary } from "intlayer";export default {  key: "product-copy",  variant: {    id: "prod_123",    category: "books",  },  content: {    title: t({ ru: "Чистый код", en: "Clean Code", fr: "Code Propre" }),  },} satisfies Dictionary;

    Использование:

    ts
    // Динамически загружает только запрошенный элемент (требуется Suspense)const product = useIntlayer("product-copy", {  variant: { id: "prod_123", category: "books" },});

    Vite Plugin: Bundled Compiler & Proxy

    Plugin Vite intlayer() теперь объединяет компилятор и proxy маршрутизации локалей напрямую, поэтому большинству проектов нужен только один plugin в vite.config.ts:

    vite.config.ts
    import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";export default defineConfig({  plugins: [intlayer()],});
    • Compiler: Активируется автоматически, когда параметр compiler.enabled установлен в true и настроен путь compiler.output. Вам больше не нужно регистрировать intlayerCompiler() отдельно.
    • Proxy: Активируется автоматически на основе нового параметра routing.enableProxy (true по умолчанию). Он подключает middleware обнаружения локалей / перенаправления / переписи в разработке, preview и production SSR. Вам больше не нужно регистрировать intlayerProxy() отдельно.

    Опция routing.enableProxy

    Новая опция routing.enableProxy контролирует, подключен ли прокси для маршрутизации локалей. По умолчанию установлено значение true. Отключите его, если вы хотите самостоятельно обрабатывать маршрутизацию локалей:

    intlayer.config.ts
    import type { IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  routing: {    enableProxy: false, // По умолчанию: true  },};export default config;

    Отдельные плагины intlayerCompiler() и intlayerProxy() остаются экспортированными для продвинутых конфигураций. Регистрация их вместе с intlayer() безопасна — каждый плагин дедублицирует себя и выполняется только один раз.


    Компилятор отключён по умолчанию

    Начиная с Intlayer v9, компилятор отключён по умолчанию (значение compiler.enabled теперь по умолчанию равно false). Чтобы включить извлечение ваших файлов .content.ts во время сборки, установите compiler.enabled: true в своей конфигурации:

    intlayer.config.ts
    import type { IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  compiler: {    enabled: true, // По умолчанию: false — требуется для включения компилятора начиная с v9    output: ({ fileName }) => `./${fileName}.content.ts`,  },};export default config;

    Когда компилятор отключён, Intlayer пропускает этап извлечения во время сборки и полагается на уже объявленные вами словари. Включайте его только тогда, когда хотите, чтобы плагин сборщика (@intlayer/swc, @intlayer/babel или Vite-плагин intlayer()) извлекал содержимое автоматически.


    React Native: импорт из одного пакета

    В приложении React Native или Expo вам больше не нужно жонглировать react-intlayer и react-native-intlayer. Пакет react-native-intlayer теперь реэкспортирует весь API react-intlayer (хуки, утилиты и подпути /format, /html и /markdown), а его IntlayerProvider автоматически применяет полифиллы React Native.

    Импортируйте все из единого пакета react-native-intlayer:

    tsx
    import {  IntlayerProvider,  useIntlayer,  useLocale,} from "react-native-intlayer";
    bash
    npm install intlayer react-native-intlayer
    Импорт из react-intlayer продолжает работать, но react-native-intlayer теперь является рекомендуемой единой точкой входа для React Native — его провайдер включает полифиллы, которых нет в веб-ориентированном провайдере react-intlayer.

    CMS SDK: используйте Intlayer как headless-базу данных контента

    Intlayer v9 включает аккуратный SDK с автоматической аутентификацией в @intlayer/api для программного взаимодействия с CMS — получать проекты, получать словари, а также отправлять или обновлять их с вашего сервера, скриптов или CI. Аутентификация (OAuth2 client_credentials) выполняется и обновляется за вас.

    SDK разделён на два отдельных импорта, чтобы ваш бандл включал только те домены, которые вы действительно используете:

    1. createIntlayerCMS — лёгкий аутентификатор, который хранит учётные данные и управляемый токен (клиенты доменов не включаются).
    2. dictionaryEndpoint, projectEndpoint, … — привязки эндпоинтов по доменам, каждая импортируется из своего подпути.
    cms.ts
    import { createIntlayerCMS } from "@intlayer/api";import { dictionaryEndpoint } from "@intlayer/api/dictionary";// Конфигурация необязательна: учётные данные берутся из INTLAYER_CLIENT_ID /// INTLAYER_CLIENT_SECRET, разрешаемых через `@intlayer/config/built`.const cms = createIntlayerCMS();// Чтениеconst { data: dictionaries } = await dictionaryEndpoint(cms).getDictionaries();// Запись — используйте CMS как базу данныхawait dictionaryEndpoint(cms).pushDictionaries([myDictionary]);
    Безопасность: учётные данные CMS дают доступ к вашему контенту на запись. Создавайте аутентификатор только на стороне сервера — никогда не передавайте clientId / clientSecret в браузер.

    Самостоятельное размещение (Self-Hosting)

    Intlayer v9 поставляется с первоклассной поддержкой запуска собственного экземпляра Intlayer с помощью одной команды — учётная запись Intlayer Cloud не требуется.

    sh
    curl -fsSL https://intlayer.org/install.sh | sh

    Установщик загружает docker-compose.yml и .env, автоматически генерирует необходимые секреты и запускает docker compose up -d. Всё — дашборд, API, база данных, хранилище объектов и транзакционная электронная почта — работает локально в контейнерах.

    Включённые сервисы

    Сервис Назначение
    app (TanStack Start) Дашборд UI на порту 3000
    backend (Fastify/Bun) REST API на порту 3100
    MongoDB 7 (одноузловой набор реплик) Основная база данных
    Redis 7 Очереди задач и кэширование
    MinIO S3-совместимое хранилище объектов (аватары, скриншоты)
    Mailpit Локальный SMTP-приёмник + веб-интерфейс для транзакционной почты на порту 8025

    Chromium (используемый для генерации скриншотов через Puppeteer) встроен в образ бэкенда — дополнительный контейнер не требуется.


    Примечания по миграции с v8

    Если вы обновляетесь с v8, обратите внимание, что v9 не содержит ломающих изменений (breaking changes). Однако вот ключевые изменения:

    • Компилятор отключён по умолчанию: значение compiler.enabled теперь по умолчанию равно false. Если вы полагаетесь на извлечение ваших файлов .content.ts во время сборки, установите compiler.enabled: true в своём intlayer.config.ts.
    • Локали и диалекты (Locales & Dialects): Если вы используете внешние зависимости i18n, добавьте соответствующие плагины адаптеров совместимости в вашу конфигурацию или настройки сборщика для автоматической перезаписи импортов.
    • Кастомные селекторы (Custom Selectors): При вызове useIntlayer второй параметр теперь зарезервирован для объекта опций, содержащего { locale, item, variant }. Если ранее вы передавали строку локали напрямую, вы все еще можете это делать, но для расширенного выбора рекомендуется использовать объект опций.

    Полезные ссылки