i18n subject in mailer
This commit is contained in:
parent
a5a8f42db6
commit
56ebf652b1
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
})
|
||||
|
@ -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'
|
||||
},
|
||||
|
@ -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)
|
||||
}
|
||||
|
1
src/templates/password-reset/de.subject.txt
Normal file
1
src/templates/password-reset/de.subject.txt
Normal file
@ -0,0 +1 @@
|
||||
Lauf für Kaya! Passwort Reset
|
1
src/templates/password-reset/en.subject.txt
Normal file
1
src/templates/password-reset/en.subject.txt
Normal file
@ -0,0 +1 @@
|
||||
Lauf für Kaya! Password Reset
|
1
src/templates/welcome/de.subject.txt
Normal file
1
src/templates/welcome/de.subject.txt
Normal file
@ -0,0 +1 @@
|
||||
Willkommen beim Lauf für Kaya! 2025
|
1
src/templates/welcome/en.subject.txt
Normal file
1
src/templates/welcome/en.subject.txt
Normal file
@ -0,0 +1 @@
|
||||
Welcome to Lauf für Kaya! 2025
|
Loading…
x
Reference in New Issue
Block a user