You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用next-intl翻译Zod默认错误信息?求替代zod-i18n方案

用next-intl批量翻译Zod默认错误信息的方案

方案1:自定义错误映射表 + next-intl翻译函数(客户端组件场景)

这个方案通过提前在next-intl的消息文件中定义所有Zod默认错误的翻译,再通过工具函数批量匹配转换。

  1. 在next-intl消息文件中添加错误翻译
    在对应语言的消息文件(如messages/en.json、messages/zh.json)中,为Zod的默认错误类型配置翻译:

    // messages/en.json
    {
      "zodErrors": {
        "invalid_type": "Expected {expected}, received {received}",
        "required": "This field is required",
        "invalid_string": {
          "email": "Invalid email address",
          "url": "Invalid URL",
          "default": "Invalid string format: {validation}"
        },
        "too_small": {
          "string": "Must be at least {minimum} characters",
          "number": "Must be greater than or equal to {minimum}"
        }
        // 按需添加其他Zod默认错误类型的翻译
      }
    }
    

    中文文件messages/zh.json对应替换为中文翻译即可。

  2. 编写批量翻译工具函数
    利用next-intl的useTranslations钩子,将Zod抛出的ZodError对象批量转换为翻译后的错误信息:

    import { useTranslations } from 'next-intl';
    import { ZodError, ZodIssue } from 'zod';
    
    // 定义错误代码与翻译逻辑的映射
    const zodErrorTranslators = {
      invalid_type: (issue: ZodIssue, t: any) => t('invalid_type', { expected: issue.expected, received: issue.received }),
      required: (_: ZodIssue, t: any) => t('required'),
      invalid_string: (issue: ZodIssue, t: any) => {
        const validationKey = issue.validation || 'default';
        return t(`invalid_string.${validationKey}`, { validation: issue.validation });
      },
      too_small: (issue: ZodIssue, t: any) => {
        const typeKey = issue.type || 'default';
        return t(`too_small.${typeKey}`, { minimum: issue.minimum });
      }
      // 扩展其他错误类型的翻译逻辑
    };
    
    export const translateZodErrors = (zodError: ZodError) => {
      const t = useTranslations('zodErrors');
      return zodError.issues.map(issue => {
        const translator = zodErrorTranslators[issue.code as keyof typeof zodErrorTranslators];
        return translator ? translator(issue, t) : issue.message;
      });
    };
    
  3. 在组件中使用
    当Zod校验失败时,调用工具函数获取翻译后的错误列表:

    import { useState } from 'react';
    import { ZodError } from 'zod';
    import { translateZodErrors } from '@/utils/translateZodErrors';
    import { userSchema } from '@/schemas/userSchema';
    
    export default function UserForm() {
      const [errors, setErrors] = useState<string[]>([]);
    
      const handleSubmit = (formData: FormData) => {
        try {
          userSchema.parse(Object.fromEntries(formData));
          // 提交逻辑
        } catch (err) {
          if (err instanceof ZodError) {
            setErrors(translateZodErrors(err));
          }
        }
      };
    
      return (
        <form onSubmit={handleSubmit}>
          {/* 表单字段 */}
          {errors.length > 0 && (
            <div className="error-list">
              {errors.map((err, idx) => <p key={idx}>{err}</p>)}
            </div>
          )}
          <button type="submit">Submit</button>
        </form>
      );
    }
    

方案2:服务端/无Hook场景的批量翻译

如果在服务端组件或API路由中处理Zod校验,可以使用next-intl的getTranslations方法实现批量翻译:

  1. 编写服务端翻译工具函数

    import { getTranslations } from 'next-intl/server';
    import { ZodError, ZodIssue } from 'zod';
    
    const zodErrorTranslators = {
      invalid_type: (issue: ZodIssue, t: any) => t('invalid_type', { expected: issue.expected, received: issue.received }),
      required: (_: ZodIssue, t: any) => t('required'),
      invalid_string: (issue: ZodIssue, t: any) => {
        const validationKey = issue.validation || 'default';
        return t(`invalid_string.${validationKey}`, { validation: issue.validation });
      }
    };
    
    export const translateZodErrorsServer = async (zodError: ZodError, locale: string) => {
      const t = await getTranslations({ locale, namespace: 'zodErrors' });
      return zodError.issues.map(issue => {
        const translator = zodErrorTranslators[issue.code as keyof typeof zodErrorTranslators];
        return translator ? translator(issue, t) : issue.message;
      });
    };
    
  2. 在API路由中使用

    import { translateZodErrorsServer } from '@/utils/translateZodErrorsServer';
    import { userSchema } from '@/schemas/userSchema';
    
    export async function POST(request: Request) {
      const locale = request.headers.get('accept-language')?.split(',')[0] || 'en';
      const data = await request.json();
    
      try {
        userSchema.parse(data);
        return Response.json({ success: true });
      } catch (err) {
        if (err instanceof ZodError) {
          const translatedErrors = await translateZodErrorsServer(err, locale);
          return Response.json({ errors: translatedErrors }, { status: 400 });
        }
        return Response.json({ error: 'Unknown error' }, { status: 500 });
      }
    }
    

内容的提问来源于stack exchange,提问作者OArnarsson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 00:39:54