diff --git a/packages/core/src/locales.ts b/packages/core/src/locales.ts index 5e0ed62a75..0adb429502 100644 --- a/packages/core/src/locales.ts +++ b/packages/core/src/locales.ts @@ -1,5 +1,6 @@ import az from "./locales/az.js"; +import be from "./locales/be.js"; import en from "./locales/en.js"; import es from "./locales/es.js"; -export { az, es, en }; +export { az, es, en, be }; diff --git a/packages/core/src/locales/be.ts b/packages/core/src/locales/be.ts new file mode 100644 index 0000000000..9cde4fa8d9 --- /dev/null +++ b/packages/core/src/locales/be.ts @@ -0,0 +1,124 @@ +import type { $ZodStringFormats } from "../checks.js"; +import type * as errors from "../errors.js"; +import * as util from "../util.js"; + +const Sizable: Record = { + string: { unit: "сімвалаў", verb: "мець" }, + file: { unit: "байтаў", verb: "мець" }, + array: { unit: "элементаў", verb: "мець" }, + set: { unit: "элементаў", verb: "мець" }, +}; + +function getSizing(origin: string): { unit: string; verb: string } | null { + return Sizable[origin] ?? null; +} + +export const parsedType = (data: any): string => { + const t = typeof data; + + switch (t) { + case "number": { + return Number.isNaN(data) ? "NaN" : "лік"; + } + case "object": { + if (Array.isArray(data)) { + return "масіў"; + } + if (data === null) { + return "null"; + } + + if (Object.getPrototypeOf(data) !== Object.prototype && data.constructor) { + return data.constructor.name; + } + } + } + return t; +}; + +const Nouns: { + [k in $ZodStringFormats | (string & {})]?: string; +} = { + regex: "увод", + email: "электронны адрас", + url: "URL", + emoji: "эмодзі", + uuid: "UUID", + uuidv4: "UUIDv4", + uuidv6: "UUIDv6", + nanoid: "nanoid", + guid: "GUID", + cuid: "cuid", + cuid2: "cuid2", + ulid: "ULID", + xid: "XID", + ksuid: "KSUID", + datetime: "ISO дата і час", + date: "ISO дата", + time: "ISO час", + duration: "ISO працягласць", + ipv4: "IPv4 адрас", + ipv6: "IPv6 адрас", + cidrv4: "IPv4 дыяпазон", + cidrv6: "IPv6 дыяпазон", + base64: "радок у кадзіроўцы base64", + base64url: "радок у кадзіроўцы base64url", + json_string: "JSON радок", + e164: "нумар E.164", + jwt: "JWT", + template_literal: "увод", +}; + +const error: errors.$ZodErrorMap = (issue) => { + switch (issue.code) { + case "invalid_type": + return `Няправільны ўвод: чакаўся ${issue.expected}, атрымана ${parsedType(issue.input)}`; + case "invalid_value": + if (issue.values.length === 1) return `Няправільны ўвод: чакалася ${util.stringifyPrimitive(issue.values[0])}`; + return `Няправільны варыянт: чакаўся адзін з ${util.joinValues(issue.values, "|")}`; + case "too_big": { + const adj = issue.inclusive ? "<=" : "<"; + const sizing = getSizing(issue.origin); + if (sizing) + return `Занадта вялікі: чакалася, што ${issue.origin ?? "значэнне"} будзе мець ${adj}${issue.maximum.toString()} ${sizing.unit ?? "элементаў"}`; + return `Занадта вялікі: чакалася, што ${issue.origin ?? "значэнне"} будзе ${adj}${issue.maximum.toString()}`; + } + case "too_small": { + const adj = issue.inclusive ? ">=" : ">"; + const sizing = getSizing(issue.origin); + if (sizing) { + return `Занадта малы: чакалася, што ${issue.origin} будзе мець ${adj}${issue.minimum.toString()} ${sizing.unit}`; + } + + return `Занадта малы: чакалася, што ${issue.origin} будзе ${adj}${issue.minimum.toString()}`; + } + case "invalid_format": { + const _issue = issue as errors.$ZodStringFormatIssues; + if (_issue.format === "starts_with") return `Няправільны радок: павінен пачынацца з "${issue}"`; + if (_issue.format === "ends_with") return `Няправільны радок: павінен заканчвацца на "${_issue.suffix}"`; + if (_issue.format === "includes") return `Няправільны радок: павінен уключаць "${_issue.includes}"`; + if (_issue.format === "regex") return `Няправільны радок: павінен адпавядаць шаблону ${_issue.pattern}`; + return `Няправільны ${Nouns[_issue.format] ?? issue.format}`; + } + case "not_multiple_of": + return `Няправільны лік: павінен быць кратным ${issue.divisor}`; + case "unrecognized_keys": + return `Нераспазнаны ключ${issue.keys.length > 1 ? "ы" : ""}: ${util.joinValues(issue.keys, ", ")}`; + case "invalid_key": + return `Няправільны ключ у ${issue.origin}`; + case "invalid_union": + return "Няправільны ўвод"; + case "invalid_element": + return `Няправільнае значэнне ў ${issue.origin}`; + default: + return `Няправільны ўвод`; + } +}; + +export { error }; + +export default function (): { localeError: errors.$ZodErrorMap } { + return { + localeError: error, + }; +} diff --git a/packages/docs/content/error-customization.mdx b/packages/docs/content/error-customization.mdx index 8a0003d20f..772f217df5 100644 --- a/packages/docs/content/error-customization.mdx +++ b/packages/docs/content/error-customization.mdx @@ -8,9 +8,9 @@ import { Tabs, Tab } from 'fumadocs-ui/components/tabs'; In Zod, validation errors are surfaced as instances of the `z.core.$ZodError` class. -> The `zod` package uses a subclass of this called `ZodError` that implements some additional convenience methods. +> The `zod` package uses a subclass of this called `ZodError` that implements some additional convenience methods. -Instances of `$ZodError` contain an `.issues` property containing a human-readable `message` and additional structured information about each encountered validation issue. +Instances of `$ZodError` contain an `.issues` property containing a human-readable `message` and additional structured information about each encountered validation issue. @@ -81,7 +81,7 @@ z.string({ error: "Bad!"}).parse(12); // expected: 'string', // code: 'invalid_type', // path: [], -// message: 'Bad!' <-- 👀 custom error message +// message: 'Bad!' <-- 👀 custom error message // } // ] // } @@ -238,7 +238,7 @@ result.error.issues; // [{ message: "highest priority", ... }] ``` -The `iss` object is a [discriminated union](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions) of all possible issue types. Use the `code` property to discriminate between them. +The `iss` object is a [discriminated union](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions) of all possible issue types. Use the `code` property to discriminate between them. > For a breakdown of all Zod issue codes, see the [`@zod/core`](/packages/core#issue-types) documentation. @@ -269,7 +269,7 @@ z.config({ }); ``` -Global error messages have *lower precedence* than schema-level or per-parse error messages. +Global error messages have *lower precedence* than schema-level or per-parse error messages. The `iss` object is a [discriminated union](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions) of all possible issue types. Use the `code` property to discriminate between them. @@ -340,3 +340,4 @@ The following locales are available: - `az` — Azerbaijani - `en` — English +- `be` — Belarusian