vue-i18n-extract-plugin 1.0.49 → 1.0.51

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/lib/index.js CHANGED
@@ -38,6 +38,10 @@ const {
38
38
  extractScriptContent
39
39
  } = require("./import-i18n-transform");
40
40
 
41
+ function defineConfig(options) {
42
+ return options;
43
+ }
44
+
41
45
  module.exports = {
42
46
  babelPluginI18n,
43
47
  extractI18n,
@@ -70,5 +74,6 @@ module.exports = {
70
74
  babelPluginImportI18n,
71
75
  i18nImportAstTransform,
72
76
  i18nImportTransform,
73
- extractScriptContent
77
+ extractScriptContent,
78
+ defineConfig
74
79
  };
package/lib/visitors.js CHANGED
@@ -15,6 +15,84 @@ function isTFunction(node, option) {
15
15
  );
16
16
  }
17
17
 
18
+ function isCreateTextVNodeCall(path) {
19
+ const node = path.node;
20
+ if (!path.isCallExpression()) return false;
21
+
22
+ const callee = node.callee;
23
+ return (
24
+ (t.isIdentifier(callee) && callee.name === "_createTextVNode") ||
25
+ (t.isMemberExpression(callee) &&
26
+ t.isIdentifier(callee.property) &&
27
+ callee.property.name === "_createTextVNode")
28
+ );
29
+ }
30
+
31
+ function getPropKey(propNode) {
32
+ if (t.isIdentifier(propNode.key)) {
33
+ return propNode.key.name;
34
+ }
35
+ if (t.isStringLiteral(propNode.key)) {
36
+ return propNode.key.value; // .replace(/-([a-z])/g, (_, char) => char.toUpperCase());
37
+ }
38
+ return null;
39
+ }
40
+
41
+ function transformDirectiveIfNeeded(path, parentPath) {
42
+ let hasCreateVNode = false;
43
+ // 属性值情况,如 title: "xxx"
44
+ if (parentPath.isObjectProperty()) {
45
+ const propKey = getPropKey(parentPath.node);
46
+
47
+ if (!propKey) return;
48
+
49
+ const vNodeCall = path.findParent(
50
+ p =>
51
+ p.isCallExpression() &&
52
+ (t.isIdentifier(p.node.callee, { name: "_createVNode" }) ||
53
+ (t.isMemberExpression(p.node.callee) &&
54
+ t.isIdentifier(p.node.callee.property, { name: "_createVNode" })))
55
+ );
56
+
57
+ if (vNodeCall) {
58
+ hasCreateVNode = true;
59
+ const args = vNodeCall.node.arguments;
60
+ // PatchFlag = 8 (PROPS), dynamicProps = ["title"]
61
+ const patchFlagIndex = 3;
62
+ const dynamicPropsIndex = 4;
63
+
64
+ // 确保第 3 个参数(children)存在,否则补 null
65
+ if (args.length === 2) {
66
+ args.push(t.nullLiteral()); // => 第三个参数
67
+ }
68
+
69
+ // 补齐参数数组长度到第 5 个参数(index: 4)
70
+ while (args.length <= dynamicPropsIndex) {
71
+ args.push(null);
72
+ }
73
+
74
+ // 设置 patchFlag = 8
75
+ args[patchFlagIndex] = t.numericLiteral(8);
76
+
77
+ // 设置 dynamicProps = ["propKey"]
78
+ const existingDynamicProps = args[dynamicPropsIndex];
79
+ if (!existingDynamicProps || !t.isArrayExpression(existingDynamicProps)) {
80
+ args[dynamicPropsIndex] = t.arrayExpression([t.stringLiteral(propKey)]);
81
+ } else {
82
+ const existingKeys = new Set(
83
+ existingDynamicProps.elements
84
+ .filter(el => t.isStringLiteral(el))
85
+ .map(el => el.value)
86
+ );
87
+ if (!existingKeys.has(propKey)) {
88
+ existingDynamicProps.elements.push(t.stringLiteral(propKey));
89
+ }
90
+ }
91
+ }
92
+ }
93
+ return hasCreateVNode;
94
+ }
95
+
18
96
  function shouldTransform(path) {
19
97
  const parent = path.parentPath;
20
98
  return !(
@@ -112,10 +190,42 @@ function createI18nVisitor(option, i18nMap) {
112
190
  i18nMap[hashed] = value;
113
191
  }
114
192
 
115
- const callExpression = t.callExpression(
116
- t.identifier(option.translateKey),
117
- [t.stringLiteral(hashed)]
118
- );
193
+ let callExpression;
194
+
195
+ // 判断是否createTextVNode或MemberExpression(如 Vue.createTextVNode)
196
+ if (isCreateTextVNodeCall(parentPath)) {
197
+ // _ctx.$t("hashed")
198
+ callExpression = t.callExpression(
199
+ t.memberExpression(
200
+ t.identifier("_ctx"),
201
+ t.identifier(option.translateKey)
202
+ ),
203
+ [t.stringLiteral(hashed)]
204
+ );
205
+
206
+ // 如果 createTextVNode 参数只有一个,则补充第二个参数 1
207
+ const args = parentPath.node.arguments;
208
+ if (args.length === 1) {
209
+ parentPath.node.arguments = [callExpression, t.numericLiteral(1)];
210
+ }
211
+ } else {
212
+ const hasCreateVNode = transformDirectiveIfNeeded(path, parentPath);
213
+ if (hasCreateVNode) {
214
+ callExpression = t.callExpression(
215
+ t.memberExpression(
216
+ t.identifier("_ctx"),
217
+ t.identifier(option.translateKey)
218
+ ),
219
+ [t.stringLiteral(hashed)]
220
+ );
221
+ } else {
222
+ // $t("hashed")
223
+ callExpression = t.callExpression(t.identifier(option.translateKey), [
224
+ t.stringLiteral(hashed)
225
+ ]);
226
+ }
227
+ }
228
+
119
229
  // 如果是 JSX 属性值,需要包裹在 JSXExpressionContainer 中
120
230
  if (parentPath.isJSXAttribute()) {
121
231
  const jsxExpression = t.jsxExpressionContainer(callExpression);
package/package.json CHANGED
@@ -1,17 +1,40 @@
1
1
  {
2
2
  "name": "vue-i18n-extract-plugin",
3
- "version": "1.0.49",
3
+ "version": "1.0.51",
4
4
  "main": "lib/index.js",
5
5
  "types": "types/index.d.ts",
6
6
  "bin": {
7
7
  "extract-i18n": "lib/cli.js"
8
8
  },
9
9
  "exports": {
10
- ".": "./lib/index.js",
11
- "./translators": "./lib/translators/index.js",
12
- "./babel-plugin-i18n": "./lib/babel-plugin-i18n.js",
13
- "./babel-plugin-import-i18n": "./lib/babel-plugin-import-i18n.js",
14
- "./webpack-import-i18n-loader": "./lib/webpack-import-i18n-loader.js"
10
+ ".": {
11
+ "require": "./lib/index.js",
12
+ "import": "./lib/index.js",
13
+ "types": "./types/index.d.ts"
14
+ },
15
+ "./translators": {
16
+ "require": "./lib/translators/index.js",
17
+ "import": "./lib/translators/index.js",
18
+ "types": "./types/translators/index.d.ts"
19
+ },
20
+ "./babel-plugin-i18n": {
21
+ "require": "./lib/babel-plugin-i18n.js",
22
+ "import": "./lib/babel-plugin-i18n.js",
23
+ "types": "./types/babel-plugin-i18n.d.ts"
24
+ },
25
+ "./babel-plugin-import-i18n": {
26
+ "require": "./lib/babel-plugin-import-i18n.js",
27
+ "import": "./lib/babel-plugin-import-i18n.js",
28
+ "types": "./types/babel-plugin-import-i18n.d.ts"
29
+ },
30
+ "./webpack-import-i18n-loader": {
31
+ "require": "./lib/webpack-import-i18n-loader.js",
32
+ "import": "./lib/webpack-import-i18n-loader.js",
33
+ "types": "./types/webpack-import-i18n-loader.d.ts"
34
+ },
35
+ "./client": {
36
+ "types": "./types/extract-i18n.config.d.ts"
37
+ }
15
38
  },
16
39
  "keywords": [
17
40
  "vue-i18n-extract-plugin",
@@ -1,6 +1,6 @@
1
1
  import { PluginObj, PluginPass } from '@babel/core';
2
2
  import { I18nOptions } from './options';
3
3
 
4
- declare const plugin: (api: any, options?: I18nOptions) => PluginObj<PluginPass>;
4
+ declare const plugin: (api: any, options?: Partial<I18nOptions>) => PluginObj<PluginPass>;
5
5
 
6
6
  export default plugin;
@@ -1,6 +1,6 @@
1
1
  import { PluginObj } from '@babel/core';
2
2
  import { I18nOptions } from './options';
3
3
 
4
- declare function babelPluginImportI18n(options?: I18nOptions): PluginObj;
4
+ declare function babelPluginImportI18n(options?: Partial<I18nOptions>): PluginObj;
5
5
 
6
6
  export = babelPluginImportI18n;
@@ -0,0 +1,7 @@
1
+ import { I18nOptions } from './options';
2
+
3
+ declare module 'extract-i18n.config.ts' {
4
+ const config: Partial<I18nOptions>;
5
+ export default config;
6
+ }
7
+
@@ -9,13 +9,13 @@ export interface WriteResult {
9
9
 
10
10
  export function writeI18nMapToFile(
11
11
  i18nMap: I18nMap,
12
- options: Options,
12
+ options: Partial<Options>,
13
13
  checkDiffs?: boolean
14
14
  ): Promise<WriteResult>;
15
15
 
16
16
  export function handleFinalI18nMap(
17
17
  i18nMap: I18nMap,
18
- options: Options,
18
+ options: Partial<Options>,
19
19
  checkDiffs?: boolean
20
20
  ): Promise<void>;
21
21
 
@@ -23,6 +23,6 @@ export function addI18nImportIfNeeded(ast: Node, options: Partial<Options>): Nod
23
23
  export function addI18nImportIfNeeded(ast: Node, options: Partial<Options>, generateCode: false): Node
24
24
  export function addI18nImportIfNeeded(ast: Node, options: Partial<Options>, generateCode: true): string
25
25
 
26
- export function extractI18n(options: Options): Promise<void>;
26
+ export function extractI18n(options: Partial<Options>): Promise<void>;
27
27
 
28
28
  export let globalI18nMap: I18nMap;
package/types/index.d.ts CHANGED
@@ -1,8 +1,6 @@
1
- /// <reference path="./extract-i18n.config.d.ts" />
2
-
3
1
  export { default as babelPluginI18n } from "./babel-plugin-i18n";
4
2
  export { extractI18n, addI18nImportIfNeeded } from "./extract";
5
- export { I18nOptions as defaultOptions } from "./options";
3
+ import { I18nOptions } from "./options";
6
4
  export {
7
5
  autoTranslate,
8
6
  translateChunks,
@@ -38,4 +36,10 @@ export {
38
36
  i18nImportAstTransform,
39
37
  i18nImportTransform,
40
38
  extractScriptContent
41
- } from "./import-i18n-transform";
39
+ } from "./import-i18n-transform";
40
+
41
+ declare const defaultOptions: I18nOptions;
42
+
43
+ export { defaultOptions }
44
+
45
+ export function defineConfig(options: Partial<I18nOptions>): I18nOptions;
package/types/utils.d.ts CHANGED
@@ -8,7 +8,7 @@ export function isEmptyObject(obj: Record<string, any>): boolean;
8
8
  export function checkAgainstRegexArray(value: string, regexArray?: (string | RegExp)[]): boolean;
9
9
  export function extractFunctionName(path: NodePath): string;
10
10
  export function relativeCWDPath(subPath: string): string;
11
- export function getLangJsonPath(langKey: LangKey, option: I18nOptions): string;
11
+ export function getLangJsonPath(langKey: LangKey, option: Partial<I18nOptions>): string;
12
12
  export function readJsonWithDefault(pathStr: string, defaultValue?: Record<string, any>): Record<string, any>;
13
13
  export function resolveAliasPath(pathStr: string): string;
14
14
  export function resolveFilterPath(pathStr: string): string;
@@ -4,6 +4,6 @@ import { I18nOptions } from "./options";
4
4
  import { I18nMap } from "./common";
5
5
 
6
6
  export declare function shouldTransform(path: NodePath): boolean;
7
- export declare function isTFunction(node: Node, option: I18nOptions): boolean;
8
- export declare function createI18nVisitor(option: I18nOptions, i18nMap?: I18nMap): Record<string, (path: NodePath) => void>;
9
- export declare function createI18nPlugin(option: I18nOptions, i18nMap?: I18nMap): () => { visitor: Record<string, (path: NodePath) => void> };
7
+ export declare function isTFunction(node: Node, option: Partial<I18nOptions>): boolean;
8
+ export declare function createI18nVisitor(option: Partial<I18nOptions>, i18nMap?: I18nMap): Record<string, (path: NodePath) => void>;
9
+ export declare function createI18nPlugin(option: Partial<I18nOptions>, i18nMap?: I18nMap): () => { visitor: Record<string, (path: NodePath) => void> };
@@ -2,7 +2,7 @@ import webpack from 'webpack'
2
2
  import { I18nOptions } from './options';
3
3
 
4
4
  export declare class WebpackPluginI18n {
5
- options: I18nOptions;
5
+ options: Partial<I18nOptions>;
6
6
  timer: NodeJS.Timeout | null;
7
7
  constructor(optionInfo?: Partial<I18nOptions>);
8
8
  apply(compiler: webpack.Compiler): void;
@@ -1,7 +0,0 @@
1
- import { I18nOptions as Options } from './options';
2
-
3
- declare module 'extract-i18n.config' {
4
- const config: Options;
5
- export default config;
6
- }
7
-