-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
Summary
Context
I am using i18next with typescript (https://www.i18next.com/overview/typescript) to get intellisense for translations and rely on type safety.
Therefore, the translation keys expected by the library are string literals instead of simple strings :
t($ => $['my.key'])To keep static zod schema definitions, I am giving only the keys to my zod errors, for instance :
// schema.ts
export const SOME_SCHEMA = z.object({
description: z.string("field.invalid").min(1, "field.required"),
});I then rely on rendering inside components to make sure my translations are recomputed whenever language changes :
// component.tsx
return (
{errors.description?.message && (
{t($ => $[errors.description.message]}
})
)This is my best option so far, to keep schemas and i18n decorrelated.
Please note I am using RHF as my form manager. The library receives those errors and seems to type them itself. It would then be also responsible for properly typing error messages.
Need
I'd need a way to infer the possible types of an error message based on its schema definition :
t($ => $[errors.description.message]
// ideal type for message : 'field.invalid' | 'field.required'Alternatives considered
Integrating with zod locales
Is there a way to load my custom error messages with their i18n into zod ?
Zod built-in locales seem not to match my need, as I want custom error messages.
Calling t within Zod schemas
Sadly, this option not only tightly couples my i18n solution with zod, it also brings 2 issues, mentioned here : #5259 (comment)
since RHF use some memoization on error messages, translation isn't recomputed after a "change locale event"
every schema is computed from a hook that use the useTranslate hook under the hood (not very suitable since the ideal solution would be to declare schema outside the React lifecycle)
Checking translation keys exist via a satisfies check
Adding the following to my schema :
// schema.ts
export const SOME_SCHEMA = z.object({
description: z.string("field.invalid" satisfies keyof SomeDictType).min(1, "field.required" satisfies keyof SomeDictType),
});Would ensure my translation keys exist. The only requirement is to have access to the generated dictionnary of translations.