feat(emails): localize templates to 7 locales and add newsletter double opt-in #158
No reviewers
Labels
No labels
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
javascript
question
severity: high
severity: low
severity: medium
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
isyuricunha/website!158
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/email-i18n-and-newsletter-double-opt-in"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Closes the two scope gaps flagged in the project audit: transactional email templates now cover all seven website locales, and the newsletter uses double opt-in.
Email localization
packages/emails/src/locales.ts:EmailLocaletype coveringen, pt, es, ja, zh-CN, fr, de,resolve_email_locale()(normalizes BCP-47 input,zh-*->zh-CN, unknown ->en), plusEMAIL_LANGfor<Html lang>and shared greetings.en|ptternary to a typedcopy_by_localedictionary with hand-written translations for all seven locales.contact-formhas no recipient-facing copy and stays as-is.get_request_locale()(auth emails, comment notifications, password reset) now returnsEmailLocale, so transactional emails follow the visitor's locale across the full site.NewsletterConfirmationtemplate (7 locales).Newsletter double opt-in
POST /api/newsletter/subscribeno longer writes to the Resend audience. Instead it:token -> emailin Redis with a 24h TTL.GET /api/newsletter/confirm?token=...validates the token, then adds the contact, re-enables a previously unsubscribed contact, or short-circuits as already-subscribed, and burns the token. Nobody can subscribe a third-party address on their behalf, and typo'd or hostile signups no longer pollute the audience.Tests
newsletter-subscribe-route.test.ts: rewritten for double opt-in — asserts a token is stored with 24h TTL and thataddContact/findContactByEmailare never called on subscribe.newsletter-confirm-route.test.ts: new — missing/unknown token 400, success adds contact and burns token, re-subscribe of an unsubscribed contact, idempotent already-subscribed case.Validation
Residual risks
The latest updates on your projects. Learn more about Vercel for GitHub.