@cimom/vben-locales
v5.6.4
Published
国际化(i18n)工具包,提供了多语言支持功能,基于 vue-i18n 实现,支持动态加载语言包和语言切换。
Readme
@cimom/vben-locales
国际化(i18n)工具包,提供了多语言支持功能,基于 vue-i18n 实现,支持动态加载语言包和语言切换。
安装
npm install @cimom/vben-locales基本使用
初始化国际化
import { setupI18n } from '@cimom/vben-locales';
import type { App } from 'vue';
// 在应用启动时初始化
export async function setupApp(app: App) {
// 初始化国际化
await setupI18n(app, {
locale: 'zh-CN',
fallbackLocale: 'en-US',
availableLocales: ['zh-CN', 'en-US'],
});
// ... 其他初始化
}使用翻译函数
import { $t, $te } from '@cimom/vben-locales';
// 翻译文本
const welcomeText = $t('common.welcome');
// 检查翻译键是否存在
if ($te('common.welcome')) {
console.log('欢迎文本已定义');
}在组件中使用
<template>
<div>
<h1>{{ $t('common.welcome') }}</h1>
<p>{{ $t('common.description') }}</p>
<select v-model="currentLocale" @change="changeLocale">
<option value="zh-CN">简体中文</option>
<option value="en-US">English</option>
</select>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useI18n, loadLocaleMessages } from '@cimom/vben-locales';
const { locale } = useI18n();
const currentLocale = ref(locale.value);
async function changeLocale() {
// 加载语言包
await loadLocaleMessages(currentLocale.value);
// 设置当前语言
locale.value = currentLocale.value;
}
</script>API 参考
核心函数
| 函数名 | 参数 | 返回值 | 说明 |
| --- | --- | --- | --- |
| setupI18n | app: App, options: LocaleSetupOptions | Promise<void> | 初始化国际化配置 |
| loadLocaleMessages | lang: SupportedLanguagesType | Promise<void> | 加载指定语言的语言包 |
| loadLocalesMap | modules: Record<string, () => Promise<unknown>> | Record<Locale, ImportLocaleFn> | 加载语言模块映射 |
| loadLocalesMapFromDir | regexp: RegExp, modules: Record<string, () => Promise<unknown>> | Record<Locale, ImportLocaleFn> | 从目录结构加载语言模块映射 |
| $t | key: string, ...args | string | 全局翻译函数 |
| $te | key: string | boolean | 检查翻译键是否存在 |
类型定义
// 支持的语言类型
type SupportedLanguagesType = 'zh-CN' | 'en-US' | string;
// 语言包导入函数
type ImportLocaleFn = () => Promise<{ default: Record<string, any> }>;
// 国际化设置选项
interface LocaleSetupOptions {
// 当前语言
locale: SupportedLanguagesType;
// 备用语言
fallbackLocale?: SupportedLanguagesType;
// 可用语言列表
availableLocales?: SupportedLanguagesType[];
// 语言包加载函数
loadLocale?: LoadMessageFn;
}目录结构
语言包应按照以下目录结构组织:
src/
langs/
zh-CN/
common.json
login.json
dashboard.json
...
en-US/
common.json
login.json
dashboard.json
...每个语言包文件应该是一个 JSON 文件,包含相应模块的翻译键值对:
// zh-CN/common.json
{
"welcome": "欢迎使用",
"description": "这是一个示例描述",
"buttons": {
"submit": "提交",
"cancel": "取消",
"confirm": "确认"
}
}// en-US/common.json
{
"welcome": "Welcome",
"description": "This is a sample description",
"buttons": {
"submit": "Submit",
"cancel": "Cancel",
"confirm": "Confirm"
}
}高级用法
动态加载语言包
import { loadLocaleMessages } from '@cimom/vben-locales';
// 异步加载语言包
async function loadLanguage(lang: string) {
try {
await loadLocaleMessages(lang);
console.log(`语言 ${lang} 加载成功`);
} catch (error) {
console.error(`加载语言 ${lang} 失败:`, error);
}
}自定义语言包加载器
import { setupI18n } from '@cimom/vben-locales';
import type { App } from 'vue';
// 自定义语言包加载函数
async function customLoadLocale(lang: string) {
// 从自定义API加载语言包
const response = await fetch(`/api/locales/${lang}`);
const messages = await response.json();
return messages;
}
// 在应用启动时初始化
export async function setupApp(app: App) {
// 初始化国际化,使用自定义加载器
await setupI18n(app, {
locale: 'zh-CN',
fallbackLocale: 'en-US',
availableLocales: ['zh-CN', 'en-US'],
loadLocale: customLoadLocale,
});
}使用组合式 API
<template>
<div>
<h1>{{ t('common.welcome') }}</h1>
<p>{{ t('common.description') }}</p>
<div>
<button
v-for="lang in availableLocales"
:key="lang"
@click="changeLocale(lang)"
:class="{ active: locale === lang }"
>
{{ lang === 'zh-CN' ? '中文' : 'English' }}
</button>
</div>
</div>
</template>
<script setup lang="ts">
import { useI18n, loadLocaleMessages } from '@cimom/vben-locales';
const { t, locale, availableLocales } = useI18n();
async function changeLocale(lang: string) {
// 加载语言包
await loadLocaleMessages(lang);
// 设置当前语言
locale.value = lang;
}
</script>处理日期和数字格式化
<template>
<div>
<p>{{ t('common.currentDate', { date: d(new Date()) }) }}</p>
<p>{{ t('common.price', { price: n(1234.56) }) }}</p>
</div>
</template>
<script setup lang="ts">
import { useI18n } from '@cimom/vben-locales';
const { t, d, n } = useI18n();
</script>示例
语言切换组件
<template>
<div class="language-switcher">
<button
v-for="lang in availableLocales"
:key="lang"
@click="changeLocale(lang)"
:class="{ active: currentLocale === lang }"
class="lang-button"
>
<span v-if="lang === 'zh-CN'">🇨🇳 中文</span>
<span v-else-if="lang === 'en-US'">🇺🇸 English</span>
<span v-else>{{ lang }}</span>
</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useI18n, loadLocaleMessages } from '@cimom/vben-locales';
const { locale, availableLocales } = useI18n();
const currentLocale = ref(locale.value);
async function changeLocale(lang: string) {
try {
// 加载语言包
await loadLocaleMessages(lang);
// 设置当前语言
locale.value = lang;
currentLocale.value = lang;
} catch (error) {
console.error(`切换语言失败:`, error);
}
}
</script>
<style scoped>
.language-switcher {
display: flex;
gap: 8px;
}
.lang-button {
padding: 6px 12px;
border: 1px solid #ddd;
border-radius: 4px;
background: white;
cursor: pointer;
transition: all 0.2s;
}
.lang-button.active {
background: #1677ff;
color: white;
border-color: #1677ff;
}
</style>国际化表单验证
<template>
<form @submit.prevent="submitForm">
<div class="form-item">
<label>{{ t('form.username') }}</label>
<input v-model="form.username" type="text" />
<div v-if="errors.username" class="error">
{{ t(`validation.${errors.username}`) }}
</div>
</div>
<div class="form-item">
<label>{{ t('form.email') }}</label>
<input v-model="form.email" type="email" />
<div v-if="errors.email" class="error">
{{ t(`validation.${errors.email}`) }}
</div>
</div>
<button type="submit">{{ t('form.submit') }}</button>
</form>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
import { useI18n } from '@cimom/vben-locales';
const { t } = useI18n();
const form = reactive({
username: '',
email: '',
});
const errors = reactive({
username: '',
email: '',
});
function validateForm() {
let isValid = true;
// 验证用户名
if (!form.username) {
errors.username = 'required';
isValid = false;
} else if (form.username.length < 3) {
errors.username = 'minLength';
isValid = false;
} else {
errors.username = '';
}
// 验证邮箱
if (!form.email) {
errors.email = 'required';
isValid = false;
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email)) {
errors.email = 'invalidEmail';
isValid = false;
} else {
errors.email = '';
}
return isValid;
}
function submitForm() {
if (validateForm()) {
console.log('表单提交:', form);
// 提交表单逻辑...
}
}
</script>
<style scoped>
.form-item {
margin-bottom: 16px;
}
label {
display: block;
margin-bottom: 4px;
}
input {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.error {
color: red;
font-size: 12px;
margin-top: 4px;
}
button {
padding: 8px 16px;
background: #1677ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>语言包示例:
// zh-CN/form.json
{
"username": "用户名",
"email": "电子邮箱",
"submit": "提交"
}
// zh-CN/validation.json
{
"required": "此字段为必填项",
"minLength": "长度不能少于3个字符",
"invalidEmail": "请输入有效的电子邮箱地址"
}
// en-US/form.json
{
"username": "Username",
"email": "Email",
"submit": "Submit"
}
// en-US/validation.json
{
"required": "This field is required",
"minLength": "Length must be at least 3 characters",
"invalidEmail": "Please enter a valid email address"
}