diff --git a/packages/demo/utils.demo.js b/packages/demo/utils.demo.js new file mode 100644 index 0000000..48e9427 --- /dev/null +++ b/packages/demo/utils.demo.js @@ -0,0 +1,28 @@ +const { objectToString } = require("../tools/stringify") +const path = require("path"); +const fs = require("fs"); + + +const data = { + name:"张三丰", + age:12, + active:true, + address:[ + "北京市", + "福建省泉州市" + ], + posts:{ + title:"标题", + content:"内容", + //comments:[] + }, + "产品清单":[ + "手机", + "电脑" + ] +} + +const result = objectToString(data) + +console.log(result) + diff --git a/packages/runtime/index.js b/packages/runtime/index.js index b81f32d..d56479f 100644 --- a/packages/runtime/index.js +++ b/packages/runtime/index.js @@ -279,7 +279,7 @@ function getFormatter(scope,activeLanguage,name){ // 缓存格式化器引用,避免重复检索 if(!scope.$cache) resetScopeCache(scope) if(scope.$cache.activeLanguage === activeLanguage) { - if(dataType in scope.$cache.formatters) return scope.$cache.formatters[dataType] + if(name in scope.$cache.formatters) return scope.$cache.formatters[name] }else{// 当语言切换时清空缓存 resetScopeCache(scope,activeLanguage) } @@ -300,7 +300,7 @@ function getFormatter(scope,activeLanguage,name){ /** * 执行格式化器并返回结果 * @param {*} value - * @param {*} formatters + * @param {*} formatters 多个格式化器顺序执行,前一个输出作为下一个格式化器的输入 */ function executeFormatter(value,formatters){ if(formatters.length===0) return value @@ -309,8 +309,8 @@ function executeFormatter(value,formatters){ for(let formatter of formatters){ if(typeof(formatter) === "function") { result = formatter(result) - }else{ - return result + }else{// 如果碰到无效的格式化器,则跳过过续的格式化器 + return result } } }catch(e){ @@ -504,19 +504,13 @@ function translate(message) { }) } - // 由于在编译语言时会使用JSON.stringify进行保存,而JSON.stringify会将\t\n\r转换为\\t\\n\\r的形式 - // 这会导致在翻译时,如果消息中有\t\n\r则会出现翻译错误 - // 所以需要将message再次使用JSON.stringify进行转换才可以匹配 - content = JSON.stringify(content) - content = content.substr(1,content.length-2) - - // 2. 取得翻译文本模板字符串 + // 2. 取得翻译文本模板字符串 if(activeLanguage === scope.defaultLanguage){ // 2.1 从默认语言中取得翻译文本模板字符串 // 如果当前语言就是默认语言,不需要查询加载,只需要做插值变换即可 // 当源文件运用了babel插件后会将原始文本内容转换为msgId // 如果是msgId则从scope.default中读取,scope.default=默认语言包={:} - if(isMessageId(text)){ + if(isMessageId(content)){ content = scope.default[content] || message } }else{ diff --git a/packages/tools/babel-plugin-voerkai18n.js b/packages/tools/babel-plugin-voerkai18n.js index b739244..65184a1 100644 --- a/packages/tools/babel-plugin-voerkai18n.js +++ b/packages/tools/babel-plugin-voerkai18n.js @@ -19,7 +19,7 @@ const fs = require("fs"); const path = require("path"); -const { isPlainObject } = require("../runtime/utils"); +const { isPlainObject } = require("./utils"); const DefaultI18nPluginOptions = { translateFunctionName:"t", // 默认的翻译函数名称 diff --git a/packages/tools/stringify.js b/packages/tools/stringify.js new file mode 100644 index 0000000..b79f864 --- /dev/null +++ b/packages/tools/stringify.js @@ -0,0 +1,111 @@ + +const { isPlainObject } = require("./utils") +/** + * + * JSON.stringify在将一个JSON转化为字符串时会对字符串里面的\t等转义符进行再次转义 + * 导致在使用包含\t等转义符为key时会出现问题 + * + * + * @param {*} obj + * @returns + */ + function escape(str){ + return str.replaceAll("\t","\\t") + .replaceAll("\n","\\n") + .replaceAll("\b","\\b") + .replaceAll("\r","\\r") + .replaceAll("\f","\\f") + .replaceAll("\\","\\\\") + .replaceAll("\'","\\'") + .replaceAll('\"','\\"') + .replaceAll('\v','\\v') +} +/** + * 获取字符串的长度,中文算两个字符 + * @param {*} s + * @returns + */ +function getStringWidth(s){ + let str = String(s) + var realLength = 0, len = str.length, charCode = -1; + for (var i = 0; i < len; i++) { + charCode = str.charCodeAt(i); + if (charCode >= 0 && charCode <= 128) realLength += 1; + else realLength += 2; + } + return realLength; +} + +function objectToString(obj,{indent=4,alignKey=true}={}){ + function nodeToString(node,level,last=false){ + let results = [],beginChar = "",endChar = "" + level++ + if(Array.isArray(node)){ + beginChar = "[\n" + node.forEach((value,index)=>{ + const isLastItem = index ===node.length-1 + let item = value + if(Array.isArray(value) || isPlainObject(value)){ + item = nodeToString(value, level,isLastItem) + }else if(typeof(value)==="string"){ + item = `"${escape(value)}"` + }else if(typeof(value)==="number"){ + item = value.toString() + }else if(typeof(value)==="boolean"){ + item = value.toString() + } + // 如果最后一项 + if(!isLastItem){ + item = item+"," + }else{ + item = item+"\n" + } + results.push(item) + }) + endChar =" ".repeat((level-1) * indent) + ( last ? "]" : "]") + return beginChar + results.map(item=>{ + return `${" ".repeat(level * indent)}${item}` + }).join("\n") + endChar + }else if(isPlainObject(node)){ + beginChar = "{\n" + const length = Object.keys(node).length + const indentSpace = " ".repeat(level * indent) + let alignIndent = 0 + Object.entries(node).forEach(([key,value],index)=>{ + const isLastItem = index ===length-1 + alignIndent = Math.max(getStringWidth(key),alignIndent) + let item = [`${indentSpace}"${escape(key)}"`,value] + if(Array.isArray(value) || isPlainObject(value)){ + item[1] = nodeToString(value, level,isLastItem) + }else if(typeof(value)==="string"){ + item[1] = `"${escape(value)}"` + }else if(typeof(value)==="number"){ + item[1] = `${value.toString()}` + }else if(typeof(value)==="boolean"){ + item[1] = `${value.toString()}` + } + // 如果最后一项 + if(!isLastItem){ + item[1] = item[1]+"," + }else{ + item[1] = item[1]+"\n" + } + results.push(item) + }) + endChar =" ".repeat((level-1) * indent) + ( last ? "}" : "}") + return beginChar + results.map(item=>{ + if(alignKey){ + return `${item[0]}${ " ".repeat(alignIndent-getStringWidth(item[0].trim())+2)}: ${item[1]}` + }else{ + return `${item[0]}: ${item[1]}` + } + }).join("\n") + endChar + } + + } + return nodeToString(obj,0,true) +} +module.exports = { + objectToString, + getStringWidth +} diff --git a/packages/tools/utils.js b/packages/tools/utils.js index abddae8..9ef8a54 100644 --- a/packages/tools/utils.js +++ b/packages/tools/utils.js @@ -111,74 +111,12 @@ function createJsModuleFile(filename,defaultExports={},namedExports={},moduleTyp } } -/** - * - * JSON.stringify在将一个JSON转化为字符串时会对字符串里面的\t等转义符进行再次转义 - * 导致在使用包含\t等转义符为key时会出现问题 - * - * - * @param {*} obj - * @returns - */ -function escape(str){ - return str.replaceAll("\t","\\t") -} - -function ObjectToString(obj,{indent=4,alignKey=true}={}){ - function nodeToString(node,level,last=false){ - let results = [],beginChar = "",endChar = "" - level++ - if(Array.isArray(node)){ - beginChar = "[\n" - node.forEach((value,index)=>{ - - }) - endChar =" ".repeat((level-1) * indent) + ( last ? "]" : "]\n") - }else if(isPlainObject(node)){ - beginChar = "{\n" - const length = Object.keys(node).length - const indentSpace = " ".repeat(level * indent) - let alignIndent = 0 - Object.entries(node).forEach(([key,value],index)=>{ - const isLastItem = index ===length-1 - alignIndent = Math.max(getStringWidth(key),alignIndent) - let item = [`${indentSpace}"${key}"`,value] - if(Array.isArray(value) || isPlainObject(value)){ - item[1] = nodeToString(value, level,isLastItem) - }else if(typeof(value)==="string"){ - item[1] = `"${value.toString()}"` - }else if(typeof(value)==="number"){ - item[1] = `${value.toString()}` - }else if(typeof(value)==="boolean"){ - item[1] = `${value.toString()}` - } - // 如果最后一项 - if(!isLastItem){ - item[1] = item[1]+"," - }else{ - item[1] = item[1]+"\n" - } - results.push(item) - }) - endChar =" ".repeat((level-1) * indent) + ( last ? "}" : "}\n") - return beginChar + results.map(item=>{ - if(alignKey){ - return `${escape(item[0])}${ " ".repeat(alignIndent-getStringWidth(item[0].trim())+2)}: ${escape(item[1])}` - }else{ - return `${escape(item[0])}: ${escape(item[1])}` - } - }).join("\n") + endChar - } - - } - return nodeToString(obj,0,true) -} - module.exports = { importModule, findModuleType, - createPackageJsonFile + createPackageJsonFile, + isPlainObject } diff --git a/test/app.test.js b/test/app.test.js index e63dd06..581ec5a 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -1,13 +1,11 @@ /** * 测试demp app的语言运行环境 */ - const compile = require('../packages/tools/compile.command'); + const i18n = require('../packages/tools/languages'); const path = require("path") -test("导入多语言包",async ()=>{ - await compile(path.resolve(__dirname,'../packages/demo/apps/app/languages'),{moduleType:"commonjs"}) - const { t,scope,languages } = require(path.join(__dirname,'../packages/demo/apps/app/languages/index.js')); +test("导入多语言包",done=>{ expect(t).toBeFunction() }) \ No newline at end of file