/** * Per-locale formatters used in PDF rendering. We pin these to specific * locales (de-AT for German invoices) so that the output is deterministic * regardless of the runtime's default locale. */ const MONEY_FORMATTERS = new Map(); const QTY_FORMATTERS = new Map(); const DATE_FORMATTERS = new Map(); function localeFor(language: string): string { return language === "en" ? "en-GB" : "de-AT"; } export function formatMoney( amount: number | string, currency: string, language: string, ): string { const num = typeof amount === "string" ? Number(amount) : amount; const key = `${language}|${currency}`; let f = MONEY_FORMATTERS.get(key); if (!f) { f = new Intl.NumberFormat(localeFor(language), { style: "decimal", minimumFractionDigits: 2, maximumFractionDigits: 2, }); MONEY_FORMATTERS.set(key, f); } return `${f.format(Number.isFinite(num) ? num : 0)} ${currency}`; } export function formatQuantity(qty: number, unit: string, language: string): string { let f = QTY_FORMATTERS.get(language); if (!f) { f = new Intl.NumberFormat(localeFor(language), { minimumFractionDigits: 2, maximumFractionDigits: 2, }); QTY_FORMATTERS.set(language, f); } return `${f.format(qty)} ${unit}`; } export function formatDate(date: Date | string, language: string): string { const d = typeof date === "string" ? new Date(date) : date; let f = DATE_FORMATTERS.get(language); if (!f) { f = new Intl.DateTimeFormat(localeFor(language), { day: "2-digit", month: "2-digit", year: "numeric", }); DATE_FORMATTERS.set(language, f); } return f.format(d); } /** Adds days to a date, returning a new Date. */ export function addDays(date: Date, days: number): Date { const d = new Date(date); d.setDate(d.getDate() + days); return d; } /** * Formats a percentage. Tax rates from Shopify can be either 0.20 or 20 — we * accept both shapes via heuristics. */ export function formatTaxRate(rate: number, language: string): string { const pct = rate <= 1 ? rate * 100 : rate; const f = new Intl.NumberFormat(localeFor(language), { minimumFractionDigits: 0, maximumFractionDigits: 2, }); return `${f.format(pct)}%`; }