@vite-plugin-i18n-auto/core 0.1.0 → 0.1.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 malinli-88
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.d.ts CHANGED
@@ -17,8 +17,13 @@ interface ExtractCodeOptions {
17
17
  moduleName: string;
18
18
  /** 默认语言代码 */
19
19
  defaultLocale: string;
20
- /** 是否改写 AST t('key') */
20
+ /** 是否改写 AST 为翻译函数调用 */
21
21
  replaceInSource: boolean;
22
+ /**
23
+ * replaceInSource 为真时:`t('key')`(key 为稳定 hash)或 `__tr('原文')`(默认语言文案,切换语言时按反向表解析;仅插件生成)
24
+ */
25
+ /** inline 时用 `__tr('原文')`(仅插件生成,非对外 API);`t` 为按 key */
26
+ translateCallee?: 't' | '__tr';
22
27
  /** 静态通道 callee:处于这些调用内的字面量不提取 */
23
28
  skipCallNames?: string[];
24
29
  }
@@ -32,7 +37,7 @@ interface ExtractCodeResult {
32
37
  }
33
38
 
34
39
  /**
35
- * 从单文件源码提取中文并按选项替换为 t('key')
40
+ * 从单文件源码提取中文并按选项替换为 t('key') 或 __tr('原文')
36
41
  */
37
42
  declare function extractFromSource(code: string, options: ExtractCodeOptions): ExtractCodeResult;
38
43
 
@@ -45,7 +50,7 @@ interface WriteLocalesParams {
45
50
  targetLocales: string[];
46
51
  translate: TranslateMode;
47
52
  }
48
- /** 生成可供 runtime 安全解析的 index.ts(JSON 数组单行,便于正则 + JSON.parse) */
53
+ /** 生成可供 runtime 安全解析的 index.ts(空模块/语言列表时类型为 never,避免出现 `export type X = ;`) */
49
54
  declare function generateIndexTsContent(moduleNames: string[], locales: string[]): string;
