Fixes localisation of {EVENT_DATE} in workflows (#6907)
* translate {EVENT_DATE} variable to correct language * fix locale for cron schedule reminder emails/sms * fix type error * add missing locale to attendees * fix type error * code clean up * revert last commit * using Intl for date translations --------- Co-authored-by: CarinaWolli <wollencarina@gmail.com>
This commit is contained in:
parent
a4b7f1af65
commit
b3d8d7e944
|
@ -95,6 +95,12 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||
? reminder.booking?.attendees[0].timeZone
|
||||
: reminder.booking?.user?.timeZone;
|
||||
|
||||
const locale =
|
||||
reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE ||
|
||||
reminder.workflowStep.action === WorkflowActions.SMS_ATTENDEE
|
||||
? reminder.booking?.attendees[0].locale
|
||||
: reminder.booking?.user?.locale;
|
||||
|
||||
let emailContent = {
|
||||
emailSubject: reminder.workflowStep.emailSubject || "",
|
||||
emailBody: {
|
||||
|
@ -131,13 +137,13 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||
const emailSubject = await customTemplate(
|
||||
reminder.workflowStep.emailSubject || "",
|
||||
variables,
|
||||
reminder.booking?.user?.locale || ""
|
||||
locale || ""
|
||||
);
|
||||
emailContent.emailSubject = emailSubject.text;
|
||||
emailContent.emailBody = await customTemplate(
|
||||
reminder.workflowStep.reminderBody || "",
|
||||
variables,
|
||||
reminder.booking?.user?.locale || ""
|
||||
locale || ""
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -76,6 +76,12 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||
|
||||
const senderID = getSenderId(sendTo, reminder.workflowStep.sender);
|
||||
|
||||
const locale =
|
||||
reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE ||
|
||||
reminder.workflowStep.action === WorkflowActions.SMS_ATTENDEE
|
||||
? reminder.booking?.attendees[0].locale
|
||||
: reminder.booking?.user?.locale;
|
||||
|
||||
let message: string | null = reminder.workflowStep.reminderBody;
|
||||
switch (reminder.workflowStep.template) {
|
||||
case WorkflowTemplates.REMINDER:
|
||||
|
@ -104,7 +110,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||
const customMessage = await customTemplate(
|
||||
reminder.workflowStep.reminderBody || "",
|
||||
variables,
|
||||
reminder.booking?.user?.locale || ""
|
||||
locale || ""
|
||||
);
|
||||
message = customMessage.text;
|
||||
break;
|
||||
|
|
|
@ -108,13 +108,14 @@ export const scheduleEmailReminder = async (
|
|||
meetingUrl: bookingMetadataSchema.parse(evt.metadata || {})?.videoCallUrl,
|
||||
};
|
||||
|
||||
const emailSubjectTemplate = await customTemplate(
|
||||
emailSubject,
|
||||
variables,
|
||||
evt.organizer.language.locale
|
||||
);
|
||||
const locale =
|
||||
action === WorkflowActions.EMAIL_ATTENDEE || action === WorkflowActions.SMS_ATTENDEE
|
||||
? evt.attendees[0].language?.locale
|
||||
: evt.organizer.language.locale;
|
||||
|
||||
const emailSubjectTemplate = await customTemplate(emailSubject, variables, locale);
|
||||
emailContent.emailSubject = emailSubjectTemplate.text;
|
||||
emailContent.emailBody = await customTemplate(emailBody, variables, evt.organizer.language.locale);
|
||||
emailContent.emailBody = await customTemplate(emailBody, variables, locale);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import dayjs from "@calcom/dayjs";
|
|||
import prisma from "@calcom/prisma";
|
||||
import { Prisma } from "@calcom/prisma/client";
|
||||
import { bookingMetadataSchema } from "@calcom/prisma/zod-utils";
|
||||
import { Person } from "@calcom/types/Calendar";
|
||||
|
||||
import { getSenderId } from "../alphanumericSenderIdSupport";
|
||||
import * as twilio from "./smsProviders/twilioProvider";
|
||||
|
@ -24,7 +25,7 @@ export enum timeUnitLowerCase {
|
|||
|
||||
export type BookingInfo = {
|
||||
uid?: string | null;
|
||||
attendees: { name: string; email: string; timeZone: string }[];
|
||||
attendees: { name: string; email: string; timeZone: string; language: { locale: string } }[];
|
||||
organizer: {
|
||||
language: { locale: string };
|
||||
name: string;
|
||||
|
@ -87,6 +88,11 @@ export const scheduleSMSReminder = async (
|
|||
const timeZone =
|
||||
action === WorkflowActions.SMS_ATTENDEE ? evt.attendees[0].timeZone : evt.organizer.timeZone;
|
||||
|
||||
const locale =
|
||||
action === WorkflowActions.EMAIL_ATTENDEE || action === WorkflowActions.SMS_ATTENDEE
|
||||
? evt.attendees[0].language?.locale
|
||||
: evt.organizer.language.locale;
|
||||
|
||||
switch (template) {
|
||||
case WorkflowTemplates.REMINDER:
|
||||
message = smsReminderTemplate(evt.startTime, evt.title, timeZone, attendeeName, name) || message;
|
||||
|
@ -105,7 +111,7 @@ export const scheduleSMSReminder = async (
|
|||
customInputs: evt.customInputs,
|
||||
meetingUrl: bookingMetadataSchema.parse(evt.metadata || {})?.videoCallUrl,
|
||||
};
|
||||
const customMessage = await customTemplate(message, variables, evt.organizer.language.locale);
|
||||
const customMessage = await customTemplate(message, variables, locale);
|
||||
message = customMessage.text;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,14 @@ export type VariablesType = {
|
|||
};
|
||||
|
||||
const customTemplate = async (text: string, variables: VariablesType, locale: string) => {
|
||||
const timeWithTimeZone = `${variables.eventTime?.locale(locale).format("HH:mm")} (${variables.timeZone})`;
|
||||
const translatedDate = new Intl.DateTimeFormat(locale, {
|
||||
weekday: "long",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
}).format(variables.eventDate?.toDate());
|
||||
|
||||
const timeWithTimeZone = `${variables.eventTime?.format("HH:mm")} (${variables.timeZone})`;
|
||||
let locationString = variables.location || "";
|
||||
|
||||
if (text.includes("{LOCATION}")) {
|
||||
|
@ -30,7 +37,7 @@ const customTemplate = async (text: string, variables: VariablesType, locale: st
|
|||
.replaceAll("{ATTENDEE}", variables.attendeeName || "")
|
||||
.replaceAll("{ORGANIZER_NAME}", variables.organizerName || "") //old variable names
|
||||
.replaceAll("{ATTENDEE_NAME}", variables.attendeeName || "") //old variable names
|
||||
.replaceAll("{EVENT_DATE}", variables.eventDate?.locale(locale).format("dddd, MMMM D, YYYY") || "")
|
||||
.replaceAll("{EVENT_DATE}", translatedDate)
|
||||
.replaceAll("{EVENT_TIME}", timeWithTimeZone)
|
||||
.replaceAll("{LOCATION}", locationString)
|
||||
.replaceAll("{ADDITIONAL_NOTES}", variables.additionalNotes || "")
|
||||
|
|
|
@ -433,7 +433,12 @@ export const workflowsRouter = router({
|
|||
const bookingInfo = {
|
||||
uid: booking.uid,
|
||||
attendees: booking.attendees.map((attendee) => {
|
||||
return { name: attendee.name, email: attendee.email, timeZone: attendee.timeZone };
|
||||
return {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
timeZone: attendee.timeZone,
|
||||
language: { locale: attendee.locale || "" },
|
||||
};
|
||||
}),
|
||||
organizer: booking.user
|
||||
? {
|
||||
|
@ -625,7 +630,12 @@ export const workflowsRouter = router({
|
|||
const bookingInfo = {
|
||||
uid: booking.uid,
|
||||
attendees: booking.attendees.map((attendee) => {
|
||||
return { name: attendee.name, email: attendee.email, timeZone: attendee.timeZone };
|
||||
return {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
timeZone: attendee.timeZone,
|
||||
language: { locale: attendee.locale || "" },
|
||||
};
|
||||
}),
|
||||
organizer: booking.user
|
||||
? {
|
||||
|
@ -746,7 +756,12 @@ export const workflowsRouter = router({
|
|||
const bookingInfo = {
|
||||
uid: booking.uid,
|
||||
attendees: booking.attendees.map((attendee) => {
|
||||
return { name: attendee.name, email: attendee.email, timeZone: attendee.timeZone };
|
||||
return {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
timeZone: attendee.timeZone,
|
||||
language: { locale: attendee.locale || "" },
|
||||
};
|
||||
}),
|
||||
organizer: booking.user
|
||||
? {
|
||||
|
@ -903,72 +918,72 @@ export const workflowsRouter = router({
|
|||
}
|
||||
|
||||
if (isSMSAction(step.action) /*|| step.action === WorkflowActions.EMAIL_ADDRESS*/ /*) {
|
||||
const hasTeamPlan = (await ctx.prisma.membership.count({ where: { userId: user.id } })) > 0;
|
||||
if (!hasTeamPlan) {
|
||||
throw new TRPCError({ code: "UNAUTHORIZED", message: "Team plan needed" });
|
||||
}
|
||||
}
|
||||
const hasTeamPlan = (await ctx.prisma.membership.count({ where: { userId: user.id } })) > 0;
|
||||
if (!hasTeamPlan) {
|
||||
throw new TRPCError({ code: "UNAUTHORIZED", message: "Team plan needed" });
|
||||
}
|
||||
}
|
||||
|
||||
const booking = await ctx.prisma.booking.findFirst({
|
||||
orderBy: {
|
||||
createdAt: "desc",
|
||||
},
|
||||
where: {
|
||||
userId: ctx.user.id,
|
||||
},
|
||||
include: {
|
||||
attendees: true,
|
||||
user: true,
|
||||
},
|
||||
});
|
||||
const booking = await ctx.prisma.booking.findFirst({
|
||||
orderBy: {
|
||||
createdAt: "desc",
|
||||
},
|
||||
where: {
|
||||
userId: ctx.user.id,
|
||||
},
|
||||
include: {
|
||||
attendees: true,
|
||||
user: true,
|
||||
},
|
||||
});
|
||||
|
||||
let evt: BookingInfo;
|
||||
if (booking) {
|
||||
evt = {
|
||||
uid: booking?.uid,
|
||||
attendees:
|
||||
booking?.attendees.map((attendee) => {
|
||||
return { name: attendee.name, email: attendee.email, timeZone: attendee.timeZone };
|
||||
}) || [],
|
||||
organizer: {
|
||||
language: {
|
||||
locale: booking?.user?.locale || "",
|
||||
},
|
||||
name: booking?.user?.name || "",
|
||||
email: booking?.user?.email || "",
|
||||
timeZone: booking?.user?.timeZone || "",
|
||||
},
|
||||
startTime: booking?.startTime.toISOString() || "",
|
||||
endTime: booking?.endTime.toISOString() || "",
|
||||
title: booking?.title || "",
|
||||
location: booking?.location || null,
|
||||
additionalNotes: booking?.description || null,
|
||||
customInputs: booking?.customInputs,
|
||||
};
|
||||
} else {
|
||||
//if no booking exists create an example booking
|
||||
evt = {
|
||||
attendees: [{ name: "John Doe", email: "john.doe@example.com", timeZone: "Europe/London" }],
|
||||
organizer: {
|
||||
language: {
|
||||
locale: ctx.user.locale,
|
||||
},
|
||||
name: ctx.user.name || "",
|
||||
email: ctx.user.email,
|
||||
timeZone: ctx.user.timeZone,
|
||||
},
|
||||
startTime: dayjs().add(10, "hour").toISOString(),
|
||||
endTime: dayjs().add(11, "hour").toISOString(),
|
||||
title: "Example Booking",
|
||||
location: "Office",
|
||||
additionalNotes: "These are additional notes",
|
||||
};
|
||||
}
|
||||
let evt: BookingInfo;
|
||||
if (booking) {
|
||||
evt = {
|
||||
uid: booking?.uid,
|
||||
attendees:
|
||||
booking?.attendees.map((attendee) => {
|
||||
return { name: attendee.name, email: attendee.email, timeZone: attendee.timeZone };
|
||||
}) || [],
|
||||
organizer: {
|
||||
language: {
|
||||
locale: booking?.user?.locale || "",
|
||||
},
|
||||
name: booking?.user?.name || "",
|
||||
email: booking?.user?.email || "",
|
||||
timeZone: booking?.user?.timeZone || "",
|
||||
},
|
||||
startTime: booking?.startTime.toISOString() || "",
|
||||
endTime: booking?.endTime.toISOString() || "",
|
||||
title: booking?.title || "",
|
||||
location: booking?.location || null,
|
||||
additionalNotes: booking?.description || null,
|
||||
customInputs: booking?.customInputs,
|
||||
};
|
||||
} else {
|
||||
//if no booking exists create an example booking
|
||||
evt = {
|
||||
attendees: [{ name: "John Doe", email: "john.doe@example.com", timeZone: "Europe/London" }],
|
||||
organizer: {
|
||||
language: {
|
||||
locale: ctx.user.locale,
|
||||
},
|
||||
name: ctx.user.name || "",
|
||||
email: ctx.user.email,
|
||||
timeZone: ctx.user.timeZone,
|
||||
},
|
||||
startTime: dayjs().add(10, "hour").toISOString(),
|
||||
endTime: dayjs().add(11, "hour").toISOString(),
|
||||
title: "Example Booking",
|
||||
location: "Office",
|
||||
additionalNotes: "These are additional notes",
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
action === WorkflowActions.EMAIL_ATTENDEE ||
|
||||
action === WorkflowActions.EMAIL_HOST /*||
|
||||
action === WorkflowActions.EMAIL_ADDRESS*/
|
||||
if (
|
||||
action === WorkflowActions.EMAIL_ATTENDEE ||
|
||||
action === WorkflowActions.EMAIL_HOST /*||
|
||||
action === WorkflowActions.EMAIL_ADDRESS*/
|
||||
/*) {
|
||||
scheduleEmailReminder(
|
||||
evt,
|
||||
|
|
Loading…
Reference in New Issue
Block a user