babaofan-translate-cli 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.
- package/README.md +728 -0
- package/bin/i18n.js +1450 -0
- package/config.js +1 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,728 @@
|
|
|
1
|
+
# babaofan-translate-cli
|
|
2
|
+
|
|
3
|
+
一个本地运行的 i18n 翻译 CLI。
|
|
4
|
+
|
|
5
|
+
它的目标很直接:扫描前端项目中的 `t("...")`、`$t("...")` 这类国际化调用,把中文词条提取出来,自动生成稳定的 i18n key,把源码里的中文调用改写成 key 调用,然后直接在本地通过 Google AI Studio 的 Gemini 模型完成翻译,最后生成对应的多语言文件。
|
|
6
|
+
|
|
7
|
+
整个过程在用户自己的终端闭环完成,不依赖自建后端服务。
|
|
8
|
+
|
|
9
|
+
## 功能概览
|
|
10
|
+
|
|
11
|
+
- 扫描前端项目中的 i18n 调用
|
|
12
|
+
- 支持 `Vue`、`nvue`、`uvue`、`React`、`Next.js`、`Nuxt` 以及其他基于 `JS/TS` 的前端项目
|
|
13
|
+
- 使用 AST 扫描,而不是简单正则
|
|
14
|
+
- 直接调用 Google 官方 SDK `@google/genai`
|
|
15
|
+
- 支持通过 `config.js` 配置默认 API Key
|
|
16
|
+
- 支持命令行覆盖 API Key,例如 `--apiKey=xxx`
|
|
17
|
+
- 支持指定扫描范围
|
|
18
|
+
- 支持指定语言列表
|
|
19
|
+
- 支持指定输出目录和输出格式
|
|
20
|
+
- 支持自动把源码里的中文调用改写成 i18n key
|
|
21
|
+
- 支持预览模式 `--dry-run`
|
|
22
|
+
- 支持合并已有 locale 文件,而不是粗暴覆盖
|
|
23
|
+
|
|
24
|
+
## 工作原理
|
|
25
|
+
|
|
26
|
+
这个工具的执行流程分 4 步:
|
|
27
|
+
|
|
28
|
+
1. 扫描项目文件
|
|
29
|
+
2. 使用 AST 提取 `t("中文")`、`$t("中文")`、`this.$t("中文")` 等调用中的静态字符串
|
|
30
|
+
3. 为每个词条生成稳定的 key
|
|
31
|
+
4. 把源码里的 `t("中文")` 改成 `t("生成的.key")`
|
|
32
|
+
5. 调用 Google Gemini 接口批量翻译
|
|
33
|
+
6. 合并已有 locale 文件
|
|
34
|
+
7. 生成或更新 `locales/*.json` 等翻译文件
|
|
35
|
+
|
|
36
|
+
### 为什么用 AST
|
|
37
|
+
|
|
38
|
+
正则方案看着省事,实际上很容易误伤:
|
|
39
|
+
|
|
40
|
+
- 把普通字符串里的 `t("xxx")` 当成真实调用
|
|
41
|
+
- 漏掉模板里的表达式
|
|
42
|
+
- 遇到嵌套、换行、模板字符串时结果不稳定
|
|
43
|
+
|
|
44
|
+
AST 扫描会靠谱得多,至少不是拿锤子当手术刀。
|
|
45
|
+
|
|
46
|
+
## 支持的扫描文件类型
|
|
47
|
+
|
|
48
|
+
当前支持以下文件后缀:
|
|
49
|
+
|
|
50
|
+
- `.js`
|
|
51
|
+
- `.jsx`
|
|
52
|
+
- `.mjs`
|
|
53
|
+
- `.cjs`
|
|
54
|
+
- `.ts`
|
|
55
|
+
- `.tsx`
|
|
56
|
+
- `.mts`
|
|
57
|
+
- `.cts`
|
|
58
|
+
- `.vue`
|
|
59
|
+
- `.nvue`
|
|
60
|
+
- `.uvue`
|
|
61
|
+
- `.uts`
|
|
62
|
+
|
|
63
|
+
默认会忽略这些目录:
|
|
64
|
+
|
|
65
|
+
- `node_modules`
|
|
66
|
+
- `dist`
|
|
67
|
+
- `build`
|
|
68
|
+
- `coverage`
|
|
69
|
+
- `.next`
|
|
70
|
+
- `.nuxt`
|
|
71
|
+
- `.output`
|
|
72
|
+
- `.turbo`
|
|
73
|
+
- `.git`
|
|
74
|
+
- `locales`
|
|
75
|
+
|
|
76
|
+
这样做是为了避免把依赖、构建产物和已生成翻译文件再次扫进去。
|
|
77
|
+
|
|
78
|
+
## 安装依赖
|
|
79
|
+
|
|
80
|
+
项目已经依赖:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm install
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
如果你是把这个 CLI 集成到别的项目里,确保目标环境至少满足:
|
|
87
|
+
|
|
88
|
+
- 已安装 `Node.js`
|
|
89
|
+
- 已安装当前项目依赖
|
|
90
|
+
- 能访问 Google AI Studio / Gemini 接口
|
|
91
|
+
|
|
92
|
+
## 发布到 npm
|
|
93
|
+
|
|
94
|
+
发布前建议先确认:
|
|
95
|
+
|
|
96
|
+
- [package.json](./package.json) 中的 `name`、`version`、`description` 已经正确
|
|
97
|
+
- [config.js](./config.js) 里不要保留你自己的真实 API Key
|
|
98
|
+
- 本地已经执行过测试命令
|
|
99
|
+
|
|
100
|
+
### 1. 登录 npm
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npm login
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 2. 检查最终会发布哪些文件
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npm pack --dry-run
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 3. 发布
|
|
113
|
+
|
|
114
|
+
首次发布:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npm publish
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
如果后续发新版本,先改 `version`,再发布:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npm version patch
|
|
124
|
+
npm publish
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
你也可以按需使用:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npm version minor
|
|
131
|
+
npm version major
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 在别的项目里使用
|
|
135
|
+
|
|
136
|
+
### 安装
|
|
137
|
+
|
|
138
|
+
建议作为开发依赖安装:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
npm install -D babaofan-translate-cli
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
或者:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
pnpm add -D babaofan-translate-cli
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
或者:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
yarn add -D babaofan-translate-cli
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### 方式 1:直接用 npx 执行
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
npx babaofan-translate create --languages zh-cn,en --files "src/**/*.vue,src/**/*.tsx" --dry-run
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### 方式 2:写进项目 scripts
|
|
163
|
+
|
|
164
|
+
在目标项目的 `package.json` 里加:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"scripts": {
|
|
169
|
+
"i18n:scan": "babaofan-translate create --languages zh-cn,en --files \"src/**/*.vue,src/**/*.tsx\" --dry-run",
|
|
170
|
+
"i18n:run": "babaofan-translate create --languages zh-cn,en --files \"src/**/*.vue,src/**/*.tsx\""
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
然后执行:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
npm run i18n:scan
|
|
179
|
+
npm run i18n:run
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### 方式 3:临时传入 API Key
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
npx babaofan-translate create --apiKey=你的_key --languages zh-cn,en --files "src/**/*.vue,src/**/*.tsx"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 方式 4:通过环境变量
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
GEMINI_API_KEY=你的_key npx babaofan-translate create --languages zh-cn,en --files "src/**/*.vue,src/**/*.tsx"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Windows PowerShell 可以这样:
|
|
195
|
+
|
|
196
|
+
```powershell
|
|
197
|
+
$env:GEMINI_API_KEY="你的_key"
|
|
198
|
+
npx babaofan-translate create --languages zh-cn,en --files "src/**/*.vue,src/**/*.tsx"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## API Key 配置
|
|
202
|
+
|
|
203
|
+
默认 API Key 配置在 [config.js](./config.js):
|
|
204
|
+
|
|
205
|
+
```js
|
|
206
|
+
export const defaultGoogleApiKey = "你的_google_ai_studio_key";
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
你也可以不写死在配置里,而是在命令行传入:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
node bin/i18n.js create --apiKey=你的_key
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
或者:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
node bin/i18n.js create --api-key=你的_key
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Key 优先级
|
|
222
|
+
|
|
223
|
+
当前优先级如下:
|
|
224
|
+
|
|
225
|
+
1. 命令行传入的 `--apiKey` / `--api-key`
|
|
226
|
+
2. `config.js` 中的 `defaultGoogleApiKey`
|
|
227
|
+
3. 环境变量
|
|
228
|
+
- `GEMINI_API_KEY`
|
|
229
|
+
- `GOOGLE_AI_STUDIO_API_KEY`
|
|
230
|
+
- `GOOGLE_API_KEY`
|
|
231
|
+
|
|
232
|
+
### 安全提醒
|
|
233
|
+
|
|
234
|
+
如果 `config.js` 里写了真实 Key,别傻乎乎直接提交到公开仓库。
|
|
235
|
+
|
|
236
|
+
更稳的方式是:
|
|
237
|
+
|
|
238
|
+
- 本地开发时临时写 `config.js`
|
|
239
|
+
- 或者使用环境变量
|
|
240
|
+
- 或者在实际项目里用命令行参数覆盖
|
|
241
|
+
|
|
242
|
+
## 命令说明
|
|
243
|
+
|
|
244
|
+
### 1. 创建翻译文件
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
node bin/i18n.js create [options]
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
示例:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
node bin/i18n.js create --languages zh-cn,en --files "src/**/*.{vue,js,jsx,ts,tsx}"
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### 2. 为 `uni_modules` 模块生成翻译文件
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
node bin/i18n.js add uni_modules/模块名 [options]
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
示例:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
node bin/i18n.js add uni_modules/demo --languages zh-cn,en
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 3. 清空翻译输出目录
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
node bin/i18n.js clear
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## npm script 用法
|
|
275
|
+
|
|
276
|
+
项目里已经定义了:
|
|
277
|
+
|
|
278
|
+
```json
|
|
279
|
+
"scripts": {
|
|
280
|
+
"i18n": "node bin/i18n.js"
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
所以也可以这样用:
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
npm run i18n -- create --languages zh-cn,en --files "src/**/*.{vue,js,jsx,ts,tsx}"
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
如果你要传 Key:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
npm run i18n -- create --apiKey=你的_key --languages zh-cn,en --files "src/**/*.{vue,js,jsx,ts,tsx}"
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
注意这里中间那个 `--` 不能少。
|
|
297
|
+
|
|
298
|
+
少了以后,参数不会传给脚本,命令看着像执行了,实际上啥也没喂进去,贼恶心。
|
|
299
|
+
|
|
300
|
+
## 参数说明
|
|
301
|
+
|
|
302
|
+
### 通用参数
|
|
303
|
+
|
|
304
|
+
#### `--apiKey <key>`
|
|
305
|
+
|
|
306
|
+
Google AI Studio API Key,适合 `npm run xxx -- --apiKey=***` 这种场景。
|
|
307
|
+
|
|
308
|
+
#### `--api-key <key>`
|
|
309
|
+
|
|
310
|
+
和 `--apiKey` 作用一致,只是另一种写法。
|
|
311
|
+
|
|
312
|
+
#### `--model <model>`
|
|
313
|
+
|
|
314
|
+
指定 Gemini 模型。
|
|
315
|
+
|
|
316
|
+
默认值:
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
gemini-2.5-flash
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
#### `--batch-size <size>`
|
|
323
|
+
|
|
324
|
+
单批翻译条数。
|
|
325
|
+
|
|
326
|
+
默认值:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
20
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### `--files <paths>`
|
|
333
|
+
|
|
334
|
+
指定扫描文件或 glob,多个值用英文逗号分隔。
|
|
335
|
+
|
|
336
|
+
示例:
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
--files "src/**/*.vue,src/**/*.tsx"
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### `--languages <codes>`
|
|
343
|
+
|
|
344
|
+
指定语言列表,多个值用英文逗号分隔。
|
|
345
|
+
|
|
346
|
+
示例:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
--languages zh-cn,en,ja
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
如果不传,CLI 会尝试自动检测项目里的语言配置。
|
|
353
|
+
|
|
354
|
+
#### `--output-dir <dir>`
|
|
355
|
+
|
|
356
|
+
指定输出目录。
|
|
357
|
+
|
|
358
|
+
默认值:
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
locales
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
#### `--output-format <format>`
|
|
365
|
+
|
|
366
|
+
输出格式,可选:
|
|
367
|
+
|
|
368
|
+
- `auto`
|
|
369
|
+
- `pair-array`
|
|
370
|
+
- `object`
|
|
371
|
+
|
|
372
|
+
说明:
|
|
373
|
+
|
|
374
|
+
- `auto`:自动判断
|
|
375
|
+
- `pair-array`:输出二维数组,例如 `[[key, value]]`
|
|
376
|
+
- `object`:输出对象,例如 `{ "key": "value" }`
|
|
377
|
+
|
|
378
|
+
#### `--source-locale <code>`
|
|
379
|
+
|
|
380
|
+
指定源语言代码,默认是:
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
zh-cn
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
#### `--no-rewrite`
|
|
387
|
+
|
|
388
|
+
只生成 locale 文件,不改写源码。
|
|
389
|
+
|
|
390
|
+
默认情况下,CLI 会自动把源码中的中文调用替换成生成后的 key。
|
|
391
|
+
|
|
392
|
+
#### `--dry-run`
|
|
393
|
+
|
|
394
|
+
预览模式。
|
|
395
|
+
|
|
396
|
+
开启后,CLI 会输出:
|
|
397
|
+
|
|
398
|
+
- 开始翻译总览
|
|
399
|
+
- 正在调用 Google AI 生成语义 key 的提示
|
|
400
|
+
- 语义 key 分批生成进度提示
|
|
401
|
+
- 哪些文件会被改写
|
|
402
|
+
- 会生成哪些 key
|
|
403
|
+
- 会写入哪些 locale 文件
|
|
404
|
+
- 对应 locale 文件是新建还是合并已有文件
|
|
405
|
+
|
|
406
|
+
不会真正执行翻译、改写源码或写入文件。
|
|
407
|
+
|
|
408
|
+
注意:
|
|
409
|
+
|
|
410
|
+
- 为了预览真正的语义 key,`dry-run` 仍可能调用 Google 来生成 key
|
|
411
|
+
|
|
412
|
+
## 输出格式说明
|
|
413
|
+
|
|
414
|
+
## 源码改写说明
|
|
415
|
+
|
|
416
|
+
默认情况下,工具会把源码里的调用:
|
|
417
|
+
|
|
418
|
+
```ts
|
|
419
|
+
t("你好")
|
|
420
|
+
$t("欢迎使用")
|
|
421
|
+
this.$t("按钮文案")
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
自动改成类似这样:
|
|
425
|
+
|
|
426
|
+
```ts
|
|
427
|
+
t("home.button.title")
|
|
428
|
+
$t("home.welcome.message")
|
|
429
|
+
this.$t("header.action.confirm")
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
同时在 locale 文件里生成:
|
|
433
|
+
|
|
434
|
+
```json
|
|
435
|
+
{
|
|
436
|
+
"home.button.title": "你好"
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### key 生成规则
|
|
441
|
+
|
|
442
|
+
当前 key 由三部分组成:
|
|
443
|
+
|
|
444
|
+
1. 文件相对路径
|
|
445
|
+
2. Gemini 生成的英文语义 key
|
|
446
|
+
3. 必要时附加短 hash 做冲突兜底
|
|
447
|
+
|
|
448
|
+
补充说明:
|
|
449
|
+
|
|
450
|
+
- 目录层级之间使用 `.`
|
|
451
|
+
- 单个目录名内部会尽量保留原始语义,例如 `tmp-generic-test` 会保留为 `tmp-generic-test`
|
|
452
|
+
- 不会把一个目录名再拆成 `tmp.generic.test`
|
|
453
|
+
- 对明显的临时目录或测试目录,例如 `tmp-*`、`temp-*`、`test-*`、`playground`,会自动压缩或忽略,避免 key 前缀过长
|
|
454
|
+
- 对真正的业务模块目录,例如 `user-center`、`order-management`,会尽量保留
|
|
455
|
+
|
|
456
|
+
这样做的目的是:
|
|
457
|
+
|
|
458
|
+
- 保持 key 稳定
|
|
459
|
+
- 尽量让 key 能被人看懂
|
|
460
|
+
- 避免简单重名冲突
|
|
461
|
+
- 不依赖外部服务来生成 key
|
|
462
|
+
|
|
463
|
+
如果你暂时不想改源码,可以显式传:
|
|
464
|
+
|
|
465
|
+
```bash
|
|
466
|
+
--no-rewrite
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## 合并已有 locale 文件
|
|
470
|
+
|
|
471
|
+
默认情况下,工具写 locale 文件时会先读取已有文件,再把本次新生成的 key 合并进去。
|
|
472
|
+
|
|
473
|
+
也就是说:
|
|
474
|
+
|
|
475
|
+
- 旧 key 会保留
|
|
476
|
+
- 新 key 会追加
|
|
477
|
+
- 同名 key 会用本次生成结果覆盖
|
|
478
|
+
|
|
479
|
+
支持两种已有文件格式:
|
|
480
|
+
|
|
481
|
+
- `object`
|
|
482
|
+
- `pair-array`
|
|
483
|
+
|
|
484
|
+
这意味着你项目里已经有一部分翻译内容时,不需要每次从零开始重建。
|
|
485
|
+
|
|
486
|
+
### `object`
|
|
487
|
+
|
|
488
|
+
示例:
|
|
489
|
+
|
|
490
|
+
```json
|
|
491
|
+
{
|
|
492
|
+
"你好": "Hello",
|
|
493
|
+
"欢迎使用": "Welcome"
|
|
494
|
+
}
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### `pair-array`
|
|
498
|
+
|
|
499
|
+
示例:
|
|
500
|
+
|
|
501
|
+
```json
|
|
502
|
+
[
|
|
503
|
+
["你好", "Hello"],
|
|
504
|
+
["欢迎使用", "Welcome"]
|
|
505
|
+
]
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
## 自动检测语言配置
|
|
509
|
+
|
|
510
|
+
如果没有手动传 `--languages`,CLI 会尝试扫描这些路径里的语言配置:
|
|
511
|
+
|
|
512
|
+
- `plugins/locale.*`
|
|
513
|
+
- `src/plugins/locale.*`
|
|
514
|
+
- `src/i18n/**/*`
|
|
515
|
+
- `i18n/**/*`
|
|
516
|
+
- `config/**/*locale*`
|
|
517
|
+
- `locales/**/*`
|
|
518
|
+
|
|
519
|
+
它会尝试识别这些字段:
|
|
520
|
+
|
|
521
|
+
- `languages`
|
|
522
|
+
- `locales`
|
|
523
|
+
- `supportedLocales`
|
|
524
|
+
- `availableLocales`
|
|
525
|
+
- `supportedLngs`
|
|
526
|
+
|
|
527
|
+
如果自动检测失败,请直接传:
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
--languages zh-cn,en
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
别跟 CLI 斗气,明确告诉它最省事。
|
|
534
|
+
|
|
535
|
+
## 本地测试
|
|
536
|
+
|
|
537
|
+
### 最小测试方式
|
|
538
|
+
|
|
539
|
+
先在你的项目里建一个测试文件,比如 `src/test-i18n.ts`:
|
|
540
|
+
|
|
541
|
+
```ts
|
|
542
|
+
const a = t("你好");
|
|
543
|
+
const b = $t("欢迎使用");
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
然后执行:
|
|
547
|
+
|
|
548
|
+
```bash
|
|
549
|
+
node bin/i18n.js create --languages zh-cn,en --files "src/test-i18n.ts"
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### 你应该看到什么
|
|
553
|
+
|
|
554
|
+
正常情况下,终端会看到类似输出:
|
|
555
|
+
|
|
556
|
+
```bash
|
|
557
|
+
开始翻译
|
|
558
|
+
● 项目 ...
|
|
559
|
+
● 提供方 Google AI Studio
|
|
560
|
+
● 模型 gemini-2.5-flash
|
|
561
|
+
● 词条 2 个
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
然后输出目录里会生成:
|
|
565
|
+
|
|
566
|
+
- `locales/zh-cn.json`
|
|
567
|
+
- `locales/en.json`
|
|
568
|
+
|
|
569
|
+
如果开启默认回写,还会看到源文件中的中文被替换成生成后的 key。
|
|
570
|
+
|
|
571
|
+
### 预览测试方式
|
|
572
|
+
|
|
573
|
+
如果你想先看结果,不想真正改文件,可以执行:
|
|
574
|
+
|
|
575
|
+
```bash
|
|
576
|
+
node bin/i18n.js create --languages zh-cn,en --files "src/test-i18n.ts" --dry-run
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
正常情况下,你会看到:
|
|
580
|
+
|
|
581
|
+
- 改写文件数量
|
|
582
|
+
- key 预览
|
|
583
|
+
- locale 文件输出位置
|
|
584
|
+
- 是新建还是合并已有文件
|
|
585
|
+
|
|
586
|
+
## 常见问题
|
|
587
|
+
|
|
588
|
+
### 1. 终端提示 `词条 0 个`
|
|
589
|
+
|
|
590
|
+
通常是下面几个原因:
|
|
591
|
+
|
|
592
|
+
- `--files` 路径没写对
|
|
593
|
+
- 文件里没有 `t("静态字符串")` 或 `$t("静态字符串")`
|
|
594
|
+
- 写的是 `t(variable)`,这种动态参数当前不会提取
|
|
595
|
+
|
|
596
|
+
### 2. 终端提示 `fetch failed`
|
|
597
|
+
|
|
598
|
+
通常是:
|
|
599
|
+
|
|
600
|
+
- API Key 无效
|
|
601
|
+
- 当前网络访问不到 Google 接口
|
|
602
|
+
- 本机网络环境限制了 Gemini 服务访问
|
|
603
|
+
|
|
604
|
+
这不是扫描逻辑的问题。
|
|
605
|
+
|
|
606
|
+
现在批量调用失败时,CLI 也会额外提示失败批次,例如:
|
|
607
|
+
|
|
608
|
+
```bash
|
|
609
|
+
语义命名失败:第 2/5 批(20 条)执行失败
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
这样可以更快判断是偶发网络问题,还是某一批词条太多、太杂。
|
|
613
|
+
|
|
614
|
+
### 3. `npm run` 参数不生效
|
|
615
|
+
|
|
616
|
+
检查是不是漏了这个:
|
|
617
|
+
|
|
618
|
+
```bash
|
|
619
|
+
npm run i18n -- create --languages zh-cn,en
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
中间那个 `--` 必须有。
|
|
623
|
+
|
|
624
|
+
### 4. 为什么源码没有被替换
|
|
625
|
+
|
|
626
|
+
先看是不是传了:
|
|
627
|
+
|
|
628
|
+
```bash
|
|
629
|
+
--no-rewrite
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
如果传了这个参数,CLI 只生成 locale,不改源码。
|
|
633
|
+
|
|
634
|
+
另外,只有静态字符串调用才会被改写。
|
|
635
|
+
|
|
636
|
+
### 5. 为什么没有真正写文件
|
|
637
|
+
|
|
638
|
+
先看是不是传了:
|
|
639
|
+
|
|
640
|
+
```bash
|
|
641
|
+
--dry-run
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
如果传了,CLI 只预览,不会真正翻译、改源码或写 locale。
|
|
645
|
+
|
|
646
|
+
不过为了生成可预览的语义 key,它仍可能调用 Google。
|
|
647
|
+
|
|
648
|
+
### 6. 为什么有些调用没被提取
|
|
649
|
+
|
|
650
|
+
当前优先提取静态字符串调用,比如:
|
|
651
|
+
|
|
652
|
+
```ts
|
|
653
|
+
t("你好")
|
|
654
|
+
$t("欢迎使用")
|
|
655
|
+
this.$t("按钮文案")
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
像下面这种动态值,目前不会提取:
|
|
659
|
+
|
|
660
|
+
```ts
|
|
661
|
+
t(messageKey)
|
|
662
|
+
t(`prefix.${name}`)
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
这是故意的,不是 bug。
|
|
666
|
+
|
|
667
|
+
动态 key 一旦瞎提,生成结果十有八九一团糟。
|
|
668
|
+
|
|
669
|
+
## 推荐用法
|
|
670
|
+
|
|
671
|
+
### Vue / Nuxt 项目
|
|
672
|
+
|
|
673
|
+
```bash
|
|
674
|
+
npm run i18n -- create --languages zh-cn,en --files "src/**/*.{vue,ts,js}"
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
### React / Next 项目
|
|
678
|
+
|
|
679
|
+
```bash
|
|
680
|
+
npm run i18n -- create --languages zh-cn,en --files "src/**/*.{tsx,ts,jsx,js}"
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
### 指定输出目录
|
|
684
|
+
|
|
685
|
+
```bash
|
|
686
|
+
npm run i18n -- create --languages zh-cn,en --files "src/**/*.{vue,ts}" --output-dir src/locales
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
### 指定输出格式
|
|
690
|
+
|
|
691
|
+
```bash
|
|
692
|
+
npm run i18n -- create --languages zh-cn,en --files "src/**/*.{tsx,ts}" --output-format object
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
### 只生成 locale,不改源码
|
|
696
|
+
|
|
697
|
+
```bash
|
|
698
|
+
npm run i18n -- create --languages zh-cn,en --files "src/**/*.{vue,ts}" --no-rewrite
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### 先预览,不真正执行
|
|
702
|
+
|
|
703
|
+
```bash
|
|
704
|
+
npm run i18n -- create --languages zh-cn,en --files "src/**/*.{vue,ts}" --dry-run
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
### 全项目递归扫描
|
|
708
|
+
|
|
709
|
+
```bash
|
|
710
|
+
node bin/i18n.js create --languages zh-cn,en --files "**/*.{vue,js,jsx,ts,tsx}" --dry-run
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
注意:
|
|
714
|
+
|
|
715
|
+
- 不要写成 `/*.{vue,js,jsx,ts,tsx}`,那只会扫项目根目录一层
|
|
716
|
+
- 默认忽略目录仍然生效,所以不会去扫 `node_modules`、`dist`、`locales` 这些地方
|
|
717
|
+
|
|
718
|
+
## 未来可以继续扩展的方向
|
|
719
|
+
|
|
720
|
+
- 自动合并已有 locale 文件
|
|
721
|
+
- 支持更多 i18n 框架约定
|
|
722
|
+
- 增加 `--dry-run`
|
|
723
|
+
- 增加翻译缓存
|
|
724
|
+
- 增加忽略规则
|
|
725
|
+
|
|
726
|
+
## License
|
|
727
|
+
|
|
728
|
+
MIT
|