Автор:
    Создание:2025-03-13Последнее обновление:2026-06-21

    Sync JSON (i18n bridges) — Синхронизация JSON с поддержкой ICU / i18next

    www.youtube.com

    Используйте Intlayer как дополнение к вашему существующему стеку i18n. Этот плагин синхронизирует ваши сообщения JSON со словарями Intlayer, чтобы вы могли:

    • Сохраняйте поддержку i18next, next‑intl, react‑intl, vue‑i18n, next‑translate, nuxt‑i18n, Solid‑i18next, svelte‑i18n и других.
    • Управляйте и переводите свои сообщения с помощью Intlayer (CLI, CI, провайдеры, CMS) без рефакторинга вашего приложения.
    • Создавайте руководства и SEO-контент для каждой экосистемы, предлагая Intlayer в качестве слоя управления JSON.

    Заметки и текущая область применения:

    • Экспорт в CMS работает для переводов и обычного текста.
    • Пока нет поддержки вставок, множественного числа/ICU или продвинутых функций рантайма других библиотек.
    • Визуальный редактор пока не поддерживает вывод i18n сторонних библиотек.

    Когда использовать этот плагин

    • Вы уже используете библиотеку i18n и храните сообщения в JSON-файлах.
    • Вы хотите использовать автозаполнение с помощью ИИ, тесты в CI и content ops без изменения вашего рантайма рендеринга.

    Установка

    bash
    pnpm add -D @intlayer/sync-json-plugin# илиnpm i -D @intlayer/sync-json-plugin

    Плагины

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

    • loadJSON: Загрузка JSON-файлов в словари Intlayer.

      • Этот плагин используется для загрузки JSON-файлов из источника и их загрузки в словари Intlayer. Он может сканировать всю codebase и искать определенные JSON-файлы. Этот плагин можно использовать
        • если вы используете библиотеку i18n, которая требует определенного расположения для загрузки ваших JSON (например, next-intl, i18next, react-intl, vue-i18n и т. д.), но вы хотите размещать объявления контента там, где вам удобно в вашей codebase.
        • Его также можно использовать, если вы хотите получать сообщения из удаленного источника (например, CMS, API и т. д.) и сохранять их в JSON-файлах.

      Внутри этот плагин будет сканировать всю кодовую базу (codebase), искать определенные JSON-файлы и загружать их в словари Intlayer. Обратите внимание, что этот плагин не будет записывать результат и переводы обратно в JSON-файлы.

    • syncJSON: Синхронизация JSON-файлов со словарями Intlayer.

      • Этот плагин используется для синхронизации JSON-файлов со словарями Intlayer. Он может сканировать указанное местоположение и загружать JSON, соответствующие шаблону для определенных JSON-файлов. Этот плагин полезен, если вы хотите получить преимущества Intlayer, используя при этом другую библиотеку i18n.

    Использование обоих плагинов

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";import { loadJSON, syncJSON } from "@intlayer/sync-json-plugin";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],    defaultLocale: Locales.ENGLISH,  },  // Поддерживайте ваши текущие JSON-файлы в синхронизации со словарями Intlayer  plugins: [    /**     * Загрузит все JSON-файлы в src, которые соответствуют шаблону {key}.i18n json     */    loadJSON({      source: ({ key }) => `./src/**/${key}.i18n.json`,      locale: Locales.ENGLISH,      priority: 1, // Гарантирует, что эти JSON-файлы имеют приоритет над файлами в `./locales/en/${key}.json`      format: "intlayer", // Формат содержимого JSON    }),    /**     * Загрузит, а также запишет результат и переводы обратно в JSON-файлы в директории locales     */    syncJSON({      source: ({ key, locale }) => `./locales/${locale}/${key}.json`,      priority: 0,      format: "i18next",    }),  ],};export default config;

    syncJSON plugin

    Быстрый старт

    Добавьте плагин в ваш intlayer.config.ts и укажите ему на вашу существующую структуру JSON.

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";import { syncJSON } from "@intlayer/sync-json-plugin";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],    defaultLocale: Locales.ENGLISH,  },  // Поддерживайте ваши текущие JSON-файлы в синхронизации со словарями Intlayer  plugins: [    syncJSON({      // Макет для каждой локали, для каждого пространства имен (например, next-intl, i18next с пространствами имен)      source: ({ key, locale }) => `./locales/${locale}/${key}.json`,      format: "icu",    }),  ],};export default config;

    Альтернатива: один файл на локаль (часто используется в настройках i18next/react-intl):

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";import { syncJSON } from "@intlayer/sync-json-plugin";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH],    defaultLocale: Locales.ENGLISH,  },  plugins: [    syncJSON({      format: "i18next",      source: ({ locale }) => `./locales/${locale}.json`,      format: "i18next",    }),  ],};export default config;

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

    • Чтение: плагин обнаруживает JSON-файлы из вашего source билдера и загружает их как словари Intlayer.
    • Запись: после сборки и заполнения он записывает локализованный JSON обратно по тем же путям (с конечной новой строкой, чтобы избежать проблем с форматированием).
    • Автозаполнение: плагин объявляет путь autoFill для каждого словаря. Запуск intlayer fill по умолчанию обновляет только отсутствующие переводы в ваших JSON-файлах.

    API:

    ts
    syncJSON({  source: ({ key, locale }) => string, // required  location?: string, // optional label, default: "plugin"  priority?: number, // optional priority for conflict resolution, default: 0  format?: 'intlayer' | 'icu' | 'i18next', // optional formatter, used for intlayer runtime compatibility  splitKeys?: boolean, // необязательно, разделяет один файл на один словарь для каждого ключа верхнего уровня (автоматическое определение)});

    format ('intlayer' | 'icu' | 'i18next')

    Указывает форматтер, который будет использоваться для содержимого словаря при синхронизации JSON-файлов. Это позволяет использовать различные синтаксисы форматирования сообщений, совместимые с рантаймом intlayer.

    • undefined: Форматтер не будет использоваться, содержимое JSON будет использоваться как есть.
    • 'intlayer': Форматтер Intlayer по умолчанию (default).
    • 'icu': Использует форматирование сообщений ICU (совместимо с такими библиотеками, как react-intl, vue-i18n).
    • 'i18next': Использует форматирование сообщений i18next (совместимо с i18next, next-i18next, Solid-i18next).

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

    Пример:

    ts
    syncJSON({  source: ({ key, locale }) => `./locales/${locale}/${key}.json`,  format: "i18next", // Use i18next formatting for compatibility}),

    splitKeys (boolean)

    Определяет, должен ли один JSON-файл, ключи первого уровня которого являются пространствами имен, становиться одним словарем на каждый ключ верхнего уровня, вместо одного словаря, содержащего весь файл.

    Это соответствует модели пространств имен таких библиотек, как next-intl и react-intl, где один файл messages/{locale}.json группирует несколько пространств имен по своим ключам первого уровня, каждое из которых адресуется независимо (например, useTranslations('Hero') разрешается в словарь Hero).

    • undefined (по умолчанию): автоматическое определение — файл разделяется, когда шаблон source не содержит сегмента {key} (один файл содержит все пространства имен), и сохраняется как один словарь в противном случае (один файл на ключ).
    • true: всегда разделять каждый ключ верхнего уровня на свой собственный словарь.
    • false: никогда не разделять; весь файл становится одним словарем.

    Пример одного файла messages/{locale}.json:

    messages/en.json
    {  "Hero": { "title": "Full-stack developer" },  "Nav": { "work": "Work", "about": "About" },  "About": { "lead": "I build apps end to end." }}
    intlayer.config.ts
    syncJSON({  format: "icu",  source: ({ locale }) => `./messages/${locale}.json`,  // splitKeys: true, // подразумевается, потому что шаблон не содержит сегмента `{key}`}),

    Это создает три словаря — Hero, Nav и About — так что useTranslations('Hero') (next-intl) разрешается правильно. При обратной записи все пространства имен снова собираются в тот же файл для каждой локали.

    Когда вы сохраняете явный сегмент {key} в вашем source (например, ./locales/${locale}/${key}.json), каждый файл уже является одним пространством имен, поэтому разделение по умолчанию отключено.

    Несколько источников JSON и приоритет

    Вы можете добавить несколько плагинов syncJSON для синхронизации различных источников JSON. Это полезно, когда у вас есть несколько библиотек i18n или различные структуры JSON в вашем проекте.

    Система приоритетов

    Когда несколько плагинов нацелены на один и тот же ключ словаря, параметр priority определяет, какой плагин имеет приоритет:

    • Более высокие номера приоритета преобладают над более низкими
    • Приоритет по умолчанию для файлов .content равен 0
    • Приоритет по умолчанию для плагинов равен 0
    • Плагины с одинаковым приоритетом обрабатываются в порядке их появления в конфигурации
    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";import { syncJSON } from "@intlayer/sync-json-plugin";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH],    defaultLocale: Locales.ENGLISH,  },  plugins: [    // Primary JSON source (highest priority)    syncJSON({      format: "i18next",      source: ({ key, locale }) => `./locales/${locale}/${key}.json`,      location: "main-translations",      priority: 10,    }),    // Fallback JSON source (lower priority)    syncJSON({      format: "i18next",      source: ({ locale }) => `./fallback-locales/${locale}.json`,      location: "fallback-translations",      priority: 5,    }),    // Legacy JSON source (lowest priority)    syncJSON({      format: "i18next",      source: ({ locale }) => `/my/other/app/legacy/${locale}/messages.json`,      location: "legacy-translations",      priority: 1,    }),  ],};export default config;

    Load JSON plugin

    Быстрый старт

    Добавьте плагин в ваш intlayer.config.ts, чтобы импортировать существующие JSON-файлы как словари Intlayer. Этот плагин предназначен только для чтения (без записи на диск):

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";import { loadJSON } from "@intlayer/sync-json-plugin";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],    defaultLocale: Locales.ENGLISH,  },  plugins: [    // Импорт JSON-сообщений, расположенных в любом месте вашего исходного дерева    loadJSON({      source: ({ key }) => `./src/**/${key}.i18n.json`,      // Загрузка одной локали для каждого экземпляра плагина (по умолчанию используется defaultLocale из конфигурации)      locale: Locales.ENGLISH,      priority: 0,    }),  ],};export default config;

    Альтернатива: макет для каждой локали, только для чтения (загружается только выбранная локаль):

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";import { loadJSON } from "@intlayer/sync-json-plugin";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH],    defaultLocale: Locales.ENGLISH,  },  plugins: [    loadJSON({      // Только файлы для Locales.FRENCH будут загружены по этому шаблону      source: ({ key, locale }) => `./locales/${locale}/${key}.json`,      locale: Locales.FRENCH,    }),  ],};export default config;

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

    • Обнаружение: создает glob из вашего source билдера и собирает соответствующие JSON-файлы.
    • Импорт: загружает каждый JSON-файл как словарь Intlayer с предоставленной locale.
    • Только для чтения: не записывает и не форматирует выходные файлы; используйте syncJSON, если вам нужна двусторонняя синхронизация.
    • Готовность к автозаполнению: определяет шаблон fill, чтобы intlayer content fill мог заполнять отсутствующие ключи.

    API

    ts
    loadJSON({  // Build paths to your JSON. `locale` is optional if your structure has no locale segment  source: ({ key, locale }) => string,  // Target locale for the dictionaries loaded by this plugin instance  // Defaults to configuration.internationalization.defaultLocale  locale?: Locale,  // Optional label to identify the source  location?: string, // default: "plugin"  // Priority used for conflict resolution against other sources  priority?: number, // default: 0  // Optional formatter for the JSON content  format?: 'intlayer' | 'icu' | 'i18next', // default: 'intlayer'  // Разделяет один файл на один словарь для каждого ключа верхнего уровня (автоматическое определение)  splitKeys?: boolean,});

    format ('intlayer' | 'icu' | 'i18next')

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

    • 'intlayer': Форматтер Intlayer по умолчанию (default).
    • 'icu': Использует форматирование сообщений ICU (совместимо с такими библиотеками, как react-intl, vue-i18n).
    • 'i18next': Использует форматирование сообщений i18next (совместимо с i18next, next-i18next, Solid-i18next).

    Пример:

    ts
    loadJSON({  source: ({ key }) => `./src/**/${key}.i18n.json`,  locale: Locales.ENGLISH,  format: "icu", // Use ICU formatting for compatibility}),

    splitKeys (boolean)

    Поведение такое же, как в syncJSON: когда один JSON-файл группирует несколько пространств имен по своим ключам первого уровня, каждый ключ верхнего уровня становится своим собственным словарем.

    • undefined (по умолчанию): автоматическое определение — разделение происходит, когда шаблон source не содержит сегмента {key}, в противном случае — один словарь.
    • true / false: принудительное включение или отключение разделения.
    ts
    loadJSON({  source: ({ locale }) => `./messages/${locale}.json`,  format: "icu",  // splitKeys auto-enabled: `Hero`, `Nav`, `About`, … each become a dictionary}),

    Поведение и соглашения

    • Если ваша маска source включает плейсхолдер локали, будут импортированы только файлы для выбранной locale.
    • Если в вашей маске нет сегмента {key}, каждый ключ верхнего уровня файла становится отдельным словарем по умолчанию (см. splitKeys). Установите splitKeys: false, чтобы вместо этого загрузить весь файл как единый словарь index.
    • Ключи выводятся из путей к файлам путем подстановки плейсхолдера {key} в вашем source билдере.
    • Плагин использует только обнаруженные файлы и не создает отсутствующие локали или ключи.
    • Путь fill выводится из вашего source и используется для обновления отсутствующих значений через CLI, когда вы соглашаетесь.

    Разрешение конфликтов

    Когда один и тот же ключ перевода существует в нескольких источниках JSON:

    1. Плагин с наивысшим приоритетом определяет окончательное значение
    2. Источники с более низким приоритетом используются в качестве запасных для отсутствующих ключей
    3. Это позволяет вам поддерживать устаревшие переводы, постепенно переходя к новым структурам

    CLI

    Синхронизированные JSON-файлы будут рассматриваться как другие файлы .content. Это означает, что все команды intlayer будут доступны для синхронизированных JSON-файлов. Включая:

    • intlayer content test для проверки наличия отсутствующих переводов
    • intlayer content list для вывода списка синхронизированных JSON-файлов
    • intlayer content fill для заполнения отсутствующих переводов
    • intlayer content push для отправки синхронизированных JSON-файлов
    • intlayer content pull для получения синхронизированных JSON-файлов

    Подробнее см. в Intlayer CLI.

    Ограничения (текущие)

    • Нет поддержки вставок или множественного числа/ICU при работе со сторонними библиотеками.
    • Визуальный редактор пока недоступен для рантаймов, отличных от Intlayer.
    • Только синхронизация JSON; форматы каталогов, отличные от JSON, не поддерживаются.

    Почему это важно

    • Мы можем рекомендовать проверенные решения i18n и позиционировать Intlayer как дополнение.
    • Мы используем их SEO/ключевые слова с руководствами, которые заканчиваются предложением Intlayer для управления JSON.
    • Расширяет целевую аудиторию от «новых проектов» до «любой команды, уже использующей i18n».