schema-dsl 1.1.2 → 1.1.4

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.
@@ -0,0 +1,367 @@
1
+ # v1.0.9 变更日志
2
+
3
+ > **发布日期**: 2026-01-04
4
+ > **版本号**: v1.0.9
5
+ > **类型**: 🎉 重大改进
6
+
7
+ ---
8
+
9
+ ## 📋 变更概览
10
+
11
+ | 类型 | 数量 | 说明 |
12
+ |------|------|------|
13
+ | 🎉 新功能 | 2 | 完整多语言支持、I18nError类 |
14
+ | ⚡ 功能增强 | 1 | TypeScript类型定义完善 |
15
+ | 📚 文档更新 | 5 | 多语言相关文档 |
16
+
17
+ ---
18
+
19
+ ## 🎉 新功能
20
+
21
+ ### 1. 完整的多语言支持
22
+
23
+ **内置5种语言,开箱即用的国际化方案**
24
+
25
+ #### 支持的语言
26
+
27
+ | 语言代码 | 语言名称 | 完整度 | 说明 |
28
+ |---------|---------|--------|------|
29
+ | zh-CN | 简体中文 | 100% | 默认语言 |
30
+ | en-US | 英文(美国) | 100% | 完整翻译 |
31
+ | ja-JP | 日语 | 95% | 主要功能已翻译 |
32
+ | es-ES | 西班牙语 | 90% | 核心功能已翻译 |
33
+ | fr-FR | 法语 | 90% | 核心功能已翻译 |
34
+
35
+ #### 快速配置
36
+
37
+ **方式1:使用内置语言**
38
+
39
+ ```javascript
40
+ const { dsl, validate, Locale } = require('schema-dsl');
41
+
42
+ // 设置全局语言
43
+ Locale.setLocale('zh-CN');
44
+
45
+ const schema = dsl({ username: 'string:3-32!' });
46
+
47
+ // 中文错误消息
48
+ const result = validate(schema, { username: 'ab' });
49
+ console.log(result.errors[0].message);
50
+ // => "username长度不能少于3个字符"
51
+ ```
52
+
53
+ **方式2:配置自定义语言包目录**
54
+
55
+ ```javascript
56
+ const path = require('path');
57
+
58
+ // 应用启动时配置一次
59
+ dsl.config({
60
+ i18n: path.join(__dirname, 'locales')
61
+ });
62
+
63
+ // 自动加载目录下所有语言文件
64
+ // locales/zh-CN.js
65
+ // locales/en-US.js
66
+ // locales/custom-lang.js
67
+ ```
68
+
69
+ #### 自定义语言包
70
+
71
+ ```javascript
72
+ // locales/zh-CN.js
73
+ module.exports = {
74
+ 'required': '{{#path}} 是必填项',
75
+ 'string.min': '{{#path}} 长度不能少于 {{#min}} 个字符',
76
+ 'string.max': '{{#path}} 长度不能超过 {{#max}} 个字符',
77
+ 'email': '{{#path}} 必须是有效的邮箱地址',
78
+ 'account.notFound': '账户不存在',
79
+ 'account.insufficientBalance': '余额不足,当前余额{{balance}},需要{{required}}'
80
+ };
81
+
82
+ // locales/en-US.js
83
+ module.exports = {
84
+ 'required': '{{#path}} is required',
85
+ 'string.min': '{{#path}} must be at least {{#min}} characters',
86
+ 'string.max': '{{#path}} must not exceed {{#max}} characters',
87
+ 'email': '{{#path}} must be a valid email',
88
+ 'account.notFound': 'Account not found',
89
+ 'account.insufficientBalance': 'Insufficient balance, current: {{balance}}, required: {{required}}'
90
+ };
91
+ ```
92
+
93
+ #### 运行时切换语言
94
+
95
+ ```javascript
96
+ // 全局切换
97
+ Locale.setLocale('en-US');
98
+
99
+ // 验证时指定语言
100
+ validate(schema, data, { locale: 'ja-JP' });
101
+
102
+ // 获取当前语言
103
+ const currentLocale = Locale.getLocale(); // 'en-US'
104
+ ```
105
+
106
+ #### 参数插值
107
+
108
+ ```javascript
109
+ // 自动插值
110
+ const schema = dsl({ age: 'number:18-120!' });
111
+ validate(schema, { age: 15 });
112
+ // => "age must be at least 18" (en-US)
113
+ // => "age 必须至少为 18" (zh-CN)
114
+
115
+ // 自定义参数插值
116
+ const error = new I18nError('account.insufficientBalance', {
117
+ balance: 50,
118
+ required: 100
119
+ });
120
+ console.log(error.message);
121
+ // => "余额不足,当前余额50,需要100" (zh-CN)
122
+ // => "Insufficient balance, current: 50, required: 100" (en-US)
123
+ ```
124
+
125
+ ---
126
+
127
+ ### 2. I18nError 多语言错误类
128
+
129
+ **统一的多语言错误处理类**
130
+
131
+ #### 基础用法
132
+
133
+ ```javascript
134
+ const { I18nError } = require('schema-dsl');
135
+
136
+ // 创建错误
137
+ const error = new I18nError(
138
+ 'account.notFound', // 错误代码
139
+ {}, // 参数(可选)
140
+ 404 // HTTP状态码(可选)
141
+ );
142
+
143
+ console.log(error.code); // 'account.notFound'
144
+ console.log(error.message); // '账户不存在' (zh-CN)
145
+ console.log(error.statusCode); // 404
146
+ ```
147
+
148
+ #### 静态方法
149
+
150
+ ```javascript
151
+ // 直接抛出错误
152
+ I18nError.throw('user.noPermission');
153
+
154
+ // 断言风格
155
+ I18nError.assert(user, 'user.notFound');
156
+ I18nError.assert(
157
+ user.role === 'admin',
158
+ 'user.noPermission'
159
+ );
160
+
161
+ // 创建错误对象
162
+ const error = I18nError.create('account.notFound', {}, 404);
163
+ ```
164
+
165
+ #### 错误对象属性
166
+
167
+ ```javascript
168
+ const error = new I18nError('account.insufficientBalance', {
169
+ balance: 50,
170
+ required: 100
171
+ }, 400);
172
+
173
+ console.log(error.code); // 'account.insufficientBalance'
174
+ console.log(error.message); // '余额不足,当前余额50,需要100'
175
+ console.log(error.statusCode); // 400
176
+ console.log(error.params); // { balance: 50, required: 100 }
177
+
178
+ // JSON序列化
179
+ console.log(error.toJSON());
180
+ // {
181
+ // code: 'account.insufficientBalance',
182
+ // message: '余额不足,当前余额50,需要100',
183
+ // statusCode: 400,
184
+ // params: { balance: 50, required: 100 }
185
+ // }
186
+ ```
187
+
188
+ #### Express/Koa 集成
189
+
190
+ ```javascript
191
+ // Express 错误处理中间件
192
+ app.use((error, req, res, next) => {
193
+ if (error instanceof I18nError) {
194
+ return res.status(error.statusCode).json({
195
+ success: false,
196
+ code: error.code,
197
+ message: error.message,
198
+ params: error.params
199
+ });
200
+ }
201
+ next(error);
202
+ });
203
+
204
+ // 业务代码
205
+ app.post('/api/withdraw', async (req, res, next) => {
206
+ try {
207
+ const account = await getAccount(req.user.id);
208
+ I18nError.assert(account, 'account.notFound', {}, 404);
209
+
210
+ I18nError.assert(
211
+ account.balance >= req.body.amount,
212
+ 'account.insufficientBalance',
213
+ { balance: account.balance, required: req.body.amount },
214
+ 400
215
+ );
216
+
217
+ // 处理提现...
218
+ res.json({ success: true });
219
+ } catch (error) {
220
+ next(error);
221
+ }
222
+ });
223
+ ```
224
+
225
+ ---
226
+
227
+ ## ⚡ 功能增强
228
+
229
+ ### TypeScript 类型定义完善
230
+
231
+ **完整的类型定义,100% 类型安全**
232
+
233
+ #### 新增类型
234
+
235
+ ```typescript
236
+ // Locale 类型
237
+ interface Locale {
238
+ setLocale(locale: string): void;
239
+ getLocale(): string;
240
+ getMessage(code: string, params?: Record<string, any>): string;
241
+ setMessages(messages: Record<string, string>): void;
242
+ }
243
+
244
+ // I18nError 类型
245
+ class I18nError extends Error {
246
+ code: string;
247
+ statusCode: number;
248
+ params: Record<string, any>;
249
+
250
+ constructor(
251
+ code: string,
252
+ params?: Record<string, any>,
253
+ statusCode?: number
254
+ );
255
+
256
+ static throw(code: string, params?: Record<string, any>, statusCode?: number): never;
257
+ static assert(condition: any, code: string, params?: Record<string, any>, statusCode?: number): asserts condition;
258
+ static create(code: string, params?: Record<string, any>, statusCode?: number): I18nError;
259
+
260
+ toJSON(): object;
261
+ is(code: string): boolean;
262
+ }
263
+
264
+ // ValidationOptions 扩展
265
+ interface ValidationOptions {
266
+ locale?: string; // 新增:验证时指定语言
267
+ // ...其他选项
268
+ }
269
+ ```
270
+
271
+ #### 使用示例
272
+
273
+ ```typescript
274
+ import { dsl, validate, I18nError, Locale } from 'schema-dsl';
275
+
276
+ // 完整的类型推导
277
+ const schema = dsl({ email: 'email!' });
278
+
279
+ // 验证时指定语言
280
+ const result = validate(schema, data, { locale: 'en-US' });
281
+
282
+ // I18nError 类型安全
283
+ try {
284
+ I18nError.throw('account.notFound', {}, 404);
285
+ } catch (error) {
286
+ if (error instanceof I18nError) {
287
+ console.log(error.code); // string
288
+ console.log(error.statusCode); // number
289
+ console.log(error.params); // Record<string, any>
290
+ }
291
+ }
292
+ ```
293
+
294
+ ---
295
+
296
+ ## 📚 文档更新
297
+
298
+ 1. ✅ **多语言用户指南**: [docs/i18n-user-guide.md](../docs/i18n-user-guide.md)
299
+ 2. ✅ **I18n 完整文档**: [docs/i18n.md](../docs/i18n.md)
300
+ 3. ✅ **I18nError API 文档**: [docs/error-handling.md](../docs/error-handling.md)
301
+ 4. ✅ **自定义语言包指南**: [docs/add-custom-locale.md](../docs/add-custom-locale.md)
302
+ 5. ✅ **前端 i18n 集成**: [docs/frontend-i18n-guide.md](../docs/frontend-i18n-guide.md)
303
+
304
+ ---
305
+
306
+ ## 🔄 破坏性变更
307
+
308
+ **无破坏性变更** - 所有新功能都是可选的,默认行为保持不变。
309
+
310
+ ---
311
+
312
+ ## 🎯 升级指南
313
+
314
+ ### 从 v1.0.8 升级到 v1.0.9
315
+
316
+ ```bash
317
+ npm install schema-dsl@1.0.9
318
+ ```
319
+
320
+ **可选:启用多语言**
321
+
322
+ ```javascript
323
+ const { Locale } = require('schema-dsl');
324
+
325
+ // 设置全局语言(可选)
326
+ Locale.setLocale('zh-CN');
327
+
328
+ // 或在验证时指定(可选)
329
+ validate(schema, data, { locale: 'en-US' });
330
+ ```
331
+
332
+ **可选:使用 I18nError**
333
+
334
+ ```javascript
335
+ const { I18nError } = require('schema-dsl');
336
+
337
+ // 替代普通 Error
338
+ I18nError.throw('account.notFound');
339
+ ```
340
+
341
+ ---
342
+
343
+ ## 📦 依赖变更
344
+
345
+ **无依赖变更**
346
+
347
+ ---
348
+
349
+ ## 🙏 致谢
350
+
351
+ 感谢社区贡献者提供的多语言翻译和反馈。
352
+
353
+ ---
354
+
355
+ ## 🔗 相关链接
356
+
357
+ - [GitHub Repository](https://github.com/vextjs/schema-dsl)
358
+ - [npm Package](https://www.npmjs.com/package/schema-dsl)
359
+ - [完整多语言文档](../docs/i18n.md)
360
+ - [I18nError 示例](../examples/i18n-error.examples.js)
361
+
362
+ ---
363
+
364
+ **发布者**: schema-dsl Team
365
+ **发布时间**: 2026-01-04
366
+ **下一版本**: v1.1.0
367
+