@intlayer/docs 9.3.1 → 9.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/cjs/generated/docs.entry.cjs +20 -0
  2. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  3. package/dist/esm/generated/docs.entry.mjs +20 -0
  4. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  5. package/dist/types/generated/docs.entry.d.ts +1 -0
  6. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  7. package/docs/ar/eslint.md +336 -0
  8. package/docs/ar/intlayer_with_react_router_v7_fs_routes.md +1 -1
  9. package/docs/bn/eslint.md +336 -0
  10. package/docs/cs/eslint.md +336 -0
  11. package/docs/de/eslint.md +336 -0
  12. package/docs/en/eslint.md +336 -0
  13. package/docs/en-GB/eslint.md +336 -0
  14. package/docs/en-GB/intlayer_with_create_react_app.md +32 -35
  15. package/docs/en-GB/intlayer_with_react_router_v7_fs_routes.md +1 -1
  16. package/docs/es/eslint.md +336 -0
  17. package/docs/fr/eslint.md +336 -0
  18. package/docs/hi/eslint.md +336 -0
  19. package/docs/hi/intlayer_with_react_router_v7_fs_routes.md +1 -1
  20. package/docs/hi/intlayer_with_vite+svelte.md +2 -2
  21. package/docs/id/eslint.md +336 -0
  22. package/docs/it/eslint.md +336 -0
  23. package/docs/ja/eslint.md +336 -0
  24. package/docs/ja/intlayer_with_react_router_v7.md +1 -146
  25. package/docs/ja/intlayer_with_vite+react.md +5 -1
  26. package/docs/ko/eslint.md +336 -0
  27. package/docs/ko/intlayer_with_lynx+react.md +4 -0
  28. package/docs/ko/intlayer_with_react_router_v7_fs_routes.md +1 -1
  29. package/docs/ko/intlayer_with_storybook.md +5 -5
  30. package/docs/nl/eslint.md +336 -0
  31. package/docs/pl/eslint.md +336 -0
  32. package/docs/pl/intlayer_with_astro.md +1 -114
  33. package/docs/pl/migration_from_i18next_to_intlayer.md +4 -0
  34. package/docs/pl/migration_from_next-i18next_to_intlayer.md +8 -4
  35. package/docs/pl/migration_from_next-intl_to_intlayer.md +11 -5
  36. package/docs/pl/migration_from_nuxtjs_i18n_to_intlayer.md +8 -4
  37. package/docs/pl/migration_from_react-i18next_to_intlayer.md +8 -4
  38. package/docs/pl/migration_from_vue-i18n_to_intlayer.md +4 -0
  39. package/docs/pt/eslint.md +336 -0
  40. package/docs/pt/intlayer_with_astro.md +1 -114
  41. package/docs/ru/eslint.md +336 -0
  42. package/docs/tr/eslint.md +336 -0
  43. package/docs/uk/eslint.md +336 -0
  44. package/docs/uk/packages/angular-intlayer/exports.md +2 -2
  45. package/docs/ur/eslint.md +336 -0
  46. package/docs/vi/eslint.md +336 -0
  47. package/docs/zh/eslint.md +336 -0
  48. package/docs/zh/intlayer_with_create_react_app.md +4 -0
  49. package/docs/zh/intlayer_with_lynx+react.md +4 -0
  50. package/docs/zh/intlayer_with_nextjs_14.md +0 -2
  51. package/docs/zh/intlayer_with_nextjs_15.md +0 -2
  52. package/docs/zh/intlayer_with_nextjs_page_router.md +0 -2
  53. package/docs/zh/intlayer_with_nuxt.md +1 -1
  54. package/docs/zh/intlayer_with_react_router_v7.md +4 -0
  55. package/docs/zh/intlayer_with_react_router_v7_fs_routes.md +4 -0
  56. package/docs/zh/intlayer_with_solid_start.md +1 -1
  57. package/docs/zh/intlayer_with_vite+vue.md +0 -2
  58. package/docs/zh-TW/eslint.md +336 -0
  59. package/package.json +6 -6
  60. package/src/generated/docs.entry.ts +20 -0
