From 23e49c6e6e63a518e704f82879a5fdcf268c51d8 Mon Sep 17 00:00:00 2001 From: INOUE Daisuke Date: Tue, 8 Apr 2025 22:14:04 +0900 Subject: 1st stage, only language switch. Thank you, MomentQYC ( https://github.com/MomentQYC ). Your first attemt encourage me. --- src/routes/frontend.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/routes') diff --git a/src/routes/frontend.ts b/src/routes/frontend.ts index 14bb779..96d7587 100644 --- a/src/routes/frontend.ts +++ b/src/routes/frontend.ts @@ -8,7 +8,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 { @@ -546,7 +546,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) { @@ -568,7 +568,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) { @@ -594,7 +594,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) { -- cgit v1.2.3 From f2ee19f15a78125a1dc2ba8b9c175dd9831e5700 Mon Sep 17 00:00:00 2001 From: INOUE Daisuke Date: Thu, 20 Mar 2025 22:54:38 +0900 Subject: hidden attendees (? people) --- locales/en-US.json | 1 + locales/en.json | 1 + locales/ja.json | 7 ++++--- src/app.ts | 6 ------ src/routes/frontend.ts | 3 ++- 5 files changed, 8 insertions(+), 10 deletions(-) (limited to 'src/routes') diff --git a/locales/en-US.json b/locales/en-US.json index afa6d5f..a02c500 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -101,6 +101,7 @@ "eventpwd": "Event password", "fixerrors": "Please fix these errors:", "forgotpwd": "Forgot password", + "frontend.elnumber": "({{count}} people)", "frontend.eventattendees": "people", "group.about": "About", "group.addevent": "To link an existing event to this group, copy and paste the two codes below into the 'Event Group' box when creating a new event or editing an existing event.", diff --git a/locales/en.json b/locales/en.json index afa6d5f..a02c500 100644 --- a/locales/en.json +++ b/locales/en.json @@ -101,6 +101,7 @@ "eventpwd": "Event password", "fixerrors": "Please fix these errors:", "forgotpwd": "Forgot password", + "frontend.elnumber": "({{count}} people)", "frontend.eventattendees": "people", "group.about": "About", "group.addevent": "To link an existing event to this group, copy and paste the two codes below into the 'Event Group' box when creating a new event or editing an existing event.", diff --git a/locales/ja.json b/locales/ja.json index f04c342..6d7de9e 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -26,7 +26,7 @@ "event.attendeenamedesc": "またはニックネームとか...", "event.attendeenum": "何人で参加しますか?", "event.attendees": "参加者", - "event.attendeevisible": "公開参加者リストに自分の名前を載せる", + "event.attendeevisible": "このイベントの参加者リストに参加者名を載せる", "event.attendeevisibledesc": "参加者名を匿名にする場合でも、イベント主催者だけは確認できます。", "event.attention": "このイベントの編集用秘密パスワード : {{eventData.editToken}}
ブラウザストレージに保存してあり、メールアドレスを入力したのならメールでも送信しています。メールアドレスを入力しなかったのなら、すぐに安全な場所に保存してください。もう二度と表示しませんので!", "event.capacity": "このイベントは満員です。", @@ -41,7 +41,7 @@ "event.editlater": "後でいつでも編集できます。", "event.ended": "終了済み", "event.enternum": "人数を入力してください", - "event.hidden": "( 匿名 )", + "event.hidden": " - 匿名", "event.hiddenattendee_one": "匿名 {{count}} 人", "event.hiddenattendee_other": "匿名 {{count}} 人", "event.hiddenattendee_zero": "匿名 なし", @@ -101,6 +101,7 @@ "eventpwd": "イベントパスワード", "fixerrors": "エラーを修正してください :", "forgotpwd": "パスワードがわからない?", + "frontend.elnumber": "( {{count}} 人 )", "frontend.eventattendees": "人で", "group.about": "このグループについて", "group.addevent": "このグループにイベントをリンクするには、新しくイベントを作る際に、もしくは既存のイベントを編集して、以下の 2 つのコードをコピー・貼り付けします。", @@ -195,4 +196,4 @@ "upcomingevents": "今後のイベント", "wontshow": "どこにも表示しません ( 任意 )。", "youremail": "あなたのメールアドレス" -} \ No newline at end of file +} diff --git a/src/app.ts b/src/app.ts index 9828905..9301484 100755 --- a/src/app.ts +++ b/src/app.ts @@ -125,12 +125,6 @@ async function initializeApp() { console.error('handlebars-i18next helper is not properly loaded'); } - - (hbsInstance.handlebars as typeof Handlebars).registerHelper('pluralize', function(count: number, key: string, options: any) { - const translation = i18next.t(key, { count: count }); - return translation; - }); - app.engine("handlebars", hbsInstance.engine); app.set("view engine", "handlebars"); app.set("hbsInstance", hbsInstance); diff --git a/src/routes/frontend.ts b/src/routes/frontend.ts index 96d7587..40b5393 100644 --- a/src/routes/frontend.ts +++ b/src/routes/frontend.ts @@ -19,6 +19,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(); @@ -257,7 +258,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, -- cgit v1.2.3 From 2449234e28aab435ffe28d567ece8c651d45d2b3 Mon Sep 17 00:00:00 2001 From: INOUE Daisuke Date: Sat, 22 Mar 2025 21:03:25 +0900 Subject: DateTime format, and some translation fix --- locales/en-US.json | 13 +++++++- locales/en.json | 13 +++++++- locales/ja.json | 19 ++++++++--- src/lib/event.ts | 4 ++- src/routes/frontend.ts | 91 ++++++++++++++++++++++++++++++++------------------ views/event.handlebars | 4 +-- 6 files changed, 102 insertions(+), 42 deletions(-) (limited to 'src/routes') diff --git a/locales/en-US.json b/locales/en-US.json index a02c500..d397809 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -11,6 +11,7 @@ "create": "Create", "creating": "Creating...", "creatoremaildesc": "If you provide your email, we will send your secret editing password here, and use it to notify you of updates to the event.", + "datetimeformat": "{{thedate, intlDate}}", "del": "Delete", "edittoken": "Enter editing password", "edittokendesc": "Enter the editing password you received by email or were shown when the event was created.", @@ -31,6 +32,8 @@ "event.attention": "Your secret editing password for this event is: {{eventData.editToken}}. It's been saved in your browser storage, and if you supplied your email, it's also been sent to you. If you didn't supply your email, you must save it somewhere safe, because it won't be shown again!", "event.capacity": "This event is at capacity.", "event.comment": "Comment", + "event.commentauthor": "Name", + "event.commentauthorph": "Your name", "event.commentcontent": "What would you like to say?", "event.concludeddel": " This event has concluded. It can no longer be edited{{#if eventWillBeDeleted}}, and will be automatically deleted {{daysUntilDeletion}}{{/if}}.", "event.confremoveattendee": "Are you sure you want to remove this attendee from the event? This action cannot be undone.", @@ -73,7 +76,7 @@ "event.p.hostname": "Host name", "event.p.hostnamedesc": "Will be shown on the event page (optional).", "event.p.maxattendees": "Attendee limit", - "event.p.maxattendeestitle": "This event is at capacity.", + "event.p.maxattendeestitle": "Set a limit on the maximum number of attendees", "event.p.publicevent": "Display this event on the public event list", "event.p.timezone": "Timezone", "event.partof": "{{eventData.eventGroup.name}}", @@ -101,8 +104,14 @@ "eventpwd": "Event password", "fixerrors": "Please fix these errors:", "forgotpwd": "Forgot password", + "frontend.dateformat": "LL", + "frontend.displaydate-days": "{{ startdate }} at {{ starttime }} - {{ enddate }} at {{ endtime }} {{ timezone }}", + "frontend.displaydate-sameday": "{{ startdate }} from {{ starttime }} to {{ endtime }}{{ timezone}}", "frontend.elnumber": "({{count}} people)", "frontend.eventattendees": "people", + "frontend.publicevents": "Public events", + "frontend.sameday.to": " to ", + "frontend.timeformat": "LT", "group.about": "About", "group.addevent": "To link an existing event to this group, copy and paste the two codes below into the 'Event Group' box when creating a new event or editing an existing event.", "group.del": "Delete this event group", @@ -157,6 +166,7 @@ "interaction": "Users can post comments on this event", "join": "Users can mark themselves as attending this event", "joinemaildesc": "If you provide your email, you will receive updates to the event.", + "magiclink-invalid": "This magic link is invalid or has expired. Please request a new one here.", "main.defaultmetadata": "An easier, quicker, and much less privacy-invading way to make and share events", "main.footnote": " Gathio version {{version}} · GitHub · Made with by Raphael and contributors", "mdsupport": "Markdown formatting\nsupported.", @@ -195,5 +205,6 @@ "snappy": "Make it snappy.", "upcomingevents": "Upcoming events", "wontshow": "Will not be shown anywhere (optional).", + "year-month-format": "MMMM YYYY", "youremail": "Your email" } \ No newline at end of file diff --git a/locales/en.json b/locales/en.json index a02c500..d397809 100644 --- a/locales/en.json +++ b/locales/en.json @@ -11,6 +11,7 @@ "create": "Create", "creating": "Creating...", "creatoremaildesc": "If you provide your email, we will send your secret editing password here, and use it to notify you of updates to the event.", + "datetimeformat": "{{thedate, intlDate}}", "del": "Delete", "edittoken": "Enter editing password", "edittokendesc": "Enter the editing password you received by email or were shown when the event was created.", @@ -31,6 +32,8 @@ "event.attention": "Your secret editing password for this event is: {{eventData.editToken}}. It's been saved in your browser storage, and if you supplied your email, it's also been sent to you. If you didn't supply your email, you must save it somewhere safe, because it won't be shown again!", "event.capacity": "This event is at capacity.", "event.comment": "Comment", + "event.commentauthor": "Name", + "event.commentauthorph": "Your name", "event.commentcontent": "What would you like to say?", "event.concludeddel": " This event has concluded. It can no longer be edited{{#if eventWillBeDeleted}}, and will be automatically deleted {{daysUntilDeletion}}{{/if}}.", "event.confremoveattendee": "Are you sure you want to remove this attendee from the event? This action cannot be undone.", @@ -73,7 +76,7 @@ "event.p.hostname": "Host name", "event.p.hostnamedesc": "Will be shown on the event page (optional).", "event.p.maxattendees": "Attendee limit", - "event.p.maxattendeestitle": "This event is at capacity.", + "event.p.maxattendeestitle": "Set a limit on the maximum number of attendees", "event.p.publicevent": "Display this event on the public event list", "event.p.timezone": "Timezone", "event.partof": "{{eventData.eventGroup.name}}", @@ -101,8 +104,14 @@ "eventpwd": "Event password", "fixerrors": "Please fix these errors:", "forgotpwd": "Forgot password", + "frontend.dateformat": "LL", + "frontend.displaydate-days": "{{ startdate }} at {{ starttime }} - {{ enddate }} at {{ endtime }} {{ timezone }}", + "frontend.displaydate-sameday": "{{ startdate }} from {{ starttime }} to {{ endtime }}{{ timezone}}", "frontend.elnumber": "({{count}} people)", "frontend.eventattendees": "people", + "frontend.publicevents": "Public events", + "frontend.sameday.to": " to ", + "frontend.timeformat": "LT", "group.about": "About", "group.addevent": "To link an existing event to this group, copy and paste the two codes below into the 'Event Group' box when creating a new event or editing an existing event.", "group.del": "Delete this event group", @@ -157,6 +166,7 @@ "interaction": "Users can post comments on this event", "join": "Users can mark themselves as attending this event", "joinemaildesc": "If you provide your email, you will receive updates to the event.", + "magiclink-invalid": "This magic link is invalid or has expired. Please request a new one here.", "main.defaultmetadata": "An easier, quicker, and much less privacy-invading way to make and share events", "main.footnote": " Gathio version {{version}} · GitHub · Made with by Raphael and contributors", "mdsupport": "Markdown formatting\nsupported.", @@ -195,5 +205,6 @@ "snappy": "Make it snappy.", "upcomingevents": "Upcoming events", "wontshow": "Will not be shown anywhere (optional).", + "year-month-format": "MMMM YYYY", "youremail": "Your email" } \ No newline at end of file diff --git a/locales/ja.json b/locales/ja.json index 6d7de9e..44c0b63 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -11,6 +11,7 @@ "create": "作成", "creating": "作成中...", "creatoremaildesc": "メールアドレスを入力すると、編集用秘密パスワードを送信します。またイベントについての更新情報も送信します。", + "datetimeformat": "{{thedate, long}}", "del": "削除", "edittoken": "編集パスワードを入力します", "edittokendesc": "編集パスワードを入力してください。イベントが作成時に表示したほか、メールアドレスを入力していたらメールでも送信しています。", @@ -31,6 +32,8 @@ "event.attention": "このイベントの編集用秘密パスワード : {{eventData.editToken}}
ブラウザストレージに保存してあり、メールアドレスを入力したのならメールでも送信しています。メールアドレスを入力しなかったのなら、すぐに安全な場所に保存してください。もう二度と表示しませんので!", "event.capacity": "このイベントは満員です。", "event.comment": "コメント", + "event.commentauthor": "お名前", + "event.commentauthorph": "お名前をお願いします", "event.commentcontent": "コメントをどうぞ", "event.concludeddel": "このイベントは終了しました。編集もできなくなりました。{{#if eventWillBeDeleted}}また {{daysUntilDeletion}} 日後に自動的に削除します。{{/if}}", "event.confremoveattendee": "この参加者をイベントから削除します。よろしいですか? この操作は取り消しできません。", @@ -73,7 +76,7 @@ "event.p.hostname": "主催者名", "event.p.hostnamedesc": "イベントのページに表示します ( 任意 )。", "event.p.maxattendees": "定員", - "event.p.maxattendeestitle": "満員です。", + "event.p.maxattendeestitle": "定員を設定する", "event.p.publicevent": "このイベントを公開イベントリストに表示", "event.p.timezone": "タイムゾーン", "event.partof": "{{eventData.eventGroup.name}} グループのイベント", @@ -95,14 +98,20 @@ "event.share": "イベントを共有するには、このメッセージのすぐ上に表示しているリンクをご利用ください。参加者にはイベントを編集したり削除したりすることはできません。", "event.showonGM": "Google マップで表示", "event.showonOM": "OpenStreetMap で表示", - "event.started": "開始済み", + "event.started": "開催中", "event.welcome": "あなたが作成したイベントです。ようこそ!", "eventgroups": "イベントグループ", "eventpwd": "イベントパスワード", "fixerrors": "エラーを修正してください :", "forgotpwd": "パスワードがわからない?", + "frontend.dateformat": "LL (dd)", + "frontend.displaydate-days": "{{ startdate }} {{ starttime }} - {{ enddate }} {{ endtime }} {{ timezone }}", + "frontend.displaydate-sameday": "{{ startdate }} {{ starttime }} {{ endtime }}{{ timezone}}", "frontend.elnumber": "( {{count}} 人 )", "frontend.eventattendees": "人で", + "frontend.publicevents": "公開イベント", + "frontend.sameday.to": " ", + "frontend.timeformat": "LT", "group.about": "このグループについて", "group.addevent": "このグループにイベントをリンクするには、新しくイベントを作る際に、もしくは既存のイベントを編集して、以下の 2 つのコードをコピー・貼り付けします。", "group.del": "このイベントグループを削除", @@ -140,7 +149,7 @@ "home.fedtitle": "連合プロトコルとセルフホスト", "home.flagshipsetting": "Gathio のフラッグシップインスタンスは gath.io です。終わり次第順次削除されるイベント、URL を知っている人にしか開けないイベントを、だれでも作成できるよう設計しています。\nもう一度言います、ここではだれでもイベントを作成できます。イベントがパブリックな場所に公開されることはありません。そしてイベント終了の 7 日後に削除します。", "home.imgexample": "ピクニックに行くイベントページの例です。イベントの場所、主催、日時と説明を記載しています。また Google カレンダーに保存、エクスポート、場所を OpenStreetMap と Google マップから開くこともできます。", - "home.intro": "Gathio は、簡単、プライバシー・ファーストでイベントを作成・共有するシステムです。連合プロトコルにも対応しています。", + "home.intro": "Gathio は、簡単、プライバシー・ファーストで、イベントを作成・共有するシステムです。連合プロトコルにも対応しています。", "home.kofi": "Ko-fi で支援を", "home.kofidesc": "gathio 、よく使ってるし便利だよね…と思ったら、コーヒー 1 杯分を出してくれませんか? かならずサイトの運営に役立てます! ", "home.onpre": "あなたのコミュニティーで自分たちの Gathio インスタンスを建てるなら、そこではイベントの作成を特定の人しかできないようにしたり、ホームページに便利なイベント一覧を表示したり、イベント削除を一切しない…といった制限・設定を加えることもできます。", @@ -157,6 +166,7 @@ "interaction": "ユーザーにコメントを許可する", "join": "ユーザーは自分で参加登録する", "joinemaildesc": "メールアドレスを入力しておくと、このイベントについての情報を送信します。", + "magiclink-invalid": "このマジックリンクは無効、または期限が切れています。再度リクエストしてください。", "main.defaultmetadata": "より簡単に、より速く、よりプライバシー侵害の小さい、イベントを作成・共有する方法", "main.footnote": "Gathio {{version}} バージョン · GitHub · Raphael協力者たち を込めて作成しています。", "mdsupport": "Markdown 書式対応", @@ -195,5 +205,6 @@ "snappy": "ズバッと。", "upcomingevents": "今後のイベント", "wontshow": "どこにも表示しません ( 任意 )。", + "year-month-format": "YYYY年MMM", "youremail": "あなたのメールアドレス" -} +} \ No newline at end of file diff --git a/src/lib/event.ts b/src/lib/event.ts index 334ddf6..09631b9 100644 --- a/src/lib/event.ts +++ b/src/lib/event.ts @@ -1,3 +1,4 @@ +import i18next from "i18next"; import { IEventGroup } from "../models/EventGroup.js"; export interface EventListEvent { @@ -15,7 +16,8 @@ export const bucketEventsByMonth = ( acc: Record[], event: EventListEvent, ) => { - const month = event.startMoment.format("MMMM YYYY"); + event.startMoment.locale(i18next.language); + const month = event.startMoment.format(i18next.t("year-month-format" )); const matchingBucket = acc.find((bucket) => bucket.title === month); if (!matchingBucket) { acc.push({ diff --git a/src/routes/frontend.ts b/src/routes/frontend.ts index 40b5393..6f9e00a 100644 --- a/src/routes/frontend.ts +++ b/src/routes/frontend.ts @@ -71,7 +71,7 @@ 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("magiclink-invalid"), }, }); } @@ -92,6 +92,7 @@ router.get("/events", async (_: Request, res: Response) => { .lean() .sort("start"); const updatedEvents: EventListEvent[] = events.map((event) => { + moment.locale(i18next.language); const startMoment = moment.tz(event.start, event.timezone); const endMoment = moment.tz(event.end, event.timezone); const isSameDay = startMoment.isSame(endMoment, "day"); @@ -101,9 +102,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, @@ -133,7 +134,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, @@ -155,31 +156,57 @@ router.get("/:eventID", async (req: Request, res: Response) => { } const parsedLocation = event.location.replace(/\s+/g, "+"); let displayDate; + moment.locale(i18next.language); + 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 [from] h:mm a', - ) + - moment - .tz(event.end, event.timezone) - .format( - ' [to] h:mm a [](z)[]', - ); + 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: + i18next.t('frontend.sameday.timezone', + { tz: + moment + .tz(event.end, event.timezone) + .format('(z)',) + } ) + }); } else { - displayDate = - moment - .tz(event.start, event.timezone) - .format( - 'dddd D MMMM YYYY [at] h:mm a', - ) + - moment - .tz(event.end, event.timezone) - .format( - ' [] dddd D MMMM YYYY [at] h:mm a [](z)[]', - ); + 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(); @@ -430,8 +457,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 { @@ -439,10 +466,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), ), diff --git a/views/event.handlebars b/views/event.handlebars index 009dfbd..1307983 100755 --- a/views/event.handlebars +++ b/views/event.handlebars @@ -285,9 +285,9 @@
{{t "event.discussion" }}
- +
- +
-- cgit v1.2.3 From 73e8b168c3ffc4e3ffe30e50dd3e46ed70d909d8 Mon Sep 17 00:00:00 2001 From: INOUE Daisuke Date: Sat, 22 Mar 2025 22:55:46 +0900 Subject: some fix, moment.locale setting --- locales/en-US.json | 6 +++--- locales/en.json | 6 +++--- locales/ja.json | 4 ++-- package.json | 1 + pnpm-lock.yaml | 3 +++ src/app.ts | 5 +++++ src/routes/frontend.ts | 6 ++---- views/partials/eventGroupForm.handlebars | 2 +- 8 files changed, 20 insertions(+), 13 deletions(-) (limited to 'src/routes') diff --git a/locales/en-US.json b/locales/en-US.json index d397809..b15933f 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -84,7 +84,6 @@ "event.remaining_one": "{{count}} spot remaining - add yourself now!", "event.remaining_other": "{{count}} spots remaining - add yourself now!", "event.remaining_zero": "This event is at capacity.", - "event.remove-attendee": "Remove {{ attendeeName }} from {{eventData.name}}", "event.removeAttendee": "Remove attendee", "event.removeattendeedesc": "Remove attendee from '{{eventData.name}}'", "event.removeme": "Remove me", @@ -109,8 +108,8 @@ "frontend.displaydate-sameday": "{{ startdate }} from {{ starttime }} to {{ endtime }}{{ timezone}}", "frontend.elnumber": "({{count}} people)", "frontend.eventattendees": "people", + "frontend.newevent": "New event", "frontend.publicevents": "Public events", - "frontend.sameday.to": " to ", "frontend.timeformat": "LT", "group.about": "About", "group.addevent": "To link an existing event to this group, copy and paste the two codes below into the 'Event Group' box when creating a new event or editing an existing event.", @@ -124,6 +123,7 @@ "group.feedlinkdesc": "Paste this URL into your calendar app\nto subscribe to a live feed of events from this group.", "group.hostedby": "Hosted by {{eventGroupData.hostName}}", "group.ICSexport": "Export as ICS", + "group.options": "Options", "group.p.creatoremail": "Your email", "group.p.del": "Delete this event group", "group.p.delbutton": "Delete event group", @@ -141,7 +141,7 @@ "group.subscribedesc": "Enter your email address (optional) to receive\nupdates\nwhenever a new event is created in this group.", "group.subscribetitle": "Subscribe to updates", "group.welcome": "Welcome to your event group! We've just sent you an email with your secret editing link, which you can also see in the address bar above. Haven't got the email? Check your spam or junk folder. To share your event group, use the link you can see just below this message - that way your attendees won't be able to edit or delete your event group!", - "home.about": "About", + "home.about": "About {{ sn }}", "home.aboutgathio": "About Gathio", "home.attention": "But remember: all events are visible to anyone who knows the link, so probably don't use Gathio to plot your surprise birthday party or revolution. Or whatever, you do you.", "home.autodelete": "If this instance automatically deletes its events, sometime after the event finishes, it's deleted from the database for ever, and your data goes with it.", diff --git a/locales/en.json b/locales/en.json index d397809..b15933f 100644 --- a/locales/en.json +++ b/locales/en.json @@ -84,7 +84,6 @@ "event.remaining_one": "{{count}} spot remaining - add yourself now!", "event.remaining_other": "{{count}} spots remaining - add yourself now!", "event.remaining_zero": "This event is at capacity.", - "event.remove-attendee": "Remove {{ attendeeName }} from {{eventData.name}}", "event.removeAttendee": "Remove attendee", "event.removeattendeedesc": "Remove attendee from '{{eventData.name}}'", "event.removeme": "Remove me", @@ -109,8 +108,8 @@ "frontend.displaydate-sameday": "{{ startdate }} from {{ starttime }} to {{ endtime }}{{ timezone}}", "frontend.elnumber": "({{count}} people)", "frontend.eventattendees": "people", + "frontend.newevent": "New event", "frontend.publicevents": "Public events", - "frontend.sameday.to": " to ", "frontend.timeformat": "LT", "group.about": "About", "group.addevent": "To link an existing event to this group, copy and paste the two codes below into the 'Event Group' box when creating a new event or editing an existing event.", @@ -124,6 +123,7 @@ "group.feedlinkdesc": "Paste this URL into your calendar app\nto subscribe to a live feed of events from this group.", "group.hostedby": "Hosted by {{eventGroupData.hostName}}", "group.ICSexport": "Export as ICS", + "group.options": "Options", "group.p.creatoremail": "Your email", "group.p.del": "Delete this event group", "group.p.delbutton": "Delete event group", @@ -141,7 +141,7 @@ "group.subscribedesc": "Enter your email address (optional) to receive\nupdates\nwhenever a new event is created in this group.", "group.subscribetitle": "Subscribe to updates", "group.welcome": "Welcome to your event group! We've just sent you an email with your secret editing link, which you can also see in the address bar above. Haven't got the email? Check your spam or junk folder. To share your event group, use the link you can see just below this message - that way your attendees won't be able to edit or delete your event group!", - "home.about": "About", + "home.about": "About {{ sn }}", "home.aboutgathio": "About Gathio", "home.attention": "But remember: all events are visible to anyone who knows the link, so probably don't use Gathio to plot your surprise birthday party or revolution. Or whatever, you do you.", "home.autodelete": "If this instance automatically deletes its events, sometime after the event finishes, it's deleted from the database for ever, and your data goes with it.", diff --git a/locales/ja.json b/locales/ja.json index 44c0b63..13b38eb 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -84,7 +84,6 @@ "event.remaining_one": "残り {{count}} 枠 - 参加登録しましょう !", "event.remaining_other": "残り {{count}} 枠 - 参加登録しましょう !", "event.remaining_zero": "このイベントは満員です。", - "event.remove-attendee": "'{{eventData.name}}' から {{ attendeeName }} を削除", "event.removeAttendee": "参加者を削除", "event.removeattendeedesc": "'{{eventData.name}}' から参加者を削除", "event.removeme": "キャンセル ( 辞退 )", @@ -109,8 +108,8 @@ "frontend.displaydate-sameday": "{{ startdate }} {{ starttime }} {{ endtime }}{{ timezone}}", "frontend.elnumber": "( {{count}} 人 )", "frontend.eventattendees": "人で", + "frontend.newevent": "イベントの作成", "frontend.publicevents": "公開イベント", - "frontend.sameday.to": " ", "frontend.timeformat": "LT", "group.about": "このグループについて", "group.addevent": "このグループにイベントをリンクするには、新しくイベントを作る際に、もしくは既存のイベントを編集して、以下の 2 つのコードをコピー・貼り付けします。", @@ -124,6 +123,7 @@ "group.feedlinkdesc": "この URL をカレンダーアプリに登録することで、このグループのイベントスケジュールを購読できます。", "group.hostedby": "主催 : ", "group.ICSexport": "iCalendar ファイル", + "group.options": "オプション項目", "group.p.creatoremail": "あなたのメールアドレス", "group.p.del": "このイベントグループを削除する", "group.p.delbutton": "イベントグループを削除", diff --git a/package.json b/package.json index 0182815..8465506 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "jimp": "^0.16.13", "jsdom": "^22.1.0", "marked": "^12.0.2", + "moment": "^2.30.1", "moment-timezone": "^0.5.45", "mongoose": "^5.13.22", "multer": "1.4.5-lts.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c45ff07..f78966b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -77,6 +77,9 @@ importers: marked: specifier: ^12.0.2 version: 12.0.2 + moment: + specifier: ^2.30.1 + version: 2.30.1 moment-timezone: specifier: ^0.5.45 version: 0.5.45 diff --git a/src/app.ts b/src/app.ts index 9301484..a71bf30 100755 --- a/src/app.ts +++ b/src/app.ts @@ -31,6 +31,7 @@ import { activityPubContentType, alternateActivityPubContentType, } from "./lib/activitypub.js"; +import moment from "moment"; const app = express(); @@ -125,6 +126,10 @@ async function initializeApp() { console.error('handlebars-i18next helper is not properly loaded'); } + i18next.on('languageChanged', function(lng) { + moment.locale(lng); + }); + app.engine("handlebars", hbsInstance.engine); app.set("view engine", "handlebars"); app.set("hbsInstance", hbsInstance); diff --git a/src/routes/frontend.ts b/src/routes/frontend.ts index 6f9e00a..44d3a76 100644 --- a/src/routes/frontend.ts +++ b/src/routes/frontend.ts @@ -50,7 +50,7 @@ router.get("/new", (req: Request, res: Response) => { return res.render("createEventMagicLink", frontendConfig(res)); } return res.render("newevent", { - title: "New event", + title: i18next.t("frontend.newevent"), ...frontendConfig(res), }); }); @@ -76,7 +76,7 @@ router.get("/new/:magicLinkToken", async (req: Request, res: Response) => { }); } res.render("newevent", { - title: "New event", + title: i18next.t("frontend.newevent"), ...frontendConfig(res), magicLinkToken: req.params.magicLinkToken, creatorEmail: magicLink.email, @@ -92,7 +92,6 @@ router.get("/events", async (_: Request, res: Response) => { .lean() .sort("start"); const updatedEvents: EventListEvent[] = events.map((event) => { - moment.locale(i18next.language); const startMoment = moment.tz(event.start, event.timezone); const endMoment = moment.tz(event.end, event.timezone); const isSameDay = startMoment.isSame(endMoment, "day"); @@ -156,7 +155,6 @@ router.get("/:eventID", async (req: Request, res: Response) => { } const parsedLocation = event.location.replace(/\s+/g, "+"); let displayDate; - moment.locale(i18next.language); const dateformat = i18next.t("frontend.dateformat"); const timeformat = i18next.t('frontend.timeformat'); if (moment.tz(event.end, event.timezone).isSame(event.start, "day")) { diff --git a/views/partials/eventGroupForm.handlebars b/views/partials/eventGroupForm.handlebars index 3d13d69..0f30790 100644 --- a/views/partials/eventGroupForm.handlebars +++ b/views/partials/eventGroupForm.handlebars @@ -34,7 +34,7 @@
{{#if showPublicEventList}}
- +