vue-i18n-extract-plugin 1.0.53 → 1.0.55
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/README.md +1 -0
- package/lib/index.js +2 -0
- package/lib/options.js +1 -0
- package/lib/utils.js +16 -4
- package/lib/visitors.js +93 -1
- package/package.json +1 -1
- package/types/index.d.ts +1 -0
- package/types/utils.d.ts +1 -0
package/README.md
CHANGED
|
@@ -48,6 +48,7 @@ extractI18n(options)
|
|
|
48
48
|
```javascript
|
|
49
49
|
const defaultOptions = {
|
|
50
50
|
translateKey: "$t", // 提取的函数的名称
|
|
51
|
+
JSXElement: "Trans", // 提取的函数的 JSX 元素名称 默认为 Trans, 如:<Trans id="aaa" defaultMsg="xxx" />
|
|
51
52
|
rewrite: false, // 是否将提取到的内容转换为id后重写入源文件
|
|
52
53
|
extractFromText: true, // 是否允许从纯文本节点中提取翻译内容
|
|
53
54
|
autoImportI18n: true, // 是否自动导入 i18n 模块
|
package/lib/index.js
CHANGED
|
@@ -16,6 +16,7 @@ const {
|
|
|
16
16
|
relativeCWDPath,
|
|
17
17
|
getLangJsonPath,
|
|
18
18
|
shouldExtract,
|
|
19
|
+
registerLangMatch,
|
|
19
20
|
trimEmptyLine,
|
|
20
21
|
padEmptyLine,
|
|
21
22
|
excludeDirectives,
|
|
@@ -58,6 +59,7 @@ module.exports = {
|
|
|
58
59
|
extractFunctionName,
|
|
59
60
|
relativeCWDPath,
|
|
60
61
|
shouldExtract,
|
|
62
|
+
registerLangMatch,
|
|
61
63
|
trimEmptyLine,
|
|
62
64
|
padEmptyLine,
|
|
63
65
|
excludeDirectives,
|
package/lib/options.js
CHANGED
|
@@ -2,6 +2,7 @@ const { GoogleTranslator } = require("./translators");
|
|
|
2
2
|
|
|
3
3
|
const defaultOptions = {
|
|
4
4
|
translateKey: "$t", // 提取的函数的名称
|
|
5
|
+
JSXElement: "Trans", // 提取的函数的 JSX 元素名称 默认为 Trans, 如:<Trans id="aaa" defaultMsg="xxx" />
|
|
5
6
|
rewrite: false, // 是否将提取到的内容转换为id后重写入源文件
|
|
6
7
|
extractFromText: true, // 是否允许从纯文本节点中提取翻译内容
|
|
7
8
|
autoImportI18n: true, // 是否自动导入 i18n 模块
|
package/lib/utils.js
CHANGED
|
@@ -157,10 +157,18 @@ function sleep(ms) {
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
function shouldExtract(str, langKey) {
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
const regex = REGEX_MAP[langKey] || REGEX_MAP[translateLangKeyEnum.ZH];
|
|
161
|
+
if (regex instanceof RegExp) {
|
|
162
|
+
return regex.test(str);
|
|
162
163
|
}
|
|
163
|
-
|
|
164
|
+
if (typeof regex === "function") {
|
|
165
|
+
return regex(str);
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function registerLangMatch(langKey, regex) {
|
|
171
|
+
REGEX_MAP[langKey] = regex;
|
|
164
172
|
}
|
|
165
173
|
|
|
166
174
|
function trimEmptyLine(str) {
|
|
@@ -178,13 +186,15 @@ const translateLangKeyEnum = {
|
|
|
178
186
|
KO: "ko",
|
|
179
187
|
RU: "ru"
|
|
180
188
|
};
|
|
189
|
+
|
|
181
190
|
const REGEX_MAP = {
|
|
182
|
-
[translateLangKeyEnum.ZH]: /[\u4e00-\u9fff]/,
|
|
191
|
+
[translateLangKeyEnum.ZH]: /[\u4e00-\u9fff]/, // 简中/繁中
|
|
183
192
|
[translateLangKeyEnum.EN]: /[a-zA-Z]/,
|
|
184
193
|
[translateLangKeyEnum.JA]: /[\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]/, // 日语假名和汉字
|
|
185
194
|
[translateLangKeyEnum.KO]: /[\uAC00-\uD7A3]/, // 韩语字母
|
|
186
195
|
[translateLangKeyEnum.RU]: /[йцукенгшщзхъфывапролджэячсмитьбюё .-]{1,}/ // 俄语字母
|
|
187
196
|
};
|
|
197
|
+
|
|
188
198
|
const excludeDirectives = [
|
|
189
199
|
"model",
|
|
190
200
|
"slot",
|
|
@@ -195,6 +205,7 @@ const excludeDirectives = [
|
|
|
195
205
|
"once",
|
|
196
206
|
"memo"
|
|
197
207
|
];
|
|
208
|
+
|
|
198
209
|
const EXCLUDED_CALL = [
|
|
199
210
|
"$deepScan",
|
|
200
211
|
"console.log",
|
|
@@ -227,6 +238,7 @@ module.exports = {
|
|
|
227
238
|
fixFolderPath,
|
|
228
239
|
sleep,
|
|
229
240
|
shouldExtract,
|
|
241
|
+
registerLangMatch,
|
|
230
242
|
trimEmptyLine,
|
|
231
243
|
padEmptyLine,
|
|
232
244
|
excludeDirectives,
|
package/lib/visitors.js
CHANGED
|
@@ -28,6 +28,22 @@ function isVNodeCall(path, nodeName) {
|
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
function isJSXElement(path, nodeName) {
|
|
32
|
+
const jsxElement = path.findParent(p => p.isJSXOpeningElement());
|
|
33
|
+
|
|
34
|
+
if (
|
|
35
|
+
jsxElement &&
|
|
36
|
+
t.isJSXIdentifier(jsxElement.node.name, { name: nodeName })
|
|
37
|
+
) {
|
|
38
|
+
const jsxAttr = path.findParent(p => p.isJSXAttribute());
|
|
39
|
+
const attrName = jsxAttr.node.name.name;
|
|
40
|
+
if (attrName === "defaultMsg" || attrName === "values") {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
31
47
|
function getPropKey(propNode) {
|
|
32
48
|
if (t.isIdentifier(propNode.key)) {
|
|
33
49
|
return propNode.key.name;
|
|
@@ -158,6 +174,11 @@ function createI18nVisitor(option, i18nMap) {
|
|
|
158
174
|
return;
|
|
159
175
|
}
|
|
160
176
|
|
|
177
|
+
// 跳过<Trans defaultMsg="你好,{name}" values={{name: '世界'} /> defaultMsg和values属性的转换
|
|
178
|
+
if (isJSXElement(path, option.JSXElement)) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
161
182
|
// 获取真实调用函数
|
|
162
183
|
const extractFnName = extractFunctionName(path);
|
|
163
184
|
|
|
@@ -330,6 +351,77 @@ function createI18nVisitor(option, i18nMap) {
|
|
|
330
351
|
)
|
|
331
352
|
);
|
|
332
353
|
}
|
|
354
|
+
},
|
|
355
|
+
JSXElement(path) {
|
|
356
|
+
// <Trans id="aaa" defaultMsg="xxx" />
|
|
357
|
+
const openingElement = path.node.openingElement;
|
|
358
|
+
if (
|
|
359
|
+
!t.isJSXIdentifier(openingElement.name) ||
|
|
360
|
+
openingElement.name.name !== option.JSXElement
|
|
361
|
+
) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
let idAttr = null;
|
|
366
|
+
let idValue = null;
|
|
367
|
+
let defaultMsgValue = null;
|
|
368
|
+
|
|
369
|
+
// 遍历属性,查找 id 和 defaultMsg
|
|
370
|
+
openingElement.attributes.forEach(attr => {
|
|
371
|
+
if (!t.isJSXAttribute(attr) || !t.isJSXIdentifier(attr.name)) return;
|
|
372
|
+
|
|
373
|
+
if (attr.name.name === "id") {
|
|
374
|
+
idAttr = attr;
|
|
375
|
+
if (attr.value && t.isStringLiteral(attr.value)) {
|
|
376
|
+
idValue = attr.value.value;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (attr.name.name === "defaultMsg") {
|
|
381
|
+
if (attr.value && t.isStringLiteral(attr.value)) {
|
|
382
|
+
defaultMsgValue = attr.value.value;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// 计算 id,如果未提供,则使用 defaultMsg 的哈希值
|
|
388
|
+
if (!idValue && defaultMsgValue) {
|
|
389
|
+
idValue = generateId(defaultMsgValue);
|
|
390
|
+
|
|
391
|
+
if (i18nMap) {
|
|
392
|
+
i18nMap[idValue] = defaultMsgValue;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// 有id并且有defaultMsg的情况
|
|
397
|
+
if (idValue && defaultMsgValue) {
|
|
398
|
+
if (i18nMap) {
|
|
399
|
+
i18nMap[idValue] = defaultMsgValue;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (idValue) {
|
|
404
|
+
// 添加或更新 id 属性
|
|
405
|
+
if (idAttr) {
|
|
406
|
+
idAttr.value = t.stringLiteral(idValue);
|
|
407
|
+
} else {
|
|
408
|
+
openingElement.attributes.push(
|
|
409
|
+
t.jsxAttribute(t.jsxIdentifier("id"), t.stringLiteral(idValue))
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (!option.keepRaw) {
|
|
415
|
+
// 移除 defaultMsg
|
|
416
|
+
openingElement.attributes = openingElement.attributes.filter(
|
|
417
|
+
attr =>
|
|
418
|
+
!(
|
|
419
|
+
t.isJSXAttribute(attr) &&
|
|
420
|
+
t.isJSXIdentifier(attr.name) &&
|
|
421
|
+
attr.name.name === "defaultMsg"
|
|
422
|
+
)
|
|
423
|
+
);
|
|
424
|
+
}
|
|
333
425
|
}
|
|
334
426
|
};
|
|
335
427
|
}
|
|
@@ -337,7 +429,7 @@ function createI18nVisitor(option, i18nMap) {
|
|
|
337
429
|
function createI18nPlugin(option, i18nMap) {
|
|
338
430
|
return () => {
|
|
339
431
|
return {
|
|
340
|
-
visitor: createI18nVisitor(option, i18nMap)
|
|
432
|
+
visitor: createI18nVisitor({ ...option, keepRaw: false }, i18nMap)
|
|
341
433
|
};
|
|
342
434
|
};
|
|
343
435
|
}
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
package/types/utils.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export function resolveFilterPath(pathStr: string): string;
|
|
|
15
15
|
export function fixFolderPath(pathStr: string | RegExp): string;
|
|
16
16
|
export function sleep(ms: number): Promise<void>;
|
|
17
17
|
export function shouldExtract(str: string, langKey: LangKey): boolean;
|
|
18
|
+
export function registerLangMatch(langKey: LangKey, regex: RegExp | ((str: string) => boolean)): void;
|
|
18
19
|
export function trimEmptyLine(str: string): string;
|
|
19
20
|
export function padEmptyLine(str: string): string;
|
|
20
21
|
export const excludeDirectives: string[];
|