feat: add i18n translated form errors (#509)
This commit is contained in:
@@ -1 +1,33 @@
|
||||
export const name = "form";
|
||||
import { useForm, zodResolver } from "@mantine/form";
|
||||
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import { z } from "@homarr/validation";
|
||||
import type {
|
||||
AnyZodObject,
|
||||
ZodEffects,
|
||||
ZodIntersection,
|
||||
} from "@homarr/validation";
|
||||
import { zodErrorMap } from "@homarr/validation/form";
|
||||
|
||||
export const useZodForm = <
|
||||
TSchema extends
|
||||
| AnyZodObject
|
||||
| ZodEffects<AnyZodObject>
|
||||
| ZodIntersection<AnyZodObject, AnyZodObject>,
|
||||
>(
|
||||
schema: TSchema,
|
||||
options: Omit<
|
||||
Exclude<Parameters<typeof useForm<z.infer<TSchema>>>[0], undefined>,
|
||||
"validate" | "validateInputOnBlur" | "validateInputOnChange"
|
||||
>,
|
||||
) => {
|
||||
const t = useI18n();
|
||||
|
||||
z.setErrorMap(zodErrorMap(t));
|
||||
return useForm<z.infer<TSchema>>({
|
||||
...options,
|
||||
validateInputOnBlur: true,
|
||||
validateInputOnChange: true,
|
||||
validate: zodResolver(schema),
|
||||
});
|
||||
};
|
||||
|
||||
110
packages/form/src/messages.ts
Normal file
110
packages/form/src/messages.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import type { TranslationObject } from "@homarr/translation";
|
||||
import type {
|
||||
ErrorMapCtx,
|
||||
z,
|
||||
ZodTooBigIssue,
|
||||
ZodTooSmallIssue,
|
||||
} from "@homarr/validation";
|
||||
import { ZodIssueCode } from "@homarr/validation";
|
||||
|
||||
const handleStringError = (issue: z.ZodInvalidStringIssue) => {
|
||||
if (typeof issue.validation === "object") {
|
||||
// Check if object contains startsWith / endsWith key to determine the error type. If not, it's an includes error. (see type of issue.validation)
|
||||
if ("startsWith" in issue.validation) {
|
||||
return {
|
||||
key: "errors.string.startsWith",
|
||||
params: {
|
||||
startsWith: issue.validation.startsWith,
|
||||
},
|
||||
} as const;
|
||||
} else if ("endsWith" in issue.validation) {
|
||||
return {
|
||||
key: "errors.string.endsWith",
|
||||
params: {
|
||||
endsWith: issue.validation.endsWith,
|
||||
},
|
||||
} as const;
|
||||
}
|
||||
|
||||
return {
|
||||
key: "errors.invalid_string.includes",
|
||||
params: {
|
||||
includes: issue.validation.includes,
|
||||
},
|
||||
} as const;
|
||||
}
|
||||
|
||||
return {
|
||||
message: issue.message,
|
||||
};
|
||||
};
|
||||
|
||||
const handleTooSmallError = (issue: ZodTooSmallIssue) => {
|
||||
if (issue.type !== "string" && issue.type !== "number") {
|
||||
return {
|
||||
message: issue.message,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
key: `errors.tooSmall.${issue.type}`,
|
||||
params: {
|
||||
minimum: issue.minimum,
|
||||
count: issue.minimum,
|
||||
},
|
||||
} as const;
|
||||
};
|
||||
|
||||
const handleTooBigError = (issue: ZodTooBigIssue) => {
|
||||
if (issue.type !== "string" && issue.type !== "number") {
|
||||
return {
|
||||
message: issue.message,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
key: `errors.tooBig.${issue.type}`,
|
||||
params: {
|
||||
maximum: issue.maximum,
|
||||
count: issue.maximum,
|
||||
},
|
||||
} as const;
|
||||
};
|
||||
|
||||
export const handleZodError = (
|
||||
issue: z.ZodIssueOptionalMessage,
|
||||
ctx: ErrorMapCtx,
|
||||
) => {
|
||||
if (ctx.defaultError === "Required") {
|
||||
return {
|
||||
key: "errors.required",
|
||||
params: {},
|
||||
} as const;
|
||||
}
|
||||
if (issue.code === ZodIssueCode.invalid_string) {
|
||||
return handleStringError(issue);
|
||||
}
|
||||
if (issue.code === ZodIssueCode.too_small) {
|
||||
return handleTooSmallError(issue);
|
||||
}
|
||||
if (issue.code === ZodIssueCode.too_big) {
|
||||
return handleTooBigError(issue);
|
||||
}
|
||||
if (issue.code === ZodIssueCode.custom && issue.params?.i18n) {
|
||||
const { i18n } = issue.params as CustomErrorParams;
|
||||
return {
|
||||
key: `errors.custom.${i18n.key}`,
|
||||
} as const;
|
||||
}
|
||||
|
||||
return {
|
||||
message: issue.message,
|
||||
};
|
||||
};
|
||||
|
||||
export interface CustomErrorParams {
|
||||
i18n: {
|
||||
key: keyof TranslationObject["common"]["zod"]["errors"]["custom"];
|
||||
params?: Record<string, unknown>;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user