vite-plugin-ai-i18n 1.0.3 → 1.0.5
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/dist/index.js +163 -123
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +109 -93
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import fs3 from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import pc3 from 'picocolors';
|
|
4
|
-
import { ChatOpenAI } from '@langchain/openai';
|
|
5
|
-
import { SystemMessage, HumanMessage } from '@langchain/core/messages';
|
|
6
|
-
|
|
7
1
|
// src/index.ts
|
|
2
|
+
import fs4 from "fs";
|
|
3
|
+
import path4 from "path";
|
|
4
|
+
import pc3 from "picocolors";
|
|
5
|
+
|
|
6
|
+
// src/scanner.ts
|
|
7
|
+
import fs2 from "fs";
|
|
8
|
+
import path2 from "path";
|
|
9
|
+
|
|
10
|
+
// src/utils.ts
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
8
13
|
async function glob(patterns, excludePatterns) {
|
|
9
14
|
const results = [];
|
|
10
15
|
const cwd = process.cwd();
|
|
@@ -27,15 +32,15 @@ async function matchPattern(pattern, cwd) {
|
|
|
27
32
|
await walkDir(path.join(cwd, baseDir), filePattern, results);
|
|
28
33
|
} else {
|
|
29
34
|
const fullPath = path.join(cwd, pattern);
|
|
30
|
-
if (
|
|
35
|
+
if (fs.existsSync(fullPath)) {
|
|
31
36
|
results.push(fullPath);
|
|
32
37
|
}
|
|
33
38
|
}
|
|
34
39
|
return results;
|
|
35
40
|
}
|
|
36
41
|
async function walkDir(dir, pattern, results) {
|
|
37
|
-
if (!
|
|
38
|
-
const entries =
|
|
42
|
+
if (!fs.existsSync(dir)) return;
|
|
43
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
39
44
|
for (const entry of entries) {
|
|
40
45
|
const fullPath = path.join(dir, entry.name);
|
|
41
46
|
if (entry.isDirectory()) {
|
|
@@ -88,9 +93,9 @@ var I18nScanner = class {
|
|
|
88
93
|
* 扫描单个文件
|
|
89
94
|
*/
|
|
90
95
|
scanFile(filePath) {
|
|
91
|
-
if (!
|
|
92
|
-
const content =
|
|
93
|
-
const ext =
|
|
96
|
+
if (!fs2.existsSync(filePath)) return [];
|
|
97
|
+
const content = fs2.readFileSync(filePath, "utf-8");
|
|
98
|
+
const ext = path2.extname(filePath);
|
|
94
99
|
let texts = [];
|
|
95
100
|
if (ext === ".vue") {
|
|
96
101
|
texts = this.scanVueFile(content);
|
|
@@ -251,77 +256,82 @@ var I18nScanner = class {
|
|
|
251
256
|
isValidText(text) {
|
|
252
257
|
const debug = this.options.debug;
|
|
253
258
|
if (text.length < 2) {
|
|
254
|
-
if (debug) console.log(`[
|
|
259
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 文本太短`);
|
|
255
260
|
return false;
|
|
256
261
|
}
|
|
257
262
|
if (!/[\u4e00-\u9fa5]/.test(text)) {
|
|
258
|
-
if (debug) console.log(`[
|
|
263
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 不包含中文`);
|
|
259
264
|
return false;
|
|
260
265
|
}
|
|
261
266
|
if (/^\s*$/.test(text)) {
|
|
262
|
-
if (debug) console.log(`[
|
|
267
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 纯空格`);
|
|
263
268
|
return false;
|
|
264
269
|
}
|
|
265
270
|
if (/^\$t\(|^t\(|^i18n\.|_uni_app$|^[a-z_]+_[a-z_]+$/.test(text)) {
|
|
266
|
-
if (debug) console.log(`[
|
|
271
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: i18n key`);
|
|
267
272
|
return false;
|
|
268
273
|
}
|
|
269
274
|
if (/^[⚠️❌✅🔍📝💡🎯🚀🔧📊]/.test(text)) {
|
|
270
|
-
if (debug) console.log(`[
|
|
275
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 系统提示`);
|
|
271
276
|
return false;
|
|
272
277
|
}
|
|
273
278
|
if (/\.(json|js|ts|vue|md|txt|html|css|jsx|tsx)\s*(文件|不存在|已|错误)/.test(
|
|
274
279
|
text
|
|
275
280
|
)) {
|
|
276
|
-
if (debug) console.log(`[
|
|
281
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 技术术语`);
|
|
277
282
|
return false;
|
|
278
283
|
}
|
|
279
284
|
if (/^[a-zA-Z0-9_\-\.]+\s*(文件|不存在|错误|失败)/.test(text)) {
|
|
280
|
-
if (debug) console.log(`[
|
|
285
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 技术错误信息`);
|
|
281
286
|
return false;
|
|
282
287
|
}
|
|
283
288
|
if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(text)) {
|
|
284
|
-
if (debug) console.log(`[
|
|
289
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 变量名`);
|
|
285
290
|
return false;
|
|
286
291
|
}
|
|
287
292
|
if (/^\/[a-zA-Z0-9_\-\/]*$/.test(text)) {
|
|
288
|
-
if (debug) console.log(`[
|
|
293
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 路径`);
|
|
289
294
|
return false;
|
|
290
295
|
}
|
|
291
296
|
if (/^https?:\/\//.test(text)) {
|
|
292
|
-
if (debug) console.log(`[
|
|
297
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: URL`);
|
|
293
298
|
return false;
|
|
294
299
|
}
|
|
295
300
|
if (/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(text)) {
|
|
296
|
-
if (debug) console.log(`[
|
|
301
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 邮箱`);
|
|
297
302
|
return false;
|
|
298
303
|
}
|
|
299
304
|
if (/^\d+$/.test(text)) {
|
|
300
|
-
if (debug) console.log(`[
|
|
305
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 纯数字`);
|
|
301
306
|
return false;
|
|
302
307
|
}
|
|
303
308
|
if (/^\d{4}-\d{2}-\d{2}/.test(text)) {
|
|
304
|
-
if (debug) console.log(`[
|
|
309
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 日期`);
|
|
305
310
|
return false;
|
|
306
311
|
}
|
|
307
312
|
if (/^(const|let|var|function|class|import|export|return)\s/.test(text)) {
|
|
308
|
-
if (debug) console.log(`[
|
|
313
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 代码片段`);
|
|
309
314
|
return false;
|
|
310
315
|
}
|
|
311
316
|
if (text.length > 100) {
|
|
312
|
-
if (debug) console.log(`[
|
|
317
|
+
if (debug) console.log(`[过滤] "${text}" - 原因: 文本过长`);
|
|
313
318
|
return false;
|
|
314
319
|
}
|
|
315
320
|
const specialCharCount = (text.match(/[^\u4e00-\u9fa5a-zA-Z0-9\s,。!?、;:""''()《》]/g) || []).length;
|
|
316
321
|
if (specialCharCount > text.length * 0.3) {
|
|
317
322
|
if (debug)
|
|
318
|
-
console.log(`[
|
|
323
|
+
console.log(`[过滤] "${text}" - 原因: 特殊字符过多 (${specialCharCount})`);
|
|
319
324
|
return false;
|
|
320
325
|
}
|
|
321
|
-
if (debug) console.log(`[
|
|
326
|
+
if (debug) console.log(`[保留] "${text}"`);
|
|
322
327
|
return true;
|
|
323
328
|
}
|
|
324
329
|
};
|
|
330
|
+
|
|
331
|
+
// src/translator.ts
|
|
332
|
+
import { ChatOpenAI } from "@langchain/openai";
|
|
333
|
+
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
334
|
+
import pc from "picocolors";
|
|
325
335
|
var I18nTranslator = class {
|
|
326
336
|
constructor(options) {
|
|
327
337
|
this.llm = null;
|
|
@@ -341,7 +351,7 @@ var I18nTranslator = class {
|
|
|
341
351
|
*/
|
|
342
352
|
async translate(texts, sourceLocale, targetLocale, existingTranslations) {
|
|
343
353
|
if (!this.llm) {
|
|
344
|
-
console.warn(
|
|
354
|
+
console.warn(pc.yellow("⚠️ 未配置 API Key,跳过翻译"));
|
|
345
355
|
const results2 = /* @__PURE__ */ new Map();
|
|
346
356
|
for (const [file, fileTexts] of texts) {
|
|
347
357
|
const textMap = /* @__PURE__ */ new Map();
|
|
@@ -364,19 +374,19 @@ var I18nTranslator = class {
|
|
|
364
374
|
textsToTranslate.push(text);
|
|
365
375
|
}
|
|
366
376
|
});
|
|
367
|
-
console.log(
|
|
368
|
-
console.log(`
|
|
377
|
+
console.log(pc.blue("📊 翻译统计:"));
|
|
378
|
+
console.log(` 总计: ${pc.cyan(uniqueTexts.length.toString())} 条`);
|
|
369
379
|
console.log(
|
|
370
|
-
`
|
|
380
|
+
` ✅ 已有: ${pc.green(cachedTranslations.size.toString())} 条`
|
|
371
381
|
);
|
|
372
382
|
console.log(
|
|
373
|
-
`
|
|
383
|
+
` 🆕 新增: ${pc.yellow(textsToTranslate.length.toString())} 条`
|
|
374
384
|
);
|
|
375
385
|
try {
|
|
376
386
|
let newTranslations = [];
|
|
377
387
|
if (textsToTranslate.length > 0) {
|
|
378
|
-
console.log(
|
|
379
|
-
|
|
388
|
+
console.log(pc.cyan(`
|
|
389
|
+
🤖 正在翻译新增文本...`));
|
|
380
390
|
newTranslations = await this.batchTranslate(
|
|
381
391
|
textsToTranslate,
|
|
382
392
|
sourceLocale,
|
|
@@ -396,7 +406,7 @@ var I18nTranslator = class {
|
|
|
396
406
|
}
|
|
397
407
|
return results;
|
|
398
408
|
} catch (error) {
|
|
399
|
-
console.error(
|
|
409
|
+
console.error(pc.red("❌ 翻译失败:"), error.message);
|
|
400
410
|
const results2 = /* @__PURE__ */ new Map();
|
|
401
411
|
for (const [file, fileTexts] of texts) {
|
|
402
412
|
const textMap = /* @__PURE__ */ new Map();
|
|
@@ -446,8 +456,8 @@ var I18nTranslator = class {
|
|
|
446
456
|
results.push(...translated);
|
|
447
457
|
const progress = Math.min(i + batchSize, texts.length);
|
|
448
458
|
console.log(
|
|
449
|
-
|
|
450
|
-
`
|
|
459
|
+
pc.gray(
|
|
460
|
+
` 📊 翻译进度: ${pc.cyan(progress.toString())}/${pc.cyan(
|
|
451
461
|
texts.length.toString()
|
|
452
462
|
)}`
|
|
453
463
|
)
|
|
@@ -461,16 +471,16 @@ var I18nTranslator = class {
|
|
|
461
471
|
async translateBatch(texts, sourceLocale, targetLocale) {
|
|
462
472
|
const localeName = this.getLocaleName(targetLocale);
|
|
463
473
|
const systemPrompt = new SystemMessage(
|
|
464
|
-
|
|
474
|
+
`你是专业的软件本地化翻译专家。请将以下${this.getLocaleName(
|
|
465
475
|
sourceLocale
|
|
466
|
-
)}
|
|
467
|
-
|
|
468
|
-
1.
|
|
469
|
-
2.
|
|
470
|
-
3.
|
|
471
|
-
4.
|
|
472
|
-
5.
|
|
473
|
-
6.
|
|
476
|
+
)}文本翻译成${localeName}。
|
|
477
|
+
要求:
|
|
478
|
+
1. 保持专业术语的准确性
|
|
479
|
+
2. 翻译要自然流畅,符合目标语言习惯
|
|
480
|
+
3. 保留原文中的变量占位符(如 {name}、%s 等)
|
|
481
|
+
4. 每行一个翻译,与输入顺序严格对应
|
|
482
|
+
5. 只输出翻译结果,不要解释
|
|
483
|
+
6. 如果原文包含换行,翻译也保持相同的换行`
|
|
474
484
|
);
|
|
475
485
|
const userPrompt = new HumanMessage(
|
|
476
486
|
texts.map((t, i) => `${i + 1}. ${t}`).join("\n")
|
|
@@ -494,21 +504,26 @@ var I18nTranslator = class {
|
|
|
494
504
|
*/
|
|
495
505
|
getLocaleName(locale) {
|
|
496
506
|
const names = {
|
|
497
|
-
"zh-CN": "
|
|
498
|
-
"zh-TW": "
|
|
499
|
-
"en-US": "
|
|
500
|
-
"ja-JP": "
|
|
501
|
-
"ko-KR": "
|
|
502
|
-
"fr-FR": "
|
|
503
|
-
"de-DE": "
|
|
504
|
-
"es-ES": "
|
|
505
|
-
"pt-BR": "
|
|
506
|
-
"ru-RU": "
|
|
507
|
-
"ar-SA": "
|
|
507
|
+
"zh-CN": "简体中文",
|
|
508
|
+
"zh-TW": "繁体中文",
|
|
509
|
+
"en-US": "英语",
|
|
510
|
+
"ja-JP": "日语",
|
|
511
|
+
"ko-KR": "韩语",
|
|
512
|
+
"fr-FR": "法语",
|
|
513
|
+
"de-DE": "德语",
|
|
514
|
+
"es-ES": "西班牙语",
|
|
515
|
+
"pt-BR": "葡萄牙语",
|
|
516
|
+
"ru-RU": "俄语",
|
|
517
|
+
"ar-SA": "阿拉伯语"
|
|
508
518
|
};
|
|
509
519
|
return names[locale] || locale;
|
|
510
520
|
}
|
|
511
521
|
};
|
|
522
|
+
|
|
523
|
+
// src/generator.ts
|
|
524
|
+
import fs3 from "fs";
|
|
525
|
+
import path3 from "path";
|
|
526
|
+
import pc2 from "picocolors";
|
|
512
527
|
var I18nGenerator = class {
|
|
513
528
|
constructor(options) {
|
|
514
529
|
this.options = options;
|
|
@@ -521,13 +536,13 @@ var I18nGenerator = class {
|
|
|
521
536
|
if (!fs3.existsSync(localesDir)) {
|
|
522
537
|
fs3.mkdirSync(localesDir, { recursive: true });
|
|
523
538
|
}
|
|
524
|
-
const filePath =
|
|
539
|
+
const filePath = path3.join(localesDir, `${locale}.json`);
|
|
525
540
|
let existing = {};
|
|
526
541
|
if (fs3.existsSync(filePath)) {
|
|
527
542
|
try {
|
|
528
543
|
existing = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
529
544
|
} catch (e) {
|
|
530
|
-
console.warn(
|
|
545
|
+
console.warn(pc2.yellow(`⚠️ 无法解析现有语言文件: ${filePath}`));
|
|
531
546
|
}
|
|
532
547
|
}
|
|
533
548
|
const translations = { ...existing };
|
|
@@ -546,9 +561,9 @@ var I18nGenerator = class {
|
|
|
546
561
|
return obj;
|
|
547
562
|
}, {});
|
|
548
563
|
fs3.writeFileSync(filePath, JSON.stringify(sorted, null, 2), "utf-8");
|
|
549
|
-
console.log(
|
|
564
|
+
console.log(pc2.green(`✅ 已更新 ${pc2.cyan(locale)} 语言文件: ${pc2.gray(filePath)}`));
|
|
550
565
|
if (newCount > 0) {
|
|
551
|
-
console.log(
|
|
566
|
+
console.log(pc2.gray(` 新增 ${pc2.yellow(newCount.toString())} 条翻译`));
|
|
552
567
|
}
|
|
553
568
|
}
|
|
554
569
|
/**
|
|
@@ -559,13 +574,13 @@ var I18nGenerator = class {
|
|
|
559
574
|
if (!fs3.existsSync(localesDir)) {
|
|
560
575
|
fs3.mkdirSync(localesDir, { recursive: true });
|
|
561
576
|
}
|
|
562
|
-
const filePath =
|
|
577
|
+
const filePath = path3.join(localesDir, `${locale}.json`);
|
|
563
578
|
let existing = {};
|
|
564
579
|
if (fs3.existsSync(filePath)) {
|
|
565
580
|
try {
|
|
566
581
|
existing = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
567
582
|
} catch (e) {
|
|
568
|
-
console.warn(
|
|
583
|
+
console.warn(pc2.yellow(`⚠️ 无法解析现有语言文件: ${filePath}`));
|
|
569
584
|
}
|
|
570
585
|
}
|
|
571
586
|
const translationsObj = { ...existing };
|
|
@@ -587,12 +602,12 @@ var I18nGenerator = class {
|
|
|
587
602
|
return obj;
|
|
588
603
|
}, {});
|
|
589
604
|
fs3.writeFileSync(filePath, JSON.stringify(sorted, null, 2), "utf-8");
|
|
590
|
-
console.log(
|
|
605
|
+
console.log(pc2.green(`✅ 已更新 ${pc2.cyan(locale)} 语言文件: ${pc2.gray(filePath)}`));
|
|
591
606
|
if (newCount > 0) {
|
|
592
|
-
console.log(
|
|
607
|
+
console.log(pc2.gray(` ✨ 新增 ${pc2.yellow(newCount.toString())} 条翻译`));
|
|
593
608
|
}
|
|
594
609
|
if (skippedCount > 0) {
|
|
595
|
-
console.log(
|
|
610
|
+
console.log(pc2.gray(` ⏭️ 跳过 ${pc2.blue(skippedCount.toString())} 条已有翻译`));
|
|
596
611
|
}
|
|
597
612
|
}
|
|
598
613
|
/**
|
|
@@ -600,12 +615,12 @@ var I18nGenerator = class {
|
|
|
600
615
|
*/
|
|
601
616
|
loadExistingTranslations(locale) {
|
|
602
617
|
const { localesDir } = this.options;
|
|
603
|
-
const filePath =
|
|
618
|
+
const filePath = path3.join(localesDir, `${locale}.json`);
|
|
604
619
|
if (fs3.existsSync(filePath)) {
|
|
605
620
|
try {
|
|
606
621
|
return JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
607
622
|
} catch (e) {
|
|
608
|
-
console.warn(
|
|
623
|
+
console.warn(pc2.yellow(`⚠️ 无法解析现有语言文件: ${filePath}`));
|
|
609
624
|
}
|
|
610
625
|
}
|
|
611
626
|
return {};
|
|
@@ -658,44 +673,44 @@ function vitePluginAII18n(options = {}) {
|
|
|
658
673
|
name: "vite-plugin-ai-i18n",
|
|
659
674
|
enforce: "pre",
|
|
660
675
|
configResolved(config) {
|
|
661
|
-
const fullLocalesDir =
|
|
662
|
-
if (!
|
|
663
|
-
|
|
676
|
+
const fullLocalesDir = path4.resolve(config.root, localesDir);
|
|
677
|
+
if (!fs4.existsSync(fullLocalesDir)) {
|
|
678
|
+
fs4.mkdirSync(fullLocalesDir, { recursive: true });
|
|
664
679
|
}
|
|
665
680
|
const allLocales = [defaultLocale, ...targetLocales];
|
|
666
681
|
for (const locale of allLocales) {
|
|
667
|
-
const filePath =
|
|
668
|
-
if (!
|
|
669
|
-
|
|
682
|
+
const filePath = path4.join(fullLocalesDir, `${locale}.json`);
|
|
683
|
+
if (!fs4.existsSync(filePath)) {
|
|
684
|
+
fs4.writeFileSync(filePath, "{}", "utf-8");
|
|
670
685
|
console.log(
|
|
671
686
|
pc3.green(
|
|
672
|
-
|
|
687
|
+
`✅ 已生成 ${pc3.cyan(locale)} 语言文件: ${pc3.gray(
|
|
673
688
|
`src\\locales\\${locale}.json`
|
|
674
689
|
)}`
|
|
675
690
|
)
|
|
676
691
|
);
|
|
677
692
|
}
|
|
678
693
|
}
|
|
679
|
-
console.log(pc3.cyan("\n
|
|
680
|
-
console.log(
|
|
681
|
-
console.log(
|
|
682
|
-
console.log(
|
|
683
|
-
console.log(
|
|
694
|
+
console.log(pc3.cyan("\n🌍 AI 国际化助手已启动..."));
|
|
695
|
+
console.log(`📂 语言文件目录: ${pc3.yellow(localesDir)}`);
|
|
696
|
+
console.log(`🔤 默认语言: ${pc3.cyan(defaultLocale)}`);
|
|
697
|
+
console.log(`🎯 目标语言: ${pc3.cyan(targetLocales.join(", "))}`);
|
|
698
|
+
console.log(`🔍 自动扫描: ${autoScan ? pc3.green("✅") : pc3.red("❌")}`);
|
|
684
699
|
console.log(
|
|
685
|
-
|
|
700
|
+
`🤖 自动翻译: ${autoTranslate ? pc3.green("✅") : pc3.red("❌")}`
|
|
686
701
|
);
|
|
687
702
|
console.log(
|
|
688
|
-
|
|
703
|
+
`🔑 API Key: ${apiKey ? pc3.green("已配置") : pc3.yellow("未配置")}
|
|
689
704
|
`
|
|
690
705
|
);
|
|
691
706
|
},
|
|
692
707
|
async buildStart() {
|
|
693
708
|
if (!autoScan) return;
|
|
694
|
-
console.log(pc3.cyan("
|
|
709
|
+
console.log(pc3.cyan("🔍 正在扫描中文文本...\n"));
|
|
695
710
|
scannedTexts = await scanner.scan();
|
|
696
711
|
const totalTexts = Array.from(scannedTexts.values()).flat().length;
|
|
697
712
|
console.log(
|
|
698
|
-
pc3.blue(
|
|
713
|
+
pc3.blue(`📝 发现 ${pc3.yellow(totalTexts.toString())} 条待翻译文本
|
|
699
714
|
`)
|
|
700
715
|
);
|
|
701
716
|
if (totalTexts === 0) return;
|
|
@@ -703,7 +718,7 @@ function vitePluginAII18n(options = {}) {
|
|
|
703
718
|
if (autoTranslate && apiKey) {
|
|
704
719
|
for (const locale of targetLocales) {
|
|
705
720
|
console.log(pc3.cyan(`
|
|
706
|
-
|
|
721
|
+
🌐 正在翻译到 ${pc3.yellow(locale)}...`));
|
|
707
722
|
const existingTranslations = generator.loadExistingTranslations(locale);
|
|
708
723
|
const translations = await translator.translate(
|
|
709
724
|
scannedTexts,
|
|
@@ -718,7 +733,7 @@ function vitePluginAII18n(options = {}) {
|
|
|
718
733
|
);
|
|
719
734
|
}
|
|
720
735
|
}
|
|
721
|
-
console.log(pc3.green("\n
|
|
736
|
+
console.log(pc3.green("\n✨ 国际化处理完成\n"));
|
|
722
737
|
},
|
|
723
738
|
// 监听文件变化,增量更新
|
|
724
739
|
async handleHotUpdate({ file, server }) {
|
|
@@ -726,10 +741,10 @@ function vitePluginAII18n(options = {}) {
|
|
|
726
741
|
if (!file.match(/\.(vue|ts|tsx)$/)) return;
|
|
727
742
|
if (file.includes("node_modules") || file.includes(localesDir)) return;
|
|
728
743
|
console.log(`
|
|
729
|
-
|
|
744
|
+
🔄 检测到文件变化: ${file}`);
|
|
730
745
|
const texts = scanner.scanFile(file);
|
|
731
746
|
if (texts.length > 0) {
|
|
732
|
-
console.log(
|
|
747
|
+
console.log(`📝 发现 ${texts.length} 条新文本`);
|
|
733
748
|
scannedTexts.set(file, texts);
|
|
734
749
|
await generator.generate(scannedTexts, defaultLocale);
|
|
735
750
|
if (autoTranslate && apiKey) {
|
|
@@ -754,7 +769,8 @@ function vitePluginAII18n(options = {}) {
|
|
|
754
769
|
};
|
|
755
770
|
}
|
|
756
771
|
var index_default = vitePluginAII18n;
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
772
|
+
export {
|
|
773
|
+
index_default as default,
|
|
774
|
+
vitePluginAII18n
|
|
775
|
+
};
|
|
760
776
|
//# sourceMappingURL=index.mjs.map
|