vite-gc-i18n-plugin 1.1.3 → 1.1.4
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.cjs +159 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +159 -27
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1676,7 +1676,6 @@ async function autoTranslate() {
|
|
|
1676
1676
|
|
|
1677
1677
|
// 无新内容提前退出
|
|
1678
1678
|
if (Object.keys(transLangObj).length === 0) {
|
|
1679
|
-
console.info('✅ 当前没有需要翻译的新内容');
|
|
1680
1679
|
return;
|
|
1681
1680
|
}
|
|
1682
1681
|
|
|
@@ -1822,8 +1821,10 @@ async function translateChunks(transLangObj, translateKey) {
|
|
|
1822
1821
|
const {
|
|
1823
1822
|
translator
|
|
1824
1823
|
} = exports.option;
|
|
1824
|
+
const placeholders = [];
|
|
1825
|
+
const protectedValues = Object.values(transLangObj).map(value => protectInterpolationPlaceholders(value, placeholders));
|
|
1825
1826
|
// 获取分块后的文本列表
|
|
1826
|
-
const translationChunks = createTextSplitter(
|
|
1827
|
+
const translationChunks = createTextSplitter(protectedValues, translator.option.maxChunkSize);
|
|
1827
1828
|
// 并行执行分块翻译
|
|
1828
1829
|
const translatePromises = [];
|
|
1829
1830
|
for (let i = 0; i < translationChunks.length; i++) {
|
|
@@ -1833,6 +1834,7 @@ async function translateChunks(transLangObj, translateKey) {
|
|
|
1833
1834
|
// 等待所有分块完成并合并结果
|
|
1834
1835
|
const chunkResults = await Promise.all(translatePromises);
|
|
1835
1836
|
return chunkResults.map(item => {
|
|
1837
|
+
item = restoreInterpolationPlaceholders(item, placeholders);
|
|
1836
1838
|
// 提取分割逻辑到单独的函数中,提高代码复用性
|
|
1837
1839
|
const splitTranslation = (text, separatorRegex) => {
|
|
1838
1840
|
return text.split(separatorRegex).map(v => v.trim());
|
|
@@ -1856,6 +1858,17 @@ async function translateChunks(transLangObj, translateKey) {
|
|
|
1856
1858
|
}
|
|
1857
1859
|
}).flat();
|
|
1858
1860
|
}
|
|
1861
|
+
function protectInterpolationPlaceholders(value, placeholders) {
|
|
1862
|
+
return value.replace(/\$\{[^}]*\}/g, match => {
|
|
1863
|
+
const index = placeholders.push(match) - 1;
|
|
1864
|
+
return `__GC_I18N_PH_${index}__`;
|
|
1865
|
+
});
|
|
1866
|
+
}
|
|
1867
|
+
function restoreInterpolationPlaceholders(value, placeholders) {
|
|
1868
|
+
return value.replace(/__GC_I18N_PH_(\d+)__/g, (match, index) => {
|
|
1869
|
+
return placeholders[Number(index)] || match;
|
|
1870
|
+
});
|
|
1871
|
+
}
|
|
1859
1872
|
/**
|
|
1860
1873
|
* @description: 清理多余的翻译配置JSON文件
|
|
1861
1874
|
* @return {void} 无返回值
|
|
@@ -2015,8 +2028,6 @@ function createTextSplitter(values, maxChunkSize) {
|
|
|
2015
2028
|
* @returns 处理后的字符串数组
|
|
2016
2029
|
*/
|
|
2017
2030
|
function splitByRegex(str, separatorRegex) {
|
|
2018
|
-
if (str.includes('\n')) console.log(str, separatorRegex);
|
|
2019
|
-
|
|
2020
2031
|
// 定义标点符号的正则表达式
|
|
2021
2032
|
const punctuationRegex = /[,。?!《》,..:!?""'';'"、0-9\n\r\t\v\f]/;
|
|
2022
2033
|
// 创建一个新的正则表达式,用于分割字符串
|
|
@@ -2295,8 +2306,17 @@ function TemplateLiteral (insertOption) {
|
|
|
2295
2306
|
};
|
|
2296
2307
|
}
|
|
2297
2308
|
function handleTemplateLiteralWithExpressions(node, path) {
|
|
2298
|
-
|
|
2299
|
-
|
|
2309
|
+
let hasOptimizedExpression = false;
|
|
2310
|
+
const expressionLabels = node.expressions.map((expression, index) => {
|
|
2311
|
+
const optimizedExpression = optimizeConditionalExpression(expression);
|
|
2312
|
+
if (optimizedExpression) {
|
|
2313
|
+
hasOptimizedExpression = true;
|
|
2314
|
+
node.expressions[index] = optimizedExpression.expression;
|
|
2315
|
+
return optimizedExpression.label;
|
|
2316
|
+
}
|
|
2317
|
+
return getExpressionPlaceholder(expression);
|
|
2318
|
+
});
|
|
2319
|
+
if (expressionLabels.some(placeholder => placeholder === null)) {
|
|
2300
2320
|
return false;
|
|
2301
2321
|
}
|
|
2302
2322
|
const fullValue = node.quasis.reduce((result, quasi, index) => {
|
|
@@ -2308,9 +2328,13 @@ function handleTemplateLiteralWithExpressions(node, path) {
|
|
|
2308
2328
|
console.log('转换异常');
|
|
2309
2329
|
}
|
|
2310
2330
|
}
|
|
2311
|
-
return result + value + (index < node.expressions.length ?
|
|
2331
|
+
return result + value + (index < node.expressions.length ? formatExpressionPlaceholder(expressionLabels[index]) : '');
|
|
2312
2332
|
}, '');
|
|
2313
2333
|
if (!fullValue || !hasOriginSymbols(fullValue) || !exports.option.excludedPattern.length || checkAgainstRegexArray(fullValue, [...exports.option.excludedPattern])) {
|
|
2334
|
+
if (hasOptimizedExpression) {
|
|
2335
|
+
path.skip();
|
|
2336
|
+
return true;
|
|
2337
|
+
}
|
|
2314
2338
|
return false;
|
|
2315
2339
|
}
|
|
2316
2340
|
const {
|
|
@@ -2318,22 +2342,12 @@ function handleTemplateLiteralWithExpressions(node, path) {
|
|
|
2318
2342
|
valStr
|
|
2319
2343
|
} = normalizeTranslateValue(fullValue);
|
|
2320
2344
|
const id = generateId(valStr);
|
|
2321
|
-
const translateNode = createTranslateNode(path, id, valStr,
|
|
2345
|
+
const translateNode = createTranslateNode(path, id, valStr, expressionLabels, node.expressions);
|
|
2322
2346
|
path.replaceWith(translateNode);
|
|
2323
|
-
path.skip();
|
|
2324
2347
|
setLangObj(id, trimmedValue);
|
|
2325
2348
|
return true;
|
|
2326
2349
|
}
|
|
2327
2350
|
function getExpressionPlaceholder(expression) {
|
|
2328
|
-
if (types.isIdentifier(expression)) {
|
|
2329
|
-
return expression.name;
|
|
2330
|
-
}
|
|
2331
|
-
if (types.isMemberExpression(expression)) {
|
|
2332
|
-
const objectName = getExpressionPlaceholder(expression.object);
|
|
2333
|
-
const propertyName = expression.computed ? getExpressionPlaceholder(expression.property) : types.isIdentifier(expression.property) ? expression.property.name : '';
|
|
2334
|
-
const value = [objectName, propertyName].filter(Boolean).join('.');
|
|
2335
|
-
return cleanVueRuntimePrefix(value);
|
|
2336
|
-
}
|
|
2337
2351
|
if (types.isStringLiteral(expression) || types.isNumericLiteral(expression)) {
|
|
2338
2352
|
return String(expression.value);
|
|
2339
2353
|
}
|
|
@@ -2344,21 +2358,142 @@ function getExpressionPlaceholder(expression) {
|
|
|
2344
2358
|
return getExpressionPlaceholder(expression.expression);
|
|
2345
2359
|
}
|
|
2346
2360
|
const generateCode = generate__namespace.default?.default || generate__namespace.default || generate__namespace;
|
|
2347
|
-
return
|
|
2361
|
+
return generateCode(expression, {
|
|
2362
|
+
comments: false
|
|
2363
|
+
}).code;
|
|
2364
|
+
}
|
|
2365
|
+
function optimizeConditionalExpression(expression) {
|
|
2366
|
+
if (!types.isConditionalExpression(expression)) return null;
|
|
2367
|
+
const consequent = translateConditionalStringBranch(expression.consequent);
|
|
2368
|
+
const alternate = translateConditionalStringBranch(expression.alternate);
|
|
2369
|
+
if (!consequent.changed && !alternate.changed) return null;
|
|
2370
|
+
return {
|
|
2371
|
+
label: getConditionalExpressionLabel(expression),
|
|
2372
|
+
expression: types.conditionalExpression(types.cloneNode(expression.test), consequent.expression, alternate.expression)
|
|
2373
|
+
};
|
|
2374
|
+
}
|
|
2375
|
+
function translateConditionalStringBranch(expression) {
|
|
2376
|
+
if (types.isStringLiteral(expression) && hasOriginSymbols(expression.value)) {
|
|
2377
|
+
return {
|
|
2378
|
+
changed: true,
|
|
2379
|
+
expression: createTrackedTranslateCall(expression.value)
|
|
2380
|
+
};
|
|
2381
|
+
}
|
|
2382
|
+
if (types.isTemplateLiteral(expression)) {
|
|
2383
|
+
const translateCall = createTemplateLiteralTranslateCall(expression);
|
|
2384
|
+
if (translateCall) {
|
|
2385
|
+
return {
|
|
2386
|
+
changed: true,
|
|
2387
|
+
expression: translateCall
|
|
2388
|
+
};
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
if (types.isConditionalExpression(expression)) {
|
|
2392
|
+
const optimizedExpression = optimizeConditionalExpression(expression);
|
|
2393
|
+
if (optimizedExpression) {
|
|
2394
|
+
return {
|
|
2395
|
+
changed: true,
|
|
2396
|
+
expression: optimizedExpression.expression
|
|
2397
|
+
};
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
return {
|
|
2401
|
+
changed: false,
|
|
2402
|
+
expression: types.cloneNode(expression)
|
|
2403
|
+
};
|
|
2404
|
+
}
|
|
2405
|
+
function createTrackedTranslateCall(value) {
|
|
2406
|
+
const translateCall = createI18nTranslator({
|
|
2407
|
+
value,
|
|
2408
|
+
isExpression: true
|
|
2409
|
+
});
|
|
2410
|
+
const {
|
|
2411
|
+
trimmedValue,
|
|
2412
|
+
valStr
|
|
2413
|
+
} = normalizeTranslateValue(value);
|
|
2414
|
+
const id = generateId(valStr);
|
|
2415
|
+
if (id && trimmedValue) {
|
|
2416
|
+
setLangObj(id, trimmedValue);
|
|
2417
|
+
}
|
|
2418
|
+
return translateCall;
|
|
2419
|
+
}
|
|
2420
|
+
function createTemplateLiteralTranslateCall(node) {
|
|
2421
|
+
const expressions = node.expressions.map(expression => {
|
|
2422
|
+
const optimizedExpression = optimizeConditionalExpression(expression);
|
|
2423
|
+
return optimizedExpression ? optimizedExpression.expression : expression;
|
|
2424
|
+
});
|
|
2425
|
+
const expressionLabels = expressions.map(expression => getExpressionPlaceholder(expression));
|
|
2426
|
+
if (expressionLabels.some(placeholder => placeholder === null)) {
|
|
2427
|
+
return null;
|
|
2428
|
+
}
|
|
2429
|
+
const fullValue = node.quasis.reduce((result, quasi, index) => {
|
|
2430
|
+
let value = quasi.value.raw || quasi.value.cooked || '';
|
|
2431
|
+
if (asianLangs.some(lang => exports.option.originLang.includes(lang) || exports.option.originLang === lang)) {
|
|
2432
|
+
try {
|
|
2433
|
+
value = unicodeToString(value);
|
|
2434
|
+
} catch (error) {
|
|
2435
|
+
console.log('转换异常');
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
return result + value + (index < expressions.length ? formatExpressionPlaceholder(expressionLabels[index]) : '');
|
|
2439
|
+
}, '');
|
|
2440
|
+
if (!fullValue || !hasOriginSymbols(fullValue) || !exports.option.excludedPattern.length || checkAgainstRegexArray(fullValue, [...exports.option.excludedPattern])) {
|
|
2441
|
+
return null;
|
|
2442
|
+
}
|
|
2443
|
+
const {
|
|
2444
|
+
trimmedValue,
|
|
2445
|
+
valStr
|
|
2446
|
+
} = normalizeTranslateValue(fullValue);
|
|
2447
|
+
const id = generateId(valStr);
|
|
2448
|
+
if (id && trimmedValue) {
|
|
2449
|
+
setLangObj(id, trimmedValue);
|
|
2450
|
+
}
|
|
2451
|
+
return createTranslateCall(id, valStr, expressionLabels, expressions);
|
|
2452
|
+
}
|
|
2453
|
+
function getConditionalExpressionLabel(expression) {
|
|
2454
|
+
const test = expression.test;
|
|
2455
|
+
if (types.isBinaryExpression(test) || types.isLogicalExpression(test)) {
|
|
2456
|
+
return getExpressionPlaceholder(test.left);
|
|
2457
|
+
}
|
|
2458
|
+
return getExpressionPlaceholder(test);
|
|
2459
|
+
}
|
|
2460
|
+
function formatExpressionPlaceholder(placeholder) {
|
|
2461
|
+
if (placeholder === null) return '';
|
|
2462
|
+
return placeholder.trim() ? `\${${placeholder}}` : placeholder;
|
|
2348
2463
|
}
|
|
2349
2464
|
function createTranslateNode(path, id, valStr) {
|
|
2350
2465
|
let placeholders = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
|
|
2351
2466
|
let expressions = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [];
|
|
2352
|
-
const
|
|
2353
|
-
if (placeholders.length) {
|
|
2354
|
-
args.push(types.objectExpression(placeholders.map((placeholder, index) => types.objectProperty(types.stringLiteral(placeholder), types.cloneNode(expressions[index])))));
|
|
2355
|
-
}
|
|
2356
|
-
const translateCall = types.callExpression(types.identifier(exports.option.translateKey), args);
|
|
2467
|
+
const translateCall = createTranslateCall(id, valStr, placeholders, expressions);
|
|
2357
2468
|
if (!isVueTemplateRender(path)) {
|
|
2358
2469
|
return translateCall;
|
|
2359
2470
|
}
|
|
2360
2471
|
return types.sequenceExpression([createVueTemplateLanguageDependency(), translateCall]);
|
|
2361
2472
|
}
|
|
2473
|
+
function createTranslateCall(id, valStr) {
|
|
2474
|
+
let placeholders = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
|
|
2475
|
+
let expressions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
|
|
2476
|
+
const args = [types.stringLiteral(id), types.stringLiteral(valStr)];
|
|
2477
|
+
if (placeholders.length) {
|
|
2478
|
+
const placeholderEntries = placeholders.map((placeholder, index) => ({
|
|
2479
|
+
placeholder,
|
|
2480
|
+
expression: expressions[index]
|
|
2481
|
+
})).filter(_ref => {
|
|
2482
|
+
let {
|
|
2483
|
+
placeholder
|
|
2484
|
+
} = _ref;
|
|
2485
|
+
return placeholder && placeholder.trim();
|
|
2486
|
+
});
|
|
2487
|
+
args.push(types.objectExpression(placeholderEntries.map(_ref2 => {
|
|
2488
|
+
let {
|
|
2489
|
+
placeholder,
|
|
2490
|
+
expression
|
|
2491
|
+
} = _ref2;
|
|
2492
|
+
return types.objectProperty(types.stringLiteral(placeholder), types.cloneNode(expression));
|
|
2493
|
+
})));
|
|
2494
|
+
}
|
|
2495
|
+
return types.callExpression(types.identifier(exports.option.translateKey), args);
|
|
2496
|
+
}
|
|
2362
2497
|
function isVueTemplateRender(path) {
|
|
2363
2498
|
return Boolean(path.scope?.getBinding('_vm'));
|
|
2364
2499
|
}
|
|
@@ -2372,9 +2507,6 @@ function createVueTemplateLanguageDependency() {
|
|
|
2372
2507
|
const i18nLocale = types.logicalExpression('&&', types.cloneNode(i18n), types.memberExpression(types.cloneNode(i18n), types.identifier('locale')));
|
|
2373
2508
|
return types.logicalExpression('||', storeLanguage, i18nLocale);
|
|
2374
2509
|
}
|
|
2375
|
-
function cleanVueRuntimePrefix(value) {
|
|
2376
|
-
return value.replace(/^(?:\$setup|_ctx|_vm|this)\./, '').replace(/([^\w$.])(?:\$setup|_ctx|_vm|this)\./g, '$1');
|
|
2377
|
-
}
|
|
2378
2510
|
|
|
2379
2511
|
// 处理模板元素
|
|
2380
2512
|
function handleTemplateElement(node, insertOption) {
|