@@ -0,0 +1,336 @@
1
+ ---
2
+ createdAt: 2026-08-12
3
+ updatedAt: 2026-08-12
4
+ title: ESLint Plugin | Lint-regels voor Intlayer
5
+ description: Detecteer hardgecodeerde strings, dynamische aanroepen die de Intlayer-compiler niet kan optimaliseren en ongebruikte woordenboekinhoud met eslint-plugin-intlayer. Werkt met ESLint en oxlint op React, Vue, Svelte, Angular en Astro.
6
+ keywords:
7
+ - Intlayer
8
+ - ESLint
9
+ - oxlint
10
+ - Linting
11
+ - i18n
12
+ - Internationalisering
13
+ - no-raw-text
14
+ - Hardgecodeerde strings
15
+ - Ongebruikte vertalingen
16
+ - Dode inhoud
17
+ - React
18
+ - Vue
19
+ - Svelte
20
+ - Angular
21
+ slugs:
22
+ - doc
23
+ - eslint
24
+ history:
25
+ - version: 9.3.1
26
+ date: 2026-08-12
27
+ changes: "Initiële geschiedenis"
28
+ author: aymericzip
29
+ ---
30
+
31
+ # ESLint x OXLint Plugin
32
+
33
+ `eslint-plugin-intlayer` detecteert het soort i18n-fouten dat TypeScript niet kan opmerken:
34
+
35
+ 1. **Hardgecodeerde tekst** die nooit in een woordenboek is opgenomen.
36
+ 2. **Dynamische aanroepen** die type-checks doorstaan en functioneren, maar die de Intlayer-compiler niet kan optimaliseren.
37
+ 3. **Dode inhoud (Dead content)** — woordenboeken en velden die nergens in het project worden gelezen (opt-in).
38
+
39
+ Onbekende woordenboeksleutels, onbekende veldpaden en ontbrekende locales zijn al compilatiefouten, dus de plugin herhaalt deze niet.
40
+
41
+ ## Installatie
42
+
43
+ ```bash packageManager="npm"
44
+ npm install --save-dev eslint-plugin-intlayer
45
+ ```
46
+
47
+ ```bash packageManager="pnpm"
48
+ pnpm add --save-dev eslint-plugin-intlayer
49
+ ```
50
+
51
+ ```bash packageManager="yarn"
52
+ yarn add --dev eslint-plugin-intlayer
53
+ ```
54
+
55
+ Vereist ESLint 9 of nieuwer (flat config).
56
+
57
+ ## Gebruik
58
+
59
+ De plugin werkt in zowel ESLint als [oxlint](https://oxc.rs) — dezelfde regels, dezelfde opties.
60
+
61
+ <Tabs defaultTab="eslint">
62
+ <Tab label="ESLint" value="eslint">
63
+
64
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
65
+ import intlayer from "eslint-plugin-intlayer";
66
+
67
+ export default [...intlayer.configs.recommended];
68
+ ```
69
+
70
+ Of schakel regels één voor één in:
71
+
72
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
73
+ import intlayer from "eslint-plugin-intlayer";
74
+
75
+ export default [
76
+ {
77
+ plugins: { intlayer },
78
+ rules: {
79
+ "intlayer/no-raw-text": "warn",
80
+ "intlayer/static-dictionary-key": "error",
81
+ "intlayer/no-dynamic-field-access": "error",
82
+ "intlayer/enforce-adapter-import": "warn",
83
+ "intlayer/no-unused-content": "warn",
84
+ },
85
+ },
86
+ ];
87
+ ```
88
+
89
+ </Tab>
90
+ <Tab label="oxlint" value="oxlint">
91
+
92
+ ```json fileName=".oxlintrc.json"
93
+ {
94
+ "jsPlugins": ["eslint-plugin-intlayer"],
95
+ "rules": {
96
+ "intlayer/no-raw-text": "warn",
97
+ "intlayer/static-dictionary-key": "error",
98
+ "intlayer/no-dynamic-field-access": "error",
99
+ "intlayer/enforce-adapter-import": "warn"
100
+ }
101
+ }
102
+ ```
103
+
104
+ Twee kanttekeningen: de JS-pluginondersteuning in oxlint is nog in alfa en oxlint ondersteunt geen aangepaste parsers — dus `.vue`-, `.svelte`-, `.astro`-bestanden en Angular-templates worden daar niet gecontroleerd. Voer oxlint uit op uw JS/TS/JSX-bestanden en behoud ESLint voor de rest.
105
+
106
+ `no-unused-content` is hierboven opzettelijk weggelaten: het vereist de werkmap en het gecontroleerde bestandspad uit de regelcontext, wat de alfa JS-plugin-bridge niet garandeert. Voer dit uit onder ESLint.
107
+
108
+ </Tab>
109
+ </Tabs>
110
+
111
+ ### Configuraties
112
+
113
+ | Configuratie | `no-raw-text` | `static-dictionary-key` | `no-dynamic-field-access` | `enforce-adapter-import` | `no-unused-content` |
114
+ | --------------- | --------------------------- | ----------------------- | ------------------------- | ------------------------ | ------------------- |
115
+ | `recommended` | warn | error | error | off | off |
116
+ | `strict` | error (+ niet-JSX literals) | error | error | error | off |
117
+ | `contract-only` | off | error | error | off | off |
118
+
119
+ `recommended` houdt `no-raw-text` opzettelijk op `warn`: als u dit toepast op een bestaande codebase, worden alle onvertaalde strings in één keer zichtbaar, wat uw build niet vanaf dag één zou moeten laten mislukken.
120
+
121
+ `enforce-adapter-import` staat standaard uit — schakel dit expliciet in als u het wilt gebruiken.
122
+
123
+ `no-unused-content` staat uit in elke configuratie, inclusief `strict`. Het is de enige regel die uw Intlayer-configuratie leest en bronbestanden van schijf doorzoekt, dus het inschakelen ervan moet een bewuste keuze zijn in plaats van iets wat een preset automatisch doet.
124
+
125
+ ## Regels
126
+
127
+ ### `no-raw-text`
128
+
129
+ Meldt gebruikersgerichte tekst die niet in een woordenboek is gedeclareerd. Het gebruikt dezelfde detectie als `intlayer extract`, waardoor merknamen, CSS-klassen en technische identifiers worden genegeerd.
130
+
131
+ ```jsx
132
+ // ✗ Gemeld
133
+ <h1>Welcome to our documentation</h1>
134
+ <input placeholder="Enter your email address" />
135
+
136
+ // ✓ Goed
137
+ const { title } = useIntlayer("home");
138
+ <h1>{title}</h1>
139
+ ```
140
+
141
+ Bestanden voor inhoudsdeclaratie (`*.content.ts`, …) worden overgeslagen.
142
+
143
+ Om een heel bestand in één keer te herstellen, voert u `npx intlayer extract` uit en laat u de compiler de strings voor u naar een woordenboek verplaatsen.
144
+
145
+ **Opties**
146
+
147
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
148
+ {
149
+ "intlayer/no-raw-text": [
150
+ "warn",
151
+ {
152
+ // Attributen waarvan de waarde gebruikersgerichte tekst is.
153
+ // Standaard: title, placeholder, alt, aria-label, label
154
+ attributes: ["title", "placeholder", "alt", "aria-label", "label"],
155
+
156
+ // Elementen waarvan de inhoud nooit gebruikersgerichte tekst is.
157
+ // Standaard: code, pre, script, style
158
+ ignoreElements: ["code", "pre", "script", "style"],
159
+
160
+ // Reguliere expressies voor tekst die nooit gemeld mag worden.
161
+ ignorePatterns: ["^Powered by"],
162
+
163
+ // Meld ook string-literals buiten markup. Standaard: false
164
+ includeStringLiterals: false,
165
+ },
166
+ ],
167
+ }
168
+ ```
169
+
170
+ ### `static-dictionary-key`
171
+
172
+ Vereist dat de woordenboeksleutel een string-literal is.
173
+
174
+ De compiler kan een woordenboek alleen vooraf laden wanneer deze de sleutel direct op de aanroeplocatie kan lezen. Bij een berekende sleutel wordt de optimalisatie stilzwijgend overgeslagen en worden in plaats daarvan alle woordenboeken gebundeld.
175
+
176
+ ```typescript
177
+ // ✗ Gemeld
178
+ useIntlayer(dictionaryKey);
179
+ useIntlayer(`home-${suffix}`);
180
+ getTranslations({ namespace: page });
181
+
182
+ // ✗ Een variabele is nog steeds geen literal
183
+ const key = "home";
184
+ useIntlayer(key);
185
+
186
+ // ✓ Goed
187
+ useIntlayer("home");
188
+ getTranslations({ namespace: "home" });
189
+ ```
190
+
191
+ Dit geldt voor `useIntlayer`, `getIntlayer` en elke compatibiliteitsadapter (`useTranslation`, `useTranslations`, `formatMessage`, `<FormattedMessage id>`, `<Trans i18nKey>`, …).
192
+
193
+ ### `no-dynamic-field-access`
194
+
195
+ Vereist dat het veld dat u uit een woordenboek leest statisch bekend is.
196
+
197
+ De compiler verwijdert velden waarvan hij niet ziet dat ze worden gebruikt. Een dynamisch berekende toegang is onzichtbaar voor de compiler, waardoor het lezen tijdens runtime `undefined` kan retourneren.
198
+
199
+ ```typescript
200
+ // ✗ Gemeld
201
+ const content = useIntlayer("home");
202
+ content[fieldName];
203
+
204
+ const t = useTranslations("home");
205
+ t(messageKey);
206
+
207
+ // ✓ Goed
208
+ content.title;
209
+ content["title"];
210
+ content.items[0];
211
+ t("hero.title");
212
+ ```
213
+
214
+ ### `enforce-adapter-import`
215
+
216
+ Geeft de voorkeur aan de `@intlayer/*` compatibiliteitsadapter boven het originele pakket. Het origineel verwijst alleen naar Intlayer als de bundler-alias is geconfigureerd; de adapter doet dit altijd. Automatisch te herstellen met `--fix`.
217
+
218
+ ```typescript
219
+ // ✗ Gemeld
220
+ import { useTranslation } from "react-i18next";
221
+ import { getTranslations } from "next-intl/server";
222
+
223
+ // ✓ Goed
224
+ import { useTranslation } from "@intlayer/react-i18next";
225
+ import { getTranslations } from "@intlayer/next-intl/server";
226
+ ```
227
+
228
+ ### `no-unused-content`
229
+
230
+ **Standaard uitgeschakeld.** Meldt inhoud die nergens in uw project wordt gelezen, plus woordenboeksleutels die op meer dan één plek zijn gedeclareerd.
231
+
232
+ ```typescript fileName="src/home.content.ts"
233
+ export default {
234
+ key: "home", // ✗ Gemeld wanneer geen enkele aanroeper in het project om "home" vraagt
235
+ content: {
236
+ title: t({ nl: "Titel", en: "Title" }),
237
+
238
+ // ✗ Gemeld wanneer niets `hero` leest
239
+ hero: {
240
+ subtitle: t({ nl: "Subtitel", en: "Subtitle" }),
241
+ },
242
+ },
243
+ };
244
+ ```
245
+
246
+ In tegenstelling tot de andere regels kan deze regel niet alleen oordelen op basis van het geopende bestand — een veld is alleen ongebruikt ten opzichte van het hele project. Bij de eerste inhoudsdeclaratie van een lint-run laadt deze uw Intlayer-configuratie, scant de bronbestanden die de configuratie declareert (`build.traversePattern`, `compiler.transformPattern`) en voert dezelfde gebruiksanalysator uit die `@intlayer/lsp` en de doorhaling "ongebruikt" in de VS Code-extensie aandrijft. Het resultaat wordt gedurende `cacheTtl` milliseconden in de cache opgeslagen, zodat de scan eenmaal per run plaatsvindt in plaats van per bestand.
247
+
248
+ **Opties**
249
+
250
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
251
+ {
252
+ "intlayer/no-unused-content": [
253
+ "warn",
254
+ {
255
+ // Meld woordenboeksleutels waarnaar niets verwijst. Standaard: true
256
+ reportUnusedDictionaries: true,
257
+
258
+ // Meld inhoudsvelden die niets leest. Standaard: true
259
+ reportUnusedFields: true,
260
+
261
+ // Meld sleutels die op meer dan één plek zijn gedeclareerd. Standaard: true
262
+ reportDuplicateKeys: true,
263
+
264
+ // Reguliere expressies voor veldpaden die nooit gemeld mogen worden.
265
+ ignoreFields: ["^meta"],
266
+
267
+ // Projectroot waar de scan begint. Standaard: de werkmap van ESLint
268
+ baseDir: process.cwd(),
269
+
270
+ // Hoe lang een projectscan wordt hergebruikt, in ms. Standaard: 30000
271
+ cacheTtl: 30000,
272
+ },
273
+ ],
274
+ }
275
+ ```
276
+
277
+ Verlaag `cacheTtl` wanneer u lint vanuit een langlopende editorserver en wilt dat bewerkingen sneller worden weergegeven; stel `baseDir` in wanneer een enkele lint-run meerdere Intlayer-projecten in een monorepo omvat.
278
+
279
+ > **Neigt naar stilte.** Een vals-positief resultaat zou hier een vertaling verwijderen, dus er wordt niets gemeld wanneer het woordenboek wordt gebruikt op een manier die de analyse niet kan volgen: het inhoudsobject in zijn geheel doorgegeven, een vertaalfunctie die eraan is gebonden (`const t = useTranslations("home")`), een declaratie bereikt via een directe import (`useDictionary(myDictionary)`), een `nest()` vanuit een ander woordenboek of een veldenlijst die niet-exhaustief is gemaakt door een spread. Single-file componenten (`.vue`, `.svelte`, `.astro`) tellen alsof ze elk veld gebruiken van de woordenboeken die ze vermelden, omdat hun scriptblokken hier niet worden geparseerd.
280
+
281
+ `reportDuplicateKeys` leest de niet-samengevoegde woordenboeken die de build wegschrijft onder `.intlayer/`, dus het blijft stil totdat het project ten minste eenmaal is gebouwd. Twee declaraties die een sleutel delen worden samengevoegd, wat een legitiem patroon is — het rapport bestaat omdat een veld dat aan beide zijden is gedefinieerd stilzwijgend slechts een van de twee waarden behoudt.
282
+
283
+ De analyser wordt geladen vanuit `@intlayer/lsp`, dat als ESM wordt gedistribueerd. De regel vereist daarom een Node-versie die een ES-module kan `require()`-en — Node 20.19+ of 22.12+. Op oudere versies meldt het niets in plaats van de lint-run te laten mislukken.
284
+
285
+ ## Frameworks
286
+
287
+ Elke regel werkt in alle Intlayer-integraties, inclusief binnen Vue-, Svelte- en Angular-templates. U hoeft ESLint alleen te vertellen welke parser elk bestandstype leest.
288
+
289
+ | Framework | Bestanden | Parser |
290
+ | ------------------------- | ----------------- | --------------------------------- |
291
+ | React, Preact, Solid, Lit | `.jsx` `.tsx` | `typescript-eslint` |
292
+ | Next.js | `.jsx` `.tsx` | `typescript-eslint` |
293
+ | Vue, Nuxt | `.vue` | `vue-eslint-parser` |
294
+ | Svelte, SvelteKit | `.svelte` | `svelte-eslint-parser` |
295
+ | Angular | `.ts` | `typescript-eslint` |
296
+ | Angular-templates | `.component.html` | `@angular-eslint/template-parser` |
297
+ | Astro | `.astro` | `astro-eslint-parser` |
298
+
299
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
300
+ import intlayer from "eslint-plugin-intlayer";
301
+ import tseslint from "typescript-eslint";
302
+ import vueParser from "vue-eslint-parser";
303
+ import svelteParser from "svelte-eslint-parser";
304
+ import angularTemplateParser from "@angular-eslint/template-parser";
305
+
306
+ export default [
307
+ ...intlayer.configs.recommended,
308
+
309
+ {
310
+ files: ["**/*.{ts,tsx,jsx}"],
311
+ languageOptions: { parser: tseslint.parser },
312
+ },
313
+ {
314
+ files: ["**/*.vue"],
315
+ languageOptions: {
316
+ parser: vueParser,
317
+ parserOptions: { parser: tseslint.parser },
318
+ },
319
+ },
320
+ {
321
+ files: ["**/*.svelte"],
322
+ languageOptions: {
323
+ parser: svelteParser,
324
+ parserOptions: { parser: tseslint.parser },
325
+ },
326
+ },
327
+ {
328
+ files: ["**/*.component.html"],
329
+ languageOptions: { parser: angularTemplateParser },
330
+ },
331
+ ];
332
+ ```
333
+
334
+ Installeer alleen de parsers die uw project nodig heeft.
335
+
336
+ > **Bekende beperking.** In Vue- en Angular-templates wordt een expressie zoals `{{ content[key] }}` niet gecontroleerd door `no-dynamic-field-access`. Dynamische aanroepen geschreven in het scriptblok worden normaal opgevangen.
@@ -0,0 +1,336 @@
1
+ ---
2
+ createdAt: 2026-08-12
3
+ updatedAt: 2026-08-12
4
+ title: Wtyczka ESLint | Reguły lintera dla Intlayer
5
+ description: Wykrywaj zahardkodowane ciągi znaków, wywołania dynamiczne, których kompilator Intlayer nie jest w stanie zoptymalizować, oraz nieużywaną zawartość słowników dzięki eslint-plugin-intlayer. Działa z ESLint i oxlint w React, Vue, Svelte, Angular i Astro.
6
+ keywords:
7
+ - Intlayer
8
+ - ESLint
9
+ - oxlint
10
+ - Linting
11
+ - i18n
12
+ - Internacjonalizacja
13
+ - no-raw-text
14
+ - Zahardkodowane ciągi znaków
15
+ - Nieużywane tłumaczenia
16
+ - Martwa zawartość
17
+ - React
18
+ - Vue
19
+ - Svelte
20
+ - Angular
21
+ slugs:
22
+ - doc
23
+ - eslint
24
+ history:
25
+ - version: 9.3.1
26
+ date: 2026-08-12
27
+ changes: "Inicjalna historia"
28
+ author: aymericzip
29
+ ---
30
+
31
+ # Wtyczka ESLint x OXLint
32
+
33
+ `eslint-plugin-intlayer` wychwytuje rodzaje błędów i18n, których TypeScript nie jest w stanie wykryć:
34
+
35
+ 1. **Zahardkodowany tekst**, który nigdy nie trafił do słownika.
36
+ 2. **Dynamiczne wywołania**, które przechodzą sprawdzanie typów i działają, ale których kompilator Intlayer nie potrafi zoptymalizować.
37
+ 3. **Martwa zawartość (Dead content)** — słowniki i pola, których nic w projekcie nie odczytuje (opcjonalne).
38
+
39
+ 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.
40
+
41
+ ## Instalacja
42
+
43
+ ```bash packageManager="npm"
44
+ npm install --save-dev eslint-plugin-intlayer
45
+ ```
46
+
47
+ ```bash packageManager="pnpm"
48
+ pnpm add --save-dev eslint-plugin-intlayer
49
+ ```
50
+
51
+ ```bash packageManager="yarn"
52
+ yarn add --dev eslint-plugin-intlayer
53
+ ```
54
+
55
+ Wymaga ESLint w wersji 9 lub nowszej (flat config).
56
+
57
+ ## Użycie
58
+
59
+ Wtyczka działa zarówno w ESLint, jak i [oxlint](https://oxc.rs) — te same reguły, te same opcje.
60
+
61
+ <Tabs defaultTab="eslint">
62
+ <Tab label="ESLint" value="eslint">
63
+
64
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
65
+ import intlayer from "eslint-plugin-intlayer";
66
+
67
+ export default [...intlayer.configs.recommended];
68
+ ```
69
+
70
+ Lub włączaj reguły pojedynczo:
71
+
72
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
73
+ import intlayer from "eslint-plugin-intlayer";
74
+
75
+ export default [
76
+ {
77
+ plugins: { intlayer },
78
+ rules: {
79
+ "intlayer/no-raw-text": "warn",
80
+ "intlayer/static-dictionary-key": "error",
81
+ "intlayer/no-dynamic-field-access": "error",
82
+ "intlayer/enforce-adapter-import": "warn",
83
+ "intlayer/no-unused-content": "warn",
84
+ },
85
+ },
86
+ ];
87
+ ```
88
+
89
+ </Tab>
90
+ <Tab label="oxlint" value="oxlint">
91
+
92
+ ```json fileName=".oxlintrc.json"
93
+ {
94
+ "jsPlugins": ["eslint-plugin-intlayer"],
95
+ "rules": {
96
+ "intlayer/no-raw-text": "warn",
97
+ "intlayer/static-dictionary-key": "error",
98
+ "intlayer/no-dynamic-field-access": "error",
99
+ "intlayer/enforce-adapter-import": "warn"
100
+ }
101
+ }
102
+ ```
103
+
104
+ Dwa zastrzeżenia: obsługa wtyczek JS w oxlint jest w fazie alfa, a oxlint nie obsługuje niestandardowych parserów — pliki `.vue`, `.svelte`, `.astro` oraz szablony Angular nie są tam sprawdzane. Uruchamiaj oxlint na plikach JS/TS/JSX, a ESLint pozostaw dla reszty.
105
+
106
+ Reguła `no-unused-content` została celowo pominięta powyżej: wymaga ona katalogu roboczego i ścieżki do sprawdzanego pliku z kontekstu reguły, czego mostek wtyczek JS w fazie alfa nie gwarantuje. Uruchamiaj ją pod ESLintem.
107
+
108
+ </Tab>
109
+ </Tabs>
110
+
111
+ ### Konfiguracje
112
+
113
+ | Konfiguracja | `no-raw-text` | `static-dictionary-key` | `no-dynamic-field-access` | `enforce-adapter-import` | `no-unused-content` |
114
+ | --------------- | --------------------------- | ----------------------- | ------------------------- | ------------------------ | ------------------- |
115
+ | `recommended` | warn | error | error | off | off |
116
+ | `strict` | error (+ literały poza JSX) | error | error | error | off |
117
+ | `contract-only` | off | error | error | off | off |
118
+
119
+ `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.
120
+
121
+ `enforce-adapter-import` jest domyślnie wyłączona — włącz ją jawnie, jeśli tego potrzebujesz.
122
+
123
+ `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.
124
+
125
+ ## Reguły
126
+
127
+ ### `no-raw-text`
128
+
129
+ 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.
130
+
131
+ ```jsx
132
+ // ✗ Zgłoszone
133
+ <h1>Welcome to our documentation</h1>
134
+ <input placeholder="Enter your email address" />
135
+
136
+ // ✓ Prawidłowo
137
+ const { title } = useIntlayer("home");
138
+ <h1>{title}</h1>
139
+ ```
140
+
141
+ Pliki deklaracji zawartości (`*.content.ts`, …) są pomijane.
142
+
143
+ Aby naprawić cały plik naraz, uruchom `npx intlayer extract`, a kompilator automatycznie przeniesie ciągi znaków do słownika.
144
+
145
+ **Opcje**
146
+
147
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
148
+ {
149
+ "intlayer/no-raw-text": [
150
+ "warn",
151
+ {
152
+ // Atrybuty, których wartością jest tekst widoczny dla użytkownika.
153
+ // Domyślnie: title, placeholder, alt, aria-label, label
154
+ attributes: ["title", "placeholder", "alt", "aria-label", "label"],
155
+
156
+ // Elementy, których zawartość nigdy nie jest tekstem widocznym dla użytkownika.
157
+ // Domyślnie: code, pre, script, style
158
+ ignoreElements: ["code", "pre", "script", "style"],
159
+
160
+ // Wyrażenia regularne dla tekstu, który nigdy nie powinien być zgłaszany.
161
+ ignorePatterns: ["^Powered by"],
162
+
163
+ // Zgłaszaj także literały łańcuchowe poza markupem. Domyślnie: false
164
+ includeStringLiterals: false,
165
+ },
166
+ ],
167
+ }
168
+ ```
169
+
170
+ ### `static-dictionary-key`
171
+
172
+ Wymaga, aby klucz słownika był literałem łańcuchowym.
173
+
174
+ 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.
175
+
176
+ ```typescript
177
+ // ✗ Zgłoszone
178
+ useIntlayer(dictionaryKey);
179
+ useIntlayer(`home-${suffix}`);
180
+ getTranslations({ namespace: page });
181
+
182
+ // ✗ Zmienna nadal nie jest literałem
183
+ const key = "home";
184
+ useIntlayer(key);
185
+
186
+ // ✓ Prawidłowo
187
+ useIntlayer("home");
188
+ getTranslations({ namespace: "home" });
189
+ ```
190
+
191
+ Dotyczy to `useIntlayer`, `getIntlayer` oraz każdego adaptera kompatybilności (`useTranslation`, `useTranslations`, `formatMessage`, `<FormattedMessage id>`, `<Trans i18nKey>`, …).
192
+
193
+ ### `no-dynamic-field-access`
194
+
195
+ Wymaga, aby pole odczytywane ze słownika było znane statycznie.
196
+
197
+ 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.
198
+
199
+ ```typescript
200
+ // ✗ Zgłoszone
201
+ const content = useIntlayer("home");
202
+ content[fieldName];
203
+
204
+ const t = useTranslations("home");
205
+ t(messageKey);
206
+
207
+ // ✓ Prawidłowo
208
+ content.title;
209
+ content["title"];
210
+ content.items[0];
211
+ t("hero.title");
212
+ ```
213
+
214
+ ### `enforce-adapter-import`
215
+
216
+ 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`.
217
+
218
+ ```typescript
219
+ // ✗ Zgłoszone
220
+ import { useTranslation } from "react-i18next";
221
+ import { getTranslations } from "next-intl/server";
222
+
223
+ // ✓ Prawidłowo
224
+ import { useTranslation } from "@intlayer/react-i18next";
225
+ import { getTranslations } from "@intlayer/next-intl/server";
226
+ ```
227
+
228
+ ### `no-unused-content`
229
+
230
+ **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.
231
+
232
+ ```typescript fileName="src/home.content.ts"
233
+ export default {
234
+ key: "home", // ✗ Zgłaszane, gdy żadne wywołanie w projekcie nie odpytuje o "home"
235
+ content: {
236
+ title: t({ pl: "Tytuł", en: "Title" }),
237
+
238
+ // ✗ Zgłaszane, gdy nic nie odczytuje `hero`
239
+ hero: {
240
+ subtitle: t({ pl: "Podtytuł", en: "Subtitle" }),
241
+ },
242
+ },
243
+ };
244
+ ```
245
+
246
+ 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.
247
+
248
+ **Opcje**
249
+
250
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
251
+ {
252
+ "intlayer/no-unused-content": [
253
+ "warn",
254
+ {
255
+ // Zgłaszaj klucze słowników, do których nic się nie odwołuje. Domyślnie: true
256
+ reportUnusedDictionaries: true,
257
+
258
+ // Zgłaszaj pola zawartości, których nic nie odczytuje. Domyślnie: true
259
+ reportUnusedFields: true,
260
+
261
+ // Zgłaszaj klucze zadeklarowane w więcej niż jednym miejscu. Domyślnie: true
262
+ reportDuplicateKeys: true,
263
+
264
+ // Wyrażenia regularne dla ścieżek pól, które nigdy nie powinny być zgłaszane.
265
+ ignoreFields: ["^meta"],
266
+
267
+ // Katalog główny projektu, od którego zaczyna się skanowanie. Domyślnie: katalog roboczy ESLint
268
+ baseDir: process.cwd(),
269
+
270
+ // Czas ponownego użycia skanu projektu (w ms). Domyślnie: 30000
271
+ cacheTtl: 30000,
272
+ },
273
+ ],
274
+ }
275
+ ```
276
+
277
+ 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.
278
+
279
+ > **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.
280
+
281
+ `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.
282
+
283
+ 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.
284
+
285
+ ## Frameworki
286
+
287
+ 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.
288
+
289
+ | Framework | Pliki | Parser |
290
+ | ------------------------- | ----------------- | --------------------------------- |
291
+ | React, Preact, Solid, Lit | `.jsx` `.tsx` | `typescript-eslint` |
292
+ | Next.js | `.jsx` `.tsx` | `typescript-eslint` |
293
+ | Vue, Nuxt | `.vue` | `vue-eslint-parser` |
294
+ | Svelte, SvelteKit | `.svelte` | `svelte-eslint-parser` |
295
+ | Angular | `.ts` | `typescript-eslint` |
296
+ | Szablony Angular | `.component.html` | `@angular-eslint/template-parser` |
297
+ | Astro | `.astro` | `astro-eslint-parser` |
298
+
299
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
300
+ import intlayer from "eslint-plugin-intlayer";
301
+ import tseslint from "typescript-eslint";
302
+ import vueParser from "vue-eslint-parser";
303
+ import svelteParser from "svelte-eslint-parser";
304
+ import angularTemplateParser from "@angular-eslint/template-parser";
305
+
306
+ export default [
307
+ ...intlayer.configs.recommended,
308
+
309
+ {
310
+ files: ["**/*.{ts,tsx,jsx}"],
311
+ languageOptions: { parser: tseslint.parser },
312
+ },
313
+ {
314
+ files: ["**/*.vue"],
315
+ languageOptions: {
316
+ parser: vueParser,
317
+ parserOptions: { parser: tseslint.parser },
318
+ },
319
+ },
320
+ {
321
+ files: ["**/*.svelte"],
322
+ languageOptions: {
323
+ parser: svelteParser,
324
+ parserOptions: { parser: tseslint.parser },
325
+ },
326
+ },
327
+ {
328
+ files: ["**/*.component.html"],
329
+ languageOptions: { parser: angularTemplateParser },
330
+ },
331
+ ];
332
+ ```
333
+
334
+ Instaluj tylko te parsery, których wymaga Twój projekt.
335
+
336
+ > **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.