From e7ff3c75707648aeccf7ef1b75ba4cb23285718a Mon Sep 17 00:00:00 2001 From: Carrotzpc Date: Tue, 19 Mar 2024 16:22:46 +0800 Subject: [PATCH] fix(lowcode-i18n-extract): fix RegExp test and function i18n var inject issues --- .github/workflows/release.yml | 1 + packages/lowcode-i18n-extract/src/extract.ts | 19 ++- packages/lowcode-i18n-extract/src/replace.ts | 8 +- .../tests/data/results/matches.json | 101 ++++++++---- .../tests/data/results/schema-with-i18n.json | 146 ++++++++++------- .../tests/data/schema.json | 148 ++++++++++-------- .../lowcode-i18n-extract/tests/index.test.ts | 2 +- 7 files changed, 264 insertions(+), 161 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6cff3d6..c479d3a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -49,6 +49,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + # @Todo: should check if relase successfully - name: Sync to cnpm run: | npm install -g cnpm diff --git a/packages/lowcode-i18n-extract/src/extract.ts b/packages/lowcode-i18n-extract/src/extract.ts index 016ee17..efbc563 100644 --- a/packages/lowcode-i18n-extract/src/extract.ts +++ b/packages/lowcode-i18n-extract/src/extract.ts @@ -1,3 +1,4 @@ +/* eslint-disable unicorn/prefer-regexp-test */ import { IPublicTypePageSchema, IPublicTypeProjectSchema } from '@alilc/lowcode-types'; import * as babelParser from '@babel/parser'; import * as babelTraverse from '@babel/traverse'; @@ -35,7 +36,11 @@ function findTextInJs(code: string, type: string, path: string[]) { babelTraverse.default(ast, { StringLiteral({ node }) { const { start, end, value } = node as babelTypes.StringLiteral; - if (value && DOUBLE_BYTE_REGEX.test(value)) { + // 注意这里不能是用 `DOUBLE_BYTE_REGEX.test()`,如果正则表达式设置了全局标志 `g`, + // `test()` 的执行会改变正则表达式 `lastIndex` 属性。连续的执行 `test` 方法, + // 后续的执行将会从 `lastIndex` 处开始匹配字符串,(`exec()` 同样改变正则本身的 `lastIndex` 属性值) + // 详见 https://yi-love.github.io/articles/regexp-test + if (value && value.match(DOUBLE_BYTE_REGEX)) { const range = { start: start - offset, end: end - offset }; jsMatches.matches.push({ range, @@ -47,7 +52,7 @@ function findTextInJs(code: string, type: string, path: string[]) { TemplateLiteral({ node }) { const { start, end } = node as babelTypes.TemplateLiteral; const templateContent = fixedCode.slice(start, end); - if (DOUBLE_BYTE_REGEX.test(templateContent)) { + if (templateContent.match(DOUBLE_BYTE_REGEX)) { const range = { start: start - offset, end: end - offset }; jsMatches.matches.push({ range, @@ -62,7 +67,7 @@ function findTextInJs(code: string, type: string, path: string[]) { if (babelTypes.isJSXText(child)) { const { value, start, end } = child; const range = { start: start - offset, end: end - offset }; - if (DOUBLE_BYTE_REGEX.test(value)) { + if (value.match(DOUBLE_BYTE_REGEX)) { jsMatches.matches.push({ range, text: value.trim(), @@ -96,6 +101,9 @@ const findI18n = (obj: Record, path: string[] = [], matches: I18nMa if (jsMatches.matches.length === 0) { continue; } + // 调整文案顺序,保证从后面的文案往前替换,避免位置更新导致替换出错 + jsMatches.matches = sortBy(jsMatches.matches, match => -match.range.start); + matches.push(jsMatches); // 需要对 methods 中的 source 进行特殊处理 if (value.source) { const sourceJsMatches = findTextInJs(value.source, value.type, [ @@ -108,9 +116,6 @@ const findI18n = (obj: Record, path: string[] = [], matches: I18nMa ); matches.push(sourceJsMatches); } - // 调整文案顺序,保证从后面的文案往前替换,避免位置更新导致替换出错 - jsMatches.matches = sortBy(jsMatches.matches, match => -match.range.start); - matches.push(jsMatches); } catch (error) { console.warn(`parse '${newPath.join(' > ')}' failed, code is: ${value.value}`, error); } @@ -133,7 +138,7 @@ const findI18n = (obj: Record, path: string[] = [], matches: I18nMa findI18n(value, newPath, matches); continue; } - if (valueType === 'string' && DOUBLE_BYTE_REGEX.test(value)) { + if (valueType === 'string' && value.match(DOUBLE_BYTE_REGEX)) { matches.push({ path: newPath, text: value, diff --git a/packages/lowcode-i18n-extract/src/replace.ts b/packages/lowcode-i18n-extract/src/replace.ts index e6c666d..074556f 100644 --- a/packages/lowcode-i18n-extract/src/replace.ts +++ b/packages/lowcode-i18n-extract/src/replace.ts @@ -105,9 +105,11 @@ export const replaceAndUpdateJsCode = (matches: I18nMatch[], jsCode: string, typ newCode = code; i18nRecords[match.key] = text; } - // 函数类型的 code 在函数体首行增加 i18n 函数变量声明,可以避免一些 this 指向引起的 i18n 无法获取的问题 - if (IS_ADD_I18N_VAR) { - newCode = newCode.replace(JS_FUNCTION_PREFIX_REG, `$1\n const __I18N = this.i18n;\n`); + const I18N_VAR_EXPRESSION = 'const __I18N = this.i18n;'; + // 函数类型的 code 在函数体首行增加 __I18N 函数变量声明,可以避免一些 this 指向引起的 i18n 无法获取的问题 + // 需要判断函数体内部是否已经添加过 __I18N 变量,避免重复添加 + if (IS_ADD_I18N_VAR && !newCode.includes(I18N_VAR_EXPRESSION)) { + newCode = newCode.replace(JS_FUNCTION_PREFIX_REG, `$1\n ${I18N_VAR_EXPRESSION}\n`); } return { code: newCode, diff --git a/packages/lowcode-i18n-extract/tests/data/results/matches.json b/packages/lowcode-i18n-extract/tests/data/results/matches.json index 0382422..87521c6 100644 --- a/packages/lowcode-i18n-extract/tests/data/results/matches.json +++ b/packages/lowcode-i18n-extract/tests/data/results/matches.json @@ -1,6 +1,6 @@ [ { - "path": ["componentsTree", "0", "methods", "paginationShowTotal", "source"], + "path": ["componentsTree", "0", "methods", "paginationShowTotal", "value"], "matches": [ { "range": { @@ -14,7 +14,7 @@ ] }, { - "path": ["componentsTree", "0", "methods", "paginationShowTotal", "value"], + "path": ["componentsTree", "0", "methods", "paginationShowTotal", "source"], "matches": [ { "range": { @@ -28,12 +28,40 @@ ] }, { - "path": ["componentsTree", "0", "methods", "getStatusText", "source"], + "path": ["componentsTree", "0", "methods", "getHelloWorldText", "value"], "matches": [ { "range": { - "start": 465, - "end": 518 + "start": 92, + "end": 96 + }, + "text": "絮黎", + "isString": true, + "key": "i18n-xu-li" + } + ] + }, + { + "path": ["componentsTree", "0", "methods", "getHelloWorldText", "source"], + "matches": [ + { + "range": { + "start": 92, + "end": 96 + }, + "text": "絮黎", + "isString": true, + "key": "i18n-xu-li" + } + ] + }, + { + "path": ["componentsTree", "0", "methods", "getStatusText", "value"], + "matches": [ + { + "range": { + "start": 570, + "end": 623 }, "text": "审核未通过:${this.state.value === 1 ? '姓名未通过' : '地址未通过'}", "isString": true, @@ -41,8 +69,8 @@ }, { "range": { - "start": 325, - "end": 329 + "start": 423, + "end": 437 }, "text": "进度", "isString": true, @@ -50,11 +78,11 @@ }, { "range": { - "start": 301, - "end": 316 + "start": 342, + "end": 368 }, "text": "审核中(", - "isString": false, + "isString": true, "key": "i18n-shen-he-zhong" }, { @@ -78,12 +106,12 @@ ] }, { - "path": ["componentsTree", "0", "methods", "getStatusText", "value"], + "path": ["componentsTree", "0", "methods", "getStatusText", "source"], "matches": [ { "range": { - "start": 570, - "end": 623 + "start": 465, + "end": 518 }, "text": "审核未通过:${this.state.value === 1 ? '姓名未通过' : '地址未通过'}", "isString": true, @@ -91,8 +119,8 @@ }, { "range": { - "start": 423, - "end": 437 + "start": 325, + "end": 329 }, "text": "进度", "isString": true, @@ -100,11 +128,11 @@ }, { "range": { - "start": 342, - "end": 368 + "start": 301, + "end": 316 }, "text": "审核中(", - "isString": true, + "isString": false, "key": "i18n-shen-he-zhong" }, { @@ -127,6 +155,23 @@ } ] }, + { + "path": [ + "componentsTree", + "0", + "children", + "0", + "children", + "0", + "children", + "0", + "props", + "children" + ], + "text": "国际化文案提取测试", + "isString": true, + "key": "i18n-guo-ji-hua-wen-an" + }, { "path": [ "componentsTree", @@ -176,7 +221,7 @@ "children", "0", "children", - "2", + "3", "children", "0", "children", @@ -205,7 +250,7 @@ "children", "0", "children", - "2", + "3", "children", "0", "children", @@ -234,7 +279,7 @@ "children", "0", "children", - "2", + "3", "children", "0", "children", @@ -263,7 +308,7 @@ "children", "0", "children", - "2", + "3", "children", "1", "children", @@ -288,7 +333,7 @@ "children", "0", "children", - "2", + "3", "children", "1", "children", @@ -313,7 +358,7 @@ "children", "0", "children", - "2", + "3", "children", "1", "children", @@ -338,7 +383,7 @@ "children", "0", "children", - "2", + "3", "children", "1", "children", @@ -363,7 +408,7 @@ "children", "0", "children", - "2", + "3", "children", "1", "children", @@ -388,7 +433,7 @@ "children", "0", "children", - "2", + "3", "children", "1", "children", @@ -419,7 +464,7 @@ "children", "0", "children", - "2", + "3", "children", "1", "children", diff --git a/packages/lowcode-i18n-extract/tests/data/results/schema-with-i18n.json b/packages/lowcode-i18n-extract/tests/data/results/schema-with-i18n.json index 19e44af..bbc810b 100644 --- a/packages/lowcode-i18n-extract/tests/data/results/schema-with-i18n.json +++ b/packages/lowcode-i18n-extract/tests/data/results/schema-with-i18n.json @@ -16,6 +16,14 @@ "subName": "", "componentName": "Col" }, + { + "package": "@tenx-ui/materials", + "version": "1.5.32", + "exportName": "Alert", + "destructuring": true, + "subName": "", + "componentName": "Alert" + }, { "package": "@tenx-ui/materials", "version": "1.5.32", @@ -95,14 +103,6 @@ "destructuring": true, "subName": "", "componentName": "Page" - }, - { - "package": "@tenx-ui/materials", - "version": "1.5.32", - "exportName": "Alert", - "destructuring": true, - "subName": "", - "componentName": "Alert" } ], "componentsTree": [ @@ -110,12 +110,12 @@ "componentName": "Page", "id": "page-kww7j", "props": {}, - "docId": "docltnxqm9h", "css": "body {\n font-size: 12px;\n}", "meta": { "title": "国际化文案提取测试", "router": "/i18n-extract" }, + "docId": "docltnxqm9h", "title": "", "hidden": false, "fileName": "I18nExtract", @@ -134,6 +134,11 @@ "value": "function paginationShowTotal(total, range) {\n const __I18N = this.i18n;\n\n return __I18N('i18n-gong-tota', { val1: total });\n}", "source": "function paginationShowTotal(total, range) {\n const __I18N = this.i18n;\n\n return __I18N('i18n-gong-tota', { val1: total });\n}" }, + "getHelloWorldText": { + "type": "JSFunction", + "value": "function getHelloWorldText() {\n const __I18N = this.i18n;\n\n // 测试新增中文文案的提取\n const name = __I18N('i18n-xu-li');\n return __I18N('i18n-ni-hao-nam', {\n val1: name\n });\n}", + "source": "function getHelloWorldText() {\n const __I18N = this.i18n;\n\n // 测试新增中文文案的提取\n const name = __I18N('i18n-xu-li');\n return __I18N('i18n-ni-hao-nam', {\n val1: name\n });\n}" + }, "getStatusText": { "type": "JSFunction", "value": "function getStatusText(record) {\n const __I18N = this.i18n;\n\n console.log('record', record);\n return [{\n type: 'success',\n id: '1',\n children: __I18N('i18n-yi-ji-huo')\n }, {\n type: 'error',\n id: '2',\n // 测试带参数提取\n children: __I18N('i18n-ji-huo-shi-bai-r', { val1: record.reason })\n }, {\n type: 'primary',\n id: '3',\n // 测试 jsx 提取\n children: /*#__PURE__*/React.createElement(\"div\", null, __I18N('i18n-shen-he-zhong'), /*#__PURE__*/React.createElement(\"i\", {\n title: __I18N('i18n-jin-du')\n }, record.reason), \"\\uFF09\")\n }, {\n type: 'primary',\n id: '4',\n // 测试模板字符串中变量嵌套中文提取(注意以下为错误写法,只是为了测试提取)\n children: __I18N('i18n-shen-he-wei-tong-guo', { val1: this.state.value === 1 ? '姓名未通过' : '地址未通过' })\n }];\n}", @@ -178,7 +183,7 @@ "level": 1, "bordered": false, "children": { - "key": "i18n-s7vniwvk", + "key": "i18n-guo-ji-hua-wen-an", "type": "i18n" }, "ellipsis": true, @@ -234,16 +239,16 @@ "componentName": "Alert", "id": "node_oclto0j15r1", "props": { + "type": "success", "message": { "key": "i18n-zhe-shi-ce-shi-wen", "type": "i18n" }, - "__component_name": "Alert", - "type": "success", - "showIcon": true + "showIcon": true, + "__component_name": "Alert" }, - "hidden": false, "title": "", + "hidden": false, "isLocked": false, "condition": true, "conditionGroup": "" @@ -252,16 +257,35 @@ "componentName": "Alert", "id": "node_oclto0j15r2", "props": { + "type": "success", "message": { "key": "i18n-zhe-shi-ce-shi-wen-2", "type": "i18n" }, - "__component_name": "Alert", - "type": "success", - "showIcon": true + "showIcon": true, + "__component_name": "Alert" }, + "title": "", "hidden": false, + "isLocked": false, + "condition": true, + "conditionGroup": "" + }, + { + "componentName": "Alert", + "id": "node_ocltxy0e3h1", + "props": { + "type": "success", + "message": { + "type": "JSExpression", + "value": "this.getHelloWorldText()" + }, + "showIcon": true, + "__component_name": "Alert", + "_unsafe_MixedSetter_message_select": "VariableSetter" + }, "title": "", + "hidden": false, "isLocked": false, "condition": true, "conditionGroup": "" @@ -376,14 +400,14 @@ "shape": "default", "danger": false, "__events": { - "eventDataList": [], "eventList": [ { "name": "onClick", - "template": "onClick(event,${extParams}){\n// 点击按钮时的回调\nconsole.log('onClick', event);}", - "disabled": true + "disabled": true, + "template": "onClick(event,${extParams}){\n// 点击按钮时的回调\nconsole.log('onClick', event);}" } - ] + ], + "eventDataList": [] }, "children": { "key": "i18n-shua-xin", @@ -407,49 +431,49 @@ "width": "240px" }, "__events": { - "eventDataList": [], "eventList": [ { "name": "onChange", - "template": "onChange(event,${extParams}){\n// 输入框内容变化时的回调\nconsole.log('onChange',event);}", - "disabled": false + "disabled": false, + "template": "onChange(event,${extParams}){\n// 输入框内容变化时的回调\nconsole.log('onChange',event);}" }, { "name": "onPressEnter", - "template": "onPressEnter(event,${extParams}){\n// 按下回车的回调\nconsole.log('onPressEnter',event);}", - "disabled": false + "disabled": false, + "template": "onPressEnter(event,${extParams}){\n// 按下回车的回调\nconsole.log('onPressEnter',event);}" }, { "name": "onSearch", - "template": "onSearch(value,event,${extParams}){\n// 点击搜索图标、清除图标,或按下回车键时的回调\nconsole.log('onSearch',value,event);}", - "disabled": true + "disabled": true, + "template": "onSearch(value,event,${extParams}){\n// 点击搜索图标、清除图标,或按下回车键时的回调\nconsole.log('onSearch',value,event);}" }, { "name": "onFocus", - "template": "onFocus(event,${extParams}){\n// 获取焦点回调\nconsole.log('onFocus',event);}", - "disabled": false + "disabled": false, + "template": "onFocus(event,${extParams}){\n// 获取焦点回调\nconsole.log('onFocus',event);}" }, { "name": "onKeyDown", - "template": "onKeyDown(event,${extParams}){\n// 按键按下时的回调\nconsole.log('onKeyDown',event);}", - "disabled": false + "disabled": false, + "template": "onKeyDown(event,${extParams}){\n// 按键按下时的回调\nconsole.log('onKeyDown',event);}" }, { "name": "onKeyPress", - "template": "onKeyPress(event,${extParams}){\n// 按键按下后的回调\nconsole.log('onKeyPress',event);}", - "disabled": false + "disabled": false, + "template": "onKeyPress(event,${extParams}){\n// 按键按下后的回调\nconsole.log('onKeyPress',event);}" }, { "name": "onKeyUp", - "template": "onKeyUp(event,${extParams}){\n// 按键释放回调\nconsole.log('onKeyUp',event);}", - "disabled": false + "disabled": false, + "template": "onKeyUp(event,${extParams}){\n// 按键释放回调\nconsole.log('onKeyUp',event);}" }, { "name": "onBlur", - "template": "onBlur(event,${extParams}){\n// 按键释放回调\nconsole.log('onBlur',event);}", - "disabled": false + "disabled": false, + "template": "onBlur(event,${extParams}){\n// 按键释放回调\nconsole.log('onBlur',event);}" } - ] + ], + "eventDataList": [] }, "placeholder": { "key": "i18n-shu-ru-ming-cheng-jin", @@ -600,10 +624,10 @@ "key": "i18n-di-zhi", "type": "i18n" }, - "dataIndex": "address", "ellipsis": { "showTitle": true - } + }, + "dataIndex": "address" }, { "key": "status", @@ -620,9 +644,9 @@ "id": "node_ocltnxqx9j2", "props": { "id": { + "mock": "", "type": "JSExpression", - "value": "this.text", - "mock": "" + "value": "this.text" }, "types": { "type": "JSExpression", @@ -780,34 +804,34 @@ } ], "__events": { - "eventDataList": [], "eventList": [ { "name": "onChange", - "template": "onChange(pagination,filters,sorter,extra,${extParams}){\n// 表格翻页事件\nconsole.log('onChange', pagination);}", - "disabled": true + "disabled": true, + "template": "onChange(pagination,filters,sorter,extra,${extParams}){\n// 表格翻页事件\nconsole.log('onChange', pagination);}" }, { "name": "rowSelection.onChange", - "template": "onRowSelectionChange(selectedRowKeys,selectedRows,${extParams}){\n// 选中项发生变化时的回调\nconsole.log('onRowSelectionChange', selectedRowKeys, selectedRows);}", - "disabled": false + "disabled": false, + "template": "onRowSelectionChange(selectedRowKeys,selectedRows,${extParams}){\n// 选中项发生变化时的回调\nconsole.log('onRowSelectionChange', selectedRowKeys, selectedRows);}" }, { "name": "expandable.onExpand", - "template": "onExpandableExpand(expanded,record){\n// 点击展开图标时触发\nconsole.log('onRowSelectionChange', expanded, record);}", - "disabled": false + "disabled": false, + "template": "onExpandableExpand(expanded,record){\n// 点击展开图标时触发\nconsole.log('onRowSelectionChange', expanded, record);}" }, { "name": "pagination.onChange", - "template": "onPaginationChange(page, pageSize){\n// 页码或 pageSize 改变的回调 \nconsole.log('onPaginationChange', page, pageSize);}", - "disabled": false + "disabled": false, + "template": "onPaginationChange(page, pageSize){\n// 页码或 pageSize 改变的回调 \nconsole.log('onPaginationChange', page, pageSize);}" }, { "name": "pagination.onShowSizeChange", - "template": "onPaginationShowSizeChange(current, size){\n// pageSize 变化的回调\nconsole.log('onPaginationShowSizeChange', current, size);}", - "disabled": false + "disabled": false, + "template": "onPaginationShowSizeChange(current, size){\n// pageSize 变化的回调\nconsole.log('onPaginationShowSizeChange', current, size);}" } - ] + ], + "eventDataList": [] }, "dataSource": [ { @@ -914,7 +938,6 @@ "mock": "false", "type": "JSExpression", "value": "process.env.NODE_ENV === 'production'", - "builtin": true, "description": "是否为生产环境" }, "basename": { @@ -933,12 +956,15 @@ }, "i18n": { "en-US": { + "i18n-ni-hao-nam": "Hello, {val1}", "i18n-gong-tota": "共{val1}条", + "i18n-xu-li": "絮黎", "i18n-shen-he-wei-tong-guo": "审核未通过:{val1}", "i18n-jin-du": "进度", "i18n-shen-he-zhong": "审核中(", "i18n-ji-huo-shi-bai-r": "激活失败:{val1}", "i18n-yi-ji-huo": "已激活", + "i18n-guo-ji-hua-wen-an": "国际化文案提取测试", "i18n-zhe-shi-ce-shi-wen": "这是测试文案", "i18n-zhe-shi-ce-shi-wen-2": "这是测试文案(开头重复)", "i18n-tian-jia": "添加", @@ -953,12 +979,15 @@ "i18n-bian-ji": "编辑" }, "zh-CN": { + "i18n-ni-hao-nam": "你好,{val1}", "i18n-gong-tota": "共{val1}条", + "i18n-xu-li": "絮黎", "i18n-shen-he-wei-tong-guo": "审核未通过:{val1}", "i18n-jin-du": "进度", "i18n-shen-he-zhong": "审核中(", "i18n-ji-huo-shi-bai-r": "激活失败:{val1}", "i18n-yi-ji-huo": "已激活", + "i18n-guo-ji-hua-wen-an": "国际化文案提取测试", "i18n-zhe-shi-ce-shi-wen": "这是测试文案", "i18n-zhe-shi-ce-shi-wen-2": "这是测试文案(开头重复)", "i18n-tian-jia": "添加", @@ -978,10 +1007,7 @@ "version": "0.1.2", "basename": "/hello-world", "namespace": "hello-world", - "description": "cs", - "lowCode": { - "packages": [] - } + "description": "cs" }, "utils": [ { diff --git a/packages/lowcode-i18n-extract/tests/data/schema.json b/packages/lowcode-i18n-extract/tests/data/schema.json index 75ab694..fad9548 100644 --- a/packages/lowcode-i18n-extract/tests/data/schema.json +++ b/packages/lowcode-i18n-extract/tests/data/schema.json @@ -16,6 +16,14 @@ "subName": "", "componentName": "Col" }, + { + "package": "@tenx-ui/materials", + "version": "1.5.32", + "exportName": "Alert", + "destructuring": true, + "subName": "", + "componentName": "Alert" + }, { "package": "@tenx-ui/materials", "version": "1.5.32", @@ -95,14 +103,6 @@ "destructuring": true, "subName": "", "componentName": "Page" - }, - { - "package": "@tenx-ui/materials", - "version": "1.5.32", - "exportName": "Alert", - "destructuring": true, - "subName": "", - "componentName": "Alert" } ], "componentsTree": [ @@ -110,18 +110,18 @@ "componentName": "Page", "id": "page-kww7j", "props": {}, - "docId": "docltnxqm9h", "css": "body {\n font-size: 12px;\n}", "meta": { "title": "国际化文案提取测试", "router": "/i18n-extract" }, + "docId": "docltnxqm9h", "title": "", "hidden": false, "fileName": "I18nExtract", "isLocked": false, "condition": true, - "originCode": "class Page extends Component {\n state = {\n value: 1,\n }\n paginationShowTotal(total, range) {\n return `共${total}条`;\n }\n getStatusText(record) {\n console.log('record', record)\n return [\n {\n type: 'success',\n id: '1',\n children: '已激活'\n },\n {\n type: 'error',\n id: '2',\n // 测试带参数提取\n children: `激活失败:${record.reason}`\n },\n {\n type: 'primary',\n id: '3',\n // 测试 jsx 提取\n children:
\n 审核中({record.reason})\n
\n },\n {\n type: 'primary',\n id: '4',\n // 测试模板字符串中变量嵌套中文提取(注意以下为错误写法,只是为了测试提取)\n children: `审核未通过:${this.state.value === 1 ? '姓名未通过' : '地址未通过'}`\n },\n ];\n }\n}", + "originCode": "class Page extends Component {\n state = {\n value: 1,\n }\n paginationShowTotal(total, range) {\n return `共${total}条`;\n }\n getHelloWorldText() {\n const __I18N = this.i18n;\n\n // 测试新增中文文案的提取\n const name = '絮黎';\n return __I18N('i18n-ni-hao-nam', {\n val1: name\n });\n }\n getStatusText(record) {\n console.log('record', record)\n return [\n {\n type: 'success',\n id: '1',\n children: '已激活'\n },\n {\n type: 'error',\n id: '2',\n // 测试带参数提取\n children: `激活失败:${record.reason}`\n },\n {\n type: 'primary',\n id: '3',\n // 测试 jsx 提取\n children:
\n 审核中({record.reason})\n
\n },\n {\n type: 'primary',\n id: '4',\n // 测试模板字符串中变量嵌套中文提取(注意以下为错误写法,只是为了测试提取)\n children: `审核未通过:${this.state.value === 1 ? '姓名未通过' : '地址未通过'}`\n },\n ];\n }\n}", "conditionGroup": "", "state": { "value": { @@ -135,6 +135,11 @@ "value": "function paginationShowTotal(total, range) {\n return `共${total}条`;\n}", "source": "function paginationShowTotal(total, range) {\n return `共${total}条`;\n}" }, + "getHelloWorldText": { + "type": "JSFunction", + "value": "function getHelloWorldText() {\n const __I18N = this.i18n;\n\n // 测试新增中文文案的提取\n const name = '絮黎';\n return __I18N('i18n-ni-hao-nam', {\n val1: name\n });\n}", + "source": "function getHelloWorldText() {\n const __I18N = this.i18n;\n\n // 测试新增中文文案的提取\n const name = '絮黎';\n return __I18N('i18n-ni-hao-nam', {\n val1: name\n });\n}" + }, "getStatusText": { "type": "JSFunction", "value": "function getStatusText(record) {\n console.log('record', record);\n return [{\n type: 'success',\n id: '1',\n children: '已激活'\n }, {\n type: 'error',\n id: '2',\n // 测试带参数提取\n children: `激活失败:${record.reason}`\n }, {\n type: 'primary',\n id: '3',\n // 测试 jsx 提取\n children: /*#__PURE__*/React.createElement(\"div\", null, \"\\u5BA1\\u6838\\u4E2D\\uFF08\", /*#__PURE__*/React.createElement(\"i\", {\n title: \"\\u8FDB\\u5EA6\"\n }, record.reason), \"\\uFF09\")\n }, {\n type: 'primary',\n id: '4',\n // 测试模板字符串中变量嵌套中文提取(注意以下为错误写法,只是为了测试提取)\n children: `审核未通过:${this.state.value === 1 ? '姓名未通过' : '地址未通过'}`\n }];\n}", @@ -232,13 +237,13 @@ "componentName": "Alert", "id": "node_oclto0j15r1", "props": { - "message": "这是测试文案", - "__component_name": "Alert", "type": "success", - "showIcon": true + "message": "这是测试文案", + "showIcon": true, + "__component_name": "Alert" }, - "hidden": false, "title": "", + "hidden": false, "isLocked": false, "condition": true, "conditionGroup": "" @@ -247,13 +252,32 @@ "componentName": "Alert", "id": "node_oclto0j15r2", "props": { - "message": "这是测试文案(开头重复)", - "__component_name": "Alert", "type": "success", - "showIcon": true + "message": "这是测试文案(开头重复)", + "showIcon": true, + "__component_name": "Alert" }, + "title": "", "hidden": false, + "isLocked": false, + "condition": true, + "conditionGroup": "" + }, + { + "componentName": "Alert", + "id": "node_ocltxy0e3h1", + "props": { + "type": "success", + "message": { + "type": "JSExpression", + "value": "this.getHelloWorldText()" + }, + "showIcon": true, + "__component_name": "Alert", + "_unsafe_MixedSetter_message_select": "VariableSetter" + }, "title": "", + "hidden": false, "isLocked": false, "condition": true, "conditionGroup": "" @@ -365,14 +389,14 @@ "shape": "default", "danger": false, "__events": { - "eventDataList": [], "eventList": [ { "name": "onClick", - "template": "onClick(event,${extParams}){\n// 点击按钮时的回调\nconsole.log('onClick', event);}", - "disabled": true + "disabled": true, + "template": "onClick(event,${extParams}){\n// 点击按钮时的回调\nconsole.log('onClick', event);}" } - ] + ], + "eventDataList": [] }, "children": "刷新", "disabled": false, @@ -393,49 +417,49 @@ "width": "240px" }, "__events": { - "eventDataList": [], "eventList": [ { "name": "onChange", - "template": "onChange(event,${extParams}){\n// 输入框内容变化时的回调\nconsole.log('onChange',event);}", - "disabled": false + "disabled": false, + "template": "onChange(event,${extParams}){\n// 输入框内容变化时的回调\nconsole.log('onChange',event);}" }, { "name": "onPressEnter", - "template": "onPressEnter(event,${extParams}){\n// 按下回车的回调\nconsole.log('onPressEnter',event);}", - "disabled": false + "disabled": false, + "template": "onPressEnter(event,${extParams}){\n// 按下回车的回调\nconsole.log('onPressEnter',event);}" }, { "name": "onSearch", - "template": "onSearch(value,event,${extParams}){\n// 点击搜索图标、清除图标,或按下回车键时的回调\nconsole.log('onSearch',value,event);}", - "disabled": true + "disabled": true, + "template": "onSearch(value,event,${extParams}){\n// 点击搜索图标、清除图标,或按下回车键时的回调\nconsole.log('onSearch',value,event);}" }, { "name": "onFocus", - "template": "onFocus(event,${extParams}){\n// 获取焦点回调\nconsole.log('onFocus',event);}", - "disabled": false + "disabled": false, + "template": "onFocus(event,${extParams}){\n// 获取焦点回调\nconsole.log('onFocus',event);}" }, { "name": "onKeyDown", - "template": "onKeyDown(event,${extParams}){\n// 按键按下时的回调\nconsole.log('onKeyDown',event);}", - "disabled": false + "disabled": false, + "template": "onKeyDown(event,${extParams}){\n// 按键按下时的回调\nconsole.log('onKeyDown',event);}" }, { "name": "onKeyPress", - "template": "onKeyPress(event,${extParams}){\n// 按键按下后的回调\nconsole.log('onKeyPress',event);}", - "disabled": false + "disabled": false, + "template": "onKeyPress(event,${extParams}){\n// 按键按下后的回调\nconsole.log('onKeyPress',event);}" }, { "name": "onKeyUp", - "template": "onKeyUp(event,${extParams}){\n// 按键释放回调\nconsole.log('onKeyUp',event);}", - "disabled": false + "disabled": false, + "template": "onKeyUp(event,${extParams}){\n// 按键释放回调\nconsole.log('onKeyUp',event);}" }, { "name": "onBlur", - "template": "onBlur(event,${extParams}){\n// 按键释放回调\nconsole.log('onBlur',event);}", - "disabled": false + "disabled": false, + "template": "onBlur(event,${extParams}){\n// 按键释放回调\nconsole.log('onBlur',event);}" } - ] + ], + "eventDataList": [] }, "placeholder": "输入名称进行搜索", "__component_name": "Input.Search" @@ -577,10 +601,10 @@ { "key": "address", "title": "地址", - "dataIndex": "address", "ellipsis": { "showTitle": true - } + }, + "dataIndex": "address" }, { "key": "status", @@ -594,9 +618,9 @@ "id": "node_ocltnxqx9j2", "props": { "id": { + "mock": "", "type": "JSExpression", - "value": "this.text", - "mock": "" + "value": "this.text" }, "types": { "type": "JSExpression", @@ -742,34 +766,34 @@ } ], "__events": { - "eventDataList": [], "eventList": [ { "name": "onChange", - "template": "onChange(pagination,filters,sorter,extra,${extParams}){\n// 表格翻页事件\nconsole.log('onChange', pagination);}", - "disabled": true + "disabled": true, + "template": "onChange(pagination,filters,sorter,extra,${extParams}){\n// 表格翻页事件\nconsole.log('onChange', pagination);}" }, { "name": "rowSelection.onChange", - "template": "onRowSelectionChange(selectedRowKeys,selectedRows,${extParams}){\n// 选中项发生变化时的回调\nconsole.log('onRowSelectionChange', selectedRowKeys, selectedRows);}", - "disabled": false + "disabled": false, + "template": "onRowSelectionChange(selectedRowKeys,selectedRows,${extParams}){\n// 选中项发生变化时的回调\nconsole.log('onRowSelectionChange', selectedRowKeys, selectedRows);}" }, { "name": "expandable.onExpand", - "template": "onExpandableExpand(expanded,record){\n// 点击展开图标时触发\nconsole.log('onRowSelectionChange', expanded, record);}", - "disabled": false + "disabled": false, + "template": "onExpandableExpand(expanded,record){\n// 点击展开图标时触发\nconsole.log('onRowSelectionChange', expanded, record);}" }, { "name": "pagination.onChange", - "template": "onPaginationChange(page, pageSize){\n// 页码或 pageSize 改变的回调 \nconsole.log('onPaginationChange', page, pageSize);}", - "disabled": false + "disabled": false, + "template": "onPaginationChange(page, pageSize){\n// 页码或 pageSize 改变的回调 \nconsole.log('onPaginationChange', page, pageSize);}" }, { "name": "pagination.onShowSizeChange", - "template": "onPaginationShowSizeChange(current, size){\n// pageSize 变化的回调\nconsole.log('onPaginationShowSizeChange', current, size);}", - "disabled": false + "disabled": false, + "template": "onPaginationShowSizeChange(current, size){\n// pageSize 变化的回调\nconsole.log('onPaginationShowSizeChange', current, size);}" } - ] + ], + "eventDataList": [] }, "dataSource": [ { @@ -876,7 +900,6 @@ "mock": "false", "type": "JSExpression", "value": "process.env.NODE_ENV === 'production'", - "builtin": true, "description": "是否为生产环境" }, "basename": { @@ -894,18 +917,19 @@ } }, "i18n": { - "en-US": {}, - "zh-CN": {} + "en-US": { + "i18n-ni-hao-nam": "Hello, {val1}" + }, + "zh-CN": { + "i18n-ni-hao-nam": "你好,{val1}" + } }, "meta": { "name": "cs", "version": "0.1.2", "basename": "/hello-world", "namespace": "hello-world", - "description": "cs", - "lowCode": { - "packages": [] - } + "description": "cs" }, "utils": [ { diff --git a/packages/lowcode-i18n-extract/tests/index.test.ts b/packages/lowcode-i18n-extract/tests/index.test.ts index 4bcf059..aee73bf 100644 --- a/packages/lowcode-i18n-extract/tests/index.test.ts +++ b/packages/lowcode-i18n-extract/tests/index.test.ts @@ -35,5 +35,5 @@ test('extract chinese text to i18n from schema', async () => { ); // Assert 断言测试结果 - expect(matches.length).toBe(17); + expect(matches.length).toBe(19); });