Vue2+vue-i18n实现国际化
整个功能依赖于vue-i18n插件,通过 i18n.locale 来显示对应语言的文本内容。
首先安装插件
npm install vue-i18n@8.28.2
yarn add vue-i18n@8.28.2
在main.js中配置插件
import VueI18n from 'vue-i18n'
import { getLanguage } from './api/Language'
Vue.use(VueI18n)
//默认中文
const savedLanguage = localStorage.getItem('language') || 'zh-CN';
const i18n = new VueI18n({
locale: savedLanguage,
messages: {} // 初始化为空对象
})
async function initAppLanguage() {
const [err, { Result: res }] = await getLanguage(savedLanguage);
if (!err && res) {
const backendLang = JSON.parse(res).message;
i18n.setLocaleMessage(savedLanguage, backendLang);
}
}
initAppLanguage();
这里的getLanguage 是获取后端语言的接口方法
在全局配置了i18n以及网页启动获取语言包并且配置语言,本地不需要配置lang文件
创建语言切换组件
编辑
<a-dropdown :trigger="['click']" class="language-switch" style="padding-right: 15px;">
<a class="ant-dropdown-link" @click="e => e.preventDefault()">
{{ currentLanguageName || $t('切换语言') }} <a-icon type="global" />
</a>
<a-menu slot="overlay" @click="changeLanguage">
<a-menu-item v-for="item in languageList" :key="item.Code">
{{ item.Name }}
</a-menu-item>
</a-menu>
</a-dropdown>
在模板中使用 a-dropdown 和 a-menu 组件创建下拉菜单,通过 v-for 遍历 languageList 生成语言选项,其中currentLanguageName 意味着currentLanguageName 通过计算属性从 languageList 中匹配当前选中的语言名称,$t()指的是vue-i18n的方法。
语言切换逻辑
async changeLanguage({ key }) {
const [err, { Result: res }] = await getLanguage(key)
if (!err && res) {
// 直接使用后端返回的语言数据,不加载本地文件
const backendLang = JSON.parse(res).message;
this.$i18n.setLocaleMessage(key, backendLang);
this.$i18n.locale = key;
localStorage.setItem('language', key);
}
}
该方法通过调用 getLanguage 接口获取对应语言的翻译数据,并更新i18n配置
- 调用后端接口获取指定语言的翻译数据
- 使用 this.i18n.locale 切换当前语言
- 将选中的语言代码存储到localStorage中,以便下次页面加载时恢复。
静态文本翻译
在切换语言后如何另其他的部分实现翻译呢
编辑
编辑
静态文本
{{$t('示例')}}
其他场景(输入提示语)
:placeholder="$t('用户名')"
动态文本:
表头数据
:tab="$t(item.title)"
{{(userInfo.userCode)}}
data()中的配置我这里是翻译失败了,有大佬解决可以分享一下
data(){
return [
{
title: "标题",
dataIndex: "title",
scopedSlots: { customRender: 'name' },
},
{
title: "类型",
width:150,
dataIndex: "typeName",
},
{
title: "接收时间",
width:200,
dataIndex: "receivedTime",
},
];
}
在合理直接用$t()去包裹会无法识别,也可以尝试在当前页面引用i18n的插件去翻译
另一种场景
{{ parent.$t(props.name) }}
函数式组件声明为template functiona , 没有实例化的Vue对象 ,因此无法通过 this 访问组件实例
常规组件中使用的 this.$t() 在此处不可用,必须通过其他方式获取i18n实例
当用了functional来包裹了组件
<template functional>
<!-- 组件内容 -->
</template>
- parent 是函数式组件的内置参数,指向 父组件的Vue实例
- 通过 parent.parent.$t()
为什么不直接使用$t
- 函数式组件没有 this 上下文,无法直接访问t会报错(找不到该方法)
- 必须显式通过 parent 访问父组件的i18n实例
选择前端不配置文件的原因
实现方式
传统静态翻译
本项目动态翻译
翻译数据位置
前端JSON文件
后端数据库
更新方式
需修改文件并重新部署
后端直接更新,前端无感刷新
加载时机
应用打包时加载
运行时动态加载
灵活性
低(需前端发版
高(可随时更新)