50
55
  /**
51
56
  * 将聚合结果写入磁盘并生成 index.ts
package/dist/index.js CHANGED
@@ -42,7 +42,7 @@ function generateCode(ast, code) {
42
42
  return generateFn(ast, { retainLines: false, compact: false }, code).code;
43
43
  }
44
44
 
45
- const DEFAULT_SKIP_CALLS = ["t", "$t"];
45
+ const DEFAULT_SKIP_CALLS = ["t", "__tr", "$t", "$$t"];
46
46
  function buildSkipSet(extra) {
47
47
  const s = new Set(DEFAULT_SKIP_CALLS);
48
48
  if (extra) for (const n of extra) s.add(n);
@@ -65,18 +65,29 @@ function isInsideSkippedCall(path, skipSet) {
65
65
  }
66
66
  return false;
67
67
  }
68
+ function normalizeExtractText(raw) {
69
+ return raw.trim();
70
+ }
68
71
  function isModuleSpecifierLiteral(path) {
69
72
  const p = path.parentPath;
70
73
  return !!(p?.isImportDeclaration() || p?.isExportAllDeclaration() || p?.isExportNamedDeclaration() || p?.isImportExpression());
71
74
  }
72
- function replaceStringLiteral(path, key, messages, value) {
75
+ function replaceStringLiteral(path, key, messages, value, callee) {
73
76
  messages[key] = value;
74
- path.replaceWith(t.callExpression(t.identifier("t"), [t.stringLiteral(key)]));
77
+ const arg = callee === "__tr" ? t.stringLiteral(value) : t.stringLiteral(key);
78
+ const call = t.callExpression(t.identifier(callee), [arg]);
79
+ const parent = path.parentPath;
80
+ if (parent?.isJSXAttribute()) {
81
+ path.replaceWith(t.jsxExpressionContainer(call));
82
+ } else {
83
+ path.replaceWith(call);
84
+ }
75
85
  }
76
- function replaceJsxText(path, key, messages, value) {
86
+ function replaceJsxText(path, key, messages, value, callee) {
77
87
  messages[key] = value;
88
+ const arg = callee === "__tr" ? t.stringLiteral(value) : t.stringLiteral(key);
78
89
  path.replaceWith(
79
- t.jsxExpressionContainer(t.callExpression(t.identifier("t"), [t.stringLiteral(key)]))
90
+ t.jsxExpressionContainer(t.callExpression(t.identifier(callee), [arg]))
80
91
  );
81
92
  }
82
93
  function extractFromSource(code, options) {
@@ -92,28 +103,30 @@ function extractFromSource(code, options) {
92
103
  return { messages: {}, code, modified: false };
93
104
  }
94
105
  const { keyRegistry, filePath, replaceInSource } = options;
106
+ const callee = options.translateCallee ?? "t";
95
107
  const skipSet = buildSkipSet(options.skipCallNames);
96
108
  traverseAst(ast, {
97
109
  StringLiteral(path) {
98
- const v = path.node.value;
110
+ const v = normalizeExtractText(path.node.value);
111
+ if (!v) return;
99
112
  if (!hasChinese(v)) return;
100
113
  if (isModuleSpecifierLiteral(path)) return;
101
114
  if (isInsideSkippedCall(path, skipSet)) return;
102
115
  const key = makeStableKey(keyRegistry, filePath, v);
103
116
  if (replaceInSource) {
104
- replaceStringLiteral(path, key, messages, v);
117
+ replaceStringLiteral(path, key, messages, v, callee);
105
118
  } else {
106
119
  messages[key] = v;
107
120
  }
108
121
  },
109
122
  JSXText(path) {
110
- const v = path.node.value;
123
+ const v = normalizeExtractText(path.node.value);
124
+ if (!v) return;
111
125
  if (!hasChinese(v)) return;
112
126
  if (isInsideSkippedCall(path, skipSet)) return;
113
- if (!v.trim()) return;
114
127
  const key = makeStableKey(keyRegistry, filePath, v);
115
128
  if (replaceInSource) {
116
- replaceJsxText(path, key, messages, v);
129
+ replaceJsxText(path, key, messages, v, callee);
117
130
  } else {
118
131
  messages[key] = v;
119
132
  }
@@ -137,17 +150,15 @@ function extractFromSource(code, options) {
137
150
  function generateIndexTsContent(moduleNames, locales) {
138
151
  const modSorted = [...moduleNames].sort();
139
152
  const locSorted = [...locales].sort();
140
- const localeUnion = locSorted.map((l) => JSON.stringify(l)).join(" | ");
141
- const moduleUnion = modSorted.map((m) => JSON.stringify(m)).join(" | ");
142
153
  const modulesJson = JSON.stringify(modSorted);
143
154
  const localesJson = JSON.stringify(locSorted);
144
155
  return `/* \u7531 vite-plugin-i18n-auto extract \u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u6539\u6A21\u5757/\u8BED\u8A00\u5217\u8868\u7ED3\u6784 */
145
- export type Locale = ${localeUnion};
146
- export type ModuleName = ${moduleUnion};
147
-
148
156
  export const modules = ${modulesJson} as const;
149
157
  export const locales = ${localesJson} as const;
150
158
 
