/** UI localization (en/ru). The engine itself understands both languages at once. */ const dict: Record> = { en: { settings: "Settings", theme: "Theme", system: "System", light: "Light", dark: "Dark", precision: "Decimal places", groupsep: "Thousands separator", language: "Language", hotkey: "Global hotkey", autostart: "Launch at startup", alwaysontop: "Always on top", fontsize: "Font size", extensions: "Extensions folder", done: "Done", newDocument: "New document", untitled: "Untitled", copied: "Copied", ratesUpdated: "Rates updated", ratesOffline: "Offline rates", deleteDoc: "Delete document?", pressKeys: "Press keys…", total: "Total", resultswidth: "Results column", selection: "Selection", rates: "Rates", market: "Market", justNow: "just now", minAgo: "{}m ago", hourAgo: "{}h ago", dayAgo: "{}d ago", refreshRates: "Click to refresh", bindays: "Bin retention (days)", datadir: "Data folder", backups: "Backups", defaultFolder: "Default", folderConflict: "The selected folder already contains Summarum sheets. Use them, or replace with the current ones?", useExisting: "Use existing", replaceMine: "Replace with mine", folderChanged: "Data folder changed", folderError: "Could not change the data folder", hotkeyFailed: "Hotkey is taken by another app", decimalsep: "Decimal separator", exportCopy: "Copy sheet", exportSum: "Save as .sum", exportTxt: "Export as text", exportPrint: "Print / PDF", saved: "Saved", updateAvailable: "Version {} is available. Install and restart now?", updateInstall: "Install", updateLater: "Later", updateInstalling: "Installing update…", updateFailed: "Update failed", searchPlaceholder: "Search all sheets…", searchEmpty: "No matches", closeSheet: "Close this sheet?", close: "Close", cancel: "Cancel", pin: "Pin", unpin: "Unpin", marketUpdated: "Market data updated", exportImage: "Copy as image", imageCopied: "Image copied", imageFailed: "Could not copy image", checkUpdate: "Check for updates", upToDate: "You're on the latest version", updateCheckFailed: "Could not check for updates", autoUpdate: "Automatically check for updates", dateformat: "Date format", sysDefault: "System", tabGeneral: "General", tabFormat: "Format", tabData: "Data", tabUpdates: "Updates", version: "Version", }, ru: { settings: "Настройки", theme: "Тема", system: "Системная", light: "Светлая", dark: "Тёмная", precision: "Знаков после запятой", groupsep: "Разделитель тысяч", language: "Язык", hotkey: "Глобальный хоткей", autostart: "Запуск при старте Windows", alwaysontop: "Поверх всех окон", fontsize: "Размер шрифта", extensions: "Папка расширений", done: "Готово", newDocument: "Новый документ", untitled: "Без названия", copied: "Скопировано", ratesUpdated: "Курсы обновлены", ratesOffline: "Курсы офлайн", deleteDoc: "Удалить документ?", pressKeys: "Нажмите клавиши…", total: "Сумма", resultswidth: "Колонка результатов", selection: "Выделение", rates: "Курсы", market: "Рынок", justNow: "только что", minAgo: "{} мин назад", hourAgo: "{} ч назад", dayAgo: "{} дн назад", refreshRates: "Клик — обновить", bindays: "Корзина (дней)", datadir: "Папка данных", backups: "Бэкапы", defaultFolder: "По умолчанию", folderConflict: "В выбранной папке уже есть листы Summarum. Использовать их или заменить текущими?", useExisting: "Использовать их", replaceMine: "Заменить моими", folderChanged: "Папка данных изменена", folderError: "Не удалось сменить папку данных", hotkeyFailed: "Хоткей занят другой программой", decimalsep: "Десятичный разделитель", exportCopy: "Скопировать лист", exportSum: "Сохранить как .sum", exportTxt: "Экспорт в текст", exportPrint: "Печать / PDF", saved: "Сохранено", updateAvailable: "Доступна версия {}. Установить и перезапустить сейчас?", updateInstall: "Установить", updateLater: "Позже", updateInstalling: "Установка обновления…", updateFailed: "Не удалось обновить", searchPlaceholder: "Поиск по всем листам…", searchEmpty: "Ничего не найдено", closeSheet: "Закрыть этот лист?", close: "Закрыть", cancel: "Отмена", pin: "Закрепить", unpin: "Открепить", marketUpdated: "Рыночные данные обновлены", exportImage: "Скопировать картинкой", imageCopied: "Картинка скопирована", imageFailed: "Не удалось скопировать картинку", checkUpdate: "Проверить обновления", upToDate: "У вас последняя версия", updateCheckFailed: "Не удалось проверить обновления", autoUpdate: "Автоматически проверять обновления", dateformat: "Формат даты", sysDefault: "Системный", tabGeneral: "Общие", tabFormat: "Формат", tabData: "Данные", tabUpdates: "Обновления", version: "Версия", }, }; let lang = "en"; export function setLang(l: string): void { lang = dict[l] ? l : "en"; document.documentElement.lang = lang; for (const el of document.querySelectorAll("[data-i18n]")) { const key = el.dataset.i18n!; el.textContent = t(key); } } export function t(key: string): string { return dict[lang]?.[key] ?? dict.en[key] ?? key; } export function detectLang(): string { return navigator.language?.toLowerCase().startsWith("ru") ? "ru" : "en"; }