// Strings, loaded once from the flat dictionary scripts/build-locale.mjs // generates from locales/en-US/main.ftl. No Fluent parser ships here — the // build step already resolved the source file's syntax down to plain // `{ $var }` placeholders, which is all this needs to substitute. let messages = null; export async function loadLocale() { const response = await fetch("locales/en-US.json"); messages = await response.json(); } // Falls back to the id itself on a miss, so a typo'd or forgotten call // shows up as visibly wrong text in the UI rather than disappearing. export function t(id, args = {}) { const value = messages?.[id]; if (value === undefined) return id; return value.replace(/\{\s*\$(\w+)\s*\}/g, (_, name) => args[name] ?? ""); } // index.html's static markup keeps its literal English text and gains // data-l10n-* attributes alongside it, so the page still reads correctly // even if this runs late — this pass just overwrites it from the same // English source, proving the wiring for whenever a second locale exists. export function applyStaticLocale(root = document) { for (const el of root.querySelectorAll("[data-l10n-id]")) el.textContent = t(el.dataset.l10nId); for (const el of root.querySelectorAll("[data-l10n-placeholder]")) el.placeholder = t(el.dataset.l10nPlaceholder); for (const el of root.querySelectorAll("[data-l10n-title]")) el.title = t(el.dataset.l10nTitle); for (const el of root.querySelectorAll("[data-l10n-aria-label]")) el.setAttribute("aria-label", t(el.dataset.l10nAriaLabel)); }