多语言配置指南

版本: v2.0.0-beta.1
最后更新: 2026-04-30


📚 多语言文档导航

根据你的需求选择合适的文档:


📖 概述

schema-dsl 支持完整的多语言功能,允许你自定义字段标签和错误消息的翻译。

Node.js 要求>=18.0.0

目录加载(Node >=18)默认支持的语言文件格式

  • .js(CommonJS 语言包)
  • .cjs
  • .json
  • .jsonc
  • .json5

推荐:如果你的应用是 type: module / ESM 项目,优先使用 .cjs.json.jsonc.json5.js 更适合 CommonJS 语言包文件。

v2 当前能力

  • ✅ 支持参数化语言切换(无需修改全局状态)
  • ✅ 支持自定义错误消息(三种格式)
  • ✅ TypeScript 类型定义完整
  • ✅ 目录递归加载 .js/.cjs/.json/.jsonc/.json5

🚀 快速开始

方式1:验证时动态指定语言(推荐)⭐

const { dsl, validate } = require('schema-dsl');

const schema = dsl({ username: 'string:3-32!' });

// 使用中文错误消息
const result = validate(schema, { username: 'ab' }, { locale: 'zh-CN' });
// message: "username长度不能少于3个字符"

// 使用英文错误消息
const result2 = validate(schema, { username: 'ab' }, { locale: 'en-US' });
// message: "username length must be at least 3"

方式2:使用全局配置(向后兼容)

const { Locale } = require('schema-dsl');

// 设置默认语言
Locale.setLocale('zh-CN');

// 后续验证会使用中文错误消息
const result = validate(schema, data);

📝 内置语言支持

schema-dsl 内置了以下语言包:

语言代码语言名称支持状态
zh-CN简体中文✅ 完整支持
en-US英语(美国)✅ 完整支持
ja-JP日语✅ 完整支持
es-ES西班牙语✅ 完整支持
fr-FR法语✅ 完整支持

🎯 高级用法

基础配置

const { dsl, validate } = require('schema-dsl');
const path = require('path');

// ✅ 方式 1: 从目录加载(推荐)
dsl.config({
  i18n: path.join(__dirname, 'i18n/dsl')  // Node >=18:支持 .js/.cjs/.json/.jsonc/.json5
});

// ✅ 方式 2: 直接传入对象
dsl.config({
  i18n: {
    'zh-CN': require('./i18n/dsl/zh-CN'),
    'en-US': require('./i18n/dsl/en-US')
  }
});

目录结构

project/
├── i18n/
│   └── dsl/              # schema-dsl 语言包目录
│       ├── zh-CN.cjs     # CommonJS / ESM 项目都稳定
│       ├── en-US.jsonc   # 带注释/末尾逗号
│       └── ja-JP.json5   # JSON5 风格(可选)

📝 语言包格式

完整示例 (i18n/dsl/zh-CN.cjs)

module.exports = {
  // ========== 字段标签 ==========
  'field.username': '用户名',
  'field.email': '邮箱地址',
  'field.password': '密码',
  'field.age': '年龄',
  
  // ========== 覆盖默认错误消息 ==========
  'required': '{{#label}}是必填项',
  'string.minLength': '{{#label}}长度不能少于{{#limit}}个字符',
  'string.maxLength': '{{#label}}长度不能超过{{#limit}}个字符',
  'string.enum': '{{#label}}必须是以下值之一: {{#valids}}',
  'number.base': '{{#label}}必须是数字类型',
  'number.min': '{{#label}}不能小于{{#limit}}',
  'number.max': '{{#label}}不能大于{{#limit}}',
  'boolean.base': '{{#label}}必须是布尔类型',
  'enum': '{{#label}}必须是以下值之一: {{#allowed}}',
  
  // ========== 自定义错误消息 ==========
  'custom.invalidEmail': '邮箱格式不正确,请重新输入',
  'custom.emailTaken': '该邮箱已被注册',
  'custom.passwordWeak': '密码强度不够'
};

🎯 使用方法

1. 字段标签翻译

const schema = dsl({
  username: dsl('string:3-32!').label('field.username'),
  email: dsl('email!').label('field.email')
});

const result = validate(schema, { username: 'ab' });
// 错误消息: "用户名长度不能少于3个字符"

2. 覆盖默认错误消息

// 语言包
module.exports = {
  'required': '{{#label}}必须填写'
};

// Schema
const schema = dsl({ username: 'string!' });

validate(schema, {});
// 错误消息: "username必须填写"

3. 自定义错误消息

const schema = dsl({
  status: dsl('active|inactive').messages({
    'enum': '状态必须是 active 或 inactive'
  })
});

4. 动态语言切换

dsl.config({
  i18n: {
    'zh-CN': { 'required': '{{#label}}是必填项' },
    'en-US': { 'required': '{{#label}} is required' }
  }
});

// 默认语言(zh-CN)
validate(schema, data);

// 切换到英文
validate(schema, data, { locale: 'en-US' });

📋 内置错误消息键

通用错误

