/** * Vue i18n - dùng messages từ server (window.__I18N__). */ declare global { interface Window { __I18N__?: { locale: string; messages: Record }; } } function getNested(obj: Record, path: string): unknown { return path.split('.').reduce((o: unknown, k) => { if (o && typeof o === 'object' && k in o) return (o as Record)[k]; return undefined; }, obj); } export function createT(messages: Record): (key: string, opts?: Record) => string { return (key: string, opts?: Record) => { let val = getNested(messages, key); if (typeof val !== 'string') val = key; let s = String(val); if (opts) { Object.entries(opts).forEach(([k, v]) => { s = s.replace(new RegExp(`{{${k}}}`, 'g'), String(v)); }); } return s; }; } export function getI18n() { const data = window.__I18N__ || { locale: "vi", messages: {} }; return { locale: data.locale, messages: data.messages as Record, t: createT(data.messages as Record), }; } /** Giữ `?locale=` giống server (res.locals.withLocale). */ export function withLocalePath(href: string, locale?: string): string { const loc = locale ?? (typeof window !== "undefined" ? window.__I18N__?.locale : undefined) ?? "vi"; if (!href || href.startsWith("#")) return href; try { const u = new URL(href, "http://_"); u.searchParams.set("locale", loc); return u.pathname + u.search + u.hash; } catch { const sep = href.includes("?") ? "&" : "?"; return `${href}${sep}locale=${encodeURIComponent(loc)}`; } }