Appearance
国际化
组件库内置 zh-CN 与 en-US 两套语言包,所有面向用户展示的文案(含 aria-label 等无障碍标注)都取自语言包,不在组件里硬编码。
切换语言
用 ConfigProvider 包裹应用即可,两种写法等价:
vue
<template>
<!-- 传内置包名 -->
<KbConfigProvider locale="en-US">
<App />
</KbConfigProvider>
<!-- 或直接传语言包对象 -->
<KbConfigProvider :locale="enUS">
<App />
</KbConfigProvider>
</template>
<script setup lang="ts">
import { KbConfigProvider, enUS } from 'kb-ui-vue'
</script>语言是响应式的,运行时切换 locale 会立即生效:
vue
<script setup lang="ts">
import { ref } from 'vue'
const locale = ref<'zh-CN' | 'en-US'>('zh-CN')
</script>
<template>
<KbConfigProvider :locale="locale">
<button @click="locale = locale === 'zh-CN' ? 'en-US' : 'zh-CN'">切换语言</button>
<KbTable :columns="columns" :data="rows" />
</KbConfigProvider>
</template>文案优先级
组件的内置文案遵循「显式 prop > 语言包 > 默认语言包」的取值顺序:
vue
<!-- 未传 description,用语言包中的 empty.description -->
<KbEmpty />
<!-- 传了 description,忽略语言包 -->
<KbEmpty description="这里空空如也" />
<!-- 传 null / '' 之外的假值时按未传处理(走语言包) -->
<KbEmpty :description="undefined" />因此已有的显式传参代码不受切换语言影响,可以渐进式迁移。
自定义语言包
传入一个与 ProjectLocale 同构的对象即可。缺字段会自动回退到默认语言包,不必抄全量:
ts
import { KbConfigProvider, type ProjectLocale } from 'kb-ui-vue'
const jaJP: ProjectLocale = {
name: 'ja-JP',
// 只覆盖需要翻译的部分,其余回退到 zh-CN
empty: { description: 'データがありません' },
popconfirm: { confirmText: 'OK', cancelText: 'キャンセル' },
} as ProjectLocalevue
<KbConfigProvider :locale="jaJP">
<App />
</KbConfigProvider>由于 TypeScript 会校验
ProjectLocale的完整性,部分覆盖时需要as ProjectLocale断言。运行时缺字段的兜底是安全的。
在自定义组件中使用
vue
<script setup lang="ts">
import { computed } from 'vue'
import { useLocale } from 'kb-ui-vue'
const { t, locale } = useLocale()
// t() 支持 %s 占位符,按入参顺序替换
const tip = computed(() => t('pagination.total', 42)) // 共 42 条
// locale 是 ref,读取具体字段用 locale.value
const week = computed(() => locale.value.calendar.weekShorts)
</script>语言包字段一览
| 路径 | 中文 | 英文 |
|---|---|---|
common.confirm | 确定 | Confirm |
common.cancel | 取消 | Cancel |
common.clear | 清空 | Clear |
common.loading | 加载中 | Loading… |
empty.description | 暂无数据 | No data |
list.empty | 暂无数据 | No data |
table.emptyText | 暂无数据 | No data |
cascader.placeholder | 请选择 | Please select |
cascader.loading | 加载中… | Loading… |
cascader.leafTag | 可选 | Selectable |
cascader.panel | 级联选择 | Cascader panel |
cascader.level | 第 %s 级 | Level %s |
calendar.prevMonth | 上一月 | Previous month |
calendar.nextMonth | 下一月 | Next month |
calendar.title | %s 年 %s 月 | %s/%s |
calendar.weekShorts | 一…日(7 项) | Mon…Sun(7 项) |
datePicker.separator | 至 | ~ |
datePicker.selectedCount | 已选 %s 个日期 | %s dates selected |
datePicker.panel | 选择日期 | Select date |
datePicker.panelRange | 选择日期范围 | Select date range |
datePicker.panelMultiple | 选择日期(可多选) | Select dates |
dialog.panel | 对话框 | Dialog |
form.required | %s 为必填项 | %s is required |
form.pattern | %s 格式不正确 | %s is malformed |
form.invalid | %s 不合法 | %s is invalid |
carousel.prev | 上一张 | Previous slide |
carousel.next | 下一张 | Next slide |
carousel.indicator | 第 %s 张 | Slide %s |
colorPicker.pick | 选择颜色 %s | Pick color %s |
inputPassword.show | 显示密码 | Show password |
inputPassword.hide | 隐藏密码 | Hide password |
pagination.prev | 上一页 | Previous page |
pagination.next | 下一页 | Next page |
pagination.pageSize | 每页 %s 条 | %s / page |
pagination.total | 共 %s 条 | %s items |
popconfirm.confirmText | 确定 | Confirm |
popconfirm.cancelText | 取消 | Cancel |
search.placeholder | 搜索… | Search… |
search.action | 搜索 | Search |
transfer.titles | 待选 / 已选 | Source / Target |
transfer.filterPlaceholder | 请输入搜索内容 | Search |
transfer.noMatch | 无匹配数据 | No matches |
transfer.prevPage | 上一页 | Previous page |
transfer.nextPage | 下一页 | Next page |
upload.chooseFile | 选择文件 | Choose file |
upload.remove | 删除 | Remove |
upload.uploading | 上传中 %s% | Uploading %s% |
upload.uploaded | 已上传 | Uploaded |
upload.failed | 上传失败 | Upload failed |