import sharedLang from "~/assets/langs/shared.js" /** * Server-side access to the shared translation bundles keyed by the language of a * RECORD (typically `c_bpartner.AD_Language`, iDempiere format `de_DE`) instead of * the logged-in user's UI language. Used wherever text is persisted onto a document * the partner will read (order/line descriptions, invoice period-of-performance, …). */ export const MONTH_KEYS = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'] const DEFAULT_LANG = 'en-US' // Regional variants without their own bundle (de_CH, en_GB, es_MX, …) → base-language bundle const BUNDLE_BY_BASE: Record = { de: 'de-DE', en: 'en-US', es: 'es-ES', ne: 'ne-NP' } /** * Normalises a language value to a sharedLang bundle key, or null when nothing matches. * Accepts iDempiere codes (`de_DE`), browser codes (`de-DE`) and the expanded REST * object form (`{ id: 'de_DE', identifier: 'German (Germany)' }`). */ export const toBundleKey = (code: any): string | null => { const raw = code !== null && typeof code === 'object' ? (code.id ?? code.AD_Language ?? '') : code const normalized = String(raw ?? '').trim().replace('_', '-') if (!normalized) return null if (sharedLang(normalized)) return normalized const base = normalized.split('-')[0].toLowerCase() const byBase = BUNDLE_BY_BASE[base] return byBase && sharedLang(byBase) ? byBase : null } /** Translation bundle of the first resolvable code in `codes`, falling back to en-US. */ export const resolveLangBundle = (...codes: any[]): Record => { for (const code of codes) { const key = toBundleKey(code) if (key) return sharedLang(key) } return sharedLang(DEFAULT_LANG) } /** The logged-in user's language (`logship_language` cookie, iDempiere format e.g. `de_DE`). */ export const sessionLanguage = (event: any): string => getCookie(event, 'logship_language') || getCookie(event, 'language') || DEFAULT_LANG /** * `YYYY-MM-DD` of the last day of `month` (1-12), built from local date parts. * NB `new Date(y, m, 0).toISOString()` shifts to the PREVIOUS day on any host east of UTC * (Europe/Berlin: 31 Aug 00:00 local → "2026-08-30T22:00Z"), which is how prod orders ended * up with PeriodPerformanceDate 2026-08-30 for August. */ export const lastDayOfMonthIso = (year: number, month: number): string => { const day = new Date(year, month, 0).getDate() return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}` }