想法来源于工做需求,最后倒腾出一个国际化工做流,指望是这样的:vue
1. 自动化处理国际化文案(表现为转义翻译人员给到的文件处理成技术人员所识别的文件)node
2. 转化后的国际化文件可以按需加载,实现懒加载的功能webpack
综上,实现以上需求所涉及知识点:nodejs, webpackweb
本文只记录文件实现懒加载功能,至于国家化文案转换若是须要的告知。那么,就开始啦。
先上实际效果图:框架
以上即是最终效果,有兴趣的能够继续往下看this
Q: 首先有这样一个HTML文本,思考如何讲要替换的文字进行国际化?spa
<section> <div class="icon-bg"></div> <div id="create" class="lx-button lx-button-black">Create wallet</div> <div id="import" class="lx-button">Import wallet</div> <button id="cn">zh-cn</button> <button id="hant">zh-hant</button> <br> </section>
...: 经过观察了vue 和angular的国际化方案,最后决定在元素上增长一个标识,用来识别该元素须要作国际化,思路就是经过document.querySelectorAll()选择全部具备i18n类的元素翻译
A: 效果以下3d
有了标识符后,怎么才能替换文字?思路是这样的:code
如何替换文字? -> 替换什么语言的文字 ? -> 替换的内容具体是什么?
一路逆推过去:
1. 替换的内容具体是什么?
替换的内容考虑到懒加载,因此通常对于相同的字段的文案都会按照不一样国家分开来(此处,参考平时用的angular 和vue框架)
因此,中文文案和繁体文案分红了两个文件夹存放,存放以下:
(PS: 我的习惯会把文案相关文件放入叫作i18n的文件夹中)
此时,便解决了替换的内容具体是什么 。
2. 替换什么语言的文字?
语言确定是在页面加载的时候获取的,并且是不固定的,因此在初始化国际化的时候确定是须要明确指定的,而且,为了方便检索,一般国际化文件夹里面会根据不一样语言的标识码进行划分,可是有些国家比较特别公用一种文字,好比新加坡的和香港的和台湾的就都是繁体,因此咱们确定不会sasa的去创建三个繁体的国际化文案的,因此,这里须要统一入口作这种需求处理;
3. 如何替换文字?
反推到最后一步,很显然,获取了须要国际化的元素以后,根据指定的替换的语言去获取相应的资源文件,而后并把资源文件中的字段替换掉页面上的文案
具体代码以下:
export class TinaI18n { constructor (obj){ this.currentLang = obj['currentLang']; this.useFileName = obj['useFileName']; } // 设置当前国际化语言 setLang(){ if(/^zh/i.test(this.currentLang)){ if(/^zh[-—](cn|SG)/gi.test(this.currentLang)){ this.currentLang = 'zh-cn'; }else { this.currentLang = 'zh-hant'; } }else { this.currentLang = this.currentLang.slice(0,2).toLowerCase(); } } // 获取当前国际化语言翻译文案 static getI18nFile(fileUrl){ return import(/* webpackIgnore: true */ fileUrl).then(({default: ctx}) => { return ctx; }) } // 变换国际化 setInnerHtml(lang){ lang && (this.currentLang = lang); let ele = document.querySelectorAll('.i18n'); if (!(ele.length > 0)) { return new Error('请检查class是否有添加i18n'); } this.setLang(); TinaI18n.getI18nFile(`${window.location.href}i18n/${this.currentLang}/${this.useFileName}.js`).then(ctx => {for (let i = 0; i < ele.length; i++) { if (this.currentLang && ctx) { if (!ele[i].getAttribute('placeholder')) { ele[i].innerText = ctx[ele[i].getAttribute('data-i18n')]; } } else { if (!(ctx)) { console.error('获取文案失败: 路径指定错误? 文件不存在?'); return } } } }).catch(err => { console.log('err', err); }); } }
如何使用?
import {TinaI18n} from "./i18n/TinaI18n"; window.onload = function () { // 实例化国际化 const tinaI18n = initI18N('zh-hant', 'add'); // 简体中文 document.querySelector('#cn').addEventListener('click', ()=>{ tinaI18n.setInnerHtml('zh-cn'); }); // 繁体中文 document.querySelector('#hant').addEventListener('click', ()=>{ tinaI18n.setInnerHtml('zh-hant'); }) }; // 初始化国际化 function initI18N(currentlang, currentFile) { const tinaI18n = new TinaI18n({ currentLang: currentlang, useFileName: currentFile }); tinaI18n.setInnerHtml(); return tinaI18n; }
这里建立了一个专门作国际化的类,经过实例化这个类,传入语言代码(一种语言标识)和文件名称,调用setInnerHtml(),对页面上的元素进行替换,注意,这个功能只能替换标签里的文案,像placehoder要新写一个方法,像变量也是要写一个方法
下一篇更新勇于动态加载webpack的配置