ciscoheat / sveltekit-superforms

Making SvelteKit forms a pleasure to use!
https://superforms.rocks
MIT License
2.26k stars 66 forks source link

when using `zod-i18n-map`, field errors are `[undefined]` #455

Closed demetrius-mp closed 3 months ago

demetrius-mp commented 4 months ago

Description When using zod-i18n-map, errors are undefined.

if i have a schema defined as follows:

import { z } from 'zod';

const schema = z.object({
  name: z.string().min(3),
  age: z.number()
})

It works as expected, when sending a name with less than 3 characters, the error is displayed correctly.

However, if it is defined as follows (see the zod-i18n-map docs):

import i18next from "i18next";
import { z } from "zod";
import { zodI18nMap } from "zod-i18n-map";
import translation from "zod-i18n-map/locales/es/zod.json";

i18next.init({
  lng: "es",
  resources: {
    es: { zod: translation },
  },
});

z.setErrorMap(zodI18nMap);

const schema = z.object({
  name: z.string().min(3),
  age: z.number()
})

When sending a name with less then 3 characters, the form object has the following shape:

{
  id: '9yawuu',
  valid: false,
  posted: true,
  // see that even though the array has an item, the item is `undefined`
  // instead of the error string
  errors: { name: [ undefined ] },
  data: { name: '2', email: '' }
}

If applicable, a MRE

SvelteLab link to a MRE

If the link is not working, you can just grab the template and set the routes/schema.ts file content as follows:

// routes/schema.ts
import i18next from "i18next";
import { z } from "zod";
import { zodI18nMap } from "zod-i18n-map";
import translation from "zod-i18n-map/locales/es/zod.json";

i18next.init({
  lng: "es",
  resources: {
    es: { zod: translation },
  },
});
z.setErrorMap(zodI18nMap);

export const schema = z.object({
    name: z.string().min(2),
    email: z.string().email()
});

To see the bug happen, click to submit the form and look at the terminal to see the form shape.

Additional information

At first i thought it was some sort of error in zod-i18n-map itself, but i tried .safeParse() directly from the schema and the error messages are displayed correctly (in the configured language)

ciscoheat commented 4 months ago

There is an errorMap option on the adapter that you should use instead of the global function.

demetrius-mp commented 4 months ago

Ok, but how do I use it with zod-i18n-map?

Here's what i tried:

// schemas.ts

import i18next from 'i18next';
import { z } from 'zod';
import translation from 'zod-i18n-map/locales/es/zod.json';

i18next.init({
  lng: 'es',
  resources: {
    es: { zod: translation }
  }
});

export const schema = z.object({
  name: z.string().min(2),
  email: z.string().email()
});
// some +page.server.ts file

import type { PageServerLoad } from './$types';
import { zodI18nMap } from 'zod-i18n-map';

export const load = (async () => {
  const form = await superValidate(
    zod(itemSchema, {
      errorMap: zodI18nMap
    })
  );

  return {
    form
  };
}) satisfies PageServerLoad;

With the setup above, errors are still [undefined]

I also tried to set the error map both globally (with z.setErrorMap(zodI18nMap)) and "locally" (only within the zod adapter), and it didnt work as well.

ciscoheat commented 4 months ago

See if you can make a MRE at https://sveltelab.dev/github.com/ciscoheat/superforms-examples/tree/zod and I'll take a look.

demetrius-mp commented 3 months ago

link to a MRE.

See that in schemas.ts i load the translation using i18next and the json translation file from zod-i18n-map.

Also, in +page.server.ts i also load the error map from zod-i18n-map from within the adapter.

ciscoheat commented 3 months ago

Even after following the instructions at https://github.com/aiji42/zod-i18n, I can't get safeParse (used directly on the schema) to show localized errors, unfortunately. Can you link to a working example for that?

demetrius-mp commented 3 months ago

just found out the weirdest thing:

first, i figured that the problem is with zod-i18n (see this issue). it seems like it is having trouble with ecmascript modules.

however, i was sure that (at some point) i was able to get it to work, but didnt know how

conclusion: if the page that is importing the schema is SSR'd, it wont work (meaning the errors will be an array with a single undefined value). however, if the page is not SSR'd, it will work correctly (translated messages will show up just fine)

im going to close the issue as it's unrelated to your package, sorry for the disturbance