【i18n】使用 vue-i18n 实现国际化多语言切换
发布时间:2024-02-11 21:05:00

学习关键语句:
i18n 进行多语言国际化
使用 vue-i18n 语言切换

写在前面

由于以前没有过国际化的经验 , 所以第一次遇到的时候还是有点懵逼的 , 赶紧在网上转了一大圈 , 分享给大家一点点我的使用经验

我写这篇文章的目的是大家看了之后跟着步骤走就能完成多语言切换的任务

提示 : 本文演示的内容基于 使用 vite 创建的 vue3 项目

开始

安装与配置

  1. 使用 npm 或者 yarn 命令进行安装
npm install vue-i18n
yarn add vue-i18n

本文所使用的 vue-i18n 版本号为 ^9.2.2
在网上搜了搜 , 一般认为版本大于 9 就可以使用了 , 我没尝试过低版本的 , 麻烦

  1. 配置语言文件

在 src 目录下新增一个 langs 文件夹 , 名字你可以自己取 , 暂时只考虑中英文语言切换 , 新建三个文件 , 分别是

主文件 index.js
中文文件 zh.js
英文文件 en.js
< 图中使用了 ts 但是无妨一会儿会去掉 >

index.js

import { createI18n } from 'vue-i18n'		//引入vue-i18n组件
// 引入同级目录下所有文件 , 我们的目的是引入中文文件 zh.js 和英文文件 en.js
const modules = import.meta.globEager('./*')

// 获取所有语言的详细内容
function getLangAll() {
    let message = {}
    getLangFiles(modules, message)
    return message
}

// 遍历获取每个文件中语言的详细内容
function getLangFiles(mList, msg) {
    for (let path in mList) {
        if (mList[path].default) {
            //  获取文件名
            let pathName = path.substr(path.lastIndexOf('/') + 1, 5)
            if (msg[pathName]) {
                msg[pathName] = {
                    ...mList[pathName],
                    ...mList[path].default
                }
            } else {
                msg[pathName] = mList[path].default
            }
        }
    }
}
// 注册i8n实例并引入语言文件
const i18n = createI18n({
    legacy: false,
    locale: 'zh.js',
    messages: getLangAll()
})

export default i18n // 将i18n暴露出去,在main.js中引入挂载

主要配置文件就是上面的 index.js 了 , 接下来我们随便写一点语言切换相关的内容

zh.js

export default {
    common: {
        name: '邵雅虎',
        status: '状态',
        operate: '操作',
        change: '修改',
        delete: '删除'
    }
}

en.js

export default {
    common: {
        name: 'shaoyahu',
        status: 'Status',
        operate: 'Operate',
        change: 'Change',
        delete: 'Delete'
    }
}

接下来需要在 main.js 中进行引用和挂载

// main.js
// 主要内容就是和 i18n 有关的引用和 use 
// 你只需要见缝插针 , 找到你的项目文件 main.js 中没有的复制进去
import { createApp } from 'vue'
import VueI18n from '@/langs'
const app = createApp(App)
app.use(VueI18n)
app.mount('#app')

好 , 目前配置相关的工作我们已经完成了 , 接下来让我们来使用多语言化

国际化改造

不得不说的是 , 国际化没有想象的那么先进和高级 , 他不是文字内容的实时翻译切换 , 而是由程序员提前写好的相关内容的不同语言的文字表示进行的切换

我们先来看一个普通的页面 , 没有多语言切换的页面

简单使用一个表格作为例子 , 使用的是 element plus 的组件

<template>
	<el-table :data="data" border>
		<el-table-column label="状态">
			<el-switch />
		</el-table-column>
		<el-table-column label="操作">
			<el-button type="primary" text>修改</el-button>
			<el-button type="danger" text>删除</el-button>
		</el-table-column>
	</el-table>
</template>

<script setup>
import { ref } from 'vue'

let data = ref([{}])
let myName = '邵雅虎'
</script>

可以看到我们目前代码中写的中文字都是写死的 , 写死的是没办法进行语言切换的 , 现在我们来进行国际化改造 , 先将写死的内容活起来

第一步 , 引入

<script setup>
import { ref } from 'vue'
// 解构引入 vue-i18n , 我们只需要其中的 useI18n hook函数
import { useI18n } from "vue-i18n"
// 解构使用引入的hook函数 , 获得我们需要的 , 额 , 应该是个函数 t
const { t } = useI18n()

let data = ref([{}])
let myName = '邵雅虎'
</script>

第二步 , 在 script 中使用

只要使用 t 函数就可以实现读取语言文件中的内容

<script setup>
import { ref } from 'vue'
// 解构引入 i18n , 我们只需要其中的 useI18n
import { useI18n } from "vue-i18n"
// 解构引入的函数 , 获得我们需要的 , 额 , 应该是个函数 t
const { t } = useI18n()

let data = ref([{}])
// 使用 t 函数 , 将我们需要的内容的名称放入函数中
// 我猜你可能忘了这个 common.name 是什么, 没关系看下面截好的图
let myName = t('common.name')
</script>

第三步 , 在 template 中使用

使用和在 script 中一样 , 只不过由于是 script 的写法 , 需要在属性前加上 v-bind 绑定
我们先来看下这几个变量怎么定的 , 我写到这里还真忘了 , 我们对照着进行改造

