前端国际化的思考与实践

1,448 阅读5分钟

万丈苍穹水更深,无限乾坤尽眼中

写在开头

之前一直听别人在后台模板中或者博客模板中提到国际化,i18n等,但是自己只是百度谷歌浏览了解一下,并未深入,直到上月公司开始拓展海外市场。我这边就提前考虑到业务这边会有国际化的需求,就开始进行详细的技术调研。

官网英文版

最开始是想把公司的主产品的官网进行英文版改造。官网是php+webpack+html+css+jq进行开发的。

当时的第一个思路是在git上且一个语言分支,通过jquery-i18n库进行改造,两个分支的language配置不同就行了。但是后来想了一下,这样如果有更新,分支同步也挺麻烦,总是需要改动language配置。

然后就有了第二个思路,因为反正官网也不需要把切换语言环境的功能放在主页上,而是不同的语言版本都投放到特定的渠道上,就通过编译命令传参的方式将不同的环境通过编译命令传入到编译后的包中。

这里就需要解决两个问题,一是编译命令传参,一是webpack注入全局变量。

webpack注入全局变量,在我之前的文章中有提到,感兴趣的可以去翻一翻。这里贴一下编译命令传参,其实也很简单:

  // 1、通过--argv=value来传递参数
  // 2、通过cross-env CONST_ARGV=value来传递参数
  
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build:cn": "npx webpack --config build/webpack.config.js --mode production --lan=zh-cn",
    "build:en": "cross-env TARGET_LAN=en npx webpack --config build/webpack.config.js --mode production"
  },

 // 1、通过process.argv获取参数
 // 2、通过process.env.CONST_ARGV获取
console.log( process.argv)
console.log(process.env.TARGET_LAN)

拿到参数后注入到生产环境即可,然后使用i18n配置

jQuery.i18n.properties({ // 加载资浏览器语言对应的资源文件
                name: 'lan', // 资源文件名称
                path: './i18n/', // 资源文件路径
                cache: true,
                language: lan, // 传入全局语言
                mode: 'map', // 用 Map 的方式使用资源文件中的值
                callback: function() { // 加载成功后设置显示内容
                      
                                }
                        });

然后配合CI或者找运维兄弟帮一下忙,写一下部署命令就可以分别编译不同的语言版本上线了。 就这样,果然过了没几天,老板就让改官网,很快就上线了,顺便摸了半天鱼,写了篇总结。

移动端国际化

随着官网上线,我们的APP的IOS及安卓端也开始搞国际化,而且搞得不只一个客户端,是有很多个客户端,然后面对我们统一的前端平台,国际化似乎有点难度。不过坑大家早就踩过了,网上搜了一下vue相关的国际化组件,很快找到了vue-i18n。本身vue-i18n很简单,文档也很全。这里简单贴一下我的配置:语言库+实例化+引入

语言库

Image.png

语言库内容
 // 这里贴一下ja.js 和 zh-Cn.js的部分内容 返回一套map语言
 export default {
  // #region 测试
  test: '試験',
  // #endregion
  // #region common
  common: {
    cancel: '取消',
    confirm: '決定',
    submit: '送付',
    view: '確認',
    success: '成功',
    fail: '失敗',
    mobile: '携帯電話番号',
    code: '認証コード',
    getCode: '認証コード取得',
    requireMobile: '携帯電話番号を入力してください',
    requireCode: '認証コードを入力してください',
    vipMember: 'VIP会員',
    svipMember: 'SVIP会員',
    expand: '展開',
    collapse: 'しまう'
  },
  // #endregion
  // #region 单位
  unit: {
    day: '日間',
    minute: '分',
    hour: '時間',
    s: '個',
    score: '分',
    year: '年',
    month: '月',
    times: '回'
  }
  // #endregion
}


export default {
  // #region 测试
  test: '测试',
  // #endregion
  // #region common
  common: {
    cancel: '取消',
    confirm: '确定',
    submit: '提交',
    view: '查看',
    success: '成功',
    fail: '失败',
    mobile: '手机号',
    code: '验证码',
    getCode: '获取验证码',
    requireMobile: '请输入手机号',
    requireCode: '请输入验证码',
    vipMember: 'VIP会员',
    svipMember: 'SVIP会员',
    expand: '展开',
    collapse: '收起'
  },
  // #endregion
  // #region 单位
  unit: {
    day: '天',
    minute: '分钟',
    hour: '小时',
    s: '个',
    score: '分',
    year: '年',
    month: '月',
    times: '次'
  }
  // #endregion
}
实例化
import VueI18n from 'vue-i18n'
import Vue from 'vue'
import en from './lang/en'
import zhCn from './lang/zh-CN'
import zhHk from './lang/zh-HK'
import vi from './lang/vi'
import ja from './lang/ja'
Vue.use(VueI18n)
export default new VueI18n({
  locale: 'zh-CN',
  fallbackLocale: 'zh-CN',
  messages: {
    'zh-CN': zhCn,
    'zh-HK': zhHk,
    'en': en,
    'vi': vi,
    'ja': ja
  }
})
引入
const gloabVue = new Vue({
  el: '#app',
  template: '<App/>',
  components: {
    App
  },
  store,
  router,
  i18n
})

基础库搭好之后就是如何切换配置和调用了,调用很简单文档就行基本就是字符串方法替换函数的调用

  // 模板调用
  <span class="unit">{{$t('unit.day')}}</span>
 // 逻辑调用
   this.$toast(this.$t('unit.day'))

由于我们的项目放到移动客户端的webview的,所以我们的语言环境其实是需要和客户端保持一致的,因此我们需要从客户端那边获取到语言标志,然后进行语言包替换,我们可以写一个jsbridge方法用来获取用户的语言标记,jsbridge相关方法可以参考我之前的文章,这里贴一下封装的调用:

// App.vue/mounted
  mounted() {
    // 设置语言
    this.GetAppUserInfo(userinfo => {
      this.$i18n.locale = userinfo.lan // lan需要和服务端客户端进行约定协议 和语言库文件名保持一致
    })
  },

自此,国际化改造完毕。另外关于TDK相关的国际化实际上同理,也可以在初始化的时候一次搞定,这里不多赘述

总结

国际化本质上就是字符串替换,在应用中主要考量实施的环境和业务的需求,宏观上只要有语言包,那么需要考虑的就是语言环境在什么时候获取,像本文中,可以在编译时获取,可以在初始化主页面时候获取,也可以像很多博客中一样在运行时通过按钮进行切换。

另外需要说明的是字符串替换其实可以解决很多问题,最基本的是替换文字,也可以替换资源如图片视频等,还可以替换请求域名等等,这些都可以在项目中灵活改变。当我们思路打开,简单的东西可以解决很多复杂的事情。

本文4个月前就开头了,今天才写完,主要是最近大作太多,刚肝玩,开始学习总结。