-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat(locales): add nl #4425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(locales): add nl #4425
Conversation
WalkthroughThis update adds Dutch (nl) language support for Zod validation error messages. It introduces a new locale module with Dutch translations, updates the locale export list to include Dutch, and refreshes the documentation to mention the new locale. No other logic or control flow changes are present. Changes
Poem
Note ⚡️ AI Code Reviews for VS Code, Cursor, WindsurfCodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback. Note ⚡️ Faster reviews with cachingCodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🔇 Additional comments (5)
✨ Finishing Touches
🧪 Generate Unit Tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting
📒 Files selected for processing (3)
packages/docs/content/error-customization.mdx
(1 hunks)packages/zod/src/v4/locales/index.ts
(1 hunks)packages/zod/src/v4/locales/nl.ts
(1 hunks)
🧰 Additional context used
🪛 GitHub Actions: test
packages/zod/src/v4/locales/nl.ts
[error] 5-12: Biome formatting check failed. Formatting differences detected in whitespace around type annotations. Run 'biome format' to fix code style issues.
🔇 Additional comments (7)
packages/zod/src/v4/locales/nl.ts (5)
12-14
: LGTM!Nice utility function to handle sizing units for different data types.
16-37
: LGTM!The parsedType function looks good - it handles all the expected data types and returns appropriate Dutch descriptions.
39-70
: LGTM!Great job on the comprehensive mapping of format types to their Dutch equivalents. The translations look accurate.
122-126
: LGTM!Export looks good. This follows the same pattern as other locale files.
5-10
:⚠️ Potential issueFix the whitespace formatting to resolve pipeline failure.
The pipeline is complaining about whitespace around type annotations. Make sure there's proper spacing around the colon in type declarations.
-const Sizable: Record<string, { unit: string; }> = { +const Sizable: Record<string, { unit: string }> = { string: { unit: "tekens" }, file: { unit: "bytes" }, array: { unit: "elementen" }, set: { unit: "elementen" }, };Likely an incorrect or invalid review comment.
🧰 Tools
🪛 GitHub Actions: test
[error] 5-12: Biome formatting check failed. Formatting differences detected in whitespace around type annotations. Run 'biome format' to fix code style issues.
packages/docs/content/error-customization.mdx (1)
365-365
: LGTM!Successfully added Dutch to the list of supported locales. The text "Dutch" is correct.
packages/zod/src/v4/locales/index.ts (1)
21-21
: LGTM!Great job adding the Dutch locale export in the correct alphabetical position.
case "invalid_key": | ||
return `Ongeldige key in ${issue.origin}`; | ||
case "invalid_union": | ||
return "Ongeldige invoer"; |
There was a problem hiding this comment.
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.
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.
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}`; |
There was a problem hiding this comment.
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.
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.
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`; | ||
} |
There was a problem hiding this comment.
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.
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.
packages/zod/src/v4/locales/nl.ts
Outdated
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}`; | ||
} |
There was a problem hiding this comment.
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.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (2)
packages/zod/src/v4/locales/nl.ts (2)
97-102
: Return formatting & wording consistency in invalid_format
The mix of"string"
vs"tekst"
and single-line vs block returns was noted previously. Let’s unify to “tekst” and always use braces:- 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 === "starts_with") { + return `Ongeldige tekst: 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}`; + }
113-114
: Add context to invalid_union message
The generic “Ongeldige invoer” was flagged before. Let’s give users more to go on, e.g.:-case "invalid_union": - return "Ongeldige invoer"; +case "invalid_union": + return "Ongeldige invoer: voldoet aan geen van de toegestane types";
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting
📒 Files selected for processing (1)
packages/zod/src/v4/locales/nl.ts
(1 hunks)
🔇 Additional comments (10)
packages/zod/src/v4/locales/nl.ts (10)
5-14
: Nice Sizable mapping & helper
TheSizable
record andgetSizing
function correctly map origins to Dutch units and fall back tonull
as intended.
16-37
: parsedType logic is solid
Your switch handles numbers (including NaN), arrays,null
, and custom constructors, then defaults totypeof
. Clean and clear.
39-70
: Comprehensive Nouns mapping
All$ZodStringFormats
are covered with appropriate Dutch nouns. Nice coverage.
74-75
: invalid_type: clear expected vs received
The message “Ongeldige invoer: verwacht …, ontving …” is concise and informative.
76-78
: invalid_value handles single vs multiple well
Good that you differentiate between one expected value and multiple options.
79-85
: too_big: inclusive logic & sizing work nicely
Using<=" vs
<` plus unit lookup gives a precise Dutch error.
105-107
: not_multiple_of: clear & accurate
The message “moet een veelvoud van … zijn” is spot on.
115-116
: invalid_element: clear, includes origin
This gives precise feedback on which element failed. All good.
117-118
: Default fallback makes sense
Ongeldige invoer
as a catch-all is concise and consistent.
120-126
: Exports look good
The namederror
export and default factory match other locales’ patterns.
case "invalid_key": | ||
return `Ongeldige key in ${issue.origin}`; | ||
case "invalid_union": |
There was a problem hiding this comment.
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.
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.
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`; | ||
} |
There was a problem hiding this comment.
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.
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 "unrecognized_keys": | ||
return `Onbekende key${issue.keys.length > 1 ? "s" : ""}: ${util.joinValues(issue.keys, ", ")}`; | ||
case "invalid_key": |
There was a problem hiding this comment.
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.
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.
Adds localized error messages in Dutch (NL), as requested in #4168.
Summary by CodeRabbit
New Features
Documentation