Skip to content

Localize validation errors of the dashboard API - #300

Merged
Musiker15 merged 2 commits into
mainfrom
fix/localized-validation-errors
Oct 29, 2026
Merged

Musiker15 merged 2 commits into
mainfrom
fix/localized-validation-errors

Conversation

@Musiker15

Copy link
Copy Markdown
Member

Problem

13 dashboard routes returned parsed.error.issues[0]?.message as the error of their 422, and the forms show that text as is. A German or Polish owner saw "Enter a valid Discord ID." or zod's own "Too big: expected string to have <=80 characters".

Fix

  • packages/shared/src/validation-messages.ts: the 13 custom messages of our schemas as constants (VALIDATION_MESSAGES) plus validationMessageKey() for the reverse lookup. The schemas in audit-log, bot-config, branding, categories, domains, form-definition, form-settings, handle, status-defs and webhooks use the constants instead of inline text.
  • apps/web/src/lib/validation-message.ts (pure, tested): our own message → validation dictionary entry. A built-in zod message → zod's locale for de, hu, fr, es, pt, pl. invalid_type → a generic "This value isn't valid.", because a finished issue no longer carries the input and zod's text would say "received undefined".
  • apps/web/src/lib/validation-error.ts: validationMessage(error) reads the locale and dictionary of the request. The 13 routes call it instead of reading the issue directly.
  • New validation section in all seven dictionaries. Dictionary = typeof en plus the key type make a missing translation a compile error.
  • api/v1/hooks keeps English on purpose. It's the public REST API for integrations.
  • Wording: "Duplicate key." became "Each key can only be used once.", and the category colour message uses the same example (#00E676) as branding and statuses.

Tests

  • validation-message.test.ts: own message translated, English untouched, zod's German for a built-in issue, generic text for a wrong type, every key present in every language.
  • Counter-check: without the dictionary branch, the "own schema messages" test fails.
  • pnpm --filter @msk-forms/shared and @msk-forms/web: typecheck and tests (107 and 322) green, eslint on the changed files.

Thirteen dashboard routes answered a rejected body with the first zod
issue's message, so every language saw English: our own schema texts
("Enter a valid Discord ID.") as well as zod's built-in ones.

The custom messages now live as constants in VALIDATION_MESSAGES
(packages/shared) and the schemas use them. validationMessage() in
lib/validation-error.ts maps a message back to its key and answers from
the new `validation` dictionary section; zod's built-in messages come
from zod's own locales. A wrong type gets a generic text, because a
finished issue no longer has the input and zod would claim it received
"undefined". The public REST API (api/v1) stays English on purpose.

"Duplicate key." reads "Each key can only be used once." now, and the
category colour message uses the same example as the others.
@Musiker15
Musiker15 merged commit a07d8f9 into main Oct 29, 2026
4 checks passed
@Musiker15
Musiker15 deleted the fix/localized-validation-errors branch October 29, 2026 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant