Skip to content

多语言规范

TIP

规定前端国际化与多语言实现规范。适用于 Vue 3 + TypeScript + Vite + Guava UI 技术栈。

设计原则

原则说明
见名知意key 应该准确表达用途,避免 str1temp1aaa 等模糊命名
风格统一key 值使用小驼峰风格,禁止使用中文,全项目保持一致
避免过长key 值应使用短名称,尽量保持在20个字符以内,如过长,尽量找出最合理的英文简写
禁止拼音禁止使用拼音或拼音缩写,如 yongHuXingMing

通用

  • 缩进 2 空格,UTF-8 编码
  • 按功能分类组织代码,每个分类创建一个对象,对象名与功能名一致
  • 每个分类下的 key 值应保持一致,避免使用不同的命名风格
  • 每个分类下的 key 值应保持唯一,避免重复定义
  • 每个分类下使用独立的 key 值,避免与其他分类冲突
  • 所有的 key 值都必须是小驼峰风格,禁止使用中文,全项目保持一致
  • 英文 value 部分,第一个单词首字母大写,后续单词首字母小写,避免使用下划线分隔单词
  • 中文部分与英文部分key要保持顺序一致,避免顺序不一致导致排查困难

基础使用示例

跨模块 / 公共工具 / 通用组件:推荐用全局 t()

优点

  • 可以随意访问所有 key
  • 更灵活(适合公共组件)
  • 不用重复 useI18n

缺点

  • key 很长、可读性差
  • 容易写错 namespace
  • 大项目容易“乱用 key”
  • 无约束,维护成本高
vue
<script setup lang="ts">
import { useI18n } from '@/hook/web/useI18n';

// @hook
const { t } = useI18n();

// @data
const templateTableHeadList = ref([
  {
    type: 'action',
    label: t('templateUpload.op'),
    content: [t('templateUpload.download')],
    action: [(row: Recordable<any>, index: number) => handleDownload(row, index)]
  },
  {
    label: t('templateUpload.templateName'),
    prop: 'fileName',
    fixed: 'left',
    query: true
  },
  {
    label: t('templateUpload.folderPath'),
    prop: 'folderPath',
    fixed: 'left'
  }
]);
</script>

<template>
  <div :class="prefixCls">
    <GvForm ref="deptSearchFm" ref-form="deptSearchFm" :divider="t('searchBar.searchFilter')" :form-list="deptSearchList">
      <GvSearchBar>
        <GvButton>{{ t('searchBar.reset') }}</GvButton>
      </GvSearchBar>
    </GvForm>
    <GvTable ref="templateTableList" ref-table="templateTableList" :table-head="templateTableHeadList" :table-data="searchTemplateData" />
  </div>
</template>
typescript
// en.ts
export default = {
  // ...
  templateUpload: {
    op: 'Operation',
    templateName: 'Template name',
    download: 'Download',
    folderPath: 'Folder path',
    isHoldname: 'Hold name',
    uploadBy: 'Upload by',
    uploadTime: 'Upload time',
  },
  // ...
}

// zh-CN.ts
export default = {
  // ...
  templateUpload: {
    op: '操作',
    templateName: '模板名称',
    download: '下载',
    folderPath: '文件夹路径',
    isHoldname: '是否保留名称',
    uploadBy: '上传人',
    uploadTime: '上传时间',
  },
  // ...
}

传 scope 使用示例

业务组件 / 页面内:推荐用 useI18n('xxx')scope

优点

  • 命名空间清晰(不会写长 key)
  • 避免 key 冲突(尤其多人协作)
  • 更符合“模块化 i18n”
  • 代码更干净

缺点

  • 不能方便跨 namespace 使用
  • 一个文件多个模块时要写多个 useI18n
  • 对复用组件不友好
vue
<script setup lang="ts">
import { useI18n } from '@/hook/web/useI18n';

// @hook
const { t } = useI18n('templateUpload');
const { t: st } = useI18n('searchBar');

// @data
const templateTableHeadList = ref([
  {
    type: 'action',
    label: t('op'),
    content: [t('download')],
    action: [(row: Recordable<any>, index: number) => handleDownload(row, index)]
  },
  {
    label: t('templateName'),
    prop: 'fileName',
    fixed: 'left',
    query: true
  },
  {
    label: t('folderPath'),
    prop: 'folderPath',
    fixed: 'left'
  }
]);
</script>

<template>
  <div :class="prefixCls">
    <GvForm ref="deptSearchFm" ref-form="deptSearchFm" :divider="st('searchFilter')" :form-list="deptSearchList">
      <GvSearchBar>
        <GvButton>{{ st('reset') }}</GvButton>
      </GvSearchBar>
    </GvForm>
    <GvTable ref="templateTableList" ref-table="templateTableList" :table-head="templateTableHeadList" :table-data="searchTemplateData" />
  </div>
</template>
typescript
// en.ts
export default = {
  // ...
  templateUpload: {
    op: 'Operation',
    templateName: 'Template name',
    download: 'Download',
    folderPath: 'Folder path',
    isHoldname: 'Hold name',
    uploadBy: 'Upload by',
    uploadTime: 'Upload time',
  },
  // ...
}

// zh-CN.ts
export default = {
  // ...
  templateUpload: {
    op: '操作',
    templateName: '模板名称',
    download: '下载',
    folderPath: '文件夹路径',
    isHoldname: '是否保留名称',
    uploadBy: '上传人',
    uploadTime: '上传时间',
  },
  // ...
}

动态多语言示例

下述示例为动态多语言示例,用于删除用户的提示框。

如删除的用户名userName为: admin 则删除用户提示框为: 确认删除用户 admin

vue
<script setup lang="ts">
import { useI18n } from '@/hook/web/useI18n';
import { useNotify } from '@/hook/web/useNotify';

// @hook
const { t } = useI18n();
const { message } = useNotify();

// @method
const deleteUser = (userName: string) =>{
  message(t('userList.deleteUser', { userName }), 'confirm');
  // ...
}
typescript
// en.ts
export default = {
  // ...
  userList: {
    deleteUser: 'Confirm delete user {userName}',
  },
  // ...
}

// zh-CN.ts
export default = {
  // ...
  userList: {
    deleteUser: '确认删除用户 {userName}',
  },
  // ...
}

编译器插件

  • i18n Ally 插件 — 用于显示多语言文本,可对应检查多语言文本是否存在

相关规范