Files

230 lines
7.4 KiB
JavaScript
Raw Permalink Normal View History

"use strict";
// Translation dictionary. Add a language by adding a key here and an <option>
// to #lang-select in index.html.
const I18N = {
ru: {
subtitle: "веб-панель управления мостом",
sync_now: "⟳ Синхронизировать",
pause: "Пауза",
resume: "Возобновить",
tab_dashboard: "Дашборд",
tab_feeds: "Фиды",
tab_settings: "Настройки",
// dashboard cards
card_feeds: "Фидов (активно)",
card_topics: "Топиков",
card_sent: "Отправлено всего",
card_history: "В истории",
// status panel
status: "Состояние",
engine: "Движок",
last_sync: "Последняя синхронизация",
next_sync: "Следующая",
interval: "Интервал",
error: "Ошибка",
test_notification: "Тестовое уведомление",
ph_topic: "топик (напр. news)",
ph_message: "сообщение",
send: "Отправить",
// log panel
log: "Журнал",
clear_history: "Очистить историю",
// feeds
feeds: "Фиды",
add_feed: "+ Добавить фид",
import_opml: "Импорт OPML",
export_opml: "Экспорт OPML",
feeds_empty: "Фидов пока нет. Нажмите «Добавить фид».",
no_name: "(без названия)",
priority: "приоритет",
quiet: "тихо",
edit: "Изменить",
delete: "Удалить",
// settings
settings_global: "Глобальные настройки",
s_ntfy_url: "ntfy сервер (URL)",
s_ntfy_token: "ntfy токен (необязательно)",
s_interval: "Интервал синхронизации (сек)",
s_tz: "Часовой пояс (IANA)",
s_batch: "Лимит новых записей за цикл",
s_maxdesc: "Макс. длина описания",
s_ua: "User-Agent",
s_flood: "Флуд-защита (задержки для низкого приоритета)",
save: "Сохранить",
// feed modal
feed_new: "Новый фид",
feed_edit: "Изменить фид",
f_name: "Название",
f_url: "URL фида *",
f_topic: "Топик ntfy *",
f_priority: "Приоритет (15)",
f_icon: "Иконка (URL)",
f_quiet_hours: "Тихие часы (напр. 22-7)",
f_quiet_priority: "Приоритет в тихие часы",
f_include: "Include regex (показывать только совпадения)",
f_exclude: "Exclude regex (отбрасывать совпадения)",
f_enabled: "Включён",
check_feed: "Проверить фид",
// dynamic / toasts
sync_started: "Синхронизация запущена",
history_cleared: "История очищена",
need_topic: "Укажите топик",
notify_sent: "Уведомление отправлено",
saved: "Сохранено",
feed_deleted: "Фид удалён",
feed_saved: "Фид сохранён",
confirm_delete_feed: "Удалить этот фид?",
confirm_clear_history: "Очистить историю отправленных записей? Старые записи могут прийти повторно.",
checking: "Проверяю…",
need_url: "Укажите URL",
preview_ok: "OK:",
preview_entries: "записей:",
err_prefix: "Ошибка: ",
no_connection: "нет связи",
st_syncing: "синхронизация…",
st_running: "работает",
st_paused: "на паузе",
pill_syncing: "● синхронизация",
pill_running: "● работает",
pill_paused: "‖ пауза",
sec: "сек",
err_suffix_sync_failed: " (ошибка)",
import_done: "Импорт OPML: добавлено {n} из {total}",
import_choose: "Выберите .opml файл",
},
en: {
subtitle: "web control panel for the bridge",
sync_now: "⟳ Sync now",
pause: "Pause",
resume: "Resume",
tab_dashboard: "Dashboard",
tab_feeds: "Feeds",
tab_settings: "Settings",
card_feeds: "Feeds (active)",
card_topics: "Topics",
card_sent: "Sent total",
card_history: "In history",
status: "Status",
engine: "Engine",
last_sync: "Last sync",
next_sync: "Next",
interval: "Interval",
error: "Error",
test_notification: "Test notification",
ph_topic: "topic (e.g. news)",
ph_message: "message",
send: "Send",
log: "Log",
clear_history: "Clear history",
feeds: "Feeds",
add_feed: "+ Add feed",
import_opml: "Import OPML",
export_opml: "Export OPML",
feeds_empty: "No feeds yet. Click \"Add feed\".",
no_name: "(no name)",
priority: "priority",
quiet: "quiet",
edit: "Edit",
delete: "Delete",
settings_global: "Global settings",
s_ntfy_url: "ntfy server (URL)",
s_ntfy_token: "ntfy token (optional)",
s_interval: "Sync interval (sec)",
s_tz: "Timezone (IANA)",
s_batch: "New items per cycle limit",
s_maxdesc: "Max description length",
s_ua: "User-Agent",
s_flood: "Flood protection (delay low-priority items)",
save: "Save",
feed_new: "New feed",
feed_edit: "Edit feed",
f_name: "Name",
f_url: "Feed URL *",
f_topic: "ntfy topic *",
f_priority: "Priority (15)",
f_icon: "Icon (URL)",
f_quiet_hours: "Quiet hours (e.g. 22-7)",
f_quiet_priority: "Priority during quiet hours",
f_include: "Include regex (only matching items)",
f_exclude: "Exclude regex (drop matching items)",
f_enabled: "Enabled",
check_feed: "Check feed",
sync_started: "Sync started",
history_cleared: "History cleared",
need_topic: "Enter a topic",
notify_sent: "Notification sent",
saved: "Saved",
feed_deleted: "Feed deleted",
feed_saved: "Feed saved",
confirm_delete_feed: "Delete this feed?",
confirm_clear_history: "Clear the history of sent items? Old items may be delivered again.",
checking: "Checking…",
need_url: "Enter a URL",
preview_ok: "OK:",
preview_entries: "items:",
err_prefix: "Error: ",
no_connection: "no connection",
st_syncing: "syncing…",
st_running: "running",
st_paused: "paused",
pill_syncing: "● syncing",
pill_running: "● running",
pill_paused: "‖ paused",
sec: "sec",
err_suffix_sync_failed: " (error)",
import_done: "OPML import: added {n} of {total}",
import_choose: "Choose an .opml file",
},
};
let LANG = localStorage.getItem("lang") || "ru";
function t(key) {
const dict = I18N[LANG] || I18N.ru;
return (key in dict) ? dict[key] : (I18N.ru[key] || key);
}
function locale() {
return LANG === "ru" ? "ru-RU" : "en-US";
}
function applyI18n() {
document.documentElement.lang = LANG;
document.querySelectorAll("[data-i18n]").forEach((el) => {
el.textContent = t(el.dataset.i18n);
});
document.querySelectorAll("[data-i18n-ph]").forEach((el) => {
el.placeholder = t(el.dataset.i18nPh);
});
document.querySelectorAll("[data-i18n-title]").forEach((el) => {
el.title = t(el.dataset.i18nTitle);
});
const sel = document.getElementById("lang-select");
if (sel) sel.value = LANG;
}
function setLang(lang) {
LANG = lang;
localStorage.setItem("lang", lang);
applyI18n();
}
// DOM is fully parsed (scripts sit at the end of <body>).
applyI18n();