feat(contact): full validation, CMS-translated strings, smaller UI
Deploy / verify (push) Failing after 47s
Deploy / deploy (push) Has been skipped

- contact-form-validation.ts: shared client+server validator returning
  {key, params} so messages can be translated via the CMS bundle.
- ContactFormComponent: 3 honeypots, subject field, GDPR consent
  checkbox, character counter, inline per-field errors after submit,
  uses useTranslate() everywhere.
- /api/contact: origin allowlist, multiple honeypot check, client-age
  gate, server-side re-validation, forwards X-Forwarded-For + UA to
  CMS forms plugin with consent timestamp in payload.
- TextInput/Textarea: new size="sm" variant (rounded-sm, shadow-sm,
  h-10, smaller padding/text). Default "md" unchanged.
- translations.ts: 37 new contact_* keys.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Peter Meier
2026-05-21 11:28:23 +02:00
parent 8575572183
commit 94a8feeb67
7 changed files with 409 additions and 70 deletions
+38
View File
@@ -276,6 +276,44 @@ const TRANSLATION_KEYS = [
"strommix_trend_flat",
"strommix_sparkline_aria", // {{from}}, {{to}}
"strommix_stale_badge",
// Contact form (ContactFormComponent.svelte).
"contact_label_name",
"contact_placeholder_name",
"contact_label_email",
"contact_placeholder_email",
"contact_label_subject",
"contact_placeholder_subject",
"contact_label_message",
"contact_placeholder_message",
"contact_message_remaining", // {{n}}
"contact_message_overflow", // {{n}}
"contact_label_consent",
"contact_privacy_note",
"contact_submit",
"contact_submitting",
"contact_success_title",
"contact_success_body",
"contact_fix_errors",
"contact_server_error_generic",
"contact_server_error_network",
"contact_server_error_blocked",
"contact_server_error_throttle",
"contact_server_error_validation",
// Per-field validation errors (params: n).
"contact_error_name_min", // {{n}}
"contact_error_name_max", // {{n}}
"contact_error_name_no_links",
"contact_error_name_invalid_chars",
"contact_error_email_required",
"contact_error_email_max", // {{n}}
"contact_error_email_invalid",
"contact_error_subject_max", // {{n}}
"contact_error_subject_invalid_chars",
"contact_error_message_min", // {{n}}
"contact_error_message_max", // {{n}}
"contact_error_message_too_many_links", // {{n}}
"contact_error_message_invalid_chars",
"contact_error_consent_required",
] as const;
export type TranslationKey = (typeof TRANSLATION_KEYS)[number];