<template>
	<el-table :data="data" border>
		<el-table-column :label="t('common.status')">
			<el-switch />
		</el-table-column>
		<el-table-column :label="t('common.operate')">
			<el-button type="primary" text>{{ t('common.change') }}</el-button>
			<el-button type="danger" text>{{ t('common.delete') }}</el-button>
		</el-table-column>
	</el-table>
</template>

好了 , 我们已经完成国际化改造了 , 我们来看一看效果


emmm 好像和之前没有什么区别 , 那不就对了 , 我们一开始就是中文的嘛

那么接下来我们就来做语言的切换 , 切换到英文上来

语言切换

语言切换的关键在哪里 ?

还记得我们写的配置文件中最后使用的 createI18n 方法吗 , 就是这里面决定了我们使用的是哪一个语言文件 , 不记得没关系 , 我们看一看关键的地方

//注册i8n实例并引入语言文件
const i18n = createI18n({
    legacy: false,
    locale: 'zh.js',
    messages: getLangAll()
})

很显然 , 我们可以大胆猜测 , locale 的属性就是语言文件 , 我们尝试将 zh.js 改为 en.js 看看有没有什么效果

果然 , 页面的语言发生了改变

那么我们进行语言切换的控制

我们的解决思路是 : locale 的属性值由一个函数来决定 , 函数的返回值为需要的语言文件 , 为了避免用户手动点击刷新页面时语言被自动切换回去 , 我们将需要的语言存入到 cookie 中

这里我觉得太麻烦了我就引了一个库来做 cookie 的存储 , 而且在这篇文章中没有封装
所以建议使用 cookie 这一块大家还是自己封装几个方法用一用
如果你决定照着我这篇文章走 , 请安装如下依赖 , 使用的是 VueUse
npm i @vueuse/integrations
npm i universal-cookie

如果你并不想使用这种方式使用 cookie 或者你有更好的方式 , 你可以在下面 index.js 文件中使用到 cookie 的地方使用你自己的方法

index.js

import { createI18n } from 'vue-i18n'		//引入vue-i18n组件

// 引入 cookie 的使用函数
import { useCookies } from '@vueuse/integrations/useCookies'
const cookie = useCookies()

// 引入同级目录下所有文件 , 我们的目的是引入中文文件 zh.js 和英文文件 en.js
const modules = import.meta.globEager('./*')

// 获取所有语言的详细内容
function getLangAll() {
    let message = {}
    getLangFiles(modules, message)
    return message
}

// 遍历获取每个文件中语言的详细内容
function getLangFiles(mList, msg) {
    for (let path in mList) {
        if (mList[path].default) {
            //  获取文件名
            let pathName = path.substr(path.lastIndexOf('/') + 1, 5)
            if (msg[pathName]) {
                msg[pathName] = {
                    ...mList[pathName],
                    ...mList[path].default
                }
            } else {
                msg[pathName] = mList[path].default
            }
        }
    }
}

// 写一个函数获取存储在 cookie 中的语言文件名字 , 如果没有就给中文
function getLanguage() {
    return cookie.get('localLang') || 'zh.js'
}

// 注册i8n实例并引入语言文件
const i18n = createI18n({
    legacy: false,
    locale: getLanguage(), // 使用函数返回值
    messages: getLangAll()
})

export default i18n // 将i18n暴露出去,在main.js中引入挂载

完成了 index.js 的改造 , 我们还需要一个提供语言切换的按钮

在一般项目中 , 我们通常使用下拉框来做语言的选择切换

这里并不打算做这个下拉框的代码 , 只打算弄两个按钮 糊弄一下在座的各位 演示一下

下面是我们上面的 .vue 文件 , 我们对他进行改造

<template>
	<el-table :data="data" border>
		<el-table-column :label="t('common.status')">
			<el-switch />
		</el-table-column>
		<el-table-column :label="t('common.operate')">
			<el-button type="primary" text>{{ t('common.change') }}</el-button>
			<el-button type="danger" text>{{ t('common.delete') }}</el-button>
		</el-table-column>
	</el-table>
	// 新增切换语言的按钮
	<el-button v-for="item, index in langs" :key="index" @click='changeLang(item)'>
		{{ item.name }}
	</el-button>
</template>

<script setup>
import { ref } from 'vue'
// 解构引入 i18n , 我们只需要其中的 useI18n
import { useI18n } from "vue-i18n"
// 解构引入的函数 , 获得我们需要的 , 额 , 应该是个函数 t
const { t } = useI18n()

let data = ref([{}])
// 使用 t 函数 , 将我们需要的内容的名称放入函数中
let myName = t('common.name')

const langs = [
    {
        name: '中文',
        lang: 'zh.js'
    },
    {
        name: 'English',
        lang: 'en.js'
    },
]

const i18n = useI18n()
const changeLang = (item) => {
    i18n.locale.value = item.lang
    cookie.set('localLang', item.lang)
    location.reload()
}
</script>

OK 这样一来我们的语言也可以切换啦

总结

使用国际化一共有以下三步

  1. 引入 vue-i18n
  2. 配置配置文件
  3. 在 .vue 文件中使用

虽然以上看起来和废话一样

结束

国际化的路程才刚开始呢 , 写多语言文件才是最烦的一件事情好吧

如果你跟着做遇到了什么问题无法实现 , 请在评论区或者私信告诉我 , 我发动网友给你解答