i18n-easy 1.0.0

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 (70) hide show
  1. package/README.md +527 -0
  2. package/esm/assets/const.js +7 -0
  3. package/esm/ast_transformer.d.ts +19 -0
  4. package/esm/ast_transformer.js +54 -0
  5. package/esm/eslint/react/i18n_easy_plugin.d.ts +3 -0
  6. package/esm/eslint/react/i18n_easy_plugin.js +111 -0
  7. package/esm/eslint/react/i18n_utils.d.ts +61 -0
  8. package/esm/eslint/react/i18n_utils.js +115 -0
  9. package/esm/eslint/react/report_and_fix.d.ts +67 -0
  10. package/esm/eslint/react/report_and_fix.js +118 -0
  11. package/esm/eslint/vue/i18n_easy_plugin.d.ts +5 -0
  12. package/esm/eslint/vue/i18n_easy_plugin.js +141 -0
  13. package/esm/eslint/vue/i18n_utils.d.ts +65 -0
  14. package/esm/eslint/vue/i18n_utils.js +133 -0
  15. package/esm/eslint/vue/report_and_fix.d.ts +8 -0
  16. package/esm/eslint/vue/report_and_fix.js +169 -0
  17. package/esm/file_processor_utils.d.ts +14 -0
  18. package/esm/file_processor_utils.js +68 -0
  19. package/esm/i18n_easy.d.ts +77 -0
  20. package/esm/i18n_easy.js +171 -0
  21. package/esm/index.d.ts +4 -0
  22. package/esm/index.js +9 -0
  23. package/esm/key_map.d.ts +14 -0
  24. package/esm/key_map.js +51 -0
  25. package/esm/patch.d.ts +5 -0
  26. package/esm/progressBus.d.ts +7 -0
  27. package/esm/progressBus.js +25 -0
  28. package/esm/translate.d.ts +34 -0
  29. package/esm/translate.js +107 -0
  30. package/esm/type.d.ts +94 -0
  31. package/esm/type.js +0 -0
  32. package/esm/utils.d.ts +54 -0
  33. package/esm/utils.js +102 -0
  34. package/lib/assets/const.js +32 -0
  35. package/lib/ast_transformer.js +88 -0
  36. package/lib/cli.d.ts +2 -0
  37. package/lib/cli.js +5 -0
  38. package/lib/eslint/react/i18n_easy_plugin.js +131 -0
  39. package/lib/eslint/react/i18n_utils.js +145 -0
  40. package/lib/eslint/react/report_and_fix.js +156 -0
  41. package/lib/eslint/vue/i18n_easy_plugin.js +161 -0
  42. package/lib/eslint/vue/i18n_utils.js +164 -0
  43. package/lib/eslint/vue/report_and_fix.js +203 -0
  44. package/lib/file_processor_utils.js +109 -0
  45. package/lib/i18n_easy.js +205 -0
  46. package/lib/index.js +35 -0
  47. package/lib/key_map.js +71 -0
  48. package/lib/package.json +3 -0
  49. package/lib/patch.d.ts +5 -0
  50. package/lib/progressBus.js +50 -0
  51. package/lib/translate.js +127 -0
  52. package/lib/type.js +17 -0
  53. package/lib/utils.js +142 -0
  54. package/package.json +68 -0
  55. package/types/assets/const.d.ts +2 -0
  56. package/types/ast_transformer.d.ts +19 -0
  57. package/types/eslint/react/i18n_easy_plugin.d.ts +3 -0
  58. package/types/eslint/react/i18n_utils.d.ts +61 -0
  59. package/types/eslint/react/report_and_fix.d.ts +67 -0
  60. package/types/eslint/vue/i18n_easy_plugin.d.ts +5 -0
  61. package/types/eslint/vue/i18n_utils.d.ts +65 -0
  62. package/types/eslint/vue/report_and_fix.d.ts +8 -0
  63. package/types/file_processor_utils.d.ts +14 -0
  64. package/types/i18n_easy.d.ts +77 -0
  65. package/types/index.d.ts +4 -0
  66. package/types/key_map.d.ts +14 -0
  67. package/types/progressBus.d.ts +6 -0
  68. package/types/translate.d.ts +34 -0
  69. package/types/type.d.ts +94 -0
  70. package/types/utils.d.ts +54 -0
