近期在重构我的开源项目 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 ,作为老本行的前端当然也要配置,先看看效果
本项目使用了 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: ' '
}).$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