语言: Vue
插件: Vue-i18n
环境: VSCode
本教程主要有以下内容:
- 通用的vue项目国际化解决方案
- 如何组织管理翻译文件
- uniapp国际化的特殊解决方案
1. 通用解决方案
国际化主要有三个步骤:
- 安装并引入插件
- 编写翻译文件
- 使用对象属性代替普通文本
1. 安装并引入
首先安装vue-i18n 这个插件:
npm i vue-i18n
新建一个local 文件夹,里头再建一个index 文件,初始化一个i18n对象:
// src/local/index.js
import Vue from 'vue';
import VueI18n from 'vue-i18n'
import en from './en/index'; //待会会讲到引入翻译文件。这里先暂时不管
import zh from './zh/index';
Vue.use(VueI18n)
// 默认语言
const loadLanguage = 'zh'
const messages = {
"en": en,
"zh": zh,
}
function getLanguage() {
localStorage.getItem('lang') ? null : localStorage.setItem('lang', loadLanguage)
let locale = localStorage.getItem('lang')
if (!(locale in messages)) locale = loadLanguage
return locale
}
const i18n = new VueI18n({
locale: getLanguage(),
messages,
})
Vue.prototype._i18n = i18n
export default i18n
main.js 中引入
/* main.js */
import Vue from 'vue'
import App from './App.vue'
import i18n from './i18n'
new Vue({
render: h => h(App),
i18n
}).$mount('#app')
2. 编写翻译文件
这里就要稍微讲讲了,因为网上大部分都没提及这个问题。
现在我们就来思考一下这个配置文件怎么搞才好.
一种语言只写一个翻译文件,在多人开发时容易造成冲突,而且也不好起名字和维护。 我们一个页面单独配置一个翻译文件固然清晰明了, 但是对于那些经常重复的文字(确定,取消, 是否删除, 正在加载...)要写很多次, 确实比较烦,而且很冗余。
所以我们采用1+多 的形式, 我们可以把常用翻译的抽离成一个公共的文件,这样就会解决冗余的问题, 然后一些页面有许多特有的字段其他页面用不到,那么就给这个页面单独列一个翻译文件,这样就解决了如何命名对象属性,以及对象往哪放的问题, 以及和别人合作开发以防git冲突。
最后把所有的翻译文件都集中到index.js 中,就还是一种语言对应一个文件了。
so, 最终的文件目录是长这样的:
- local
- index.js
- zh //中文翻译
- index.js // 抽离公共的翻译, 并引入所有翻译文件
- page1.js
- page2.js
- something.js
- ......
- en // 英文翻译
- index.js // 抽离公共的翻译,并引入所有翻译文件
- page1.js
- page2.js
- something.js
- ......
所有翻译文件引入到index.js中,然后公共的部分可以直接写在index.js文件中,下面是示例:
// local/zh/index.js
import page1 from "./page1";
import page2 from "./page2";
export default {
page1,
page2,
....,
dialog: {
// 确认
confirm: "确认",
submit: "提交",
// 取消
cancel: "取消",
// 删除
delete: "删除",
// 编辑
edit: "编辑",
// 新增
add: "新增",
// 是否继续删除?
confirmDelete: "确认删除?",
// 设为默认
setDefault: "设为默认",
// 添加成功
addSuccess: "添加成功",
// 修改成功
editSuccess: "修改成功",
},
//其他
。。。。
}
好了,其他国家的语言,就把中文的翻译值改成(英语,日语,俄语啥的)就行,你可以用ai帮你写。
3. 页面中使用
在页面中,我们使用$t() 来替代需要翻译的文案。括号里头接收一个字符串,即对象属性名。 举个栗子;
<!-- 在template中 -->
<el-button>{{ $t('dialog.submit') }}</el-button> // 代替“提交”这个需要翻译的字段。
<script>
methods: {
handleDeleteAddress(id){
let superThis = this;
uni.showModal({
title: this.$t('dialog.delete'),
content: this.$t('dialog.confirmDelete'), // 使用this.$t('xxx')替代文案
confirmText: this.$t('dialog.confirm'),
cancelText: this.$t('dialog.cancel'),
......
},
}
</script>
好的,普通的vue项目国际化解决方案应该就到这了。 接下来我们说说uni-appp 中的国际化。
uni-app 国际化解决方案
对于uniapp我们还是用上述的vue国际化方案,但是还需要改两个地方:一个是底部的导航栏tabBar, 第二个是页面标题navigationBarTitleText 。
修改页面标题
uniapp 他使用json字符串的格式,可能是为了配合pages.json 文件, 因为pages.json 识别不了我们.js 对象的写法,只能识别字符串的写法,也就是官网的写法, 所以更改页面标题,我们得另寻出路。
解决方法:
首先,我们在pages.json文件中,页面标题写翻译文件中对象的key:
"navigationBarTitleText": "pagesTitle.history", //写对象的属性名
在进入页面的时候,我们调用钩子函数,获取当前页面的标题, 然后再调用api,用$t('页面标题') 的形式将页面标题进行转译。
每个页面都要调用钩子函数,emmm, 不会要给每个页面都写一个钩子吧,,,当然不会!! 我们可以使用Mxin 来注册一个全局的钩子就好了。
可以在根目录下创建一个globalMixin.js 的文件,然后附上下面的代码:
// globalMixin.js
export default {
onLoad() {
this.getPageTitle();
},
methods: {
getPageTitle() {
const pages = getCurrentPages();
if (pages.length == 0) return;
const page = pages[pages.length - 1];
// 获取页面标题
const pageTitle = page.$holder.navigationBarTitleText;
uni.setNavigationBarTitle({
// 修改页面标题
title: this.$t(pageTitle),
})
}
}
}
然后main.js中全局混入:
// main.js
import globalMixin from "@/globalMixin.js"
Vue.mixin(globalMixin);
pages.json文件中,我们的页面标题就得写对象的key了:
{
"path": "pages/user/readHistory",
"style": {
"enablePullDownRefresh": true,
"navigationBarTitleText": "pagesTitle.history", //写对象的属性名
}
}
翻译文件中就可以这样写:
// local/zh/index.js
exports default {
.....,
pagesTitle: {
home: '首页',
cart: '购物车',
history: '浏览记录',
.....
}
}
设置tabBar导航栏
// APP.vue
//调用一次性钩子
onLaunch() {
// 动态设置导航栏和标题
uni.setTabBarItem({
index: 0,
text: this.$t("tabBar.home")
});
uni.setTabBarItem(
index: 1,
text: this.$t("tabBar.category")
});
uni.setTabBarItem({
index: 2,
text: this.$t("tabBar.cart")
});
uni.setTabBarItem({
index: 3,
text: this.$t("tabBar.me")
});
}
ok, 大功告成! 希望对你有所帮助或者启发, 如果有更好的解决方案,请多多指点和分享!!