@intlayer/docs 9.3.1 → 9.3.3

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 (151) hide show
  1. package/blog/ar/nextjs-multilingual-seo-comparison.md +10 -10
  2. package/blog/de/nextjs-multilingual-seo-comparison.md +9 -9
  3. package/blog/en/nextjs-multilingual-seo-comparison.md +10 -10
  4. package/blog/en-GB/nextjs-multilingual-seo-comparison.md +10 -10
  5. package/blog/es/nextjs-multilingual-seo-comparison.md +10 -10
  6. package/blog/fr/nextjs-multilingual-seo-comparison.md +10 -10
  7. package/blog/hi/nextjs-multilingual-seo-comparison.md +10 -10
  8. package/blog/id/nextjs-multilingual-seo-comparison.md +10 -10
  9. package/blog/it/nextjs-multilingual-seo-comparison.md +10 -10
  10. package/blog/ja/nextjs-multilingual-seo-comparison.md +9 -9
  11. package/blog/ko/nextjs-multilingual-seo-comparison.md +9 -9
  12. package/blog/pl/nextjs-multilingual-seo-comparison.md +10 -10
  13. package/blog/pt/nextjs-multilingual-seo-comparison.md +9 -9
  14. package/blog/ru/nextjs-multilingual-seo-comparison.md +9 -9
  15. package/blog/tr/nextjs-multilingual-seo-comparison.md +9 -9
  16. package/blog/uk/nextjs-multilingual-seo-comparison.md +10 -10
  17. package/blog/vi/nextjs-multilingual-seo-comparison.md +10 -10
  18. package/blog/zh/nextjs-multilingual-seo-comparison.md +10 -10
  19. package/dist/cjs/generated/docs.entry.cjs +20 -0
  20. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  21. package/dist/esm/generated/docs.entry.mjs +20 -0
  22. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  23. package/dist/types/generated/docs.entry.d.ts +1 -0
  24. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  25. package/docs/ar/bundle_optimization.md +1 -1
  26. package/docs/ar/configuration.md +32 -9
  27. package/docs/ar/dictionary/content_file.md +0 -22
  28. package/docs/ar/dictionary/function_fetching.md +23 -0
  29. package/docs/ar/eslint.md +336 -0
  30. package/docs/ar/intlayer_with_react_router_v7_fs_routes.md +1 -1
  31. package/docs/bn/configuration.md +34 -9
  32. package/docs/bn/eslint.md +336 -0
  33. package/docs/cs/bundle_optimization.md +1 -1
  34. package/docs/cs/configuration.md +33 -9
  35. package/docs/cs/eslint.md +336 -0
  36. package/docs/de/bundle_optimization.md +1 -1
  37. package/docs/de/configuration.md +34 -9
  38. package/docs/de/dictionary/content_file.md +0 -22
  39. package/docs/de/dictionary/function_fetching.md +23 -0
  40. package/docs/de/eslint.md +336 -0
  41. package/docs/en/bundle_optimization.md +1 -1
  42. package/docs/en/configuration.md +34 -9
  43. package/docs/en/dictionary/content_file.md +0 -22
  44. package/docs/en/dictionary/function_fetching.md +23 -0
  45. package/docs/en/eslint.md +336 -0
  46. package/docs/en/packages/intlayer/getLocalizedPath.md +70 -19
  47. package/docs/en-GB/configuration.md +33 -9
  48. package/docs/en-GB/dictionary/content_file.md +0 -22
  49. package/docs/en-GB/dictionary/function_fetching.md +23 -0
  50. package/docs/en-GB/eslint.md +336 -0
  51. package/docs/en-GB/intlayer_with_create_react_app.md +32 -35
  52. package/docs/en-GB/intlayer_with_react_router_v7_fs_routes.md +1 -1
  53. package/docs/es/bundle_optimization.md +1 -1
  54. package/docs/es/configuration.md +35 -9
  55. package/docs/es/dictionary/content_file.md +0 -22
  56. package/docs/es/dictionary/function_fetching.md +23 -0
  57. package/docs/es/eslint.md +336 -0
  58. package/docs/fr/bundle_optimization.md +1 -1
  59. package/docs/fr/configuration.md +35 -9
  60. package/docs/fr/dictionary/content_file.md +0 -22
  61. package/docs/fr/dictionary/function_fetching.md +23 -0
  62. package/docs/fr/eslint.md +336 -0
  63. package/docs/hi/configuration.md +35 -9
  64. package/docs/hi/dictionary/content_file.md +0 -22
  65. package/docs/hi/dictionary/function_fetching.md +23 -0
  66. package/docs/hi/eslint.md +336 -0
  67. package/docs/hi/intlayer_with_react_router_v7_fs_routes.md +1 -1
  68. package/docs/hi/intlayer_with_vite+svelte.md +2 -2
  69. package/docs/id/configuration.md +35 -9
  70. package/docs/id/dictionary/content_file.md +0 -22
  71. package/docs/id/dictionary/function_fetching.md +23 -0
  72. package/docs/id/eslint.md +336 -0
  73. package/docs/it/bundle_optimization.md +1 -1
  74. package/docs/it/configuration.md +35 -9
  75. package/docs/it/dictionary/content_file.md +0 -22
  76. package/docs/it/dictionary/function_fetching.md +23 -0
  77. package/docs/it/eslint.md +336 -0
  78. package/docs/ja/configuration.md +30 -9
  79. package/docs/ja/dictionary/content_file.md +0 -22
  80. package/docs/ja/dictionary/function_fetching.md +23 -0
  81. package/docs/ja/eslint.md +336 -0
  82. package/docs/ja/intlayer_with_react_router_v7.md +1 -146
  83. package/docs/ja/intlayer_with_vite+react.md +5 -1
  84. package/docs/ko/configuration.md +31 -9
  85. package/docs/ko/dictionary/content_file.md +0 -22
  86. package/docs/ko/dictionary/function_fetching.md +23 -0
  87. package/docs/ko/eslint.md +336 -0
  88. package/docs/ko/intlayer_with_lynx+react.md +4 -0
  89. package/docs/ko/intlayer_with_react_router_v7_fs_routes.md +1 -1
  90. package/docs/ko/intlayer_with_storybook.md +5 -5
  91. package/docs/nl/configuration.md +33 -9
  92. package/docs/nl/eslint.md +336 -0
  93. package/docs/pl/bundle_optimization.md +1 -1
  94. package/docs/pl/configuration.md +34 -9
  95. package/docs/pl/dictionary/content_file.md +0 -22
  96. package/docs/pl/dictionary/function_fetching.md +23 -0
  97. package/docs/pl/eslint.md +336 -0
  98. package/docs/pl/intlayer_with_astro.md +1 -114
  99. package/docs/pl/migration_from_i18next_to_intlayer.md +4 -0
  100. package/docs/pl/migration_from_next-i18next_to_intlayer.md +8 -4
  101. package/docs/pl/migration_from_next-intl_to_intlayer.md +11 -5
  102. package/docs/pl/migration_from_nuxtjs_i18n_to_intlayer.md +8 -4
  103. package/docs/pl/migration_from_react-i18next_to_intlayer.md +8 -4
  104. package/docs/pl/migration_from_vue-i18n_to_intlayer.md +4 -0
  105. package/docs/pt/bundle_optimization.md +1 -1
  106. package/docs/pt/configuration.md +34 -9
  107. package/docs/pt/dictionary/content_file.md +0 -22
  108. package/docs/pt/dictionary/function_fetching.md +23 -0
  109. package/docs/pt/eslint.md +336 -0
  110. package/docs/pt/intlayer_with_astro.md +1 -114
  111. package/docs/ru/bundle_optimization.md +1 -1
  112. package/docs/ru/configuration.md +34 -9
  113. package/docs/ru/dictionary/content_file.md +0 -22
  114. package/docs/ru/dictionary/function_fetching.md +23 -0
  115. package/docs/ru/eslint.md +336 -0
  116. package/docs/tr/bundle_optimization.md +1 -1
  117. package/docs/tr/configuration.md +33 -9
  118. package/docs/tr/dictionary/content_file.md +0 -22
  119. package/docs/tr/dictionary/function_fetching.md +23 -0
  120. package/docs/tr/eslint.md +336 -0
  121. package/docs/uk/configuration.md +35 -9
  122. package/docs/uk/dictionary/content_file.md +0 -22
  123. package/docs/uk/dictionary/function_fetching.md +23 -0
  124. package/docs/uk/eslint.md +336 -0
  125. package/docs/uk/packages/angular-intlayer/exports.md +2 -2
  126. package/docs/ur/configuration.md +35 -9
  127. package/docs/ur/eslint.md +336 -0
  128. package/docs/vi/bundle_optimization.md +1 -1
  129. package/docs/vi/configuration.md +33 -9
  130. package/docs/vi/dictionary/content_file.md +0 -22
  131. package/docs/vi/dictionary/function_fetching.md +23 -0
  132. package/docs/vi/eslint.md +336 -0
  133. package/docs/zh/bundle_optimization.md +1 -1
  134. package/docs/zh/configuration.md +29 -9
  135. package/docs/zh/dictionary/content_file.md +0 -22
  136. package/docs/zh/dictionary/function_fetching.md +23 -0
  137. package/docs/zh/eslint.md +336 -0
  138. package/docs/zh/intlayer_with_create_react_app.md +4 -0
  139. package/docs/zh/intlayer_with_lynx+react.md +4 -0
  140. package/docs/zh/intlayer_with_nextjs_14.md +0 -2
  141. package/docs/zh/intlayer_with_nextjs_15.md +0 -2
  142. package/docs/zh/intlayer_with_nextjs_page_router.md +0 -2
  143. package/docs/zh/intlayer_with_nuxt.md +1 -1
  144. package/docs/zh/intlayer_with_react_router_v7.md +4 -0
  145. package/docs/zh/intlayer_with_react_router_v7_fs_routes.md +4 -0
  146. package/docs/zh/intlayer_with_solid_start.md +1 -1
  147. package/docs/zh/intlayer_with_vite+vue.md +0 -2
  148. package/docs/zh-TW/bundle_optimization.md +1 -1
  149. package/docs/zh-TW/eslint.md +336 -0
  150. package/package.json +7 -7
  151. package/src/generated/docs.entry.ts +20 -0
