Autor:
    Data utworzenia:2026-08-12Ostatnia aktualizacja:2026-08-13

    Wtyczka ESLint x OXLint

    eslint-plugin-intlayer wychwytuje rodzaje błędów i18n, których TypeScript nie jest w stanie wykryć:

    1. Zahardkodowany tekst, który nigdy nie trafił do słownika.
    2. Dynamiczne wywołania, które przechodzą sprawdzanie typów i działają, ale których kompilator Intlayer nie potrafi zoptymalizować.
    3. Martwa zawartość (Dead content) — słowniki i pola, których nic w projekcie nie odczytuje (opcjonalne).

    Nieznane klucze słowników, nieznane ścieżki pól oraz brakujące ustawienia regionalne stanowią już błędy kompilacji, więc wtyczka ich nie powiela.

    Instalacja

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

    Wymaga ESLint w wersji 9 lub nowszej (flat config). ESLint 10 jest wspierany.

    Użycie

    Wtyczka działa zarówno w ESLint, jak i oxlint — te same reguły, te same opcje.

    Albo rozwiń konfigurację i sam ustaw poziomy zgłoszeń:

    Konfiguracje

    Konfiguracja no-raw-text static-dictionary-key no-dynamic-field-access enforce-adapter-import no-unused-content
    recommended warn error error off off
    strict error (+ literały poza JSX) error error error off
    contract-only off error error off off

    recommended celowo utrzymuje no-raw-text na poziomie warn: uruchomienie jej na istniejącej bazie kodu ujawnia wszystkie nieprzetłumaczone ciągi znaków naraz, co nie powinno blokować procesu budowania od pierwszego dnia.

    enforce-adapter-import jest domyślnie wyłączona — włącz ją jawnie, jeśli tego potrzebujesz.

    no-unused-content jest wyłączona w każdej konfiguracji, w tym strict. Jest to jedyna reguła, która odczytuje konfigurację Intlayer i przeszukuje pliki źródłowe na dysku, więc jej włączenie powinno być świadomym wyborem, a nie domyślnym zachowaniem zestawu.

    Reguły

    no-raw-text

    Zgłasza tekst widoczny dla użytkownika, który nie jest zadeklarowany w słowniku. Używa tej samej metody detekcji co intlayer extract, dzięki czemu nazwy marek, klasy CSS i identyfikatory techniczne są ignorowane.

    jsx
    // ✗ Zgłoszone<h1>Welcome to our documentation</h1><input placeholder="Enter your email address" />// ✓ Prawidłowoconst { title } = useIntlayer("home");<h1>{title}</h1>

    Pliki deklaracji zawartości (*.content.ts, …) są pomijane.

    Aby naprawić cały plik naraz, uruchom npx intlayer extract, a kompilator automatycznie przeniesie ciągi znaków do słownika.

    Opcje

    static-dictionary-key

    Wymaga, aby klucz słownika był literałem łańcuchowym.

    Kompilator może wstępnie załadować słownik tylko wtedy, gdy może bezpośrednio odczytać klucz w miejscu wywołania. W przypadku obliczanego klucza optymalizacja jest po cichu pomijana i zamiast tego dołączane są wszystkie słowniki.

    typescript
    // ✗ ZgłoszoneuseIntlayer(dictionaryKey);useIntlayer(`home-${suffix}`);getTranslations({ namespace: page });// ✗ Zmienna nadal nie jest literałemconst key = "home";useIntlayer(key);// ✓ PrawidłowouseIntlayer("home");getTranslations({ namespace: "home" });

    Dotyczy to useIntlayer, getIntlayer oraz każdego adaptera kompatybilności (useTranslation, useTranslations, formatMessage, <FormattedMessage id>, <Trans i18nKey>, …).

    no-dynamic-field-access

    Wymaga, aby pole odczytywane ze słownika było znane statycznie.

    Kompilator usuwa pola, których użycia nie zarejestruje. Dostęp dynamiczny jest dla niego niewidoczny, więc odczyt może zwrócić undefined w czasie wykonywania.

    typescript
    // ✗ Zgłoszoneconst content = useIntlayer("home");content[fieldName];const t = useTranslations("home");t(messageKey);// ✓ Prawidłowocontent.title;content["title"];content.items[0];t("hero.title");

    enforce-adapter-import

    Preferuje adapter kompatybilności @intlayer/* zamiast oryginalnego pakietu. Oryginalny pakiet rozwiązuje się do Intlayer tylko wtedy, gdy skonfigurowany jest alias bundlera; adapter działa zawsze. Możliwość automatycznej naprawy za pomocą --fix.

    typescript
    // ✗ Zgłoszoneimport { useTranslation } from "react-i18next";import { getTranslations } from "next-intl/server";// ✓ Prawidłowoimport { useTranslation } from "@intlayer/react-i18next";import { getTranslations } from "@intlayer/next-intl/server";

    no-unused-content

    Domyślnie wyłączona. Zgłasza zawartość, której nic w projekcie nie odczytuje, oraz klucze słowników zadeklarowane w więcej niż jednym miejscu.

    src/home.content.ts
    export default {  key: "home", // ✗ Zgłaszane, gdy żadne wywołanie w projekcie nie odpytuje o "home"  content: {    title: t({ pl: "Tytuł", en: "Title" }),    // ✗ Zgłaszane, gdy nic nie odczytuje `hero`    hero: {      subtitle: t({ pl: "Podtytuł", en: "Subtitle" }),    },  },};

    W przeciwieństwie do innych reguł, ta nie jest w stanie ocenić sytuacji wyłącznie na podstawie sprawdzanego pliku — pole jest nieużywane tylko w kontekście całego projektu. Przy pierwszej deklaracji zawartości podczas działania lintera wczytuje konfigurację Intlayer, skanuje pliki źródłowe wskazane przez tę konfigurację (build.traversePattern, compiler.transformPattern) i uruchamia ten sam analizator użycia, który zasila @intlayer/lsp oraz przekreślenie „nieużywane” w rozszerzeniu VS Code. Wynik jest buforowany przez cacheTtl milisekund, więc skanowanie odbywa się raz na uruchomienie, a nie dla każdego pliku.

    Opcje

    Zmniejsz cacheTtl, gdy korzystasz z lintera działającego jako serwer edytora i chcesz szybciej widzieć zmiany; ustaw baseDir, gdy jedno uruchomienie lintera obejmuje kilka projektów Intlayer w monorepo.

    Preferuje brak zgłoszenia w razie wątpliwości. Fałszywy alarm w tym miejscu mógłby usunąć potrzebne tłumaczenie, dlatego nic nie jest zgłaszane, gdy słownik jest używany w sposób, którego analiza nie potrafi prześledzić: przekazanie całego obiektu zawartości, powiązana z niego funkcja tłumacząca (const t = useTranslations("home")), deklaracja dostępna przez bezpośredni import (useDictionary(myDictionary)), nest() z innego słownika lub lista pól, która stała się niepełna przez operator spread. Komponenty jednoplikowe (.vue, .svelte, .astro) są traktowane jako używające każdego pola wymienionych słowników, ponieważ ich bloki skryptów nie są tu parsowane.

    reportDuplicateKeys odczytuje niescalone słowniki, które proces budowania zapisuje w .intlayer/, więc zachowuje milczenie do momentu, aż projekt zostanie zbudowany przynajmniej raz. Dwie deklaracje dzielące ten sam klucz są scalane, co jest poprawnym wzorcem — raport istnieje, ponieważ pole zdefiniowane po obu stronach po cichu zachowuje tylko jedną z dwóch wartości.

    Analizator jest ładowany z @intlayer/lsp, który jest dystrybuowany jako ESM. Reguła wymaga zatem wersji Node obsługującej require() dla modułów ES — Node 20.19+ lub 22.12+. Na starszych wersjach reguła nic nie zgłasza, zamiast powodować błąd działania lintera.

    Frameworki

    Każda reguła działa we wszystkich integracjach Intlayer, w tym wewnątrz szablonów Vue, Svelte i Angular. Wystarczy wskazać ESLintowi, który parser obsługuje dany typ pliku.

    Framework Pliki 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
    Szablony Angular .component.html @angular-eslint/template-parser
    Astro .astro astro-eslint-parser

    Instaluj tylko te parsery, których wymaga Twój projekt.

    Znane ograniczenie. W szablonach Vue i Angular wyrażenie takie jak {{ content[key] }} nie jest sprawdzane przez no-dynamic-field-access. Odczyty dynamiczne zapisane w bloku script są wykrywane w normalny sposób.