nuxt.js + vue-i18n开发国际化项目
接到公司项目要做一个国际化的官网、之前一直没有搞过,百度了一下也不是很难;记录一下;
步骤一:安装vue+i18n
npm install vue-i18n 或 yarn add vue-i18n
步骤二:在store文件夹下更新index.js文件
export const state = () => ({
locales: ['en', 'zh'],
locale: 'zh'
})
export const mutations = {
SET_LANG(state, locale) {
if (state.locales.indexOf(locale) !== -1) {
state.locale = locale
}
}
}
步骤三:在plugins文件夹下,添加文件:i18n.js
import Vue from 'vue';
import VueI18n from 'vue-i18n';
Vue.use(VueI18n);
export default ({ app, store }) => {
// Set i18n instance on app
// This way we can use it in middleware and pages asyncData/fetch
app.i18n = new VueI18n({
locale: store.state.locale,
fallbackLocale: 'zh',
messages: {
'en': require('~/locales/en.json'),
'zh': require('~/locales/zh.json')
}
});
app.i18n.path = (link) => {
if (app.i18n.locale === app.i18n.fallbackLocale) {
return `/${link}`;
}
return `/${app.i18n.locale}/${link}`;
}
}
步骤四:在middleware文件夹下,添加文件: i18n.js
export default function ({
isHMR, app, store, route, params, error, redirect
}) {
if (isHMR) { // ignore if called from hot module replacement
return;
} // if url does not have language, redirect to english
else if (!params.lang) {
return redirect('/zh'+route.fullPath);
}
// based on directory structure _lang/xxxx, en/about has params.lang as "en"
const locale = params.lang || 'zh';
store.commit('SET_LANG', locale); // set store
app.i18n.locale = store.state.locale;
}
步骤五:增加locales文件夹;并且创建en.json和zh.json两个文件夹
一定要注意两个json文件分别代表的是中文和英文,对应的key值一点要相同;只有相同的key,才能翻译成功
zh.json
{
"menu":{
"home": "主页",
"news":"新闻动态",
"ecological":"生态联盟",
"solution":"技术优势",
"trials":"加入社区",
"signup":"报名入口"
}
}
en.json
{
"menu":{
"home": "Home",
"news":"News",
"ecological":"Ecological",
"solution":"Solution",
"trials":"Trials",
"signup":"Signup"
}
}
步骤六:配置nuxt.config.js文件
必须添加以下两句,否则无法运行;具体为啥我也不知道!
router: {
middleware: 'i18n'
},
plugins: ['@/plugins/i18n.js'],
步骤七:那我们已经配置完了,不能每次切换语言跑来修改代码吧;我们在页面上创建一个点击事件;用来切换我们的语言;当然我这个是中英双语的;如果你是好几种语言,你可以通过select来控制和选择语言;
这个地方i18n暴漏了一个方法this.$i18n,可以打印一下i18n,里面就包括locale这个语言选择项;
switchLang() {
// console.log(this.$i18n)
if (this.$i18n.locale == "zh") {
this.$i18n.locale = "en";
} else {
this.$i18n.locale = "zh";
}
}
步骤八:页面上使用i18n;
html里面直接使用
<el-button @click="switchLang">{{ $t("btn.switchLang") }}</el-button>
如果是定义到data里面使用:
return {
menu: [
{ path: "/", title: this.$t('menu.home'), disable: false },
{ path: "/news", title: this.$t('menu.news'), disable: false },
]
}
这个时候有一个坑;如果你想直接想用v-for循环到页面上的话;他是不会变得,原因也比较简单:
html中使用{{$t('XXXX')}}的数据就会跟着更新,data中定义的数组就没有更新。
data是一次性生产的,你这么写只能是在 data 初始化的时候拿到这些被国际化的值,并不能响应变化。
官方的解决办法是,建议我们将表达式写到computed属性里(当然也可以写在watch里面去监听),不要写到data里;
那在conputer里面的写法就是:
menu(){
return [
{ path: "/", title: this.$t('menu.home'), disable: false },
{ path: "/news", title: this.$t('menu.news'), disable: false },
]
}
这个时候一定要把原来data里面的数据删除掉或者注释掉;要不然还是不会生效还会报错;
做一个简单的记录,因为项目还没有做完,遇到问题随时回来更新!谢谢大家指教!