@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 插件 | Intlayer 的 Lint 规则
5
+ description: 使用 eslint-plugin-intlayer 捕获硬编码字符串、Intlayer 编译器无法优化的动态调用以及未使用的字典内容。支持 ESLint 和 oxlint,适用于 React、Vue、Svelte、Angular 和 Astro。
6
+ keywords:
7
+ - Intlayer
8
+ - ESLint
9
+ - oxlint
10
+ - 代码检查
11
+ - i18n
12
+ - 国际化
13
+ - no-raw-text
14
+ - 硬编码字符串
15
+ - 未使用的翻译
16
+ - 死内容
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: "初始化历史"
28
+ author: aymericzip
29
+ ---
30
+
31
+ # ESLint x OXLint 插件
32
+
33
+ `eslint-plugin-intlayer` 能够捕获 TypeScript 无法发现的几类 i18n 错误:
34
+
35
+ 1. **硬编码文本**:从未写入字典中的文本。
36
+ 2. **动态调用**:能够通过类型检查并正常运行,但 Intlayer 编译器无法进行优化的调用。
37
+ 3. **死内容(Dead content)**:项目中没有任何地方读取的字典和字段(需手动开启)。
38
+
39
+ 未知的字典键、未知的字段路径和缺失的语言环境本身已是编译错误,因此插件不会重复报告它们。
40
+
41
+ ## 安装
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
+ 需要 ESLint 9 或更高版本(Flat config)。支持 ESLint 10。
56
+
57
+ ## 使用方法
58
+
59
+ 该插件可在 ESLint 和 [oxlint](https://oxc.rs) 中运行 — 拥有相同的规则和配置选项。
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
+ 或者展开某个配置并自行设置严重级别:
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
+ 两点注意事项:oxlint 对 JS 插件的支持仍处于 Alpha 阶段,且 oxlint 不支持自定义解析器 — 因此 `.vue`、`.svelte`、`.astro` 和 Angular 模板无法在此处进行 lint。请在 JS/TS/JSX 文件上运行 oxlint,其余文件保留使用 ESLint。
105
+
106
+ 上面特意排除了 `no-unused-content`:它需要从规则上下文中获取工作目录和被检查文件的路径,而 Alpha 阶段的 JS 插件桥接层无法保证提供这些信息。请在 ESLint 下运行该规则。
107
+
108
+ </Tab>
109
+ </Tabs>
110
+
111
+ ### 预设配置
112
+
113
+ | 配置 | `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 (+ 非 JSX 字面量) | error | error | error | off |
117
+ | `contract-only` | off | error | error | off | off |
118
+
119
+ `recommended` 特意将 `no-raw-text` 设为 `warn`:将其指向现有代码库会一次性暴露所有未翻译的字符串,这不应该在第一天就导致构建中断。
120
+
121
+ `enforce-adapter-import` 默认关闭 — 如果需要请显式启用。
122
+
123
+ `no-unused-content` 在所有配置中均默认关闭(包括 `strict`)。这是唯一一个需要读取 Intlayer 配置并从磁盘遍历源文件的规则,因此启用它应当是一项经过深思熟虑的选择,而非预设自动执行的行为。
124
+
125
+ ## 规则列表
126
+
127
+ ### `no-raw-text`
128
+
129
+ 报告未在字典中声明的面向用户的文本。它使用与 `intlayer extract` 相同的检测逻辑,因此品牌名称、CSS 类名和技术标识符都会被忽略。
130
+
131
+ ```jsx
132
+ // ✗ 报告错误
133
+ <h1>Welcome to our documentation</h1>
134
+ <input placeholder="Enter your email address" />
135
+
136
+ // ✓ 正常
137
+ const { title } = useIntlayer("home");
138
+ <h1>{title}</h1>
139
+ ```
140
+
141
+ 内容声明文件(`*.content.ts`, …)会被跳过。
142
+
143
+ 若要一次性修复整个文件,运行 `npx intlayer extract`,让编译器自动将字符串移入字典。
144
+
145
+ **配置选项**
146
+
147
+ ```javascript fileName="eslint.config.mjs"
148
+ {
149
+ "intlayer/no-raw-text": [
150
+ "warn",
151
+ {
152
+ // 值为面向用户文本的属性列表。
153
+ // 默认值: title, placeholder, alt, aria-label, label
154
+ attributes: ["title", "placeholder", "alt", "aria-label", "label"],
155
+
156
+ // 内容绝非面向用户文本的元素列表。
157
+ // 默认值: code, pre, script, style
158
+ ignoreElements: ["code", "pre", "script", "style"],
159
+
160
+ // 绝不报告的文本正则表达式。
161
+ ignorePatterns: ["^Powered by"],
162
+
163
+ // 是否同时报告标记语言之外的字符串字面量。默认值: false
164
+ includeStringLiterals: false,
165
+ },
166
+ ],
167
+ }
168
+ ```
169
+
170
+ ### `static-dictionary-key`
171
+
172
+ 要求字典键必须是字符串字面量。
173
+
174
+ 编译器只有在调用位置直接读取到键时,才能预加载字典。使用计算键会静默跳过优化,转而打包所有字典。
175
+
176
+ ```typescript
177
+ // ✗ 报告错误
178
+ useIntlayer(dictionaryKey);
179
+ useIntlayer(`home-${suffix}`);
180
+ getTranslations({ namespace: page });
181
+
182
+ // ✗ 变量仍然不是字面量
183
+ const key = "home";
184
+ useIntlayer(key);
185
+
186
+ // ✓ 正常
187
+ useIntlayer("home");
188
+ getTranslations({ namespace: "home" });
189
+ ```
190
+
191
+ 这适用于 `useIntlayer`、`getIntlayer` 以及所有兼容适配器(`useTranslation`、`useTranslations`、`formatMessage`、`<FormattedMessage id>`、`<Trans i18nKey>` 等)。
192
+
193
+ ### `no-dynamic-field-access`
194
+
195
+ 要求从字典中读取的字段必须是静态已知的。
196
+
197
+ 编译器会移除它未检测到使用的字段。动态计算访问对其不可见,因此该读取在运行时可能会返回 `undefined`。
198
+
199
+ ```typescript
200
+ // ✗ 报告错误
201
+ const content = useIntlayer("home");
202
+ content[fieldName];
203
+
204
+ const t = useTranslations("home");
205
+ t(messageKey);
206
+
207
+ // ✓ 正常
208
+ content.title;
209
+ content["title"];
210
+ content.items[0];
211
+ t("hero.title");
212
+ ```
213
+
214
+ ### `enforce-adapter-import`
215
+
216
+ 优先使用 `@intlayer/*` 兼容适配器而非原始包。原始包仅在配置了打包工具别名时才会解析为 Intlayer;而适配器始终生效。可通过 `--fix` 自动修复。
217
+
218
+ ```typescript
219
+ // ✗ 报告错误
220
+ import { useTranslation } from "react-i18next";
221
+ import { getTranslations } from "next-intl/server";
222
+
223
+ // ✓ 正常
224
+ import { useTranslation } from "@intlayer/react-i18next";
225
+ import { getTranslations } from "@intlayer/next-intl/server";
226
+ ```
227
+
228
+ ### `no-unused-content`
229
+
230
+ **默认关闭。** 报告项目中没有任何地方读取的内容,以及在多个位置声明的字典键。
231
+
232
+ ```typescript fileName="src/home.content.ts"
233
+ export default {
234
+ key: "home", // ✗ 当项目中没有任何调用方请求 "home" 时报告
235
+ content: {
236
+ title: t({ zh: "标题", en: "Title" }),
237
+
238
+ // ✗ 当没有任何地方读取 `hero` 时报告
239
+ hero: {
240
+ subtitle: t({ zh: "副标题", en: "Subtitle" }),
241
+ },
242
+ },
243
+ };
244
+ ```
245
+
246
+ 与其他规则不同,此规则无法仅凭眼前的文件给出判断 — 字段是否未使用仅相对于整个项目而言。在一次 lint 运行的首次内容声明时,它会加载你的 Intlayer 配置,匹配该配置声明的源文件(`build.traversePattern`、`compiler.transformPattern`),并运行驱动 `@intlayer/lsp` 和 VS Code 扩展中“未使用”删除线的同一套使用情况分析器。结果会缓存 `cacheTtl` 毫秒,因此每次运行只会扫描一次,而不是每个文件扫描一次。
247
+
248
+ **配置选项**
249
+
250
+ ```javascript fileName="eslint.config.mjs"
251
+ {
252
+ "intlayer/no-unused-content": [
253
+ "warn",
254
+ {
255
+ // 报告没有任何地方引用的字典键。默认值: true
256
+ reportUnusedDictionaries: true,
257
+
258
+ // 报告没有任何地方读取的内容字段。默认值: true
259
+ reportUnusedFields: true,
260
+
261
+ // 报告在多处声明的重复键。默认值: true
262
+ reportDuplicateKeys: true,
263
+
264
+ // 绝不报告的字段路径正则表达式。
265
+ ignoreFields: ["^meta"],
266
+
267
+ // 扫描起始的项目根目录。默认值: ESLint 的工作目录
268
+ baseDir: process.cwd(),
269
+
270
+ // 项目扫描结果复用时长(毫秒)。默认值: 30000
271
+ cacheTtl: 30000,
272
+ },
273
+ ],
274
+ }
275
+ ```
276
+
277
+ 如果你在长期运行的编辑器服务中进行 lint 且希望更快看到修改结果,可以降低 `cacheTtl`;当单次 lint 运行跨越 monorepo 中的多个 Intlayer 项目时,请设置 `baseDir`。
278
+
279
+ > **倾向于保持沉默。** 此处的误报会导致翻译被误删,因此当字典以分析器无法跟踪的方式被使用时,不会报告任何内容:内容对象被整体传递、从中绑定的翻译函数(`const t = useTranslations("home")`)、通过直接导入访问的声明(`useDictionary(myDictionary)`)、来自另一个字典的 `nest()`、或者因 spread 展开而不详尽的字段列表。单文件组件(`.vue`、`.svelte`、`.astro`)计为使用了它们提及的字典中的所有字段,因为它们的脚本块在此处不会被解析。
280
+
281
+ `reportDuplicateKeys` 读取构建时写入 `.intlayer/` 下的未合并字典,因此在项目至少构建过一次之前它会保持静默。共享一个键的两个声明会被合并,这是一种合法的模式 — 该报告之所以存在,是因为在两边同时定义的字段会静默保留两个值中的一个。
282
+
283
+ 分析器从以 ESM 形式分发的 `@intlayer/lsp` 中加载。因此该规则需要能够 `require()` ES 模块的 Node 版本 — Node 20.19+ 或 22.12+。在更低版本上,它不会报错中断 lint 运行,而是什么都不报告。
284
+
285
+ ## 框架支持
286
+
287
+ 每条规则均适用于所有 Intlayer 集成,包括 Vue、Svelte 和 Angular 模板内部。你只需告诉 ESLint 哪个解析器负责读取对应的文件类型即可。
288
+
289
+ | 框架 | 文件 | 解析器 |
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 模板 | `.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
+ 请仅安装项目所需的解析器。
335
+
336
+ > **已知局限性。** 在 Vue 和 Angular 模板中,类似于 `{{ content[key] }}` 的表达式不会被 `no-dynamic-field-access` 检查。写在 script 块中的动态读取仍会被正常捕获。
@@ -612,6 +612,10 @@ export default App;
612
612
  - 根据语言环境调整 **文本方向** (`dir`),提升不同阅读顺序语言的可读性和可用性。
613
613
  - 提供更 **无障碍** 的体验,因为辅助技术依赖这些属性以实现最佳功能。
614
614
 
615
+ </Step>
616
+
617
+ </Steps>
618
+
615
619
  ### 配置 TypeScript
616
620
 
617
621
  Intlayer 使用模块增强来利用 TypeScript 的优势,使您的代码库更强大。
@@ -67,6 +67,10 @@ Intlayer 不仅仅是一个 i18n 解决方案,还提供了一个**自托管的
67
67
 
68
68
  ---
69
69
 
70
+ <Steps>
71
+
72
+ <Step number={1} title="安装依赖">
73
+
70
74
  ### Packages
71
75
 
72
76
  - **intlayer**
@@ -531,8 +531,6 @@ const ServerComponentExample: FC = () => {
531
531
 
532
532
  > 若要了解有关 `useIntlayer` 钩子的更多信息,请参阅[文档](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/packages/next-intlayer/useIntlayer.md)。
533
533
 
534
- <Steps>
535
-
536
534
  </Step>
537
535
 
538
536
  <Step number={8} title="元数据的国际化">
@@ -433,8 +433,6 @@ export const ServerComponentExample: FC = () => {
433
433
 
434
434
  > 要了解有关 `useIntlayer` 钩子的更多信息,请参阅[文档](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/packages/next-intlayer/useIntlayer.md)。
435
435
 
436
- <Steps>
437
-
438
436
  </Step>
439
437
 
440
438
  <Step number={7} title="配置中间件以检测语言环境">
@@ -514,8 +514,6 @@ const ComponentExample = () => {
514
514
 
515
515
  > 要了解有关 `useIntlayer` 钩子的更多信息,请参阅[文档](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/packages/next-intlayer/useIntlayer.md)。
516
516
 
517
- <Steps>
518
-
519
517
  </Step>
520
518
 
521
519
  <Step number={8} title="元数据的国际化">
@@ -314,7 +314,7 @@ Intlayer 提供了多种 API 来访问您的内容:
314
314
  - 使用 `const content = useIntlayer("myContent");` 以及 `{{ content.myContent }}` / `<content.myContent />`。
315
315
  - 或者使用 `const { myContent } = useIntlayer("myContent");` 以及 `{{ myContent}}` / `<myContent/>` 来解构内容。
316
316
 
317
- <Steps>
317
+ </Step>
318
318
 
319
319
  <Step number={6} title="更改内容语言">
320
320
 
@@ -198,6 +198,10 @@ export default config;
198
198
 
199
199
  > 通过此配置文件,您可以设置本地化的 URL、中间件重定向、cookie 名称、内容声明的位置和扩展名,禁用控制台中的 Intlayer 日志等。有关可用参数的完整列表,请参阅[配置文档](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/configuration.md)。
200
200
 
201
+ <Steps>
202
+
203
+ <Step number={5} title="创建根布局">
204
+
201
205
  #### 根布局
202
206
 
203
207
  ```tsx fileName="app/root.tsx"
@@ -131,6 +131,10 @@ export default config;
131
131
 
132
132
  > 通过此配置文件,您可以设置本地化的 URL、中间件重定向、cookie 名称、内容声明的位置和扩展名,禁用控制台中的 Intlayer 日志等。有关可用参数的完整列表,请参阅[配置文档](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/configuration.md)。
133
133
 
134
+ <Steps>
135
+
136
+ <Step number={5} title="创建根布局">
137
+
134
138
  #### 文件结构
135
139
 
136
140
  ```bash
@@ -572,7 +572,7 @@ export const Nav: Component = () => {
572
572
 
573
573
  <Step number={10} title="创建语言切换器组件">
574
574
 
575
- 将切换器渲染为**真实的 <a> 锚点**而非 `<select>`:当前页面的每种语言都会变为可爬取的链接,并且可以在新标签页中打开,这是仅依靠 JavaScript 的控件无法提供的。
575
+ 将切换器渲染为**真实的 `<a>` 锚点**而非 `<select>`:当前页面的每种语言都会变为可爬取的链接,并且可以在新标签页中打开,这是仅依靠 JavaScript 的控件无法提供的。
576
576
 
577
577
  `getPathWithoutLocale` 会从当前路径中剥离语言段,而 `getLocalizedUrl` 会为目标语言重新构建它,因此这些链接会遵循你的路由模式,无需硬编码任何内容。导航是改变渲染语言的原因 —— `[[locale]]` 路由从 URL 中推导语言 —— 而 `setLocale` 会将选择保存在 `INTLAYER_LOCALE` cookie 中,以便以后访问无语言前缀的 URL 时能解析为相同的语言。
578
578
 
@@ -444,8 +444,6 @@ Intlayer 提供了多种 API 来访问您的内容:
444
444
 
445
445
  > 如果您的应用程序已经存在,您可以结合使用 [Intlayer 编译器](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/compiler.md) 和 [提取命令](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/cli/extract.md) 在一秒钟内转换成干个组件。
446
446
 
447
- <Steps>
448
-
449
447
  </Step>
450
448
 
451
449
  <Step number={6} title="更改内容语言">
@@ -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 {