TypeBox 将错误消息翻译为中文
TypeBox 是一个用于在 TypeScript 中动态创建 JSON Schema 的工具库,性能很高,Elysia.js 校验参数时底层依赖的就是这个库。
类似 Zod,官方提供了一个 SetErrorFunction 方法来自定义错误消息。
借助 AI,很容易可以将官方默认的英文错误消息,翻译为中文。
核心代码
import { Kind } from "@sinclair/typebox" import { ErrorFunctionParameter, ValueErrorType, SetErrorFunction } from "@sinclair/typebox/errors" /** 使用 zh-CN 作为默认语言创建错误消息 */ export function zhError(error: ErrorFunctionParameter) { switch (error.errorType) { case ValueErrorType.ArrayContains: return '数组应包含至少一个匹配的值' case ValueErrorType.ArrayMaxContains: return `数组包含的匹配值不应超过 ${error.schema.maxContains} 个` case ValueErrorType.ArrayMinContains: return `数组应包含至少 ${error.schema.minContains} 个匹配值` case ValueErrorType.ArrayMaxItems: return `数组长度应小于或等于 ${error.schema.maxItems}` case ValueErrorType.ArrayMinItems: return `数组长度应大于或等于 ${error.schema.minItems}` case ValueErrorType.ArrayUniqueItems: return '数组元素应唯一' case ValueErrorType.Array: return '应为数组类型' case ValueErrorType.AsyncIterator: return '应为异步迭代器' case ValueErrorType.BigIntExclusiveMaximum: return `BigInt 应小于 ${error.schema.exclusiveMaximum}` case ValueErrorType.BigIntExclusiveMinimum: return `BigInt 应大于 ${error.schema.exclusiveMinimum}` case ValueErrorType.BigIntMaximum: return `BigInt 应小于或等于 ${error.schema.maximum}` case ValueErrorType.BigIntMinimum: return `BigInt 应大于或等于 ${error.schema.minimum}` case ValueErrorType.BigIntMultipleOf: return `BigInt 应为 ${error.schema.multipleOf} 的倍数` case ValueErrorType.BigInt: return '应为 BigInt 类型' case ValueErrorType.Boolean: return '应为布尔类型' case ValueErrorType.DateExclusiveMinimumTimestamp: return `日期时间戳应大于 ${error.schema.exclusiveMinimumTimestamp}` case ValueErrorType.DateExclusiveMaximumTimestamp: return `日期时间戳应小于 ${error.schema.exclusiveMaximumTimestamp}` case ValueErrorType.DateMinimumTimestamp: return `日期时间戳应大于或等于 ${error.schema.minimumTimestamp}` case ValueErrorType.DateMaximumTimestamp: return `日期时间戳应小于或等于 ${error.schema.maximumTimestamp}` case ValueErrorType.DateMultipleOfTimestamp: return `日期时间戳应为 ${error.schema.multipleOfTimestamp} 的倍数` case ValueErrorType.Date: return '应为日期类型' case ValueErrorType.Function: return '应为函数类型' case ValueErrorType.IntegerExclusiveMaximum: return `整数应小于 ${error.schema.exclusiveMaximum}` case ValueErrorType.IntegerExclusiveMinimum: return `整数应大于 ${error.schema.exclusiveMinimum}` case ValueErrorType.IntegerMaximum: return `整数应小于或等于 ${error.schema.maximum}` case ValueErrorType.IntegerMinimum: return `整数应大于或等于 ${error.schema.minimum}` case ValueErrorType.IntegerMultipleOf: return `整数应为 ${error.schema.multipleOf} 的倍数` case ValueErrorType.Integer: return '应为整数类型' case ValueErrorType.IntersectUnevaluatedProperties: return '存在未预期的属性' case ValueErrorType.Intersect: return '所有值均应匹配' case ValueErrorType.Iterator: return '应为迭代器' case ValueErrorType.Literal: return typeof error.schema.const === 'string' ? `期望值为 '${error.schema.const}'` : `期望值为 ${error.schema.const}` case ValueErrorType.Never: return '不应存在此值' case ValueErrorType.Not: return '值不应匹配当前模式' case ValueErrorType.Null: return '应为 null' case ValueErrorType.NumberExclusiveMaximum: return `数值应小于 ${error.schema.exclusiveMaximum}` case ValueErrorType.NumberExclusiveMinimum: return `数值应大于 ${error.schema.exclusiveMinimum}` case ValueErrorType.NumberMaximum: return `数值应小于或等于 ${error.schema.maximum}` case ValueErrorType.NumberMinimum: return `数值应大于或等于 ${error.schema.minimum}` case ValueErrorType.NumberMultipleOf: return `数值应为 ${error.schema.multipleOf} 的倍数` case ValueErrorType.Number: return '应为数值类型' case ValueErrorType.Object: return '应为对象类型' case ValueErrorType.ObjectAdditionalProperties: return '存在未预期的属性' case ValueErrorType.ObjectMaxProperties: return `对象属性数量不应超过 ${error.schema.maxProperties} 个` case ValueErrorType.ObjectMinProperties: return `对象属性数量应至少为 ${error.schema.minProperties} 个` case ValueErrorType.ObjectRequiredProperty: return '属性必填' case ValueErrorType.Promise: return '应为 Promise 对象' case ValueErrorType.RegExp: return '字符串不符合正则表达式' case ValueErrorType.StringFormatUnknown: return `未知的格式 '${error.schema.format}'` case ValueErrorType.StringFormat: return `字符串不符合 '${error.schema.format}' 格式` case ValueErrorType.StringMaxLength: return `字符串长度不应超过 ${error.schema.maxLength}` case ValueErrorType.StringMinLength: return `字符串长度应至少为 ${error.schema.minLength}` case ValueErrorType.StringPattern: return `字符串不符合模式 '${error.schema.pattern}'` case ValueErrorType.String: return '应为字符串类型' case ValueErrorType.Symbol: return '应为 Symbol 类型' case ValueErrorType.TupleLength: return `元组应包含 ${error.schema.maxItems || 0} 个元素` case ValueErrorType.Tuple: return '应为元组类型' case ValueErrorType.Uint8ArrayMaxByteLength: return `字节长度应小于或等于 ${error.schema.maxByteLength}` case ValueErrorType.Uint8ArrayMinByteLength: return `字节长度应至少为 ${error.schema.minByteLength}` case ValueErrorType.Uint8Array: return '应为 Uint8Array 类型' case ValueErrorType.Undefined: return '应为 undefined' case ValueErrorType.Union: const union = error.schema.anyOf .map((x: Record<string, unknown>) => `'${x?.format ?? x.type}'`) .join(', ') return '应匹配联合类型中的至少一种: ' + union; case ValueErrorType.Void: return '应为 Void' case ValueErrorType.Kind: return `期望类型为 '${error.schema[Kind]}'` default: return '未知错误类型' } } SetErrorFunction((error) => zhError(error));
如果是在 [[Elysia.js]] 或者是 [[Hono.js]] 等框架中使用 Typebox 校验参数,也可以使用这种方式,只要确保调用了 SetErrorFunction
方法。
如果针对错误描述有自定义需求,从 error.schema 中取出需要的参数,自己拼接下字符串即可。