@@ -0,0 +1,336 @@
1
+ ---
2
+ createdAt: 2026-08-12
3
+ updatedAt: 2026-08-13
4
+ title: ESLint Plugin | Linting-Regeln für Intlayer
5
+ description: Erkennen Sie hartcodierte Zeichenketten, dynamische Aufrufe, die der Intlayer-Compiler nicht optimieren kann, und ungenutzte Wörterbuchinhalte mit eslint-plugin-intlayer. Funktioniert mit ESLint und oxlint für React, Vue, Svelte, Angular und Astro.
6
+ keywords:
7
+ - Intlayer
8
+ - ESLint
9
+ - oxlint
10
+ - Linting
11
+ - i18n
12
+ - Internationalisierung
13
+ - no-raw-text
14
+ - Hartcodierte Zeichenketten
15
+ - Ungenutzte Übersetzungen
16
+ - Toter Inhalt
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: "Initialer Verlauf"
28
+ author: aymericzip
29
+ ---
30
+
31
+ # ESLint x OXLint Plugin
32
+
33
+ `eslint-plugin-intlayer` erkennt die typischen i18n-Fehler, die TypeScript nicht erfassen kann:
34
+
35
+ 1. **Hartcodierter Text**, der nie in einem Wörterbuch deklariert wurde.
36
+ 2. **Dynamische Aufrufe**, die die Typüberprüfung bestehen und ausgeführt werden, die der Intlayer-Compiler jedoch nicht optimieren kann.
37
+ 3. **Toter Inhalt** — Wörterbücher und Felder, die an keiner Stelle im Projekt gelesen werden (Opt-in).
38
+
39
+ Unbekannte Wörterbuchschlüssel, unbekannte Feldpfade und fehlende Locales sind bereits Kompilierungsfehler, weshalb das Plugin diese nicht wiederholt.
40
+
41
+ ## Installation
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
+ Erfordert ESLint 9 oder höher (Flat Config). ESLint 10 wird unterstützt.
56
+
57
+ ## Verwendung
58
+
59
+ Das Plugin funktioniert sowohl in ESLint als auch in [oxlint](https://oxc.rs) — dieselben Regeln, dieselben Optionen.
60
+
61
+ <Tabs defaultTab="eslint">
62
+ <Tab label="ESLint" value="eslint">
63
+
64
+ ```javascript fileName="eslint.config.mjs"
65
+ import intlayer from "eslint-plugin-intlayer";
66
+
67
+ export default [...intlayer.configs.recommended];
68
+ ```
69
+
70
+ Oder fügen Sie eine Konfiguration ein und legen die Schweregrade selbst fest:
71
+
72
+ ```javascript fileName="eslint.config.mjs"
73
+ import intlayer from "eslint-plugin-intlayer";
74
+
75
+ export default [
76
+ ...intlayer.configs.recommended,
77
+ {
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
+ Zwei Hinweise: Die JS-Plugin-Unterstützung von oxlint befindet sich noch im Alpha-Stadium und oxlint unterstützt keine benutzerdefinierten Parser — `.vue`-, `.svelte`-, `.astro`-Dateien und Angular-Templates werden dort daher nicht geprüft. Führen Sie oxlint für Ihre JS/TS/JSX-Dateien aus und behalten Sie ESLint für den Rest bei.
105
+
106
+ `no-unused-content` wird oben absichtlich weggelassen: Die Regel benötigt das Arbeitsverzeichnis und den Pfad der geprüften Datei aus dem Regelkontext, was die Alpha-Bridge für JS-Plugins nicht garantiert. Führen Sie diese Regel unter ESLint aus.
107
+
108
+ </Tab>
109
+ </Tabs>
110
+
111
+ ### Konfigurationen
112
+
113
+ | Konfiguration | `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 (+ Nicht-JSX-Zeichenfolgen) | error | error | error | off |
117
+ | `contract-only` | off | error | error | off | off |
118
+
119
+ `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.
120
+
121
+ `enforce-adapter-import` ist standardmäßig deaktiviert — aktivieren Sie die Regel bei Bedarf explizit.
122
+
123
+ `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.
124
+
125
+ ## Regeln
126
+
127
+ ### `no-raw-text`
128
+
129
+ 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.
130
+
131
+ ```jsx
132
+ // ✗ Gemeldet
133
+ <h1>Welcome to our documentation</h1>
134
+ <input placeholder="Enter your email address" />
135
+
136
+ // ✓ Gültig
137
+ const { title } = useIntlayer("home");
138
+ <h1>{title}</h1>
139
+ ```
140
+
141
+ Inhaltsdeklarationsdateien (`*.content.ts`, …) werden übersprungen.
142
+
143
+ 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.
144
+
145
+ **Optionen**
146
+
147
+ ```javascript fileName="eslint.config.mjs"
148
+ {
149
+ "intlayer/no-raw-text": [
150
+ "warn",
151
+ {
152
+ // Attribute, deren Wert benutzerorientierter Text ist.
153
+ // Standard: title, placeholder, alt, aria-label, label
154
+ attributes: ["title", "placeholder", "alt", "aria-label", "label"],
155
+
156
+ // Elemente, deren Inhalt niemals benutzerorientierter Text ist.
157
+ // Standard: code, pre, script, style
158
+ ignoreElements: ["code", "pre", "script", "style"],
159
+
160
+ // Reguläre Ausdrücke für Text, der niemals gemeldet werden soll.
161
+ ignorePatterns: ["^Powered by"],
162
+
163
+ // Auch Zeichenketten-Literale außerhalb von Markup melden. Standard: false
164
+ includeStringLiterals: false,
165
+ },
166
+ ],
167
+ }
168
+ ```
169
+
170
+ ### `static-dictionary-key`
171
+
172
+ Erfordert, dass der Wörterbuchschlüssel ein Zeichenfolgen-Literal ist.
173
+
174
+ 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.
175
+
176
+ ```typescript
177
+ // ✗ Gemeldet
178
+ useIntlayer(dictionaryKey);
179
+ useIntlayer(`home-${suffix}`);
180
+ getTranslations({ namespace: page });
181
+
182
+ // ✗ Eine Variable ist immer noch kein Literal
183
+ const key = "home";
184
+ useIntlayer(key);
185
+
186
+ // ✓ Gültig
187
+ useIntlayer("home");
188
+ getTranslations({ namespace: "home" });
189
+ ```
190
+
191
+ Dies gilt für `useIntlayer`, `getIntlayer` und jeden Kompatibilitätsadapter (`useTranslation`, `useTranslations`, `formatMessage`, `<FormattedMessage id>`, `<Trans i18nKey>`, …).
192
+
193
+ ### `no-dynamic-field-access`
194
+
195
+ Erfordert, dass das Feld, das Sie aus einem Wörterbuch lesen, statisch bekannt ist.
196
+
197
+ 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.
198
+
199
+ ```typescript
200
+ // ✗ Gemeldet
201
+ const content = useIntlayer("home");
202
+ content[fieldName];
203
+
204
+ const t = useTranslations("home");
205
+ t(messageKey);
206
+
207
+ // ✓ Gültig
208
+ content.title;
209
+ content["title"];
210
+ content.items[0];
211
+ t("hero.title");
212
+ ```
213
+
214
+ ### `enforce-adapter-import`
215
+
216
+ 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`.
217
+
218
+ ```typescript
219
+ // ✗ Gemeldet
220
+ import { useTranslation } from "react-i18next";
221
+ import { getTranslations } from "next-intl/server";
222
+
223
+ // ✓ Gültig
224
+ import { useTranslation } from "@intlayer/react-i18next";
225
+ import { getTranslations } from "@intlayer/next-intl/server";
226
+ ```
227
+
228
+ ### `no-unused-content`
229
+
230
+ **Standardmäßig deaktiviert.** Meldet Inhalte, die im Projekt nirgends gelesen werden, sowie Wörterbuchschlüssel, die an mehr als einer Stelle deklariert sind.
231
+
232
+ ```typescript fileName="src/home.content.ts"
233
+ export default {
234
+ key: "home", // ✗ Gemeldet, wenn kein Aufrufer im Projekt "home" abfragt
235
+ content: {
236
+ title: t({ de: "Titel", en: "Title" }),
237
+
238
+ // ✗ Gemeldet, wenn nichts `hero` liest
239
+ hero: {
240
+ subtitle: t({ de: "Untertitel", en: "Subtitle" }),
241
+ },
242
+ },
243
+ };
244
+ ```
245
+
246
+ 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.
247
+
248
+ **Optionen**
249
+
250
+ ```javascript fileName="eslint.config.mjs"
251
+ {
252
+ "intlayer/no-unused-content": [
253
+ "warn",
254
+ {
255
+ // Wörterbuchschlüssel melden, auf die nichts verweist. Standard: true
256
+ reportUnusedDictionaries: true,
257
+
258
+ // Inhaltsfelder melden, die nichts liest. Standard: true
259
+ reportUnusedFields: true,
260
+
261
+ // Schlüssel melden, die an mehr als einer Stelle deklariert sind. Standard: true
262
+ reportDuplicateKeys: true,
263
+
264
+ // Reguläre Ausdrücke für Feldpfade, die niemals gemeldet werden sollen.
265
+ ignoreFields: ["^meta"],
266
+
267
+ // Projekt-Root, ab dem der Scan startet. Standard: ESLint-Arbeitsverzeichnis
268
+ baseDir: process.cwd(),
269
+
270
+ // Wie lange ein Projektscan wiederverwendet wird, in ms. Standard: 30000
271
+ cacheTtl: 30000,
272
+ },
273
+ ],
274
+ }
275
+ ```
276
+
277
+ 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.
278
+
279
+ > **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.
280
+
281
+ `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.
282
+
283
+ 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.
284
+
285
+ ## Frameworks
286
+
287
+ 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.
288
+
289
+ | Framework | Dateien | 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"
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
+ Installieren Sie nur die Parser, die Ihr Projekt benötigt.
335
+
336
+ > **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.
@@ -159,7 +159,7 @@ pnpm add -D webpack-bundle-analyzer
159
159
  bun add -d webpack-bundle-analyzer
160
160
  ```
161
161
 
162
- ```typescript fileName="webpack.config.ts
162
+ ```typescript fileName="webpack.config.ts"
163
163
  import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer";
164
164
 
165
165
  export default {
@@ -482,6 +482,29 @@ const config: IntlayerConfig = {
482
482
  */
483
483
  purge: false,
484
484
 
485
+ /**
486
+ * Group the per-locale dictionary chunks by the code-split boundary that uses
487
+ * them, so a lazily loaded page fetches its content in one request.
488
+ * Default: true
489
+ *
490
+ * Note:
491
+ * - Only applies to dictionaries using `importMode: 'dynamic'`.
492
+ */
493
+ chunkGrouping: true,
494
+
495
+ /**
496
+ * Load a dictionary together with the chunk that uses it, instead of fetching
497
+ * it once that chunk renders. Readers render synchronously instead of
498
+ * suspending, so navigating no longer flashes a loading state.
499
+ * Default: true
500
+ *
501
+ * Note:
502
+ * - Only applies to dictionaries using `importMode: 'dynamic'`.
503
+ * - Only the resolved locale is awaited, so a page still downloads only the
504
+ * language it renders.
505
+ */
506
+ dictionariesPreload: true,
507
+
485
508
  /**
486
509
  * Output format for generated dictionary files.
487
510
  * Default: ['cjs', 'esm']
@@ -1062,15 +1085,17 @@ Build options apply to the `@intlayer/babel` and `@intlayer/swc` plugins.
1062
1085
 
1063
1086
  > When optimized, Intlayer will replace dictionary calls to optimize chunking, so the final bundle only imports dictionaries that are actually used.
1064
1087
 
1065
- | Field | Description | Type | Default | Example | Note |
1066
- | ----------------- | -------------------------------------------------------------------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1067
- | `mode` | Controls the mode of the build. | `'auto'` &#124; <br/> `'manual'` | `'auto'` | `'manual'` | • `'auto'`: build enabled automatically when the application is built.<br/>• `'manual'`: only runs when the build command is executed.<br/>• Can be used to disable dictionary builds (e.g. to avoid running in Node.js environments). |
1068
- | `optimize` | Controls whether the build should be optimized. | `boolean` | `undefined` | `process.env.NODE_ENV === 'production'` | • If unset, optimization is triggered on framework build (Vite/Next.js).<br/>• `true` forces optimization including dev mode.<br/>• `false` disables it.<br/>• When enabled, replaces dictionary calls to optimize chunking - only used dictionaries are imported.<br/>• Relies on `@intlayer/babel` and `@intlayer/swc` plugins.<br/>• Keys must be declared statically. |
1069
- | `minify` | Whether to minify the dictionaries to reduce the bundle size. | `boolean` | `false` | | • Indicates whether the bundle should be minified.<br/>• Default: `false`.<br/>• This option will be ignored if `optimize` is disabled.<br/>• This option will be ignored if `editor.enabled` is true. |
1070
- | `purge` | Whether to purge the unused keys in a dictionaries. | `boolean` | `false` | | • Indicates whether the bundle should be purged.<br/>• Default: `false`.<br/>• This option will be ignored if `optimize` is disabled. |
1071
- | `checkTypes` | Indicates if the build should check TypeScript types and log errors. | `boolean` | `false` | | Can slow down the build. |
1072
- | `outputFormat` | Controls the output format of the dictionaries. | `('esm' &#124; 'cjs')[]` | `['esm', 'cjs']` | `['cjs']` | |
1073
- | `traversePattern` | Patterns defining which files to traverse during optimization. | `string[]` | `['**/*.{tsx,ts,js,mjs,cjs,jsx,vue,svelte,svte}', '!**/node_modules/**', '!**/dist/**', '!**/.intlayer/**', '!**/*.config.*', '!**/*.test.*', '!**/*.spec.*', '!**/*.stories.*']` | `['src/**/*.{ts,tsx}', '../ui-library/**/*.{ts,tsx}', '!**/node_modules/**']` | Limit optimization to relevant files to improve build performance.<br/>• Ignored if `optimize` is disabled.<br/>• Uses glob pattern. |
1088
+ | Field | Description | Type | Default | Example | Note |
1089
+ | --------------------- | ------------------------------------------------------------------------------------------------------------------------ | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1090
+ | `mode` | Controls the mode of the build. | `'auto'` &#124; <br/> `'manual'` | `'auto'` | `'manual'` | • `'auto'`: build enabled automatically when the application is built.<br/>• `'manual'`: only runs when the build command is executed.<br/>• Can be used to disable dictionary builds (e.g. to avoid running in Node.js environments). |
1091
+ | `optimize` | Controls whether the build should be optimized. | `boolean` | `undefined` | `process.env.NODE_ENV === 'production'` | • If unset, optimization is triggered on framework build (Vite/Next.js).<br/>• `true` forces optimization including dev mode.<br/>• `false` disables it.<br/>• When enabled, replaces dictionary calls to optimize chunking - only used dictionaries are imported.<br/>• Relies on `@intlayer/babel` and `@intlayer/swc` plugins.<br/>• Keys must be declared statically. |
1092
+ | `minify` | Whether to minify the dictionaries to reduce the bundle size. | `boolean` | `false` | | • Indicates whether the bundle should be minified.<br/>• Default: `false`.<br/>• This option will be ignored if `optimize` is disabled.<br/>• This option will be ignored if `editor.enabled` is true. |
1093
+ | `purge` | Whether to purge the unused keys in a dictionaries. | `boolean` | `false` | | • Indicates whether the bundle should be purged.<br/>• Default: `false`.<br/>• This option will be ignored if `optimize` is disabled. |
1094
+ | `checkTypes` | Indicates if the build should check TypeScript types and log errors. | `boolean` | `false` | | Can slow down the build. |
1095
+ | `chunkGrouping` | Whether to group the per-locale dictionary chunks by the code-split boundary that uses them. | `boolean` | `true` | | • Without grouping, a page assembled from many components issues one request per dictionary.<br/>• Dictionaries reached from several boundaries move to a shared chunk, so no page ships another page's content.<br/>• Only applies to dictionaries using `importMode: 'dynamic'`.<br/>• Only applies to the client build, and only when bundling (not in dev). |
1096
+ | `dictionariesPreload` | Whether a dictionary should load together with the chunk that uses it, instead of being fetched once that chunk renders. | `boolean` | `true` | | The generated entry point requests the browsing locale as it evaluates, so the request leaves with the chunk that needs it instead of once that chunk renders.<br/>• Readers usually render synchronously instead of suspending, so navigating no longer flashes a loading state.<br/>• Only the resolved locale is requested, so a page still downloads only the language it renders.<br/>• Only applies to dictionaries using `importMode: 'dynamic'`, on the client build.<br/>• Not applied by Metro-based bundlers. |
1097
+ | `outputFormat` | Controls the output format of the dictionaries. | `('esm' &#124; 'cjs')[]` | `['esm', 'cjs']` | `['cjs']` | |
1098
+ | `traversePattern` | Patterns defining which files to traverse during optimization. | `string[]` | `['**/*.{tsx,ts,js,mjs,cjs,jsx,vue,svelte,svte}', '!**/node_modules/**', '!**/dist/**', '!**/.intlayer/**', '!**/*.config.*', '!**/*.test.*', '!**/*.spec.*', '!**/*.stories.*']` | `['src/**/*.{ts,tsx}', '../ui-library/**/*.{ts,tsx}', '!**/node_modules/**']` | • Limit optimization to relevant files to improve build performance.<br/>• Ignored if `optimize` is disabled.<br/>• Uses glob pattern. |
1074
1099
 
1075
1100
  ---
1076
1101
 
@@ -539,28 +539,6 @@ Used in conjunction with [Variants](https://github.com/aymericzip/intlayer/blob/
539
539
 
540
540
  > See [Variants](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dynamic_dictionaries/variants.md) for more information.
541
541
 
542
- #### `meta` (`Record<string, string | number | boolean>`)
543
-
544
- Used in conjunction with Dynamic Records, this field allows declaring CMS-managed records or arbitrary data fetched at runtime by an opaque ID. The dictionary identity is defined by the arbitrary set of key-value pairs declared in this `meta` field.
545
-
546
- **Example:**
547
-
548
- ```typescript
549
- {
550
- key: "product-copy",
551
- meta: {
552
- id: "prod_abc",
553
- userId: "user_123"
554
- },
555
- content: {
556
- name: "Widget Pro",
557
- description: "The best widget."
558
- }
559
- }
560
- ```
561
-
562
- > See [Dynamic Records](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dynamic_dictionaries/dynamic_content.md) for more information.
563
-
564
542
  ### CMS Properties
565
543
 
566
544
  ##### `version` (string)
@@ -89,6 +89,29 @@ No way to fetch content from a JSON file, use a .ts or .js file instead
89
89
 
90
90
  In this case, the `fakeFetch` function mimics a delay to simulate server response time. Intlayer executes the asynchronous function and uses the result as the content for the `text` key.
91
91
 
92
+ ## Fetching Remote Content
93
+
94
+ You can also assign a promise directly to a content field. Intlayer awaits it while building the dictionaries and inlines the resolved value:
95
+
96
+ ```typescript fileName="**/*.content.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
97
+ import type { Dictionary } from "intlayer";
98
+
99
+ const remoteContent = {
100
+ key: "remote_content",
101
+ content: {
102
+ externalContent: fetch("https://example.com").then((res) => res.json()),
103
+ },
104
+ } satisfies Dictionary;
105
+
106
+ export default remoteContent;
107
+ ```
108
+
109
+ ```plaintext fileName="**/*.content.json" contentDeclarationFormat="json"
110
+ No way to fetch content from a JSON file, use a .ts or .js file instead
111
+ ```
112
+
113
+ > The request runs at build time, so the fetched data is a snapshot embedded in the dictionary. Rebuild your dictionaries to refresh it.
114
+
92
115
  ## Using Function-Based Content in React Components
93
116
 
94
117
  To use function-based content in a React component, you need to import `useIntlayer` from `react-intlayer` and call it with the content ID to retrieve the content. Here's an example: