@chaoswise/intl 1.0.0 → 1.2.0

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.
Files changed (41) hide show
  1. package/bin/chaoswise-intl.js +5 -1
  2. package/bin/scripts/collect.js +38 -18
  3. package/bin/scripts/conf/default.js +40 -2
  4. package/bin/scripts/conf/getCustomConfig.js +8 -0
  5. package/bin/scripts/conf/index.js +2 -25
  6. package/bin/scripts/conf/initConfig.js +37 -0
  7. package/bin/scripts/initConfig.js +3 -0
  8. package/bin/scripts/service/index.js +2 -2
  9. package/bin/scripts/update.js +5 -5
  10. package/bin/scripts/util/FormPath/contexts.d.ts +10 -0
  11. package/bin/scripts/util/FormPath/contexts.js +23 -0
  12. package/bin/scripts/util/FormPath/destructor.d.ts +15 -0
  13. package/bin/scripts/util/FormPath/destructor.js +124 -0
  14. package/bin/scripts/util/FormPath/index.d.ts +49 -0
  15. package/bin/scripts/util/FormPath/index.js +536 -0
  16. package/bin/scripts/util/FormPath/lru.d.ts +1 -0
  17. package/bin/scripts/util/FormPath/lru.js +246 -0
  18. package/bin/scripts/util/FormPath/matcher.d.ts +33 -0
  19. package/bin/scripts/util/FormPath/matcher.js +216 -0
  20. package/bin/scripts/util/FormPath/parser.d.ts +28 -0
  21. package/bin/scripts/util/FormPath/parser.js +302 -0
  22. package/bin/scripts/util/FormPath/tokenizer.d.ts +26 -0
  23. package/bin/scripts/util/FormPath/tokenizer.js +280 -0
  24. package/bin/scripts/util/FormPath/tokens.d.ts +26 -0
  25. package/bin/scripts/util/FormPath/tokens.js +212 -0
  26. package/bin/scripts/util/FormPath/types.d.ts +76 -0
  27. package/bin/scripts/util/FormPath/types.js +17 -0
  28. package/bin/scripts/util/FormPath/utils.d.ts +10 -0
  29. package/bin/scripts/util/FormPath/utils.js +63 -0
  30. package/bin/scripts/util/downloadJson.js +10 -1
  31. package/bin/scripts/util/file.js +31 -0
  32. package/bin/scripts/util/getGroupName.js +15 -0
  33. package/bin/scripts/util/getWord.js +13 -0
  34. package/bin/scripts/util/log.js +25 -4
  35. package/bin/scripts/util/makeVisitorCollect.js +351 -46
  36. package/bin/scripts/util/makeVisitorUpdate.js +38 -1
  37. package/bin/scripts/util/specialMatch.js +14 -0
  38. package/bin/scripts/util/transformAst.js +30 -22
  39. package/bin/scripts/util/writeNewWordsFile.js +30 -0
  40. package/lib/index.js +2 -1
  41. package/package.json +7 -5
@@ -1,30 +1,179 @@
1
1
  const log = require('./log');
2
2
  const t = require('@babel/types');
3
+ const generate = require('@babel/generator').default;
4
+ const { getWord } = require('./getWord');
5
+ const specialMatch = require('./specialMatch');
6
+ const { Path: FormPath } = require('./FormPath');
3
7
 
