Задайте вопрос и получите краткое содержание документа через любого ИИ-провайдера на этой странице
История версий
- "Начальная история"v9.3.112.08.2026
Содержимое этой страницы было переведено с помощью ИИ.
Смотреть последнюю версию оригинального контента на английскомIf you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.
GitHub link to the documentationCopy doc Markdown to clipboard
Плагин ESLint x OXLint
eslint-plugin-intlayer отслеживает типичные ошибки i18n, которые TypeScript не способен обнаружить:
- Жестко закодированный текст, который так и не был вынесен в словарь.
- Динамические вызовы, которые проходят проверку типов и выполняются, но не могут быть оптимизированы компилятором Intlayer.
- Мертвый контент — словари и поля, которые нигде в проекте не считываются (по желанию).
Неизвестные ключи словарей, неизвестные пути к полям и отсутствующие локали уже приводят к ошибкам компиляции, поэтому плагин не дублирует их проверку.
Установка
Копировать код в буфер обмена
npm install --save-dev eslint-plugin-intlayerТребуется ESLint 9 или новее (flat config). ESLint 10 поддерживается.
Использование
Плагин работает как в ESLint, так и в oxlint — одни и те же правила, одни и те же параметры.
Либо разверните конфигурацию и задайте уровни сами:
Пресеты конфигураций
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Конфигурация | no-raw-text | static-dictionary-key | no-dynamic-field-access | enforce-adapter-import | no-unused-content |
|---|---|---|---|---|---|
recommended | warn | error | error | off | off |
strict | error (+ строковые литералы вне JSX) | error | error | error | off |
contract-only | off | error | error | off | off |
Пресет recommended намеренно оставляет no-raw-text со статусом warn: применение правила к существующей кодовой базе покажет сразу все непереведенные строки, что не должно ломать сборку с первого же дня.
enforce-adapter-import по умолчанию выключено — включите его явно при необходимости.
no-unused-content выключено во всех пресетах, включая strict. Это единственное правило, которое считывает конфигурацию Intlayer и сканирует исходные файлы на диске, поэтому его включение должно быть осознанным выбором, а не автоматическим решением пресета.
Правила
no-raw-text
Сообщает о тексте для пользователя, который не объявлен в словаре. Использует ту же логику обнаружения, что и intlayer extract, поэтому названия брендов, CSS-классы и технические идентификаторы игнорируются.
Копировать код в буфер обмена
// ✗ Ошибка<h1>Welcome to our documentation</h1><input placeholder="Enter your email address" />// ✓ Корректноconst { title } = useIntlayer("home");<h1>{title}</h1>Файлы объявления контента (*.content.ts, …) пропускаются.
Чтобы исправить весь файл сразу, выполните npx intlayer extract, и компилятор автоматически перенесет строки в словарь.
Параметры
static-dictionary-key
Требует, чтобы ключ словаря был строковым литералом.
Компилятор может предварительно загрузить словарь только тогда, когда он может прочитать ключ непосредственно в месте вызова. При использовании вычисляемого ключа оптимизация автоматически пропускается, и вместо этого в бандл включаются все словари.
Копировать код в буфер обмена
// ✗ ОшибкаuseIntlayer(dictionaryKey);useIntlayer(`home-${suffix}`);getTranslations({ namespace: page });// ✗ Переменная по-прежнему не является литераломconst key = "home";useIntlayer(key);// ✓ КорректноuseIntlayer("home");getTranslations({ namespace: "home" });Это относится к useIntlayer, getIntlayer и всем адаптерам совместимости (useTranslation, useTranslations, formatMessage, <FormattedMessage id>, <Trans i18nKey>, …).
no-dynamic-field-access
Требует, чтобы поле, считываемое из словаря, было статически известно.
Компилятор удаляет поля, использование которых он не обнаружил. Динамический доступ для него невидим, поэтому чтение может вернуть undefined во время выполнения.
Копировать код в буфер обмена
// ✗ Ошибкаconst content = useIntlayer("home");content[fieldName];const t = useTranslations("home");t(messageKey);// ✓ Корректноcontent.title;content["title"];content.items[0];t("hero.title");enforce-adapter-import
Отдает предпочтение адаптеру совместимости @intlayer/* перед оригинальным пакетом. Оригинальный пакет разрешается в Intlayer только при настроенном псевдониме бандлера, тогда как адаптер работает всегда. Поддерживает автоисправление через --fix.
Копировать код в буфер обмена
// ✗ Ошибкаimport { useTranslation } from "react-i18next";import { getTranslations } from "next-intl/server";// ✓ Корректноimport { useTranslation } from "@intlayer/react-i18next";import { getTranslations } from "@intlayer/next-intl/server";no-unused-content
По умолчанию отключено. Сообщает о контенте, который нигде в проекте не считывается, а также о ключах словарей, объявленных более чем в одном месте.
Копировать код в буфер обмена
export default { key: "home", // ✗ Сообщается, если ни одно место в проекте не запрашивает "home" content: { title: t({ ru: "Заголовок", en: "Title" }), // ✗ Сообщается, если ничто не считывает `hero` hero: { subtitle: t({ ru: "Подзаголовок", en: "Subtitle" }), }, },};В отличие от других правил, это правило не может принять решение только по проверяемому файлу — неиспользуемость поля определяется относительно всего проекта. При первом объявлении контента во время линтинга оно загружает конфигурацию Intlayer, ищет исходные файлы по путям из конфигурации (build.traversePattern, compiler.transformPattern) и запускает тот же анализатор использования, который используется в @intlayer/lsp и зачеркивании «неиспользуемого» в расширении VS Code. Результат кэшируется на cacheTtl миллисекунд, поэтому сканирование выполняется один раз за запуск, а не для каждого файла.
Параметры
Уменьшите cacheTtl, если вы линтите из долгоживущего сервера редактора и хотите быстрее видеть изменения; установите baseDir, если один запуск линтера охватывает несколько проектов Intlayer в монорепозитории.
Стремится к минимизации ложных срабатываний. Ложное срабатывание здесь может привести к удалению нужного перевода, поэтому ничего не сообщается, когда словарь используется способом, который анализ не может отследить: объект контента передан целиком, функция перевода привязана от него (const t = useTranslations("home")), объявление получено через прямой импорт (useDictionary(myDictionary)),nest()из другого словаря или список полей, ставший неполным из-за spread-оператора. Однофайловые компоненты (.vue,.svelte,.astro) считаются использующими все поля упомянутых словарей, поскольку их блоки скриптов здесь не парсятся.
reportDuplicateKeys считывает необъединенные словари, которые сборка записывает в .intlayer/, поэтому оно не срабатывает, пока проект не будет собран хотя бы один раз. Два объявления с одинаковым ключом объединяются, что является допустимым паттерном — отчет формируется потому, что поле, определенное с обеих сторон, без предупреждения сохраняет только одно из двух значений.
Анализатор загружается из @intlayer/lsp, который поставляется как ESM. Поэтому правилу требуется версия Node, поддерживающая require() для ES-модулей — Node 20.19+ или 22.12+. На более старых версиях оно ничего не сообщает, чтобы не прерывать выполнение линтинга.
Фреймворки
Каждое правило работает во всех интеграциях Intlayer, включая шаблоны Vue, Svelte и Angular. Вам нужно лишь указать ESLint, какой парсер использовать для каждого типа файлов.
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Фреймворк | Файлы | Парсер |
|---|---|---|
| React, Preact, Solid, Lit | .jsx .tsx | typescript-eslint |
| Next.js | .jsx .tsx | typescript-eslint |
| Vue, Nuxt | .vue | vue-eslint-parser |
| Svelte, SvelteKit | .svelte | svelte-eslint-parser |
| Angular | .ts | typescript-eslint |
| Шаблоны Angular | .component.html | @angular-eslint/template-parser |
| Astro | .astro | astro-eslint-parser |
Устанавливайте только те парсеры, которые требуются вашему проекту.
Известное ограничение. В шаблонах Vue и Angular выражение вида{{ content[key] }}не проверяется правиломno-dynamic-field-access. Динамическое чтение внутри блока script определяется в штатном режиме.