i18n subject in mailer

This commit is contained in:
Philipp Dormann 2024-12-11 18:09:16 +01:00
parent a5a8f42db6
commit 56ebf652b1
Signed by: philipp
GPG Key ID: 3BB9ADD52DCA4314
9 changed files with 15 additions and 12 deletions

View File

@ -34,7 +34,6 @@ curl -X POST http://localhost:3000/api/v1/email \
-H "Content-Type: application/json" \
-d '{
"to": "user@example.com",
"subject": "Welcome to Lauf für Kaya! 2025",
"templateName": "welcome",
"language": "en",
"data": {
@ -52,13 +51,10 @@ curl -X POST http://localhost:3000/api/v1/email \
-H "Content-Type: application/json" \
-d '{
"to": "user@example.com",
"subject": "Password Reset Request",
"templateName": "password-reset",
"language": "de",
"data": {
"name": "John Doe",
"resetLink": "https://example.com/reset/123",
"expiresIn": "24 hours"
"token": "123465789"
}
}'
```
@ -79,6 +75,7 @@ SMTP_PASS="secret.1"
EMAIL_FROM="noreply@lauf-fuer-kaya.de"
EMAIL_REPLYTO="info@lauf-fuer-kaya.de"
REDIS_URL=redis://localhost:6379
FRONTEND_URL="https://run.lauf-fuer-kaya.de"
```
## 🛠️ Development

View File

@ -14,6 +14,7 @@ services:
- SMTP_PASS="secret.1"
- EMAIL_FROM="noreply@lauf-fuer-kaya.de"
- EMAIL_REPLYTO="info@lauf-fuer-kaya.de"
- FRONTEND_URL="https://run.lauf-fuer-kaya.de"
depends_on:
- redis

View File

@ -11,7 +11,6 @@ const emailService = new EmailService()
const sendEmailSchema = z.object({
to: z.string().email(),
subject: z.string(),
templateName: z.string(),
language: z.enum(['en', 'de']),
data: z.record(z.any())
@ -34,7 +33,7 @@ async function generateBarcodeDataURL(data) {
}
emailRouter.post('/', zValidator('json', sendEmailSchema), async (c) => {
let { to, subject, templateName, language, data } = c.req.valid('json')
let { to, templateName, language, data } = c.req.valid('json')
try {
const template = getEmailTemplate(templateName, language as Language)
@ -56,7 +55,7 @@ emailRouter.post('/', zValidator('json', sendEmailSchema), async (c) => {
}
await emailService.sendEmail({
to,
subject,
subject: template.subject(data),
html: template.html(data),
text: template.text(data)
})

View File

@ -10,15 +10,12 @@ const routes = {
'application/json': {
schema: {
type: 'object',
required: ['to', 'subject', 'templateName', 'language', 'data'],
required: ['to', 'templateName', 'language', 'data'],
properties: {
to: {
type: 'string',
format: 'email'
},
subject: {
type: 'string'
},
templateName: {
type: 'string'
},

View File

@ -6,6 +6,7 @@ import { compile } from 'handlebars'
interface TemplateCache {
[key: string]: {
html: HandlebarsTemplateDelegate
subject: HandlebarsTemplateDelegate,
text: HandlebarsTemplateDelegate
}
}
@ -18,12 +19,15 @@ function loadTemplate(name: string, language: Language) {
if (!templateCache[cacheKey]) {
const htmlPath = join(process.cwd(), 'src', 'templates', name, `${language}.html`)
const textPath = join(process.cwd(), 'src', 'templates', name, `${language}.txt`)
const subjectPath = join(process.cwd(), 'src', 'templates', name, `${language}.subject.txt`)
const htmlTemplate = readFileSync(htmlPath, 'utf-8')
const textTemplate = readFileSync(textPath, 'utf-8')
const subjectTemplate = readFileSync(subjectPath, 'utf-8')
templateCache[cacheKey] = {
html: compile(htmlTemplate),
subject: compile(subjectTemplate),
text: compile(textTemplate)
}
}
@ -35,6 +39,7 @@ export function getEmailTemplate(name: string, language: Language) {
const template = loadTemplate(name, language)
return {
subject: (data: any) => template.subject(data),
html: (data: any) => template.html(data),
text: (data: any) => template.text(data)
}

View File

@ -0,0 +1 @@
Lauf für Kaya! Passwort Reset

View File

@ -0,0 +1 @@
Lauf für Kaya! Password Reset

View File

@ -0,0 +1 @@
Willkommen beim Lauf für Kaya! 2025

View File

@ -0,0 +1 @@
Welcome to Lauf für Kaya! 2025