4
- module.exports = function(
8
+ const commentStr = ' @chaoswise/intl脚本替换失败 ';
9
+
10
+ module.exports = function (
5
11
  {
6
12
  primaryRegx,
7
13
  i18nObject,
8
14
  i18nMethod,
15
+ i18nDefaultFunctionKey,
9
16
  importCode,
10
17
  ignoreLines,
11
18
  ignoreMethods,
12
19
  ignoreComponents = [],
13
20
  ignoreAttributes,
21
+ intlTag,
22
+ intlTagIdPath,
23
+ intlTagDefaultWordPath,
24
+ intlFunctionName,
25
+ intlFunctionIdPath,
26
+ intlFunctionDefaultWordPath,
27
+ removePkgName,
28
+ localWordPath,
29
+ removeFunctionName,
14
30
  },
15
- returns
31
+ returns,
32
+ { filePath, special },
16
33
  ) {
34
+
35
+ // jsx默认 defaultMessage
36
+ intlTagDefaultWordPath = intlTagDefaultWordPath || 'defaultMessage';
37
+
17
38
  const { replaceWords, allWords, downloadIds } = returns;
18
39
  const hacked = {};
19
40
 
41
+ // 在没有replaceWords的情况下,不用log信息,这里统一处理
42
+ const properLog = {};
43
+ Object.keys(log).forEach(fnName => {
44
+ properLog[fnName] = (...args) => {
45
+ if (!Object.keys(replaceWords).length) return;
46
+ log[fnName](...args);
47
+ }
48
+ })
49
+
50
+ // 获取完整路劲。例如:path='key',返回'0.key'
51
+ function getFullPath (path) {
52
+ if (!path) return path;
53
+ if (typeof path !== 'string') return path;
54
+ if (/^[0-9]/.test(path)) {
55
+ return path;
56
+ }
57
+
58
+ let preFixPath = '0';
59
+ if (!/^\./.test(path)) {
60
+ preFixPath = '0.';
61
+ }
62
+ return preFixPath + path;
63
+ }
64
+ // 插入注释
65
+ function insertFailCommon(node) {
66
+ const comment = node?.leadingComments?.value
67
+ if (comment && comment.trim() === commentStr) return;
68
+ t.addComment(node, 'leading', commentStr);
69
+ }
70
+ // 在jsx中插入注释
71
+ function insertFailCommonInJsx(path) {
72
+ const comment = path?.node?.leadingComments?.value
73
+ if (comment && comment.trim() === commentStr) return;
74
+ path.insertBefore(
75
+ t.jsxExpressionContainer(
76
+ {
77
+ "type": "JSXEmptyExpression",
78
+ "innerComments": [
79
+ {
80
+ "type": "CommentBlock",
81
+ "value": commentStr
82
+ }
83
+ ]
84
+ }
85
+ )
86
+ )
87
+ }
88
+
89
+ // 获取国际化jsx标签中的id或者defaultMessage
90
+ function getJsxTagChaoswiseIntlValue(openingElement, intlTagValuePath) {
91
+ // <Tag id={{ x: ['id'] }} defaultMessage={{ x: ['中文'] }} />
92
+ // valueAst是{ x: ['id'] }的ast
93
+ let valueAst;
94
+ // intlTagValuePath 是 id.x.0
95
+ // valueKey 是 id
96
+ // valuePath 是 x.0
97
+ let valueKey = intlTagValuePath;
98
+ let valuePath = '';
99
+
100
+ const index = (intlTagValuePath || '').indexOf('.');
101
+ if (index !== -1) {
102
+ valueKey = intlTagValuePath.slice(0, index);
103
+ valuePath = intlTagValuePath.slice(index + 1);
104
+ }
105
+
106
+ // <Tag {...props} />不能找到对应的值
107
+ valueAst = openingElement.attributes.find((item) => {
108
+ return item?.name?.name === valueKey;
109
+ })?.value;
110
+ // intlTagValuePath配置不正确就会找不到value
111
+ // 比如<Tag id2='id' /> 把intlTagValuePath配置为id就不行,因为这里应该是id2
112
+ if (!valueAst) return false;
113
+
114
+ // 如果是jsx容器,就 去掉jsx容器,拿里面的值
115
+ // 从{{ x: ['id'] }} 变为 { x: ['id'] }
116
+ if (valueAst.type === 'JSXExpressionContainer') {
117
+ valueAst = valueAst.expression;
118
+ }
119
+
120
+ // 把ast转为js, 再用FormPath.getIn来取最终的值
121
+ const { code: valueCode } = generate(valueAst);
122
+ var chaoswiseIntlValue;
123
+ try {
124
+ eval('var chaoswiseIntlValue =' + valueCode);
125
+ chaoswiseIntlValue = FormPath.getIn(chaoswiseIntlValue, valuePath);
126
+ } catch (e) {
127
+ // var a = 'id'; <Tag id={a} 这样会出错
128
+ }
129
+
130
+ if (typeof chaoswiseIntlValue !== 'string') {
131
+ return false;
132
+ }
133
+
134
+ return chaoswiseIntlValue;
135
+ }
136
+
137
+ // 获取函数名称 fn/object.fn/object.a.b.c/intl.get().d
138
+ function getFnName(node) {
139
+ let fnName = '';
140
+ while (['CallExpression', 'MemberExpression', 'Identifier'].includes(node?.type)) {
141
+ if (node.type === 'CallExpression') {
142
+ let name = getFnName(node.callee);
143
+ fnName = `${name}().` + fnName;
144
+ break;
145
+ } else if (node.type === 'MemberExpression') {
146
+ fnName = `${node.property.name}.` + fnName;
147
+ if (node.object.name) {
148
+ fnName = `${node.object.name}.` + fnName;
149
+ }
150
+ node = node.object;
151
+ } else if (node.type === 'Identifier') {
152
+ // 这里获取修饰器的函数名称
153
+ fnName = fnName || (node.name + '.')
154
+ break;
155
+ }
156
+ }
157
+
158
+ // 把最后的 点. 取消
159
+ fnName = fnName.slice(0, -1);
160
+ return fnName;
161
+ }
162
+
20
163
  // XXX: [TRICKY] 防止中文转码为 unicode
21
164
  function hackValue(value, id) {
22
165
  if (id) hacked[id] = true;
23
166
 
167
+ // 字符串默认是单引号,如果模板字符串中出现单引号,需要转义,把 ' 换成 \'
168
+ // 就算用户自定配置字符串为双引号,也没事,默认会转义双引号,但是默认不会处理单引号,所以自己手动处理
169
+ if (/\'/.test(id)) {
170
+ id = id.replace(/\'/g, '\\\'');
171
+ }
172
+
24
173
  return Object.assign(t.StringLiteral(value), {
25
174
  extra: {
26
175
  raw: `'${id}'`, // id
27
- rawValue: value, // zh
176
+ rawValue: value, // word
28
177
  },
29
178
  });
30
179
  }
@@ -37,8 +186,12 @@ module.exports = function(
37
186
  return false;
38
187
  }
39
188
 
40
- // 是否命中替换的正则
189
+ // 是否命中替换条件
41
190
  function isPrimary(str) {
191
+ if (special) {
192
+ // 如果匹配到了替换过的,就返回false。为了防止多次执行collect,多次嵌套替换
193
+ if (specialMatch(str)) return false;
194
+ }
42
195
  return primaryRegx.test(str);
43
196
  }
44
197
 
@@ -58,28 +211,37 @@ module.exports = function(
58
211
  function makeObjectExpression(obj) {
59
212
  if (Object.prototype.toString.call(obj) !== '[object Object]') return null;
60
213
 
61
- // 存储每一项变量
62
- const ObjectPropertyArr = [];
63
- Object.keys(obj).forEach((k) => {
64
- const node = obj[k].value;
65
- // 模板字符串中,变量存在函数调用的情况下:如果当前变量为函数,那么需要处理函数的中文参数,比如:`hello ${getText('中文')}`
66
- if (!shouldIgnore(node) && node?.type === 'CallExpression') {
67
- node.arguments = dealArgs(node.arguments);
68
- }
69
- ObjectPropertyArr.push(
70
- t.ObjectProperty(
214
+ // 模板字符串中,转换后,如果第二项参数还有中文,或者更深层级有中文,这里处理好
215
+ // 模板字符串转换前`${f(`aa${f('中文')}中文`)}中文`
216
+ /* 转换后
217
+ intl
218
+ .get('id1', {
219
+ slot0: f(
220
+ intl
221
+ .get('id2', { slot0: f(intl.get('id3').d('中文')) })
222
+ .d('aa{slot0}中文')
223
+ ),
224
+ })
225
+ .d('{slot0}中文');
226
+ */
227
+ const keys = Object.keys(obj);
228
+ const datas = dealArgs(Object.values(obj).map(item => item.value || item));
229
+
230
+ return t.ObjectExpression(
231
+ keys.map((k, i) => {
232
+ const node = datas[i];
233
+ return t.ObjectProperty(
71
234
  t.Identifier(k),
72
- obj[k].isAstNode ? obj[k].value : t.Identifier(obj[k])
235
+ obj[k].isAstNode ? node : t.Identifier(obj[k])
73
236
  )
74
- );
75
- });
76
- return t.ObjectExpression(ObjectPropertyArr);
237
+ })
238
+ );
77
239
  }
78
240
 
79
241
  // 更新allWords
80
- function updateWordsInfo(zh) {
81
- if (allWords.includes(zh)) return;
82
- allWords.push(zh);
242
+ function updateWordsInfo(word) {
243
+ if (allWords.includes(word)) return;
244
+ allWords.push(word);
83
245
  }
84
246
 
85
247
  // 处理函数的argments
@@ -87,7 +249,7 @@ module.exports = function(
87
249
  if (!Array.isArray(args)) return args;
88
250
  const resArgs = []; // 参数处理完,用resArgs保存
89
251
  args.forEach(node => {
90
- // 字符串变量
252
+ // 字符串变量
91
253
  if (node.type === 'StringLiteral' && isPrimary(node.value)) {
92
254
  resArgs.push(makeReplace(node.value));
93
255
  }
@@ -141,6 +303,11 @@ module.exports = function(
141
303
  // 将中文词条替换为国际化api:init.t(id/key)
142
304
  const id = replaceWords[value];
143
305
 
306
+ // 特殊文件处理
307
+ if (special) {
308
+ const str = `${i18nObject ? `${i18nObject}.` : ''}${i18nMethod}("${id}").${i18nDefaultFunctionKey}("${value}")`;
309
+ return hackValue(str, str,);
310
+ }
144
311
  // 生成新的ast节点
145
312
  const v = hackValue(value, id);
146
313
  const objExp = makeObjectExpression(variables);
@@ -157,7 +324,7 @@ module.exports = function(
157
324
  : t.identifier(i18nMethod),
158
325
  objExp ? [v, objExp] : [v]
159
326
  )
160
- , t.identifier('d')
327
+ , t.identifier(i18nDefaultFunctionKey)
161
328
  ),
162
329
  [defaultV]
163
330
  );
@@ -230,67 +397,119 @@ module.exports = function(
230
397
  }
231
398
  return { needReplace, value };
232
399
  }
400
+
233
401
  // 函数表达式
234
402
  function dealCallExpressionNode(node) {
235
403
  const res = {
236
404
  needReplace: false,
237
405
  value: null,
238
406
  skip: false,
407
+ remove: false,
239
408
  }
240
409
  if (shouldIgnore(node)) {
241
410
  res.skip = true;
242
411
  return res;
243
412
  }
244
413
 
414
+ const fnName = getFnName(node.callee);
415
+
245
416
  // 处理 ignoreMethods
246
- if (node.callee.type === 'MemberExpression') {
247
- let parentNode = '';
248
- if (node.callee.object.name) {
249
- parentNode = node.callee.object.name;
250
- } else if (node.callee.object.property) {
251
- // 处理忽略类似 a.b.c 方法情况
252
- parentNode = node.callee.object.property.name;
253
- }
417
+ if ([
418
+ ...(ignoreMethods || []),
419
+ `${i18nObject}.${i18nMethod}`, // intl.get
420
+ `${i18nObject}.${i18nMethod}().${i18nDefaultFunctionKey}`, // intl.get().d
421
+ ].includes(fnName)) {
422
+ res.skip = true;
423
+ return res;
424
+ }
254
425
 
255
- const callExpression = `${parentNode}.${node.callee.property.name}`;
426
+ // 需要删除的函数
427
+ if (removeFunctionName.includes(fnName)) {
428
+ // 文件需要修改
429
+ returns.hasTouch = true;
430
+ res.remove = true;
431
+ return res;
432
+ }
433
+
434
+ // 已经做过国际化的项目,替换国际化函数
435
+ if (fnName === intlFunctionName) {
436
+ res.skip = true;
256
437
 
257
- if (ignoreMethods.includes(callExpression)) {
258
- res.skip = true;
259
- return res;
438
+ const argsAst = node.arguments;
439
+ // 把ast转为js, 再用FormPath.getIn来取最终的值
440
+ const { code: argsCode } = generate(t.arrayExpression(argsAst));
441
+ let chaoswiseIntlId
442
+ var chaoswiseIntlIdData
443
+ try {
444
+ eval('var chaoswiseIntlIdData =' + argsCode);
445
+ chaoswiseIntlId = FormPath.getIn(chaoswiseIntlIdData, getFullPath(intlFunctionIdPath));
446
+ } catch (e) {
447
+ // var a = 'id'; f(a) 这样会出错
448
+ // TODO
260
449
  }
261
- }
262
450
 
263
- if (node.callee.type === 'Identifier') {
264
- if (ignoreMethods.includes(node.callee.name)) {
265
- res.skip = true;
266
- return res;
451
+ let value = getWord(chaoswiseIntlId);
452
+ if (!value) {
453
+ let defautValue = FormPath.getIn(chaoswiseIntlIdData, getFullPath(intlFunctionDefaultWordPath));
454
+ if (typeof defautValue === 'string') {
455
+ value = defautValue;
456
+ } else {
457
+ if (intlFunctionIdPath && !chaoswiseIntlId) {
458
+ properLog.warn(`文件:${filePath} 替换的函数名intlFunctionName:${intlFunctionName} id路径intlFunctionIdPath:${intlFunctionIdPath} 未找到非空字符串`)
459
+ }
460
+ if (localWordPath && chaoswiseIntlId && !value) {
461
+ properLog.warn(`中文文件localWordPath:${localWordPath} 键:${chaoswiseIntlId} 未找到非空字符串`)
462
+ }
463
+ if (intlFunctionDefaultWordPath) {
464
+ properLog.warn(`文件:${filePath} 替换的函数名intlFunctionName:${intlFunctionName} 默认中文路径intlFunctionDefaultWordPath:${intlFunctionDefaultWordPath} 未找到非空字符串`)
465
+ }
466
+ insertFailCommon(node);
467
+ }
468
+ }
469
+
470
+ if (value && isPrimary(value)) {
471
+ res.needReplace = true;
472
+ res.value = value;
267
473
  }
268
474
  }
269
475
 
270
476
  return res;
271
477
  }
272
478
 
479
+ // TODO
480
+ /*
481
+ this.props.intl = lang === 'zh'? '中文': 'en'
482
+ intl.get(id).d('中文')
483
+ this.props.intl.lang = 'zh' ==> intl.lang = 'zh'
484
+ replaceName: { ['this.props.intl.lang']: () => 'intl.lang' }
485
+ 或者replaceName: { ['this.props.intl.lang']: 'intl.lang' }
486
+ */
273
487
  return {
274
488
  // 导入声明,比如:import foo from "mod";
275
489
  ImportDeclaration(path) {
276
490
  // 是否已经导入过 intl 的依赖
277
491
  const m = importCode.match(/from ["'](.*)["']/);
278
492
  const pkgName = m ? m[1] : '';
279
- if (path.node.source.value === pkgName) {
493
+ const name = path.node.source.value;
494
+ if (name === pkgName) {
280
495
  returns.hasImport = true;
281
496
  }
497
+ if (removePkgName.includes(name)) {
498
+ path.remove();
499
+ returns.hasTouch = true;
500
+ }
282
501
  path.skip();
283
502
  },
284
503
 
285
- // 字符串模版,比如:`我的${bar}${fun('哈哈')}中文` intl.t(我的{bar}{slot1}中文,{bar:fdsafdsdf,slot1:fn()})
504
+ // 字符串模版,比如:`我的${bar}${fun('哈哈')}中文` intl.get(我的{bar}{slot1}中文,{bar:fdsafdsdf,slot1:fn()})
286
505
  TemplateLiteral(path) {
287
506
  const { node } = path;
288
507
 
289
508
  const { needReplace, value, variable, } = dealTemplateLiteralNode(node);
290
509
  if (needReplace) {
291
510
  path.replaceWith(makeReplace(value, Object.keys(variable).length ? variable : null));
511
+ path.skip();
292
512
  }
293
- path.skip();
294
513
  },
295
514
 
296
515
  // 字符串变量
@@ -306,8 +525,17 @@ module.exports = function(
306
525
  }
307
526
  path.replaceWith(res);
308
527
  path.skip();
309
- } else if (isPrimary(value)) {
310
- log.warn('ignore 1!!!!!!', value);
528
+ }
529
+ },
530
+
531
+ // 修饰器
532
+ Decorator(path) {
533
+ const { node } = path;
534
+ const fnName = getFnName(node.expression);
535
+ if (removeFunctionName.includes(fnName)) {
536
+ returns.hasTouch = true;
537
+ path.remove();
538
+ path.skip();
311
539
  }
312
540
  },
313
541
 
@@ -315,13 +543,90 @@ module.exports = function(
315
543
  CallExpression(path) {
316
544
  const { node } = path;
317
545
 
318
- const { needReplace, value, skip } = dealCallExpressionNode(node);
546
+ const { needReplace, value, skip, remove } = dealCallExpressionNode(node);
547
+
548
+ if (remove) {
549
+ if (node.arguments.length === 1) {
550
+ // 去掉外侧的包裹组件
551
+ path.replaceWith(node.arguments[0]);
552
+ } else {
553
+ // f( 1, 2)
554
+ // 1, 2
555
+ // 移除函数有问题,这里不处理
556
+ }
557
+
558
+ return;
559
+ }
560
+
319
561
  if (needReplace) {
320
562
  path.replaceWith(makeReplace(value));
321
563
  }
322
564
  if (skip) path.skip();
323
565
  },
324
566
 
567
+ // jsx标签
568
+ JSXElement(path) {
569
+ const { node } = path;
570
+ const { openingElement } = node;
571
+ const jsxName = openingElement.name.name;
572
+
573
+ // 不解析jsx中的style标签
574
+ if (ignoreComponents.includes(jsxName)) {
575
+ path.skip();
576
+ return;
577
+ }
578
+
579
+ const parentNodeType = path.parentPath?.node?.type;
580
+
581
+ // 如果是配置的国际化jsx标签
582
+ if (!shouldIgnore(node) && intlTag && jsxName === intlTag) {
583
+
584
+ let id = getJsxTagChaoswiseIntlValue(openingElement, intlTagIdPath || 'id');
585
+
586
+ let word = getWord(id);
587
+
588
+ if (!word) {
589
+ // 根据id找不到中文,就找jsx标签的默认中文
590
+ let defaultValue = getJsxTagChaoswiseIntlValue(openingElement, intlTagDefaultWordPath);
591
+ if (typeof defaultValue === 'string') {
592
+ word = defaultValue;
593
+ } else {
594
+ if (!intlTagIdPath) {
595
+ properLog.warn(`intlTagIdPath未配置`);
596
+ } else {
597
+ if (!id) {
598
+ properLog.warn(`文件:${filePath} id路径intlTagIdPath:${intlTagIdPath} 未找到非空字符串`);
599
+ } else {
600
+ // word找不到
601
+ localWordPath && properLog.warn(`中文文件localWordPath:${localWordPath} 键:${id} 未找到非空字符串`);
602
+ }
603
+ }
604
+ if (defaultValue === false) {
605
+ properLog.warn(`文件:${filePath} 替换的标签intlTag:${intlTag} 默认中文路径intlTagDefaultWordPath:${intlTagDefaultWordPath} 未找到非空字符串`);
606
+ }
607
+
608
+ if (['JSXFragment', 'JSXElement'].includes(parentNodeType)) {
609
+ insertFailCommonInJsx(path);
610
+ } else {
611
+ insertFailCommon(node);
612
+ }
613
+
614
+ }
615
+ }
616
+ if (word && isPrimary(word)) {
617
+ // 替换国际化标签,<FormatMessage id='zhongwenid' defaultMessage="中文" /> 换成 {intl.get(id).d('中文')}
618
+ let res = makeReplace(word);
619
+
620
+ // 如果节点的父节点是JSXFragment或者JSXElement,那么就包一层JSXExpressionContainer
621
+ if (['JSXFragment', 'JSXElement'].includes(parentNodeType)) {
622
+ res = t.JSXExpressionContainer(res);
623
+ }
624
+ path.replaceWith(res);
625
+ }
626
+ path.skip();
627
+ }
628
+ },
629
+
325
630
  // JSX文本节点
326
631
  JSXText(path) {
327
632
  const { node } = path;
@@ -1,12 +1,16 @@
1
1
  const t = require('@babel/types');
2
+ const specialMatch = require('./specialMatch');
2
3
 
3
4
  module.exports = function f(
4
5
  {
5
6
  i18nObject,
6
7
  i18nMethod,
7
8
  importCode,
9
+ ignoreLines,
10
+ i18nDefaultFunctionKey,
8
11
  },
9
- returns
12
+ returns,
13
+ { special },
10
14
  ) {
11
15
  const { replaceWords, downloadIds } = returns;
12
16
 
@@ -33,6 +37,14 @@ module.exports = function f(
33
37
  return str.trim().replace(/\s+/g, ' ');
34
38
  }
35
39
 
40
+ // 是否忽略
41
+ function shouldIgnore(node) {
42
+ if (node?.loc) {
43
+ return ignoreLines.includes(node.loc.start.line);
44
+ }
45
+ return false;
46
+ }
47
+
36
48
  // 处理模板字符串中的变量
37
49
  function makeObjectExpression(obj) {
38
50
  if (Object.prototype.toString.call(obj) !== '[object Object]') return null;
@@ -118,6 +130,31 @@ module.exports = function f(
118
130
  }
119
131
 
120
132
  return {
133
+ // 字符串变量 src/config/router.config.js中的id进行替换
134
+ StringLiteral(path) {
135
+ const { node } = path;
136
+ let { value } = node;
137
+
138
+ if (!shouldIgnore(node) && special) {
139
+ // intl.get('id').d(中文) 获取id和中文
140
+ const { id, defaultValue } = specialMatch(value) || {};
141
+ if (!id) return;
142
+
143
+ const finalyId = replaceWords[id];
144
+ if (finalyId) {
145
+ returns.hasTouch = true;
146
+ downloadIds.push(finalyId);
147
+
148
+ const str = `${i18nObject ? `${i18nObject}.` : ''}${i18nMethod}("${finalyId}").${i18nDefaultFunctionKey}("${defaultValue}")`;
149
+ const newStr = hackValue(str, str,);
150
+ path.replaceWith(newStr);
151
+ path.skip();
152
+ } else {
153
+ downloadIds.push(id);
154
+ }
155
+ }
156
+ },
157
+
121
158
  // 导入声明,比如:import foo from "mod";
122
159
  ImportDeclaration(path) {
123
160
  // 是否已经导入过 intl 的依赖
@@ -0,0 +1,14 @@
1
+ const getConf = require('../conf');
2
+
3
+ let reg;
4
+
5
+ module.exports = function (str) {
6
+ if (!reg) {
7
+ const conf = getConf();
8
+ const { i18nObject, i18nMethod, i18nDefaultFunctionKey } = conf;
9
+ reg = new RegExp(`${i18nObject? `${i18nObject}\\.`: ''}${i18nMethod}\\([\\'\\"]([^\\)]*)[\\'\\"]\\)\\.${i18nDefaultFunctionKey}\\([\\'\\"]([^\\)]*)[\\'\\"]\\)`);
10
+ }
11
+ const res = str.match(reg);
12
+ if (!res) return;
13
+ return { id: res[1], defaultValue: res[2] };
14
+ }