Skip to content

国际化

INFO

该特性由 vue-i18n 提供技术支持。

vscode 扩展

如果使用 vscode 进行开发,推荐安装 i18n Ally 这个扩展。

安装该扩展后,代码里可以实时查看对应语言的内容。

语言选择器

在应用配置中设置后,会在顶栏里显示语言选择器。

ts
const globalSettings: Settings.all = {
  toolbar: {
    enableI18n: true,
  },
}

同时还可在应用配置中设置默认语言,可选设置的值参考 /src/locales/lang/ 目录下文件名,留空则会根据浏览器语言自动判断,如果找不到对应的语言则使用 中文(简体) 兜底。

ts
const globalSettings: Settings.all = {
  app: {
    defaultLang: '',
  },
}

语言包

语言包存放在 /src/locales/lang/ 目录下,因为 Element Plus 本身也有自己的语言包,所以在做国际化支持的时候,框架的语言包文件命名需要和 Element Plus 保持一致,可点击这里查看 Element Plus 的语言包文件。

假设你已经在 /src/locales/lang/ 目录下新增并配置好了一个日文语言包 ja.json ,然后你需要到 /src/locales/index.ts 文件里做以下调整。

ts
import elementLocaleZhCN from 'element-plus/lib/locale/lang/zh-cn'
import elementLocaleZhTW from 'element-plus/lib/locale/lang/zh-tw'
import elementLocaleEn from 'element-plus/lib/locale/lang/en'
// 引用 Element Plus 的日文语言包
import elementLocaleJa from 'element-plus/lib/locale/lang/ja'

function getElementLocales() {
  const locales: {
    [key: string]: any
  } = {}
  for (const key in messages) {
    locales[key] = {}
    switch (key) {
      case 'zh-cn':
        Object.assign(locales[key], elementLocaleZhCN, { labelName: '中文(简体)' })
        break
      case 'zh-tw':
        Object.assign(locales[key], elementLocaleZhTW, { labelName: '中文(繁體)' })
        break
      case 'en':
        Object.assign(locales[key], elementLocaleEn, { labelName: 'English' })
        break
      // 在这里增加一个 case 选项,其中 labelName 会在语言选择器里显示
      case 'ja':
        Object.assign(locales[key], elementLocaleJa, { labelName: '日本語' })
        break
    }
  }
  return locales
}

修改完成后,需要重新启动项目才会生效。

路由设置

以中文(简体)为例,打开 /src/locales/lang/zh-cn.json 文件可以看到路由相关的配置,在 route 对象里可以扩展需要开启国际化支持的路由。

json
{
  "route": {
    "dashboard": "控制台",
    "i18n": "国际化",
    "login": "登录",
    "personal": {
      "editpassword": "修改密码",
      "setting": "个人设置"
    }
  }
}

如果需要新增某个路由的国际化支持,光设置好中文(简体)的还不行,其它语言包文件里也要同步添加。当都设置好后,可在该路由的 meta 对象里设置 i18n 参数,例如:

ts
meta: {
  title: '国际化',
  i18n: 'route.i18n',
},

强烈建议开启国际化的时候,title 也还是设置,框架的处理逻辑是:

先查找当前语言包里的配置,如果没有再查找中文(简体)语言包里的设置,如果还没有,则显示 title 的内容,所以 title 算是个缺省项。

框架设置

以中文(简体)为例,打开 /src/locales/lang/zh-cn.json 文件可以看到框架相关的配置,在 app 对象里的就是框架部分的语言信息,如果需要对框架进行二次开发,请在这里扩展。

json
{
  "app": {
    "account": "用户名",
    "captcha": "验证码",
    "check": "确 认",
    "goLogin": "去登录",
    "login": "登 录",
    "logout": "退出登录",
    "newPassword": "新密码",
    "password": "密码",
    "profile": "个人设置",
    "sendCaptcha": "发送验证码"
  }
}

单页组件

如果每个页面都要做国际化支持,那语言包文件就会变得无比庞大且难以维护,推荐在每个页面组件里使用 <i18n> 自定义块进行语言维护,可访问 /src/MainApp/views/examples/feature_example/i18n.vue 查看示例。

vue
<i18n lang="yaml">
zh-cn:
  intro: 除了支持全局多语言切换,还支持 Vue 单文件模式语言切换,你可以尝试在这个页面点击右上角的语言切换试试
  form:
    name: 姓名
    age: 年龄
  formRules:
    name: 请输入姓名
    age: 请输入年龄
en:
  intro: In addition to global multi-language switch, also support Vue single file mode language switch, you can try to click on the top right corner of the page to switch language
  form:
    name: Name
    age: Age
  formRules:
    name: Please enter name
    age: Please enter age
</i18n>

<script lang="ts" setup>
import { useI18n } from 'vue-i18n'
import { ElMessage } from 'element-plus'
import { getLocales, setupI18n } from '@/locales'

const { t } = useI18n()

const page = ref(1)
const pageSize = ref(100)

function handleSizeChange(val: any) {
  ElMessage(`每页 ${val} 条`)
}

function handleCurrentChange(val: any) {
  ElMessage(`当前页: ${val}`)
}

const form = ref({
  name: '',
  age: ''
})

const formRules = ref({
  name: [{ required: true, message: () => t('formRules.name'), trigger: 'blur' }],
  age: [{ required: true, message: () => t('formRules.age'), trigger: 'blur' }]
})

function lazyload(lang: string) {
  const i18n = setupI18n()
  const locales = getLocales()
  // 模拟异步载入,新增的语言包数据需要和框架默认数据合并
  if (lang === 'zh-cn') {
    Object.assign(locales['zh-cn'], {
      hello: {
        world: '你好,世界!'
      }
    })
    i18n.global.setLocaleMessage(lang, locales['zh-cn'])
  }
  else {
    Object.assign(locales.en, {
      hello: {
        world: 'Hello World !'
      }
    })
    i18n.global.setLocaleMessage(lang, locales.en)
  }
  ElMessage.success('载入成功,你可以切换语言查看效果')
}
</script>

<template>
  <div>
    <page-header :title="t('route.feature.i18n')" :content="t('intro')" />
    <page-main title="Element 组件">
      <el-pagination
        v-model:currentPage="page"
        v-model:page-size="pageSize"
        :page-sizes="[100, 200, 300, 400]"
        layout="total, sizes, prev, pager, next, jumper"
        :total="400"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </page-main>
    <page-main title="表单验证">
      <el-form v-model="form" :rules="formRules" label-width="100px">
        <el-form-item :label="t('form.name')" prop="name">
          <el-input v-model="form.name" />
        </el-form-item>
        <el-form-item :label="t('form.age')" prop="age">
          <el-input v-model="form.age" />
        </el-form-item>
      </el-form>
    </page-main>
    <page-main title="延迟加载">
      <el-button @click="lazyload('zh-cn')">
        载入中文
      </el-button>
      <el-button @click="lazyload('en')">
        载入英文
      </el-button>
      <p>
        {{ t('hello.world') }}
      </p>
    </page-main>
  </div>
</template>

与服务端交互

所有的请求均会在请求头里带上 Accept-Language ,后端可根据这一状态信息做动态数据国际化处理。

关闭国际化

如果不想开启国际化,可参考以下设置,该设置表示关闭语言选择器,并以中文(简体)显示。

ts
const globalSettings: Settings.all = {
  app: {
    defaultLang: 'zh-cn',
  },
  toolbar: {
    enableI18n: false,
  },
}