VUE3 配置 i18n

203 阅读2分钟

VUE 配置 i18n

项目中与 i18n 有关的文件的结构

├── main.ts
└── src
	└── lang
        └── en.ts
        └── zh-cn.ts // 文件名最好与 language 的取值保持一致,因为后续获取国际化文本时使用的是文件名
     └── test      
        └── i18n
            └── en.ts
            └── zh-cn.ts

初始化 i18n 配置文件

import { createI18n } from 'vue-i18n'
// import elementZhCn from 'element-plus/dist/locale/zh-cn.mjs'
// import elementEn from 'element-plus/dist/locale/en.mjs'

// 获取 lang 文件夹下的所有文件
const langModules = import.meta.glob('./lang/*.ts', { eager: true })
// 获取 src 文件夹下所有名为 i18n 的文件夹下的所有文件
const i18nModules = import.meta.glob('@/**/i18n/*.ts', { eager: true })

// 读取所有国际化文本
const getFileMessage = (list: any, obj: any) => {
    for(let key in list) {
        const messages = list[key].default
        const path = (key.match(/([^/]+)\.ts/) ?? [])[1] ?? ''
        if(messages) {
            // path 获取的是文件名,所以如果 language 的取值与文件名对应不上,后续获取文本时会读不到值
            obj[path] = {
                ...obj[path],
                ...messages
            }
        }
    }
}

// 获取所有语言的文本信息
const getAllLanguage = () => {
    const msgObj = {
        // 这里的键名要和 文件名对应上,可以根据自己的需要修改 键名
        'en': {
            // ...elementEn.el
        }, 
        'zh-cn': {
            // ...elementZhCn.el
        }
    }
    getFileMessage(langModules, msgObj)
    getFileMessage(i18nModules, msgObj)
    return msgObj
}

// 获取当前语言 language 的值
const getLocalLanguage = () => {
    return sessionStorage.getItem('language') || 'zh-cn'
}

// 配置 i18n
const i18n = createI18n({
    legacy: false, // 必须设置为 false 才能使用组合式 API
    locale: getLocalLanguage(), // 获取当前语言
    messages: await getAllLanguage(), // 获取所有语言文本
})

// 根据当前语言动态设置网页的语言,以便于搜索引擎和屏幕阅读器等能够识别页面的当前语言并正确加载字体文件。
document.getElementsByTagName('html')[0].setAttribute('lang', getLocalLanguage() == 'en' ? 'en' : 'zh')
export default i18n

在 main.ts 中引入 i18n

import { createApp } from 'vue'
import App from './App.vue'
import i18n from '@/i18n/index'

const app = createApp(App)

app.use(i18n)
app.mount('#app')

切换语言按钮代码实现示例

store/index 文件示例

import { defineStore } from 'pinia'

const languageHis: string = sessionStorage.getItem('language') || 'zh-cn'

export default defineStore('layout', {
    state: () => {
        return {
            language: languageHis as string,
        }
    },
    getters: {
        getLanguage(): string {
            return this.language
        }
    },
    actions: {
        setLanguage(language: string, i18n: any) {
            this.language = language
            i18n.locale.value = language
            sessionStorage.setItem('language', language)
        }
    }
})

vue 文件示例

<template>
	<div>
		<button @click.prevent="changeLanguage">{{ language }}</button>
	</div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import layoutStore from '@/store/index'
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';

const router = useRouter()
const i18n = useI18n()
const layoutSe = layoutStore()
const language = computed(() => layoutSe.getLanguage)
const changeLanguage = () => {
	layoutSe.setLanguage(language.value == 'en' ? 'zh-cn' : 'en', i18n)
}
</script>