diff --git a/src/lib/emails/AppointmentBooked.svelte b/src/lib/emails/AppointmentBooked.svelte index 93e20fc..596987c 100644 --- a/src/lib/emails/AppointmentBooked.svelte +++ b/src/lib/emails/AppointmentBooked.svelte @@ -1,6 +1,5 @@ - - {m["emails.greeting"]({ name: user.email })} + + {m["emails.greeting"]({ name: user.email }, { locale })} - {m["emails.appointmentBooked.introduction"]()} + {m["emails.appointmentBooked.introduction"]({}, { locale })} {channel} @@ -59,8 +54,8 @@ {address.zip} {address.city} - {m["emails.appointmentBooked.action"]()} + {m["emails.appointmentBooked.action"]({}, { locale })} - {m["emails.appointmentBooked.reason"]()} + {m["emails.appointmentBooked.reason"]({}, { locale })} diff --git a/src/lib/emails/AppointmentCancelled.svelte b/src/lib/emails/AppointmentCancelled.svelte index f5e884f..e5393d6 100644 --- a/src/lib/emails/AppointmentCancelled.svelte +++ b/src/lib/emails/AppointmentCancelled.svelte @@ -1,6 +1,5 @@ - - {m["emails.greeting"]({ name: user.email })} + + {m["emails.greeting"]({ name: user.email }, { locale })} - {m["emails.appointmentCancelled.introduction"]()} + {m["emails.appointmentCancelled.introduction"]({}, { locale })} {channel} @@ -57,6 +52,6 @@ {address.city} - {m["emails.appointmentCancelled.reason"]()} + {m["emails.appointmentCancelled.reason"]({}, { locale })} diff --git a/src/lib/emails/AppointmentRejected.svelte b/src/lib/emails/AppointmentRejected.svelte index 106060e..9e4446d 100644 --- a/src/lib/emails/AppointmentRejected.svelte +++ b/src/lib/emails/AppointmentRejected.svelte @@ -1,6 +1,5 @@ - - {m["emails.greeting"]({ name: user.email })} + + {m["emails.greeting"]({ name: user.email }, { locale })} - {m["emails.appointmentRejected.introduction"]()} + {m["emails.appointmentRejected.introduction"]({}, { locale })} {channel} @@ -57,6 +52,6 @@ {address.city} - {m["emails.appointmentRejected.reason"]()} + {m["emails.appointmentRejected.reason"]({}, { locale })} diff --git a/src/lib/emails/AppointmentReminder.svelte b/src/lib/emails/AppointmentReminder.svelte index 1db9bb8..3be3d7e 100644 --- a/src/lib/emails/AppointmentReminder.svelte +++ b/src/lib/emails/AppointmentReminder.svelte @@ -1,6 +1,5 @@ - - {m["emails.greeting"]({ name: user.email })} + + {m["emails.greeting"]({ name: user.email }, { locale })} - {m["emails.appointmentReminder.introduction"]({ tenant: tenant.longName })} + {m["emails.appointmentReminder.introduction"]({ tenant: tenant.longName }, { locale })} {channel} @@ -59,8 +54,10 @@ {address.zip} {address.city} - {m["emails.appointmentReminder.action"]()} + + {m["emails.appointmentReminder.action"]({}, { locale })} + - {m["emails.appointmentReminder.reason"]()} + {m["emails.appointmentReminder.reason"]({}, { locale })} diff --git a/src/lib/emails/AppointmentRequest.svelte b/src/lib/emails/AppointmentRequest.svelte index da948ac..0829c0d 100644 --- a/src/lib/emails/AppointmentRequest.svelte +++ b/src/lib/emails/AppointmentRequest.svelte @@ -37,10 +37,10 @@ }); - - {m["emails.greeting"]({ name: user.email })} + + {m["emails.greeting"]({ name: user.email }, { locale })} - {m["emails.appointmentRequest.introduction"]()} + {m["emails.appointmentRequest.introduction"]({}, { locale })} {channel} @@ -57,6 +57,6 @@ {address.city} - {m["emails.appointmentRequest.reason"]()} + {m["emails.appointmentRequest.reason"]({}, { locale })} diff --git a/src/lib/emails/Confirmation.svelte b/src/lib/emails/Confirmation.svelte index 9897150..c288ead 100644 --- a/src/lib/emails/Confirmation.svelte +++ b/src/lib/emails/Confirmation.svelte @@ -1,6 +1,5 @@ - - {m["emails.greeting"]({ name: user.name })} + - {m["emails.confirmation.introduction"]()} + {m["emails.greeting"]({ name: user.name }, { locale })} - {m["emails.confirmation.action"]()} - {m["emails.confirmation.hint"]({ expirationMinutes })} + {m["emails.confirmation.introduction"]({}, { locale })} + + + {m["emails.confirmation.action"]({}, { locale })} + + + {m["emails.confirmation.hint"]({ expirationMinutes }, { locale })} - {m["emails.confirmation.reason"]()} + {m["emails.confirmation.reason"]({}, { locale })} diff --git a/src/lib/emails/Notification.svelte b/src/lib/emails/Notification.svelte index ad4061a..7c0f12c 100644 --- a/src/lib/emails/Notification.svelte +++ b/src/lib/emails/Notification.svelte @@ -1,6 +1,5 @@ - - {m["emails.greeting"]({ name: user.name })} + + {m["emails.greeting"]({ name: user.name }, { locale })} - {m["emails.notification.introduction"]()} + {m["emails.notification.introduction"]({}, { locale })} - {m["emails.notification.action"]()} + {m["emails.notification.action"]({}, { locale })} - {m["emails.notification.reason"]()} + {m["emails.notification.reason"]({}, { locale })} diff --git a/src/lib/emails/PinReset.svelte b/src/lib/emails/PinReset.svelte index 3990e09..3f06b91 100644 --- a/src/lib/emails/PinReset.svelte +++ b/src/lib/emails/PinReset.svelte @@ -1,6 +1,5 @@ - - {m["emails.greeting"]({ name: user.email })} + + {m["emails.greeting"]({ name: user.email }, { locale })} - {m["emails.pinReset.introduction"]({ tenant: tenant.longName })} + {m["emails.pinReset.introduction"]({ tenant: tenant.longName }, { locale })} - {m["emails.pinReset.action"]()} + {m["emails.pinReset.action"]({}, { locale })} - {m["emails.pinReset.reason"]()} + {m["emails.pinReset.reason"]({}, { locale })} diff --git a/src/lib/emails/components/EmailHeadline.svelte b/src/lib/emails/components/EmailHeadline.svelte index 47ee03c..b5a8c73 100644 --- a/src/lib/emails/components/EmailHeadline.svelte +++ b/src/lib/emails/components/EmailHeadline.svelte @@ -1,4 +1,4 @@ - diff --git a/src/lib/emails/components/EmailLayout.svelte b/src/lib/emails/components/EmailLayout.svelte index b2ba8b0..52be5e8 100644 --- a/src/lib/emails/components/EmailLayout.svelte +++ b/src/lib/emails/components/EmailLayout.svelte @@ -1,8 +1,16 @@ -
@@ -11,7 +19,7 @@ {@render children?.()}
- {m["emails.poweredBy"]()} OpenReception + {m["emails.poweredBy"]({}, { locale })} OpenReception diff --git a/src/lib/emails/components/EmailText.svelte b/src/lib/emails/components/EmailText.svelte index c8a396b..f0c9e3e 100644 --- a/src/lib/emails/components/EmailText.svelte +++ b/src/lib/emails/components/EmailText.svelte @@ -1,4 +1,4 @@ - diff --git a/src/lib/server/email/email-service.ts b/src/lib/server/email/email-service.ts index 69e6d13..ca2af36 100644 --- a/src/lib/server/email/email-service.ts +++ b/src/lib/server/email/email-service.ts @@ -10,7 +10,6 @@ import type { SelectTenant, SelectUser } from "$lib/server/db/central-schema"; import { getTenantDb } from "$lib/server/db"; import * as tenantSchema from "$lib/server/db/tenant-schema"; import { eq } from "drizzle-orm"; -import { setLocale } from "$i18n/runtime"; import { m } from "$i18n/messages"; import { render } from "svelte/server"; import AppointmentBooked from "$lib/emails/AppointmentBooked.svelte"; @@ -139,9 +138,12 @@ export async function sendPinResetEmail( const recipient = createEmailRecipient(user); const locale = (recipient.language as Language) || "en"; - const subject = m["emails.pinReset.subject"]({ - tenant: tenant.longName, - }); + const subject = m["emails.pinReset.subject"]( + { + tenant: tenant.longName, + }, + { locale }, + ); const emailRender = render(PinReset, { props: { locale, @@ -193,9 +195,12 @@ export async function sendAppointmentReminderEmail( const { recipient, locale } = await getRecipient(user); const channelTitle = await getChannelTitle(tenant.id, appointment.channelId, locale); // Generate email - const subject = m["emails.appointmentReminder.subject"]({ - tenant: tenant.longName, - }); + const subject = m["emails.appointmentReminder.subject"]( + { + tenant: tenant.longName, + }, + { locale }, + ); const emailRender = render(AppointmentBooked, { props: { locale, @@ -219,7 +224,6 @@ const getRecipient = async (user: SelectClient | SelectUser) => { ? { email: user.email, language: user.language } : createEmailRecipient(user); const locale = (recipient.language as Language) || "en"; - setLocale(locale); return { recipient, locale }; }; @@ -259,10 +263,13 @@ export async function sendAppointmentRejectedEmail( const { recipient, locale } = await getRecipient(user); // Generate email - const subject = m["emails.appointmentRejected.subject"]({ - channel: channelTitle || appointment.channelId, - tenant: tenant.longName, - }); + const subject = m["emails.appointmentRejected.subject"]( + { + channel: channelTitle || appointment.channelId, + tenant: tenant.longName, + }, + { locale }, + ); const emailRender = render(AppointmentRejected, { props: { locale, @@ -303,10 +310,13 @@ export async function sendAppointmentCreatedEmail( const { recipient, locale } = await getRecipient(user); // Generate email - const subject = m["emails.appointmentBooked.subject"]({ - channel: channelTitle || appointment.channelId, - tenant: tenant.longName, - }); + const subject = m["emails.appointmentBooked.subject"]( + { + channel: channelTitle || appointment.channelId, + tenant: tenant.longName, + }, + { locale }, + ); const emailRender = render(AppointmentBooked, { props: { locale, @@ -344,10 +354,13 @@ export async function sendAppointmentRequestEmail( const agent = await agentService.getAgentById(appointment.agentId); const { recipient, locale } = await getRecipient(user); // Generate email - const subject = m["emails.appointmentRequest.subject"]({ - channel: channelTitle || appointment.channelId, - tenant: tenant.longName, - }); + const subject = m["emails.appointmentRequest.subject"]( + { + channel: channelTitle || appointment.channelId, + tenant: tenant.longName, + }, + { locale }, + ); const emailRender = render(AppointmentRequest, { props: { locale, @@ -364,35 +377,6 @@ export async function sendAppointmentRequestEmail( await sendEmail(recipient, subject, html, text, tenant.longName); } -/** - * Send appointment update notification email - * @param {SelectClient | SelectUser} user - Database user object - * @param {SelectTenant} tenant - Tenant information for branding - * @param {SelectAppointment} appointment - Updated appointment details - * @param {string} [channelTitle] - Optional channel title/name - * @param {string} [cancelUrl] - Optional URL to cancel appointment - * @throws {Error} When email sending fails - * @returns {Promise} - */ -export async function sendAppointmentUpdatedEmail( - user: SelectClient | SelectUser, - tenant: SelectTenant, - appointment: SelectAppointment, - channelTitle?: string, - cancelUrl?: string, -): Promise { - const recipient = createEmailRecipient(user); - const language = (recipient.language as Language) || "en"; - const subject = language === "en" ? "Appointment Updated" : "Termin aktualisiert"; - - await sendTemplatedEmail("appointment-updated", recipient, subject, language, tenant, { - appointment, - appointmentDate: appointment.appointmentDate, - title: channelTitle || appointment.channelId, - cancelUrl, - }); -} - /** * Generate base URL for email templates based on request URL and tenant * @param {URL} requestUrl - The request URL @@ -427,13 +411,17 @@ export async function sendConfirmationEmail( const baseUrl = generateBaseUrl(requestUrl); const confirmUrl = `${baseUrl}/confirm/${confirmationCode}`; const recipient = user; + const locale = (user.language as Language) ?? "en"; // Generate email - const subject = m["emails.confirmation.subject"]({ - tenant: tenant.longName, - }); + const subject = m["emails.confirmation.subject"]( + { + tenant: tenant.longName, + }, + { locale }, + ); const emailRender = render(Confirmation, { props: { - locale: (user.language as Language) ?? "en", + locale, user: user as SelectUserEmail, confirmUrl, expirationMinutes, @@ -464,10 +452,13 @@ export async function sendAppointmentCancelledEmail( // Create recipient directly for SelectClient type, use helper for SelectUser const { recipient, locale } = await getRecipient(user); // Generate email - const subject = m["emails.appointmentCancelled.subject"]({ - channel: channelTitle || appointment.channelId, - tenant: tenant.longName, - }); + const subject = m["emails.appointmentCancelled.subject"]( + { + channel: channelTitle || appointment.channelId, + tenant: tenant.longName, + }, + { locale }, + ); const emailRender = render(AppointmentCancelled, { props: { locale, @@ -499,7 +490,7 @@ export async function sendNotificationEmail( // Create recipient directly for SelectClient type, use helper for SelectUser const { recipient, locale } = await getRecipient(user); // Generate email - const subject = m["emails.notification.subject"](); + const subject = m["emails.notification.subject"]({}, { locale }); const emailRender = render(Notification, { props: { locale,