Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 34 additions & 33 deletions packages/docs/content/error-customization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -342,40 +342,41 @@ z.config(z.locales.en());

The following locales are available:

- `ar` — Arabic
- `az` — Azerbaijani
- `be` — Belarusian
- `ca` — Catalan
- `cs` — Czech
- `de` — German
- `en` — English
- `es` — Spanish
- `fa` — Farsi
- `fi` — Finnish
- `fr` — French
- `frCA` — Canadian French
- `he` — Hebrew
- `hu` — Hungarian
- `id` — Indonesian
- `it` — Italian
- `ja` — Japanese
- `ko` — Korean
- `mk` — Macedonian
- `ms` — Malay
- `ar` — Arabic
- `az` — Azerbaijani
- `be` — Belarusian
- `ca` — Catalan
- `cs` — Czech
- `de` — German
- `en` — English
- `es` — Spanish
- `fa` — Farsi
- `fi` — Finnish
- `fr` — French
- `frCA` — Canadian French
- `he` — Hebrew
- `hu` — Hungarian
- `id` — Indonesian
- `it` — Italian
- `ja` — Japanese
- `ko` — Korean
- `mk` — Macedonian
- `ms` — Malay
- `nl` — Dutch
- `no` — Norwegian
- `ota` — Türkî
- `pl` — Polish
- `pt` — Portuguese
- `ru` — Russian
- `sl` — Slovenian
- `ta` — Tamil
- `th` — Thai
- `tr` — Türkçe
- `ua` — Ukrainian
- `ur` — Urdu
- `vi` — Tiếng Việt
- `zhCN` — Simplified Chinese
- `zhTW` — Traditional Chinese
- `ota` — Türkî
- `pl` — Polish
- `pt` — Portuguese
- `ru` — Russian
- `sl` — Slovenian
- `ta` — Tamil
- `th` — Thai
- `tr` — Türkçe
- `ua` — Ukrainian
- `ur` — Urdu
- `vi` — Tiếng Việt
- `zhCN` — Simplified Chinese
- `zhTW` — Traditional Chinese


## Error precedence
Expand Down
1 change: 1 addition & 0 deletions packages/zod/src/v4/locales/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export { default as ja } from "./ja.js";
export { default as ko } from "./ko.js";
export { default as mk } from "./mk.js";
export { default as ms } from "./ms.js";
export { default as nl } from "./nl.js";
export { default as no } from "./no.js";
export { default as ota } from "./ota.js";
export { default as pl } from "./pl.js";
Expand Down
126 changes: 126 additions & 0 deletions packages/zod/src/v4/locales/nl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import type { $ZodStringFormats } from "../core/checks.js";
import type * as errors from "../core/errors.js";
import * as util from "../core/util.js";

const Sizable: Record<string, { unit: string; }> = {
string: { unit: "tekens" },
file: { unit: "bytes" },
array: { unit: "elementen" },
set: { unit: "elementen" },
};

function getSizing(origin: string): { unit: 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" : "getal";
}
case "object": {
if (Array.isArray(data)) {
return "array";
}
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: "invoer",
email: "emailadres",
url: "URL",
emoji: "emoji",
uuid: "UUID",
uuidv4: "UUIDv4",
uuidv6: "UUIDv6",
nanoid: "nanoid",
guid: "GUID",
cuid: "cuid",
cuid2: "cuid2",
ulid: "ULID",
xid: "XID",
ksuid: "KSUID",
datetime: "ISO datum en tijd",
date: "ISO datum",
time: "ISO tijd",
duration: "ISO duur",
ipv4: "IPv4-adres",
ipv6: "IPv6-adres",
cidrv4: "IPv4-bereik",
cidrv6: "IPv6-bereik",
base64: "base64-gecodeerde tekst",
base64url: "base64 URL-gecodeerde tekst",
json_string: "JSON string",
e164: "E.164-nummer",
jwt: "JWT",
template_literal: "invoer",
};