159
+ export type ModuleName = (typeof modules)[number];
160
+ export type Locale = (typeof locales)[number];
161
+
151
162
  export async function loadModule(
152
163
  locale: Locale,
153
164
  module: ModuleName
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/chinese.ts","../src/stable-key.ts","../src/babel-traverse.ts","../src/babel-generate.ts","../src/babel-extract.ts","../src/locale-writer.ts","../src/parse-index.ts"],"sourcesContent":["/** 是否包含需提取的中文(含常见 CJK 标点范围) */\nconst CHINESE_RE = /[\\u4e00-\\u9fff\\u3000-\\u303f\\uff00-\\uffef]/;\n\nexport function hasChinese(text: string): boolean {\n return CHINESE_RE.test(text);\n}\n","import { createHash } from 'node:crypto';\n\nconst usedKeys = new WeakMap<object, Set<string>>();\n\n/**\n * 基于文件路径与原文生成稳定 key,并在一次处理周期内按 registry 去重碰撞。\n */\nexport function makeStableKey(\n registry: object,\n filePath: string,\n literalText: string\n): string {\n const h = createHash('sha256')\n .update(`${filePath}\\0${literalText}`, 'utf8')\n .digest('hex')\n .slice(0, 12);\n let base = `i18n_${h}`;\n let set = usedKeys.get(registry);\n if (!set) {\n set = new Set();\n usedKeys.set(registry, set);\n }\n let key = base;\n let n = 0;\n while (set.has(key)) {\n key = `${base}_${++n}`;\n }\n set.add(key);\n return key;\n}\n\n/** 新一轮构建开始前清空某 registry(用聚合根对象作为 registry) */\nexport function clearKeyRegistry(registry: object): void {\n usedKeys.delete(registry);\n}\n","import traverseImport from '@babel/traverse';\nimport type { NodePath } from '@babel/traverse';\nimport type * as t from '@babel/types';\n\n/* CJS 打包进 ESM 后 default 可能落在 .default 上 */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst traverseFn = ((traverseImport as any).default ?? traverseImport) as (\n ast: t.File,\n visitor: object\n) => void;\n\nexport function traverseAst(ast: t.File, visitor: object): void {\n traverseFn(ast, visitor);\n}\n\nexport type { NodePath };\n","import genImport from '@babel/generator';\nimport type * as t from '@babel/types';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst generateFn = ((genImport as any).default ?? genImport) as (\n ast: t.Node,\n opts?: object,\n code?: string\n) => { code: string };\n\nexport function generateCode(ast: t.File, code: string): string {\n return generateFn(ast, { retainLines: false, compact: false }, code).code;\n}\n","import { parse } from '@babel/parser';\nimport type { NodePath } from '@babel/traverse';\nimport { traverseAst } from './babel-traverse.js';\nimport { generateCode } from './babel-generate.js';\nimport * as t from '@babel/types';\nimport type { ExtractCodeOptions, ExtractCodeResult } from './types.js';\nimport { hasChinese } from './chinese.js';\nimport { makeStableKey } from './stable-key.js';\n\nconst DEFAULT_SKIP_CALLS = ['t', '$t'];\n\nfunction buildSkipSet(extra?: string[]): Set<string> {\n const s = new Set<string>(DEFAULT_SKIP_CALLS);\n if (extra) for (const n of extra) s.add(n);\n return s;\n}\n\nfunction calleeMatchesSkip(\n callee: t.CallExpression['callee'],\n skipNames: Set<string>\n): boolean {\n if (t.isIdentifier(callee) && skipNames.has(callee.name)) return true;\n if (\n t.isMemberExpression(callee) &&\n !callee.computed &&\n t.isIdentifier(callee.object, { name: 'i18n' }) &&\n t.isIdentifier(callee.property, { name: 't' })\n ) {\n return true;\n }\n return false;\n}\n\n/** 字面量是否位于应跳过的 CallExpression 参数树内(t / $t / i18n.t) */\nfunction isInsideSkippedCall(\n path: NodePath<t.StringLiteral | t.JSXText>,\n skipSet: Set<string>\n): boolean {\n let p: NodePath<t.Node> | null = path.parentPath;\n while (p) {\n if (p.isCallExpression() && calleeMatchesSkip(p.node.callee, skipSet)) {\n return true;\n }\n p = p.parentPath;\n }\n return false;\n}\n\n/** import / export / dynamic import 的源字符串不提取 */\nfunction isModuleSpecifierLiteral(path: NodePath<t.StringLiteral>): boolean {\n const p = path.parentPath;\n return !!(\n p?.isImportDeclaration() ||\n p?.isExportAllDeclaration() ||\n p?.isExportNamedDeclaration() ||\n p?.isImportExpression()\n );\n}\n\nfunction replaceStringLiteral(\n path: NodePath<t.StringLiteral>,\n key: string,\n messages: Record<string, string>,\n value: string\n): void {\n messages[key] = value;\n path.replaceWith(t.callExpression(t.identifier('t'), [t.stringLiteral(key)]));\n}\n\nfunction replaceJsxText(\n path: NodePath<t.JSXText>,\n key: string,\n messages: Record<string, string>,\n value: string\n): void {\n messages[key] = value;\n path.replaceWith(\n t.jsxExpressionContainer(t.callExpression(t.identifier('t'), [t.stringLiteral(key)]))\n );\n}\n\n/**\n * 从单文件源码提取中文并按选项替换为 t('key')\n */\nexport function extractFromSource(code: string, options: ExtractCodeOptions): ExtractCodeResult {\n const messages: Record<string, string> = {};\n\n let ast: t.File;\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n errorRecovery: false,\n });\n } catch {\n return { messages: {}, code, modified: false };\n }\n\n const { keyRegistry, filePath, replaceInSource } = options;\n const skipSet = buildSkipSet(options.skipCallNames);\n\n traverseAst(ast, {\n StringLiteral(path) {\n const v = path.node.value;\n if (!hasChinese(v)) return;\n if (isModuleSpecifierLiteral(path)) return;\n if (isInsideSkippedCall(path, skipSet)) return;\n\n const key = makeStableKey(keyRegistry, filePath, v);\n if (replaceInSource) {\n replaceStringLiteral(path, key, messages, v);\n } else {\n messages[key] = v;\n }\n },\n JSXText(path) {\n const v = path.node.value;\n if (!hasChinese(v)) return;\n if (isInsideSkippedCall(path, skipSet)) return;\n if (!v.trim()) return;\n\n const key = makeStableKey(keyRegistry, filePath, v);\n if (replaceInSource) {\n replaceJsxText(path, key, messages, v);\n } else {\n messages[key] = v;\n }\n },\n });\n\n const hasMsgs = Object.keys(messages).length > 0;\n if (!hasMsgs) {\n return { messages: {}, code, modified: false };\n }\n\n if (!replaceInSource) {\n return { messages, code, modified: false };\n }\n\n const out = generateCode(ast, code);\n return {\n messages,\n code: out,\n modified: true,\n };\n}\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { TranslateMode } from './types.js';\n\nexport interface WriteLocalesParams {\n cwd: string;\n outputDir: string;\n /** moduleName -> locale -> messages */\n aggregate: Map<string, Map<string, Record<string, string>>>;\n defaultLocale: string;\n targetLocales: string[];\n translate: TranslateMode;\n}\n\n/** 生成可供 runtime 安全解析的 index.ts(JSON 数组单行,便于正则 + JSON.parse) */\nexport function generateIndexTsContent(\n moduleNames: string[],\n locales: string[]\n): string {\n const modSorted = [...moduleNames].sort();\n const locSorted = [...locales].sort();\n const localeUnion = locSorted.map((l) => JSON.stringify(l)).join(' | ');\n const moduleUnion = modSorted.map((m) => JSON.stringify(m)).join(' | ');\n const modulesJson = JSON.stringify(modSorted);\n const localesJson = JSON.stringify(locSorted);\n\n return `/* 由 vite-plugin-i18n-auto extract 生成,请勿手改模块/语言列表结构 */\nexport type Locale = ${localeUnion};\nexport type ModuleName = ${moduleUnion};\n\nexport const modules = ${modulesJson} as const;\nexport const locales = ${localesJson} as const;\n\nexport async function loadModule(\n locale: Locale,\n module: ModuleName\n): Promise<Record<string, string>> {\n const mod = await import(/* @vite-ignore */ \\`./\\${module}/\\${locale}.json\\`);\n return (mod as { default: Record<string, string> }).default;\n}\n`;\n}\n\n/**\n * 填充目标语言 key(占位空串),便于 manual / ai 写入\n */\nfunction ensureTargetPlaceholders(\n aggregate: Map<string, Map<string, Record<string, string>>>,\n defaultLocale: string,\n targetLocales: string[]\n): void {\n for (const [, byLoc] of aggregate) {\n const def = byLoc.get(defaultLocale) ?? {};\n for (const tl of targetLocales) {\n if (!byLoc.has(tl)) byLoc.set(tl, {});\n const tgt = byLoc.get(tl)!;\n for (const key of Object.keys(def)) {\n if (!(key in tgt)) tgt[key] = '';\n }\n }\n }\n}\n\nasync function readJsonFile(file: string): Promise<Record<string, string>> {\n try {\n const raw = await readFile(file, 'utf8');\n return JSON.parse(raw) as Record<string, string>;\n } catch {\n return {};\n }\n}\n\nfunction mergeDefaultLocale(\n existing: Record<string, string>,\n incoming: Record<string, string>\n): Record<string, string> {\n return { ...existing, ...incoming };\n}\n\n/** 目标语言:已有非空译文不被空字符串覆盖 */\nfunction mergeTargetLocale(\n existing: Record<string, string>,\n incoming: Record<string, string>\n): Record<string, string> {\n const out = { ...incoming };\n for (const [k, v] of Object.entries(existing)) {\n if (v && String(v).trim() !== '' && (!out[k] || String(out[k]).trim() === '')) {\n out[k] = v;\n }\n }\n return out;\n}\n\n/**\n * 将聚合结果写入磁盘并生成 index.ts\n */\nexport async function writeLocaleArtifacts(params: WriteLocalesParams): Promise<void> {\n const root = path.resolve(params.cwd, params.outputDir);\n await mkdir(root, { recursive: true });\n\n const { aggregate, defaultLocale, targetLocales, translate } = params;\n\n if (translate !== false) {\n ensureTargetPlaceholders(aggregate, defaultLocale, targetLocales);\n }\n\n const localesToWrite =\n translate === false ? [defaultLocale] : [defaultLocale, ...targetLocales];\n\n const moduleNames = [...aggregate.keys()].sort();\n\n for (const mod of moduleNames) {\n const byLoc = aggregate.get(mod)!;\n const modDir = path.join(root, mod);\n await mkdir(modDir, { recursive: true });\n\n for (const loc of localesToWrite) {\n const file = path.join(modDir, `${loc}.json`);\n const incoming = { ...(byLoc.get(loc) ?? {}) };\n const existing = await readJsonFile(file);\n const merged =\n loc === defaultLocale\n ? mergeDefaultLocale(existing, incoming)\n : mergeTargetLocale(existing, incoming);\n await writeFile(file, `${JSON.stringify(merged, null, 2)}\\n`, 'utf8');\n }\n }\n\n const indexLocales =\n translate === false ? [defaultLocale] : [defaultLocale, ...targetLocales];\n const indexContent = generateIndexTsContent(moduleNames, [...new Set(indexLocales)]);\n await writeFile(path.join(root, 'index.ts'), indexContent, 'utf8');\n}\n","/**\n * 从 extract 生成的 index.ts 源码中解析 modules、locales(禁止 eval)\n */\nexport function parseModulesAndLocalesFromIndexTs(source: string): {\n modules: string[];\n locales: string[];\n} {\n const modMatch = source.match(/export const modules = (\\[[^\\]]*\\])\\s+as\\s+const/);\n const locMatch = source.match(/export const locales = (\\[[^\\]]*\\])\\s+as\\s+const/);\n let modules: string[] = [];\n let locales: string[] = [];\n try {\n if (modMatch) modules = JSON.parse(modMatch[1]) as string[];\n } catch {\n modules = [];\n }\n try {\n if (locMatch) locales = JSON.parse(locMatch[1]) as string[];\n } catch {\n locales = [];\n }\n return { modules, locales };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/chinese.ts","../src/stable-key.ts","../src/babel-traverse.ts","../src/babel-generate.ts","../src/babel-extract.ts","../src/locale-writer.ts","../src/parse-index.ts"],"sourcesContent":["/** 是否包含需提取的中文(含常见 CJK 标点范围) */\nconst CHINESE_RE = /[\\u4e00-\\u9fff\\u3000-\\u303f\\uff00-\\uffef]/;\n\nexport function hasChinese(text: string): boolean {\n return CHINESE_RE.test(text);\n}\n","import { createHash } from 'node:crypto';\n\nconst usedKeys = new WeakMap<object, Set<string>>();\n\n/**\n * 基于文件路径与原文生成稳定 key,并在一次处理周期内按 registry 去重碰撞。\n */\nexport function makeStableKey(\n registry: object,\n filePath: string,\n literalText: string\n): string {\n const h = createHash('sha256')\n .update(`${filePath}\\0${literalText}`, 'utf8')\n .digest('hex')\n .slice(0, 12);\n let base = `i18n_${h}`;\n let set = usedKeys.get(registry);\n if (!set) {\n set = new Set();\n usedKeys.set(registry, set);\n }\n let key = base;\n let n = 0;\n while (set.has(key)) {\n key = `${base}_${++n}`;\n }\n set.add(key);\n return key;\n}\n\n/** 新一轮构建开始前清空某 registry(用聚合根对象作为 registry) */\nexport function clearKeyRegistry(registry: object): void {\n usedKeys.delete(registry);\n}\n","import traverseImport from '@babel/traverse';\nimport type { NodePath } from '@babel/traverse';\nimport type * as t from '@babel/types';\n\n/* CJS 打包进 ESM 后 default 可能落在 .default 上 */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst traverseFn = ((traverseImport as any).default ?? traverseImport) as (\n ast: t.File,\n visitor: object\n) => void;\n\nexport function traverseAst(ast: t.File, visitor: object): void {\n traverseFn(ast, visitor);\n}\n\nexport type { NodePath };\n","import genImport from '@babel/generator';\nimport type * as t from '@babel/types';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst generateFn = ((genImport as any).default ?? genImport) as (\n ast: t.Node,\n opts?: object,\n code?: string\n) => { code: string };\n\nexport function generateCode(ast: t.File, code: string): string {\n return generateFn(ast, { retainLines: false, compact: false }, code).code;\n}\n","import { parse } from '@babel/parser';\nimport type { NodePath } from '@babel/traverse';\nimport { traverseAst } from './babel-traverse.js';\nimport { generateCode } from './babel-generate.js';\nimport * as t from '@babel/types';\nimport type { ExtractCodeOptions, ExtractCodeResult } from './types.js';\nimport { hasChinese } from './chinese.js';\nimport { makeStableKey } from './stable-key.js';\n\n/** t / __tr / $t:已接入 i18n;$$t:显式不参与提取与翻译(__tr 仅插件注入,不对手写 tr 兼容) */\nconst DEFAULT_SKIP_CALLS = ['t', '__tr', '$t', '$$t'];\n\nfunction buildSkipSet(extra?: string[]): Set<string> {\n const s = new Set<string>(DEFAULT_SKIP_CALLS);\n if (extra) for (const n of extra) s.add(n);\n return s;\n}\n\nfunction calleeMatchesSkip(\n callee: t.CallExpression['callee'],\n skipNames: Set<string>\n): boolean {\n if (t.isIdentifier(callee) && skipNames.has(callee.name)) return true;\n if (\n t.isMemberExpression(callee) &&\n !callee.computed &&\n t.isIdentifier(callee.object, { name: 'i18n' }) &&\n t.isIdentifier(callee.property, { name: 't' })\n ) {\n return true;\n }\n return false;\n}\n\n/** 字面量是否位于应跳过的 CallExpression 参数树内(t / __tr / $t / $$t / i18n.t) */\nfunction isInsideSkippedCall(\n path: NodePath<t.StringLiteral | t.JSXText>,\n skipSet: Set<string>\n): boolean {\n let p: NodePath<t.Node> | null = path.parentPath;\n while (p) {\n if (p.isCallExpression() && calleeMatchesSkip(p.node.callee, skipSet)) {\n return true;\n }\n p = p.parentPath;\n }\n return false;\n}\n\n/**\n * 提取与 key 生成使用:去掉前后空格、换行等,避免 JSX 缩进导致语言包原文与 __tr(…) 不一致\n */\nfunction normalizeExtractText(raw: string): string {\n return raw.trim();\n}\n\n/** import / export / dynamic import 的源字符串不提取 */\nfunction isModuleSpecifierLiteral(path: NodePath<t.StringLiteral>): boolean {\n const p = path.parentPath;\n return !!(\n p?.isImportDeclaration() ||\n p?.isExportAllDeclaration() ||\n p?.isExportNamedDeclaration() ||\n p?.isImportExpression()\n );\n}\n\nfunction replaceStringLiteral(\n path: NodePath<t.StringLiteral>,\n key: string,\n messages: Record<string, string>,\n value: string,\n callee: 't' | '__tr'\n): void {\n messages[key] = value;\n const arg = callee === '__tr' ? t.stringLiteral(value) : t.stringLiteral(key);\n const call = t.callExpression(t.identifier(callee), [arg]);\n // JSX 属性简写为 attr=\"中文\" 时 value 为 StringLiteral,需包一层 JSXExpressionContainer,否则替换为 CallExpression 非法\n const parent = path.parentPath;\n if (parent?.isJSXAttribute()) {\n path.replaceWith(t.jsxExpressionContainer(call));\n } else {\n path.replaceWith(call);\n }\n}\n\nfunction replaceJsxText(\n path: NodePath<t.JSXText>,\n key: string,\n messages: Record<string, string>,\n value: string,\n callee: 't' | '__tr'\n): void {\n messages[key] = value;\n const arg = callee === '__tr' ? t.stringLiteral(value) : t.stringLiteral(key);\n path.replaceWith(\n t.jsxExpressionContainer(t.callExpression(t.identifier(callee), [arg]))\n );\n}\n\n/**\n * 从单文件源码提取中文并按选项替换为 t('key') 或 __tr('原文')\n */\nexport function extractFromSource(code: string, options: ExtractCodeOptions): ExtractCodeResult {\n const messages: Record<string, string> = {};\n\n let ast: t.File;\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n errorRecovery: false,\n });\n } catch {\n return { messages: {}, code, modified: false };\n }\n\n const { keyRegistry, filePath, replaceInSource } = options;\n const callee: 't' | '__tr' = options.translateCallee ?? 't';\n const skipSet = buildSkipSet(options.skipCallNames);\n\n traverseAst(ast, {\n StringLiteral(path: NodePath<t.StringLiteral>) {\n const v = normalizeExtractText(path.node.value);\n if (!v) return;\n if (!hasChinese(v)) return;\n if (isModuleSpecifierLiteral(path)) return;\n if (isInsideSkippedCall(path, skipSet)) return;\n\n const key = makeStableKey(keyRegistry, filePath, v);\n if (replaceInSource) {\n replaceStringLiteral(path, key, messages, v, callee);\n } else {\n messages[key] = v;\n }\n },\n JSXText(path: NodePath<t.JSXText>) {\n const v = normalizeExtractText(path.node.value);\n if (!v) return;\n if (!hasChinese(v)) return;\n if (isInsideSkippedCall(path, skipSet)) return;\n\n const key = makeStableKey(keyRegistry, filePath, v);\n if (replaceInSource) {\n replaceJsxText(path, key, messages, v, callee);\n } else {\n messages[key] = v;\n }\n },\n });\n\n const hasMsgs = Object.keys(messages).length > 0;\n if (!hasMsgs) {\n return { messages: {}, code, modified: false };\n }\n\n if (!replaceInSource) {\n return { messages, code, modified: false };\n }\n\n const out = generateCode(ast, code);\n return {\n messages,\n code: out,\n modified: true,\n };\n}\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { TranslateMode } from './types.js';\n\nexport interface WriteLocalesParams {\n cwd: string;\n outputDir: string;\n /** moduleName -> locale -> messages */\n aggregate: Map<string, Map<string, Record<string, string>>>;\n defaultLocale: string;\n targetLocales: string[];\n translate: TranslateMode;\n}\n\n/** 生成可供 runtime 安全解析的 index.ts(空模块/语言列表时类型为 never,避免出现 `export type X = ;`) */\nexport function generateIndexTsContent(\n moduleNames: string[],\n locales: string[]\n): string {\n const modSorted = [...moduleNames].sort();\n const locSorted = [...locales].sort();\n const modulesJson = JSON.stringify(modSorted);\n const localesJson = JSON.stringify(locSorted);\n\n return `/* 由 vite-plugin-i18n-auto extract 生成,请勿手改模块/语言列表结构 */\nexport const modules = ${modulesJson} as const;\nexport const locales = ${localesJson} as const;\n\nexport type ModuleName = (typeof modules)[number];\nexport type Locale = (typeof locales)[number];\n\nexport async function loadModule(\n locale: Locale,\n module: ModuleName\n): Promise<Record<string, string>> {\n const mod = await import(/* @vite-ignore */ \\`./\\${module}/\\${locale}.json\\`);\n return (mod as { default: Record<string, string> }).default;\n}\n`;\n}\n\n/**\n * 填充目标语言 key(占位空串),便于 manual / ai 写入\n */\nfunction ensureTargetPlaceholders(\n aggregate: Map<string, Map<string, Record<string, string>>>,\n defaultLocale: string,\n targetLocales: string[]\n): void {\n for (const [, byLoc] of aggregate) {\n const def = byLoc.get(defaultLocale) ?? {};\n for (const tl of targetLocales) {\n if (!byLoc.has(tl)) byLoc.set(tl, {});\n const tgt = byLoc.get(tl)!;\n for (const key of Object.keys(def)) {\n if (!(key in tgt)) tgt[key] = '';\n }\n }\n }\n}\n\nasync function readJsonFile(file: string): Promise<Record<string, string>> {\n try {\n const raw = await readFile(file, 'utf8');\n return JSON.parse(raw) as Record<string, string>;\n } catch {\n return {};\n }\n}\n\nfunction mergeDefaultLocale(\n existing: Record<string, string>,\n incoming: Record<string, string>\n): Record<string, string> {\n return { ...existing, ...incoming };\n}\n\n/** 目标语言:已有非空译文不被空字符串覆盖 */\nfunction mergeTargetLocale(\n existing: Record<string, string>,\n incoming: Record<string, string>\n): Record<string, string> {\n const out = { ...incoming };\n for (const [k, v] of Object.entries(existing)) {\n if (v && String(v).trim() !== '' && (!out[k] || String(out[k]).trim() === '')) {\n out[k] = v;\n }\n }\n return out;\n}\n\n/**\n * 将聚合结果写入磁盘并生成 index.ts\n */\nexport async function writeLocaleArtifacts(params: WriteLocalesParams): Promise<void> {\n const root = path.resolve(params.cwd, params.outputDir);\n await mkdir(root, { recursive: true });\n\n const { aggregate, defaultLocale, targetLocales, translate } = params;\n\n if (translate !== false) {\n ensureTargetPlaceholders(aggregate, defaultLocale, targetLocales);\n }\n\n const localesToWrite =\n translate === false ? [defaultLocale] : [defaultLocale, ...targetLocales];\n\n const moduleNames = [...aggregate.keys()].sort();\n\n for (const mod of moduleNames) {\n const byLoc = aggregate.get(mod)!;\n const modDir = path.join(root, mod);\n await mkdir(modDir, { recursive: true });\n\n for (const loc of localesToWrite) {\n const file = path.join(modDir, `${loc}.json`);\n const incoming = { ...(byLoc.get(loc) ?? {}) };\n const existing = await readJsonFile(file);\n const merged =\n loc === defaultLocale\n ? mergeDefaultLocale(existing, incoming)\n : mergeTargetLocale(existing, incoming);\n await writeFile(file, `${JSON.stringify(merged, null, 2)}\\n`, 'utf8');\n }\n }\n\n const indexLocales =\n translate === false ? [defaultLocale] : [defaultLocale, ...targetLocales];\n const indexContent = generateIndexTsContent(moduleNames, [...new Set(indexLocales)]);\n await writeFile(path.join(root, 'index.ts'), indexContent, 'utf8');\n}\n","/**\n * 从 extract 生成的 index.ts 源码中解析 modules、locales(禁止 eval)\n */\nexport function parseModulesAndLocalesFromIndexTs(source: string): {\n modules: string[];\n locales: string[];\n} {\n const modMatch = source.match(/export const modules = (\\[[^\\]]*\\])\\s+as\\s+const/);\n const locMatch = source.match(/export const locales = (\\[[^\\]]*\\])\\s+as\\s+const/);\n let modules: string[] = [];\n let locales: string[] = [];\n try {\n if (modMatch) modules = JSON.parse(modMatch[1]) as string[];\n } catch {\n modules = [];\n }\n try {\n if (locMatch) locales = JSON.parse(locMatch[1]) as string[];\n } catch {\n locales = [];\n }\n return { modules, locales };\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,19 @@
1
1
  {
2
2
  "name": "@vite-plugin-i18n-auto/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
+ "license": "MIT",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/malinli-88/vite-plugin-i18n-auto.git",
8
+ "directory": "packages/core"
9
+ },
10
+ "bugs": {
11
+ "url": "https://github.com/malinli-88/vite-plugin-i18n-auto/issues"
12
+ },
13
+ "homepage": "https://github.com/malinli-88/vite-plugin-i18n-auto/tree/main/packages/core#readme",
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
4
17
  "type": "module",
5
18
  "main": "./dist/index.js",
6
19
  "module": "./dist/index.js",