schema-dsl 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +195 -12
- package/README.md +39 -17
- package/STATUS.md +74 -3
- package/docs/add-custom-locale.md +395 -0
- package/docs/dynamic-locale.md +74 -28
- package/docs/frontend-i18n-guide.md +18 -15
- package/docs/i18n-user-guide.md +7 -9
- package/docs/i18n.md +65 -2
- package/index.d.ts +63 -5
- package/index.js +12 -3
- package/lib/core/ErrorFormatter.js +102 -33
- package/lib/core/Validator.js +6 -14
- package/package.json +3 -2
package/docs/i18n.md
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
# 多语言配置指南
|
|
2
2
|
|
|
3
|
-
**版本**: v1.0.
|
|
4
|
-
**最后更新**:
|
|
3
|
+
**版本**: v1.0.9
|
|
4
|
+
**最后更新**: 2026-01-04
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 📚 多语言文档导航
|
|
9
|
+
|
|
10
|
+
根据你的需求选择合适的文档:
|
|
11
|
+
|
|
12
|
+
- 🚀 **新手快速上手**: [i18n.md](./i18n.md)(当前文档)- 5分钟学会基础用法
|
|
13
|
+
- 📖 **完整使用指南**: [i18n-user-guide.md](./i18n-user-guide.md) - 详细的用户指南和最佳实践
|
|
14
|
+
- 🎯 **添加新语言**: [add-custom-locale.md](./add-custom-locale.md) - 添加自定义语言包教程
|
|
15
|
+
- 🔄 **动态切换语言**: [dynamic-locale.md](./dynamic-locale.md) - API开发中的动态语言切换
|
|
16
|
+
- 🌐 **前端集成**: [frontend-i18n-guide.md](./frontend-i18n-guide.md) - 前后端分离项目集成指南
|
|
5
17
|
|
|
6
18
|
---
|
|
7
19
|
|
|
@@ -9,10 +21,61 @@
|
|
|
9
21
|
|
|
10
22
|
schema-dsl 支持完整的多语言功能,允许你自定义字段标签和错误消息的翻译。
|
|
11
23
|
|
|
24
|
+
**v1.0.9 新增**:
|
|
25
|
+
- ✅ 支持参数化语言切换(无需修改全局状态)
|
|
26
|
+
- ✅ 支持自定义错误消息(三种格式)
|
|
27
|
+
- ✅ TypeScript 类型定义完整
|
|
28
|
+
|
|
12
29
|
---
|
|
13
30
|
|
|
14
31
|
## 🚀 快速开始
|
|
15
32
|
|
|
33
|
+
### 方式1:验证时动态指定语言(推荐)⭐
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
const { dsl, validate } = require('schema-dsl');
|
|
37
|
+
|
|
38
|
+
const schema = dsl({ username: 'string:3-32!' });
|
|
39
|
+
|
|
40
|
+
// 使用中文错误消息
|
|
41
|
+
const result = validate(schema, { username: 'ab' }, { locale: 'zh-CN' });
|
|
42
|
+
// message: "username长度不能少于3个字符"
|
|
43
|
+
|
|
44
|
+
// 使用英文错误消息
|
|
45
|
+
const result2 = validate(schema, { username: 'ab' }, { locale: 'en-US' });
|
|
46
|
+
// message: "username length must be at least 3"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 方式2:使用全局配置(向后兼容)
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
const { Locale } = require('schema-dsl');
|
|
53
|
+
|
|
54
|
+
// 设置默认语言
|
|
55
|
+
Locale.setLocale('zh-CN');
|
|
56
|
+
|
|
57
|
+
// 后续验证会使用中文错误消息
|
|
58
|
+
const result = validate(schema, data);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 📝 内置语言支持
|
|
64
|
+
|
|
65
|
+
schema-dsl 内置了以下语言包:
|
|
66
|
+
|
|
67
|
+
| 语言代码 | 语言名称 | 支持状态 |
|
|
68
|
+
|---------|---------|---------|
|
|
69
|
+
| `zh-CN` | 简体中文 | ✅ 完整支持 |
|
|
70
|
+
| `en-US` | 英语(美国)| ✅ 完整支持 |
|
|
71
|
+
| `ja-JP` | 日语 | ✅ 完整支持 |
|
|
72
|
+
| `es-ES` | 西班牙语 | ✅ 完整支持 |
|
|
73
|
+
| `fr-FR` | 法语 | ✅ 完整支持 |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 🎯 高级用法
|
|
78
|
+
|
|
16
79
|
### 基础配置
|
|
17
80
|
|
|
18
81
|
```javascript
|
package/index.d.ts
CHANGED
|
@@ -112,6 +112,35 @@ declare module 'schema-dsl' {
|
|
|
112
112
|
field?: string;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
/**
|
|
116
|
+
* 验证选项
|
|
117
|
+
*
|
|
118
|
+
* @description validate() 和 Validator.validate() 的配置选项
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* const options: ValidateOptions = {
|
|
123
|
+
* format: true,
|
|
124
|
+
* locale: 'zh-CN',
|
|
125
|
+
* messages: {
|
|
126
|
+
* min: '至少需要 {{#limit}} 个字符'
|
|
127
|
+
* }
|
|
128
|
+
* };
|
|
129
|
+
*
|
|
130
|
+
* const result = validate(schema, data, options);
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
export interface ValidateOptions {
|
|
134
|
+
/** 是否格式化错误(默认true) */
|
|
135
|
+
format?: boolean;
|
|
136
|
+
/** 动态指定语言(如 'zh-CN', 'en-US', 'ja-JP', 'es-ES', 'fr-FR') */
|
|
137
|
+
locale?: string;
|
|
138
|
+
/** 自定义错误消息 */
|
|
139
|
+
messages?: ErrorMessages;
|
|
140
|
+
/** 扩展选项 */
|
|
141
|
+
[key: string]: any;
|
|
142
|
+
}
|
|
143
|
+
|
|
115
144
|
/**
|
|
116
145
|
* 错误消息对象
|
|
117
146
|
*
|
|
@@ -1257,9 +1286,27 @@ declare module 'schema-dsl' {
|
|
|
1257
1286
|
* 验证数据
|
|
1258
1287
|
* @param schema - JSON Schema对象
|
|
1259
1288
|
* @param data - 要验证的数据
|
|
1289
|
+
* @param options - 验证选项
|
|
1260
1290
|
* @returns 验证结果
|
|
1291
|
+
*
|
|
1292
|
+
* @example
|
|
1293
|
+
* ```typescript
|
|
1294
|
+
* const validator = new Validator();
|
|
1295
|
+
*
|
|
1296
|
+
* // 使用默认语言
|
|
1297
|
+
* const result1 = validator.validate(schema, data);
|
|
1298
|
+
*
|
|
1299
|
+
* // 动态指定语言
|
|
1300
|
+
* const result2 = validator.validate(schema, data, { locale: 'zh-CN' });
|
|
1301
|
+
*
|
|
1302
|
+
* // 自定义错误消息
|
|
1303
|
+
* const result3 = validator.validate(schema, data, {
|
|
1304
|
+
* locale: 'zh-CN',
|
|
1305
|
+
* messages: { min: '至少{{#limit}}个字符' }
|
|
1306
|
+
* });
|
|
1307
|
+
* ```
|
|
1261
1308
|
*/
|
|
1262
|
-
validate<T = any>(schema: JSONSchema, data: any): ValidationResult<T>;
|
|
1309
|
+
validate<T = any>(schema: JSONSchema, data: any, options?: ValidateOptions): ValidationResult<T>;
|
|
1263
1310
|
|
|
1264
1311
|
/**
|
|
1265
1312
|
* 获取底层ajv实例
|
|
@@ -1300,14 +1347,25 @@ declare module 'schema-dsl' {
|
|
|
1300
1347
|
* import { dsl, validate } from 'schema-dsl';
|
|
1301
1348
|
*
|
|
1302
1349
|
* const schema = dsl({ email: 'email!' });
|
|
1303
|
-
*
|
|
1304
|
-
*
|
|
1305
|
-
*
|
|
1350
|
+
*
|
|
1351
|
+
* // 基本验证
|
|
1352
|
+
* const result1 = validate(schema, { email: 'test@example.com' });
|
|
1353
|
+
*
|
|
1354
|
+
* // 指定语言
|
|
1355
|
+
* const result2 = validate(schema, { email: 'invalid' }, { locale: 'zh-CN' });
|
|
1356
|
+
*
|
|
1357
|
+
* if (result2.valid) {
|
|
1306
1358
|
* console.log('验证通过');
|
|
1359
|
+
* } else {
|
|
1360
|
+
* console.log('错误:', result2.errors); // 中文错误消息
|
|
1307
1361
|
* }
|
|
1308
1362
|
* ```
|
|
1309
1363
|
*/
|
|
1310
|
-
export function validate<T = any>(
|
|
1364
|
+
export function validate<T = any>(
|
|
1365
|
+
schema: JSONSchema | SchemaIO,
|
|
1366
|
+
data: any,
|
|
1367
|
+
options?: ValidateOptions
|
|
1368
|
+
): ValidationResult<T>;
|
|
1311
1369
|
|
|
1312
1370
|
/**
|
|
1313
1371
|
* 便捷异步验证方法(推荐)
|
package/index.js
CHANGED
|
@@ -128,16 +128,25 @@ function getDefaultValidator() {
|
|
|
128
128
|
* 便捷验证方法(使用默认Validator)
|
|
129
129
|
* @param {Object} schema - JSON Schema对象
|
|
130
130
|
* @param {*} data - 待验证数据
|
|
131
|
+
* @param {Object} [options] - 验证选项
|
|
132
|
+
* @param {boolean} [options.format=true] - 是否格式化错误
|
|
133
|
+
* @param {string} [options.locale] - 动态指定语言(如 'zh-CN', 'en-US')
|
|
134
|
+
* @param {Object} [options.messages] - 自定义错误消息
|
|
131
135
|
* @returns {Object} 验证结果
|
|
132
136
|
*
|
|
133
137
|
* @example
|
|
134
138
|
* const { validate, dsl } = require('schema-dsl');
|
|
135
139
|
*
|
|
136
140
|
* const schema = dsl({ email: 'email!' });
|
|
137
|
-
*
|
|
141
|
+
*
|
|
142
|
+
* // 基本验证
|
|
143
|
+
* const result1 = validate(schema, { email: 'test@example.com' });
|
|
144
|
+
*
|
|
145
|
+
* // 指定语言
|
|
146
|
+
* const result2 = validate(schema, { email: 'invalid' }, { locale: 'zh-CN' });
|
|
138
147
|
*/
|
|
139
|
-
function validate(schema, data) {
|
|
140
|
-
return getDefaultValidator().validate(schema, data);
|
|
148
|
+
function validate(schema, data, options) {
|
|
149
|
+
return getDefaultValidator().validate(schema, data, options);
|
|
141
150
|
}
|
|
142
151
|
|
|
143
152
|
// ========== 工具函数 ==========
|
|
@@ -38,20 +38,41 @@ class ErrorFormatter {
|
|
|
38
38
|
/**
|
|
39
39
|
* 格式化单个错误或错误数组
|
|
40
40
|
* @param {Object|Array<Object>} error - 错误对象或错误数组
|
|
41
|
-
* @param {string} [
|
|
41
|
+
* @param {string|Object} [localeOrOptions] - 语言代码字符串或选项对象
|
|
42
|
+
* @param {string} [localeOrOptions.locale] - 动态指定语言(可选)
|
|
43
|
+
* @param {Object} [localeOrOptions.messages] - 自定义错误消息(可选)
|
|
42
44
|
* @returns {string|Array<Object>} 格式化后的错误消息或错误对象数组
|
|
43
45
|
*/
|
|
44
|
-
format(error,
|
|
46
|
+
format(error, localeOrOptions) {
|
|
47
|
+
|
|
48
|
+
// ✅ 支持两种调用方式:
|
|
49
|
+
// 1. format(errors, 'zh-CN') - 旧版兼容
|
|
50
|
+
// 2. format(errors, { locale: 'zh-CN', messages: {...} }) - 新版增强
|
|
51
|
+
let locale;
|
|
52
|
+
let customMessages;
|
|
53
|
+
|
|
54
|
+
if (typeof localeOrOptions === 'string') {
|
|
55
|
+
// 旧版:直接传入语言代码
|
|
56
|
+
locale = localeOrOptions;
|
|
57
|
+
} else if (typeof localeOrOptions === 'object' && localeOrOptions !== null) {
|
|
58
|
+
// 新版:传入选项对象
|
|
59
|
+
locale = localeOrOptions.locale;
|
|
60
|
+
customMessages = localeOrOptions.messages;
|
|
61
|
+
}
|
|
62
|
+
|
|
45
63
|
// 如果是数组,格式化为详细对象数组
|
|
46
64
|
if (Array.isArray(error)) {
|
|
47
|
-
return this.formatDetailed(error, locale);
|
|
65
|
+
return this.formatDetailed(error, locale, customMessages);
|
|
48
66
|
}
|
|
49
67
|
|
|
50
68
|
// 获取当前使用的消息模板
|
|
51
69
|
const messages = locale ? this._loadMessages(locale) : this.messages;
|
|
52
70
|
|
|
71
|
+
// 合并自定义消息
|
|
72
|
+
const finalMessages = customMessages ? { ...messages, ...customMessages } : messages;
|
|
73
|
+
|
|
53
74
|
// 单个错误对象格式化
|
|
54
|
-
const template =
|
|
75
|
+
const template = finalMessages[error.type] || error.message;
|
|
55
76
|
return this._interpolate(template, {
|
|
56
77
|
...error,
|
|
57
78
|
path: error.path || 'value',
|
|
@@ -73,16 +94,42 @@ class ErrorFormatter {
|
|
|
73
94
|
* 格式化为详细对象
|
|
74
95
|
* @param {Array<Object>} errors - ajv错误数组
|
|
75
96
|
* @param {string} [locale] - 动态指定语言(可选)
|
|
97
|
+
* @param {Object} [customMessages] - 自定义错误消息(可选)
|
|
76
98
|
* @returns {Array<Object>} 详细错误对象数组
|
|
77
99
|
*/
|
|
78
|
-
formatDetailed(errors, locale) {
|
|
100
|
+
formatDetailed(errors, locale, customMessages) {
|
|
101
|
+
|
|
79
102
|
if (!Array.isArray(errors)) {
|
|
80
103
|
errors = [errors];
|
|
81
104
|
}
|
|
82
105
|
|
|
106
|
+
// 过滤冗余的包装错误(v1.0.7.1 增强)
|
|
107
|
+
// 当存在具体字段错误时,移除通用的包装错误
|
|
108
|
+
const hasConcreteErrors = errors.some(err => {
|
|
109
|
+
const keyword = err.keyword;
|
|
110
|
+
// 包装错误关键字:if, anyOf, oneOf, allOf
|
|
111
|
+
return keyword !== 'if' &&
|
|
112
|
+
keyword !== 'anyOf' &&
|
|
113
|
+
keyword !== 'oneOf' &&
|
|
114
|
+
keyword !== 'error';
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
if (hasConcreteErrors) {
|
|
118
|
+
// 过滤掉包装错误(这些是通用的组合验证错误)
|
|
119
|
+
errors = errors.filter(err => {
|
|
120
|
+
const keyword = err.keyword;
|
|
121
|
+
return keyword !== 'if' &&
|
|
122
|
+
keyword !== 'anyOf' &&
|
|
123
|
+
keyword !== 'oneOf';
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
83
127
|
// 获取当前使用的消息模板
|
|
84
128
|
const messages = locale ? this._loadMessages(locale) : this.messages;
|
|
85
129
|
|
|
130
|
+
// ✅ 合并参数传入的自定义消息(在整个 map 循环中使用)
|
|
131
|
+
const finalMessages = customMessages ? { ...messages, ...customMessages } : messages;
|
|
132
|
+
|
|
86
133
|
return errors.map(err => {
|
|
87
134
|
// 处理 ajv 错误格式
|
|
88
135
|
const keyword = err.keyword || err.type || 'validation';
|
|
@@ -104,22 +151,27 @@ class ErrorFormatter {
|
|
|
104
151
|
|
|
105
152
|
if (label) {
|
|
106
153
|
// 如果显式设置了 label,尝试翻译它
|
|
107
|
-
if (
|
|
108
|
-
label =
|
|
154
|
+
if (finalMessages[label]) {
|
|
155
|
+
label = finalMessages[label];
|
|
109
156
|
}
|
|
110
157
|
} else {
|
|
111
158
|
// 如果没有显式设置 label,尝试自动查找翻译 (label.fieldName)
|
|
112
159
|
// 将路径分隔符 / 转换为 . (例如 address/city -> address.city)
|
|
113
160
|
const autoKey = `label.${fieldName.replace(/\//g, '.')}`;
|
|
114
|
-
if (
|
|
115
|
-
label =
|
|
161
|
+
if (finalMessages[autoKey]) {
|
|
162
|
+
label = finalMessages[autoKey];
|
|
116
163
|
} else {
|
|
117
164
|
// 没找到翻译,回退到 fieldName
|
|
118
165
|
label = fieldName;
|
|
119
166
|
}
|
|
120
167
|
}
|
|
121
168
|
|
|
122
|
-
|
|
169
|
+
// Schema 中的自定义消息
|
|
170
|
+
const schemaCustomMessages = schema._customMessages || {};
|
|
171
|
+
|
|
172
|
+
// ✅ 合并优先级:schemaCustomMessages > finalMessages
|
|
173
|
+
// schemaCustomMessages 是字段级的自定义消息,优先级最高
|
|
174
|
+
const mergedMessages = { ...finalMessages, ...schemaCustomMessages };
|
|
123
175
|
|
|
124
176
|
// 关键字映射 (ajv keyword -> schema-dsl 简写)
|
|
125
177
|
// 支持 min/max 作为 minLength/maxLength 的简写
|
|
@@ -139,18 +191,38 @@ class ErrorFormatter {
|
|
|
139
191
|
const mappedKeyword = keywordMap[keyword] || keyword;
|
|
140
192
|
const type = schema.type || 'string';
|
|
141
193
|
|
|
142
|
-
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
194
|
+
|
|
195
|
+
// ✅ 优化:如果 schema 中有自定义消息,优先使用
|
|
196
|
+
// 支持三种自定义消息格式:
|
|
197
|
+
// 1. 键引用:_customMessages.pattern = "pattern.objectId" → 查找语言包中的 "pattern.objectId"
|
|
198
|
+
// 2. 模板字符串:_customMessages.min = "{{#label}}必须大于{{#limit}}" → 直接使用并插值
|
|
199
|
+
// 3. 最终消息:_customMessages.pattern = "手机号格式不正确" → 直接使用
|
|
200
|
+
let message;
|
|
201
|
+
|
|
202
|
+
// 1. 首先检查 schema 是否为该 keyword 定义了自定义消息
|
|
203
|
+
let customValue = schemaCustomMessages[keyword] || schemaCustomMessages[mappedKeyword];
|
|
204
|
+
|
|
205
|
+
if (customValue) {
|
|
206
|
+
// 尝试从 mergedMessages 中查找这个键
|
|
207
|
+
const lookupResult = mergedMessages[customValue];
|
|
208
|
+
|
|
209
|
+
if (lookupResult) {
|
|
210
|
+
// 找到了,说明它是一个键引用
|
|
211
|
+
message = lookupResult;
|
|
212
|
+
} else {
|
|
213
|
+
// 没找到,说明它本身就是模板或最终消息,直接使用
|
|
214
|
+
message = customValue;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// 2. 如果没有自定义消息,按照通用查找顺序
|
|
219
|
+
if (!message) {
|
|
220
|
+
message = mergedMessages[`${type}.${keyword}`] ||
|
|
221
|
+
mergedMessages[`${type}.${mappedKeyword}`] ||
|
|
222
|
+
mergedMessages[mappedKeyword] ||
|
|
223
|
+
mergedMessages[keyword] ||
|
|
224
|
+
mergedMessages['default'];
|
|
225
|
+
}
|
|
154
226
|
|
|
155
227
|
// 自动查找 format 类型的消息 (例如 format.email)
|
|
156
228
|
if (!message && mappedKeyword === 'format' && err.params && err.params.format) {
|
|
@@ -160,25 +232,22 @@ class ErrorFormatter {
|
|
|
160
232
|
|
|
161
233
|
const formatKey = `format.${formatName}`;
|
|
162
234
|
|
|
163
|
-
// 优先查找
|
|
164
|
-
if (
|
|
165
|
-
message =
|
|
166
|
-
}
|
|
167
|
-
// 其次查找全局/语言包中的 format.email
|
|
168
|
-
else if (messages[formatKey]) {
|
|
169
|
-
message = messages[formatKey];
|
|
235
|
+
// 优先查找 mergedMessages 中的 format.email
|
|
236
|
+
if (mergedMessages[formatKey]) {
|
|
237
|
+
message = mergedMessages[formatKey];
|
|
170
238
|
}
|
|
171
239
|
}
|
|
172
240
|
|
|
173
241
|
if (!message) {
|
|
174
242
|
// 使用默认模板
|
|
175
|
-
const template =
|
|
243
|
+
const template = mergedMessages[mappedKeyword] || mergedMessages[keyword] || err.message || 'Validation error';
|
|
176
244
|
message = template;
|
|
177
245
|
} else {
|
|
178
246
|
// 检查 message 是否为 key (包含点号且无空格,或者是已知的 key)
|
|
179
247
|
// 如果是 key,尝试从 messages 中查找
|
|
180
|
-
if (typeof message === 'string' && (message.includes('.') ||
|
|
181
|
-
|
|
248
|
+
if (typeof message === 'string' && (message.includes('.') || mergedMessages[message])) {
|
|
249
|
+
|
|
250
|
+
let translated = mergedMessages[message];
|
|
182
251
|
|
|
183
252
|
// 尝试回退查找 (例如 pattern.phone.cn -> pattern.phone)
|
|
184
253
|
if (!translated && message.includes('.')) {
|
|
@@ -186,7 +255,7 @@ class ErrorFormatter {
|
|
|
186
255
|
while (parts.length > 1 && !translated) {
|
|
187
256
|
parts.pop();
|
|
188
257
|
const fallbackKey = parts.join('.');
|
|
189
|
-
translated =
|
|
258
|
+
translated = mergedMessages[fallbackKey];
|
|
190
259
|
}
|
|
191
260
|
}
|
|
192
261
|
|
package/lib/core/Validator.js
CHANGED
|
@@ -115,18 +115,7 @@ class Validator {
|
|
|
115
115
|
* @returns {Object} 验证结果 { valid: boolean, errors: Array, data: * }
|
|
116
116
|
*/
|
|
117
117
|
validate(schema, data, options = {}) {
|
|
118
|
-
// ✅
|
|
119
|
-
if (options.locale && options.locale !== Locale.getLocale()) {
|
|
120
|
-
const originalLocale = Locale.getLocale();
|
|
121
|
-
Locale.setLocale(options.locale);
|
|
122
|
-
try {
|
|
123
|
-
return this._validateInternal(schema, data, options);
|
|
124
|
-
} finally {
|
|
125
|
-
Locale.setLocale(originalLocale);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// 正常流程(无需切换语言)
|
|
118
|
+
// ✅ 优化:直接传递 locale 到内部方法,不再切换全局状态
|
|
130
119
|
return this._validateInternal(schema, data, options);
|
|
131
120
|
}
|
|
132
121
|
|
|
@@ -175,10 +164,13 @@ class Validator {
|
|
|
175
164
|
// 执行验证
|
|
176
165
|
const valid = validate(data);
|
|
177
166
|
|
|
178
|
-
//
|
|
167
|
+
// ✅ 优化:直接传递 locale 和 messages 到格式化器,不修改全局状态
|
|
179
168
|
const errors = valid ? [] : (
|
|
180
169
|
shouldFormat
|
|
181
|
-
? this.errorFormatter.format(validate.errors,
|
|
170
|
+
? this.errorFormatter.format(validate.errors, {
|
|
171
|
+
locale,
|
|
172
|
+
messages: options.messages
|
|
173
|
+
})
|
|
182
174
|
: validate.errors
|
|
183
175
|
);
|
|
184
176
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "schema-dsl",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "简洁强大的JSON Schema验证库 - DSL语法 + String扩展 + 便捷validate",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"ajv-formats": "^2.1.1"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
+
"benchmark": "^2.1.4",
|
|
60
61
|
"chai": "^4.5.0",
|
|
61
62
|
"eslint": "^8.57.1",
|
|
62
63
|
"joi": "^18.0.2",
|
|
@@ -67,4 +68,4 @@
|
|
|
67
68
|
"yup": "^1.7.1",
|
|
68
69
|
"zod": "^4.2.1"
|
|
69
70
|
}
|
|
70
|
-
}
|
|
71
|
+
}
|