@vite-plugin-i18n-auto/core 0.1.1 → 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/dist/index.d.ts CHANGED
@@ -50,7 +50,7 @@ interface WriteLocalesParams {
50
50
  targetLocales: string[];
51
51
  translate: TranslateMode;
52
52
  }
53
- /** 生成可供 runtime 安全解析的 index.ts(JSON 数组单行,便于正则 + JSON.parse) */
53
+ /** 生成可供 runtime 安全解析的 index.ts(空模块/语言列表时类型为 never,避免出现 `export type X = ;`) */
54
54
  declare function generateIndexTsContent(moduleNames: string[], locales: string[]): string;
55
55
  /**
56
56
  * 将聚合结果写入磁盘并生成 index.ts
package/dist/index.js CHANGED
@@ -75,7 +75,13 @@ function isModuleSpecifierLiteral(path) {
75
75
  function replaceStringLiteral(path, key, messages, value, callee) {
76
76
  messages[key] = value;
77
77
  const arg = callee === "__tr" ? t.stringLiteral(value) : t.stringLiteral(key);
78
- path.replaceWith(t.callExpression(t.identifier(callee), [arg]));
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
+ }
79
85
  }
80
86
  function replaceJsxText(path, key, messages, value, callee) {
81
87
  messages[key] = value;
@@ -144,17 +150,15 @@ function extractFromSource(code, options) {
144
150
  function generateIndexTsContent(moduleNames, locales) {
145
151
  const modSorted = [...moduleNames].sort();
146
152
  const locSorted = [...locales].sort();
147
- const localeUnion = locSorted.map((l) => JSON.stringify(l)).join(" | ");
148
- const moduleUnion = modSorted.map((m) => JSON.stringify(m)).join(" | ");
149
153
  const modulesJson = JSON.stringify(modSorted);
150
154
  const localesJson = JSON.stringify(locSorted);
151
155
  return `/* \u7531 vite-plugin-i18n-auto extract \u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u6539\u6A21\u5757/\u8BED\u8A00\u5217\u8868\u7ED3\u6784 */
152
- export type Locale = ${localeUnion};
153
- export type ModuleName = ${moduleUnion};
154
-
155
156
  export const modules = ${modulesJson} as const;
156
157
  export const locales = ${localesJson} as const;
157
158
 
159
+ export type ModuleName = (typeof modules)[number];
160
+ export type Locale = (typeof locales)[number];
161
+
158
162
  export async function loadModule(
159
163
  locale: Locale,
160
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\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 path.replaceWith(t.callExpression(t.identifier(callee), [arg]));\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(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,6 @@
1
1
  {
2
2
  "name": "@vite-plugin-i18n-auto/core",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",