4

近期在重构我的开源项目 iMap,想着要是能做成一个国际化的项目就好了,于是我在我的后端服务以及前端都引入了 i18n

后端配置

我用的是阿里系的 Egg.js Node 框架来提供后台服务,由于框架的开源插件中已经含有 egg-i18n,本着不重复造轮子的心态,于是直接上手。

首先打开 config/config.default.js 来设定 i18n 的配置项:

  exports.i18n = {
    // 默认中文
    defaultLocale: 'zh-CN', 
    // // URL 参数,默认 'local' 改为 'lang'
    queryField: 'lang', 
    // cookie 名称
    cookieField: 'lang',
    // cookie 时长
    cookieMaxAge: '1y',
  };

其中,他们的彼此之间的权重是 query > cookie > headers

配置好 config 文件之后,需要在 config 文件夹中新增一个 local 文件夹,里面放上项目的语言包,如果只有中英文,那么可以是这样的

.
├── config.default.js
├── config.local.js
├── config.prod.js
├── config.unittest.js
├── locale
│   ├── en-US.js
│   └── zh-CN.js
└── plugin.js

当然也可以使用 json 文件,详情见 egg-i18n 文档

我为了偷懒,直接使用了英文格式作为 key,像这样

// en-US
module.exports = {
  // error_handler
  'Not Found': 'Not Found',
  'Authentication Error': 'Authentication Error',
  'Server Error': 'Server Error',
  ...
};
// zh-CN
module.exports = {
  // error_handler
  'Not Found': '错误 URL',
  'Authentication Error': '权限错误',
  'Server Error': '服务器错误',
  ...
};

在项目中,例如我们需要返回 Not Found 只需要使用 ctx.__('Not Found') 就可以了,框架会自动根据当前请求语言来返回对应的预设语言包

前端配置

后端都集成了 i18n ,作为老本行的前端当然也要配置,先看看效果

zh-CN

en-US

本项目使用了 vue ,所以拿 vue 来进行举例

首先引入 vue-i18n

// main.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'

const i18n = new VueI18n({
  // 默认中文
  locale: 'zh-CN',
  messages: {
    // 语言包路径
    'zh-CN': require('@/common/lang/zh'),
    'en-US': require('@/common/lang/en')
  }
})

new Vue({
  components: { App },
  // 这里别漏了
  i18n,
  template: '<App/>'
}).$mount('#app')

再在 common 文件夹中新建 lang 文件夹以及对应的语言包

# /src/common
.
└── lang
    ├── en.js
    └── zh.js

语言包内容示例

// en-US
export const m = {
  login: {
    input_email: 'Please input email address',
    input_password: 'Please input password (4 - 25)',
    submit: 'Signin',
    github: 'Signin with ',
    reset: 'Lost your password ?',
    register: 'Signup now'
  },
// zh-CN
export const m = {
  login: {
    input_email: '请输入邮箱',
    input_password: '请输入密码(4 - 25位)',
    submit: '登录',
    github: 'GitHub ',
    reset: '忘记密码 ?',
    register: '立即注册'
  },
}

这样我们就引入语言包成功,接下来是切换语言示例,在组件 methods 中使用 switchLang 方法

    switchLang() {
      if (this.localLang === 'zh-CN') {
        this.localLang = 'en-US'
      } else {
        this.localLang = 'zh-CN'
      }
      // 切换语言
      this.$i18n.locale = this.localLang
      // 使用 vuex 存入全局变量
      this.setLang(this.localLang)
    },

template 中,使用 $t('m.你的key') 就可以实现国际化了

但是现在还有一个问题,我们如何在 script 标签中使用 i18n 呢?

利用 this.$i18n.messages[this.$i18n.locale].m.你的key 就可以做到

打通前后端

在我们前后端都分别配置完成后,我们需要前端是中文的时候,对应的后端返回的数据也是中文格式,在这里,我们利用 headers 中的 'Accept-Language' 来进行前后端的语言配对

axios 示例:

axios.post(obj.url, obj.data, {
    headers: {
        'Accept-Language': window.$lang
    }
})

这个 window.$lang 又是什么呢...

为了保证 ajax 配置文件的纯净简洁(其实是我懒)。为了不需要引入 i18n ,我在 vuex 中,将 this.$i18n.local 赋值给了 window 全局变量 $lang

// mutations
const mutations = {
  // 设置 lang
  [types.SET_LANG] (state, data) {
    state.local = data
    window.$lang = data
  }
}

这样我们就可以很轻易的获取到当前语言,从而传给后端返回对应语言的数据

当然,为了数据的持久化存储,建议前端将当前语言配置存储在 localstorage 或者是 cookie 里面,否则刷新页面将会遭到重置


作者主页:https://trevor.top
作者博客:https://blog.trevor.top


Amigooo
764 声望83 粉丝

自以为历尽沧桑,其实刚蹒跚学步;自以为掌握了竞争的秘密,其实远没有竞争的资格