From 353234cd01e7be10bb71a9c4023f9870261d5975 Mon Sep 17 00:00:00 2001 From: wxzhang Date: Tue, 15 Mar 2022 21:38:15 +0800 Subject: [PATCH] update stringify.js --- packages/demo/data.js | 22 ++++++++ packages/demo/utils.demo.js | 24 +++++++-- packages/tools/extract.plugin.js | 12 +++-- .../tools/languages/translates/default.json | 16 ++++-- packages/tools/stringify.js | 52 +++++++++++++++---- 5 files changed, 100 insertions(+), 26 deletions(-) create mode 100644 packages/demo/data.js diff --git a/packages/demo/data.js b/packages/demo/data.js new file mode 100644 index 0000000..191aaeb --- /dev/null +++ b/packages/demo/data.js @@ -0,0 +1,22 @@ +module.exports = { + "name" : "张三丰", + "age" : 12, + "active" : true, + "address" : [ + "北京市", + "福建省泉州市\n洛阳镇" + ], + "posts" : { + "title" : "标题", + "content": "内容" + }, + "产品清单\t{}": [ + "手机", + "电脑" + ], + "产品价格" : { + "手机": 1299, + "电脑": 3999 + }, + "产品\\清单" : 1 +} \ No newline at end of file diff --git a/packages/demo/utils.demo.js b/packages/demo/utils.demo.js index 48e9427..662cceb 100644 --- a/packages/demo/utils.demo.js +++ b/packages/demo/utils.demo.js @@ -1,28 +1,42 @@ -const { objectToString } = require("../tools/stringify") +const objectToString = require("../tools/stringify") const path = require("path"); const fs = require("fs"); - +const k1 = "产品清单\t{}" +const k2 = "产品\\清单" const data = { name:"张三丰", age:12, active:true, address:[ "北京市", - "福建省泉州市" + "福建省泉州市\n洛阳镇" ], posts:{ title:"标题", content:"内容", //comments:[] }, - "产品清单":[ + [k1]:[ "手机", "电脑" - ] + ], + "产品价格":{ + "手机":1299, + "电脑":3999 + }, + [k2]:1 } const result = objectToString(data) console.log(result) +fs.writeFileSync(path.join(__dirname,"./data.js"),`module.exports = ${result}`) + +const loaded = require("./data.js") + +console.log(loaded[k1]) +console.log(loaded[k2]) + + diff --git a/packages/tools/extract.plugin.js b/packages/tools/extract.plugin.js index 447b092..4634438 100644 --- a/packages/tools/extract.plugin.js +++ b/packages/tools/extract.plugin.js @@ -13,14 +13,16 @@ const readJson = require("readjson") const createLogger = require("logsets") const { replaceInterpolateVars,getDataTypeName } = require("@voerkai18n/runtime") const { findModuleType,createPackageJsonFile } = require("./utils") +const stringify = require("./stringify") const logger = createLogger() const { t } = require("./languages") -// 捕获翻译文本正则表达式一:缺点:当t(xxx,...复杂的表达式时不能正确匹配....) +// 捕获翻译文本正则表达式一: 能匹配完整的t(xx,...)函数调用,如果t函数调用不完整,则不能匹配到 +// 但是当t(xxx,...复杂的表达式时....)则不能正确匹配到,因此放弃该正则表达式 // const DefaultTranslateExtractor = String.raw`\b{funcName}\(\s*("|'){1}(?:((?\w+)::))?(?.*?)(((\1\s*\)){1})|((\1){1}\s*(,(\w|\d|(?:\{.*\})|(?:\[.*\])|([\"\'\(].*[\"\'\)]))*)*\s*\)))` -// 捕获翻译文本正则表达式二: 能够支持复杂的表达式,但是当提供不完整的t函数定义时,也会进行匹配提取 ,比如t +// 捕获翻译文本正则表达式二: 能够支持复杂的表达式,但是当提供不完整的t函数定义时,也会进行匹配提取 const DefaultTranslateExtractor = String.raw`\bt\(\s*("|'){1}(?:((?\w+)::))?(?.*?)(?=(\1\s*\))|(\1\s*\,))` @@ -314,7 +316,7 @@ function updateLanguageFile(fromTexts,toLangFile,options){ // 默认的overwrite if(!["merge","sync"].includes(updateMode)){ - fs.writeFileSync(toLangFile,JSON.stringify(targetTexts,null,4)) + fs.writeFileSync(toLangFile,stringify(targetTexts)) return } let targetTexts = {} @@ -349,7 +351,7 @@ function updateLanguageFile(fromTexts,toLangFile,options){ targetTexts[text] = sourceLangs } }) - fs.writeFileSync(toLangFile,JSON.stringify(targetTexts,null,4)) + fs.writeFileSync(toLangFile,stringify(targetTexts)) } @@ -409,7 +411,7 @@ module.exports = function(options={}){ updateLanguageFile(texts,langFile,options) logger.log(" √ 更新语言文件 : {}",path.relative(outputPath,langFile)) }else{ - fs.writeFileSync(langFile,JSON.stringify(texts,null,4)) + fs.writeFileSync(langFile,stringify(texts)) logger.log(" √ 保存语言文件 : {}",path.relative(outputPath,langFile)) } } diff --git a/packages/tools/languages/translates/default.json b/packages/tools/languages/translates/default.json index eaf3cab..5e74769 100644 --- a/packages/tools/languages/translates/default.json +++ b/packages/tools/languages/translates/default.json @@ -1,15 +1,21 @@ { - "支持的语言\t: {}": { - "en": "Supported Languages\t: {}", + "工程项目所在目录" : { + "en" : "Project Directory", + "$file": [ + "index.js" + ] + }, + "支持的语言\\t: {}": { + "en" : "支持的语言\\t: {}", "$file": [ "compile.command.js", "extract.plugin.js" ] }, - "工程项目所在目录": { - "en": "Project Directory", + "保存{}\\n" : { + "en" : "保存{}\\n", "$file": [ - "index.js" + "stringify.js" ] } } \ No newline at end of file diff --git a/packages/tools/stringify.js b/packages/tools/stringify.js index b79f864..788d1ee 100644 --- a/packages/tools/stringify.js +++ b/packages/tools/stringify.js @@ -1,3 +1,33 @@ +/** + * 实现将{}转化为字符串 + * + * 为什么不使用JSON.stringify? + * + * 假设有这样的翻译内容 + * { + * "保存{}\n": "Save{}\n", + * } + * 这个内容中包含了转义字符\n,JSON.stringify会将\n转义为\\n + * 因此,在保存后文件中就变成: + * { + * "保存{}\\n": "Save{}\n", + * } + * 这个转义方式比较不符合我们的预期,更关键的是,在require("cn.js")时, + * 得到的是: + * { + * "保存{}\\n": "Save{}\n", + * } + * 这样当我们调用t函数时就会找不到对应在的key + * + * 问题的关键就在于,JSON.stringify对转义字符的处理不能符合我们的要求。 + * + * 因此,不得不自己来处理转义字符. + * + * 使用objectToString方法后,就可以确保在翻译文件中的转义字符能按预期的方式工作。 + * + * + * + */ const { isPlainObject } = require("./utils") /** @@ -10,15 +40,16 @@ const { isPlainObject } = require("./utils") * @returns */ function escape(str){ - return str.replaceAll("\t","\\t") + return str.replaceAll('\\','\\\\') + .replaceAll("\t","\\t") .replaceAll("\n","\\n") .replaceAll("\b","\\b") .replaceAll("\r","\\r") .replaceAll("\f","\\f") - .replaceAll("\\","\\\\") .replaceAll("\'","\\'") .replaceAll('\"','\\"') .replaceAll('\v','\\v') + } /** * 获取字符串的长度,中文算两个字符 @@ -62,7 +93,7 @@ function objectToString(obj,{indent=4,alignKey=true}={}){ } results.push(item) }) - endChar =" ".repeat((level-1) * indent) + ( last ? "]" : "]") + endChar =" ".repeat((level-1) * indent) + "]" return beginChar + results.map(item=>{ return `${" ".repeat(level * indent)}${item}` }).join("\n") + endChar @@ -73,7 +104,7 @@ function objectToString(obj,{indent=4,alignKey=true}={}){ let alignIndent = 0 Object.entries(node).forEach(([key,value],index)=>{ const isLastItem = index ===length-1 - alignIndent = Math.max(getStringWidth(key),alignIndent) + alignIndent = Math.max(getStringWidth(escape(key)),alignIndent) let item = [`${indentSpace}"${escape(key)}"`,value] if(Array.isArray(value) || isPlainObject(value)){ item[1] = nodeToString(value, level,isLastItem) @@ -92,10 +123,10 @@ function objectToString(obj,{indent=4,alignKey=true}={}){ } results.push(item) }) - endChar =" ".repeat((level-1) * indent) + ( last ? "}" : "}") + endChar =" ".repeat((level-1) * indent) + "}" return beginChar + results.map(item=>{ if(alignKey){ - return `${item[0]}${ " ".repeat(alignIndent-getStringWidth(item[0].trim())+2)}: ${item[1]}` + return `${item[0]}${" ".repeat(alignIndent-getStringWidth(item[0].trim())+2)}: ${item[1]}` }else{ return `${item[0]}: ${item[1]}` } @@ -104,8 +135,7 @@ function objectToString(obj,{indent=4,alignKey=true}={}){ } return nodeToString(obj,0,true) -} -module.exports = { - objectToString, - getStringWidth -} +} +module.exports = objectToString + +