仅供参考
前端技术之---应用国际化(vue-i18n)
- 一、前言
- [二、Vue.js 的国际化插件 --- vue-i18n](#二、Vue.js 的国际化插件 --- vue-i18n)
- [三、vue-i18n 的基础用法](#三、vue-i18n 的基础用法)
-
- [1、安装 vue-i18n](#1、安装 vue-i18n)
- 2、自定义语言包
- 3、进行统一管理配置
- [4、全局注册 i18n 实例](#4、全局注册 i18n 实例)
- 5、在组件中使用vue-i18n
- 四、语言切换
- 五、进阶用法
一、前言
当我们编写一个网页 / 前端应用,使用的一般都是中文,因为我们是中国人,此时,所使用 / 展示的语言是写死的,无法切换;如果这个网页 / 前端应用要在国外打开,如英国、美国等地方,他们使用的并不是中文,而是其他语言,如果网页仍然展示中文的话,就会造成阅读障碍
在不同地区 / 国家 / 环境,网页 / 前端应用能够切换不同的语言
,就实现了应用的国际化
,或者称为实现多语言支持
二、Vue.js 的国际化插件 --- vue-i18n
vue-i18n
是 Vue.js 的国际化(i18n,即 "internationalization" 的缩写)插件,专门用于在 Vue 应用中实现多语言支持
。它允许开发者轻松地管理不同语言的文本内容,并根据用户的语言偏好动态切换显示语言
。
三、vue-i18n 的基础用法
1、安装 vue-i18n
bash
npm install vue-i18n --save
- -save
:会把包添加到 package.json 文件的 dependencies 字段中。这意味着在生产环境运行项目时,这些包是必需的(npm 5.0 以后的版本可加可不加)
2、自定义语言包
创建 locales 文件夹,在其下新建两个文件:zh-cn.js(中文简体语言包)、en.js(英文语言包)
当然还可以创建其他语言包,根据需求所定,如jp.js(日文语言包)、zh-tw(中文繁体语言包)等等
javascript
//zh-cn.js
export default {
form: {
user: "用户名",
password: "密码",
},
}
//en.js
export default {
form: {
user: "Name",
password: "Password",
},
}
3、进行统一管理配置
在 locales 文件夹下创建index.js文件,写入以下内容:
javascript
import { createI18n } from "vue-i18n"
import zhLocal from "./zh-cn"
import enLocal from "./en"
const messages = {
"zh-cn": zhLocal,
en: enLocal,
}
const i18n = createI18n({
legacy: false, // 设为 false 以支持 Composition API
locale: "zh-cn", // 设置默认语言
globalInjection: true, //全局模式,可以直接使用$t
messages,
})
window.$t = i18n.global.t //将国际化(i18n)的翻译函数 t 挂载到全局的 window 对象上
export default i18n
关键点解释:
1)import zhLocal from "./zh-cn" 引入具体的语言包
2)messages是一个消息字典,是一个对象,不同的字段对应不同的语言包,为后续创建 i18n 实例做准备
3)createI18n
是一个函数,用于创建并配置 i18n 实例,接收一个对象:
- legacy字段 :决定使用哪种
API 模式
来开发国际化功能
1、取值为false(推荐),表示采用 Composition API 模式,完全兼容 Vue 3 的 Composition API 风格;必须通过 i18n.global 访问全局 API(如 t、locale 等)
2、取值为true:表示采用 Options API 模式,兼容 Vue 2 的使用习惯;可以通过 this.$t 直接在组件中访问翻译方法(全局注入)
- locale字段:设置默认语言
1、取值为"zh-cn"为默认中文,取值为"en"默认为英文(
必须加双引号
)2、建议与messages中的字段相同
- globalInjection字段:设置是否将 i18n 的翻译函数注入到全局
1、翻译函数(
t函数
)就是起到一个翻译的作用,因为我们写代码的时候都是写入语言包中的字段,翻译函数可以将字段翻译为对应的文本2、开启后可在每个组件中直接使用翻译函数,无需重新引入翻译函数才能使用
- messages字段:决定了可以使用的语言包有哪些
4)window.$t = i18n.global.t
:将 Vue-i18n 的翻译函数 t 挂载到浏览器的全局对象 window 上,使得在 Vue 组件外部也能使用国际化翻译功能
可能看了上面之后,会对这里产生疑问,我把globalInjection字段设置为 true 全局注入,不就都可以使用翻译了吗,为什么还要把翻译函数挂载到 window 上?
简单的说,如果只设置了上面的createI18n,翻译功能只能在元素中起作用(在vue指的是<template></template>所包裹的部分),而在 JS 中是无法使用翻译的;只有把翻译函数挂载,才能在 JS 中实现翻译;可以理解为 window.$t 就是翻译函数,只不过只适用于 JS
javascript
//只设置createI18n:
<div>{{ $t("form.user") }}</div> //可正确翻译
console.log($t("form.user")) //报错
虽然window.$t 和 $t 的功能相同,但是不能混在一起用,在元素中使用 $t,在 JS 中使用 window.$t
4、全局注册 i18n 实例
javascript
import { createApp } from "vue"
import i18n from "./locales/index"
import App from "./App.vue"
const app = createApp(App)
app.use(i18n)
app.mount("#app")
5、在组件中使用vue-i18n
javascript
<script setup>
console.log(window.$t("form.user")); //输出用户名
</script>
<template>
<div>
{{ $t("form.user") }}
</div>
</template>
四、语言切换
javascript
<script setup>
import { useI18n } from "vue-i18n";
const { locale } = useI18n();
const changeLan = (lang_type) => {
localStorage.setItem("language", lang_type); // 存一下现在的语言
locale.value = lang_type; // 直接赋值
};
</script>
<template>
<div>
{{ $t("form.user") }}
</div>
<button class="first" @click="changeLan('zh-cn')">切换成中文</button>
<button class="second" @click="changeLan('en')">切换成英文</button>
</template>
实现的效果:点击按钮即可切换语言
useI18n() 返回的是当前 i18n 实例的全局状态
(默认情况下,useScope 为 'global')。locale.value = lang_type 会直接修改 i18n 实例的全局语言设置
五、进阶用法
如果你都掌握了上面的方法,那么只是学会了很基础的用法,接下来都是基于实际应用场景的使用,是更为常见的用法:
1、与响应式变量结合使用
当我想要在一个div盒子中写上"已经做完了10道题目",可以直接设置语言包中的 count: "已经完成了10道题目" ,然后在 div 中加上:
javascript
<div>{{ $t("count") }}</div>
但是,如果一分钟可以完成一道题目,那么每过一分钟,数字就会发生变化,而上面的 count 是写死的,我们只能不断的添加 count1: "已经完成了11道题目"、count2: "已经完成了12道题目"...当有上千万个数字时,很明显代码量将非常恐怖
解决办法:承接变量值
在语言包中,我们将其设置为:
javascript
done:"已经完成了{ sum }道题目"
对应的描述方式也要修改:
javascript
<script setup>
import { ref } from 'vue'
const count = ref(10) //假设count可以实现每分钟加一,这里不做展示
</script>
<template>
<div>
{{ $t("done", {sum: count}) }}
</div>
</template>
通过上面的写法,sum承接了count的值,所以当count改变时,sum也会发生改变,把原本需要多行的代码压缩到了一行