@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: Plugin ESLint | Aturan Lint untuk Intlayer
5
+ description: Deteksi string hardcoded, panggilan dinamis yang tidak dapat dioptimalkan oleh compiler Intlayer, dan konten kamus yang tidak terpakai dengan eslint-plugin-intlayer. Bekerja dengan ESLint dan oxlint di seluruh React, Vue, Svelte, Angular, dan Astro.
6
+ keywords:
7
+ - Intlayer
8
+ - ESLint
9
+ - oxlint
10
+ - Linting
11
+ - i18n
12
+ - Internasionalisasi
13
+ - no-raw-text
14
+ - String hardcoded
15
+ - Terjemahan tidak terpakai
16
+ - Konten mati
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: "Riwayat awal"
28
+ author: aymericzip
29
+ ---
30
+
31
+ # Plugin ESLint x OXLint
32
+
33
+ `eslint-plugin-intlayer` menangkap jenis kesalahan i18n yang tidak dapat dideteksi oleh TypeScript:
34
+
35
+ 1. **Teks hardcoded** yang tidak pernah dimasukkan ke dalam kamus.
36
+ 2. **Panggilan dinamis** yang lolos pemeriksaan tipe dan berjalan, namun tidak dapat dioptimalkan oleh compiler Intlayer.
37
+ 3. **Konten mati (Dead content)** — kamus dan field yang tidak dibaca oleh apa pun di dalam proyek (opsional/opt-in).
38
+
39
+ Kunci kamus yang tidak diketahui, path field yang tidak diketahui, dan locale yang hilang sudah merupakan kesalahan kompilasi, sehingga plugin tidak mengulanginya.
40
+
41
+ ## Instalasi
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
+ Memerlukan ESLint 9 atau lebih baru (flat config).
56
+
57
+ ## Penggunaan
58
+
59
+ Plugin ini berjalan di ESLint dan [oxlint](https://oxc.rs) — aturan yang sama, opsi yang sama.
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
+ Atau aktifkan aturan satu per satu:
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
+ Dua catatan: dukungan plugin JS di oxlint masih berstatus alfa, dan oxlint tidak mendukung parser kustom — sehingga file `.vue`, `.svelte`, `.astro`, dan template Angular tidak diperiksa di sana. Jalankan oxlint untuk file JS/TS/JSX Anda dan gunakan ESLint untuk sisanya.
105
+
106
+ `no-unused-content` sengaja tidak disertakan di atas: aturan ini memerlukan direktori kerja dan path file yang diperiksa dari konteks aturan, yang belum dijamin oleh bridge plugin JS alfa. Jalankan aturan ini di bawah ESLint.
107
+
108
+ </Tab>
109
+ </Tabs>
110
+
111
+ ### Konfigurasi
112
+
113
+ | Konfigurasi | `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 (+ literal non-JSX) | error | error | error | off |
117
+ | `contract-only` | off | error | error | off | off |
118
+
119
+ `recommended` sengaja menetapkan `no-raw-text` pada `warn`: menerapkannya pada codebase yang ada akan menampilkan semua string yang belum diterjemahkan sekaligus, yang seharusnya tidak merusak proses build Anda pada hari pertama.
120
+
121
+ `enforce-adapter-import` dinonaktifkan secara default — aktifkan secara eksplisit jika Anda menginginkannya.
122
+
123
+ `no-unused-content` dinonaktifkan di setiap konfigurasi, termasuk `strict`. Ini adalah satu-satunya aturan yang membaca konfigurasi Intlayer Anda dan memindai file sumber dari disk, jadi mengaktifkannya harus menjadi pilihan yang disengaja daripada sesuatu yang dilakukan preset secara otomatis.
124
+
125
+ ## Aturan
126
+
127
+ ### `no-raw-text`
128
+
129
+ Melaporkan teks yang ditampilkan kepada pengguna yang tidak dideklarasikan dalam kamus. Aturan ini menggunakan deteksi yang sama dengan `intlayer extract`, sehingga nama merek, class CSS, dan identifier teknis diabaikan.
130
+
131
+ ```jsx
132
+ // ✗ Dilaporkan
133
+ <h1>Welcome to our documentation</h1>
134
+ <input placeholder="Enter your email address" />
135
+
136
+ // ✓ Benar
137
+ const { title } = useIntlayer("home");
138
+ <h1>{title}</h1>
139
+ ```
140
+
141
+ File deklarasi konten (`*.content.ts`, …) dilewati.
142
+
143
+ Untuk memperbaiki seluruh file sekaligus, jalankan `npx intlayer extract` dan biarkan compiler memindahkan string ke dalam kamus untuk Anda.
144
+
145
+ **Opsi**
146
+
147
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
148
+ {
149
+ "intlayer/no-raw-text": [
150
+ "warn",
151
+ {
152
+ // Atribut yang nilainya berupa teks yang ditampilkan kepada pengguna.
153
+ // Default: title, placeholder, alt, aria-label, label
154
+ attributes: ["title", "placeholder", "alt", "aria-label", "label"],
155
+
156
+ // Elemen yang kontennya bukan teks yang ditampilkan kepada pengguna.
157
+ // Default: code, pre, script, style
158
+ ignoreElements: ["code", "pre", "script", "style"],
159
+
160
+ // Ekspresi reguler untuk teks yang tidak boleh dilaporkan.
161
+ ignorePatterns: ["^Powered by"],
162
+
163
+ // Laporkan juga literal string di luar markup. Default: false
164
+ includeStringLiterals: false,
165
+ },
166
+ ],
167
+ }
168
+ ```
169
+
170
+ ### `static-dictionary-key`
171
+
172
+ Mengharuskan kunci kamus berupa literal string.
173
+
174
+ Compiler hanya dapat memuat awal kamus ketika dapat membaca kunci secara langsung di lokasi pemanggilan. Dengan kunci yang dihitung, compiler secara diam-diam melewati optimasi dan menggabungkan setiap kamus sebagai gantinya.
175
+
176
+ ```typescript
177
+ // ✗ Dilaporkan
178
+ useIntlayer(dictionaryKey);
179
+ useIntlayer(`home-${suffix}`);
180
+ getTranslations({ namespace: page });
181
+
182
+ // ✗ Variabel tetap bukan literal
183
+ const key = "home";
184
+ useIntlayer(key);
185
+
186
+ // ✓ Benar
187
+ useIntlayer("home");
188
+ getTranslations({ namespace: "home" });
189
+ ```
190
+
191
+ Ini berlaku untuk `useIntlayer`, `getIntlayer`, dan setiap adapter kompatibilitas (`useTranslation`, `useTranslations`, `formatMessage`, `<FormattedMessage id>`, `<Trans i18nKey>`, …).
192
+
193
+ ### `no-dynamic-field-access`
194
+
195
+ Mengharuskan field yang Anda baca dari kamus diketahui secara statis.
196
+
197
+ Compiler menghapus field yang tidak terdeteksi digunakan. Akses yang dihitung tidak terlihat oleh compiler, sehingga pembacaan dapat menghasilkan `undefined` saat runtime.
198
+
199
+ ```typescript
200
+ // ✗ Dilaporkan
201
+ const content = useIntlayer("home");
202
+ content[fieldName];
203
+
204
+ const t = useTranslations("home");
205
+ t(messageKey);
206
+
207
+ // ✓ Benar
208
+ content.title;
209
+ content["title"];
210
+ content.items[0];
211
+ t("hero.title");
212
+ ```
213
+
214
+ ### `enforce-adapter-import`
215
+
216
+ Lebih memilih adapter kompatibilitas `@intlayer/*` daripada paket asli. Paket asli hanya me-resolve ke Intlayer ketika alias bundler dikonfigurasi; adapter selalu melakukannya. Dapat diperbaiki otomatis dengan `--fix`.
217
+
218
+ ```typescript
219
+ // ✗ Dilaporkan
220
+ import { useTranslation } from "react-i18next";
221
+ import { getTranslations } from "next-intl/server";
222
+
223
+ // ✓ Benar
224
+ import { useTranslation } from "@intlayer/react-i18next";
225
+ import { getTranslations } from "@intlayer/next-intl/server";
226
+ ```
227
+
228
+ ### `no-unused-content`
229
+
230
+ **Dinonaktifkan secara default.** Melaporkan konten yang tidak dibaca oleh apa pun di proyek Anda, ditambah kunci kamus yang dideklarasikan di lebih dari satu tempat.
231
+
232
+ ```typescript fileName="src/home.content.ts"
233
+ export default {
234
+ key: "home", // ✗ Dilaporkan jika tidak ada pemanggil di mana pun yang meminta "home"
235
+ content: {
236
+ title: t({ id: "Judul", en: "Title" }),
237
+
238
+ // ✗ Dilaporkan jika tidak ada yang membaca `hero`
239
+ hero: {
240
+ subtitle: t({ id: "Subjudul", en: "Subtitle" }),
241
+ },
242
+ },
243
+ };
244
+ ```
245
+
246
+ Berbeda dengan aturan lainnya, aturan ini tidak dapat mengambil keputusan hanya dari file yang sedang diperiksa — sebuah field hanya dianggap tidak digunakan secara relatif terhadap keseluruhan proyek. Pada deklarasi konten pertama dalam satu sesi lint, aturan ini memuat konfigurasi Intlayer Anda, memindai file sumber yang dideklarasikan konfigurasi tersebut (`build.traversePattern`, `compiler.transformPattern`), dan menjalankan penganalisis penggunaan yang sama yang menggerakkan `@intlayer/lsp` dan coretan "tidak digunakan" di ekstensi VS Code. Hasilnya di-cache selama `cacheTtl` milidetik, sehingga pemindaian terjadi sekali per sesi dan bukan per file.
247
+
248
+ **Opsi**
249
+
250
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
251
+ {
252
+ "intlayer/no-unused-content": [
253
+ "warn",
254
+ {
255
+ // Laporkan kunci kamus yang tidak direferensikan oleh apa pun. Default: true
256
+ reportUnusedDictionaries: true,
257
+
258
+ // Laporkan field konten yang tidak dibaca oleh apa pun. Default: true
259
+ reportUnusedFields: true,
260
+
261
+ // Laporkan kunci yang dideklarasikan di lebih dari satu tempat. Default: true
262
+ reportDuplicateKeys: true,
263
+
264
+ // Ekspresi reguler untuk path field yang tidak boleh dilaporkan.
265
+ ignoreFields: ["^meta"],
266
+
267
+ // Root proyek tempat pemindaian dimulai. Default: direktori kerja ESLint
268
+ baseDir: process.cwd(),
269
+
270
+ // Berapa lama satu pemindaian proyek digunakan kembali, dalam ms. Default: 30000
271
+ cacheTtl: 30000,
272
+ },
273
+ ],
274
+ }
275
+ ```
276
+
277
+ Kurangi `cacheTtl` jika Anda melakukan lint dari server editor jangka panjang dan ingin editan Anda terlihat lebih cepat; atur `baseDir` ketika satu sesi lint mencakup beberapa proyek Intlayer di dalam sebuah monorepo.
278
+
279
+ > **Cenderung memilih untuk diam.** Laporan positif palsu di sini dapat menghapus terjemahan, jadi tidak ada yang dilaporkan ketika kamus digunakan dengan cara yang tidak dapat diikuti oleh analisis: objek konten yang diteruskan secara utuh, fungsi penerjemah yang diikat darinya (`const t = useTranslations("home")`), deklarasi yang dijangkau melalui impor langsung (`useDictionary(myDictionary)`), sebuah `nest()` dari kamus lain, atau daftar field yang dibuat tidak lengkap oleh spread operator. Komponen file tunggal (`.vue`, `.svelte`, `.astro`) dihitung menggunakan setiap field dari kamus yang mereka sebutkan, karena blok skrip mereka tidak diparsing di sini.
280
+
281
+ `reportDuplicateKeys` membaca kamus yang belum digabungkan yang ditulis proses build di bawah `.intlayer/`, sehingga tetap diam sampai proyek dibangun setidaknya satu kali. Dua deklarasi yang berbagi kunci akan digabungkan, yang merupakan pola yang sah — laporan ini ada karena field yang ditentukan di kedua sisi secara diam-diam hanya menyimpan salah satu dari dua nilai.
282
+
283
+ Penganalisis dimuat dari `@intlayer/lsp`, yang didistribusikan sebagai ESM. Oleh karena itu, aturan ini memerlukan versi Node yang dapat melakukan `require()` pada modul ES — Node 20.19+ atau 22.12+. Pada versi yang lebih lama, aturan ini tidak melaporkan apa pun alih-alih menggagalkan sesi lint.
284
+
285
+ ## Framework
286
+
287
+ Setiap aturan berfungsi di semua integrasi Intlayer, termasuk di dalam template Vue, Svelte, dan Angular. Anda hanya perlu memberi tahu ESLint parser mana yang membaca setiap tipe file.
288
+
289
+ | Framework | File | 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
+ | Template 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
+ Instal hanya parser yang dibutuhkan proyek Anda.
335
+
336
+ > **Keterbatasan yang diketahui.** Dalam template Vue dan Angular, ekspresi seperti `{{ content[key] }}` tidak diperiksa oleh `no-dynamic-field-access`. Pembacaan dinamis yang ditulis dalam blok skrip tertangkap secara normal.
@@ -0,0 +1,336 @@
1
+ ---
2
+ createdAt: 2026-08-12
3
+ updatedAt: 2026-08-12
4
+ title: Plugin ESLint | Regole di lint per Intlayer
5
+ description: Rileva stringhe hardcoded, chiamate dinamiche che il compilatore Intlayer non può ottimizzare e contenuti di dizionario inutilizzati, con eslint-plugin-intlayer. Funziona con ESLint e oxlint, su React, Vue, Svelte, Angular e Astro.
6
+ keywords:
7
+ - Intlayer
8
+ - ESLint
9
+ - oxlint
10
+ - Linting
11
+ - i18n
12
+ - Internazionalizzazione
13
+ - no-raw-text
14
+ - Stringhe hardcoded
15
+ - Traduzioni inutilizzate
16
+ - Contenuto inutilizzato
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: "Cronologia iniziale"
28
+ author: aymericzip
29
+ ---
30
+
31
+ # Plugin ESLint x OXLint
32
+
33
+ `eslint-plugin-intlayer` rileva i tipi di errori i18n che TypeScript non può individuare:
34
+
35
+ 1. **Testo hardcoded** che non è mai stato inserito in un dizionario.
36
+ 2. **Chiamate dinamiche** che superano il controllo dei tipi e vengono eseguite, ma che il compilatore Intlayer non può ottimizzare.
37
+ 3. **Contenuto inutilizzato (dead content)** — dizionari e campi che nessun elemento nel progetto legge (attivazione opzionale).
38
+
39
+ Le chiavi di dizionario sconosciute, i percorsi di campo sconosciuti e le impostazioni internazionali mancanti sono già errori di compilazione, quindi il plugin non li ripete.
40
+
41
+ ## Installazione
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
+ Richiede ESLint 9 o versione successiva (flat config).
56
+
57
+ ## Utilizzo
58
+
59
+ Il plugin funziona sia in ESLint che in [oxlint](https://oxc.rs) — stesse regole, stesse opzioni.
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
+ Oppure abilita le regole una alla volta:
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
+ Due precisazioni: il supporto ai plugin JS in oxlint è ancora in versione alfa e oxlint non supporta parser personalizzati — quindi i file `.vue`, `.svelte`, `.astro` e i template Angular non vengono analizzati lì. Esegui oxlint sui tuoi file JS/TS/JSX e mantieni ESLint per il resto.
105
+
106
+ `no-unused-content` è intenzionalmente esclusa sopra: necessita della directory di lavoro e del percorso del file analizzato dal contesto della regola, cosa che il bridge alfa del plugin JS non garantisce. Eseguila sotto ESLint.
107
+
108
+ </Tab>
109
+ </Tabs>
110
+
111
+ ### Configurazioni
112
+
113
+ | Configurazione | `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 (+ letterali esterni a JSX) | error | error | error | off |
117
+ | `contract-only` | off | error | error | off | off |
118
+
119
+ `recommended` mantiene deliberatamente `no-raw-text` su `warn`: applicarla a una base di codice esistente fa emergere tutte le stringhe non tradotte contemporaneamente, il che non dovrebbe interrompere la build dal primo giorno.
120
+
121
+ `enforce-adapter-import` è disabilitata per impostazione predefinita — attivala esplicitamente se lo desideri.
122
+
123
+ `no-unused-content` è disattivata in ogni configurazione, inclusa `strict`. È l'unica regola che legge la configurazione di Intlayer ed esamina i file sorgente dal disco, pertanto la sua attivazione dovrebbe essere una scelta deliberata anziché un'impostazione predefinita.
124
+
125
+ ## Regole
126
+
127
+ ### `no-raw-text`
128
+
129
+ Segnala il testo rivolto all'utente che non è dichiarato in un dizionario. Utilizza lo stesso rilevamento di `intlayer extract`, pertanto i nomi di brand, le classi CSS e gli identificatori tecnici vengono ignorati.
130
+
131
+ ```jsx
132
+ // ✗ Segnalato
133
+ <h1>Welcome to our documentation</h1>
134
+ <input placeholder="Enter your email address" />
135
+
136
+ // ✓ Corretto
137
+ const { title } = useIntlayer("home");
138
+ <h1>{title}</h1>
139
+ ```
140
+
141
+ I file di dichiarazione del contenuto (`*.content.ts`, …) vengono ignorati.
142
+
143
+ Per correggere un intero file in una volta, esegui `npx intlayer extract` e lascia che il compilatore sposti le stringhe in un dizionario al posto tuo.
144
+
145
+ **Opzioni**
146
+
147
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
148
+ {
149
+ "intlayer/no-raw-text": [
150
+ "warn",
151
+ {
152
+ // Attributi il cui valore è testo rivolto all'utente.
153
+ // Predefinito: title, placeholder, alt, aria-label, label
154
+ attributes: ["title", "placeholder", "alt", "aria-label", "label"],
155
+
156
+ // Elementi il cui contenuto non è mai testo rivolto all'utente.
157
+ // Predefinito: code, pre, script, style
158
+ ignoreElements: ["code", "pre", "script", "style"],
159
+
160
+ // Espressioni regolari per il testo da non segnalare mai.
161
+ ignorePatterns: ["^Powered by"],
162
+
163
+ // Segnala anche i letterali di stringa fuori dal markup. Predefinito: false
164
+ includeStringLiterals: false,
165
+ },
166
+ ],
167
+ }
168
+ ```
169
+
170
+ ### `static-dictionary-key`
171
+
172
+ Richiede che la chiave del dizionario sia un valore letterale stringa.
173
+
174
+ Il compilatore può precaricare un dizionario solo quando può leggere la chiave direttamente nel punto di chiamata. Con una chiave calcolata, salta silenziosamente l'ottimizzazione e include invece tutti i dizionari nel bundle.
175
+
176
+ ```typescript
177
+ // ✗ Segnalato
178
+ useIntlayer(dictionaryKey);
179
+ useIntlayer(`home-${suffix}`);
180
+ getTranslations({ namespace: page });
181
+
182
+ // ✗ Una variabile non è un letterale
183
+ const key = "home";
184
+ useIntlayer(key);
185
+
186
+ // ✓ Corretto
187
+ useIntlayer("home");
188
+ getTranslations({ namespace: "home" });
189
+ ```
190
+
191
+ Questo vale per `useIntlayer`, `getIntlayer` e tutti gli adattatori di compatibilità (`useTranslation`, `useTranslations`, `formatMessage`, `<FormattedMessage id>`, `<Trans i18nKey>`, …).
192
+
193
+ ### `no-dynamic-field-access`
194
+
195
+ Richiede che il campo letto da un dizionario sia noto staticamente.
196
+
197
+ Il compilatore rimuove i campi che non vede utilizzati. Un accesso dinamico è invisibile per esso, quindi la lettura potrebbe restituire `undefined` a runtime.
198
+
199
+ ```typescript
200
+ // ✗ Segnalato
201
+ const content = useIntlayer("home");
202
+ content[fieldName];
203
+
204
+ const t = useTranslations("home");
205
+ t(messageKey);
206
+
207
+ // ✓ Corretto
208
+ content.title;
209
+ content["title"];
210
+ content.items[0];
211
+ t("hero.title");
212
+ ```
213
+
214
+ ### `enforce-adapter-import`
215
+
216
+ Preferisce l'adattatore di compatibilità `@intlayer/*` rispetto al pacchetto originale. Il pacchetto originale si risolve in Intlayer solo quando è configurato l'alias del bundler; l'adattatore lo fa sempre. Corregibile automaticamente con `--fix`.
217
+
218
+ ```typescript
219
+ // ✗ Segnalato
220
+ import { useTranslation } from "react-i18next";
221
+ import { getTranslations } from "next-intl/server";
222
+
223
+ // ✓ Corretto
224
+ import { useTranslation } from "@intlayer/react-i18next";
225
+ import { getTranslations } from "@intlayer/next-intl/server";
226
+ ```
227
+
228
+ ### `no-unused-content`
229
+
230
+ **Disattivata per impostazione predefinita.** Segnala i contenuti che nessun elemento nel progetto legge, oltre alle chiavi di dizionario dichiarate in più punti.
231
+
232
+ ```typescript fileName="src/home.content.ts"
233
+ export default {
234
+ key: "home", // ✗ Segnalato se nessun chiamante nel progetto richiede "home"
235
+ content: {
236
+ title: t({ it: "Titolo", en: "Title" }),
237
+
238
+ // ✗ Segnalato se nulla legge `hero`
239
+ hero: {
240
+ subtitle: t({ it: "Sottotitolo", en: "Subtitle" }),
241
+ },
242
+ },
243
+ };
244
+ ```
245
+
246
+ A differenza delle altre regole, questa non può rispondere solo dal file analizzato: un campo è inutilizzato solo rispetto all'intero progetto. Alla prima dichiarazione di contenuto di un'esecuzione di lint, carica la configurazione di Intlayer, analizza i file sorgente dichiarati da tale configurazione (`build.traversePattern`, `compiler.transformPattern`) ed esegue lo stesso analizzatore di utilizzo che alimenta `@intlayer/lsp` e il testo barrato "inutilizzato" nell'estensione VS Code. Il risultato viene memorizzato nella cache per `cacheTtl` millisecondi, pertanto la scansione avviene una volta per esecuzione anziché una volta per file.
247
+
248
+ **Opzioni**
249
+
250
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
251
+ {
252
+ "intlayer/no-unused-content": [
253
+ "warn",
254
+ {
255
+ // Segnala le chiavi di dizionario a cui nulla fa riferimento. Predefinito: true
256
+ reportUnusedDictionaries: true,
257
+
258
+ // Segnala i campi di contenuto che nulla legge. Predefinito: true
259
+ reportUnusedFields: true,
260
+
261
+ // Segnala le chiavi dichiarate in più posizioni. Predefinito: true
262
+ reportDuplicateKeys: true,
263
+
264
+ // Espressioni regolari per i percorsi di campo da non segnalare mai.
265
+ ignoreFields: ["^meta"],
266
+
267
+ // Directory radice del progetto da cui parte la scansione. Predefinito: directory di lavoro di ESLint
268
+ baseDir: process.cwd(),
269
+
270
+ // Durata del riutilizzo di una scansione del progetto, in ms. Predefinito: 30000
271
+ cacheTtl: 30000,
272
+ },
273
+ ],
274
+ }
275
+ ```
276
+
277
+ Riduci `cacheTtl` quando esegui il lint da un server dell'editor a lunga durata e desideri che le modifiche vengano riflesse prima; imposta `baseDir` quando una singola esecuzione di lint comprende diversi progetti Intlayer in un monorepo.
278
+
279
+ > **Predilige il silenzio.** Un falso positivo in questo caso eliminerebbe una traduzione, pertanto non viene segnalato nulla quando il dizionario viene utilizzato in un modo che l'analisi non può tracciare: l'oggetto contenuto passato nel suo insieme, una funzione di traduzione associata ad esso (`const t = useTranslations("home")`), una dichiarazione raggiunta tramite un'importazione diretta (`useDictionary(myDictionary)`), un `nest()` da un altro dizionario o un elenco di campi reso non esaustivo da uno spread. I componenti a file singolo (`.vue`, `.svelte`, `.astro`) contano come utilizzatori di ogni campo dei dizionari che menzionano, poiché i loro blocchi di script non vengono analizzati qui.
280
+
281
+ `reportDuplicateKeys` legge i dizionari non uniti che la build scrive sotto `.intlayer/`, quindi rimane inattiva finché il progetto non è stato compilato almeno una volta. Due dichiarazioni che condividono una chiave vengono unite, il che è un modello valido: la segnalazione esiste perché un campo definito su entrambi i lati mantiene silenziosamente solo uno dei due valori.
282
+
283
+ L'analizzatore viene caricato da `@intlayer/lsp`, distribuito come modulo ESM. La regola necessita pertanto di una versione di Node in grado di eseguire `require()` su un modulo ES — Node 20.19+ o 22.12+. Con versioni precedenti, non segnala nulla anziché interrompere l'esecuzione del lint.
284
+
285
+ ## Frameworks
286
+
287
+ Tutte le regole funzionano su tutte le integrazioni Intlayer, compresi i template Vue, Svelte e Angular. Devi solo indicare a ESLint quale parser legge ciascun tipo di file.
288
+
289
+ | Framework | File | 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
+ | Template 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
+ Installa solo i parser di cui il tuo progetto ha bisogno.
335
+
336
+ > **Limitazione nota.** Nei template Vue e Angular, un'espressione come `{{ content[key] }}` non viene verificata da `no-dynamic-field-access`. Le letture dinamiche scritte nel blocco script vengono invece rilevate normalmente.