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.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 (fs3.existsSync(fullPath)) {
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 (!fs3.existsSync(dir)) return;
38
- const entries = fs3.readdirSync(dir, { withFileTypes: true });
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 (!fs3.existsSync(filePath)) return [];
92
- const content = fs3.readFileSync(filePath, "utf-8");
93
- const ext = path.extname(filePath);
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(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u6587\u672C\u592A\u77ED`);
259
+ if (debug) console.log(`[过滤] "${text}" - 原因: 文本太短`);
255
260
  return false;
256
261
  }
257
262
  if (!/[\u4e00-\u9fa5]/.test(text)) {
258
- if (debug) console.log(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u4E0D\u5305\u542B\u4E2D\u6587`);
263
+ if (debug) console.log(`[过滤] "${text}" - 原因: 不包含中文`);
259
264
  return false;
260
265
  }
261
266
  if (/^\s*$/.test(text)) {
262
- if (debug) console.log(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u7EAF\u7A7A\u683C`);
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(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: i18n key`);
271
+ if (debug) console.log(`[过滤] "${text}" - 原因: i18n key`);
267
272
  return false;
268
273
  }
269
274
  if (/^[⚠️❌✅🔍📝💡🎯🚀🔧📊]/.test(text)) {
270
- if (debug) console.log(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u7CFB\u7EDF\u63D0\u793A`);
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(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u6280\u672F\u672F\u8BED`);
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(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u6280\u672F\u9519\u8BEF\u4FE1\u606F`);
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(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u53D8\u91CF\u540D`);
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(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u8DEF\u5F84`);
293
+ if (debug) console.log(`[过滤] "${text}" - 原因: 路径`);
289
294
  return false;
290
295
  }
291
296
  if (/^https?:\/\//.test(text)) {
292
- if (debug) console.log(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: URL`);
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(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u90AE\u7BB1`);
301
+ if (debug) console.log(`[过滤] "${text}" - 原因: 邮箱`);
297
302
  return false;
298
303
  }
299
304
  if (/^\d+$/.test(text)) {
300
- if (debug) console.log(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u7EAF\u6570\u5B57`);
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(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u65E5\u671F`);
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(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u4EE3\u7801\u7247\u6BB5`);
313
+ if (debug) console.log(`[过滤] "${text}" - 原因: 代码片段`);
309
314
  return false;
310
315
  }