package/README.md ADDED
@@ -0,0 +1,527 @@
1
+ # i18n-easy
2
+
3
+ ## 介绍
4
+
5
+ - 一键替换中文字符为国际化书写方式,适用于 `vue2/vue3/react`;
6
+ - 支持文件类型:`vue/js/ts/jsx/tsx`;
7
+
8
+ ## 配置
9
+
10
+ - `js` 配置适用于`js/ts`文件,`jsx` 配置适用于` jsx/tsx` 文件;
11
+ - 相关`ts`类型;
12
+
13
+ ```typescript
14
+ // 语言配置
15
+ interface LangType {
16
+ name: string // 目标翻译语言
17
+ i18nFilePath: string // 语言文件地址
18
+ }
19
+
20
+ // vue中国际化配置
21
+ interface I18nInfoType {
22
+ template?: {
23
+ // vue模版中配置
24
+ callMethodName: string // 国际化调用方法m
25
+ }
26
+ script?: {
27
+ // vue选项式api脚本中配置
28
+ callMethodName: string // 国际化调用方法
29
+ injectImport?: string // 注入导入语句代码
30
+ injectCodeToTopLevel?: string // 注入到顶部的代码
31
+ }
32
+ scriptSetup?: {
33
+ // vue组合式api脚本中配置
34
+ callMethodName: string // 国际化调用方法
35
+ injectImport?: string // 注入导入语句代码
36
+ injectHooksCall?: string // 注入的hooks调用代码
37
+ injectCodeToTopLevel?: string // 注入到顶部的代码
38
+ }
39
+ js?: {
40
+ // vue框架中js、ts文件配置
41
+ callMethodName: string // 国际化调用方法
42
+ injectImport?: string // 注入导入语句代码
43
+ injectCodeToTopLevel?: string // 注入到顶部的代码
44
+ }
45
+ jsx?: {
46
+ // vue框架中使用jsx、tsx文件配置
47
+ callMethodName: string // 国际化调用方法
48
+ injectImport?: string // 注入导入语句代码
49
+ injectCodeToTopLevel?: string // 注入到顶部的代码
50
+ }
51
+ }
52
+
53
+ // react中国际化配置
54
+ interface ReactI18nInfoType {
55
+ js?: {
56
+ // js、ts文件中配置
57
+ callMethodName: string // 国际化调用方法
58
+ injectImport?: string // 注入导入语句代码
59
+ injectCodeToTopLevel?: string // 注入到顶部的代码
60
+ }
61
+ jsx?: {
62
+ // jsx、tsx文件中配置
63
+ callMethodName: string // 国际化调用方法
64
+ injectImport?: string // 注入导入语句代码
65
+ injectHooksCall?: string // 注入的hooks调用代码
66
+ injectCodeToTopLevel?: string // 注入到顶部的代码
67
+ }
68
+ }
69
+
70
+ // jsxText节点
71
+ interface JSXText extends ESTree.BaseNode, ESTree.BaseExpression {
72
+ type: 'JSXText'
73
+ value: string
74
+ raw: string | undefined
75
+ }
76
+
77
+ // vue中文本节点
78
+ type TextNode = AST.VText | AST.VAttribute | ESTree.TemplateLiteral | (ESTree.Literal & Rule.NodeParentExtension) | JSXText
79
+
80
+ // react中文本节点
81
+ type ReactTextNode = ESTree.TemplateLiteral | (ESTree.Literal & Rule.NodeParentExtension) | JSXText
82
+
83
+ // 项目框架类型
84
+ type Framework = 'vue' | 'react'
85
+
86
+ // 配置文件生成对象键类型
87
+ type KeyType = 'hash' | 'pinyin' | 'pinyinWithNumber'
88
+
89
+ // fileToI18n方法options配置类型
90
+ interface FileToI18nConfig<T extends Framework> {
91
+ type: T // 框架类型
92
+ keyType?: KeyType // 生成的国际化文件key类型 默认为pinyin
93
+ i18nInfo: T extends 'vue' ? I18nInfoType : ReactI18nInfoType // 国际化配置信息
94
+ customIgnore?: (node: T extends 'vue' ? TextNode : ReactCollectItemType['textNode'], context: Rule.RuleContext) => boolean // 自定义判断节点是否忽略
95
+ }
96
+
97
+ // fileToI18nAndTranslate方法options配置类型
98
+ interface FileToI18nAndTranslateConfig<T extends Framework> extends FileToI18nConfig<T> {
99
+ lang: string[] // 目标语言列表
100
+ apiKey: string // 翻译API key
101
+ }
102
+
103
+ // 完整配置类型
104
+ interface Config<T extends Framework> {
105
+ projects: {
106
+ projectPath: string // 项目路径
107
+ lang: LangType[] // 语言配置
108
+ i18nInfo: T extends 'vue' ? I18nInfoType : ReactI18nInfoType // 国际化信息配置
109
+ keyType: KeyType // 生成的国际化文件key类型
110
+ type: T // 项目框架类型
111
+ customIgnore?: (node: T extends 'vue' ? TextNode : ReactTextNode, context: Rule.RuleContext) => boolean // 自定义是否忽略节点的国际化处理 true不处理 false处理
112
+ }[] // 项目配置
113
+ apiKey: string // 翻译API key
114
+ }
115
+ ```
116
+
117
+ - `js`:配置项用于`js` 文件、`ts`文件;
118
+ - `jsx`:配置项用于`jsx` 文件、`tsx`文件;
119
+ - `template`:`vue`中`template` 模块;
120
+ - `script`:`vue选项式api`中`script`模块;
121
+ - `scriptSetup`:`vue组合式api`中`script`模块;
122
+
123
+ ## 使用说明
124
+
125
+ 1. 安装`i18n-easy`,`npm install i18n-easy`;
126
+
127
+ 2. 在项目根目录下新建`i18n_easy.js/i18n_easy.ts文件`;
128
+
129
+ 3. 在文件中配置转换规则,插件中导出了`defineConfig方法`,推荐使用`defineConfig`进行配置,例如:
130
+
131
+ ```typescript
132
+ import { defineConfig } from 'i18n-easy'
133
+
134
+ export default defineConfig({
135
+ projects: [
136
+ {
137
+ projectPath: './',
138
+ lang: [
139
+ {
140
+ name: 'en',
141
+ i18nFilePath: './lang/english.json',
142
+ },
143
+ {
144
+ name: 'zh',
145
+ i18nFilePath: './lang/chinese.json',
146
+ },
147
+ ],
148
+ i18nInfo: {
149
+ template: {
150
+ callMethodName: '$t',
151
+ },
152
+ script: {
153
+ callMethodName: 'this.$t',
154
+ },
155
+ scriptSetup: {
156
+ callMethodName: '$t',
157
+ injectImport: "import useI18n from 'vue-i18n'",
158
+ injectHooksCall: 'const { t: $t } = useI18n()',
159
+ },
160
+ js: {
161
+ callMethodName: 'i18n.t',
162
+ injectImport: "import i18n from '@/i18n/i18n.js'",
163
+ },
164
+ jsx: {
165
+ callMethodName: 'vm.$t',
166
+ },
167
+ },
168
+ keyType: 'pinyinWithNumber',
169
+ type: 'vue',
170
+ },
171
+ ],
172
+ apiKey: '',
173
+ })
174
+ ```
175
+
176
+ 4. 将待替换的文件放入`git`暂存区(`git add`区域,只会替换`git`暂存区中的文件,并且替换**文件最新内容**);
177
+
178
+ 5. 在终端执行`npx i18n-easy`命令(需在项目根目录下执行,在处理文件路径时,会以项目根目录为基准);
179
+
180
+ ## I18nEasy类
181
+
182
+ `i18n-easy`包提供了`I18nEasy`类的导出,可供用户自行调用;
183
+
184
+ 1. 导入方法:
185
+ - `esm`模块:`import { I18nEasy } from 'i18n-easy';`
186
+ - `commonjs`模块:`const { I18nEasy } = require('i18n-easy');`
187
+
188
+ 2. 类`I18nEasy`中提供了部分方法:
189
+ - `transformModifiedFiles`:获取`git`暂存区文件进行国际化转换、翻译,并更新语言文件(命令`npx i18n-easy`底层也是调用此方法);注意:使用此方法将读取配置``i18n_easy.js/i18n_easy.ts`信息;
190
+ - 参数:无
191
+ - 返回值:无
192
+
193
+ ```typescript
194
+ import { I18nEasy } from 'i18n-easy // 导入I18nEasy类
195
+
196
+ const i18nEasy = new I18nEasy()
197
+ // 调用transformModifiedFiles方法(将使用配置文件i18n_easy.js/i18n_easy.ts配置信息)
198
+ i18nEasy.transformModifiedFiles().then()
199
+ ```
200
+
201
+ - `fileToI18n`:将指定文件转换成国际化写法(不进行翻译),并返回处理结果;
202
+ - 参数:
203
+ - `filePath`:文件绝对路径;
204
+ - `options`:配置项信息,具体可见配置相关ts类型中[`FileToI18nConfig`类型](#配置);
205
+ - 返回`Promise`:
206
+ - `oldFileContent`:转换前的文件内容;
207
+ - `newFileContent`: 转换后的文件内容;
208
+ - `fixed`:是否进行转换;
209
+ - `filePath`: 文件路径;
210
+ - `keyValueMap`:文件中的转换字段;
211
+
212
+ ```typescript
213
+ import { I18nEasy } from 'i18n-easy
214
+
215
+ const i18nEasy = new I18nEasy()
216
+
217
+ const filePath = '/Users/code/1.js' // 文件绝对路径
218
+ const config = { // 配置项
219
+ type: 'vue',
220
+ keyType: 'pinyinWithNumber',
221
+ i18nInfo: {
222
+ js: {
223
+ callMethodName: "i18n.t",
224
+ injectImport: "import i18n from '@/i18n/i18n.js'",
225
+ },
226
+ }
227
+ }
228
+
229
+ i18nEasy.fileToI18n(filePath, config).then()
230
+ ```
231
+
232
+ - `fileToI18nAndTranslate`:将指定文件转换成国际化写法并进行翻译,并返回处理结果;
233
+ - 参数:
234
+ - `filePath`:文件绝对路径;
235
+ - `options`:配置项信息,具体可见相关ts类型中[`FileToI18nAndTranslateConfig`类型](#配置);
236
+ - 返回`Promise`:
237
+ - `oldFileContent`:转换前的文件内容;
238
+ - `newFileContent`: 转换后的文件内容;
239
+ - `fixed`:是否进行转换;
240
+ - `filePath`: 文件路径;
241
+ - `keyValueMap`:文件中的转换字段;
242
+ - `translateResult`:翻译后的语言字段
243
+
244
+ ```typescript
245
+ import { I18nEasy } from 'i18n-easy
246
+
247
+ const i18nEasy = new I18nEasy()
248
+
249
+ const filePath = '/Users/code/1.js' // 文件绝对路径
250
+ const config = { // 配置项
251
+ type: 'vue',
252
+ keyType: 'pinyinWithNumber',
253
+ i18nInfo: {
254
+ js: {
255
+ callMethodName: "i18n.t",
256
+ injectImport: "import i18n from '@/i18n/i18n.js'",
257
+ },
258
+ },
259
+ apiKey: '微软翻译apikey',
260
+ lang: ['en', 'zh'],
261
+ }
262
+
263
+ i18nEasy.fileToI18nAndTranslate(filePath, config).then()
264
+ ```
265
+
266
+ - `fileToI18nAndTranslateBatch`:将指定文件列表批量转换成国际化写法并进行翻译,并返回处理结果:
267
+ - 参数:
268
+ - `filePaths`:文件绝对路径数组;
269
+ - `options`:配置项信息,具体可见相关ts类型中[`FileToI18nAndTranslateConfig`类型](#配置);
270
+ - 返回`Promise`:
271
+ - `transformResult`:转换结果数组;
272
+ - `oldFileContent`:转换前的文件内容;
273
+ - `newFileContent`: 转换后的文件内容;
274
+ - `fixed`:是否进行转换;
275
+ - `filePath`: 文件路径;
276
+ - `keyValueMap`:文件中的转换字段;
277
+ - `translateResult`:翻译后的语言字段;
278
+
279
+ ```typescript
280
+ import { I18nEasy } from 'i18n-easy
281
+
282
+ const i18nEasy = new I18nEasy()
283
+
284
+ const filePaths = ['/Users/code/1.js'] // 文件绝对路径
285
+ const config = { // 配置项
286
+ type: 'vue',
287
+ keyType: 'pinyinWithNumber',
288
+ i18nInfo: {
289
+ js: {
290
+ callMethodName: "i18n.t",
291
+ injectImport: "import i18n from '@/i18n/i18n.js'",
292
+ },
293
+ },
294
+ apiKey: '微软翻译apikey',
295
+ lang: ['en', 'zh'],
296
+ }
297
+
298
+ i18nEasy.fileToI18nAndTranslateBatch(filePaths, config).then()
299
+ ```
300
+
301
+ ## 注意事项
302
+
303
+ 1. 当在 `vue` 文件中使用 `script` 标签的`src`属性引入**外部js、ts**时,需保证对应引入文件与**当前vue文件在同一目录下**。否则将以**js、ts配置**进行替换以及代码注入;
304
+
305
+ 2. 当在 `vue` 文件中使用 `script` 标签的`src`属性引入**外部js、ts**时,**对应js、ts文件**最好使用类型`export default {}` 或者 `export default defineComponent({})`的形式,否则将以 `script` 配置进行替换以及代码注入,而无法判断是否采用`scriptSetup`配置;
306
+
307
+ 3. 当函数参数为中文时会进行国际化替换,如需不进行替换,可使用注释`// @i18n-ignore`,例如:
308
+
309
+ ```typescript
310
+ // @i18n-ignore
311
+ fn(`不会被替换`) // 中文不会被替换
312
+
313
+ /* @i18n-ignore */
314
+ fn(`不会被替换`) // 中文不会被替换
315
+ ```
316
+
317
+ 4. 如需自定义是否替换指定节点可以通过配置函数`customIgnore`来实现,例如:
318
+
319
+ ```typescript
320
+ import { defineConfig } from 'i18n-easy'
321
+
322
+ export default defineConfig({
323
+ projects: [
324
+ {
325
+ projectPath: './',
326
+ lang: [
327
+ {
328
+ name: 'en',
329
+ i18nFilePath: './lang/english.json',
330
+ },
331
+ ],
332
+ i18nInfo: {
333
+ js: {
334
+ callMethodName: 'i18n.t',
335
+ injectImport: "import i18n from '@/i18n/i18n.js'",
336
+ },
337
+ },
338
+ keyType: 'pinyinWithNumber',
339
+ type: 'vue',
340
+ /**
341
+ * 自定义是否忽略节点的国际化处理 返回true不处理 false处理
342
+ * node为将要替换的节点(具体类型查看配置部分)
343
+ * context为eslint规则上下文(具体类型方法可查看eslint官方文档)
344
+ */
345
+ customIgnore: (node, context) => {
346
+ return node.type === 'JSXText'
347
+ },
348
+ },
349
+ ],
350
+ apiKey: '',
351
+ })
352
+ ```
353
+
354
+ 5. `vue`框架中支持使用`jsx`写法,但存在以下限制:
355
+ - 对于文件后缀名为`vue`但使用`jsx`写法的文件将根据是否使用`组合式api`而应用`script`或`scriptSetup`配置,例如:
356
+
357
+ ```vue
358
+ // test.vue(选项式api使用script配置)
359
+ <script lang="jsx">
360
+ export default {
361
+ data() {
362
+ return {
363
+ str: '中文',
364
+ }
365
+ },
366
+ methods: {
367
+ handleClick() {},
368
+ },
369
+ render() {
370
+ return (
371
+ <>
372
+ <div>中文</div>
373
+ </>
374
+ )
375
+ },
376
+ }
377
+ </script>
378
+
379
+ // test.vue(组合式api使用scriptSetup配置)
380
+ <script lang="jsx">
381
+ export default defineComponent({
382
+ setup() {
383
+ const str = '中文'
384
+ function handleClick() {}
385
+ return () => (
386
+ <>
387
+ <div>中文</div>
388
+ </>
389
+ )
390
+ },
391
+ })
392
+ </script>
393
+ ```
394
+
395
+ - 对于文件后缀名为`jsx`但使用`组合式api`将应`scriptSetup`配置(因为仍使用`setup`来实现组件),例如:
396
+
397
+ ```jsx
398
+ // test.jsx(组合式api将采用scriptSetup配置)
399
+ export default defineComponent({
400
+ setup() {
401
+ const str = '中文';
402
+ function handleClick() {}
403
+ return () => (
404
+ <>
405
+ <div>中文</div>
406
+ </>
407
+ );
408
+ },
409
+ });
410
+
411
+ // test.jsx(组合式api将采用scriptSetup配置)
412
+ export default {
413
+ setup() {
414
+ const str = '中文';
415
+ function handleClick() {}
416
+ return () => (
417
+ <>
418
+ <div>中文</div>
419
+ </>
420
+ );
421
+ },
422
+ };
423
+ ```
424
+
425
+ 6. `npx i18n-easy`会替换 git **暂存区**中文件的**最新内容**,例如:当前暂存区存在文件`test.js`,又修改`test.js`文件内容后,此时暂存区和更改区均存在`test.js`文件,但是更改区的`test.js`文件内容才是最新的,进行`cli`国际化替换操作将对文件最新内容进行替换;
426
+
427
+ 7. 对于`vue`框架,仅支持`vue、js、jsx、ts、tsx`文件,对于`react`框架;仅支持`js、jsx、ts、tsx`文件,其他文件类型将被忽略;
428
+
429
+ 8. 由于使用`cli`国际化操作会根据项目对文件进行分组,因此不在配置文件的项目路径下的文件,也将被忽略,例如:
430
+
431
+ ```js
432
+ import { defineConfig } from 'i18n-easy'
433
+
434
+ export default defineConfig({
435
+ projects: [
436
+ {
437
+ projectPath: './yourProjectPath', // 项目地址
438
+ lang: [
439
+ {
440
+ name: 'en',
441
+ i18nFilePath: './lang/english.json',
442
+ },
443
+ ],
444
+ i18nInfo: {
445
+ js: {
446
+ callMethodName: 'i18n.t',
447
+ injectImport: "import i18n from '@/i18n/i18n.js'",
448
+ },
449
+ },
450
+ keyType: 'pinyinWithNumber',
451
+ type: 'vue',
452
+ },
453
+ ],
454
+ apiKey: '',
455
+ })
456
+ ```
457
+
458
+ - 此时配置项目路径为`./yourProjectPath`,在处理过程中会过滤掉不在`./yourProjectPath`路径下的后代文件;
459
+
460
+ 9. 国际化语言文件仅支持`js、ts、json`文件格式,并且推荐使用以下任意格式,否则可能会出现语言文件内容解析失败问题;
461
+
462
+ ```js
463
+ // 1. en.js(ts同理)
464
+ module.exports = {
465
+ // 键值对
466
+ }
467
+
468
+ // 2. en.js(ts同理)
469
+ export default {
470
+ // 键值对
471
+ }
472
+
473
+
474
+ // 3. en.json
475
+ {
476
+ // 键值对
477
+ }
478
+
479
+
480
+ // en.js (会替换失败)
481
+ const obj = {
482
+ // 键值对
483
+ }
484
+
485
+ export default obj
486
+ ```
487
+
488
+ 10. 对于转换模版字符串,变量将以对象的形式作为国际化调用方法的参数,并且对象`key`为`arg1~arg9`例如:
489
+
490
+ ```js
491
+ // 原始代码
492
+ const a = `你好${1 * 1}${1 + 1}`
493
+
494
+ // 转换后代码(例如调用方法为$t)
495
+ const a = $t('ni_hao_arg1_arg2', { arg1: 1 * 1, arg2: 1 + 1 })
496
+
497
+ // 语言字段
498
+ {
499
+ ni_hao_arg1_arg2: '你好{arg1}{arg2}'
500
+ }
501
+ ```
502
+
503
+ 11. 对于配置文件中的调用方法,例如:`$t`,在转换时会将键值作为第一个参数,参数对象作为第二个参数,例如:
504
+
505
+ ```jsx
506
+ // 原始代码
507
+ const a = `你好${1 * 1}${1 + 1}`
508
+
509
+ // 转换后代码(例如调用方法为$t)
510
+ const a = $t('ni_hao_arg1_arg2', { arg1: 1 * 1, arg2: 1 + 1 })
511
+
512
+ // 当使用国际化工具不支持这种传参时,可以对调用方法进行二次调用,例如:
513
+ import { useIntl } from 'umi'
514
+
515
+ // 自定义hooks,配置文件中使用customizeFormatMessage作为调用名称
516
+ function useCustomizeI18n() {
517
+ const { formatMessage } = useIntl()
518
+
519
+ function customizeFormatMessage(key, params) {
520
+ return params ? formatMessage({ id: key }, params) : formatMessage({ id: key })
521
+ }
522
+
523
+ return {
524
+ customizeFormatMessage,
525
+ }
526
+ }
527
+ ```
@@ -0,0 +1,7 @@
1
+ // src/assets/const.ts
2
+ var configFileNames = ["i18n_easy.mjs", "i18n_easy.cjs", "i18n_easy.js", "i18n_easy.ts", "i18n_easy.json"];
3
+ var checkReg = /(module\.exports\s*=\s*|export\s*default\s*)?({[\s\S]*})/;
4
+ export {
5
+ checkReg,
6
+ configFileNames
7
+ };
@@ -0,0 +1,19 @@
1
+ import { Framework, SupportFileMap, I18nInfoType, ReactI18nInfoType, TextNode, ReactCollectItemType } from './type.js';
2
+ import { type Rule } from 'eslint';
3
+ interface Props<T extends Framework> {
4
+ fileContent: string;
5
+ fileName: string;
6
+ fileType: SupportFileMap[T];
7
+ type: T;
8
+ i18nInfo: T extends 'vue' ? I18nInfoType : ReactI18nInfoType;
9
+ customIgnore?: (node: T extends 'vue' ? TextNode : ReactCollectItemType['textNode'], context: Rule.RuleContext) => boolean;
10
+ }
11
+ export declare class AstTransformer {
12
+ private linter;
13
+ constructor();
14
+ convertFileContent<T extends Framework>(props: Props<T>): {
15
+ newFileContent: string;
16
+ fixed: boolean;
17
+ };
18
+ }
19
+ export {};
@@ -0,0 +1,54 @@
1
+ // src/ast_transformer.ts
2
+ import { Linter } from "eslint";
3
+ import i18nEasyVue from "./eslint/vue/i18n_easy_plugin.js";
4
+ import i18nEasyReact from "./eslint/react/i18n_easy_plugin.js";
5
+ import * as vueParser from "vue-eslint-parser";
6
+ import * as espree from "espree";
7
+ import tsParser from "@typescript-eslint/parser";
8
+ var AstTransformer = class {
9
+ linter;
10
+ constructor() {
11
+ this.linter = new Linter();
12
+ }
13
+ // 转换文件内容
14
+ convertFileContent(props) {
15
+ const { fileContent, fileType, fileName, i18nInfo, type, customIgnore } = props;
16
+ const settings = { i18nInfo, fileType, customIgnore };
17
+ const parserOptions = {
18
+ ecmaFeatures: { jsx: true },
19
+ parser: { js: espree, jsx: espree, ts: tsParser, tsx: tsParser }
20
+ };
21
+ const vueConfig = {
22
+ files: ["*.vue", "*.js", "*.jsx", "*.ts", "*.tsx"],
23
+ plugins: { i18nEasyVue },
24
+ languageOptions: {
25
+ parser: vueParser,
26
+ parserOptions
27
+ },
28
+ rules: {
29
+ "i18nEasyVue/i18n-transform": "error"
30
+ },
31
+ settings
32
+ };
33
+ const reactConfig = {
34
+ files: ["*.js", "*.jsx", "*.ts", "*.tsx"],
35
+ plugins: { i18nEasyReact },
36
+ languageOptions: {
37
+ parser: espree,
38
+ parserOptions
39
+ },
40
+ rules: { "i18nEasyReact/i18n-transform": "error" },
41
+ settings
42
+ };
43
+ const res = this.linter.verifyAndFix(fileContent, type == "vue" ? vueConfig : reactConfig, fileName);
44
+ return {
45
+ newFileContent: res.output,
46
+ // 转换后的文件内容(如果未应用修复,可能与输入内容相同)
47
+ fixed: res.fixed
48
+ // 是否应用了修复
49
+ };
50
+ }
51
+ };
52
+ export {
53
+ AstTransformer
54
+ };
@@ -0,0 +1,3 @@
1
+ import type { ESLint } from 'eslint';
2
+ declare const ReactPlugin: ESLint.Plugin;
3
+ export default ReactPlugin;