From 1d58b285dec62f7af2cf16f8b777c2de920b74b0 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 16 May 2025 19:09:54 +0300 Subject: [PATCH] fix(server): week notes broken due to misuse of transactions --- apps/server/src/services/date_notes.ts | 51 +++++++++----------------- apps/server/src/services/i18n.ts | 25 ++++++++++++- 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/apps/server/src/services/date_notes.ts b/apps/server/src/services/date_notes.ts index ee88702ab..764c33700 100644 --- a/apps/server/src/services/date_notes.ts +++ b/apps/server/src/services/date_notes.ts @@ -6,7 +6,6 @@ import attributeService from "./attributes.js"; import cloningService from "./cloning.js"; import dayjs from "dayjs"; import hoistedNoteService from "./hoisted_note.js"; -import i18next from "i18next"; import isSameOrAfter from "dayjs/plugin/isSameOrAfter.js"; import noteService from "./notes.js"; import optionService from "./options.js"; @@ -16,6 +15,7 @@ import searchContext from "../services/search/search_context.js"; import searchService from "../services/search/services/search.js"; import sql from "./sql.js"; import { t } from "i18next"; +import { ordinal } from "./i18n.js"; dayjs.extend(isSameOrAfter); dayjs.extend(quarterOfYear); @@ -67,24 +67,7 @@ function getTimeUnitReplacements(timeUnit: TimeUnit): string[] { return units.slice(0, index + 1).flatMap(unit => baseReplacements[unit]); } -async function ordinal(date: Dayjs, lng: string) { - const localeMap: Record = { - cn: "zh-cn", - tw: "zh-tw" - }; - - const dayjsLocale = localeMap[lng] || lng; - - try { - await import(`dayjs/locale/${dayjsLocale}.js`); - } catch (err) { - console.warn(`Could not load locale ${dayjsLocale}`, err); - } - - return dayjs(date).locale(dayjsLocale).format("Do"); -} - -async function getJournalNoteTitle( +function getJournalNoteTitle( rootNote: BNote, timeUnit: TimeUnit, dateObj: Dayjs, @@ -102,7 +85,7 @@ async function getJournalNoteTitle( const monthName = t(MONTH_TRANSLATION_IDS[dateObj.month()]); const weekDay = t(WEEKDAY_TRANSLATION_IDS[dateObj.day()]); const numberStr = number.toString(); - const ordinalStr = await ordinal(dateObj, i18next.language); + const ordinalStr = ordinal(dateObj); const allReplacements: Record = { // Common date formats @@ -228,7 +211,7 @@ function getQuarterNumberStr(date: Dayjs) { return `${date.year()}-Q${date.quarter()}`; } -async function getQuarterNote(quarterStr: string, _rootNote: BNote | null = null): Promise { +function getQuarterNote(quarterStr: string, _rootNote: BNote | null = null): BNote { const rootNote = _rootNote || getRootCalendarNote(); quarterStr = quarterStr.trim().substring(0, 7); @@ -247,7 +230,7 @@ async function getQuarterNote(quarterStr: string, _rootNote: BNote | null = null const quarterStartDate = dayjs().year(parseInt(yearStr)).month(firstMonth).date(1); const yearNote = getYearNote(yearStr, rootNote); - const noteTitle = await getJournalNoteTitle( + const noteTitle = getJournalNoteTitle( rootNote, "quarter", quarterStartDate, quarterNumber ); @@ -269,7 +252,7 @@ async function getQuarterNote(quarterStr: string, _rootNote: BNote | null = null return quarterNote as unknown as BNote; } -async function getMonthNote(dateStr: string, _rootNote: BNote | null = null): Promise { +function getMonthNote(dateStr: string, _rootNote: BNote | null = null): BNote { const rootNote = _rootNote || getRootCalendarNote(); const monthStr = dateStr.substring(0, 7); @@ -286,12 +269,12 @@ async function getMonthNote(dateStr: string, _rootNote: BNote | null = null): Pr let monthParentNote; if (rootNote.hasLabel("enableQuarterNote")) { - monthParentNote = await getQuarterNote(getQuarterNumberStr(dayjs(dateStr)), rootNote); + monthParentNote = getQuarterNote(getQuarterNumberStr(dayjs(dateStr)), rootNote); } else { monthParentNote = getYearNote(dateStr, rootNote); } - const noteTitle = await getJournalNoteTitle( + const noteTitle = getJournalNoteTitle( rootNote, "month", dayjs(dateStr), parseInt(monthNumber) ); @@ -408,7 +391,7 @@ function getWeekFirstDayNote(dateStr: string, rootNote: BNote | null = null) { * @param _rootNote a {@link BNote} representing the calendar root, or {@code null} or not specified to use the default root calendar note. * @returns a Promise that resolves to the {@link BNote} corresponding to the week note. */ -async function getWeekNote(weekStr: string, _rootNote: BNote | null = null): Promise { +function getWeekNote(weekStr: string, _rootNote: BNote | null = null): BNote | null { const rootNote = _rootNote || getRootCalendarNote(); if (!rootNote.hasLabel("enableWeekNote")) { return null; @@ -435,10 +418,10 @@ async function getWeekNote(weekStr: string, _rootNote: BNote | null = null): Pro const startMonth = startDate.month(); const endMonth = endDate.month(); - const monthNote = await getMonthNote(startDate.format("YYYY-MM-DD"), rootNote); - const noteTitle = await getJournalNoteTitle(rootNote, "week", startDate, weekNumber); + const monthNote = getMonthNote(startDate.format("YYYY-MM-DD"), rootNote); + const noteTitle = getJournalNoteTitle(rootNote, "week", startDate, weekNumber); - sql.transactional(async () => { + sql.transactional(() => { weekNote = createNote(monthNote, noteTitle); attributeService.createLabel(weekNote.noteId, WEEK_LABEL, weekStr); @@ -452,7 +435,7 @@ async function getWeekNote(weekStr: string, _rootNote: BNote | null = null): Pro // If the week spans different months, clone the week note in the other month as well if (startMonth !== endMonth) { - const secondMonthNote = await getMonthNote(endDate.format("YYYY-MM-DD"), rootNote); + const secondMonthNote = getMonthNote(endDate.format("YYYY-MM-DD"), rootNote); cloningService.cloneNoteToParentNote(weekNote.noteId, secondMonthNote.noteId); } }); @@ -460,7 +443,7 @@ async function getWeekNote(weekStr: string, _rootNote: BNote | null = null): Pro return weekNote as unknown as BNote; } -async function getDayNote(dateStr: string, _rootNote: BNote | null = null): Promise { +function getDayNote(dateStr: string, _rootNote: BNote | null = null): BNote { const rootNote = _rootNote || getRootCalendarNote(); dateStr = dateStr.trim().substring(0, 10); @@ -476,13 +459,13 @@ async function getDayNote(dateStr: string, _rootNote: BNote | null = null): Prom let dateParentNote; if (rootNote.hasLabel("enableWeekNote")) { - dateParentNote = await getWeekNote(getWeekNumberStr(dayjs(dateStr)), rootNote); + dateParentNote = getWeekNote(getWeekNumberStr(dayjs(dateStr)), rootNote); } else { - dateParentNote = await getMonthNote(dateStr, rootNote); + dateParentNote = getMonthNote(dateStr, rootNote); } const dayNumber = dateStr.substring(8, 10); - const noteTitle = await getJournalNoteTitle( + const noteTitle = getJournalNoteTitle( rootNote, "day", dayjs(dateStr), parseInt(dayNumber) ); diff --git a/apps/server/src/services/i18n.ts b/apps/server/src/services/i18n.ts index a14385ab6..7630fbad4 100644 --- a/apps/server/src/services/i18n.ts +++ b/apps/server/src/services/i18n.ts @@ -5,20 +5,43 @@ import { join } from "path"; import { getResourceDir } from "./utils.js"; import hidden_subtree from "./hidden_subtree.js"; import { LOCALES, type Locale } from "@triliumnext/commons"; +import dayjs, { Dayjs } from "dayjs"; + +const DAYJS_LOCALE_MAP: Record = { + cn: "zh-cn", + tw: "zh-tw" +}; + +let dayjsLocale: string; export async function initializeTranslations() { const resourceDir = getResourceDir(); const Backend = (await import("i18next-fs-backend")).default; + const locale = getCurrentLanguage(); // Initialize translations await i18next.use(Backend).init({ - lng: getCurrentLanguage(), + lng: locale, fallbackLng: "en", ns: "server", backend: { loadPath: join(resourceDir, "assets/translations/{{lng}}/{{ns}}.json") } }); + + // Initialize dayjs locale. + dayjsLocale = DAYJS_LOCALE_MAP[locale] ?? locale; + try { + await import(`dayjs/locale/${dayjsLocale}.js`); + } catch (err) { + console.warn(`Could not load locale ${dayjsLocale}`, err); + } +} + +export function ordinal(date: Dayjs) { + return dayjs(date) + .locale(dayjsLocale) + .format("Do"); } export function getLocales(): Locale[] {