schema-dsl 1.2.4 → 2.0.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.
Files changed (242) hide show
  1. package/CHANGELOG.md +87 -210
  2. package/README.md +391 -2249
  3. package/dist/DslBuilder-DQDN0ZxZ.d.cts +341 -0
  4. package/dist/DslBuilder-DkLaOo9Q.d.ts +341 -0
  5. package/dist/Validator-C7GsVQOH.d.cts +192 -0
  6. package/dist/Validator-hFWKGxir.d.ts +192 -0
  7. package/dist/index.cjs +6594 -0
  8. package/dist/index.d.cts +1145 -0
  9. package/dist/index.d.ts +1145 -0
  10. package/dist/index.js +6528 -0
  11. package/dist/plugin-CIKtTMtS.d.cts +246 -0
  12. package/dist/plugin-CIKtTMtS.d.ts +246 -0
  13. package/dist/plugins/custom-format.cjs +3802 -0
  14. package/dist/plugins/custom-format.d.cts +12 -0
  15. package/dist/plugins/custom-format.d.ts +12 -0
  16. package/dist/plugins/custom-format.js +3772 -0
  17. package/dist/plugins/custom-type-example.cjs +3795 -0
  18. package/dist/plugins/custom-type-example.d.cts +8 -0
  19. package/dist/plugins/custom-type-example.d.ts +8 -0
  20. package/dist/plugins/custom-type-example.js +3765 -0
  21. package/dist/plugins/custom-validator.cjs +146 -0
  22. package/dist/plugins/custom-validator.d.cts +10 -0
  23. package/dist/plugins/custom-validator.d.ts +10 -0
  24. package/dist/plugins/custom-validator.js +121 -0
  25. package/docs/FEATURE-INDEX.md +102 -68
  26. package/docs/add-custom-locale.md +48 -35
  27. package/docs/add-keyword.md +24 -0
  28. package/docs/api-reference.md +396 -154
  29. package/docs/api.md +13 -0
  30. package/docs/best-practices-project-structure.md +19 -10
  31. package/docs/best-practices.md +93 -53
  32. package/docs/cache-manager.md +23 -15
  33. package/docs/compile.md +45 -0
  34. package/docs/conditional-api.md +40 -11
  35. package/docs/custom-extensions-guide.md +80 -152
  36. package/docs/design-philosophy.md +76 -71
  37. package/docs/doc-index.md +324 -0
  38. package/docs/dsl-syntax.md +69 -19
  39. package/docs/dynamic-locale.md +24 -14
  40. package/docs/enum.md +12 -5
  41. package/docs/error-handling.md +53 -44
  42. package/docs/export-guide.md +47 -8
  43. package/docs/export-limitations.md +27 -11
  44. package/docs/faq.md +86 -67
  45. package/docs/frontend-i18n-guide.md +26 -12
  46. package/docs/i18n-user-guide.md +60 -47
  47. package/docs/i18n.md +51 -32
  48. package/docs/index.md +48 -0
  49. package/docs/json-schema-basics.md +40 -0
  50. package/docs/label-vs-description.md +12 -3
  51. package/docs/markdown-exporter.md +15 -6
  52. package/docs/mongodb-exporter.md +11 -4
  53. package/docs/multi-language.md +26 -0
  54. package/docs/multi-type-support.md +26 -33
  55. package/docs/mysql-exporter.md +9 -2
  56. package/docs/number-operators.md +12 -5
  57. package/docs/optional-marker-guide.md +28 -23
  58. package/docs/performance-guide.md +49 -0
  59. package/docs/plugin-system.md +205 -366
  60. package/docs/plugin-type-registration.md +34 -0
  61. package/docs/postgresql-exporter.md +9 -2
  62. package/docs/public/favicon.svg +5 -0
  63. package/docs/quick-start.md +37 -363
  64. package/docs/runtime-locale-support.md +20 -9
  65. package/docs/schema-helper.md +10 -5
  66. package/docs/schema-utils-advanced-issues.md +23 -0
  67. package/docs/schema-utils-best-practices.md +20 -0
  68. package/docs/schema-utils-chaining.md +7 -0
  69. package/docs/schema-utils.md +76 -42
  70. package/docs/security-checklist.md +20 -0
  71. package/docs/string-extensions.md +17 -9
  72. package/docs/troubleshooting.md +36 -21
  73. package/docs/type-converter.md +41 -50
  74. package/docs/type-reference.md +38 -15
  75. package/docs/typescript-guide.md +53 -42
  76. package/docs/union-type-guide.md +11 -1
  77. package/docs/union-types.md +10 -3
  78. package/docs/validate-async.md +36 -25
  79. package/docs/validate-batch.md +49 -0
  80. package/docs/validate-dsl-object-support.md +33 -28
  81. package/docs/validate.md +36 -16
  82. package/docs/validation-guide.md +25 -7
  83. package/docs/validator.md +39 -0
  84. package/package.json +85 -27
  85. package/plugins/custom-format.cjs +8 -0
  86. package/plugins/custom-type-example.cjs +8 -0
  87. package/plugins/custom-validator.cjs +8 -0
  88. package/src/adapters/DslAdapter.ts +111 -0
  89. package/src/adapters/index.ts +1 -0
  90. package/src/config/constants.ts +83 -0
  91. package/src/config/index.ts +2 -0
  92. package/src/config/patterns.ts +77 -0
  93. package/src/core/CacheManager.ts +159 -0
  94. package/src/core/ConditionalBuilder.ts +382 -0
  95. package/src/core/ConditionalRuntime.ts +28 -0
  96. package/src/core/ConditionalValidator.ts +255 -0
  97. package/src/core/DslBuilder.ts +677 -0
  98. package/src/core/ErrorCodes.ts +38 -0
  99. package/src/core/ErrorFormatter.ts +271 -0
  100. package/src/core/JSONSchemaCore.ts +65 -0
  101. package/src/core/Locale.ts +187 -0
  102. package/src/core/MessageTemplate.ts +42 -0
  103. package/src/core/ObjectDslBuilder.ts +64 -0
  104. package/src/core/PluginManager.ts +326 -0
  105. package/src/core/StringExtensions.ts +140 -0
  106. package/src/core/TemplateEngine.ts +44 -0
  107. package/src/core/Validator.ts +448 -0
  108. package/src/errors/I18nError.ts +159 -0
  109. package/src/errors/ValidationError.ts +105 -0
  110. package/src/exporters/BaseExporter.ts +60 -0
  111. package/src/exporters/MarkdownExporter.ts +305 -0
  112. package/src/exporters/MongoDBExporter.ts +126 -0
  113. package/src/exporters/MySQLExporter.ts +155 -0
  114. package/src/exporters/PostgreSQLExporter.ts +222 -0
  115. package/src/exporters/index.ts +18 -0
  116. package/src/index.ts +633 -0
  117. package/{lib/locales/en-US.js → src/locales/en-US.ts} +21 -37
  118. package/{lib/locales/es-ES.js → src/locales/es-ES.ts} +63 -16
  119. package/{lib/locales/fr-FR.js → src/locales/fr-FR.ts} +74 -27
  120. package/src/locales/index.ts +103 -0
  121. package/{lib/locales/ja-JP.js → src/locales/ja-JP.ts} +59 -17
  122. package/src/locales/types.ts +156 -0
  123. package/{lib/locales/zh-CN.js → src/locales/zh-CN.ts} +21 -38
  124. package/src/parser/ConstraintParser.ts +101 -0
  125. package/src/parser/DslParser.ts +470 -0
  126. package/src/parser/SchemaCompiler.ts +66 -0
  127. package/src/parser/TypeRegistry.ts +250 -0
  128. package/src/parser/index.ts +6 -0
  129. package/src/plugins/custom-format.ts +126 -0
  130. package/src/plugins/custom-type-example.ts +108 -0
  131. package/src/plugins/custom-validator.ts +140 -0
  132. package/src/types/conditional.ts +28 -0
  133. package/src/types/config.ts +59 -0
  134. package/src/types/dsl.ts +131 -0
  135. package/src/types/error.ts +60 -0
  136. package/src/types/index.ts +17 -0
  137. package/src/types/infer.ts +128 -0
  138. package/src/types/plugin.ts +58 -0
  139. package/src/types/safe-regex.d.ts +9 -0
  140. package/src/types/schema.ts +66 -0
  141. package/src/types/validate.ts +71 -0
  142. package/src/utils/SchemaHelper.ts +196 -0
  143. package/src/utils/SchemaUtils.ts +346 -0
  144. package/src/utils/TypeConverter.ts +215 -0
  145. package/src/utils/index.ts +10 -0
  146. package/src/validators/CustomKeywords.ts +477 -0
  147. package/.eslintignore +0 -11
  148. package/.eslintrc.json +0 -27
  149. package/CONTRIBUTING.md +0 -368
  150. package/STATUS.md +0 -491
  151. package/changelogs/v1.0.0.md +0 -328
  152. package/changelogs/v1.0.9.md +0 -367
  153. package/changelogs/v1.1.0.md +0 -389
  154. package/changelogs/v1.1.1.md +0 -308
  155. package/changelogs/v1.1.2.md +0 -183
  156. package/changelogs/v1.1.3.md +0 -161
  157. package/changelogs/v1.1.4.md +0 -432
  158. package/changelogs/v1.1.5.md +0 -493
  159. package/changelogs/v1.1.6.md +0 -211
  160. package/changelogs/v1.1.8.md +0 -376
  161. package/changelogs/v1.2.3.md +0 -124
  162. package/docs/INDEX.md +0 -252
  163. package/docs/issues-resolved-summary.md +0 -196
  164. package/docs/performance-benchmark-report.md +0 -179
  165. package/docs/performance-quick-reference.md +0 -123
  166. package/docs/user-questions-answered.md +0 -353
  167. package/docs/validation-rules-v1.0.2.md +0 -1608
  168. package/examples/README.md +0 -81
  169. package/examples/array-dsl-example.js +0 -227
  170. package/examples/conditional-example.js +0 -288
  171. package/examples/conditional-non-object.js +0 -129
  172. package/examples/conditional-validate-example.js +0 -321
  173. package/examples/custom-extension.js +0 -85
  174. package/examples/dsl-match-example.js +0 -74
  175. package/examples/dsl-style.js +0 -118
  176. package/examples/dynamic-locale-configuration.js +0 -348
  177. package/examples/dynamic-locale-example.js +0 -287
  178. package/examples/enum.examples.js +0 -324
  179. package/examples/export-demo.js +0 -130
  180. package/examples/express-integration.js +0 -376
  181. package/examples/i18n-error-handling-complete.js +0 -381
  182. package/examples/i18n-error-handling-quickstart.md +0 -0
  183. package/examples/i18n-error.examples.js +0 -181
  184. package/examples/i18n-full-demo.js +0 -301
  185. package/examples/i18n-memory-safety.examples.js +0 -268
  186. package/examples/markdown-export.js +0 -71
  187. package/examples/middleware-usage.js +0 -93
  188. package/examples/new-features-comparison.js +0 -315
  189. package/examples/password-reset/README.md +0 -153
  190. package/examples/password-reset/schema.js +0 -26
  191. package/examples/password-reset/test.js +0 -101
  192. package/examples/plugin-system.examples.js +0 -205
  193. package/examples/schema-utils-chaining.examples.js +0 -250
  194. package/examples/simple-example.js +0 -122
  195. package/examples/slug.examples.js +0 -179
  196. package/examples/string-extensions.js +0 -297
  197. package/examples/union-type-example.js +0 -127
  198. package/examples/union-types-example.js +0 -77
  199. package/examples/user-registration/README.md +0 -156
  200. package/examples/user-registration/routes.js +0 -92
  201. package/examples/user-registration/schema.js +0 -150
  202. package/examples/user-registration/server.js +0 -74
  203. package/index.d.ts +0 -3540
  204. package/index.js +0 -457
  205. package/index.mjs +0 -60
  206. package/lib/adapters/DslAdapter.js +0 -871
  207. package/lib/adapters/index.js +0 -20
  208. package/lib/config/constants.js +0 -286
  209. package/lib/config/patterns/common.js +0 -47
  210. package/lib/config/patterns/creditCard.js +0 -9
  211. package/lib/config/patterns/idCard.js +0 -9
  212. package/lib/config/patterns/index.js +0 -9
  213. package/lib/config/patterns/licensePlate.js +0 -4
  214. package/lib/config/patterns/passport.js +0 -4
  215. package/lib/config/patterns/phone.js +0 -9
  216. package/lib/config/patterns/postalCode.js +0 -5
  217. package/lib/core/CacheManager.js +0 -376
  218. package/lib/core/ConditionalBuilder.js +0 -503
  219. package/lib/core/DslBuilder.js +0 -1400
  220. package/lib/core/ErrorCodes.js +0 -233
  221. package/lib/core/ErrorFormatter.js +0 -445
  222. package/lib/core/JSONSchemaCore.js +0 -347
  223. package/lib/core/Locale.js +0 -130
  224. package/lib/core/MessageTemplate.js +0 -98
  225. package/lib/core/PluginManager.js +0 -448
  226. package/lib/core/StringExtensions.js +0 -240
  227. package/lib/core/Validator.js +0 -654
  228. package/lib/errors/I18nError.js +0 -328
  229. package/lib/errors/ValidationError.js +0 -191
  230. package/lib/exporters/MarkdownExporter.js +0 -420
  231. package/lib/exporters/MongoDBExporter.js +0 -162
  232. package/lib/exporters/MySQLExporter.js +0 -212
  233. package/lib/exporters/PostgreSQLExporter.js +0 -289
  234. package/lib/exporters/index.js +0 -24
  235. package/lib/locales/index.js +0 -8
  236. package/lib/utils/LRUCache.js +0 -174
  237. package/lib/utils/SchemaHelper.js +0 -240
  238. package/lib/utils/SchemaUtils.js +0 -445
  239. package/lib/utils/TypeConverter.js +0 -245
  240. package/lib/utils/index.js +0 -13
  241. package/lib/validators/CustomKeywords.js +0 -616
  242. package/lib/validators/index.js +0 -11
