1.安装i8N

// 安装vue-i18n
npm install vue-i18n

// 指定版本安装vue-i18n
npm install vue-i18n@9
配置多语言文件

在项目中创建语言资源文件,例如:

  • src/locales/en.json(英文)

示例内容(英文):

{
  "message": {
        "hello": "Hello World",
        "welcome": "Welcome {name}",
        "language": "Language"
  }
}
 

src/locales/zh.json(中文)

{
  "message": {
      "hello": "你好世界",
      "welcome": "欢迎 {name}",
      "language": "语言"
  }
}
 
初始化 i18n 实例
新建i18文件 在 src/i18n.js 中配置:并封装
import { createI18n } from 'vue-i18n'
import en from './lang/en'
import zh from './lang/zh'

export type LocaleKey = 'zh' | 'en'

// 统一管理应用内可用的语言包,新增语言时只需要扩展这里。
const messages = {
  zh,
  en,
}

// 启动时优先恢复上次选择的语言,没有则默认中文。
const getSavedLocale = (): LocaleKey => {
  const locale = localStorage.getItem('locale')
  return locale === 'en' ? 'en' : 'zh'
}

const i18n = createI18n({
  legacy: false,
  globalInjection: true,
  locale: getSavedLocale(),
  fallbackLocale: 'en',
  messages,
})

// 统一切换语言,页面和组件都通过这个入口改语言。
export function setLocale(lang: LocaleKey) {
  i18n.global.locale.value = lang
  localStorage.setItem('locale', lang)
}

// 统一获取当前语言,供组合式函数和组件读取。
export function getLocale(): LocaleKey {
  return i18n.global.locale.value as LocaleKey
}

export default i18n
挂载到 Vue 实例

在 main.js 中引入并挂载:

import { createApp } from 'vue';
import App from './App.vue';
import i18n from './i18n';

const app = createApp(App);
app.use(i18n);
app.mount('#app');
 

模板中使用翻译

在组件模板中通过 $t 使用:

<template>
  <a-space direction="vertical" style="width: 100%" size="middle">
   

    <a-drawer v-model:open="drawerOpen" :title="drawerTitle" width="520" destroyOnClose @ok="handleSubmit">
      <a-form layout="vertical">
        <a-form-item :label="t('task.form.taskNo')"><a-input v-model:value="form.taskNo" /></a-form-item>
        <a-form-item :label="t('task.form.orderNo')"><a-input v-model:value="form.orderNo" /></a-form-item>
        <a-form-item :label="t('task.form.pilot')"><a-input v-model:value="form.pilot" /></a-form-item>
        <a-form-item :label="t('task.form.drone')"><a-input v-model:value="form.drone" /></a-form-item>
        <a-form-item :label="t('task.form.status')"><a-select v-model:value="form.status" :options="statusOptions" /></a-form-item>
      </a-form>
    </a-drawer>
  </a-space>
</template>

<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t } = useI18n()




</script>

封装统一的语言读写

src\composables\useLocale.ts

import { computed } from 'vue'
import { getLocale, setLocale, type LocaleKey } from '@/i18n'

// 统一封装语言读写,页面只关心当前语言和切换动作。
export function useLocale() {
  const locale = computed(() => getLocale())

  const changeLocale = (lang: LocaleKey) => {
    setLocale(lang)
  }

  return {
    locale,
    changeLocale,
  }
}

优化:封装成统一的自注册组件,避免重复注册

新建 在src/i18n文件新建i18nCompent.ts

import { useI18n } from 'vue-i18n'

type LocaleKey = 'zh' | 'en'
type Messages = Record<LocaleKey, Record<string, any>>

// 自动收集 views 下每个页面目录的局部语言文件,页面只需要传自己的目录名。
const zhModules = import.meta.glob('../views/**/i18n/zh.ts', { eager: true }) as Record<string, { default: Record<string, any> }>
const enModules = import.meta.glob('../views/**/i18n/en.ts', { eager: true }) as Record<string, { default: Record<string, any> }>

function resolveMessages(viewName: string): Messages {
  const zhPath = `../views/${viewName}/i18n/zh.ts`
  const enPath = `../views/${viewName}/i18n/en.ts`
  const zh = zhModules[zhPath]
  const en = enModules[enPath]

  if (!zh || !en) {
    throw new Error(`Missing local i18n module: ${viewName}`)
  }

  return { zh: zh.default, en: en.default }
}

// 统一的页面级 i18n 入口,避免每个页面单独导入 zh/en。
export function useViewI18n(viewName: string): any {
  return useI18n({
    useScope: 'local',
    messages: resolveMessages(viewName),
  })
}

在文件中使用:

<template>
  <a-space direction="vertical" style="width: 100%" size="middle">
   

    <a-drawer v-model:open="drawerOpen" :title="drawerTitle" width="520" destroyOnClose @ok="handleSubmit">
      <a-form layout="vertical">
        <a-form-item :label="t('task.form.taskNo')"><a-input v-model:value="form.taskNo" /></a-form-item>
        <a-form-item :label="t('task.form.orderNo')"><a-input v-model:value="form.orderNo" /></a-form-item>
        <a-form-item :label="t('task.form.pilot')"><a-input v-model:value="form.pilot" /></a-form-item>
        <a-form-item :label="t('task.form.drone')"><a-input v-model:value="form.drone" /></a-form-item>
        <a-form-item :label="t('task.form.status')"><a-select v-model:value="form.status" :options="statusOptions" /></a-form-item>
      </a-form>
    </a-drawer>
  </a-space>
</template>

<script setup lang="ts">
import { useViewI18n } from '@/i18n/i18nCompent'
const { t } = useViewI18n('task')  //task是文件名
//也可以修改 i18nCompent 的方法匹配view下的所有子文件



</script>

更多推荐