schema-dsl 1.0.8 → 1.1.0
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 +338 -3
- package/README.md +296 -17
- package/STATUS.md +74 -3
- package/docs/FEATURE-INDEX.md +1 -1
- package/docs/add-custom-locale.md +395 -0
- package/docs/best-practices.md +3 -3
- package/docs/cache-manager.md +1 -1
- package/docs/conditional-api.md +1032 -0
- package/docs/dsl-syntax.md +1 -1
- package/docs/dynamic-locale.md +76 -30
- package/docs/error-handling.md +2 -2
- package/docs/export-guide.md +2 -2
- package/docs/export-limitations.md +3 -3
- package/docs/faq.md +6 -6
- package/docs/frontend-i18n-guide.md +19 -16
- package/docs/i18n-user-guide.md +7 -9
- package/docs/i18n.md +65 -2
- package/docs/mongodb-exporter.md +3 -3
- package/docs/multi-type-support.md +12 -2
- package/docs/mysql-exporter.md +1 -1
- package/docs/plugin-system.md +4 -4
- package/docs/postgresql-exporter.md +1 -1
- package/docs/quick-start.md +4 -4
- package/docs/troubleshooting.md +2 -2
- package/docs/type-reference.md +5 -5
- package/docs/typescript-guide.md +5 -6
- package/docs/union-type-guide.md +147 -0
- package/docs/union-types.md +277 -0
- package/docs/validate-async.md +1 -1
- package/examples/array-dsl-example.js +1 -1
- package/examples/conditional-example.js +288 -0
- package/examples/conditional-non-object.js +129 -0
- package/examples/conditional-validate-example.js +321 -0
- package/examples/union-type-example.js +127 -0
- package/examples/union-types-example.js +77 -0
- package/index.d.ts +395 -12
- package/index.js +31 -4
- package/lib/adapters/DslAdapter.js +14 -5
- package/lib/core/ConditionalBuilder.js +401 -0
- package/lib/core/DslBuilder.js +113 -0
- package/lib/core/ErrorFormatter.js +81 -33
- package/lib/core/Locale.js +13 -8
- package/lib/core/Validator.js +252 -16
- package/lib/locales/en-US.js +14 -0
- package/lib/locales/es-ES.js +4 -0
- package/lib/locales/fr-FR.js +4 -0
- package/lib/locales/ja-JP.js +9 -0
- package/lib/locales/zh-CN.js +14 -0
- package/package.json +5 -2
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
# 添加自定义语言包指南
|
|
2
|
+
|
|
3
|
+
**版本**: v1.0.9
|
|
4
|
+
**最后更新**: 2026-01-04
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 📖 概述
|
|
9
|
+
|
|
10
|
+
本指南将教你如何为 schema-dsl 添加自定义语言包或扩展现有语言。
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 🚀 快速开始
|
|
15
|
+
|
|
16
|
+
### 推荐方式:配置语言包目录(一次性加载所有语言)⭐
|
|
17
|
+
|
|
18
|
+
**正确的使用方式**:在应用启动时一次性加载所有语言包,运行时直接切换。
|
|
19
|
+
|
|
20
|
+
#### 第1步:创建语言包文件
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
#### 第1步:创建语言包文件
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# 项目结构
|
|
27
|
+
my-project/
|
|
28
|
+
├── locales/ # 语言包目录
|
|
29
|
+
│ ├── zh-CN.js # 中文(已存在,将被覆盖/合并)
|
|
30
|
+
│ ├── en-US.js # 英文(已存在,将被覆盖/合并)
|
|
31
|
+
│ └── pt-BR.js # 葡萄牙语(新增)
|
|
32
|
+
└── app.js
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### 第2步:定义语言包(`locales/pt-BR.js`)
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
module.exports = {
|
|
39
|
+
// 通用验证错误
|
|
40
|
+
'required': '{{#label}} é obrigatório',
|
|
41
|
+
'type': '{{#label}} deve ser do tipo {{#expected}}',
|
|
42
|
+
'min': '{{#label}} deve ter pelo menos {{#limit}} caracteres',
|
|
43
|
+
'max': '{{#label}} não pode exceder {{#limit}} caracteres',
|
|
44
|
+
'length': '{{#label}} deve ter exatamente {{#limit}} caracteres',
|
|
45
|
+
'pattern': '{{#label}} formato inválido',
|
|
46
|
+
'enum': '{{#label}} deve ser um dos seguintes valores: {{#allowed}}',
|
|
47
|
+
|
|
48
|
+
// 格式验证
|
|
49
|
+
'format.email': '{{#label}} deve ser um e-mail válido',
|
|
50
|
+
'format.url': '{{#label}} deve ser uma URL válida',
|
|
51
|
+
'format.uuid': '{{#label}} deve ser um UUID válido',
|
|
52
|
+
'format.date': '{{#label}} deve ser uma data válida (YYYY-MM-DD)',
|
|
53
|
+
'format.datetime': '{{#label}} deve ser uma data/hora válida (ISO 8601)',
|
|
54
|
+
|
|
55
|
+
// 字符串验证
|
|
56
|
+
'string.minLength': '{{#label}} deve ter pelo menos {{#limit}} caracteres',
|
|
57
|
+
'string.maxLength': '{{#label}} não pode exceder {{#limit}} caracteres',
|
|
58
|
+
'string.pattern': '{{#label}} formato inválido',
|
|
59
|
+
'string.alphanum': '{{#label}} deve conter apenas letras e números',
|
|
60
|
+
|
|
61
|
+
// 数字验证
|
|
62
|
+
'number.base': '{{#label}} deve ser um número',
|
|
63
|
+
'number.min': '{{#label}} não pode ser menor que {{#limit}}',
|
|
64
|
+
'number.max': '{{#label}} não pode ser maior que {{#limit}}',
|
|
65
|
+
'number.integer': '{{#label}} deve ser um inteiro',
|
|
66
|
+
'number.positive': '{{#label}} deve ser um número positivo',
|
|
67
|
+
'number.negative': '{{#label}} deve ser um número negativo',
|
|
68
|
+
|
|
69
|
+
// 布尔验证
|
|
70
|
+
'boolean.base': '{{#label}} deve ser um booleano',
|
|
71
|
+
|
|
72
|
+
// 对象验证
|
|
73
|
+
'object.base': '{{#label}} deve ser um objeto',
|
|
74
|
+
|
|
75
|
+
// 数组验证
|
|
76
|
+
'array.base': '{{#label}} deve ser um array',
|
|
77
|
+
'array.min': '{{#label}} deve ter pelo menos {{#limit}} itens',
|
|
78
|
+
'array.max': '{{#label}} não pode ter mais de {{#limit}} itens',
|
|
79
|
+
|
|
80
|
+
// 日期验证
|
|
81
|
+
'date.base': '{{#label}} deve ser uma data válida',
|
|
82
|
+
'date.min': '{{#label}} não pode ser anterior a {{#limit}}',
|
|
83
|
+
'date.max': '{{#label}} não pode ser posterior a {{#limit}}',
|
|
84
|
+
|
|
85
|
+
// 自定义模式
|
|
86
|
+
'pattern.phone.cn': 'Número de telefone inválido',
|
|
87
|
+
'pattern.idCard.cn': 'Número de identidade inválido',
|
|
88
|
+
'pattern.creditCard': 'Número de cartão de crédito inválido',
|
|
89
|
+
'pattern.objectId': 'ObjectId inválido',
|
|
90
|
+
'pattern.hexColor': 'Código de cor hexadecimal inválido',
|
|
91
|
+
'pattern.macAddress': 'Endereço MAC inválido',
|
|
92
|
+
'pattern.cron': 'Expressão Cron inválida',
|
|
93
|
+
'pattern.slug': 'Slug deve conter apenas letras minúsculas, números e hífens'
|
|
94
|
+
};
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
#### 第3步:应用启动时一次性加载所有语言
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
const { dsl, validate } = require('schema-dsl');
|
|
101
|
+
const path = require('path');
|
|
102
|
+
|
|
103
|
+
// ========== 应用启动时配置(只执行一次)==========
|
|
104
|
+
dsl.config({
|
|
105
|
+
i18n: path.join(__dirname, 'locales') // 自动加载目录下所有语言文件
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// 说明:
|
|
109
|
+
// 1. 自动扫描 locales/ 目录下的所有 .js 和 .json 文件
|
|
110
|
+
// 2. 从文件名提取语言代码(如 pt-BR.js → pt-BR)
|
|
111
|
+
// 3. 自动加载并注册所有语言包
|
|
112
|
+
// 4. 用户自定义的语言包会与系统默认语言包合并,用户的优先
|
|
113
|
+
|
|
114
|
+
// ========== 运行时直接切换语言(无需重新加载)==========
|
|
115
|
+
const schema = dsl({ username: 'string:3-32!' });
|
|
116
|
+
|
|
117
|
+
// 使用葡萄牙语
|
|
118
|
+
const result1 = validate(schema, { username: 'ab' }, { locale: 'pt-BR' });
|
|
119
|
+
// 错误消息: "username deve ter pelo menos 3 caracteres"
|
|
120
|
+
|
|
121
|
+
// 使用中文
|
|
122
|
+
const result2 = validate(schema, { username: 'ab' }, { locale: 'zh-CN' });
|
|
123
|
+
// 错误消息: "username长度不能少于3个字符"
|
|
124
|
+
|
|
125
|
+
// 使用英文
|
|
126
|
+
const result3 = validate(schema, { username: 'ab' }, { locale: 'en-US' });
|
|
127
|
+
// 错误消息: "username length must be at least 3"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### 语言包合并策略
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
// 系统内置的 zh-CN 语言包
|
|
134
|
+
const systemZhCN = {
|
|
135
|
+
'required': '{{#label}}是必填项',
|
|
136
|
+
'string.minLength': '{{#label}}长度不能少于{{#limit}}个字符'
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// 用户自定义的 locales/zh-CN.js
|
|
140
|
+
const userZhCN = {
|
|
141
|
+
'required': '{{#label}}必须填写', // 覆盖系统默认
|
|
142
|
+
'custom.myError': '自定义错误' // 新增自定义消息
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// 最终合并结果(深度合并)
|
|
146
|
+
const finalZhCN = {
|
|
147
|
+
'required': '{{#label}}必须填写', // ✅ 用户的优先
|
|
148
|
+
'string.minLength': '{{#label}}长度不能少于{{#limit}}个字符', // 保留系统默认
|
|
149
|
+
'custom.myError': '自定义错误' // 新增自定义消息
|
|
150
|
+
};
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
### 方式2:直接传入对象(适合动态配置)
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
const { dsl } = require('schema-dsl');
|
|
159
|
+
|
|
160
|
+
// 应用启动时配置
|
|
161
|
+
dsl.config({
|
|
162
|
+
i18n: {
|
|
163
|
+
'pt-BR': require('./locales/pt-BR'),
|
|
164
|
+
'de-DE': require('./locales/de-DE'),
|
|
165
|
+
'ko-KR': require('./locales/ko-KR')
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// 运行时直接切换
|
|
170
|
+
validate(schema, data, { locale: 'pt-BR' });
|
|
171
|
+
validate(schema, data, { locale: 'de-DE' });
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## ⚠️ 错误示例(不推荐)
|
|
177
|
+
|
|
178
|
+
### ❌ 错误:运行时单个加载语言包
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
const { Locale } = require('schema-dsl');
|
|
182
|
+
|
|
183
|
+
// ❌ 不推荐:在每次验证前动态加载
|
|
184
|
+
function validateUser(data, locale) {
|
|
185
|
+
if (locale === 'pt-BR') {
|
|
186
|
+
Locale.addLocale('pt-BR', require('./locales/pt-BR')); // 每次都加载,性能差
|
|
187
|
+
}
|
|
188
|
+
return validate(schema, data, { locale });
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ✅ 正确:应用启动时一次性加载
|
|
195
|
+
// app.js 启动入口
|
|
196
|
+
dsl.config({ i18n: './locales' }); // 只加载一次
|
|
197
|
+
|
|
198
|
+
// 运行时直接切换,无需重新加载
|
|
199
|
+
function validateUser(data, locale) {
|
|
200
|
+
return validate(schema, data, { locale }); // ✅ 直接切换,性能好
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### 为什么推荐"首次加载,运行时切换"?
|
|
205
|
+
|
|
206
|
+
| 方式 | 加载次数 | 性能 | 内存 | 推荐度 |
|
|
207
|
+
|------|---------|------|------|--------|
|
|
208
|
+
| **首次加载所有** | 1次 | ⭐⭐⭐⭐⭐ 极快 | 低 | ✅ 强烈推荐 |
|
|
209
|
+
| 运行时单个加载 | N次 | ⭐⭐ 慢 | 中 | ❌ 不推荐 |
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 🎯 完整示例
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
// ========== app.js(应用启动入口)==========
|
|
217
|
+
const express = require('express');
|
|
218
|
+
const { dsl, validate } = require('schema-dsl');
|
|
219
|
+
const path = require('path');
|
|
220
|
+
|
|
221
|
+
// 应用启动时一次性加载所有语言包
|
|
222
|
+
dsl.config({
|
|
223
|
+
i18n: path.join(__dirname, 'locales')
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
const app = express();
|
|
227
|
+
|
|
228
|
+
// ========== routes/user.js(业务路由)==========
|
|
229
|
+
const userSchema = dsl({
|
|
230
|
+
username: 'string:3-32!',
|
|
231
|
+
email: 'email!',
|
|
232
|
+
age: 'number:18-120'
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
app.post('/api/users', (req, res) => {
|
|
236
|
+
// 从请求头获取用户语言偏好
|
|
237
|
+
const locale = req.headers['accept-language'] || 'en-US';
|
|
238
|
+
|
|
239
|
+
// 验证(直接切换语言,无需加载)
|
|
240
|
+
const result = validate(userSchema, req.body, { locale });
|
|
241
|
+
|
|
242
|
+
if (!result.valid) {
|
|
243
|
+
return res.status(400).json({
|
|
244
|
+
errors: result.errors // 自动使用用户偏好的语言
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// 处理请求...
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## 📋 完整的消息键列表
|
|
255
|
+
|
|
256
|
+
### 通用键
|
|
257
|
+
|
|
258
|
+
| 键名 | 说明 | 示例 |
|
|
259
|
+
|-----|------|------|
|
|
260
|
+
| `required` | 必填字段 | `{{#label}} é obrigatório` |
|
|
261
|
+
| `type` | 类型错误 | `{{#label}} deve ser do tipo {{#expected}}` |
|
|
262
|
+
| `min` | 最小长度(通用) | `{{#label}} deve ter pelo menos {{#limit}} caracteres` |
|
|
263
|
+
| `max` | 最大长度(通用) | `{{#label}} não pode exceder {{#limit}} caracteres` |
|
|
264
|
+
| `length` | 精确长度 | `{{#label}} deve ter exatamente {{#limit}} caracteres` |
|
|
265
|
+
| `pattern` | 模式匹配 | `{{#label}} formato inválido` |
|
|
266
|
+
| `enum` | 枚举值 | `{{#label}} deve ser um dos seguintes: {{#allowed}}` |
|
|
267
|
+
|
|
268
|
+
### 字符串验证键
|
|
269
|
+
|
|
270
|
+
| 键名 | 说明 | 可用变量 |
|
|
271
|
+
|-----|------|---------|
|
|
272
|
+
| `string.minLength` | 最小长度 | `{{#label}}`, `{{#limit}}` |
|
|
273
|
+
| `string.maxLength` | 最大长度 | `{{#label}}`, `{{#limit}}` |
|
|
274
|
+
| `string.length` | 精确长度 | `{{#label}}`, `{{#limit}}` |
|
|
275
|
+
| `string.pattern` | 模式匹配 | `{{#label}}` |
|
|
276
|
+
| `string.alphanum` | 字母数字 | `{{#label}}` |
|
|
277
|
+
| `string.enum` | 枚举值 | `{{#label}}`, `{{#valids}}` |
|
|
278
|
+
|
|
279
|
+
### 数字验证键
|
|
280
|
+
|
|
281
|
+
| 键名 | 说明 | 可用变量 |
|
|
282
|
+
|-----|------|---------|
|
|
283
|
+
| `number.base` | 类型错误 | `{{#label}}` |
|
|
284
|
+
| `number.min` | 最小值 | `{{#label}}`, `{{#limit}}` |
|
|
285
|
+
| `number.max` | 最大值 | `{{#label}}`, `{{#limit}}` |
|
|
286
|
+
| `number.integer` | 整数 | `{{#label}}` |
|
|
287
|
+
| `number.positive` | 正数 | `{{#label}}` |
|
|
288
|
+
| `number.negative` | 负数 | `{{#label}}` |
|
|
289
|
+
| `number.precision` | 小数精度 | `{{#label}}`, `{{#limit}}` |
|
|
290
|
+
| `number.port` | 端口号 | `{{#label}}` |
|
|
291
|
+
|
|
292
|
+
### 格式验证键
|
|
293
|
+
|
|
294
|
+
| 键名 | 说明 |
|
|
295
|
+
|-----|------|
|
|
296
|
+
| `format.email` | 邮箱格式 |
|
|
297
|
+
| `format.url` | URL格式 |
|
|
298
|
+
| `format.uuid` | UUID格式 |
|
|
299
|
+
| `format.date` | 日期格式 |
|
|
300
|
+
| `format.datetime` | 日期时间格式 |
|
|
301
|
+
| `format.time` | 时间格式 |
|
|
302
|
+
| `format.ipv4` | IPv4地址 |
|
|
303
|
+
| `format.ipv6` | IPv6地址 |
|
|
304
|
+
| `format.binary` | Base64编码 |
|
|
305
|
+
|
|
306
|
+
### 自定义模式键
|
|
307
|
+
|
|
308
|
+
| 键名 | 说明 |
|
|
309
|
+
|-----|------|
|
|
310
|
+
| `pattern.phone.cn` | 中国手机号 |
|
|
311
|
+
| `pattern.phone.us` | 美国电话号 |
|
|
312
|
+
| `pattern.idCard.cn` | 中国身份证 |
|
|
313
|
+
| `pattern.creditCard` | 信用卡号 |
|
|
314
|
+
| `pattern.objectId` | MongoDB ObjectId |
|
|
315
|
+
| `pattern.hexColor` | 十六进制颜色 |
|
|
316
|
+
| `pattern.macAddress` | MAC地址 |
|
|
317
|
+
| `pattern.cron` | Cron表达式 |
|
|
318
|
+
| `pattern.slug` | URL别名 |
|
|
319
|
+
| `pattern.username` | 用户名 |
|
|
320
|
+
| `pattern.password.weak` | 弱密码 |
|
|
321
|
+
| `pattern.password.medium` | 中等密码 |
|
|
322
|
+
| `pattern.password.strong` | 强密码 |
|
|
323
|
+
| `pattern.password.veryStrong` | 超强密码 |
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## 🎨 模板变量
|
|
328
|
+
|
|
329
|
+
所有错误消息支持以下模板变量:
|
|
330
|
+
|
|
331
|
+
| 变量 | 说明 | 使用示例 |
|
|
332
|
+
|------|------|---------|
|
|
333
|
+
| `{{#label}}` | 字段标签 | `{{#label}} é obrigatório` |
|
|
334
|
+
| `{{#limit}}` | 限制值(长度/大小) | `deve ter pelo menos {{#limit}} caracteres` |
|
|
335
|
+
| `{{#allowed}}` | 允许的值列表 | `deve ser um dos seguintes: {{#allowed}}` |
|
|
336
|
+
| `{{#expected}}` | 期望的类型 | `deve ser do tipo {{#expected}}` |
|
|
337
|
+
| `{{#valids}}` | 有效值列表(数组) | `deve ser: {{#valids}}` |
|
|
338
|
+
| `{{#path}}` | 字段路径 | `Erro no campo {{#path}}` |
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## 📚 参考内置语言包
|
|
343
|
+
|
|
344
|
+
你可以参考内置的语言包作为模板:
|
|
345
|
+
|
|
346
|
+
```javascript
|
|
347
|
+
// 查看中文语言包
|
|
348
|
+
const zhCN = require('schema-dsl/lib/locales/zh-CN');
|
|
349
|
+
console.log(zhCN);
|
|
350
|
+
|
|
351
|
+
// 查看英文语言包
|
|
352
|
+
const enUS = require('schema-dsl/lib/locales/en-US');
|
|
353
|
+
console.log(enUS);
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
或者直接查看源码:
|
|
357
|
+
- 中文:`node_modules/schema-dsl/lib/locales/zh-CN.js`
|
|
358
|
+
- 英文:`node_modules/schema-dsl/lib/locales/en-US.js`
|
|
359
|
+
- 日语:`node_modules/schema-dsl/lib/locales/ja-JP.js`
|
|
360
|
+
- 西班牙语:`node_modules/schema-dsl/lib/locales/es-ES.js`
|
|
361
|
+
- 法语:`node_modules/schema-dsl/lib/locales/fr-FR.js`
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## ✅ 最佳实践
|
|
366
|
+
|
|
367
|
+
1. **完整性**:确保翻译所有常用的错误消息键
|
|
368
|
+
2. **一致性**:保持错误消息风格统一
|
|
369
|
+
3. **模板变量**:正确使用 `{{#label}}`、`{{#limit}}` 等变量
|
|
370
|
+
4. **测试**:添加语言包后进行测试,确保所有消息正确显示
|
|
371
|
+
5. **文档**:为自定义语言包编写使用说明
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## 🤝 贡献语言包
|
|
376
|
+
|
|
377
|
+
如果你为 schema-dsl 添加了新语言包,欢迎提交 Pull Request:
|
|
378
|
+
|
|
379
|
+
1. Fork 项目
|
|
380
|
+
2. 在 `lib/locales/` 目录创建新语言文件(如 `pt-BR.js`)
|
|
381
|
+
3. 完整翻译所有消息键
|
|
382
|
+
4. 在 `lib/locales/index.js` 中注册新语言
|
|
383
|
+
5. 添加测试用例(在 `test/unit/locales/` 目录)
|
|
384
|
+
6. 提交 Pull Request
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## 📞 支持
|
|
389
|
+
|
|
390
|
+
如果你在添加语言包时遇到问题:
|
|
391
|
+
|
|
392
|
+
- 查看 [多语言配置指南](./i18n.md)
|
|
393
|
+
- 查看 [动态多语言配置指南](./dynamic-locale.md)
|
|
394
|
+
- 提交 Issue: https://github.com/your-repo/schema-dsl/issues
|
|
395
|
+
|
package/docs/best-practices.md
CHANGED
|
@@ -79,7 +79,7 @@ const schema = dsl({
|
|
|
79
79
|
|
|
80
80
|
### 3. 使用预设验证器
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
SchemaI-DSL 提供了常用的预设验证器,开箱即用:
|
|
83
83
|
|
|
84
84
|
```javascript
|
|
85
85
|
const schema = dsl({
|
|
@@ -639,7 +639,7 @@ setInterval(() => {
|
|
|
639
639
|
|
|
640
640
|
## 性能基准参考
|
|
641
641
|
|
|
642
|
-
基于
|
|
642
|
+
基于 SchemaI-DSL 的性能测试:
|
|
643
643
|
|
|
644
644
|
| 操作 | 性能指标 |
|
|
645
645
|
|------|---------|
|
|
@@ -655,7 +655,7 @@ setInterval(() => {
|
|
|
655
655
|
|
|
656
656
|
## 总结
|
|
657
657
|
|
|
658
|
-
遵循这些最佳实践,你的
|
|
658
|
+
遵循这些最佳实践,你的 SchemaI-DSL 代码将具备:
|
|
659
659
|
|
|
660
660
|
✅ **高性能** - 通过预编译和缓存
|
|
661
661
|
✅ **高安全性** - 避免常见安全陷阱
|