@@ -1,118 +0,0 @@
1
- /**
2
- * DSL风格API示例 v2.0
3
- *
4
- * 演示新的DSL Builder Pattern:
5
- * - 简单场景:纯字符串DSL
6
- * - 复杂场景:字符串直接链式调用(✨ 无需 dsl() 包裹)
7
- */
8
-
9
- const { dsl, Validator } = require('../index');
10
-
11
- // ========== 1. 简单场景:纯字符串DSL ==========
12
-
13
- const simpleSchema = dsl({
14
- username: 'string:3-32!', // 必填字符串,长度3-32
15
- email: 'email!', // 必填邮箱
16
- age: 'number:18-120', // 可选数字,范围18-120
17
- status: 'active|inactive|pending', // 枚举值
18
- tags: 'array<string:1-20>', // 字符串数组,每项长度1-20
19
- });
20
-
21
- console.log('========== 简单Schema(纯DSL)==========');
22
- console.log(JSON.stringify(simpleSchema, null, 2));
23
-
24
- // ========== 2. 复杂场景:字符串直接链式调用 ✨ ==========
25
-
26
- const complexSchema = dsl({
27
- // ✨ 超简洁!字符串直接调用链式方法,无需 dsl() 包裹
28
- username: 'string:3-32!'
29
- .pattern(/^[a-zA-Z0-9_]+$/)
30
- .messages({
31
- 'pattern': '只能包含字母、数字和下划线'
32
- })
33
- .label('用户名')
34
- .description('用户登录名'),
35
-
36
- // ✨ 邮箱:直接链式
37
- email: 'email!'
38
- .label('邮箱地址')
39
- .messages({
40
- 'format': '请输入有效的邮箱地址'
41
- }),
42
-
43
- // ✨ 密码:复杂正则 + 自定义消息
44
- password: 'string:8-64!'
45
- .pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$/)
46
- .messages({
47
- 'min': '密码长度不能少于8位',
48
- 'pattern': '密码必须包含大小写字母和数字'
49
- })
50
- .label('密码'),
51
-
52
- // 年龄:简单约束(无需链式)
53
- age: 'number:18-120',
54
-
55
- // 角色:枚举(无需链式)
56
- role: 'user|admin|moderator',
57
-
58
- // 嵌套对象:混合使用
59
- profile: {
60
- bio: 'string:500', // 简单:纯DSL
61
- website: 'url' // ✨ 也可以链式
62
- .description('个人主页'),
63
- avatar: 'url'
64
- .label('头像URL')
65
- }
66
- });
67
-
68
- console.log('\n========== 复杂Schema(DSL + 链式)==========');
69
- console.log(JSON.stringify(complexSchema, null, 2));
70
-
71
- // ========== 3. 验证数据 ==========
72
-
73
- const { validate } = require('../index');
74
-
75
- const testData = {
76
- username: 'john_doe',
77
- email: 'john@example.com',
78
- password: 'Password123',
79
- age: 25,
80
- role: 'user',
81
- profile: {
82
- bio: 'Full-stack developer',
83
- website: 'https://example.com',
84
- avatar: 'https://example.com/avatar.jpg'
85
- }
86
- };
87
-
88
- console.log('\n========== 验证数据 ==========');
89
- const result = validate(complexSchema, testData);
90
- console.log('验证结果:', result.valid ? '✅ 通过' : '❌ 失败');
91
- if (!result.valid) {
92
- console.log('错误:', result.errors);
93
- }
94
-
95
- // ========== 4. 展示API优势 ==========
96
-
97
- console.log('\n========== API对比 ==========');
98
-
99
- // v1.0: 需要 dsl() 包裹
100
- console.log('❌ v1.0(需要 dsl()):');
101
- console.log(` email: dsl('email!')
102
- .pattern(/custom/)
103
- .messages({ 'pattern': '格式不正确' })
104
- .label('邮箱地址')`);
105
-
106
- // v2.0: 字符串直接链式
107
- console.log('\n✅ v2.0(字符串直接链式):');
108
- console.log(` email: 'email!'
109
- .pattern(/custom/)
110
- .messages({ 'pattern': '格式不正确' })
111
- .label('邮箱地址')`);
112
-
113
- console.log('\n✅ DSL v2.0 示例运行完成!');
114
- console.log('💡 提示:简单字段用纯DSL,复杂字段直接链式调用');
115
- console.log('🎉 特色:字符串直接调用方法,无需 dsl() 包裹!');
116
-
117
-
118
-
@@ -1,348 +0,0 @@
1
- /**
2
- * 动态多语言配置完整示例
3
- *
4
- * 演示如何在各种场景下动态配置和切换语言
5
- */
6
-
7
- const { dsl, validate, Locale } = require('../index');
8
-
9
- console.log('========== 动态多语言配置示例 ==========\n');
10
-
11
- // ========================================
12
- // 示例 1: 基本的语言切换
13
- // ========================================
14
- console.log('【示例 1】基本的语言切换\n');
15
-
16
- const userSchema = dsl({
17
- email: 'email!',
18
- age: 'number:18-120!'
19
- });
20
-
21
- // 中文环境
22
- Locale.setLocale('zh-CN');
23
- let result = validate(userSchema, { email: 'invalid', age: 10 });
24
- console.log('中文错误:', result.errors.map(e => e.message).join(', '));
25
-
26
- // 切换到英文
27
- Locale.setLocale('en-US');
28
- result = validate(userSchema, { email: 'invalid', age: 10 });
29
- console.log('英文错误:', result.errors.map(e => e.message).join(', '));
30
-
31
- console.log('\n' + '='.repeat(60) + '\n');
32
-
33
- // ========================================
34
- // 示例 2: 使用 dsl.config() 批量配置语言包
35
- // ========================================
36
- console.log('【示例 2】使用 dsl.config() 批量配置\n');
37
-
38
- dsl.config({
39
- locales: {
40
- 'zh-CN': {
41
- 'custom.tooYoung': '{{#label}}年龄太小,需满18岁',
42
- 'custom.emailTaken': '{{#label}}已被占用'
43
- },
44
- 'en-US': {
45
- 'custom.tooYoung': '{{#label}} is too young, must be 18+',
46
- 'custom.emailTaken': '{{#label}} is already taken'
47
- }
48
- }
49
- });
50
-
51
- // 测试自定义消息
52
- Locale.setLocale('zh-CN');
53
- console.log('中文自定义:', Locale.getMessage('custom.tooYoung'));
54
-
55
- Locale.setLocale('en-US');
56
- console.log('英文自定义:', Locale.getMessage('custom.tooYoung'));
57
-
58
- console.log('\n' + '='.repeat(60) + '\n');
59
-
60
- // ========================================
61
- // 示例 3: 模拟前端语言切换
62
- // ========================================
63
- console.log('【示例 3】模拟前端语言切换\n');
64
-
65
- class LanguageManager {
66
- constructor() {
67
- this.locale = 'en-US';
68
- this.storage = {}; // 模拟 localStorage
69
- }
70
-
71
- // 获取用户偏好语言
72
- getUserPreference() {
73
- return this.storage.userLanguage || this.detectBrowserLanguage();
74
- }
75
-
76
- // 检测浏览器语言(模拟)
77
- detectBrowserLanguage() {
78
- // 模拟 navigator.language
79
- const browserLang = 'zh-CN';
80
- const langMap = {
81
- 'zh': 'zh-CN',
82
- 'zh-CN': 'zh-CN',
83
- 'en': 'en-US',
84
- 'en-US': 'en-US'
85
- };
86
- return langMap[browserLang] || langMap[browserLang.split('-')[0]] || 'en-US';
87
- }
88
-
89
- // 切换语言
90
- changeLanguage(newLocale) {
91
- console.log(`切换语言: ${this.locale} → ${newLocale}`);
92
- this.locale = newLocale;
93
- this.storage.userLanguage = newLocale;
94
- Locale.setLocale(newLocale);
95
- }
96
-
97
- // 初始化
98
- init() {
99
- const preferredLang = this.getUserPreference();
100
- console.log(`初始化语言: ${preferredLang}`);
101
- this.changeLanguage(preferredLang);
102
- }
103
- }
104
-
105
- const langManager = new LanguageManager();
106
- langManager.init();
107
-
108
- // 验证(使用检测到的语言)
109
- result = validate(userSchema, { email: 'test', age: 15 });
110
- console.log('当前语言:', Locale.getLocale());
111
- console.log('错误消息:', result.errors.map(e => e.message).join(', '));
112
-
113
- // 用户手动切换
114
- langManager.changeLanguage('en-US');
115
- result = validate(userSchema, { email: 'test', age: 15 });
116
- console.log('错误消息:', result.errors.map(e => e.message).join(', '));
117
-
118
- console.log('\n' + '='.repeat(60) + '\n');
119
-
120
- // ========================================
121
- // 示例 4: 模拟服务端请求语言切换
122
- // ========================================
123
- console.log('【示例 4】服务端请求语言切换(安全模式)\n');
124
-
125
- function validateWithLocale(schema, data, requestLocale) {
126
- // 保存原始语言
127
- const originalLocale = Locale.getLocale();
128
-
129
- try {
130
- // 临时切换到请求的语言
131
- Locale.setLocale(requestLocale);
132
-
133
- // 执行验证
134
- const result = validate(schema, data);
135
-
136
- return {
137
- locale: requestLocale,
138
- errors: result.errors
139
- };
140
- } finally {
141
- // 恢复原始语言(重要!)
142
- Locale.setLocale(originalLocale);
143
- }
144
- }
145
-
146
- // 模拟多个并发请求
147
- console.log('请求1 (中文):');
148
- const req1 = validateWithLocale(userSchema, { email: 'bad' }, 'zh-CN');
149
- console.log(' 语言:', req1.locale);
150
- console.log(' 错误:', req1.errors.map(e => e.message).join(', '));
151
-
152
- console.log('\n请求2 (英文):');
153
- const req2 = validateWithLocale(userSchema, { email: 'bad' }, 'en-US');
154
- console.log(' 语言:', req2.locale);
155
- console.log(' 错误:', req2.errors.map(e => e.message).join(', '));
156
-
157
- console.log('\n请求3 (日文):');
158
- const req3 = validateWithLocale(userSchema, { email: 'bad' }, 'ja-JP');
159
- console.log(' 语言:', req3.locale);
160
- console.log(' 错误:', req3.errors.map(e => e.message).join(', '));
161
-
162
- console.log('\n全局语言未被污染:', Locale.getLocale());
163
-
164
- console.log('\n' + '='.repeat(60) + '\n');
165
-
166
- // ========================================
167
- // 示例 5: 动态加载语言包(模拟)
168
- // ========================================
169
- console.log('【示例 5】动态加载语言包\n');
170
-
171
- class LocaleLoader {
172
- constructor() {
173
- this.loadedLocales = new Set(['en-US']); // 默认已加载
174
- }
175
-
176
- // 模拟异步加载语言包
177
- async loadLocale(locale) {
178
- if (this.loadedLocales.has(locale)) {
179
- console.log(`语言包 "${locale}" 已加载,跳过`);
180
- return;
181
- }
182
-
183
- console.log(`正在加载语言包 "${locale}"...`);
184
-
185
- // 模拟网络延迟
186
- await new Promise(resolve => setTimeout(resolve, 100));
187
-
188
- // 模拟语言包内容
189
- const mockLanguagePacks = {
190
- 'fr-FR': {
191
- 'required': '{{#label}} est requis',
192
- 'format.email': '{{#label}} doit être une adresse e-mail valide'
193
- },
194
- 'de-DE': {
195
- 'required': '{{#label}} ist erforderlich',
196
- 'format.email': '{{#label}} muss eine gültige E-Mail-Adresse sein'
197
- }
198
- };
199
-
200
- const messages = mockLanguagePacks[locale];
201
- if (messages) {
202
- Locale.addLocale(locale, messages);
203
- this.loadedLocales.add(locale);
204
- console.log(`✅ 语言包 "${locale}" 加载成功`);
205
- } else {
206
- console.log(`❌ 语言包 "${locale}" 不存在,回退到英文`);
207
- return 'en-US';
208
- }
209
- }
210
-
211
- // 切换语言(带自动加载)
212
- async changeLanguage(locale) {
213
- await this.loadLocale(locale);
214
- Locale.setLocale(locale);
215
- console.log(`当前语言: ${Locale.getLocale()}\n`);
216
- }
217
- }
218
-
219
- const loader = new LocaleLoader();
220
-
221
- (async () => {
222
- // 加载法语
223
- await loader.changeLanguage('fr-FR');
224
- result = validate(userSchema, { email: 'mauvais' });
225
- console.log('法语错误:', result.errors.map(e => e.message).join(', '));
226
-
227
- console.log('');
228
-
229
- // 加载德语
230
- await loader.changeLanguage('de-DE');
231
- result = validate(userSchema, { email: 'schlecht' });
232
- console.log('德语错误:', result.errors.map(e => e.message).join(', '));
233
-
234
- console.log('\n' + '='.repeat(60) + '\n');
235
-
236
- // ========================================
237
- // 示例 6: 同时获取多种语言的错误消息
238
- // ========================================
239
- console.log('【示例 6】同时获取多种语言的错误消息\n');
240
-
241
- const ErrorFormatter = require('../lib/core/ErrorFormatter');
242
- const Validator = require('../lib/core/Validator');
243
-
244
- const validator = new Validator();
245
- const invalidData = { email: 'invalid-email', age: 10 };
246
-
247
- // 执行验证
248
- const validationResult = validator.validate(userSchema, invalidData);
249
-
250
- // 获取多种语言的错误消息
251
- const languages = ['zh-CN', 'en-US', 'ja-JP'];
252
- const multiLangErrors = {};
253
-
254
- languages.forEach(lang => {
255
- const formatter = new ErrorFormatter(lang);
256
- multiLangErrors[lang] = formatter.formatDetailed(validationResult.errors);
257
- });
258
-
259
- console.log('多语言错误消息:');
260
- console.log(JSON.stringify(multiLangErrors, null, 2));
261
-
262
- console.log('\n' + '='.repeat(60) + '\n');
263
-
264
- // ========================================
265
- // 示例 7: 完整的前端应用场景
266
- // ========================================
267
- console.log('【示例 7】完整的前端应用场景\n');
268
-
269
- class FormValidator {
270
- constructor() {
271
- this.schema = dsl({
272
- username: 'string:3-20!'.label('username'),
273
- email: 'email!'.label('email'),
274
- password: 'string:8-32!'.label('password')
275
- });
276
-
277
- // 初始化语言
278
- this.initLanguage();
279
- }
280
-
281
- initLanguage() {
282
- // 1. 从 localStorage 恢复
283
- const savedLang = this.getStoredLanguage();
284
-
285
- // 2. 如果没有保存,检测浏览器语言
286
- const lang = savedLang || this.detectBrowserLanguage();
287
-
288
- // 3. 设置语言
289
- this.changeLanguage(lang);
290
-
291
- console.log(`应用启动,语言初始化为: ${lang}`);
292
- }
293
-
294
- getStoredLanguage() {
295
- // 模拟 localStorage.getItem
296
- return null; // 首次访问
297
- }
298
-
299
- detectBrowserLanguage() {
300
- // 模拟 navigator.language
301
- return 'zh-CN';
302
- }
303
-
304
- changeLanguage(lang) {
305
- console.log(`用户选择语言: ${lang}`);
306
- Locale.setLocale(lang);
307
- // 模拟 localStorage.setItem
308
- }
309
-
310
- validateForm(formData) {
311
- const result = validate(this.schema, formData);
312
-
313
- return {
314
- valid: result.valid,
315
- errors: result.errors.map(err => ({
316
- field: err.path,
317
- message: err.message
318
- }))
319
- };
320
- }
321
- }
322
-
323
- const formValidator = new FormValidator();
324
-
325
- // 模拟表单提交
326
- console.log('\n提交表单(中文环境):');
327
- let formResult = formValidator.validateForm({
328
- username: 'ab',
329
- email: 'bad',
330
- password: '123'
331
- });
332
- console.log('验证结果:', JSON.stringify(formResult, null, 2));
333
-
334
- // 用户切换语言
335
- console.log('\n用户切换到英文:');
336
- formValidator.changeLanguage('en-US');
337
-
338
- console.log('\n再次提交表单(英文环境):');
339
- formResult = formValidator.validateForm({
340
- username: 'ab',
341
- email: 'bad',
342
- password: '123'
343
- });
344
- console.log('验证结果:', JSON.stringify(formResult, null, 2));
345
-
346
- console.log('\n========== 所有示例完成 ==========');
347
- })();
348
-