关于i18n:react项目国际化实现自动装配方案

该计划提供一个外挂式的前端我的项目国际化实现计划,能够反对因为某些起因在一开始没有反对国际化,后续在简直不须要革新原有业务代码的状况下反对国际化。利用构建工具,做到业务开发无感的国际化计划。在国际化开发过程的流程个别为:前端开发工程师在碰到中文时,须要先设计一个编码,通常为了防止编码反复,还须要合乎肯定规定且随着业务迭代越来越简短的编码;而后导入国际化多语言工具函数,调用国际化多语言函数;而后翻译保护国际化配置数据;如果国际化数据是放在数据库中,反对线上动静配置,还须要数据给后端,对立保护在零碎。整个过程简短且须要不同人员协同,极易呈现问题。 如应用react-intl-universal反对国际化: import intl from 'react-intl-universal';// 初始化代码在整个零碎的入口文件时。intl.get('SIMPLE').d('简略');假如开发一个前端转译工具,在碰到代码中的中文时,主动导入国际化的工具函数,主动依照肯定的规定生成编码,将原来的中文代码替换为国际化函数的调用,而后在整个我的项目编译后,收集所有的国际化语言数据,能够间接生成国际化语言的配置文件也好,或者生成肯定的结构化数据用于插入数据库。 依照这个思路,就能够实现一个为我的项目主动拆卸国际化的计划。在该计划中,前端开发工程师开发时无需关注国际化,获取跟不须要国际化反对的我的项目一样的开发体验,能够将精力更多的放在业务开发上。同样该计划为一个根底撑持,挂载式的模式,可能疾速反对一个开始不反对国际化,起初因为倒退,须要面向国内的我的项目。 同样,这个计划着重点是如何主动生成国际化多语言函数的调用代码,对应用某个国际化框架是没有限度的。能够依据理论需要,抉择任何国际化框架,而后对它的应用进行代码转换。 该计划只针对简略的国际化需要,对于一些简单的需要,如金额,日期等,还是须要手动应用一些国际化框架的api。但一个我的项目中,最多的应该还是对于一些简略的展现文本进行国际化反对。 从计划的设计来看,次要是分为两局部: 剖析代码:当碰到中文时,转译为国际化函数调用语句。收集信息:将剖析代码过程中的转换语句的信息收集起来,用于生成配置数据。两个局部别离用两个工具去解决。 代码剖析工具剖析代码能够实现一个babel插件,在转译js代码时进行中文国际化解决。 中文文本,次要是字符串或在模版字符串中,所以只须要对这两种语句进行解析转化即可,也就在babel插件须要解决StringLiteral和TemplateLiteral语句即可。 那么插件的次要构造为: module.exports = (babel) => { visitor: { StringLiteral(path, state) { }, TemplateLiteral: { enter(_path, state) { }, }, },};TemplateLiteral解决起来比较复杂,所以以StringLiteral为例阐明要害逻辑。在StringLiteral语句中剖析字符串是否蕴含中文,用正则判断: StringLiteral(path, state) { const { node } = path; const text = node.value; if (str.search(/[^\x00-\xff]/) === -1) { return; }},如果不蕴含中文,则间接返回不解决。如果蕴含中文,则转换为国际化导入函数(以react-intl-universal库的应用形式): const intlMember = t.memberExpression( t.identifier('intl'), t.identifier('get'), false, false,);// 编码生成,这里间接用中文作为编码。如果怕乱码等问题,// 能够采纳md5码或者或者依据理论规定和文件门路生成编码const codeText = text;const codeTextNode = t.stringLiteral(codeText);// 解决codeTextNode.extra = { rawValue: codeText, raw: `'${codeText.split("'").join('\\\'').split('\n').join('\\\n')}'`,};const intlCall = t.callExpression(intlMember, [codeTextNode]);const memberExpression = t.memberExpression(intlCall, t.identifier('d'), false, false);let fnNode = t.callExpression(memberExpression, [node]);const parentNode = _.get(path, 'parentPath.node');if (t.isJSXAttribute(parentNode)) { fnNode = t.jsxExpressionContainer(fnNode);}path.replaceWith(fnNode);这样对于文本 ...

February 15, 2022 · 2 min · jiezi