const error: errors.$ZodErrorMap = (issue) => {
switch (issue.code) {
case "invalid_type":
return `Ongeldige invoer: verwacht ${issue.expected}, ontving ${parsedType(issue.input)}`;
case "invalid_value":
if (issue.values.length === 1) return `Ongeldige invoer: verwacht ${util.stringifyPrimitive(issue.values[0])}`;
return `Ongeldige optie: verwacht één van ${util.joinValues(issue.values, "|")}`;
case "too_big": {
const adj = issue.inclusive ? "<=" : "<";
const sizing = getSizing(issue.origin);
if (sizing)
return `Te lang: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elementen"} bevat`;
return `Te lang: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.maximum.toString()} is`;
}
case "too_small": {
const adj = issue.inclusive ? ">=" : ">";
const sizing = getSizing(issue.origin);
if (sizing) {
return `Te kort: verwacht dat ${issue.origin} ${adj}${issue.minimum.toString()} ${sizing.unit} bevat`;
}

return `Te kort: verwacht dat ${issue.origin} ${adj}${issue.minimum.toString()} is`;
}
Comment on lines +89 to +94
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider adding a line break for consistency.

In the 'too_small' case, you have an extra line break after the sizing conditional, but not in the 'too_big' case.

case "too_big": {
  const adj = issue.inclusive ? "<=" : "<";
  const sizing = getSizing(issue.origin);
  if (sizing)
    return `Te lang: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elementen"} bevat`;
+
  return `Te lang: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.maximum.toString()} is`;
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (sizing) {
return `Te kort: verwacht dat ${issue.origin} ${adj}${issue.minimum.toString()} ${sizing.unit} bevat`;
}
return `Te kort: verwacht dat ${issue.origin} ${adj}${issue.minimum.toString()} is`;
}
case "too_big": {
const adj = issue.inclusive ? "<=" : "<";
const sizing = getSizing(issue.origin);
if (sizing)
return `Te lang: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elementen"} bevat`;
return `Te lang: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.maximum.toString()} is`;
}
🤖 Prompt for AI Agents
In packages/zod/src/v4/locales/nl.ts around lines 89 to 94, the 'too_small' case
includes an extra line break after the sizing conditional, but the 'too_big'
case does not. To maintain consistency, add a similar line break after the
sizing conditional in the 'too_big' case as well.

Comment on lines +86 to +94
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Inconsistent fallback for issue.origin in too_small
In too_big you use issue.origin ?? "waarde", but in too_small you assume issue.origin is always truthy. Let’s align them:

- if (sizing) {
-   return `Te kort: verwacht dat ${issue.origin} ${adj}${issue.minimum.toString()} ${sizing.unit} bevat`;
- }
- return `Te kort: verwacht dat ${issue.origin} ${adj}${issue.minimum.toString()} is`;
+ if (sizing) {
+   return `Te kort: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.minimum.toString()} ${sizing.unit} bevat`;
+ }
+ return `Te kort: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.minimum.toString()} is`;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case "too_small": {
const adj = issue.inclusive ? ">=" : ">";
const sizing = getSizing(issue.origin);
if (sizing) {
return `Te kort: verwacht dat ${issue.origin} ${adj}${issue.minimum.toString()} ${sizing.unit} bevat`;
}
return `Te kort: verwacht dat ${issue.origin} ${adj}${issue.minimum.toString()} is`;
}
case "too_small": {
const adj = issue.inclusive ? ">=" : ">";
const sizing = getSizing(issue.origin);
if (sizing) {
return `Te kort: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.minimum.toString()} ${sizing.unit} bevat`;
}
return `Te kort: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.minimum.toString()} is`;
}
🤖 Prompt for AI Agents
In packages/zod/src/v4/locales/nl.ts around lines 86 to 94, the fallback for
issue.origin in the too_small case is missing, unlike in too_big where
issue.origin ?? "waarde" is used. Update the too_small case to use the same
fallback by replacing all instances of issue.origin with issue.origin ??
"waarde" to ensure consistent behavior when issue.origin is falsy.

case "invalid_format": {
const _issue = issue as errors.$ZodStringFormatIssues;
if (_issue.format === "starts_with") {
return `Ongeldige string: moet met "${_issue.prefix}" beginnen`;
}
if (_issue.format === "ends_with") return `Ongeldige tekst: moet op "${_issue.suffix}" eindigen`;
if (_issue.format === "includes") return `Ongeldige tekst: moet "${_issue.includes}" bevatten`;
if (_issue.format === "regex") return `Ongeldige tekst: moet overeenkomen met patroon ${_issue.pattern}`;
Comment on lines +100 to +102
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Keep consistent code style for return statements.

Some return statements use braces and others are on the same line. Let's make it consistent.

if (_issue.format === "starts_with") {
  return `Ongeldige string: moet met "${_issue.prefix}" beginnen`;
}

-if (_issue.format === "ends_with") return `Ongeldige tekst: moet op "${_issue.suffix}" eindigen`;
-if (_issue.format === "includes") return `Ongeldige tekst: moet "${_issue.includes}" bevatten`;
-if (_issue.format === "regex") return `Ongeldige tekst: moet overeenkomen met patroon ${_issue.pattern}`;
+if (_issue.format === "ends_with") {
+  return `Ongeldige tekst: moet op "${_issue.suffix}" eindigen`;
+}
+if (_issue.format === "includes") {
+  return `Ongeldige tekst: moet "${_issue.includes}" bevatten`;
+}
+if (_issue.format === "regex") {
+  return `Ongeldige tekst: moet overeenkomen met patroon ${_issue.pattern}`;
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (_issue.format === "ends_with") return `Ongeldige tekst: moet op "${_issue.suffix}" eindigen`;
if (_issue.format === "includes") return `Ongeldige tekst: moet "${_issue.includes}" bevatten`;
if (_issue.format === "regex") return `Ongeldige tekst: moet overeenkomen met patroon ${_issue.pattern}`;
if (_issue.format === "starts_with") {
return `Ongeldige string: moet met "${_issue.prefix}" beginnen`;
}
if (_issue.format === "ends_with") {
return `Ongeldige tekst: moet op "${_issue.suffix}" eindigen`;
}
if (_issue.format === "includes") {
return `Ongeldige tekst: moet "${_issue.includes}" bevatten`;
}
if (_issue.format === "regex") {
return `Ongeldige tekst: moet overeenkomen met patroon ${_issue.pattern}`;
}
🤖 Prompt for AI Agents
In packages/zod/src/v4/locales/nl.ts around lines 100 to 102, the return
statements have inconsistent formatting with some using braces and others on the
same line. To fix this, choose one style—either always use braces with a return
statement on a new line or always use a single-line return without braces—and
apply it consistently to all these return statements.

return `Ongeldig: ${Nouns[_issue.format] ?? issue.format}`;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add line break for consistent error cases.

For clarity and consistency with other cases, consider adding a line break after the first _issue format check.

case "invalid_format": {
  const _issue = issue as errors.$ZodStringFormatIssues;
  if (_issue.format === "starts_with") {
    return `Ongeldige string: moet met "${_issue.prefix}" beginnen`;
  }
+
  if (_issue.format === "ends_with") return `Ongeldige tekst: moet op "${_issue.suffix}" eindigen`;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const _issue = issue as errors.$ZodStringFormatIssues;
if (_issue.format === "starts_with") {
return `Ongeldige string: moet met "${_issue.prefix}" beginnen`;
}
if (_issue.format === "ends_with") return `Ongeldige tekst: moet op "${_issue.suffix}" eindigen`;
if (_issue.format === "includes") return `Ongeldige tekst: moet "${_issue.includes}" bevatten`;
if (_issue.format === "regex") return `Ongeldige tekst: moet overeenkomen met patroon ${_issue.pattern}`;
return `Ongeldig: ${Nouns[_issue.format] ?? issue.format}`;
}
case "invalid_format": {
const _issue = issue as errors.$ZodStringFormatIssues;
if (_issue.format === "starts_with") {
return `Ongeldige string: moet met "${_issue.prefix}" beginnen`;
}
if (_issue.format === "ends_with") return `Ongeldige tekst: moet op "${_issue.suffix}" eindigen`;
if (_issue.format === "includes") return `Ongeldige tekst: moet "${_issue.includes}" bevatten`;
if (_issue.format === "regex") return `Ongeldige tekst: moet overeenkomen met patroon ${_issue.pattern}`;
return `Ongeldig: ${Nouns[_issue.format] ?? issue.format}`;
}
🤖 Prompt for AI Agents
In packages/zod/src/v4/locales/nl.ts between lines 96 and 104, the first if
condition handling _issue.format === "starts_with" returns a string without a
line break, unlike the other cases. To maintain consistency and clarity, modify
this return statement to include a line break at the end, matching the style of
the other error messages.

case "not_multiple_of":
return `Ongeldig getal: moet een veelvoud van ${issue.divisor} zijn`;
case "unrecognized_keys":
return `Onbekende key${issue.keys.length > 1 ? "s" : ""}: ${util.joinValues(issue.keys, ", ")}`;
case "invalid_key":
Comment on lines +107 to +109
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Translate “key(s)” to Dutch
Mixing English keys in a Dutch locale is a translation bug. Let’s use “sleutel(s)”:

-case "unrecognized_keys":
-  return `Onbekende key${issue.keys.length > 1 ? "s" : ""}: ${util.joinValues(issue.keys, ", ")}`;
+case "unrecognized_keys":
+  return `Onbekende sleutel${issue.keys.length > 1 ? "s" : ""}: ${util.joinValues(issue.keys, ", ")}`;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case "unrecognized_keys":
return `Onbekende key${issue.keys.length > 1 ? "s" : ""}: ${util.joinValues(issue.keys, ", ")}`;
case "invalid_key":
case "unrecognized_keys":
return `Onbekende sleutel${issue.keys.length > 1 ? "s" : ""}: ${util.joinValues(issue.keys, ", ")}`;
case "invalid_key":
🤖 Prompt for AI Agents
In packages/zod/src/v4/locales/nl.ts around lines 107 to 109, the word "key(s)"
is used in English within a Dutch locale, which is inconsistent. Replace "key"
and "keys" with the Dutch equivalent "sleutel" and "sleutels" respectively,
ensuring the pluralization logic remains correct by using "sleutel" for singular
and "sleutels" for plural.

return `Ongeldige key in ${issue.origin}`;
case "invalid_union":
Comment on lines +109 to +111
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Translate “key” in invalid_key
Similarly, replace “key” with “sleutel” for consistency:

-case "invalid_key":
-  return `Ongeldige key in ${issue.origin}`;
+case "invalid_key":
+  return `Ongeldige sleutel in ${issue.origin}`;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case "invalid_key":
return `Ongeldige key in ${issue.origin}`;
case "invalid_union":
case "invalid_key":
return `Ongeldige sleutel in ${issue.origin}`;
case "invalid_union":
🤖 Prompt for AI Agents
In packages/zod/src/v4/locales/nl.ts around lines 109 to 111, the word "key" in
the "invalid_key" case is not translated to Dutch. Replace "key" with "sleutel"
in the returned string to maintain language consistency.

return "Ongeldige invoer";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider adding more context to error message.

The "invalid_union" error message is very generic. Consider providing more detail to help users understand what went wrong.

-  return "Ongeldige invoer";
+  return "Ongeldige invoer: voldoet aan geen van de toegestane types";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return "Ongeldige invoer";
return "Ongeldige invoer: voldoet aan geen van de toegestane types";
🤖 Prompt for AI Agents
In packages/zod/src/v4/locales/nl.ts at line 112, the error message for
"invalid_union" is too generic. Enhance the message by adding more specific
context about why the union validation failed, such as mentioning that the input
did not match any of the expected types, to help users better understand the
error.

case "invalid_element":
return `Ongeldige waarde in ${issue.origin}`;
default:
return `Ongeldige invoer`;
}
};

export { error };

export default function (): { localeError: errors.$ZodErrorMap } {
return {
localeError: error,
};
}
Loading