结合webpack 一步一步实现懒加载的国际化简易版方案

 想法来源于工作需求,最后倒腾出一个国际化工作流,期望是这样的:

1. 自动化处理国际化文案(表现为转义翻译人员给到的文件处理成技术人员所识别的文件)

2. 转化后的国际化文件能够按需加载,实现懒加载的功能

综上,实现以上需求所涉及知识点:nodejs, webpack

本文只记录文件实现懒加载功能,至于国家化文案转换如果需要的告知。那么,就开始啦。
先上实际效果图:



以上便是最终效果,有兴趣的可以继续往下看

Q: 首先有这样一个HTML文本,思考如何讲要替换的文字进行国际化?

<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: 效果如下

 

 有了标识符后,怎么才能替换文字?思路是这样的:

如何替换文字? -> 替换什么语言的文字 ? -> 替换的内容具体是什么?

一路逆推过去: 
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的配置

 

posted @ 2019-04-28 18:46  承蒙时光  阅读(956)  评论(0编辑  收藏  举报