vue项目中使用vue-i18n实现多语言系统

 0 0条评论

国际化现在是很多项目的标准,所以我也在新项目中尝试一下国际化。这里我记录一下我使用vue-i18n的过程。

首先安装vue-i18n。

src目录下新建language文件夹,当然名字可以自己起。


其中除了index.ts是各个语言包文件,建议按照国际惯例命名文件。每个语言包里的key必须完全一致,而值则是对应语言的文字信息。以下分别是中文和英文的语言包。



重点就是index.ts文件了,由于需要实现按需引用,而且不是项目一开始加载所有语言包,所以相对复杂一点。需要使用到vite的动态引用模块功能。

useStore().config.lang.defaultLang,根据store中的默认语言,加载不同的语言包。暴露出registerI18n方法。

import { Composer, createI18n, I18n } from 'vue-i18n'
import { App } from 'vue'
import useStore from '@/stores'
export let i18n: {
    global: Composer
}
/**
 * 语言插件,需要在main中传递app对象
 */
export const registerI18n = async (app: App) => {
    const defaultLang = useStore().config.lang.defaultLang
    const path = `./${defaultLang}.ts`
    let defaultLocal: anyObj = {}
    /**
    * 因为所有 import.meta.glob 的参数都必须以字面量传入。你 不 可以在其中使用变量或表达式。只能通过if来判断
    * @link https://cn.vitejs.dev/guide/features.html#dynamic-import
    */
    if (defaultLang === 'zh-cn') {
        defaultLocal = import.meta.glob(`./zh-cn.ts`, { eager: true })
    }
    else if (defaultLang === 'en') {
        defaultLocal = import.meta.glob(`./en.ts`, { eager: true })
    }
    else if (defaultLang === 'ja') {
        defaultLocal = import.meta.glob(`./ja.ts`, { eager: true })
    }
    const messages = {
        [defaultLang]: (defaultLocal[path] as anyObj).default
    }
    document.querySelector('html')?.setAttribute('lang', defaultLang) // 设置html中lang属性
    // 不能把createI18n里的对象独立出来,必须直接把对象放在构造函数里
    i18n = createI18n({
        locale: defaultLang || 'zh-cn',
        legacy: false, // 组合式api
        globalInjection: true, // 挂载$t,$d等到全局
        fallbackLocale: 'zh-cn',
        messages
    })
    app.use(i18n as I18n)
}

然后main项目中,传递app对象

const setup = async () => {
    const app = createApp(App)
  app.use(pinia)
  await registerI18n(app)
  for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
    app.component(key, component)
  }
  app.use(router)
  //app.use(i18n)

  app.mount('#app')
}
setup()

最后,新建一个translate组件,使用下拉框来切换语言。

<!-- 语言切换组件 -->
<template>
    <el-dropdown trigger="click" :size="props.size === 'mini' ? 'small' : props.size">
        <i class="bi bi-translate  text-white" :class="fontSize"></i>
        <template #dropdown>
            <el-dropdown-menu>
            <el-dropdown-item v-for="item in config.$state.lang.langArray" :key="item.name"
            @click=" config.setDefaultLang(item.name as LocaleType)">{{ item.value
            }}</el-dropdown-item>
        </el-dropdown-menu>
        </template>
    </el-dropdown>
</template>
<script setup lang="ts">
import useStore from '@/stores'
const { config } = useStore()

其中,config.setDefaultLang方法,就是更改store中的默认语言,具体实现逻辑,就请根据自己项目实际情况来切换了,我的代码如下。

/**
    * 设置系统语言
    * @param lang 
    * @param isReload 是否需要刷新页面,默认true
*/
    setDefaultLang(lang: LocaleType, isReload = true) {
        this.$state.lang.defaultLang = lang
        if (isReload)
            location.reload()
        }

一定要刷新一下页面哦,我使用的是pinia,做了location持久化,所以下次访问后也会显示默认语言。

最后在需要使用多语言的界面,使用t(key)这样的形式显示文字。

import { i18n } from '@/language'
const { t } = i18n.global
<ElFormItem :label="t('login.code')" prop="code">

看看效果吧。


本文作者:双黑

版权声明:本站文章欢迎链接分享,禁止全文转载!

游客