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 中取出需要的参数,自己拼接下字符串即可。