Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why is the zod error message undefined when using zod-i18n in server side code

i'm using the following schema

const propertySchema = z.object({
    rent_type: z.enum(['rent', 'sell']),
    title: z.string().min(10),
    typ: z.enum(['house', 'flat', 'garage', 'office', 'hotel']),
    price: z.coerce.number().positive(),
    area: z.coerce.number().positive(),
    rooms: z.coerce.number().positive(),
    address: z.string().min(10),
    description: z.string().min(20),
    beds: z.coerce.number().positive(),
    bathrooms: z.coerce.number().positive(),
    garage: z.coerce.number(),
    constructionYear: z.coerce.number().int().positive().min(1900)
});

and parsing over: const propertyData = propertySchema.safeParse(formData);

in my

+page.server.ts

so far it works great but i wanted to add now translations for the error messages and there is a package called zod-i18n

i'm initiating the i18next as described in the docs in the +layout.server.ts

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

// lng and resources key depend on your locale.
i18next.init({
  lng: "es",
  resources: {
    es: { zod: translation },
  },
});
z.setErrorMap(zodI18nMap);

but when i try to parse the error message keeps undefined which looks like its not loading the translation

const schema = z.string().email();
// Translated into Spanish (es)
schema.parse("foo"); // => error.message is undefined

it works when i do the initializing in the +layout.svelte in the onMount() lifecycle - but how could i get this work server side ?

like image 688
Jul Pod Avatar asked Oct 16 '25 07:10

Jul Pod


1 Answers

import i18next from "i18next";

import { z } from 'zod';
import { zodI18nMap } from "zod-i18n-map/dist/index.mjs"; // <-- use mjs version

import translation from "zod-i18n-map/locales/es/zod.json";

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

I had the same bug and just found a solution. I think the problem is that by default the import takes the zod-i18n-map/dist/index.js and not the index.mjs (at least in my case).

Because of this, the "global" i18n variable isn't the same in the two files. So when zod-i18n is mapping the error, i18next required in index.js try to translate a key, for wich he has no translation since it isn't the same as the i18next that is imported in +layout.server and initialized there.

My IDE (vscode) isn't happy then, saying that there is no module declared (ts error), you just need to add "declare module 'zod-i18n-map/dist/*'" inside the declare global of the app.d.ts file.

Bonus point, in the documentation it is said that i18n should not be initialised multiple times. So the init could be inserted into the hooks.server.js file, outside of the function to be executed once at the startup of the server (just did this so not fully tested).

Hope it helps someone

like image 150
daden2000 Avatar answered Oct 19 '25 00:10

daden2000



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!