/* The interface language — the thing the settings popup offers, distinct from the language an *article* is written in (see utils/languages.ts). Where the choice lives: a `mathew-locale` cookie, which the server reads so pages render in the right language from the first draw, and — for a signed-in person — the account itself, so the choice follows them across devices. */ export const APP_LANGUAGES = [ { code: 'en', language: 'en-US', name: 'English' }, { code: 'es', language: 'es-ES', name: 'Español' }, { code: 'ca', language: 'ca-ES', name: 'Català' }, { code: 'fr', language: 'fr-FR', name: 'Français' }, { code: 'de', language: 'de-DE', name: 'Deutsch' }, ] as const const SUPPORTED = new Set(APP_LANGUAGES.map((l) => l.code)) function escapeHtml(text: string): string { return text.replace( /[&<>"']/g, (c) => (({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }) as Record)[c]! ) } export function useAppLocale() { const { locale, setLocale, t } = useI18n() /* Translate a message that is drawn with v-html. Every interpolated value is escaped — tags, slugs and usernames wander into these — while the messages themselves are ours and carry their own / markup. */ function th(key: string, params?: Record): string { if (!params) return t(key) const escaped: Record = {} for (const [k, v] of Object.entries(params)) escaped[k] = typeof v === 'string' ? escapeHtml(v) : v return t(key, escaped) } /* Turn the interface to another language. setLocale loads the messages and keeps the detection cookie in step; where the person also has an account, the caller saves it there too (see SettingsModal). */ async function choose(code: string) { if (!SUPPORTED.has(code) || code === locale.value) return await setLocale(code) } /* Follow an account's own choice — at startup or on signing in, where the account outranks whatever this device was showing. */ async function applyAccount(code?: string) { if (!code || !SUPPORTED.has(code) || code === locale.value) return try { await setLocale(code) } catch { /* the device keeps its own language; nothing else about the session depends on this */ } } return { locale, th, choose, applyAccount } }