Zod dynamic error messages based on active locale in Next.js

clock icon

asked 3 months ago Asked

message

1 Answers

eye

21 Views

I have an issue with i18n in Zod. Basically, I have a simple form handeled by react-hook-form and Zod for validation, but when I change the locale the error messages don't seem to be translated based on active locale. If anyone can help me to make zod error messages dynamic. I am using Next.js, next-i18next:

// my zod schema
import { z } from 'zod';
import { i18n } from 'next-i18next';

export const mailSchema = z.object({
  email: z
    .string({
      invalid_type_error: i18n?.t('zod-errors.invalid_type_error') ?? '',
      required_error: i18n?.t('zod-errors.required_error') ?? '',
    })
    .email(i18n?.t('zod-errors.email') ?? ''),
  subject: z
    .string({
      invalid_type_error: i18n?.t('zod-errors.invalid_type_error') ?? '',
      required_error: i18n?.t('zod-errors.required_error') ?? '',
    })
    .min(3, i18n?.t('zod-errors.min') ?? '')
    .max(60, i18n?.t('zod-errors.max') ?? ''),
  body: z
    .string({
      invalid_type_error: i18n?.t('zod-errors.invalid_type_error') ?? '',
      required_error: i18n?.t('zod-errors.required_error' ?? ''),
    })
    .min(10, i18n?.t('zod-errors.min') ?? '')
    .max(500, i18n?.t('zod-errors.max') ?? ''),
});

1 Answers

To make Zod error messages dynamic based on the active locale in your Next.js application using `next-i18next`, you can follow these steps:

1. **Passing i18n to your Zod schema**: You can't directly access `i18n` inside your Zod schema definition as it's an external object. One way to handle this is by passing the translated error messages as arguments when defining your schema.

2. **Create a function to generate dynamic Zod schema**: You can create a function that generates your Zod schema dynamically with the translated error messages based on the active locale.

Here's an example of how you can achieve this:

// utils/zodUtils.js

import { z } from 'zod';

export const createMailSchema = (t) => {
   return z.object({
      email: z
         . string({
             invalid_type_error: t('zod-errors.invalid_type_error') ?? '',
             required_error: t('zod-errors.required_error') ?? '',
         })
        .email(t('zod-errors.email') ?? ''),
    subject: z
       .string({
            invalid_type_error: t('zod-errors.invalid_type_error') ?? '',
            required_error: t('zod-errors.required_error') ?? '',
        })
        .min(3, t('zod-errors.min') ?? '')
        .max(60, t('zod-errors.max') ?? ''),
   body: z
        .string({
            invalid_type_error: t('zod-errors.invalid_type_error') ?? '',
            required_error: t('zod-errors.required_error') ?? '',
        })
        .min(10, t('zod-errors.min') ?? '')
        .max(500, t('zod-errors.max') ?? ''),
  });
};



Then in your component where you use the Zod schema:

// YourComponent.js

import { useTranslation } from 'next-i18next';
import { createMailSchema } from 'utils/zodUtils';

const YourComponent = () => { 
   const { t } = useTranslation();

   const mailSchema = createMailSchema(t);

   // You can now use mailSchema for validation
};



This way, you can ensure that your Zod error messages are dynamically translated based on the active locale in your Next.js application.

Write your answer here

Top Questions