311
316
  if (text.length > 100) {
312
- if (debug) console.log(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u6587\u672C\u8FC7\u957F`);
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(`[\u8FC7\u6EE4] "${text}" - \u539F\u56E0: \u7279\u6B8A\u5B57\u7B26\u8FC7\u591A (${specialCharCount})`);
323
+ console.log(`[过滤] "${text}" - 原因: 特殊字符过多 (${specialCharCount})`);
319
324
  return false;
320
325
  }
321
- if (debug) console.log(`[\u4FDD\u7559] "${text}"`);
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(pc3.yellow("\u26A0\uFE0F \u672A\u914D\u7F6E API Key\uFF0C\u8DF3\u8FC7\u7FFB\u8BD1"));
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(pc3.blue("\u{1F4CA} \u7FFB\u8BD1\u7EDF\u8BA1:"));
368
- console.log(` \u603B\u8BA1: ${pc3.cyan(uniqueTexts.length.toString())} \u6761`);
377
+ console.log(pc.blue("📊 翻译统计:"));
378
+ console.log(` 总计: ${pc.cyan(uniqueTexts.length.toString())} 条`);
369
379
  console.log(
370
- ` \u2705 \u5DF2\u6709: ${pc3.green(cachedTranslations.size.toString())} \u6761`
380
+ ` 已有: ${pc.green(cachedTranslations.size.toString())} 条`
371
381
  );
372
382
  console.log(
373
- ` \u{1F195} \u65B0\u589E: ${pc3.yellow(textsToTranslate.length.toString())} \u6761`
383
+ ` 🆕 新增: ${pc.yellow(textsToTranslate.length.toString())} 条`
374
384
  );
375
385
  try {
376
386
  let newTranslations = [];
377
387
  if (textsToTranslate.length > 0) {
378
- console.log(pc3.cyan(`
379
- \u{1F916} \u6B63\u5728\u7FFB\u8BD1\u65B0\u589E\u6587\u672C...`));
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(pc3.red("\u274C \u7FFB\u8BD1\u5931\u8D25:"), error.message);
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
- pc3.gray(
450
- ` \u{1F4CA} \u7FFB\u8BD1\u8FDB\u5EA6: ${pc3.cyan(progress.toString())}/${pc3.cyan(
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
- `\u4F60\u662F\u4E13\u4E1A\u7684\u8F6F\u4EF6\u672C\u5730\u5316\u7FFB\u8BD1\u4E13\u5BB6\u3002\u8BF7\u5C06\u4EE5\u4E0B${this.getLocaleName(
474
+ `你是专业的软件本地化翻译专家。请将以下${this.getLocaleName(
465
475
  sourceLocale
466
- )}\u6587\u672C\u7FFB\u8BD1\u6210${localeName}\u3002
467
- \u8981\u6C42\uFF1A
468
- 1. \u4FDD\u6301\u4E13\u4E1A\u672F\u8BED\u7684\u51C6\u786E\u6027
469
- 2. \u7FFB\u8BD1\u8981\u81EA\u7136\u6D41\u7545\uFF0C\u7B26\u5408\u76EE\u6807\u8BED\u8A00\u4E60\u60EF
470
- 3. \u4FDD\u7559\u539F\u6587\u4E2D\u7684\u53D8\u91CF\u5360\u4F4D\u7B26\uFF08\u5982 {name}\u3001%s \u7B49\uFF09
471
- 4. \u6BCF\u884C\u4E00\u4E2A\u7FFB\u8BD1\uFF0C\u4E0E\u8F93\u5165\u987A\u5E8F\u4E25\u683C\u5BF9\u5E94
472
- 5. \u53EA\u8F93\u51FA\u7FFB\u8BD1\u7ED3\u679C\uFF0C\u4E0D\u8981\u89E3\u91CA
473
- 6. \u5982\u679C\u539F\u6587\u5305\u542B\u6362\u884C\uFF0C\u7FFB\u8BD1\u4E5F\u4FDD\u6301\u76F8\u540C\u7684\u6362\u884C`
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": "\u7B80\u4F53\u4E2D\u6587",
498
- "zh-TW": "\u7E41\u4F53\u4E2D\u6587",
499
- "en-US": "\u82F1\u8BED",
500
- "ja-JP": "\u65E5\u8BED",
501
- "ko-KR": "\u97E9\u8BED",
502
- "fr-FR": "\u6CD5\u8BED",
503
- "de-DE": "\u5FB7\u8BED",
504
- "es-ES": "\u897F\u73ED\u7259\u8BED",
505
- "pt-BR": "\u8461\u8404\u7259\u8BED",
506
- "ru-RU": "\u4FC4\u8BED",
507
- "ar-SA": "\u963F\u62C9\u4F2F\u8BED"
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 = path.join(localesDir, `${locale}.json`);
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(pc3.yellow(`\u26A0\uFE0F \u65E0\u6CD5\u89E3\u6790\u73B0\u6709\u8BED\u8A00\u6587\u4EF6: ${filePath}`));
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(pc3.green(`\u2705 \u5DF2\u66F4\u65B0 ${pc3.cyan(locale)} \u8BED\u8A00\u6587\u4EF6: ${pc3.gray(filePath)}`));
564
+ console.log(pc2.green(`✅ 已更新 ${pc2.cyan(locale)} 语言文件: ${pc2.gray(filePath)}`));
550
565
  if (newCount > 0) {
551
- console.log(pc3.gray(` \u65B0\u589E ${pc3.yellow(newCount.toString())} \u6761\u7FFB\u8BD1`));
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 = path.join(localesDir, `${locale}.json`);
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(pc3.yellow(`\u26A0\uFE0F \u65E0\u6CD5\u89E3\u6790\u73B0\u6709\u8BED\u8A00\u6587\u4EF6: ${filePath}`));
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(pc3.green(`\u2705 \u5DF2\u66F4\u65B0 ${pc3.cyan(locale)} \u8BED\u8A00\u6587\u4EF6: ${pc3.gray(filePath)}`));
605
+ console.log(pc2.green(`✅ 已更新 ${pc2.cyan(locale)} 语言文件: ${pc2.gray(filePath)}`));
591
606
  if (newCount > 0) {
592
- console.log(pc3.gray(` \u2728 \u65B0\u589E ${pc3.yellow(newCount.toString())} \u6761\u7FFB\u8BD1`));
607
+ console.log(pc2.gray(` 新增 ${pc2.yellow(newCount.toString())} 条翻译`));
593
608
  }
594
609
  if (skippedCount > 0) {
595
- console.log(pc3.gray(` \u23ED\uFE0F \u8DF3\u8FC7 ${pc3.blue(skippedCount.toString())} \u6761\u5DF2\u6709\u7FFB\u8BD1`));
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 = path.join(localesDir, `${locale}.json`);
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(pc3.yellow(`\u26A0\uFE0F \u65E0\u6CD5\u89E3\u6790\u73B0\u6709\u8BED\u8A00\u6587\u4EF6: ${filePath}`));
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 = path.resolve(config.root, localesDir);
662
- if (!fs3.existsSync(fullLocalesDir)) {
663
- fs3.mkdirSync(fullLocalesDir, { recursive: true });
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 = path.join(fullLocalesDir, `${locale}.json`);
668
- if (!fs3.existsSync(filePath)) {
669
- fs3.writeFileSync(filePath, "{}", "utf-8");
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
- `\u2705 \u5DF2\u751F\u6210 ${pc3.cyan(locale)} \u8BED\u8A00\u6587\u4EF6: ${pc3.gray(
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\u{1F30D} AI \u56FD\u9645\u5316\u52A9\u624B\u5DF2\u542F\u52A8..."));
680
- console.log(`\u{1F4C2} \u8BED\u8A00\u6587\u4EF6\u76EE\u5F55: ${pc3.yellow(localesDir)}`);
681
- console.log(`\u{1F524} \u9ED8\u8BA4\u8BED\u8A00: ${pc3.cyan(defaultLocale)}`);
682
- console.log(`\u{1F3AF} \u76EE\u6807\u8BED\u8A00: ${pc3.cyan(targetLocales.join(", "))}`);
683
- console.log(`\u{1F50D} \u81EA\u52A8\u626B\u63CF: ${autoScan ? pc3.green("\u2705") : pc3.red("\u274C")}`);
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
- `\u{1F916} \u81EA\u52A8\u7FFB\u8BD1: ${autoTranslate ? pc3.green("\u2705") : pc3.red("\u274C")}`
700
+ `🤖 自动翻译: ${autoTranslate ? pc3.green("") : pc3.red("")}`
686
701
  );
687
702
  console.log(
688
- `\u{1F511} API Key: ${apiKey ? pc3.green("\u5DF2\u914D\u7F6E") : pc3.yellow("\u672A\u914D\u7F6E")}
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("\u{1F50D} \u6B63\u5728\u626B\u63CF\u4E2D\u6587\u6587\u672C...\n"));
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(`\u{1F4DD} \u53D1\u73B0 ${pc3.yellow(totalTexts.toString())} \u6761\u5F85\u7FFB\u8BD1\u6587\u672C
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
- \u{1F310} \u6B63\u5728\u7FFB\u8BD1\u5230 ${pc3.yellow(locale)}...`));
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\u2728 \u56FD\u9645\u5316\u5904\u7406\u5B8C\u6210\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
- \u{1F504} \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u5316: ${file}`);
744
+ 🔄 检测到文件变化: ${file}`);
730
745
  const texts = scanner.scanFile(file);
731
746
  if (texts.length > 0) {
732
- console.log(`\u{1F4DD} \u53D1\u73B0 ${texts.length} \u6761\u65B0\u6587\u672C`);
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
- export { index_default as default, vitePluginAII18n };
759
- //# sourceMappingURL=index.mjs.map
772
+ export {
773
+ index_default as default,
774
+ vitePluginAII18n
775
+ };
760
776
  //# sourceMappingURL=index.mjs.map