错误键说明默认消息(zh-CN)
required必填字段缺失{{#label}}是必填项
enum枚举值不在范围{{#label}}必须是以下值之一: {{#allowed}}
pattern格式不正确{{#label}}格式不正确

String 错误

错误键说明
string.minLength最小长度
string.maxLength最大长度
string.pattern正则不匹配
string.enum字符串枚举

Number 错误

错误键说明
number.base类型不是数字
number.min小于最小值
number.max大于最大值
number.integer不是整数

Boolean 错误

错误键说明
boolean.base类型不是布尔值

Array 错误

错误键说明
array.base类型不是数组
array.min元素数量不足
array.max元素数量过多
array.unique包含重复元素

Format 错误

错误键说明
format.email邮箱格式错误
format.urlURL格式错误
format.uuidUUID格式错误
format.date日期格式错误
format.binaryBase64编码错误

Pattern 错误

错误键说明
pattern.phone手机号格式错误
pattern.idCard身份证格式错误
pattern.objectIdObjectId格式错误

完整列表请参考: src/locales/zh-CN.ts


🔧 高级用法

嵌套字段标签

// 语言包
module.exports = {
  'field.address.city': '城市',
  'field.address.street': '街道'
};

// Schema
const schema = dsl({
  address: {
    city: dsl('string!').label('field.address.city'),
    street: dsl('string!').label('field.address.street')
  }
});

错误消息优先级

  1. 字段级自定义消息 - .messages() 方法
  2. Schema级标签 - .label() 方法
  3. 语言包自定义消息 - i18n 配置
  4. 默认错误消息 - 内置语言包
// 优先级示例
dsl.config({
  i18n: {
    'zh-CN': {
      'required': '全局必填消息'  // 优先级 3
    }
  }
});

const schema = dsl({
  username: dsl('string!')
    .label('用户名')                    // 优先级 2
    .messages({ 'required': '必须填' }) // 优先级 1(最高)
});

多语言最佳实践

1. 目录结构

project/
├── i18n/
│   └── dsl/
│       ├── zh-CN.cjs     # 中文
│       ├── en-US.jsonc   # 英文
│       ├── ja-JP.json5   # 日语
│       └── index.cjs     # 导出工具

2. 导出工具 (i18n/dsl/index.cjs)

const path = require('path');

module.exports = {
  'zh-CN': require('./zh-CN.cjs'),
  'en-US': require('./en-US.jsonc'),
  'ja-JP': require('./ja-JP.json5')
};

// 使用
dsl.config({
  i18n: require('./i18n/dsl')
});

3. 消息复用

// i18n/dsl/common.cjs
module.exports = {
  required: '{{#label}}是必填项',
  minLength: '{{#label}}长度不能少于{{#limit}}个字符'
};

// i18n/dsl/zh-CN.cjs
const common = require('./common.cjs');

module.exports = {
  ...common,
  'field.username': '用户名',
  'field.email': '邮箱'
};

📊 完整示例

用户管理系统

const { dsl, validate } = require('schema-dsl');
const path = require('path');

// 配置多语言
dsl.config({
  i18n: path.join(__dirname, 'i18n/dsl')
});

// 定义 Schema
const userSchema = dsl({
  username: dsl('string:3-32!').label('field.username'),
  email: dsl('email!').label('field.email'),
  password: dsl('string:8-32!').label('field.password'),
  age: dsl('number:18-120').label('field.age'),
  role: dsl('admin|user|guest!').label('field.role')
});

// 验证(中文)
let result = validate(userSchema, {
  username: 'ab',
  email: 'invalid',
  role: 'admin'
});

console.log(result.errors);
// [
//   { path: 'username', message: '用户名长度不能少于3个字符' },
//   { path: 'email', message: '邮箱地址必须是有效的邮箱地址' },
//   { path: 'password', message: '密码是必填项' }
// ]

// 验证(英文)
result = validate(userSchema, {
  username: 'ab'
}, { locale: 'en-US' });

console.log(result.errors[0].message);
// "username must be at least 3 characters"

🐛 常见问题

1. 语言包不生效?

检查清单:

  • ✅ 配置键是否正确(i18n 而非 locales
  • ✅ 目录路径是否正确
  • ✅ 文件名是否为语言代码(如 zh-CN.cjs / zh-CN.jsonc
  • .js 文件是否为 CommonJS(module.exports),若是 ESM 项目优先使用 .cjs / .json*

2. 错误消息仍然是英文?

原因: 当前请求没有显式传入 locale,或全局默认语言尚未切到你期望的语言

// 方法 1: 全局设置
const { Locale } = require('schema-dsl');
Locale.setLocale('zh-CN');

// 方法 2: 验证时指定
validate(schema, data, { locale: 'zh-CN' });

3. 自定义消息不显示?

检查优先级:

  • .messages() > .label() > 语言包 > 默认
// 错误:label 会被 messages 覆盖
dsl('string!')
  .label('用户名')
  .messages({ 'required': '必填' })  // 这个生效

📚 相关文档


对应示例文件

示例入口: i18n.ts
说明: 覆盖内置 locale 切换、字段级消息优先级,以及自定义 locale 的最小工作路径。


文档生成时间: 2026-05-08
版本: v1.0.1