Autor:
    Erstellung:2026-08-12Letzte Aktualisierung:2026-08-13

    ESLint x OXLint Plugin

    eslint-plugin-intlayer erkennt die typischen i18n-Fehler, die TypeScript nicht erfassen kann:

    1. Hartcodierter Text, der nie in einem Wörterbuch deklariert wurde.
    2. Dynamische Aufrufe, die die Typüberprüfung bestehen und ausgeführt werden, die der Intlayer-Compiler jedoch nicht optimieren kann.
    3. Toter Inhalt — Wörterbücher und Felder, die an keiner Stelle im Projekt gelesen werden (Opt-in).

    Unbekannte Wörterbuchschlüssel, unbekannte Feldpfade und fehlende Locales sind bereits Kompilierungsfehler, weshalb das Plugin diese nicht wiederholt.

    Installation

    bash
    npm install --save-dev eslint-plugin-intlayer

    Erfordert ESLint 9 oder höher (Flat Config). ESLint 10 wird unterstützt.

    Verwendung

    Das Plugin funktioniert sowohl in ESLint als auch in oxlint — dieselben Regeln, dieselben Optionen.

    Oder fügen Sie eine Konfiguration ein und legen die Schweregrade selbst fest:

    Konfigurationen

    Konfiguration no-raw-text static-dictionary-key no-dynamic-field-access enforce-adapter-import no-unused-content
    recommended warn error error off off
    strict error (+ Nicht-JSX-Zeichenfolgen) error error error off
    contract-only off error error off off

    recommended belässt no-raw-text absichtlich bei warn: Bei Anwendung auf eine bestehende Codebasis werden alle unübersetzten Zeichenfolgen auf einmal gemeldet, was Ihren Build nicht von Tag eins an blockieren sollte.

    enforce-adapter-import ist standardmäßig deaktiviert — aktivieren Sie die Regel bei Bedarf explizit.

    no-unused-content ist in allen Konfigurationen standardmäßig deaktiviert, einschließlich strict. Es ist die einzige Regel, die Ihre Intlayer-Konfiguration liest und Ihre Quelldateien vom Dateisystem durchsucht. Die Aktivierung sollte daher eine bewusste Entscheidung sein und nicht automatisch über ein Preset erfolgen.

    Regeln

    no-raw-text

    Meldet benutzerorientierten Text, der nicht in einem Wörterbuch deklariert ist. Verwendet dieselbe Erkennung wie intlayer extract, sodass Markennamen, CSS-Klassen und technische Bezeichner ignoriert werden.

    jsx
    // ✗ Gemeldet<h1>Welcome to our documentation</h1><input placeholder="Enter your email address" />// ✓ Gültigconst { title } = useIntlayer("home");<h1>{title}</h1>

    Inhaltsdeklarationsdateien (*.content.ts, …) werden übersprungen.

    Um eine Datei vollständig auf einmal zu korrigieren, führen Sie npx intlayer extract aus und lassen Sie den Compiler die Strings in ein Wörterbuch überführen.

    Optionen

    static-dictionary-key

    Erfordert, dass der Wörterbuchschlüssel ein Zeichenfolgen-Literal ist.

    Der Compiler kann ein Wörterbuch nur dann vorladen, wenn er den Schlüssel direkt am Aufrufort lesen kann. Bei einem dynamisch berechneten Schlüssel wird die Optimierung stillschweigend übersprungen und stattdessen jedes Wörterbuch gebündelt.

    typescript
    // ✗ GemeldetuseIntlayer(dictionaryKey);useIntlayer(`home-${suffix}`);getTranslations({ namespace: page });// ✗ Eine Variable ist immer noch kein Literalconst key = "home";useIntlayer(key);// ✓ GültiguseIntlayer("home");getTranslations({ namespace: "home" });

    Dies gilt für useIntlayer, getIntlayer und jeden Kompatibilitätsadapter (useTranslation, useTranslations, formatMessage, <FormattedMessage id>, <Trans i18nKey>, …).

    no-dynamic-field-access

    Erfordert, dass das Feld, das Sie aus einem Wörterbuch lesen, statisch bekannt ist.

    Der Compiler entfernt Felder, deren Verwendung er nicht erkennen kann. Ein berechneter Zugriff ist für ihn unsichtbar, sodass der Lesezugriff zur Laufzeit undefined zurückgeben kann.

    typescript
    // ✗ Gemeldetconst content = useIntlayer("home");content[fieldName];const t = useTranslations("home");t(messageKey);// ✓ Gültigcontent.title;content["title"];content.items[0];t("hero.title");

    enforce-adapter-import

    Bevorzugt den Kompatibilitätsadapter @intlayer/* gegenüber dem Originalpaket. Das Originalpaket löst nur dann zu Intlayer auf, wenn der Bundler-Alias konfiguriert ist; der Adapter funktioniert immer. Automatisch behebbar mit --fix.

    typescript
    // ✗ Gemeldetimport { useTranslation } from "react-i18next";import { getTranslations } from "next-intl/server";// ✓ Gültigimport { useTranslation } from "@intlayer/react-i18next";import { getTranslations } from "@intlayer/next-intl/server";

    no-unused-content

    Standardmäßig deaktiviert. Meldet Inhalte, die im Projekt nirgends gelesen werden, sowie Wörterbuchschlüssel, die an mehr als einer Stelle deklariert sind.

    src/home.content.ts
    export default {  key: "home", // ✗ Gemeldet, wenn kein Aufrufer im Projekt "home" abfragt  content: {    title: t({ de: "Titel", en: "Title" }),    // ✗ Gemeldet, wenn nichts `hero` liest    hero: {      subtitle: t({ de: "Untertitel", en: "Subtitle" }),    },  },};

    Im Gegensatz zu den anderen Regeln kann diese Regel nicht allein anhand der geprüften Datei entscheiden — ein Feld ist nur relativ zum gesamten Projekt ungenutzt. Bei der ersten Inhaltsdeklaration eines Lint-Laufs lädt sie Ihre Intlayer-Konfiguration, durchsucht die Quelldateien gemäß Konfiguration (build.traversePattern, compiler.transformPattern) und führt dieselbe Nutzungsanalyse aus, die auch @intlayer/lsp und das Durchstreichen von „ungenutzt“ in der VS Code-Erweiterung antreibt. Das Ergebnis wird für cacheTtl Millisekunden zwischengespeichert, sodass der Scan einmal pro Durchlauf und nicht für jede Datei ausgeführt wird.

    Optionen

    Verringern Sie cacheTtl, wenn Sie mit einem langlebigen Editor-Server linten und Ihre Änderungen schneller sehen möchten; setzen Sie baseDir, wenn ein einzelner Lint-Lauf mehrere Intlayer-Projekte in einem Monorepo umfasst.

    Neigt zur Zurückhaltung. Ein Fehlalarm würde eine Übersetzung löschen. Daher wird nichts gemeldet, wenn das Wörterbuch auf eine Weise verwendet wird, die die Analyse nicht nachverfolgen kann: das Inhaltsobjekt als Ganzes übergeben, eine gebundene Übersetzerfunktion (const t = useTranslations("home")), eine über direkten Import erreichte Deklaration (useDictionary(myDictionary)), ein nest() aus einem anderen Wörterbuch oder eine Feldliste, die durch einen Spread nicht-exhaustiv ist. Single-File-Komponenten (.vue, .svelte, .astro) gelten als Verwender aller Felder der genannten Wörterbücher, da ihre Script-Blöcke hier nicht analysiert werden.

    reportDuplicateKeys liest die unzusammengeführten Wörterbücher, die der Build unter .intlayer/ schreibt, und bleibt daher stumm, bis das Projekt mindestens einmal gebaut wurde. Zwei Deklarationen mit demselben Schlüssel werden zusammengeführt, was ein legitimes Muster ist — die Meldung existiert, da bei einem beidseitig definierten Feld stillschweigend nur einer der beiden Werte beibehalten wird.

    Der Analysator wird aus @intlayer/lsp geladen, welches als ESM ausgeliefert wird. Die Regel benötigt daher eine Node-Version, die ein ES-Modul via require() laden kann — Node 20.19+ oder 22.12+. Bei älteren Versionen meldet sie nichts, anstatt den Lint-Lauf abbrechen zu lassen.

    Frameworks

    Jede Regel funktioniert über alle Intlayer-Integrationen hinweg, einschließlich innerhalb von Vue-, Svelte- und Angular-Templates. Sie müssen ESLint lediglich mitteilen, welcher Parser jeden Dateityp liest.

    Framework Dateien Parser
    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-Templates .component.html @angular-eslint/template-parser
    Astro .astro astro-eslint-parser

    Installieren Sie nur die Parser, die Ihr Projekt benötigt.

    Bekannte Einschränkung. In Vue- und Angular-Templates wird ein Ausdruck wie {{ content[key] }} nicht von no-dynamic-field-access geprüft. Dynamische Zugriffe im Script-Block werden normal erkannt.