diff options
author | Raphael <mail@raphaelkabo.com> | 2025-05-28 18:58:46 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-28 18:58:46 +0100 |
commit | 3d84891118f8a81af3ddb978af9b3f8b02fd5d65 (patch) | |
tree | 0a8d344e331a0551b73435bbbb3919107737f69f /src/routes | |
parent | 6f0b7a44b995b6b66baf42a9369182fc05a90b34 (diff) | |
parent | 4664b6968fdcaca54268d60f400da02364213f05 (diff) |
Merge branch 'main' into main
Diffstat (limited to 'src/routes')
-rw-r--r-- | src/routes/event.ts | 25 | ||||
-rw-r--r-- | src/routes/frontend.ts | 101 | ||||
-rw-r--r-- | src/routes/magicLink.ts | 9 |
3 files changed, 79 insertions, 56 deletions
diff --git a/src/routes/event.ts b/src/routes/event.ts index ee45d96..84a7c6b 100644 --- a/src/routes/event.ts +++ b/src/routes/event.ts @@ -27,7 +27,8 @@ import ical from "ical"; import { markdownToSanitizedHTML } from "../util/markdown.js"; import { checkMagicLink, getConfigMiddleware } from "../lib/middleware.js"; import { getConfig } from "../lib/config.js"; - +import i18next from "i18next"; +moment.locale(i18next.language); const config = getConfig(); const storage = multer.memoryStorage(); @@ -397,33 +398,33 @@ router.put( : undefined, }; let diffText = - "<p>This event was just updated with new information.</p><ul>"; + "<p>" + i18next.t("routes.event.difftext") + "</p><ul>"; let displayDate; if (event.name !== updatedEvent.name) { - diffText += `<li>the event name changed to ${updatedEvent.name}</li>`; + diffText += `<li>` + i18next.t("routes.event.namechanged", { eventname: updatedEvent.name} ) + `</li>`; } if (event.location !== updatedEvent.location) { - diffText += `<li>the location changed to ${updatedEvent.location}</li>`; + diffText += `<li>` + i18next.t("routes.event.locationchanged", { location: updatedEvent.location} ) + `</li>`; } if ( event.start.toISOString() !== updatedEvent.start.toISOString() ) { displayDate = moment .tz(updatedEvent.start, updatedEvent.timezone) - .format("dddd D MMMM YYYY h:mm a"); - diffText += `<li>the start time changed to ${displayDate}</li>`; + .format(i18next.t("common.datetimeformat")); + diffText += `<li>` + i18next.t("routes.event.starttimechanged", { starttime: displayDate }) + `</li>`; } if (event.end.toISOString() !== updatedEvent.end.toISOString()) { displayDate = moment .tz(updatedEvent.end, updatedEvent.timezone) - .format("dddd D MMMM YYYY h:mm a"); - diffText += `<li>the end time changed to ${displayDate}</li>`; + .format(i18next.t("common.datetimeformat")); + diffText += `<li>` + i18next.t("routes.event.endtimechanged", { endtime: displayDate }) + `</li>`; } if (event.timezone !== updatedEvent.timezone) { - diffText += `<li>the time zone changed to ${updatedEvent.timezone}</li>`; + diffText += `<li>` + i18next.t("routes.event.timezonechanged", { timezone: updatedEvent.timezone }) + `</li>`; } if (event.description !== updatedEvent.description) { - diffText += `<li>the event description changed</li>`; + diffText += `<li>` + i18next.t("routes.event.descriptionchanged") + `</li>`; } diffText += `</ul>`; const updatedEventObject = await Event.findOneAndUpdate( @@ -487,7 +488,7 @@ router.put( req.emailService.sendEmailFromTemplate({ to: config.general.email, bcc: attendeeEmails, - subject: `${event.name} was just edited`, + subject: i18next.t("routes.event.editedsubject", { eventname: event.name}), templateName: "editEvent", templateData: { diffText, @@ -672,7 +673,7 @@ router.delete( if (attendeeEmail) { await req.emailService.sendEmailFromTemplate({ to: attendeeEmail, - subject: "You have been removed from an event", + subject: i18next.t("routes.removeeventattendeesubject"), templateName: "unattendEvent", templateData: { eventID: req.params.eventID, diff --git a/src/routes/frontend.ts b/src/routes/frontend.ts index 1b95763..fca14c6 100644 --- a/src/routes/frontend.ts +++ b/src/routes/frontend.ts @@ -7,7 +7,7 @@ import { instanceDescription, instanceRules, } from "../lib/config.js"; -import { addToLog, exportICal } from "../helpers.js"; +import { addToLog, exportIcal } from "../helpers.js"; import Event from "../models/Event.js"; import EventGroup, { IEventGroup } from "../models/EventGroup.js"; import { @@ -18,6 +18,7 @@ import MagicLink from "../models/MagicLink.js"; import { getConfigMiddleware } from "../lib/middleware.js"; import { getMessage } from "../util/messages.js"; import { EventListEvent, bucketEventsByMonth } from "../lib/event.js"; +import i18next from "i18next"; const router = Router(); @@ -48,7 +49,7 @@ router.get("/new", (_: Request, res: Response) => { return res.render("createEventMagicLink", frontendConfig(res)); } return res.render("newevent", { - title: "New event", + title: i18next.t("frontend.newevent"), ...frontendConfig(res), }); }); @@ -69,12 +70,12 @@ router.get("/new/:magicLinkToken", async (req: Request, res: Response) => { ...frontendConfig(res), message: { type: "danger", - text: "This magic link is invalid or has expired. Please request a new one here.", + text: i18next.t("routes.magiclink-invalid"), }, }); } res.render("newevent", { - title: "New event", + title: i18next.t("frontend.newevent"), ...frontendConfig(res), magicLinkToken: req.params.magicLinkToken, creatorEmail: magicLink.email, @@ -99,9 +100,9 @@ router.get("/events", async (_: Request, res: Response) => { name: event.name, location: event.location, displayDate: isSameDay - ? startMoment.format("D MMM YYYY") - : `${startMoment.format("D MMM YYYY")} - ${endMoment.format( - "D MMM YYYY", + ? startMoment.format("LL") + : `${startMoment.format("LL")} - ${endMoment.format( + "LL", )}`, eventHasConcluded: endMoment.isBefore(moment.tz(event.timezone)), eventGroup: event.eventGroup as any as IEventGroup, @@ -131,7 +132,7 @@ router.get("/events", async (_: Request, res: Response) => { }); res.render("publicEventList", { - title: "Public events", + title: i18next.t("frontend.publicevents"), upcomingEvents: upcomingEventsInMonthBuckets, pastEvents: pastEventsInMonthBuckets, eventGroups: updatedEventGroups, @@ -153,31 +154,53 @@ router.get("/:eventID", async (req: Request, res: Response) => { } const parsedLocation = event.location.replace(/\s+/g, "+"); let displayDate; + const dateformat = i18next.t("frontend.dateformat"); + const timeformat = i18next.t('frontend.timeformat'); if (moment.tz(event.end, event.timezone).isSame(event.start, "day")) { // Happening during one day - displayDate = - moment - .tz(event.start, event.timezone) - .format( - 'dddd D MMMM YYYY [<span class="text-muted">from</span>] h:mm a', - ) + - moment - .tz(event.end, event.timezone) - .format( - ' [<span class="text-muted">to</span>] h:mm a [<span class="text-muted">](z)[</span>]', - ); + displayDate = i18next.t("frontend.displaydate-sameday", + { + startdate: + moment + .tz(event.start, event.timezone) + .format(dateformat), + starttime: + moment + .tz(event.start, event.timezone) + .format(timeformat), + endtime: + moment + .tz(event.end, event.timezone) + .format(timeformat), + timezone: + moment + .tz(event.end, event.timezone) + .format('(z)',) + }); } else { - displayDate = - moment - .tz(event.start, event.timezone) - .format( - 'dddd D MMMM YYYY [<span class="text-muted">at</span>] h:mm a', - ) + - moment - .tz(event.end, event.timezone) - .format( - ' [<span class="text-muted">–</span>] dddd D MMMM YYYY [<span class="text-muted">at</span>] h:mm a [<span class="text-muted">](z)[</span>]', - ); + displayDate = i18next.t("frontend.displaydate-days", + { + startdate: + moment + .tz(event.start, event.timezone) + .format(dateformat), + starttime: + moment + .tz(event.start, event.timezone) + .format(timeformat), + enddate: + moment + .tz(event.end, event.timezone) + .format(dateformat), + endtime: + moment + .tz(event.end, event.timezone) + .format(timeformat), + timezone: + moment + .tz(event.end, event.timezone) + .format('(z)',) + }); } let eventStartISO = moment.tz(event.start, "Etc/UTC").toISOString(); let eventEndISO = moment.tz(event.end, "Etc/UTC").toISOString(); @@ -256,7 +279,7 @@ router.get("/:eventID", async (req: Request, res: Response) => { el.id = el._id; } if (el.number && el.number > 1) { - el.name = `${el.name} (${el.number} people)`; + el.name = `${el.name} ${i18next.t("frontend.elnumber", { count: el.number })}`; } return { ...el, @@ -428,8 +451,8 @@ router.get("/group/:eventGroupID", async (req: Request, res: Response) => { .sort("start"); const updatedEvents: EventListEvent[] = events.map((event) => { - const startMoment = moment.tz(event.start, event.timezone); - const endMoment = moment.tz(event.end, event.timezone); + const startMoment = moment.tz(event.start, event.timezone).locale(i18next.language); + const endMoment = moment.tz(event.end, event.timezone).locale(i18next.language); const isSameDay = startMoment.isSame(endMoment, "day"); return { @@ -437,10 +460,8 @@ router.get("/group/:eventGroupID", async (req: Request, res: Response) => { name: event.name, location: event.location, displayDate: isSameDay - ? startMoment.format("D MMM YYYY") - : `${startMoment.format("D MMM YYYY")} - ${endMoment.format( - "D MMM YYYY", - )}`, + ? startMoment.format("LL") + : `${startMoment.format("LL")} - ${endMoment.format("LL")}`, eventHasConcluded: endMoment.isBefore( moment.tz(event.timezone), ), @@ -545,7 +566,7 @@ router.get( const events = await Event.find({ eventGroup: eventGroup._id, }).sort("start"); - const string = exportICal(events, eventGroup.name); + const string = exportIcal(events, eventGroup.name); res.set("Content-Type", "text/calendar").send(string); } } catch (err) { @@ -567,7 +588,7 @@ router.get("/export/event/:eventID", async (req: Request, res: Response) => { }).populate("eventGroup"); if (event) { - const string = exportICal([event], event.name); + const string = exportIcal([event], event.name); res.set("Content-Type", "text/calendar").send(string); } } catch (err) { @@ -593,7 +614,7 @@ router.get( const events = await Event.find({ eventGroup: eventGroup._id, }).sort("start"); - const string = exportICal(events, eventGroup.name); + const string = exportIcal(events, eventGroup.name); res.set("Content-Type", "text/calendar").send(string); } } catch (err) { diff --git a/src/routes/magicLink.ts b/src/routes/magicLink.ts index e0a6310..1e0f87b 100644 --- a/src/routes/magicLink.ts +++ b/src/routes/magicLink.ts @@ -3,6 +3,7 @@ import { frontendConfig } from "../lib/config.js"; import { generateMagicLinkToken } from "../util/generator.js"; import MagicLink from "../models/MagicLink.js"; import { getConfigMiddleware } from "../lib/middleware.js"; +import i18next from "i18next"; const router = Router(); @@ -15,7 +16,7 @@ router.post("/magic-link/event/create", async (req: Request, res: Response) => { ...frontendConfig(res), message: { type: "danger", - text: "Please provide an email address.", + text: i18next.t("routes.magiclink.provideemail"), }, }); return; @@ -30,7 +31,7 @@ router.post("/magic-link/event/create", async (req: Request, res: Response) => { ...frontendConfig(res), message: { type: "success", - text: "Thanks! If this email address can create events, you should receive an email with a magic link.", + text: i18next.t("routes.magiclink.thanks"), }, }); return; @@ -49,7 +50,7 @@ router.post("/magic-link/event/create", async (req: Request, res: Response) => { req.emailService.sendEmailFromTemplate({ to: email, - subject: "Magic link to create an event", + subject: i18next.t("routes.magiclink.mailsubject"), templateName: "createEventMagicLink", templateData: { token @@ -59,7 +60,7 @@ router.post("/magic-link/event/create", async (req: Request, res: Response) => { ...frontendConfig(res), message: { type: "success", - text: "Thanks! If this email address can create events, you should receive an email with a magic link.", + text: i18next.t("routes.magiclink.thanks"), }, }); }); |