diff --git a/pytorrent/db.py b/pytorrent/db.py index 131255a..de452ac 100644 --- a/pytorrent/db.py +++ b/pytorrent/db.py @@ -52,6 +52,7 @@ CREATE TABLE IF NOT EXISTS user_preferences ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, theme TEXT DEFAULT 'dark', + language TEXT DEFAULT 'en_US', bootstrap_theme TEXT DEFAULT 'default', font_family TEXT DEFAULT 'default', active_rtorrent_id INTEGER, @@ -523,6 +524,7 @@ MIGRATIONS = [ "ALTER TABLE users ADD COLUMN is_active INTEGER DEFAULT 1", "ALTER TABLE users ADD COLUMN updated_at TEXT", "ALTER TABLE user_preferences ADD COLUMN mobile_mode INTEGER DEFAULT 0", + "ALTER TABLE user_preferences ADD COLUMN language TEXT DEFAULT 'en_US'", "ALTER TABLE user_preferences ADD COLUMN compact_torrent_list_enabled INTEGER DEFAULT 0", "ALTER TABLE user_preferences ADD COLUMN bootstrap_theme TEXT DEFAULT 'default'", "ALTER TABLE user_preferences ADD COLUMN font_family TEXT DEFAULT 'default'", @@ -770,7 +772,7 @@ def init_db(): pref = conn.execute("SELECT id FROM user_preferences WHERE user_id=1").fetchone() if not pref: conn.execute( - "INSERT INTO user_preferences(user_id, theme, created_at, updated_at) VALUES(1, 'dark', ?, ?)", + "INSERT INTO user_preferences(user_id, theme, language, created_at, updated_at) VALUES(1, 'dark', 'en_US', ?, ?)", (now, now), ) try: diff --git a/pytorrent/routes/main.py b/pytorrent/routes/main.py index a2b694e..8747316 100644 --- a/pytorrent/routes/main.py +++ b/pytorrent/routes/main.py @@ -8,7 +8,7 @@ import threading import zipfile from flask import Blueprint, render_template, Response, request, redirect, url_for, abort, send_file, stream_with_context -from ..services.preferences import get_preferences, list_profiles, active_profile, get_profile, BOOTSTRAP_THEMES, FONT_FAMILIES +from ..services.preferences import get_preferences, list_profiles, active_profile, get_profile, BOOTSTRAP_THEMES, FONT_FAMILIES, SUPPORTED_LANGUAGES from ..services import auth, pdf_preview_links, rtorrent from ..config import PYTORRENT_TMP_DIR from ..services.frontend_assets import asset_path @@ -214,6 +214,7 @@ def index(): active_profile=active_profile(), bootstrap_themes=BOOTSTRAP_THEMES, font_families=FONT_FAMILIES, + supported_languages=SUPPORTED_LANGUAGES, auth_enabled=auth.enabled(), auth_provider=auth.provider(), external_auth=auth.uses_external_provider(), diff --git a/pytorrent/services/preferences.py b/pytorrent/services/preferences.py index 6fd9944..6104075 100644 --- a/pytorrent/services/preferences.py +++ b/pytorrent/services/preferences.py @@ -28,6 +28,18 @@ FONT_FAMILIES = { "adwaita-mono": "Adwaita Mono", } +SUPPORTED_LANGUAGES = { + "en_US": {"label": "English", "flag": "us"}, + "pl_PL": {"label": "Polski", "flag": "pl"}, + "de_DE": {"label": "Deutsch", "flag": "de"}, + "nb_NO": {"label": "Norsk bokmål", "flag": "no"}, + "ru_RU": {"label": "Русский", "flag": "ru"}, + "fr_FR": {"label": "Français", "flag": "fr"}, + "cs_CZ": {"label": "Čeština", "flag": "cz"}, + "es_ES": {"label": "Español", "flag": "es"}, +} + + # Note: Backend owns the recommended torrent table layout so frontend builds do not duplicate presets. RECOMMENDED_TABLE_COLUMNS = { "hidden": ["hash", "priority", "hashing", "active", "message", "complete", "state", "ratio_group"], @@ -445,7 +457,7 @@ def get_preferences(user_id: int | None = None, profile_id: int | None = None): pref = conn.execute("SELECT * FROM user_preferences WHERE user_id=?", (user_id,)).fetchone() if not pref: now = utcnow() - conn.execute("INSERT INTO user_preferences(user_id, theme, created_at, updated_at) VALUES(?, 'dark', ?, ?)", (user_id, now, now)) + conn.execute("INSERT INTO user_preferences(user_id, theme, language, created_at, updated_at) VALUES(?, 'dark', 'en_US', ?, ?)", (user_id, now, now)) pref = conn.execute("SELECT * FROM user_preferences WHERE user_id=?", (user_id,)).fetchone() merged = dict(pref or {}) if profile_id: @@ -457,6 +469,7 @@ def save_preferences(data: dict, user_id: int | None = None): user_id = user_id or auth.current_user_id() or default_user_id() profile_id = _active_profile_id_for_user(user_id) allowed_theme = data.get("theme") if data.get("theme") in {"light", "dark"} else None + language = data.get("language") if data.get("language") in SUPPORTED_LANGUAGES else None bootstrap_theme = data.get("bootstrap_theme") if data.get("bootstrap_theme") in BOOTSTRAP_THEMES else None font_family = data.get("font_family") if data.get("font_family") in FONT_FAMILIES else None footer_items_json = data.get("footer_items_json") @@ -487,6 +500,9 @@ def save_preferences(data: dict, user_id: int | None = None): now = utcnow() if allowed_theme: conn.execute("UPDATE user_preferences SET theme=?, updated_at=? WHERE user_id=?", (allowed_theme, now, user_id)) + if language: + # Note: Language is stored per user so every account keeps its own UI locale across profiles. + conn.execute("UPDATE user_preferences SET language=?, updated_at=? WHERE user_id=?", (language, now, user_id)) if bootstrap_theme: conn.execute("UPDATE user_preferences SET bootstrap_theme=?, updated_at=? WHERE user_id=?", (bootstrap_theme, now, user_id)) if font_family: diff --git a/pytorrent/static/i18n/cs_CZ.json b/pytorrent/static/i18n/cs_CZ.json new file mode 100644 index 0000000..f3911c4 --- /dev/null +++ b/pytorrent/static/i18n/cs_CZ.json @@ -0,0 +1,566 @@ +{ + "meta": { + "locale": "cs_CZ", + "label": "Čeština", + "flag": "cz" + }, + "translations": { + "0_MEANS_ONLY_SEED_THRESHOLD_IS_REQUIRED": "0 means pouze seed threshold je required.", + "0_MEANS_UNLIMITED_SLIDERS_USE_MBIT_S_AND_SAVE_THROUGH_THE_EXISTING_SPEED_LIMITS_": "0 means unlimited. Sliders použít Mbit/s a Uložit through existing Rychlost Limity API.", + "0_SELECTED": "0 vybráno", + "ABOUT_PYTORRENT": "About pyTorrent", + "ACTION": "Akce", + "ACTIVE": "Aktivní", + "ACTIVE_RTORRENT_DOWNLOADS_MAX_GLOBAL_DOWNLOADS": "Aktivní rTorrent Stahování / max global Stahování", + "ACTIVE_RTORRENT_UPLOADS_MAX_GLOBAL_UPLOADS": "Aktivní rTorrent Odesílání / max global Odesílání", + "ADD": "Přidat", + "ADDED": "Added", + "ADDS_REMOVALS_COMPLETIONS_AND_QUEUED_OPERATION_RESULTS": "Adds, removals, completions a queued operation results.", + "ADD_ACTION": "Přidat Akce", + "ADD_CONDITION": "Přidat Podmínka", + "ADD_CREATE_TORRENT": "Přidat / Vytvořit Torrent", + "ADD_FIRST_LABEL_ABOVE": "Přidat První Štítek above.", + "ADD_LABEL": "Přidat Štítek", + "ADD_MAGNET_LINK": "Přidat magnet link", + "ADD_NEW_LABEL": "Přidat Nový Štítek", + "ADD_OR_EDIT_GROUP": "Přidat nebo Upravit Skupina", + "ADD_PATH": "Přidat Cesta", + "ADD_PROFILE": "Přidat Profil", + "ADD_RTORRENT_PROFILE": "Přidat rTorrent Profil", + "ADD_THE_FIRST_RTORRENT_PROFILE_TO_START_LOADING_TORRENTS": "Přidat První rTorrent Profil do Spustit Načítání Torrenty.", + "ADD_TORRENT": "Přidat Torrent", + "ADD_TORRENT_FILE": "Přidat Torrent Soubor", + "ADMIN": "Správce", + "ADMIN_ONLY_FULL_APPLICATION_BACKUP_RESTORE_CAN_REPLACE_USERS_PERMISSIONS_PROFILE": "Správce-pouze full Aplikace záloha. Obnovit může replace Uživatelé, permissions, Profily a global Aplikace Nastavení.", + "AGGREGATE_ALL_PATHS": "Aggregate Vše cesty", + "ALL": "Vše", + "ALL_NON_JOB_TYPES": "Vše non-Úloha types", + "ALL_PROFILES": "Vše Profily", + "ALL_TYPES": "Vše types", + "ANNOUNCE": "Announce", + "API_DOCS": "API docs", + "APPEARANCE": "Vzhled", + "APPEARANCE_PREFERENCES_SAVED": "Vzhled Předvolby Uloženo", + "APPEARS_NEAR_CLICKED_BUTTONS_ONLY_SOMETIMES": "Appears near clicked buttons pouze sometimes.", + "APPLICATION_BACKUP": "Aplikace záloha", + "APPLICATION_BACKUP_NAME": "Aplikace záloha Název", + "APPLY": "Apply", + "APPLY_RETENTION_NOW": "Apply Uchování now", + "APPLY_SAVED_CHANGES_60S_AFTER_PYTORRENT_START": "Apply Uloženo changes 60s po pyTorrent Spustit", + "APP_STATUS": "App Stav", + "AUTHENTICATION_IS_ENABLED_FOR_THIS_PYTORRENT_INSTANCE": "Authentication je Zapnuto pro toto pyTorrent instance.", + "AUTHOR": "Autor", + "AUTOMATIC": "Automaticky", + "AUTOMATIC_KEEPS_THE_CURRENT_POLLER_CADENCE_CUSTOM_RUNS_ONLY_AFTER_THE_SELECTED_N": "Automaticky keeps Aktuální poller cadence. Vlastní runs pouze po vybráno number minut. Off disables refill completely.", + "AUTOMATIC_QUEUE_BALANCING_FOR_SLOW_OR_STALLED_DOWNLOADS": "Automaticky Fronta vyvažování pro pomalé nebo zaseknuté Stahování.", + "AUTOMATIC_RUNS_USE_THE_COOLDOWN_BELOW_MANUAL_CHECK_NOW_STILL_RUNS_IMMEDIATELY": "Automaticky runs použít Prodleva below. Ručně Zkontrolovat now still runs immediately.", + "AUTOMATIONS": "Automations", + "AUTOMATIONS_RULES": "Automations / Pravidla", + "AUTOMATION_TOASTS": "Automation toasts", + "AUTO_STOP_WHEN_IDLE": "Auto-Zastavit when idle", + "BACKEND": "Backend", + "BACKUP": "Záloha", + "BACKUP_RESTORE": "Záloha / Obnovit", + "BACK_TO_DASHBOARD": "Back do dashboard", + "BOOTSTRAP_THEME": "Bootstrap Motiv", + "BROWSER": "Prohlížeč", + "BROWSER_TITLE": "Prohlížeč Název", + "BUILD_A_RULE_AS_CONDITIONS_FIRST_THEN_ORDERED_ACTIONS_MATCHING_TORRENTS_ARE_HAND": "Build Pravidlo jako: Podmínky První, poté ordered Akce. Matching Torrenty jsou handled jako jedna batch a Prodleva je použito do whole Pravidlo.", + "BUSY": "busy", + "BY_DAYS": "Podle dny", + "BY_LINE_COUNT": "Podle line count", + "CACHED_METADATA_SUMMARY_FILE_METADATA_IS_REFRESHED_EVERY_15_MINUTES_A_FEW_MINUTE": "Cached metadata summary. Soubor metadata je refreshed every 15 minut, několik minut po start, nebo manually.", + "CANCEL": "Zrušit", + "CANCEL_EDIT": "Zrušit Upravit", + "CATEGORY": "Kategorie", + "CHANGES_APPLY_IMMEDIATELY_WHERE_POSSIBLE_INITIAL_STARTUP_LOADER_USES_THEM_AFTER_": "Changes apply immediately where possible; initial start loader uses je po reload.", + "CHANGE_RTORRENT": "Změnit rTorrent", + "CHANGE_THEME": "Změnit Motiv", + "CHANGING_RTORRENT_RELOADS_THE_LIVE_TORRENT_SNAPSHOT": "Změna rTorrent reloads live Torrent snímek.", + "CHECKING": "Kontrola", + "CHECK_NOW": "Zkontrolovat nyní", + "CHECK_PORT_NOW": "Zkontrolovat port nyní", + "CHECK_THIS_IF_YOU_WANT_TO_CONNECT_TO_A_REMOTE_RTORRENT_INSTANCE_INSTEAD_OF_LOCAL": "Zkontrolovat toto pokud chcete chcete do připojit do Vzdálené rTorrent instance místo localhost.", + "CHOOSE_COLUMNS_VISIBLE_IN_THE_TORRENT_LIST": "Vybrat Sloupce viditelné v Torrent seznam.", + "CHOOSE_FILES": "Vybrat Soubory", + "CHOOSE_RTORRENT": "Vybrat rTorrent", + "CHOOSE_TORRENTS_IGNORED_BY_SMART_QUEUE_EXISTING_BEHAVIOR_STAYS_UNCHANGED_FOR_ALL": "Vybrat Torrenty ignored podle Smart Queue. Existing behavior stays unchanged pro Vše non-excluded Torrenty.", + "CHOOSE_WHAT_THE_FOOTER_DISK_BAR_SHOULD_REPRESENT_AND_ADD_EXTRA_STORAGE_PATHS": "Vybrat what Patička disk lišta má represent a Přidat extra storage cesty.", + "CHOOSE_WHICH_STATUS_ITEMS_ARE_VISIBLE_IN_THE_BOTTOM_BAR": "Vybrat která Stav items jsou viditelné v bottom lišta.", + "CHUNKS": "Chunks", + "CLEANUP": "Čištění", + "CLEANUP_RETENTION": "Čištění / Uchování", + "CLEAR": "Vymazat", + "CLEAR_CURRENT_FILTER": "Vymazat Aktuální filtr", + "CLEAR_FINISHED": "Vymazat finished", + "CLEAR_LABELS": "Vymazat Štítky", + "CLEAR_SELECTION": "Vymazat selection", + "CLEAR_VISIBLE": "Vymazat viditelné", + "CLOSE": "Zavřít", + "COLUMNS": "Sloupce", + "COLUMNS_SAVED": "Sloupce Uloženo", + "COMMENT": "Comment", + "COMPACT_TORRENT_LIST": "Compact Torrent seznam", + "COMPLETE": "Complete", + "COMPLETED": "Dokončeno", + "CONFIGURED_RTORRENTS": "Configured rTorrents", + "CONNECTING_TO_RTORRENT_AND_PREPARING_DATA": "Connecting do rTorrent a preparing Data.", + "CONNECTION_ADDRESS_IN_SCGI_HOST_PORT_RPC2_FORMAT": "Připojení address v scgi://host:Port/RPC2 format.", + "CONTROLS_THE_DEFAULT_CATEGORY_AND_JOB_LOG_VISIBILITY_USED_BY_THE_LOGS_MODAL": "Controls Výchozí Kategorie a Úloha Log visibility used podle Logy modal.", + "CONTROLS_WHAT_IS_SHOWN_IN_THE_BROWSER_TAB": "Controls what je shown v Prohlížeč karta.", + "COOLDOWN_MINUTES": "Prodleva minut", + "COPY": "Kopírovat", + "COPY_HASH": "Kopírovat Hash", + "COPY_NAME": "Kopírovat Název", + "COPY_PATH": "Kopírovat Cesta", + "CPU_RAM_USAGE": "CPU / RAM usage", + "CREATE": "Vytvořit", + "CREATES_AND_RESTORES_SETTINGS_FOR_THE_CURRENTLY_SELECTED_PROFILE_USER_SCOPED_PRE": "Creates a restores Nastavení pro aktuálně vybráno Profil. Uživatel-scoped Předvolby jsou remapped do Aktuální Uživatel where needed.", + "CREATE_APPLICATION_BACKUP": "Vytvořit Aplikace záloha", + "CREATE_ONE_RTORRENT_PROFILE_AT_A_TIME_MOVE_REMOVE_QUEUES_KEEP_THEIR_ORDER_FOR_EA": "Vytvořit jedna rTorrent Profil at čas. Přesunout/Odebrat queues keep jejich order pro každý Profil.", + "CREATE_PROFILE_BACKUP": "Vytvořit Profil záloha", + "CREATE_REUSABLE_LABELS_AND_REMOVE_LABELS_THAT_ARE_NO_LONGER_NEEDED": "Vytvořit opakovaně použitelné Štítky a Odebrat Štítky že jsou Žádné déle needed.", + "CREATE_TORRENT": "Vytvořit Torrent", + "CTRL_A_SELECT_VISIBLE": "Ctrl+ - Vybrat viditelné", + "CTRL_I_INVERT_VISIBLE": "Ctrl+I - invert viditelné", + "CTRL_O_ADD": "Ctrl+O - Přidat", + "CTRL_S_DOWNLOAD_TORRENT": "Ctrl+S - Stahování .Torrent", + "CURRENT_TRANSFER_SPEED": "Aktuální transfer Rychlost", + "CUSTOM_DOWNLOAD": "Vlastní Stahování", + "CUSTOM_UPLOAD": "Vlastní Odesílání", + "DAYS_AND_LINE_COUNT": "Dny a line count", + "DECREASE_OR_INCREASE_THE_WHOLE_INTERFACE_SIZE": "Decrease nebo increase whole interface Velikost.", + "DEFAULT_LOG_CATEGORY": "Výchozí Log Kategorie", + "DEFAULT_LOG_VIEW": "Výchozí Log view", + "DEFAULT_RTORRENT_PATH": "Výchozí rTorrent Cesta", + "DEGRADED": "degraded", + "DELETE": "Smazat", + "DELETE_REMOVE": "Smazat - Odebrat", + "DESKTOP": "Desktop", + "DETAILS_WILL_APPEAR_AFTER_THE_FIRST_SUCCESSFUL_RESPONSE": "Detaily bude appear po První úspěšná odpověď.", + "DIAGNOSTICS": "Diagnostika", + "DISABLED": "Vypnuto", + "DISK_MONITOR": "Disk monitor", + "DISK_USAGE_UNAVAILABLE": "Disk usage unavailable", + "DISPLAYS_CURRENT_SPEEDS_NEXT_TO_PYTORRENT_IN_THE_TAB_TITLE": "Displays Aktuální speeds Další do pyTorrent v karta Název.", + "DOCS_API": "Docs API", + "DOWNLOADED": "Staženo", + "DOWNLOADING": "Stahování", + "DOWNLOADS": "Stahování", + "DOWNLOAD_KIB_S": "Stahování KiB/s", + "DOWNLOAD_STARTED": "Stahování spuštěné", + "DOWNLOAD_TORRENT": "Stahování .Torrent", + "DOWNLOAD_TRACKER_FAVICONS": "Stahování Tracker favicons", + "DRAG_TO_RESIZE_DETAILS_PANEL": "Drag do resize Detaily Panel", + "EASTER_EGG": "Easter egg", + "EDIT": "Upravit", + "EMERGENCY_CANCEL": "Emergency Zrušit", + "EMERGENCY_CLEAN_ALL": "Emergency clean Vše", + "ENABLED": "Zapnuto", + "ENABLE_AUTOMATIC_APPLICATION_BACKUPS": "Zapnout Automaticky Aplikace zálohy", + "ENABLE_AUTOMATIC_PROFILE_BACKUPS": "Zapnout Automaticky Profil zálohy", + "ENABLE_EASTER_EGG": "Zapnout easter egg", + "ENABLE_INCOMING_PORT_CHECK": "Zapnout incoming Port Zkontrolovat", + "ENABLE_REVERSE_DNS_FOR_PEERS": "Zapnout reverse DNS pro Peers", + "ENGLISH": "Angličtina", + "EPISODE": "Epizoda", + "ESC_CLEAR_SELECTION": "Esc - Vymazat selection", + "ETA": "ETA", + "EVERY_N_MINUTES": "Every N minut", + "EVERY_X_HOURS": "Every X hours", + "EXCLUDE": "Vyloučit", + "EXCLUDE_FROM_SMART_QUEUE": "Vyloučit z Smart Queue", + "EXCLUDE_PATTERN": "Vyloučit Vzor", + "EXISTING_GROUPS": "Existing Skupiny", + "EXPORT": "Export", + "EXPORT_JSON": "Export JSON", + "EXTERNAL_AUTHENTICATION_IS_ENABLED_THROUGH_EXTERNAL_PROVIDER": "External authentication je Zapnuto through {{ external_provider }}.", + "E_G_PUNKTY_KATALOGOWANIE": "e.g. Punkty katalogowanie", + "FEATURES": "Funkce", + "FEED": "Feed", + "FEEDS_ARE_CHECKED_BY_SCHEDULE_AND_EVERY_MATCH_IS_LOGGED_PER_FEED_RULE": "Kanály jsou kontrolovány podle plán a every shoda je zapsána per feed/Pravidlo.", + "FEEDS_RULES_AND_MATCHES": "Kanály, Pravidla a shody", + "FEED_NAME": "Feed Název", + "FEED_URL": "Feed URL", + "FILES": "Soubory", + "FILE_OR_DIRECTORY_PATH": "Soubor nebo Adresář Cesta", + "FONT": "Písmo", + "FOOTER": "Patička", + "FORCE": "Vynutit", + "FORCE_RECHECK": "Vynutit Znovu zkontrolovat", + "FRONTEND": "Frontend", + "FULL": "Full", + "GENERAL": "Obecné", + "GENERATED_RTORRENT_CONFIG_CHANGES_WILL_APPEAR_HERE": "Vygenerováno rTorrent Konfigurace changes bude appear here.", + "GENERATE_CONFIG": "Generate Konfigurace", + "GERMAN": "Němčina", + "GO": "Go", + "GROUPED_RTORRENT_RUNTIME_SETTINGS_WITH_INLINE_RECOMMENDATIONS_AND_COMPATIBILITY_": "Seskupená rTorrent Runtime Nastavení s inline doporučení a kompatibilita Stav.", + "GROUP_NAME": "Skupina Název", + "HASH": "Hash", + "HASHING": "Hashing", + "HEAVY_PARALLEL_JOBS": "Heavy parallel Úlohy", + "HEAVY_TIMEOUT_SECONDS": "Heavy Timeout sekund", + "HIDE_JOB_LOGS": "Skrýt Úloha Logy", + "HIDE_JOB_LOGS_BY_DEFAULT": "Skrýt Úloha Logy podle Výchozí", + "HISTORY": "Historie", + "HOW_LONG_A_MATCHING_ACTIVE_TORRENT_MUST_STAY_STALLED_BEFORE_IT_CAN_BE_REPLACED": "Jak dlouho matching Aktivní Torrent musí stay zaseknuté před it může být nahrazen.", + "IGNORE_MISSING_SEEDS_PEERS_FOR_STALLED_TIMER": "Ignorovat missing Seeds/Peers pro zaseknuté timer", + "IGNORE_SPEED_FOR_STALLED_TIMER": "Ignorovat Rychlost pro zaseknuté timer", + "IMPORT": "Import", + "IMPORT_JSON": "Import JSON", + "INCLUDE_PATTERN": "Zahrnout Vzor", + "INCOMING_CONNECTION_TEST_SEPARATE_FROM_VISUAL_PREFERENCES": "Incoming Připojení Test, separate z visual Předvolby.", + "INTERFACE_SCALE": "Interface scale", + "INTERVAL_MINUTES": "Interval minut", + "INVERT_VISIBLE": "invert viditelné", + "JOBS": "Úlohy", + "JOB_DONE": "Úloha hotovo", + "JOB_FAILED": "Úloha selhalo", + "JOB_QUEUE": "Úloha Fronta", + "JOB_SCHEDULING": "Úloha scheduling", + "JOB_STARTED": "Úloha spuštěné", + "KEEP_LINES": "Keep lines", + "KEEP_SEEDING": "Keep Seedování", + "LABEL": "Štítek", + "LABELS": "Štítky", + "LABELS_SEPARATED_BY_COMMA": "Štítky separated podle comma", + "LABEL_AFTER_SHARE": "Štítek po share", + "LABEL_EXISTS": "Štítek exists", + "LABEL_IS_MISSING": "Štítek je missing", + "LABEL_NAME_OR_SEVERAL_SEPARATED_BY_COMMA": "Štítek Název, nebo několik separated podle comma", + "LANGUAGE": "Jazyk", + "LANGUAGE_SAVED": "Jazyk Uloženo", + "LAST_OPERATIONS": "Poslední operations", + "LICENSE": "Licence", + "LIGHTWEIGHT_WEB_PANEL_FOR_RTORRENT_MANAGEMENT_QUEUE_CONTROL_AND_LIVE_TORRENT_DIA": "Lightweight web Panel pro rTorrent management, Fronta control a live Torrent Diagnostika.", + "LIGHT_PARALLEL_JOBS": "Light parallel Úlohy", + "LIGHT_TIMEOUT_SECONDS": "Light Timeout sekund", + "LIMIT_DL": "Limit DL", + "LOADING": "Načítání", + "LOADING_CLEANUP_DATA": "Načítání Čištění Data...", + "LOADING_CONFIG": "Načítání Konfigurace...", + "LOADING_IMAGE_URL": "Načítání image URL", + "LOADING_JOBS": "Načítání Úlohy...", + "LOADING_LOGS": "Načítání Logy...", + "LOADING_PROFILES": "Načítání Profily...", + "LOADING_STATISTICS": "Načítání Statistiky...", + "LOADING_TORRENTS": "Načítání Torrenty...", + "LOADING_TORRENT_DETAILS": "Načítání Torrent Detaily...", + "LOCAL_BROWSER_TIME": "Lokální Prohlížeč čas", + "LOCATION": "Umístění", + "LOG": "Log", + "LOGS": "Logy", + "LOG_IN": "Přihlásit se", + "LOG_OUT": "Odhlásit se", + "LOG_STATISTICS": "Log Statistiky", + "MAGNET_AND_TORRENT_UPLOAD_FILE_PRIORITIES_LABELS_RATIO_GROUPS_SMART_QUEUE_AUTOMA": "Magnet a Torrent Odesílání, Soubor priority, Štítky, Ratio Skupiny, Smart Queue, automation Pravidla, RSS, provoz grafy, Port kontrola, system Stav.", + "MAGNET_LINKS": "Magnet links", + "MANAGE_EXCEPTIONS": "Manage exceptions", + "MANAGE_OPERATION_LOG_RETENTION_WITHOUT_CHANGING_TORRENT_DATA": "Manage operation Log Uchování bez Změna Torrent Data.", + "MANAGE_OPTIONAL_PYTORRENT_USERS_EMPTY_PROFILE_MEANS_ALL_PROFILES_R_O_BLOCKS_RTOR": "Manage volitelné pyTorrent Uživatelé. Empty Profil means Vše Profily. R/O blocks rTorrent-Změna Akce; Full allows je.", + "MANUAL_CLEANUP_ONLY": "Ručně Čištění pouze", + "MAXIMUM_HEAVY_JOBS_RUNNING_AT_ONCE_FOR_THIS_PROFILE_DEFAULT_5": "Maximum heavy Úlohy running at once pro toto Profil. Výchozí: 5.", + "MAXIMUM_QUEUED_ACTIONS_RUNNING_AT_ONCE": "Maximum queued Akce running at once.", + "MAXIMUM_STALLED_OVERFLOW_DOWNLOADS_SMART_QUEUE_MAY_STOP_IN_ONE_PASS": "Maximum zaseknuté/overflow Stahování Smart Queue may Zastavit v jedna pass.", + "MAX_MB": "Max MB", + "MAX_RATIO": "Max Ratio", + "MAX_STOPS_PER_CHECK": "Max stops per Zkontrolovat", + "MESSAGE": "Zpráva", + "MINUTES": "Minut", + "MIN_MB": "Min MB", + "MIN_PEERS": "Min Peers", + "MIN_RATIO": "Min Ratio", + "MIN_SEEDS": "Min Seeds", + "MIN_SEED_MINUTES": "Min seed minut", + "MIN_SPEED_KIB_S": "Min Rychlost KiB/s", + "MOBILE": "Mobilní", + "MOBILE_COLUMNS": "Mobilní Sloupce", + "MOBILE_FILTER_GROUPS": "Mobilní filtr Skupiny", + "MOBILE_SIMPLE_MODE": "Mobilní/simple mode", + "MOBILE_SORT_FILTERS": "Mobilní sort filters", + "MODE": "Mode", + "MONITORED_PATHS": "Monitored cesty", + "MOVE": "Přesunout", + "MOVE_DATA": "Přesunout Data", + "MOVE_DATA_FILES": "Přesunout Data Soubory", + "MOVE_PATH": "Přesunout Cesta", + "MOVE_TO_PATH": "Přesunout do Cesta", + "MOVIES": "filmy", + "MOVING": "Moving", + "M_MOVE": "M - Přesunout", + "NAME": "Název", + "NEGATE": "Negate", + "NEWLY_QUEUE_STARTED_TORRENTS_ARE_PROTECTED_FROM_STALLED_CLEANUP_DURING_THIS_WARM": "Nově Fronta-spuštěné Torrenty jsou chráněné z zaseknuté Čištění během toto zahřívání-nahoru.", + "NEW_LABEL": "Nový Štítek", + "NEXT_READY": "Další: ready", + "NEXT_SMART_QUEUE_RUN": "Další Smart Queue běh", + "NOTIFICATIONS": "Oznámení", + "NOT_LOADED": "Nenačteno.", + "NO_CHANGES": "Žádné změny", + "NO_FILES_RETURNED_BY_RTORRENT": "Žádné Soubory returned podle rTorrent.", + "NO_FILES_SELECTED": "Nejsou vybrány žádné soubory.", + "NO_LABELS": "Žádné Štítky.", + "NO_LABELS_SELECTED": "Nejsou vybrány žádné štítky.", + "NO_PATH_LOADED": "Žádné Cesta loaded.", + "NO_PEERS_RETURNED_BY_RTORRENT": "Žádné Peers returned podle rTorrent.", + "NO_RTORRENT_PROFILE_CONFIGURED": "Žádné rTorrent Profil configured.", + "NO_SAVED_LABELS": "Žádné Uloženo Štítky.", + "NO_TORRENTS": "Žádné Torrenty.", + "NO_TORRENTS_FOR_THIS_FILTER": "Žádné Torrenty pro toto filtr.", + "NO_TORRENTS_SELECTED": "Nejsou vybrány žádné torrenty", + "NO_TORRENT_SELECTED": "Není vybrán žádný torrent", + "NO_TRACKERS_RETURNED_BY_RTORRENT": "Žádné Trackery returned podle rTorrent.", + "OFF": "Off", + "OFFLINE": "offline", + "ONE_PLACE_TO_CLEAR_LOGS_AND_ACTIVE_PROFILE_CACHES_PENDING_RUNNING_JOBS_RULES_SET": "Jedna place do Vymazat Logy a Aktivní Profil caches. Čekající/running Úlohy, Pravidla, Nastavení a Torrenty jsou preserved.", + "ONE_TRACKER_URL_PER_LINE": "Jedna Tracker URL per line", + "ONLINE": "online", + "ONLY_SELECTED": "Pouze vybráno", + "OPEN_DOWNLOAD_PLANNER": "Otevřít Stahování planner", + "OPEN_RTORRENT_FILES_MAX_OPEN_FILES": "Otevřít rTorrent Soubory / max Otevřít Soubory", + "OPEN_RTORRENT_HTTP_CONNECTIONS_MAX_HTTP_CONNECTIONS": "Otevřít rTorrent HTTP connections / max HTTP connections", + "OPEN_RTORRENT_SOCKETS": "Otevřít rTorrent sockets", + "OPEN_SOURCE": "Open source", + "OPEN_THIS_TAB_TO_LOAD_DIAGNOSTICS": "Otevřít toto karta do načíst Diagnostika.", + "OPEN_THIS_TAB_TO_LOAD_STATISTICS": "Otevřít toto karta do načíst Statistiky.", + "OPERATION_LOG_RETENTION": "Operation Log Uchování", + "OPTIONAL": "volitelné", + "OPTIONAL_PEER_TABLE_HELPERS": "Volitelné peer table helpers.", + "OPTIONAL_PRIVATE_SOURCE_TAG": "volitelné Soukromý Zdroj tag", + "OPTIONAL_VISUAL_EASTER_EGG_FOR_LOADING_STATES_AND_OCCASIONAL_BUTTON_CLICKS_DISAB": "Volitelné visual easter egg pro Načítání stavy a občasné tlačítko kliknutí. Vypnuto podle Výchozí.", + "PARALLEL_JOBS": "Parallel Úlohy", + "PARENT_DIRECTORY": "Nadřazený Adresář", + "PARTIAL_DETAILS_LOADED": "Partial Detaily loaded", + "PASSWORD": "Heslo", + "PASSWORD_NEW_PASSWORD": "Heslo / Nový Heslo", + "PASTE_ONE_MAGNET_URI_PER_LINE": "Paste jedna magnet URI per line.", + "PATH": "Cesta", + "PATH_CONTAINS": "Cesta contains", + "PATH_TEXT": "Cesta Text", + "PATH_USED_FOR_SELECTED_MODE": "Cesta used pro vybráno mode", + "PAUSE": "Pozastavit", + "PAUSED": "Pozastaveno", + "PEAK_S": "Peak S", + "PEAK_SPEED_UNAVAILABLE": "Peak Rychlost unavailable", + "PEERS": "Peers", + "PEERS_AUTO_REFRESH": "Peers auto Obnovit", + "PENDING_JOBS_OLDER_THAN_THIS_ARE_RESUBMITTED_IF_NO_WORKER_IS_CURRENTLY_HANDLING_": "Čekající Úlohy starší než toto jsou znovu odeslány pokud Žádné worker je aktuálně zpracovává je. Výchozí: 900 sekund.", + "PENDING_RUNNING_DONE_FAILED_RETRY_AND_CANCEL_HISTORY": "Čekající, running, hotovo, selhalo, Opakovat a Zrušit Historie.", + "PENDING_TIMEOUT_SECONDS": "Čekající Timeout sekund", + "PIECE_SIZE": "Piece Velikost", + "PLANNER": "Planner", + "POLISH": "Polština", + "PORT": "Port", + "PORT_CHECKER": "Port kontrola", + "PORT_CHECK_DISABLED": "Port Zkontrolovat Vypnuto", + "PORT_UNKNOWN": "Port - unknown", + "POST_CHECK": "Post-Zkontrolovat", + "PREFERENCES": "Předvolby", + "PREFERENCES_SAVED": "Předvolby Uloženo", + "PRIORITY": "Priorita", + "PRIVATE_TORRENT": "Soukromý Torrent", + "PROFILE_BACKUP": "Profil záloha", + "PROFILE_BACKUP_NAME": "Profil záloha Název", + "PROFILE_BACKUP_RESTORES_ONLY_THE_ACTIVE_PROFILE_CONTEXT_APPLICATION_BACKUP_RESTO": "Profil záloha restores pouze Aktivní Profil kontext. Aplikace záloha restores global Aplikace Data a je dostupné pouze do správci.", + "PROFILE_NAME": "Profil Název", + "PROFILE_SCOPED_LOG_COUNTS_AND_CLEANUP_OVERVIEW": "Profil-scoped Log počty a Čištění přehled.", + "PROGRESS": "Průběh", + "PROGRESS_IS_AT_LEAST": "Průběh je at least %", + "PROGRESS_IS_AT_MOST": "Průběh je at most %", + "PROGRESS_SOURCE": "Průběh Zdroj", + "PROTECT_ACTIVE_COUNT_BELOW_CAP": "Protect Aktivní count below cap", + "PYTORRENT_EXPECTS_TRUSTED_REVERSE_PROXY_IDENTITY_HEADERS_IF_YOU_ARE_ALREADY_SIGN": "pyTorrent expects trusted reverse-proxy identity headers. Pokud chcete jsou already signed v, Zkontrolovat provider headers a Uživatel mapping.", + "PYTORRENT_LOGIN": "pyTorrent login", + "PYTORRENT_STATUS": "pyTorrent Stav", + "P_PAUSE": "P - Pozastavit", + "QUALITY": "Kvalita", + "QUEUE_REFILL_DURING_COOLDOWN": "Fronta refill během Prodleva", + "RANDOM_CLICK_IMAGE_URL": "Random click image URL", + "RATIO": "Ratio", + "RATIO_GROUP": "Ratio Skupina", + "RATIO_GROUPS": "Ratio Skupiny", + "RATIO_IS_AT_LEAST": "Ratio je at least", + "RATIO_RULES": "Ratio Pravidla", + "REANNOUNCE": "Reannounce", + "RECHECK": "Znovu zkontrolovat", + "RECHECK_AFTER_MOVE": "Znovu zkontrolovat po Přesunout", + "RECOMMENDED_COLUMNS": "Doporučené Sloupce", + "RECOMMENDED_COLUMNS_APPLIED": "Doporučené Sloupce použito", + "RECONNECTING": "reconnecting", + "REFERENCE_VALUE_IS_KEPT_FROM_THE_FIRST_OVERRIDE_SAVE_LATER_SAVES_ADD_OR_CLEAR_DI": "Reference hodnota je kept z První override Uložit. Later saves Přidat nebo Vymazat differences bez replacing original reference.", + "REFRESH": "Obnovit", + "REFRESH_NOW": "Obnovit now", + "REGEX_TEXT": "Regex / Text", + "RELOAD": "Reload", + "REMOTE_LOCATION": "Vzdálené Umístění", + "REMOVE": "Odebrat", + "REMOVE_DATA": "Odebrat Data", + "REMOVE_LABEL": "Odebrat Štítek", + "REMOVE_SELECTED_TORRENTS": "Odebrat vybráno Torrenty", + "REMOVE_WITH_DATA": "Odebrat s Data", + "REPOSITORY": "Repozitář", + "RESET": "Resetovat", + "RESET_UI_SETTINGS": "Resetovat UI Nastavení", + "RESET_VIEW_DEFAULTS": "Resetovat view defaults", + "RESIZE_TORRENT_DETAILS_PANEL": "Resize Torrent Detaily Panel", + "RESOLVE_PEER_IP_TO_REVERSE_DNS_HOST": "Resolve peer IP do reverse DNS host", + "RESUME": "Pokračovat", + "RETENTION_DAYS": "Uchování dny", + "RETENTION_MODE": "Uchování mode", + "RETRY": "Opakovat", + "REVERSE_DNS": "Reverse DNS", + "RSS_DOWNLOADER": "RSS downloader", + "RTORRENT": "rTorrent", + "RTORRENTS": "rTorrents", + "RTORRENT_CONFIG": "rTorrent Konfigurace", + "RTORRENT_INCOMING_PORT": "rTorrent incoming Port", + "RTORRENT_IS_STARTING_OR_NOT_RESPONDING_YET": "rTorrent je starting nebo není responding yet.", + "RTORRENT_PROFILES": "rTorrent Profily", + "RULE": "Pravidlo", + "RULES": "Pravidla", + "RULES_ARE_CHECKED_AUTOMATICALLY_EVERY_5_MINUTES_A_TORRENT_USES_THE_GROUP_STORED_": "Pravidla jsou kontrolovány automatically every 5 minut. Torrent uses Skupina stored v its rTorrent Vlastní Ratio field.", + "RULE_NAME": "Pravidlo Název", + "RUNTIME": "Runtime", + "RUN_A_PROFILE_TEST_TO_SHOW_DIAGNOSTICS": "Běh Profil Test do Zobrazit Diagnostika.", + "RUN_SMART_QUEUE_DURING_POLLING_STOPPED_TORRENTS_ARE_MANAGED_PAUSED_TORRENTS_STAY": "Běh Smart Queue během polling. Zastaveno Torrenty jsou spravované; Pozastaveno Torrenty stay Uživatel-controlled.", + "R_RESUME": "R - Pokračovat", + "SAVE": "Uložit", + "SAVED_LABELS": "Uloženo Štítky", + "SAVE_COLUMNS": "Uložit Sloupce", + "SAVE_CONFIG": "Uložit Konfigurace", + "SAVE_EASTER_EGG": "Uložit easter egg", + "SAVE_EXCEPTIONS": "Uložit exceptions", + "SAVE_FEED": "Uložit feed", + "SAVE_FOOTER": "Uložit Patička", + "SAVE_GROUP": "Uložit Skupina", + "SAVE_JOB_SETTINGS": "Uložit Úloha Nastavení", + "SAVE_LIMITS": "Uložit Limity", + "SAVE_LOCATION": "Uložit Umístění", + "SAVE_LOG_VIEW": "Uložit Log view", + "SAVE_PATH": "Uložit Cesta", + "SAVE_PREFERENCES": "Uložit Předvolby", + "SAVE_RETENTION": "Uložit Uchování", + "SAVE_RULE": "Uložit Pravidlo", + "SAVE_SCHEDULE": "Uložit plán", + "SAVE_USER": "Uložit Uživatel", + "SCGI_URL": "SCGI URL", + "SEARCH_LOGS": "Hledat Logy...", + "SEARCH_TORRENTS": "Hledat Torrenty...", + "SEARCH_TORRENTS_TO_EXCLUDE": "Hledat Torrenty do Vyloučit...", + "SEASON": "Řada", + "SECONDS_TO_WAIT_FOR_RTORRENT_RESPONSE": "Sekund do čekat pro rTorrent odpověď.", + "SEEDING": "Seedování", + "SEEDS": "Seeds", + "SEEDS_ARE_LOW_FOR_TIME": "Seeds jsou nízké pro čas", + "SEED_MINUTES": "Seed minut", + "SELECT": "Vybrat", + "SELECTED": "vybráno", + "SELECTED_LABELS": "Vybráno Štítky", + "SELECTED_MONITORED_PATH": "Vybráno monitored Cesta", + "SELECTED_TORRENTS_WILL_BE_REMOVED": "vybráno Torrenty bude být removed.", + "SELECT_A_MONITORED_PATH_FIRST": "Vybrat monitored Cesta První.", + "SELECT_A_TORRENT": "Vybrat Torrent.", + "SELECT_ONE_OR_MORE_TORRENT_FILES": "Vybrat jedna nebo more .Torrent Soubory.", + "SELECT_PATH": "Vybrat Cesta", + "SELECT_TORRENTS_THAT_SMART_QUEUE_SHOULD_IGNORE_USE_SEARCH_TO_FILTER_BY_NAME_LABE": "Vybrat Torrenty že Smart Queue má ignorovat. Použít Hledat do filtr podle Název, Štítek, Stav nebo Hash.", + "SELECT_VISIBLE": "Vybrat viditelné", + "SEPARATE_SLOT_POOL_FOR_LIGHTWEIGHT_CONTROL_JOBS_SO_THEY_DO_NOT_WAIT_BEHIND_HEAVY": "Separate slot pool pro lightweight control Úlohy so they do není čekat za heavy IO práce. Výchozí: 4.", + "SETTINGS": "Nastavení", + "SET_LABEL": "Set Štítek...", + "SET_LABELS": "Set Štítky", + "SET_RATIO_GROUP": "Set Ratio Skupina...", + "SHARE_AFTER_CREATING": "Share po creating", + "SHORTCUTS": "Shortcuts", + "SHOWN": "Shown", + "SHOWN_IN_LOADING_STATES_INSTEAD_OF_THE_STANDARD_SPINNER": "Shown v Načítání stavy místo standardní spinner.", + "SHOWS_TRACKER_ICONS_IN_THE_SIDEBAR_TRACKER_FILTER_WHEN_AVAILABLE": "Zobrazuje Tracker ikony v postranní panel Tracker filtr when dostupné.", + "SHOW_COMBINED_USAGE_SINGLE_PATH_SELECTION_IS_DISABLED_IN_THIS_MODE": "Zobrazit kombinované usage. Jedna Cesta selection je Vypnuto v toto mode.", + "SHOW_DL_UP_IN_BROWSER_TITLE": "Zobrazit DL/UP v Prohlížeč Název", + "SHOW_SMART_QUEUE_AUTOMATIC_RUN_MESSAGES": "Zobrazit Smart Queue Automaticky běh zprávy.", + "SHOW_TOASTS_CREATED_BY_AUTOMATION_RUNS": "Zobrazit toasts created podle automation runs.", + "SIGN_IN": "Přihlásit se", + "SIZE": "Velikost", + "SKIP_ACTIVE_UPLOAD": "Skip Aktivní Odesílání", + "SKIP_PRIVATE_TORRENTS": "Skip Soukromý Torrenty", + "SMART_FILTERS": "Smart filters", + "SMART_QUEUE": "Smart Queue", + "SMART_QUEUE_EXCEPTIONS": "Smart Queue exceptions", + "SMART_QUEUE_KEEPS_ONLY_THIS_MANY_ACTIVE_DOWNLOADS_OVERFLOW_IS_STOPPED": "Smart Queue keeps pouze toto many Aktivní Stahování; overflow je Zastaveno.", + "SMART_QUEUE_TOASTS": "Smart Queue toasts", + "SOCKETS": "Sockets", + "SOURCE": "Zdroj", + "SPACE_START": "Space - Spustit", + "SPEED": "Rychlost", + "SPEED_LIMITS": "Rychlost Limity", + "SPEED_TREND": "Rychlost trend", + "STALLED_AFTER_SECONDS": "Zaseknuté po sekund", + "START": "Spustit", + "START_AFTER_ADD": "Spustit po Přidat", + "START_GRACE_SECONDS": "Spustit grace sekund", + "STATE": "Stav", + "STATUS": "Stav", + "STATUS_EQUALS": "Stav equals", + "STOP": "Zastavit", + "STOPPED": "Zastaveno", + "S_STOP": "S - Zastavit", + "TARGET_ACTIVE_DOWNLOADS": "Cíl Aktivní Stahování", + "TARGET_PATH": "Cíl Cesta", + "TEST_RULE": "Test Pravidlo", + "TEST_SCGI": "Test SCGI", + "THEME_TYPOGRAPHY_AND_INTERFACE_SCALE": "Motiv, typography a interface scale.", + "THE_FOOTER_TOOLTIP_ALWAYS_SHOWS_DETAILS_FOR_AVAILABLE_PATHS_THIS_SETTING_ONLY_DE": "Patička tooltip vždy zobrazuje Detaily pro dostupné cesty; toto nastavení pouze rozhoduje která hodnota řídí viditelné Průběh lišta.", + "TIMEOUT": "Timeout", + "TOAST_NOTIFICATIONS_FROM_AUTOMATIC_SYSTEMS": "Toast Oznámení z Automaticky systems.", + "TOOLS": "Nástroje", + "TOOLS_RTORRENTS": "Nástroje & rTorrents", + "TOOLS_SECTIONS": "Nástroje sections", + "TORRENT_ADDED": "Torrent added", + "TORRENT_COMPLETED": "Torrent Dokončeno", + "TORRENT_DETAILS": "Torrent Detaily", + "TORRENT_FILES": "Torrent Soubory", + "TORRENT_FILTERS": "Torrent filters", + "TORRENT_PROPERTIES": "Torrent properties", + "TORRENT_REMOVED": "Torrent removed", + "TORRENT_STATISTICS": "Torrent Statistiky", + "TORRENT_STATS": "Torrent stats", + "TOTAL_DL_UP": "Total DL/UP", + "TO_DOWNLOAD": "Do Stahování", + "TRACKERS": "Trackery", + "TRACKER_ICONS": "Tracker ikony", + "TRANSFER": "Transfer", + "TRANSFERRED_DATA": "Transferred Data", + "TRANSFER_HISTORY": "Transfer Historie", + "UNDEFINED": "undefined", + "UNLIMITED": "Unlimited", + "UPLOADED": "Odesláno", + "UPLOADS": "Odesílání", + "UPLOAD_KIB_S": "Odesílání KiB/s", + "USER": "Uživatel", + "USERS": "Uživatelé", + "USES_A_LIGHTWEIGHT_BUILT_IN_RESOLVER_WITH_CACHE_HOSTNAMES_APPEAR_ONLY_IN_THE_PEE": "Uses lightweight built-v resolver s cache. Hostnames appear pouze v Peers karta.", + "USES_LOWER_ROWS_AND_SMALLER_LIST_ELEMENTS_ON_DESKTOP_AND_MOBILE_SO_MORE_TORRENTS": "Uses nižší řádky a smaller seznam elements on Desktop a Mobilní so more Torrenty vejde on obrazovka.", + "USES_YOUGETSIGNAL_FIRST_MANUAL_CHECK_BYPASSES_THE_6H_CACHE": "Uses YouGetSignal První. Ručně Zkontrolovat bypasses 6h cache.", + "USE_ONE_CUSTOM_PATH_BELOW_AS_THE_FOOTER_PROGRESS_VALUE": "Použít jedna Vlastní Cesta below jako Patička Průběh hodnota.", + "USE_SELECTED": "Použít vybráno", + "USE_THE_MAIN_DIRECTORY_FROM_THE_ACTIVE_RTORRENT_PROFILE": "Použít main Adresář z Aktivní rTorrent Profil.", + "VIEW_PREFERENCES_RESET": "View Předvolby Resetovat", + "VIEW_STATE_IS_SAVED_AUTOMATICALLY_IN_THE_DATABASE_CURRENT_TORRENT_FILTER_LAST_SO": "View Stav je Uloženo automatically v database: Aktuální Torrent filtr, Poslední sort column a direction, viditelné Sloupce, a Detaily Panel height.", + "VISIBLE_NAME_USED_IN_THE_PROFILE_SELECTOR": "Viditelné Název used v Profil selector.", + "VISUAL_HELPER_FOR_TRACKER_FILTERS_IN_THE_SIDEBAR": "Visual pomocník pro Tracker filters v postranní panel.", + "WAITING_FOR_DATA": "Čekání pro Data.", + "WAITING_FOR_TORRENT_DATA_FROM_THE_ACTIVE_PROFILE": "Čekání pro Torrent Data z Aktivní Profil.", + "WATCHDOG_MARKS_A_LIGHT_JOB_AS_FAILED_AFTER_THIS_TIME_DEFAULT_300_SECONDS": "Watchdog marks light Úloha jako selhalo po toto čas. Výchozí: 300 sekund.", + "WATCHDOG_TIMEOUT_FOR_MOVE_REMOVE_ADD_JOBS_DEFAULT_7200_SECONDS": "Watchdog Timeout pro Přesunout/Odebrat/Přidat Úlohy. Výchozí: 7200 sekund.", + "WHEN_DISABLED_THE_APPLICATION_USES_THE_NORMAL_PRODUCTION_UI": "When Vypnuto, Aplikace uses normální produkční UI.", + "WHEN_ENABLED_LOW_SPEED_IS_NOT_REQUIRED_WITH_SOURCE_AND_SPEED_IGNORES_ENABLED_ONL": "When Zapnuto, nízké Rychlost je není required. S Zdroj a Rychlost ignores Zapnuto, pouze Zaseknuté po sekund rozhoduje.", + "WHEN_ENABLED_SMART_QUEUE_DOES_NOT_USE_SEED_PEER_COUNT_AS_A_STALLED_CRITERION": "When Zapnuto, Smart Queue does není použít seed/peer count jako zaseknuté kritérium.", + "WITH_ERROR": "S Chyba", + "WORKING": "Pracuji...", + "FRENCH": "Francouzština", + "CZECH": "Čeština", + "SPANISH": "Španělština", + "NORWEGIAN": "Norština", + "RUSSIAN": "Ruština" + } +} diff --git a/pytorrent/static/i18n/de_DE.json b/pytorrent/static/i18n/de_DE.json new file mode 100644 index 0000000..bf2fee2 --- /dev/null +++ b/pytorrent/static/i18n/de_DE.json @@ -0,0 +1,566 @@ +{ + "meta": { + "locale": "de_DE", + "label": "Deutsch", + "flag": "de" + }, + "translations": { + "0_MEANS_ONLY_SEED_THRESHOLD_IS_REQUIRED": "0 means nur seed threshold is required.", + "0_MEANS_UNLIMITED_SLIDERS_USE_MBIT_S_AND_SAVE_THROUGH_THE_EXISTING_SPEED_LIMITS_": "0 means unlimited. Sliders verwenden Mbit/s und Speichern through existing Geschwindigkeit Limits API.", + "0_SELECTED": "0 ausgewählt", + "ABOUT_PYTORRENT": "About pyTorrent", + "ACTION": "Aktion", + "ACTIVE": "Aktiv", + "ACTIVE_RTORRENT_DOWNLOADS_MAX_GLOBAL_DOWNLOADS": "Aktiv rTorrent Downloads / max global Downloads", + "ACTIVE_RTORRENT_UPLOADS_MAX_GLOBAL_UPLOADS": "Aktiv rTorrent Uploads / max global Uploads", + "ADD": "Hinzufügen", + "ADDED": "Hinzugefügt", + "ADDS_REMOVALS_COMPLETIONS_AND_QUEUED_OPERATION_RESULTS": "Adds, removals, completions und queued operation results.", + "ADD_ACTION": "Hinzufügen Aktion", + "ADD_CONDITION": "Hinzufügen Bedingung", + "ADD_CREATE_TORRENT": "Hinzufügen / Erstellen Torrent", + "ADD_FIRST_LABEL_ABOVE": "Hinzufügen Erste Label above.", + "ADD_LABEL": "Hinzufügen Label", + "ADD_MAGNET_LINK": "Magnet-Link hinzufügen", + "ADD_NEW_LABEL": "Hinzufügen Neu Label", + "ADD_OR_EDIT_GROUP": "Hinzufügen or Bearbeiten Gruppe", + "ADD_PATH": "Pfad hinzufügen", + "ADD_PROFILE": "Hinzufügen Profil", + "ADD_RTORRENT_PROFILE": "rTorrent-Profil hinzufügen", + "ADD_THE_FIRST_RTORRENT_PROFILE_TO_START_LOADING_TORRENTS": "Füge das erste rTorrent-Profil hinzu, um Torrents zu laden.", + "ADD_TORRENT": "Torrent hinzufügen", + "ADD_TORRENT_FILE": "Torrent-Datei hinzufügen", + "ADMIN": "Administrator", + "ADMIN_ONLY_FULL_APPLICATION_BACKUP_RESTORE_CAN_REPLACE_USERS_PERMISSIONS_PROFILE": "Administrator-nur full Anwendung Backup. Wiederherstellen kann replace Benutzer, permissions, Profile und global Anwendung Einstellungen.", + "AGGREGATE_ALL_PATHS": "Alle Pfade aggregieren", + "ALL": "Alle", + "ALL_NON_JOB_TYPES": "Alle non-Job types", + "ALL_PROFILES": "Alle Profile", + "ALL_TYPES": "Alle types", + "ANNOUNCE": "Announce", + "API_DOCS": "API docs", + "APPEARANCE": "Darstellung", + "APPEARANCE_PREFERENCES_SAVED": "Darstellungseinstellungen gespeichert", + "APPEARS_NEAR_CLICKED_BUTTONS_ONLY_SOMETIMES": "Appears near clicked buttons nur sometimes.", + "APPLICATION_BACKUP": "Anwendung Backup", + "APPLICATION_BACKUP_NAME": "Anwendung Backup Name", + "APPLY": "Apply", + "APPLY_RETENTION_NOW": "Apply Aufbewahrung now", + "APPLY_SAVED_CHANGES_60S_AFTER_PYTORRENT_START": "Apply Gespeichert changes 60s nach pyTorrent Start", + "APP_STATUS": "App Status", + "AUTHENTICATION_IS_ENABLED_FOR_THIS_PYTORRENT_INSTANCE": "Authentication ist Aktiviert für diese pyTorrent Instanz.", + "AUTHOR": "Autor", + "AUTOMATIC": "Automatisch", + "AUTOMATIC_KEEPS_THE_CURRENT_POLLER_CADENCE_CUSTOM_RUNS_ONLY_AFTER_THE_SELECTED_N": "Automatisch keeps Aktuell poller cadence. Benutzerdefiniert runs nur nach ausgewählt number Minuten. Off disables refill completely.", + "AUTOMATIC_QUEUE_BALANCING_FOR_SLOW_OR_STALLED_DOWNLOADS": "Automatisch Warteschlange balancing for slow or stalled Downloads.", + "AUTOMATIC_RUNS_USE_THE_COOLDOWN_BELOW_MANUAL_CHECK_NOW_STILL_RUNS_IMMEDIATELY": "Automatisch runs verwenden Cooldown below. Manuell Prüfen now still runs immediately.", + "AUTOMATIONS": "Automations", + "AUTOMATIONS_RULES": "Automations / Regeln", + "AUTOMATION_TOASTS": "Automation-Toasts", + "AUTO_STOP_WHEN_IDLE": "Auto-Stop when idle", + "BACKEND": "Backend", + "BACKUP": "Backup", + "BACKUP_RESTORE": "Backup / Wiederherstellen", + "BACK_TO_DASHBOARD": "Back zu dashboard", + "BOOTSTRAP_THEME": "Bootstrap-Theme", + "BROWSER": "Browser", + "BROWSER_TITLE": "Browser-Titel", + "BUILD_A_RULE_AS_CONDITIONS_FIRST_THEN_ORDERED_ACTIONS_MATCHING_TORRENTS_ARE_HAND": "Build Regel als: Bedingungen Erste, dann ordered Aktionen. Matching Torrents sind handled als eine batch und Cooldown ist angewendet zu whole Regel.", + "BUSY": "beschäftigt", + "BY_DAYS": "By Tage", + "BY_LINE_COUNT": "Nach line count", + "CACHED_METADATA_SUMMARY_FILE_METADATA_IS_REFRESHED_EVERY_15_MINUTES_A_FEW_MINUTE": "Cached metadata summary. Datei metadata ist refreshed every 15 Minuten, a einige Minuten nach Start, oder manually.", + "CANCEL": "Abbrechen", + "CANCEL_EDIT": "Abbrechen Bearbeiten", + "CATEGORY": "Kategorie", + "CHANGES_APPLY_IMMEDIATELY_WHERE_POSSIBLE_INITIAL_STARTUP_LOADER_USES_THEM_AFTER_": "Changes apply immediately where possible; initial Start loader uses sie nach reload.", + "CHANGE_RTORRENT": "Ändern rTorrent", + "CHANGE_THEME": "Change Theme", + "CHANGING_RTORRENT_RELOADS_THE_LIVE_TORRENT_SNAPSHOT": "Änderung rTorrent reloads live Torrent Snapshot.", + "CHECKING": "Prüfung", + "CHECK_NOW": "Jetzt prüfen", + "CHECK_PORT_NOW": "Port jetzt prüfen", + "CHECK_THIS_IF_YOU_WANT_TO_CONNECT_TO_A_REMOTE_RTORRENT_INSTANCE_INSTEAD_OF_LOCAL": "Prüfen diese wenn Sie möchten zu verbinden zu a Remote rTorrent Instanz statt of localhost.", + "CHOOSE_COLUMNS_VISIBLE_IN_THE_TORRENT_LIST": "Wählen Spalten sichtbar in Torrent Liste.", + "CHOOSE_FILES": "Choose Dateien", + "CHOOSE_RTORRENT": "Wählen rTorrent", + "CHOOSE_TORRENTS_IGNORED_BY_SMART_QUEUE_EXISTING_BEHAVIOR_STAYS_UNCHANGED_FOR_ALL": "Wählen Torrents ignored nach Smart Queue. Existing behavior stays unchanged für Alle non-excluded Torrents.", + "CHOOSE_WHAT_THE_FOOTER_DISK_BAR_SHOULD_REPRESENT_AND_ADD_EXTRA_STORAGE_PATHS": "Wählen what Fußzeile disk Leiste soll represent und Hinzufügen extra storage Pfade.", + "CHOOSE_WHICH_STATUS_ITEMS_ARE_VISIBLE_IN_THE_BOTTOM_BAR": "Wählen welcher Status items sind sichtbar in bottom Leiste.", + "CHUNKS": "Chunks", + "CLEANUP": "Bereinigung", + "CLEANUP_RETENTION": "Bereinigung / Aufbewahrung", + "CLEAR": "Löschen", + "CLEAR_CURRENT_FILTER": "Löschen Aktuell filter", + "CLEAR_FINISHED": "Löschen finished", + "CLEAR_LABELS": "Löschen Labels", + "CLEAR_SELECTION": "Auswahl löschen", + "CLEAR_VISIBLE": "Löschen sichtbar", + "CLOSE": "Schließen", + "COLUMNS": "Spalten", + "COLUMNS_SAVED": "Spalten gespeichert", + "COMMENT": "Comment", + "COMPACT_TORRENT_LIST": "Kompakte Torrent-Liste", + "COMPLETE": "Abgeschlossen", + "COMPLETED": "Abgeschlossen", + "CONFIGURED_RTORRENTS": "Configured rTorrents", + "CONNECTING_TO_RTORRENT_AND_PREPARING_DATA": "Verbindung zu rTorrent wird hergestellt und Daten werden vorbereitet.", + "CONNECTION_ADDRESS_IN_SCGI_HOST_PORT_RPC2_FORMAT": "Verbindung address in scgi://host:Port/RPC2 format.", + "CONTROLS_THE_DEFAULT_CATEGORY_AND_JOB_LOG_VISIBILITY_USED_BY_THE_LOGS_MODAL": "Controls Standard Kategorie und Job Log visibility used nach Logs Modal.", + "CONTROLS_WHAT_IS_SHOWN_IN_THE_BROWSER_TAB": "Steuert, was im Browser-Tab angezeigt wird.", + "COOLDOWN_MINUTES": "Cooldown Minuten", + "COPY": "Kopieren", + "COPY_HASH": "Kopieren Hash", + "COPY_NAME": "Kopieren Name", + "COPY_PATH": "Kopieren Pfad", + "CPU_RAM_USAGE": "CPU / RAM usage", + "CREATE": "Erstellen", + "CREATES_AND_RESTORES_SETTINGS_FOR_THE_CURRENTLY_SELECTED_PROFILE_USER_SCOPED_PRE": "Creates und restores Einstellungen für derzeit ausgewählt Profil. Benutzer-scoped Einstellungen sind remapped zu Aktuell Benutzer where needed.", + "CREATE_APPLICATION_BACKUP": "Erstellen Anwendung Backup", + "CREATE_ONE_RTORRENT_PROFILE_AT_A_TIME_MOVE_REMOVE_QUEUES_KEEP_THEIR_ORDER_FOR_EA": "Erstellen one rTorrent Profil at a time. Verschieben/Entfernen queues keep their order for each Profil.", + "CREATE_PROFILE_BACKUP": "Erstellen Profil Backup", + "CREATE_REUSABLE_LABELS_AND_REMOVE_LABELS_THAT_ARE_NO_LONGER_NEEDED": "Erstellen wiederverwendbare Labels und Entfernen Labels dass sind Keine länger needed.", + "CREATE_TORRENT": "Erstellen Torrent", + "CTRL_A_SELECT_VISIBLE": "Ctrl+A - Auswählen sichtbar", + "CTRL_I_INVERT_VISIBLE": "Ctrl+I - invert sichtbar", + "CTRL_O_ADD": "Ctrl+O - Hinzufügen", + "CTRL_S_DOWNLOAD_TORRENT": "Ctrl+S - Download .Torrent", + "CURRENT_TRANSFER_SPEED": "Aktuelle Übertragungsgeschwindigkeit", + "CUSTOM_DOWNLOAD": "Benutzerdefiniert Download", + "CUSTOM_UPLOAD": "Benutzerdefiniert Upload", + "DAYS_AND_LINE_COUNT": "Tage und line count", + "DECREASE_OR_INCREASE_THE_WHOLE_INTERFACE_SIZE": "Gesamte Oberfläche verkleinern oder vergrößern.", + "DEFAULT_LOG_CATEGORY": "Standard Log Kategorie", + "DEFAULT_LOG_VIEW": "Standard Log view", + "DEFAULT_RTORRENT_PATH": "Standard-rTorrent-Pfad", + "DEGRADED": "eingeschränkt", + "DELETE": "Löschen", + "DELETE_REMOVE": "Löschen - Entfernen", + "DESKTOP": "Desktop", + "DETAILS_WILL_APPEAR_AFTER_THE_FIRST_SUCCESSFUL_RESPONSE": "Details erscheinen nach der ersten erfolgreichen Antwort.", + "DIAGNOSTICS": "Diagnose", + "DISABLED": "Deaktiviert", + "DISK_MONITOR": "Festplattenmonitor", + "DISK_USAGE_UNAVAILABLE": "Disk usage unavailable", + "DISPLAYS_CURRENT_SPEEDS_NEXT_TO_PYTORRENT_IN_THE_TAB_TITLE": "Displays Aktuell speeds Nächste zu pyTorrent in Tab Titel.", + "DOCS_API": "Docs API", + "DOWNLOADED": "Heruntergeladen", + "DOWNLOADING": "Wird heruntergeladen", + "DOWNLOADS": "Downloads", + "DOWNLOAD_KIB_S": "Download KiB/s", + "DOWNLOAD_STARTED": "Download gestartete", + "DOWNLOAD_TORRENT": "Download .Torrent", + "DOWNLOAD_TRACKER_FAVICONS": "Tracker-Favicons laden", + "DRAG_TO_RESIZE_DETAILS_PANEL": "Drag to resize Details Panel", + "EASTER_EGG": "Easter Egg", + "EDIT": "Bearbeiten", + "EMERGENCY_CANCEL": "Notfall-Abbruch", + "EMERGENCY_CLEAN_ALL": "Emergency clean Alle", + "ENABLED": "Aktiviert", + "ENABLE_AUTOMATIC_APPLICATION_BACKUPS": "Enable Automatisch Anwendung backups", + "ENABLE_AUTOMATIC_PROFILE_BACKUPS": "Enable Automatisch Profil backups", + "ENABLE_EASTER_EGG": "Aktivieren easter egg", + "ENABLE_INCOMING_PORT_CHECK": "Prüfung des eingehenden Ports aktivieren", + "ENABLE_REVERSE_DNS_FOR_PEERS": "Reverse DNS für Peers aktivieren", + "ENGLISH": "Englisch", + "EPISODE": "Episode", + "ESC_CLEAR_SELECTION": "Esc - Löschen selection", + "ETA": "ETA", + "EVERY_N_MINUTES": "Every N Minuten", + "EVERY_X_HOURS": "Every X hours", + "EXCLUDE": "Ausschließen", + "EXCLUDE_FROM_SMART_QUEUE": "Ausschließen von Smart Queue", + "EXCLUDE_PATTERN": "Ausschließen Muster", + "EXISTING_GROUPS": "Existing Gruppen", + "EXPORT": "Export", + "EXPORT_JSON": "Export JSON", + "EXTERNAL_AUTHENTICATION_IS_ENABLED_THROUGH_EXTERNAL_PROVIDER": "External authentication is Aktiviert through {{ external_provider }}.", + "E_G_PUNKTY_KATALOGOWANIE": "e.g. Punkty katalogowanie", + "FEATURES": "Funktionen", + "FEED": "Feed", + "FEEDS_ARE_CHECKED_BY_SCHEDULE_AND_EVERY_MATCH_IS_LOGGED_PER_FEED_RULE": "Feeds sind checked by schedule und every match ist logged per feed/Regel.", + "FEEDS_RULES_AND_MATCHES": "Feeds, Regeln und Treffer", + "FEED_NAME": "Feed Name", + "FEED_URL": "Feed URL", + "FILES": "Dateien", + "FILE_OR_DIRECTORY_PATH": "Datei or Verzeichnis Pfad", + "FONT": "Schriftart", + "FOOTER": "Fußzeile", + "FORCE": "Erzwingen", + "FORCE_RECHECK": "Erzwingen Erneut prüfen", + "FRONTEND": "Frontend", + "FULL": "Full", + "GENERAL": "Allgemein", + "GENERATED_RTORRENT_CONFIG_CHANGES_WILL_APPEAR_HERE": "Generierte rTorrent Konfiguration changes will appear here.", + "GENERATE_CONFIG": "Generate Konfiguration", + "GERMAN": "Deutsch", + "GO": "Go", + "GROUPED_RTORRENT_RUNTIME_SETTINGS_WITH_INLINE_RECOMMENDATIONS_AND_COMPATIBILITY_": "Gruppierte rTorrent Runtime Einstellungen mit Inline Empfehlungen und Kompatibilität Status.", + "GROUP_NAME": "Gruppe Name", + "HASH": "Hash", + "HASHING": "Hashing", + "HEAVY_PARALLEL_JOBS": "Heavy parallel Jobs", + "HEAVY_TIMEOUT_SECONDS": "Heavy Timeout Sekunden", + "HIDE_JOB_LOGS": "Ausblenden Job Logs", + "HIDE_JOB_LOGS_BY_DEFAULT": "Ausblenden Job Logs nach Standard", + "HISTORY": "Verlauf", + "HOW_LONG_A_MATCHING_ACTIVE_TORRENT_MUST_STAY_STALLED_BEFORE_IT_CAN_BE_REPLACED": "Wie lange a matching Aktiv Torrent muss stay stalled vor it kann sein ersetzt.", + "IGNORE_MISSING_SEEDS_PEERS_FOR_STALLED_TIMER": "Ignore missing Seeds/Peers for stalled timer", + "IGNORE_SPEED_FOR_STALLED_TIMER": "Ignore Geschwindigkeit for stalled timer", + "IMPORT": "Import", + "IMPORT_JSON": "Import JSON", + "INCLUDE_PATTERN": "Einschließen Muster", + "INCOMING_CONNECTION_TEST_SEPARATE_FROM_VISUAL_PREFERENCES": "Incoming Verbindung Test, separate von visual Einstellungen.", + "INTERFACE_SCALE": "Interface-Skalierung", + "INTERVAL_MINUTES": "Intervall Minuten", + "INVERT_VISIBLE": "sichtbare umkehren", + "JOBS": "Jobs", + "JOB_DONE": "Job erledigt", + "JOB_FAILED": "Job fehlgeschlagen", + "JOB_QUEUE": "Job Warteschlange", + "JOB_SCHEDULING": "Job scheduling", + "JOB_STARTED": "Job gestartete", + "KEEP_LINES": "Keep lines", + "KEEP_SEEDING": "Keep Seeding", + "LABEL": "Label", + "LABELS": "Labels", + "LABELS_SEPARATED_BY_COMMA": "Labels separated nach comma", + "LABEL_AFTER_SHARE": "Label nach share", + "LABEL_EXISTS": "Label exists", + "LABEL_IS_MISSING": "Label ist missing", + "LABEL_NAME_OR_SEVERAL_SEPARATED_BY_COMMA": "Label Name, oder mehrere separated nach comma", + "LANGUAGE": "Sprache", + "LANGUAGE_SAVED": "Sprache Gespeichert", + "LAST_OPERATIONS": "Letzte operations", + "LICENSE": "Lizenz", + "LIGHTWEIGHT_WEB_PANEL_FOR_RTORRENT_MANAGEMENT_QUEUE_CONTROL_AND_LIVE_TORRENT_DIA": "Lightweight web Panel für rTorrent management, Warteschlange control und live Torrent Diagnose.", + "LIGHT_PARALLEL_JOBS": "Light parallel Jobs", + "LIGHT_TIMEOUT_SECONDS": "Light Timeout Sekunden", + "LIMIT_DL": "Limit DL", + "LOADING": "Lädt", + "LOADING_CLEANUP_DATA": "Lädt Bereinigung Daten...", + "LOADING_CONFIG": "Lädt Konfiguration...", + "LOADING_IMAGE_URL": "Lädt image URL", + "LOADING_JOBS": "Lädt Jobs...", + "LOADING_LOGS": "Lädt Logs...", + "LOADING_PROFILES": "Lädt Profile...", + "LOADING_STATISTICS": "Lädt Statistik...", + "LOADING_TORRENTS": "Torrents werden geladen...", + "LOADING_TORRENT_DETAILS": "Torrent-Details werden geladen...", + "LOCAL_BROWSER_TIME": "Local Browser time", + "LOCATION": "Ort", + "LOG": "Log", + "LOGS": "Logs", + "LOG_IN": "Anmelden", + "LOG_OUT": "Abmelden", + "LOG_STATISTICS": "Log Statistik", + "MAGNET_AND_TORRENT_UPLOAD_FILE_PRIORITIES_LABELS_RATIO_GROUPS_SMART_QUEUE_AUTOMA": "Magnet und Torrent Upload, Datei Prioritäten, Labels, Ratio Gruppen, Smart Queue, automation Regeln, RSS, Traffic Diagramme, Port Prüfer, system Status.", + "MAGNET_LINKS": "Magnet links", + "MANAGE_EXCEPTIONS": "Manage exceptions", + "MANAGE_OPERATION_LOG_RETENTION_WITHOUT_CHANGING_TORRENT_DATA": "Manage operation Log Aufbewahrung without changing Torrent Daten.", + "MANAGE_OPTIONAL_PYTORRENT_USERS_EMPTY_PROFILE_MEANS_ALL_PROFILES_R_O_BLOCKS_RTOR": "Manage optional pyTorrent Benutzer. Empty Profil means Alle Profile. R/O blocks rTorrent-Änderung Aktionen; Full allows sie.", + "MANUAL_CLEANUP_ONLY": "Manuell Bereinigung nur", + "MAXIMUM_HEAVY_JOBS_RUNNING_AT_ONCE_FOR_THIS_PROFILE_DEFAULT_5": "Maximum heavy Jobs running at once für diese Profil. Standard: 5.", + "MAXIMUM_QUEUED_ACTIONS_RUNNING_AT_ONCE": "Maximum queued Aktionen running at once.", + "MAXIMUM_STALLED_OVERFLOW_DOWNLOADS_SMART_QUEUE_MAY_STOP_IN_ONE_PASS": "Maximum hängende/overflow Downloads Smart Queue may Stop in eine pass.", + "MAX_MB": "Max MB", + "MAX_RATIO": "Max Ratio", + "MAX_STOPS_PER_CHECK": "Max stops per Prüfen", + "MESSAGE": "Meldung", + "MINUTES": "Minuten", + "MIN_MB": "Min MB", + "MIN_PEERS": "Min Peers", + "MIN_RATIO": "Min Ratio", + "MIN_SEEDS": "Min Seeds", + "MIN_SEED_MINUTES": "Min seed Minuten", + "MIN_SPEED_KIB_S": "Min Geschwindigkeit KiB/s", + "MOBILE": "Mobil", + "MOBILE_COLUMNS": "Mobile Spalten", + "MOBILE_FILTER_GROUPS": "Mobile Filtergruppen", + "MOBILE_SIMPLE_MODE": "Mobil/simple mode", + "MOBILE_SORT_FILTERS": "Mobile Sortierfilter", + "MODE": "Mode", + "MONITORED_PATHS": "Überwachte Pfade", + "MOVE": "Verschieben", + "MOVE_DATA": "Verschieben Daten", + "MOVE_DATA_FILES": "Verschieben Daten Dateien", + "MOVE_PATH": "Verschieben Pfad", + "MOVE_TO_PATH": "Verschieben to Pfad", + "MOVIES": "Filme", + "MOVING": "Verschieben", + "M_MOVE": "M - Verschieben", + "NAME": "Name", + "NEGATE": "Negate", + "NEWLY_QUEUE_STARTED_TORRENTS_ARE_PROTECTED_FROM_STALLED_CLEANUP_DURING_THIS_WARM": "Newly Warteschlange-started Torrents sind protected von stalled Bereinigung während diese warm-up.", + "NEW_LABEL": "Neu Label", + "NEXT_READY": "Nächste: ready", + "NEXT_SMART_QUEUE_RUN": "Nächste Smart Queue Lauf", + "NOTIFICATIONS": "Benachrichtigungen", + "NOT_LOADED": "Nicht geladen.", + "NO_CHANGES": "Keine Änderungen", + "NO_FILES_RETURNED_BY_RTORRENT": "rTorrent hat keine Dateien zurückgegeben.", + "NO_FILES_SELECTED": "Keine Dateien ausgewählt", + "NO_LABELS": "Keine Labels.", + "NO_LABELS_SELECTED": "Keine Labels ausgewählt.", + "NO_PATH_LOADED": "Keine Pfad loaded.", + "NO_PEERS_RETURNED_BY_RTORRENT": "rTorrent hat keine Peers zurückgegeben.", + "NO_RTORRENT_PROFILE_CONFIGURED": "Kein rTorrent-Profil konfiguriert.", + "NO_SAVED_LABELS": "Keine gespeicherten Labels.", + "NO_TORRENTS": "Keine Torrents.", + "NO_TORRENTS_FOR_THIS_FILTER": "Keine Torrents für diesen Filter.", + "NO_TORRENTS_SELECTED": "Keine Torrents ausgewählt", + "NO_TORRENT_SELECTED": "Kein Torrent ausgewählt", + "NO_TRACKERS_RETURNED_BY_RTORRENT": "rTorrent hat keine Tracker zurückgegeben.", + "OFF": "Off", + "OFFLINE": "offline", + "ONE_PLACE_TO_CLEAR_LOGS_AND_ACTIVE_PROFILE_CACHES_PENDING_RUNNING_JOBS_RULES_SET": "Eine place zu Löschen Logs und Aktiv Profil caches. Ausstehende/running Jobs, Regeln, Einstellungen und Torrents sind preserved.", + "ONE_TRACKER_URL_PER_LINE": "One Tracker URL per line", + "ONLINE": "online", + "ONLY_SELECTED": "Nur ausgewählt", + "OPEN_DOWNLOAD_PLANNER": "Öffnen Download planner", + "OPEN_RTORRENT_FILES_MAX_OPEN_FILES": "Öffnen rTorrent Dateien / max Öffnen Dateien", + "OPEN_RTORRENT_HTTP_CONNECTIONS_MAX_HTTP_CONNECTIONS": "Öffnen rTorrent HTTP connections / max HTTP connections", + "OPEN_RTORRENT_SOCKETS": "Öffnen rTorrent sockets", + "OPEN_SOURCE": "Open Source", + "OPEN_THIS_TAB_TO_LOAD_DIAGNOSTICS": "Öffnen diese Tab zu laden Diagnose.", + "OPEN_THIS_TAB_TO_LOAD_STATISTICS": "Öffnen diese Tab zu laden Statistik.", + "OPERATION_LOG_RETENTION": "Operation Log Aufbewahrung", + "OPTIONAL": "optional", + "OPTIONAL_PEER_TABLE_HELPERS": "Optional peer table helpers.", + "OPTIONAL_PRIVATE_SOURCE_TAG": "optional Privater Quelle tag", + "OPTIONAL_VISUAL_EASTER_EGG_FOR_LOADING_STATES_AND_OCCASIONAL_BUTTON_CLICKS_DISAB": "Optional visual easter egg für Lädt Zustände und gelegentliche Schaltfläche Klicks. Deaktiviert by Standard.", + "PARALLEL_JOBS": "Parallel Jobs", + "PARENT_DIRECTORY": "Übergeordnet Verzeichnis", + "PARTIAL_DETAILS_LOADED": "Details teilweise geladen", + "PASSWORD": "Passwort", + "PASSWORD_NEW_PASSWORD": "Passwort / Neu Passwort", + "PASTE_ONE_MAGNET_URI_PER_LINE": "Paste eine magnet URI per line.", + "PATH": "Pfad", + "PATH_CONTAINS": "Pfad contains", + "PATH_TEXT": "Pfad Text", + "PATH_USED_FOR_SELECTED_MODE": "Pfad für ausgewählten Modus", + "PAUSE": "Pause", + "PAUSED": "Pausiert", + "PEAK_S": "Peak S", + "PEAK_SPEED_UNAVAILABLE": "Peak Geschwindigkeit unavailable", + "PEERS": "Peers", + "PEERS_AUTO_REFRESH": "Peers auto Aktualisieren", + "PENDING_JOBS_OLDER_THAN_THIS_ARE_RESUBMITTED_IF_NO_WORKER_IS_CURRENTLY_HANDLING_": "Ausstehende Jobs älter als diese sind erneut eingereicht wenn Keine Worker ist derzeit bearbeitet sie. Standard: 900 Sekunden.", + "PENDING_RUNNING_DONE_FAILED_RETRY_AND_CANCEL_HISTORY": "Ausstehende, running, erledigt, fehlgeschlagen, Wiederholen und Abbrechen Verlauf.", + "PENDING_TIMEOUT_SECONDS": "Pending Timeout Sekunden", + "PIECE_SIZE": "Piece Größe", + "PLANNER": "Planner", + "POLISH": "Polnisch", + "PORT": "Port", + "PORT_CHECKER": "Portprüfung", + "PORT_CHECK_DISABLED": "Port Prüfen Deaktiviert", + "PORT_UNKNOWN": "Port - unknown", + "POST_CHECK": "Nachprüfung", + "PREFERENCES": "Einstellungen", + "PREFERENCES_SAVED": "Einstellungen gespeichert", + "PRIORITY": "Priorität", + "PRIVATE_TORRENT": "Privater Torrent", + "PROFILE_BACKUP": "Profil Backup", + "PROFILE_BACKUP_NAME": "Profil Backup Name", + "PROFILE_BACKUP_RESTORES_ONLY_THE_ACTIVE_PROFILE_CONTEXT_APPLICATION_BACKUP_RESTO": "Profil Backup restores nur Aktiv Profil Kontext. Anwendung Backup restores global Anwendung Daten und ist verfügbar nur zu Administratoren.", + "PROFILE_NAME": "Profil Name", + "PROFILE_SCOPED_LOG_COUNTS_AND_CLEANUP_OVERVIEW": "Profil-scoped Log Anzahlen und Bereinigung Übersicht.", + "PROGRESS": "Fortschritt", + "PROGRESS_IS_AT_LEAST": "Fortschritt is at least %", + "PROGRESS_IS_AT_MOST": "Fortschritt is at most %", + "PROGRESS_SOURCE": "Fortschrittsquelle", + "PROTECT_ACTIVE_COUNT_BELOW_CAP": "Protect Aktiv count below cap", + "PYTORRENT_EXPECTS_TRUSTED_REVERSE_PROXY_IDENTITY_HEADERS_IF_YOU_ARE_ALREADY_SIGN": "pyTorrent expects trusted reverse-proxy identity headers. Wenn Sie sind already signed in, Prüfen provider headers und Benutzer mapping.", + "PYTORRENT_LOGIN": "pyTorrent login", + "PYTORRENT_STATUS": "pyTorrent Status", + "P_PAUSE": "P - Pause", + "QUALITY": "Qualität", + "QUEUE_REFILL_DURING_COOLDOWN": "Warteschlange refill during Cooldown", + "RANDOM_CLICK_IMAGE_URL": "Random click image URL", + "RATIO": "Ratio", + "RATIO_GROUP": "Ratio-Gruppe", + "RATIO_GROUPS": "Ratio Gruppen", + "RATIO_IS_AT_LEAST": "Ratio ist at least", + "RATIO_RULES": "Ratio Regeln", + "REANNOUNCE": "Reannounce", + "RECHECK": "Erneut prüfen", + "RECHECK_AFTER_MOVE": "Erneut prüfen nach Verschieben", + "RECOMMENDED_COLUMNS": "Empfohlene Spalten", + "RECOMMENDED_COLUMNS_APPLIED": "Empfohlene Spalten angewendet", + "RECONNECTING": "erneut verbinden", + "REFERENCE_VALUE_IS_KEPT_FROM_THE_FIRST_OVERRIDE_SAVE_LATER_SAVES_ADD_OR_CLEAR_DI": "Reference Wert ist kept von Erste override Speichern. Later saves Hinzufügen oder Löschen differences ohne replacing original reference.", + "REFRESH": "Aktualisieren", + "REFRESH_NOW": "Aktualisieren now", + "REGEX_TEXT": "Regex / Text", + "RELOAD": "Reload", + "REMOTE_LOCATION": "Remote Ort", + "REMOVE": "Entfernen", + "REMOVE_DATA": "Entfernen Daten", + "REMOVE_LABEL": "Entfernen Label", + "REMOVE_SELECTED_TORRENTS": "Entfernen ausgewählt Torrents", + "REMOVE_WITH_DATA": "Entfernen mit Daten", + "REPOSITORY": "Repository", + "RESET": "Zurücksetzen", + "RESET_UI_SETTINGS": "Zurücksetzen UI Einstellungen", + "RESET_VIEW_DEFAULTS": "Zurücksetzen view defaults", + "RESIZE_TORRENT_DETAILS_PANEL": "Resize Torrent Details Panel", + "RESOLVE_PEER_IP_TO_REVERSE_DNS_HOST": "Resolve peer IP zu reverse DNS host", + "RESUME": "Fortsetzen", + "RETENTION_DAYS": "Aufbewahrung Tage", + "RETENTION_MODE": "Aufbewahrung mode", + "RETRY": "Wiederholen", + "REVERSE_DNS": "Reverse DNS", + "RSS_DOWNLOADER": "RSS downloader", + "RTORRENT": "rTorrent", + "RTORRENTS": "rTorrents", + "RTORRENT_CONFIG": "rTorrent Konfiguration", + "RTORRENT_INCOMING_PORT": "rTorrent incoming Port", + "RTORRENT_IS_STARTING_OR_NOT_RESPONDING_YET": "rTorrent startet oder antwortet noch nicht.", + "RTORRENT_PROFILES": "rTorrent Profile", + "RULE": "Regel", + "RULES": "Regeln", + "RULES_ARE_CHECKED_AUTOMATICALLY_EVERY_5_MINUTES_A_TORRENT_USES_THE_GROUP_STORED_": "Regeln sind geprüft automatically every 5 Minuten. Torrent uses Gruppe stored in its rTorrent Benutzerdefiniert Ratio field.", + "RULE_NAME": "Regel Name", + "RUNTIME": "Runtime", + "RUN_A_PROFILE_TEST_TO_SHOW_DIAGNOSTICS": "Run a Profil Test to Anzeigen Diagnose.", + "RUN_SMART_QUEUE_DURING_POLLING_STOPPED_TORRENTS_ARE_MANAGED_PAUSED_TORRENTS_STAY": "Lauf Smart Queue während polling. Gestoppt Torrents sind verwaltet; Pausiert Torrents stay Benutzer-controlled.", + "R_RESUME": "R - Fortsetzen", + "SAVE": "Speichern", + "SAVED_LABELS": "Gespeichert Labels", + "SAVE_COLUMNS": "Speichern Spalten", + "SAVE_CONFIG": "Speichern Konfiguration", + "SAVE_EASTER_EGG": "Speichern easter egg", + "SAVE_EXCEPTIONS": "Speichern exceptions", + "SAVE_FEED": "Speichern feed", + "SAVE_FOOTER": "Speichern Fußzeile", + "SAVE_GROUP": "Speichern Gruppe", + "SAVE_JOB_SETTINGS": "Speichern Job Einstellungen", + "SAVE_LIMITS": "Speichern Limits", + "SAVE_LOCATION": "Speichern Ort", + "SAVE_LOG_VIEW": "Speichern Log view", + "SAVE_PATH": "Speichern Pfad", + "SAVE_PREFERENCES": "Einstellungen speichern", + "SAVE_RETENTION": "Speichern Aufbewahrung", + "SAVE_RULE": "Speichern Regel", + "SAVE_SCHEDULE": "Speichern schedule", + "SAVE_USER": "Speichern Benutzer", + "SCGI_URL": "SCGI URL", + "SEARCH_LOGS": "Suchen Logs...", + "SEARCH_TORRENTS": "Torrents suchen...", + "SEARCH_TORRENTS_TO_EXCLUDE": "Suchen Torrents to Ausschließen...", + "SEASON": "Staffel", + "SECONDS_TO_WAIT_FOR_RTORRENT_RESPONSE": "Sekunden to wait for rTorrent response.", + "SEEDING": "Seeding", + "SEEDS": "Seeds", + "SEEDS_ARE_LOW_FOR_TIME": "Seeds sind niedrig für Zeit", + "SEED_MINUTES": "Seed Minuten", + "SELECT": "Auswählen", + "SELECTED": "ausgewählt", + "SELECTED_LABELS": "Ausgewählt Labels", + "SELECTED_MONITORED_PATH": "Ausgewählter überwachter Pfad", + "SELECTED_TORRENTS_WILL_BE_REMOVED": "ausgewählt Torrents will be removed.", + "SELECT_A_MONITORED_PATH_FIRST": "Zuerst einen überwachten Pfad auswählen.", + "SELECT_A_TORRENT": "Auswählen a Torrent.", + "SELECT_ONE_OR_MORE_TORRENT_FILES": "Auswählen one or more .Torrent Dateien.", + "SELECT_PATH": "Auswählen Pfad", + "SELECT_TORRENTS_THAT_SMART_QUEUE_SHOULD_IGNORE_USE_SEARCH_TO_FILTER_BY_NAME_LABE": "Auswählen Torrents dass Smart Queue soll ignorieren. Verwenden Suchen zu filtern nach Name, Label, Status oder Hash.", + "SELECT_VISIBLE": "sichtbare auswählen", + "SEPARATE_SLOT_POOL_FOR_LIGHTWEIGHT_CONTROL_JOBS_SO_THEY_DO_NOT_WAIT_BEHIND_HEAVY": "Separate Slot Pool für lightweight control Jobs so they do nicht warten hinter heavy IO Arbeit. Standard: 4.", + "SETTINGS": "Einstellungen", + "SET_LABEL": "Set Label...", + "SET_LABELS": "Set Labels", + "SET_RATIO_GROUP": "Set Ratio Gruppe...", + "SHARE_AFTER_CREATING": "Share nach creating", + "SHORTCUTS": "Tastenkürzel", + "SHOWN": "Shown", + "SHOWN_IN_LOADING_STATES_INSTEAD_OF_THE_STANDARD_SPINNER": "Shown in Lädt Zustände statt Standard Spinner.", + "SHOWS_TRACKER_ICONS_IN_THE_SIDEBAR_TRACKER_FILTER_WHEN_AVAILABLE": "Zeigt Tracker Symbole in Seitenleiste Tracker filtern when verfügbar.", + "SHOW_COMBINED_USAGE_SINGLE_PATH_SELECTION_IS_DISABLED_IN_THIS_MODE": "Anzeigen kombinierte usage. Einzelne Pfad selection ist Deaktiviert in diese mode.", + "SHOW_DL_UP_IN_BROWSER_TITLE": "DL/UP im Browser-Titel anzeigen", + "SHOW_SMART_QUEUE_AUTOMATIC_RUN_MESSAGES": "Anzeigen Smart Queue Automatisch Lauf Meldungen.", + "SHOW_TOASTS_CREATED_BY_AUTOMATION_RUNS": "Anzeigen toasts created by automation runs.", + "SIGN_IN": "Anmelden", + "SIZE": "Größe", + "SKIP_ACTIVE_UPLOAD": "Skip Aktiv Upload", + "SKIP_PRIVATE_TORRENTS": "Skip Privater Torrents", + "SMART_FILTERS": "Smart-Filter", + "SMART_QUEUE": "Smart Queue", + "SMART_QUEUE_EXCEPTIONS": "Smart Queue exceptions", + "SMART_QUEUE_KEEPS_ONLY_THIS_MANY_ACTIVE_DOWNLOADS_OVERFLOW_IS_STOPPED": "Smart Queue keeps nur diese many Aktiv Downloads; overflow ist Gestoppt.", + "SMART_QUEUE_TOASTS": "Smart Queue toasts", + "SOCKETS": "Sockets", + "SOURCE": "Quelle", + "SPACE_START": "Space - Start", + "SPEED": "Geschwindigkeit", + "SPEED_LIMITS": "Geschwindigkeit Limits", + "SPEED_TREND": "Geschwindigkeit trend", + "STALLED_AFTER_SECONDS": "Stalled nach Sekunden", + "START": "Starten", + "START_AFTER_ADD": "Start nach Hinzufügen", + "START_GRACE_SECONDS": "Start grace Sekunden", + "STATE": "Zustand", + "STATUS": "Status", + "STATUS_EQUALS": "Status equals", + "STOP": "Stoppen", + "STOPPED": "Gestoppt", + "S_STOP": "S - Stop", + "TARGET_ACTIVE_DOWNLOADS": "Ziel Aktiv Downloads", + "TARGET_PATH": "Ziel Pfad", + "TEST_RULE": "Test Regel", + "TEST_SCGI": "Test SCGI", + "THEME_TYPOGRAPHY_AND_INTERFACE_SCALE": "Theme, Typografie und Interface-Skalierung.", + "THE_FOOTER_TOOLTIP_ALWAYS_SHOWS_DETAILS_FOR_AVAILABLE_PATHS_THIS_SETTING_ONLY_DE": "Fußzeile Tooltip immer zeigt Details für verfügbar Pfade; diese Einstellung nur entscheidet welcher Wert steuert sichtbar Fortschritt Leiste.", + "TIMEOUT": "Timeout", + "TOAST_NOTIFICATIONS_FROM_AUTOMATIC_SYSTEMS": "Toast Benachrichtigungen von Automatisch systems.", + "TOOLS": "Werkzeuge", + "TOOLS_RTORRENTS": "Werkzeuge & rTorrents", + "TOOLS_SECTIONS": "Werkzeuge sections", + "TORRENT_ADDED": "Torrent added", + "TORRENT_COMPLETED": "Torrent Abgeschlossen", + "TORRENT_DETAILS": "Torrent-Details", + "TORRENT_FILES": "Torrent Dateien", + "TORRENT_FILTERS": "Torrent filters", + "TORRENT_PROPERTIES": "Torrent properties", + "TORRENT_REMOVED": "Torrent removed", + "TORRENT_STATISTICS": "Torrent Statistik", + "TORRENT_STATS": "Torrent stats", + "TOTAL_DL_UP": "Total DL/UP", + "TO_DOWNLOAD": "Zu laden", + "TRACKERS": "Tracker", + "TRACKER_ICONS": "Tracker-Icons", + "TRANSFER": "Transfer", + "TRANSFERRED_DATA": "Transferred Daten", + "TRANSFER_HISTORY": "Transfer Verlauf", + "UNDEFINED": "undefined", + "UNLIMITED": "Unlimited", + "UPLOADED": "Hochgeladen", + "UPLOADS": "Uploads", + "UPLOAD_KIB_S": "Upload KiB/s", + "USER": "Benutzer", + "USERS": "Benutzer", + "USES_A_LIGHTWEIGHT_BUILT_IN_RESOLVER_WITH_CACHE_HOSTNAMES_APPEAR_ONLY_IN_THE_PEE": "Uses lightweight built-in Resolver mit Cache. Hostnamen appear nur in Peers Tab.", + "USES_LOWER_ROWS_AND_SMALLER_LIST_ELEMENTS_ON_DESKTOP_AND_MOBILE_SO_MORE_TORRENTS": "Uses niedrigere Zeilen und smaller Liste elements on Desktop und Mobil so more Torrents passen on Bildschirm.", + "USES_YOUGETSIGNAL_FIRST_MANUAL_CHECK_BYPASSES_THE_6H_CACHE": "Uses YouGetSignal Erste. Manuell Prüfen bypasses 6h Cache.", + "USE_ONE_CUSTOM_PATH_BELOW_AS_THE_FOOTER_PROGRESS_VALUE": "Verwenden eine Benutzerdefiniert Pfad below als Fußzeile Fortschritt Wert.", + "USE_SELECTED": "Verwenden ausgewählt", + "USE_THE_MAIN_DIRECTORY_FROM_THE_ACTIVE_RTORRENT_PROFILE": "Verwenden main Verzeichnis von Aktiv rTorrent Profil.", + "VIEW_PREFERENCES_RESET": "Ansichtseinstellungen zurückgesetzt", + "VIEW_STATE_IS_SAVED_AUTOMATICALLY_IN_THE_DATABASE_CURRENT_TORRENT_FILTER_LAST_SO": "View Status ist Gespeichert automatically in database: Aktuell Torrent filtern, Letzte sort column und direction, sichtbar Spalten, und Details Panel height.", + "VISIBLE_NAME_USED_IN_THE_PROFILE_SELECTOR": "Sichtbar Name used in Profil selector.", + "VISUAL_HELPER_FOR_TRACKER_FILTERS_IN_THE_SIDEBAR": "Visual Helfer für Tracker filters in Seitenleiste.", + "WAITING_FOR_DATA": "Warten for Daten.", + "WAITING_FOR_TORRENT_DATA_FROM_THE_ACTIVE_PROFILE": "Warte auf Torrent-Daten vom aktiven Profil.", + "WATCHDOG_MARKS_A_LIGHT_JOB_AS_FAILED_AFTER_THIS_TIME_DEFAULT_300_SECONDS": "Watchdog marks light Job als fehlgeschlagen nach diese Zeit. Standard: 300 Sekunden.", + "WATCHDOG_TIMEOUT_FOR_MOVE_REMOVE_ADD_JOBS_DEFAULT_7200_SECONDS": "Watchdog Timeout für Verschieben/Entfernen/Hinzufügen Jobs. Standard: 7200 Sekunden.", + "WHEN_DISABLED_THE_APPLICATION_USES_THE_NORMAL_PRODUCTION_UI": "When Deaktiviert, Anwendung uses normale Produktions UI.", + "WHEN_ENABLED_LOW_SPEED_IS_NOT_REQUIRED_WITH_SOURCE_AND_SPEED_IGNORES_ENABLED_ONL": "When Aktiviert, niedrig Geschwindigkeit ist nicht required. Mit Quelle und Geschwindigkeit ignores Aktiviert, nur Hängende nach Sekunden entscheidet.", + "WHEN_ENABLED_SMART_QUEUE_DOES_NOT_USE_SEED_PEER_COUNT_AS_A_STALLED_CRITERION": "When Aktiviert, Smart Queue does nicht verwenden seed/peer count als hängende Kriterium.", + "WITH_ERROR": "Mit Fehler", + "WORKING": "Arbeite...", + "FRENCH": "Französisch", + "CZECH": "Tschechisch", + "SPANISH": "Spanisch", + "NORWEGIAN": "Norwegisch", + "RUSSIAN": "Russisch" + } +} diff --git a/pytorrent/static/i18n/en_US.json b/pytorrent/static/i18n/en_US.json new file mode 100644 index 0000000..9af808b --- /dev/null +++ b/pytorrent/static/i18n/en_US.json @@ -0,0 +1,566 @@ +{ + "meta": { + "locale": "en_US", + "label": "English", + "flag": "us" + }, + "translations": { + "0_MEANS_ONLY_SEED_THRESHOLD_IS_REQUIRED": "0 means only seed threshold is required.", + "0_MEANS_UNLIMITED_SLIDERS_USE_MBIT_S_AND_SAVE_THROUGH_THE_EXISTING_SPEED_LIMITS_": "0 means unlimited. Sliders use Mbit/s and save through the existing speed limits API.", + "0_SELECTED": "0 selected", + "ABOUT_PYTORRENT": "About pyTorrent", + "ACTION": "Action", + "ACTIVE": "Active", + "ACTIVE_RTORRENT_DOWNLOADS_MAX_GLOBAL_DOWNLOADS": "Active rTorrent downloads / max global downloads", + "ACTIVE_RTORRENT_UPLOADS_MAX_GLOBAL_UPLOADS": "Active rTorrent uploads / max global uploads", + "ADD": "Add", + "ADDED": "Added", + "ADDS_REMOVALS_COMPLETIONS_AND_QUEUED_OPERATION_RESULTS": "Adds, removals, completions and queued operation results.", + "ADD_ACTION": "Add action", + "ADD_CONDITION": "Add condition", + "ADD_CREATE_TORRENT": "Add / create torrent", + "ADD_FIRST_LABEL_ABOVE": "Add first label above.", + "ADD_LABEL": "Add label", + "ADD_MAGNET_LINK": "Add magnet link", + "ADD_NEW_LABEL": "Add new label", + "ADD_OR_EDIT_GROUP": "Add or edit group", + "ADD_PATH": "Add path", + "ADD_PROFILE": "Add profile", + "ADD_RTORRENT_PROFILE": "Add rTorrent profile", + "ADD_THE_FIRST_RTORRENT_PROFILE_TO_START_LOADING_TORRENTS": "Add the first rTorrent profile to start loading torrents.", + "ADD_TORRENT": "Add torrent", + "ADD_TORRENT_FILE": "Add torrent file", + "ADMIN": "admin", + "ADMIN_ONLY_FULL_APPLICATION_BACKUP_RESTORE_CAN_REPLACE_USERS_PERMISSIONS_PROFILE": "Admin-only full application backup. Restore can replace users, permissions, profiles and global application settings.", + "AGGREGATE_ALL_PATHS": "Aggregate all paths", + "ALL": "All", + "ALL_NON_JOB_TYPES": "All non-job types", + "ALL_PROFILES": "All profiles", + "ALL_TYPES": "All types", + "ANNOUNCE": "Announce", + "API_DOCS": "API docs", + "APPEARANCE": "Appearance", + "APPEARANCE_PREFERENCES_SAVED": "Appearance preferences saved", + "APPEARS_NEAR_CLICKED_BUTTONS_ONLY_SOMETIMES": "Appears near clicked buttons only sometimes.", + "APPLICATION_BACKUP": "Application backup", + "APPLICATION_BACKUP_NAME": "Application backup name", + "APPLY": "Apply", + "APPLY_RETENTION_NOW": "Apply retention now", + "APPLY_SAVED_CHANGES_60S_AFTER_PYTORRENT_START": "Apply saved changes 60s after pyTorrent start", + "APP_STATUS": "App status", + "AUTHENTICATION_IS_ENABLED_FOR_THIS_PYTORRENT_INSTANCE": "Authentication is enabled for this pyTorrent instance.", + "AUTHOR": "Author", + "AUTOMATIC": "Automatic", + "AUTOMATIC_KEEPS_THE_CURRENT_POLLER_CADENCE_CUSTOM_RUNS_ONLY_AFTER_THE_SELECTED_N": "Automatic keeps the current poller cadence. Custom runs only after the selected number of minutes. Off disables refill completely.", + "AUTOMATIC_QUEUE_BALANCING_FOR_SLOW_OR_STALLED_DOWNLOADS": "Automatic queue balancing for slow or stalled downloads.", + "AUTOMATIC_RUNS_USE_THE_COOLDOWN_BELOW_MANUAL_CHECK_NOW_STILL_RUNS_IMMEDIATELY": "Automatic runs use the cooldown below. Manual Check now still runs immediately.", + "AUTOMATIONS": "Automations", + "AUTOMATIONS_RULES": "Automations / rules", + "AUTOMATION_TOASTS": "Automation toasts", + "AUTO_STOP_WHEN_IDLE": "Auto-stop when idle", + "BACKEND": "Backend", + "BACKUP": "Backup", + "BACKUP_RESTORE": "Backup / restore", + "BACK_TO_DASHBOARD": "Back to dashboard", + "BOOTSTRAP_THEME": "Bootstrap theme", + "BROWSER": "Browser", + "BROWSER_TITLE": "Browser title", + "BUILD_A_RULE_AS_CONDITIONS_FIRST_THEN_ORDERED_ACTIONS_MATCHING_TORRENTS_ARE_HAND": "Build a rule as: conditions first, then ordered actions. Matching torrents are handled as one batch and the cooldown is applied to the whole rule.", + "BUSY": "busy", + "BY_DAYS": "By days", + "BY_LINE_COUNT": "By line count", + "CACHED_METADATA_SUMMARY_FILE_METADATA_IS_REFRESHED_EVERY_15_MINUTES_A_FEW_MINUTE": "Cached metadata summary. File metadata is refreshed every 15 minutes, a few minutes after startup, or manually.", + "CANCEL": "Cancel", + "CANCEL_EDIT": "Cancel edit", + "CATEGORY": "Category", + "CHANGES_APPLY_IMMEDIATELY_WHERE_POSSIBLE_INITIAL_STARTUP_LOADER_USES_THEM_AFTER_": "Changes apply immediately where possible; initial startup loader uses them after reload.", + "CHANGE_RTORRENT": "Change rTorrent", + "CHANGE_THEME": "Change theme", + "CHANGING_RTORRENT_RELOADS_THE_LIVE_TORRENT_SNAPSHOT": "Changing rTorrent reloads the live torrent snapshot.", + "CHECKING": "Checking", + "CHECK_NOW": "Check now", + "CHECK_PORT_NOW": "Check port now", + "CHECK_THIS_IF_YOU_WANT_TO_CONNECT_TO_A_REMOTE_RTORRENT_INSTANCE_INSTEAD_OF_LOCAL": "Check this if you want to connect to a remote rTorrent instance instead of localhost.", + "CHOOSE_COLUMNS_VISIBLE_IN_THE_TORRENT_LIST": "Choose columns visible in the torrent list.", + "CHOOSE_FILES": "Choose files", + "CHOOSE_RTORRENT": "Choose rTorrent", + "CHOOSE_TORRENTS_IGNORED_BY_SMART_QUEUE_EXISTING_BEHAVIOR_STAYS_UNCHANGED_FOR_ALL": "Choose torrents ignored by Smart Queue. Existing behavior stays unchanged for all non-excluded torrents.", + "CHOOSE_WHAT_THE_FOOTER_DISK_BAR_SHOULD_REPRESENT_AND_ADD_EXTRA_STORAGE_PATHS": "Choose what the footer disk bar should represent and add extra storage paths.", + "CHOOSE_WHICH_STATUS_ITEMS_ARE_VISIBLE_IN_THE_BOTTOM_BAR": "Choose which status items are visible in the bottom bar.", + "CHUNKS": "Chunks", + "CLEANUP": "Cleanup", + "CLEANUP_RETENTION": "Cleanup / retention", + "CLEAR": "Clear", + "CLEAR_CURRENT_FILTER": "Clear current filter", + "CLEAR_FINISHED": "Clear finished", + "CLEAR_LABELS": "Clear labels", + "CLEAR_SELECTION": "clear selection", + "CLEAR_VISIBLE": "Clear visible", + "CLOSE": "Close", + "COLUMNS": "Columns", + "COLUMNS_SAVED": "Columns saved", + "COMMENT": "Comment", + "COMPACT_TORRENT_LIST": "Compact torrent list", + "COMPLETE": "Complete", + "COMPLETED": "Completed", + "CONFIGURED_RTORRENTS": "Configured rTorrents", + "CONNECTING_TO_RTORRENT_AND_PREPARING_DATA": "Connecting to rTorrent and preparing data.", + "CONNECTION_ADDRESS_IN_SCGI_HOST_PORT_RPC2_FORMAT": "Connection address in scgi://host:port/RPC2 format.", + "CONTROLS_THE_DEFAULT_CATEGORY_AND_JOB_LOG_VISIBILITY_USED_BY_THE_LOGS_MODAL": "Controls the default category and job log visibility used by the Logs modal.", + "CONTROLS_WHAT_IS_SHOWN_IN_THE_BROWSER_TAB": "Controls what is shown in the browser tab.", + "COOLDOWN_MINUTES": "Cooldown minutes", + "COPY": "Copy", + "COPY_HASH": "Copy hash", + "COPY_NAME": "Copy name", + "COPY_PATH": "Copy path", + "CPU_RAM_USAGE": "CPU / RAM usage", + "CREATE": "Create", + "CREATES_AND_RESTORES_SETTINGS_FOR_THE_CURRENTLY_SELECTED_PROFILE_USER_SCOPED_PRE": "Creates and restores settings for the currently selected profile. User-scoped preferences are remapped to the current user where needed.", + "CREATE_APPLICATION_BACKUP": "Create application backup", + "CREATE_ONE_RTORRENT_PROFILE_AT_A_TIME_MOVE_REMOVE_QUEUES_KEEP_THEIR_ORDER_FOR_EA": "Create one rTorrent profile at a time. Move/remove queues keep their order for each profile.", + "CREATE_PROFILE_BACKUP": "Create profile backup", + "CREATE_REUSABLE_LABELS_AND_REMOVE_LABELS_THAT_ARE_NO_LONGER_NEEDED": "Create reusable labels and remove labels that are no longer needed.", + "CREATE_TORRENT": "Create torrent", + "CTRL_A_SELECT_VISIBLE": "Ctrl+A - select visible", + "CTRL_I_INVERT_VISIBLE": "Ctrl+I - invert visible", + "CTRL_O_ADD": "Ctrl+O - add", + "CTRL_S_DOWNLOAD_TORRENT": "Ctrl+S - download .torrent", + "CURRENT_TRANSFER_SPEED": "Current transfer speed", + "CUSTOM_DOWNLOAD": "Custom download", + "CUSTOM_UPLOAD": "Custom upload", + "DAYS_AND_LINE_COUNT": "Days and line count", + "DECREASE_OR_INCREASE_THE_WHOLE_INTERFACE_SIZE": "Decrease or increase the whole interface size.", + "DEFAULT_LOG_CATEGORY": "Default log category", + "DEFAULT_LOG_VIEW": "Default log view", + "DEFAULT_RTORRENT_PATH": "Default rTorrent path", + "DEGRADED": "degraded", + "DELETE": "Delete", + "DELETE_REMOVE": "Delete - remove", + "DESKTOP": "Desktop", + "DETAILS_WILL_APPEAR_AFTER_THE_FIRST_SUCCESSFUL_RESPONSE": "Details will appear after the first successful response.", + "DIAGNOSTICS": "Diagnostics", + "DISABLED": "disabled", + "DISK_MONITOR": "Disk monitor", + "DISK_USAGE_UNAVAILABLE": "Disk usage unavailable", + "DISPLAYS_CURRENT_SPEEDS_NEXT_TO_PYTORRENT_IN_THE_TAB_TITLE": "Displays current speeds next to pyTorrent in the tab title.", + "DOCS_API": "Docs API", + "DOWNLOADED": "Downloaded", + "DOWNLOADING": "Downloading", + "DOWNLOADS": "Downloads", + "DOWNLOAD_KIB_S": "Download KiB/s", + "DOWNLOAD_STARTED": "Download started", + "DOWNLOAD_TORRENT": "Download .torrent", + "DOWNLOAD_TRACKER_FAVICONS": "Download tracker favicons", + "DRAG_TO_RESIZE_DETAILS_PANEL": "Drag to resize details panel", + "EASTER_EGG": "Easter egg", + "EDIT": "Edit", + "EMERGENCY_CANCEL": "Emergency cancel", + "EMERGENCY_CLEAN_ALL": "Emergency clean all", + "ENABLED": "Enabled", + "ENABLE_AUTOMATIC_APPLICATION_BACKUPS": "Enable automatic application backups", + "ENABLE_AUTOMATIC_PROFILE_BACKUPS": "Enable automatic profile backups", + "ENABLE_EASTER_EGG": "Enable easter egg", + "ENABLE_INCOMING_PORT_CHECK": "Enable incoming port check", + "ENABLE_REVERSE_DNS_FOR_PEERS": "Enable reverse DNS for peers", + "ENGLISH": "English", + "EPISODE": "Episode", + "ESC_CLEAR_SELECTION": "Esc - clear selection", + "ETA": "ETA", + "EVERY_N_MINUTES": "Every N minutes", + "EVERY_X_HOURS": "Every X hours", + "EXCLUDE": "Exclude", + "EXCLUDE_FROM_SMART_QUEUE": "Exclude from Smart Queue", + "EXCLUDE_PATTERN": "Exclude pattern", + "EXISTING_GROUPS": "Existing groups", + "EXPORT": "Export", + "EXPORT_JSON": "Export JSON", + "EXTERNAL_AUTHENTICATION_IS_ENABLED_THROUGH_EXTERNAL_PROVIDER": "External authentication is enabled through {{ external_provider }}.", + "E_G_PUNKTY_KATALOGOWANIE": "e.g. Punkty katalogowanie", + "FEATURES": "Features", + "FEED": "Feed", + "FEEDS_ARE_CHECKED_BY_SCHEDULE_AND_EVERY_MATCH_IS_LOGGED_PER_FEED_RULE": "Feeds are checked by schedule and every match is logged per feed/rule.", + "FEEDS_RULES_AND_MATCHES": "Feeds, rules and matches", + "FEED_NAME": "Feed name", + "FEED_URL": "Feed URL", + "FILES": "Files", + "FILE_OR_DIRECTORY_PATH": "File or directory path", + "FONT": "Font", + "FOOTER": "Footer", + "FORCE": "Force", + "FORCE_RECHECK": "Force recheck", + "FRONTEND": "Frontend", + "FULL": "Full", + "GENERAL": "General", + "GENERATED_RTORRENT_CONFIG_CHANGES_WILL_APPEAR_HERE": "Generated rTorrent config changes will appear here.", + "GENERATE_CONFIG": "Generate config", + "GERMAN": "German", + "GO": "Go", + "GROUPED_RTORRENT_RUNTIME_SETTINGS_WITH_INLINE_RECOMMENDATIONS_AND_COMPATIBILITY_": "Grouped rTorrent runtime settings with inline recommendations and compatibility status.", + "GROUP_NAME": "Group name", + "HASH": "Hash", + "HASHING": "Hashing", + "HEAVY_PARALLEL_JOBS": "Heavy parallel jobs", + "HEAVY_TIMEOUT_SECONDS": "Heavy timeout seconds", + "HIDE_JOB_LOGS": "Hide job logs", + "HIDE_JOB_LOGS_BY_DEFAULT": "Hide job logs by default", + "HISTORY": "History", + "HOW_LONG_A_MATCHING_ACTIVE_TORRENT_MUST_STAY_STALLED_BEFORE_IT_CAN_BE_REPLACED": "How long a matching active torrent must stay stalled before it can be replaced.", + "IGNORE_MISSING_SEEDS_PEERS_FOR_STALLED_TIMER": "Ignore missing seeds/peers for stalled timer", + "IGNORE_SPEED_FOR_STALLED_TIMER": "Ignore speed for stalled timer", + "IMPORT": "Import", + "IMPORT_JSON": "Import JSON", + "INCLUDE_PATTERN": "Include pattern", + "INCOMING_CONNECTION_TEST_SEPARATE_FROM_VISUAL_PREFERENCES": "Incoming connection test, separate from visual preferences.", + "INTERFACE_SCALE": "Interface scale", + "INTERVAL_MINUTES": "Interval minutes", + "INVERT_VISIBLE": "invert visible", + "JOBS": "Jobs", + "JOB_DONE": "Job done", + "JOB_FAILED": "Job failed", + "JOB_QUEUE": "Job queue", + "JOB_SCHEDULING": "Job scheduling", + "JOB_STARTED": "Job started", + "KEEP_LINES": "Keep lines", + "KEEP_SEEDING": "Keep seeding", + "LABEL": "Label", + "LABELS": "Labels", + "LABELS_SEPARATED_BY_COMMA": "Labels separated by comma", + "LABEL_AFTER_SHARE": "Label after share", + "LABEL_EXISTS": "Label exists", + "LABEL_IS_MISSING": "Label is missing", + "LABEL_NAME_OR_SEVERAL_SEPARATED_BY_COMMA": "Label name, or several separated by comma", + "LANGUAGE": "Language", + "LANGUAGE_SAVED": "Language saved", + "LAST_OPERATIONS": "Last operations", + "LICENSE": "License", + "LIGHTWEIGHT_WEB_PANEL_FOR_RTORRENT_MANAGEMENT_QUEUE_CONTROL_AND_LIVE_TORRENT_DIA": "Lightweight web panel for rTorrent management, queue control and live torrent diagnostics.", + "LIGHT_PARALLEL_JOBS": "Light parallel jobs", + "LIGHT_TIMEOUT_SECONDS": "Light timeout seconds", + "LIMIT_DL": "Limit DL", + "LOADING": "Loading", + "LOADING_CLEANUP_DATA": "Loading cleanup data...", + "LOADING_CONFIG": "Loading config...", + "LOADING_IMAGE_URL": "Loading image URL", + "LOADING_JOBS": "Loading jobs...", + "LOADING_LOGS": "Loading logs...", + "LOADING_PROFILES": "Loading profiles...", + "LOADING_STATISTICS": "Loading statistics...", + "LOADING_TORRENTS": "Loading torrents...", + "LOADING_TORRENT_DETAILS": "Loading torrent details...", + "LOCAL_BROWSER_TIME": "Local browser time", + "LOCATION": "Location", + "LOG": "Log", + "LOGS": "Logs", + "LOG_IN": "Log in", + "LOG_OUT": "Log out", + "LOG_STATISTICS": "Log statistics", + "MAGNET_AND_TORRENT_UPLOAD_FILE_PRIORITIES_LABELS_RATIO_GROUPS_SMART_QUEUE_AUTOMA": "Magnet and torrent upload, file priorities, labels, ratio groups, Smart Queue, automation rules, RSS, traffic charts, port checker, system status.", + "MAGNET_LINKS": "Magnet links", + "MANAGE_EXCEPTIONS": "Manage exceptions", + "MANAGE_OPERATION_LOG_RETENTION_WITHOUT_CHANGING_TORRENT_DATA": "Manage operation log retention without changing torrent data.", + "MANAGE_OPTIONAL_PYTORRENT_USERS_EMPTY_PROFILE_MEANS_ALL_PROFILES_R_O_BLOCKS_RTOR": "Manage optional pyTorrent users. Empty profile means all profiles. R/O blocks rTorrent-changing actions; Full allows them.", + "MANUAL_CLEANUP_ONLY": "Manual cleanup only", + "MAXIMUM_HEAVY_JOBS_RUNNING_AT_ONCE_FOR_THIS_PROFILE_DEFAULT_5": "Maximum heavy jobs running at once for this profile. Default: 5.", + "MAXIMUM_QUEUED_ACTIONS_RUNNING_AT_ONCE": "Maximum queued actions running at once.", + "MAXIMUM_STALLED_OVERFLOW_DOWNLOADS_SMART_QUEUE_MAY_STOP_IN_ONE_PASS": "Maximum stalled/overflow downloads Smart Queue may stop in one pass.", + "MAX_MB": "Max MB", + "MAX_RATIO": "Max ratio", + "MAX_STOPS_PER_CHECK": "Max stops per check", + "MESSAGE": "Message", + "MINUTES": "Minutes", + "MIN_MB": "Min MB", + "MIN_PEERS": "Min peers", + "MIN_RATIO": "Min ratio", + "MIN_SEEDS": "Min seeds", + "MIN_SEED_MINUTES": "Min seed minutes", + "MIN_SPEED_KIB_S": "Min speed KiB/s", + "MOBILE": "Mobile", + "MOBILE_COLUMNS": "Mobile columns", + "MOBILE_FILTER_GROUPS": "Mobile filter groups", + "MOBILE_SIMPLE_MODE": "Mobile/simple mode", + "MOBILE_SORT_FILTERS": "Mobile sort filters", + "MODE": "Mode", + "MONITORED_PATHS": "Monitored paths", + "MOVE": "Move", + "MOVE_DATA": "Move data", + "MOVE_DATA_FILES": "Move data files", + "MOVE_PATH": "Move path", + "MOVE_TO_PATH": "Move to path", + "MOVIES": "movies", + "MOVING": "Moving", + "M_MOVE": "M - move", + "NAME": "Name", + "NEGATE": "Negate", + "NEWLY_QUEUE_STARTED_TORRENTS_ARE_PROTECTED_FROM_STALLED_CLEANUP_DURING_THIS_WARM": "Newly queue-started torrents are protected from stalled cleanup during this warm-up.", + "NEW_LABEL": "New label", + "NEXT_READY": "next: ready", + "NEXT_SMART_QUEUE_RUN": "Next Smart Queue run", + "NOTIFICATIONS": "Notifications", + "NOT_LOADED": "Not loaded.", + "NO_CHANGES": "No changes", + "NO_FILES_RETURNED_BY_RTORRENT": "No files returned by rTorrent.", + "NO_FILES_SELECTED": "No files selected.", + "NO_LABELS": "No labels.", + "NO_LABELS_SELECTED": "No labels selected.", + "NO_PATH_LOADED": "No path loaded.", + "NO_PEERS_RETURNED_BY_RTORRENT": "No peers returned by rTorrent.", + "NO_RTORRENT_PROFILE_CONFIGURED": "No rTorrent profile configured.", + "NO_SAVED_LABELS": "No saved labels.", + "NO_TORRENTS": "No torrents.", + "NO_TORRENTS_FOR_THIS_FILTER": "No torrents for this filter.", + "NO_TORRENTS_SELECTED": "No torrents selected", + "NO_TORRENT_SELECTED": "No torrent selected", + "NO_TRACKERS_RETURNED_BY_RTORRENT": "No trackers returned by rTorrent.", + "OFF": "Off", + "OFFLINE": "offline", + "ONE_PLACE_TO_CLEAR_LOGS_AND_ACTIVE_PROFILE_CACHES_PENDING_RUNNING_JOBS_RULES_SET": "One place to clear logs and active profile caches. Pending/running jobs, rules, settings and torrents are preserved.", + "ONE_TRACKER_URL_PER_LINE": "One tracker URL per line", + "ONLINE": "online", + "ONLY_SELECTED": "Only selected", + "OPEN_DOWNLOAD_PLANNER": "Open Download planner", + "OPEN_RTORRENT_FILES_MAX_OPEN_FILES": "Open rTorrent files / max open files", + "OPEN_RTORRENT_HTTP_CONNECTIONS_MAX_HTTP_CONNECTIONS": "Open rTorrent HTTP connections / max HTTP connections", + "OPEN_RTORRENT_SOCKETS": "Open rTorrent sockets", + "OPEN_SOURCE": "Open source", + "OPEN_THIS_TAB_TO_LOAD_DIAGNOSTICS": "Open this tab to load diagnostics.", + "OPEN_THIS_TAB_TO_LOAD_STATISTICS": "Open this tab to load statistics.", + "OPERATION_LOG_RETENTION": "Operation log retention", + "OPTIONAL": "optional", + "OPTIONAL_PEER_TABLE_HELPERS": "Optional peer table helpers.", + "OPTIONAL_PRIVATE_SOURCE_TAG": "optional private source tag", + "OPTIONAL_VISUAL_EASTER_EGG_FOR_LOADING_STATES_AND_OCCASIONAL_BUTTON_CLICKS_DISAB": "Optional visual easter egg for loading states and occasional button clicks. Disabled by default.", + "PARALLEL_JOBS": "Parallel jobs", + "PARENT_DIRECTORY": "Parent directory", + "PARTIAL_DETAILS_LOADED": "Partial details loaded", + "PASSWORD": "Password", + "PASSWORD_NEW_PASSWORD": "Password / new password", + "PASTE_ONE_MAGNET_URI_PER_LINE": "Paste one magnet URI per line.", + "PATH": "Path", + "PATH_CONTAINS": "Path contains", + "PATH_TEXT": "Path text", + "PATH_USED_FOR_SELECTED_MODE": "Path used for selected mode", + "PAUSE": "Pause", + "PAUSED": "Paused", + "PEAK_S": "Peak S", + "PEAK_SPEED_UNAVAILABLE": "Peak speed unavailable", + "PEERS": "Peers", + "PEERS_AUTO_REFRESH": "Peers auto refresh", + "PENDING_JOBS_OLDER_THAN_THIS_ARE_RESUBMITTED_IF_NO_WORKER_IS_CURRENTLY_HANDLING_": "Pending jobs older than this are resubmitted if no worker is currently handling them. Default: 900 seconds.", + "PENDING_RUNNING_DONE_FAILED_RETRY_AND_CANCEL_HISTORY": "Pending, running, done, failed, retry and cancel history.", + "PENDING_TIMEOUT_SECONDS": "Pending timeout seconds", + "PIECE_SIZE": "Piece size", + "PLANNER": "Planner", + "POLISH": "Polish", + "PORT": "Port", + "PORT_CHECKER": "Port checker", + "PORT_CHECK_DISABLED": "Port check disabled", + "PORT_UNKNOWN": "Port - unknown", + "POST_CHECK": "Post-check", + "PREFERENCES": "Preferences", + "PREFERENCES_SAVED": "Preferences saved", + "PRIORITY": "Priority", + "PRIVATE_TORRENT": "Private torrent", + "PROFILE_BACKUP": "Profile backup", + "PROFILE_BACKUP_NAME": "Profile backup name", + "PROFILE_BACKUP_RESTORES_ONLY_THE_ACTIVE_PROFILE_CONTEXT_APPLICATION_BACKUP_RESTO": "Profile backup restores only the active profile context. Application backup restores global application data and is available only to admins.", + "PROFILE_NAME": "Profile name", + "PROFILE_SCOPED_LOG_COUNTS_AND_CLEANUP_OVERVIEW": "Profile-scoped log counts and cleanup overview.", + "PROGRESS": "Progress", + "PROGRESS_IS_AT_LEAST": "Progress is at least %", + "PROGRESS_IS_AT_MOST": "Progress is at most %", + "PROGRESS_SOURCE": "Progress source", + "PROTECT_ACTIVE_COUNT_BELOW_CAP": "Protect active count below cap", + "PYTORRENT_EXPECTS_TRUSTED_REVERSE_PROXY_IDENTITY_HEADERS_IF_YOU_ARE_ALREADY_SIGN": "pyTorrent expects trusted reverse-proxy identity headers. If you are already signed in, check provider headers and user mapping.", + "PYTORRENT_LOGIN": "pyTorrent login", + "PYTORRENT_STATUS": "pyTorrent status", + "P_PAUSE": "P - pause", + "QUALITY": "Quality", + "QUEUE_REFILL_DURING_COOLDOWN": "Queue refill during cooldown", + "RANDOM_CLICK_IMAGE_URL": "Random click image URL", + "RATIO": "Ratio", + "RATIO_GROUP": "Ratio group", + "RATIO_GROUPS": "Ratio groups", + "RATIO_IS_AT_LEAST": "Ratio is at least", + "RATIO_RULES": "Ratio rules", + "REANNOUNCE": "Reannounce", + "RECHECK": "Recheck", + "RECHECK_AFTER_MOVE": "Recheck after move", + "RECOMMENDED_COLUMNS": "Recommended columns", + "RECOMMENDED_COLUMNS_APPLIED": "Recommended columns applied", + "RECONNECTING": "reconnecting", + "REFERENCE_VALUE_IS_KEPT_FROM_THE_FIRST_OVERRIDE_SAVE_LATER_SAVES_ADD_OR_CLEAR_DI": "Reference value is kept from the first override save. Later saves add or clear differences without replacing the original reference.", + "REFRESH": "Refresh", + "REFRESH_NOW": "Refresh now", + "REGEX_TEXT": "Regex / text", + "RELOAD": "Reload", + "REMOTE_LOCATION": "Remote location", + "REMOVE": "Remove", + "REMOVE_DATA": "remove data", + "REMOVE_LABEL": "Remove label", + "REMOVE_SELECTED_TORRENTS": "Remove selected torrents", + "REMOVE_WITH_DATA": "Remove with data", + "REPOSITORY": "Repository", + "RESET": "Reset", + "RESET_UI_SETTINGS": "Reset UI settings", + "RESET_VIEW_DEFAULTS": "Reset view defaults", + "RESIZE_TORRENT_DETAILS_PANEL": "Resize torrent details panel", + "RESOLVE_PEER_IP_TO_REVERSE_DNS_HOST": "Resolve peer IP to reverse DNS host", + "RESUME": "Resume", + "RETENTION_DAYS": "Retention days", + "RETENTION_MODE": "Retention mode", + "RETRY": "Retry", + "REVERSE_DNS": "Reverse DNS", + "RSS_DOWNLOADER": "RSS downloader", + "RTORRENT": "rTorrent", + "RTORRENTS": "rTorrents", + "RTORRENT_CONFIG": "rTorrent config", + "RTORRENT_INCOMING_PORT": "rTorrent incoming port", + "RTORRENT_IS_STARTING_OR_NOT_RESPONDING_YET": "rTorrent is starting or not responding yet.", + "RTORRENT_PROFILES": "rTorrent profiles", + "RULE": "Rule", + "RULES": "Rules", + "RULES_ARE_CHECKED_AUTOMATICALLY_EVERY_5_MINUTES_A_TORRENT_USES_THE_GROUP_STORED_": "Rules are checked automatically every 5 minutes. A torrent uses the group stored in its rTorrent custom ratio field.", + "RULE_NAME": "Rule name", + "RUNTIME": "Runtime", + "RUN_A_PROFILE_TEST_TO_SHOW_DIAGNOSTICS": "Run a profile test to show diagnostics.", + "RUN_SMART_QUEUE_DURING_POLLING_STOPPED_TORRENTS_ARE_MANAGED_PAUSED_TORRENTS_STAY": "Run Smart Queue during polling. Stopped torrents are managed; Paused torrents stay user-controlled.", + "R_RESUME": "R - resume", + "SAVE": "Save", + "SAVED_LABELS": "Saved labels", + "SAVE_COLUMNS": "Save columns", + "SAVE_CONFIG": "Save config", + "SAVE_EASTER_EGG": "Save easter egg", + "SAVE_EXCEPTIONS": "Save exceptions", + "SAVE_FEED": "Save feed", + "SAVE_FOOTER": "Save footer", + "SAVE_GROUP": "Save group", + "SAVE_JOB_SETTINGS": "Save job settings", + "SAVE_LIMITS": "Save limits", + "SAVE_LOCATION": "Save location", + "SAVE_LOG_VIEW": "Save log view", + "SAVE_PATH": "Save path", + "SAVE_PREFERENCES": "Save preferences", + "SAVE_RETENTION": "Save retention", + "SAVE_RULE": "Save rule", + "SAVE_SCHEDULE": "Save schedule", + "SAVE_USER": "Save user", + "SCGI_URL": "SCGI URL", + "SEARCH_LOGS": "Search logs...", + "SEARCH_TORRENTS": "Search torrents...", + "SEARCH_TORRENTS_TO_EXCLUDE": "Search torrents to exclude...", + "SEASON": "Season", + "SECONDS_TO_WAIT_FOR_RTORRENT_RESPONSE": "Seconds to wait for rTorrent response.", + "SEEDING": "Seeding", + "SEEDS": "Seeds", + "SEEDS_ARE_LOW_FOR_TIME": "Seeds are low for time", + "SEED_MINUTES": "Seed minutes", + "SELECT": "Select", + "SELECTED": "selected", + "SELECTED_LABELS": "Selected labels", + "SELECTED_MONITORED_PATH": "Selected monitored path", + "SELECTED_TORRENTS_WILL_BE_REMOVED": "selected torrents will be removed.", + "SELECT_A_MONITORED_PATH_FIRST": "Select a monitored path first.", + "SELECT_A_TORRENT": "Select a torrent.", + "SELECT_ONE_OR_MORE_TORRENT_FILES": "Select one or more .torrent files.", + "SELECT_PATH": "Select path", + "SELECT_TORRENTS_THAT_SMART_QUEUE_SHOULD_IGNORE_USE_SEARCH_TO_FILTER_BY_NAME_LABE": "Select torrents that Smart Queue should ignore. Use search to filter by name, label, status or hash.", + "SELECT_VISIBLE": "Select visible", + "SEPARATE_SLOT_POOL_FOR_LIGHTWEIGHT_CONTROL_JOBS_SO_THEY_DO_NOT_WAIT_BEHIND_HEAVY": "Separate slot pool for lightweight control jobs so they do not wait behind heavy IO work. Default: 4.", + "SETTINGS": "Settings", + "SET_LABEL": "Set label...", + "SET_LABELS": "Set labels", + "SET_RATIO_GROUP": "Set ratio group...", + "SHARE_AFTER_CREATING": "Share after creating", + "SHORTCUTS": "Shortcuts", + "SHOWN": "Shown", + "SHOWN_IN_LOADING_STATES_INSTEAD_OF_THE_STANDARD_SPINNER": "Shown in loading states instead of the standard spinner.", + "SHOWS_TRACKER_ICONS_IN_THE_SIDEBAR_TRACKER_FILTER_WHEN_AVAILABLE": "Shows tracker icons in the sidebar tracker filter when available.", + "SHOW_COMBINED_USAGE_SINGLE_PATH_SELECTION_IS_DISABLED_IN_THIS_MODE": "Show combined usage. Single path selection is disabled in this mode.", + "SHOW_DL_UP_IN_BROWSER_TITLE": "Show DL/UP in browser title", + "SHOW_SMART_QUEUE_AUTOMATIC_RUN_MESSAGES": "Show Smart Queue automatic run messages.", + "SHOW_TOASTS_CREATED_BY_AUTOMATION_RUNS": "Show toasts created by automation runs.", + "SIGN_IN": "Sign in", + "SIZE": "Size", + "SKIP_ACTIVE_UPLOAD": "Skip active upload", + "SKIP_PRIVATE_TORRENTS": "Skip private torrents", + "SMART_FILTERS": "Smart filters", + "SMART_QUEUE": "Smart Queue", + "SMART_QUEUE_EXCEPTIONS": "Smart Queue exceptions", + "SMART_QUEUE_KEEPS_ONLY_THIS_MANY_ACTIVE_DOWNLOADS_OVERFLOW_IS_STOPPED": "Smart Queue keeps only this many active downloads; overflow is stopped.", + "SMART_QUEUE_TOASTS": "Smart Queue toasts", + "SOCKETS": "Sockets", + "SOURCE": "Source", + "SPACE_START": "Space - start", + "SPEED": "Speed", + "SPEED_LIMITS": "Speed limits", + "SPEED_TREND": "Speed trend", + "STALLED_AFTER_SECONDS": "Stalled after seconds", + "START": "Start", + "START_AFTER_ADD": "Start after add", + "START_GRACE_SECONDS": "Start grace seconds", + "STATE": "State", + "STATUS": "Status", + "STATUS_EQUALS": "Status equals", + "STOP": "Stop", + "STOPPED": "Stopped", + "S_STOP": "S - stop", + "TARGET_ACTIVE_DOWNLOADS": "Target active downloads", + "TARGET_PATH": "Target path", + "TEST_RULE": "Test rule", + "TEST_SCGI": "Test SCGI", + "THEME_TYPOGRAPHY_AND_INTERFACE_SCALE": "Theme, typography and interface scale.", + "THE_FOOTER_TOOLTIP_ALWAYS_SHOWS_DETAILS_FOR_AVAILABLE_PATHS_THIS_SETTING_ONLY_DE": "The footer tooltip always shows details for available paths; this setting only decides which value drives the visible progress bar.", + "TIMEOUT": "Timeout", + "TOAST_NOTIFICATIONS_FROM_AUTOMATIC_SYSTEMS": "Toast notifications from automatic systems.", + "TOOLS": "Tools", + "TOOLS_RTORRENTS": "Tools & rTorrents", + "TOOLS_SECTIONS": "Tools sections", + "TORRENT_ADDED": "Torrent added", + "TORRENT_COMPLETED": "Torrent completed", + "TORRENT_DETAILS": "Torrent details", + "TORRENT_FILES": "Torrent files", + "TORRENT_FILTERS": "Torrent filters", + "TORRENT_PROPERTIES": "Torrent properties", + "TORRENT_REMOVED": "Torrent removed", + "TORRENT_STATISTICS": "Torrent statistics", + "TORRENT_STATS": "Torrent stats", + "TOTAL_DL_UP": "Total DL/UP", + "TO_DOWNLOAD": "To download", + "TRACKERS": "Trackers", + "TRACKER_ICONS": "Tracker icons", + "TRANSFER": "Transfer", + "TRANSFERRED_DATA": "Transferred data", + "TRANSFER_HISTORY": "Transfer history", + "UNDEFINED": "undefined", + "UNLIMITED": "Unlimited", + "UPLOADED": "Uploaded", + "UPLOADS": "Uploads", + "UPLOAD_KIB_S": "Upload KiB/s", + "USER": "User", + "USERS": "Users", + "USES_A_LIGHTWEIGHT_BUILT_IN_RESOLVER_WITH_CACHE_HOSTNAMES_APPEAR_ONLY_IN_THE_PEE": "Uses a lightweight built-in resolver with cache. Hostnames appear only in the Peers tab.", + "USES_LOWER_ROWS_AND_SMALLER_LIST_ELEMENTS_ON_DESKTOP_AND_MOBILE_SO_MORE_TORRENTS": "Uses lower rows and smaller list elements on desktop and mobile so more torrents fit on screen.", + "USES_YOUGETSIGNAL_FIRST_MANUAL_CHECK_BYPASSES_THE_6H_CACHE": "Uses YouGetSignal first. Manual check bypasses the 6h cache.", + "USE_ONE_CUSTOM_PATH_BELOW_AS_THE_FOOTER_PROGRESS_VALUE": "Use one custom path below as the footer progress value.", + "USE_SELECTED": "Use selected", + "USE_THE_MAIN_DIRECTORY_FROM_THE_ACTIVE_RTORRENT_PROFILE": "Use the main directory from the active rTorrent profile.", + "VIEW_PREFERENCES_RESET": "View preferences reset", + "VIEW_STATE_IS_SAVED_AUTOMATICALLY_IN_THE_DATABASE_CURRENT_TORRENT_FILTER_LAST_SO": "View state is saved automatically in the database: current torrent filter, last sort column and direction, visible columns, and details panel height.", + "VISIBLE_NAME_USED_IN_THE_PROFILE_SELECTOR": "Visible name used in the profile selector.", + "VISUAL_HELPER_FOR_TRACKER_FILTERS_IN_THE_SIDEBAR": "Visual helper for tracker filters in the sidebar.", + "WAITING_FOR_DATA": "Waiting for data.", + "WAITING_FOR_TORRENT_DATA_FROM_THE_ACTIVE_PROFILE": "Waiting for torrent data from the active profile.", + "WATCHDOG_MARKS_A_LIGHT_JOB_AS_FAILED_AFTER_THIS_TIME_DEFAULT_300_SECONDS": "Watchdog marks a light job as failed after this time. Default: 300 seconds.", + "WATCHDOG_TIMEOUT_FOR_MOVE_REMOVE_ADD_JOBS_DEFAULT_7200_SECONDS": "Watchdog timeout for move/remove/add jobs. Default: 7200 seconds.", + "WHEN_DISABLED_THE_APPLICATION_USES_THE_NORMAL_PRODUCTION_UI": "When disabled, the application uses the normal production UI.", + "WHEN_ENABLED_LOW_SPEED_IS_NOT_REQUIRED_WITH_SOURCE_AND_SPEED_IGNORES_ENABLED_ONL": "When enabled, low speed is not required. With source and speed ignores enabled, only Stalled after seconds decides.", + "WHEN_ENABLED_SMART_QUEUE_DOES_NOT_USE_SEED_PEER_COUNT_AS_A_STALLED_CRITERION": "When enabled, Smart Queue does not use seed/peer count as a stalled criterion.", + "WITH_ERROR": "With error", + "WORKING": "Working...", + "FRENCH": "French", + "CZECH": "Czech", + "SPANISH": "Spanish", + "NORWEGIAN": "Norwegian", + "RUSSIAN": "Russian" + } +} diff --git a/pytorrent/static/i18n/es_ES.json b/pytorrent/static/i18n/es_ES.json new file mode 100644 index 0000000..19c9bfe --- /dev/null +++ b/pytorrent/static/i18n/es_ES.json @@ -0,0 +1,566 @@ +{ + "meta": { + "locale": "es_ES", + "label": "Español", + "flag": "es" + }, + "translations": { + "0_MEANS_ONLY_SEED_THRESHOLD_IS_REQUIRED": "0 means solo seed threshold está required.", + "0_MEANS_UNLIMITED_SLIDERS_USE_MBIT_S_AND_SAVE_THROUGH_THE_EXISTING_SPEED_LIMITS_": "0 means unlimited. Sliders usar Mbit/s y Guardar through existing Velocidad Límites API.", + "0_SELECTED": "0 seleccionado", + "ABOUT_PYTORRENT": "About pyTorrent", + "ACTION": "Acción", + "ACTIVE": "Activo", + "ACTIVE_RTORRENT_DOWNLOADS_MAX_GLOBAL_DOWNLOADS": "Activo rTorrent Descargas / max global Descargas", + "ACTIVE_RTORRENT_UPLOADS_MAX_GLOBAL_UPLOADS": "Activo rTorrent Subidas / max global Subidas", + "ADD": "Añadir", + "ADDED": "Added", + "ADDS_REMOVALS_COMPLETIONS_AND_QUEUED_OPERATION_RESULTS": "Adds, removals, completions y queued operation results.", + "ADD_ACTION": "Añadir Acción", + "ADD_CONDITION": "Añadir Condición", + "ADD_CREATE_TORRENT": "Añadir / Crear Torrent", + "ADD_FIRST_LABEL_ABOVE": "Añadir Primero Etiqueta above.", + "ADD_LABEL": "Añadir Etiqueta", + "ADD_MAGNET_LINK": "Añadir magnet link", + "ADD_NEW_LABEL": "Añadir Nuevo Etiqueta", + "ADD_OR_EDIT_GROUP": "Añadir o Editar Grupo", + "ADD_PATH": "Añadir Ruta", + "ADD_PROFILE": "Añadir Perfil", + "ADD_RTORRENT_PROFILE": "Añadir rTorrent Perfil", + "ADD_THE_FIRST_RTORRENT_PROFILE_TO_START_LOADING_TORRENTS": "Añadir Primero rTorrent Perfil a Iniciar Cargando Torrents.", + "ADD_TORRENT": "Añadir Torrent", + "ADD_TORRENT_FILE": "Añadir Torrent Archivo", + "ADMIN": "Administrador", + "ADMIN_ONLY_FULL_APPLICATION_BACKUP_RESTORE_CAN_REPLACE_USERS_PERMISSIONS_PROFILE": "Administrador-solo full Aplicación copia de seguridad. Restaurar puede replace Usuarios, permissions, Perfiles y global Aplicación Ajustes.", + "AGGREGATE_ALL_PATHS": "Aggregate Todos rutas", + "ALL": "Todos", + "ALL_NON_JOB_TYPES": "Todos non-Tarea types", + "ALL_PROFILES": "Todos Perfiles", + "ALL_TYPES": "Todos types", + "ANNOUNCE": "Announce", + "API_DOCS": "API docs", + "APPEARANCE": "Apariencia", + "APPEARANCE_PREFERENCES_SAVED": "Apariencia Preferencias Guardado", + "APPEARS_NEAR_CLICKED_BUTTONS_ONLY_SOMETIMES": "Appears near clicked buttons solo sometimes.", + "APPLICATION_BACKUP": "Aplicación copia de seguridad", + "APPLICATION_BACKUP_NAME": "Aplicación copia de seguridad Nombre", + "APPLY": "Apply", + "APPLY_RETENTION_NOW": "Apply Retención now", + "APPLY_SAVED_CHANGES_60S_AFTER_PYTORRENT_START": "Apply Guardado changes 60s después pyTorrent Iniciar", + "APP_STATUS": "App Estado", + "AUTHENTICATION_IS_ENABLED_FOR_THIS_PYTORRENT_INSTANCE": "Authentication está Activado para este pyTorrent instancia.", + "AUTHOR": "Autor", + "AUTOMATIC": "Automático", + "AUTOMATIC_KEEPS_THE_CURRENT_POLLER_CADENCE_CUSTOM_RUNS_ONLY_AFTER_THE_SELECTED_N": "Automático keeps Actual poller cadence. Personalizado runs solo después seleccionado number de minutos. Off disables refill completely.", + "AUTOMATIC_QUEUE_BALANCING_FOR_SLOW_OR_STALLED_DOWNLOADS": "Automático Cola equilibrado para lentas o atascadas Descargas.", + "AUTOMATIC_RUNS_USE_THE_COOLDOWN_BELOW_MANUAL_CHECK_NOW_STILL_RUNS_IMMEDIATELY": "Automático runs usar Espera below. Manual Comprobar now still runs immediately.", + "AUTOMATIONS": "Automations", + "AUTOMATIONS_RULES": "Automations / Reglas", + "AUTOMATION_TOASTS": "Automation toasts", + "AUTO_STOP_WHEN_IDLE": "Auto-Detener when idle", + "BACKEND": "Backend", + "BACKUP": "Copia de seguridad", + "BACKUP_RESTORE": "Copia de seguridad / Restaurar", + "BACK_TO_DASHBOARD": "Back a dashboard", + "BOOTSTRAP_THEME": "Bootstrap Tema", + "BROWSER": "Navegador", + "BROWSER_TITLE": "Navegador Título", + "BUILD_A_RULE_AS_CONDITIONS_FIRST_THEN_ORDERED_ACTIONS_MATCHING_TORRENTS_ARE_HAND": "Build Regla como: Condiciones Primero, luego ordered Acciones. Matching Torrents son handled como uno batch y Espera está aplicado a whole Regla.", + "BUSY": "busy", + "BY_DAYS": "Por días", + "BY_LINE_COUNT": "Por line count", + "CACHED_METADATA_SUMMARY_FILE_METADATA_IS_REFRESHED_EVERY_15_MINUTES_A_FEW_MINUTE": "Cached metadata summary. Archivo metadata está refreshed every 15 minutos, unos minutos después inicio, o manually.", + "CANCEL": "Cancelar", + "CANCEL_EDIT": "Cancelar Editar", + "CATEGORY": "Categoría", + "CHANGES_APPLY_IMMEDIATELY_WHERE_POSSIBLE_INITIAL_STARTUP_LOADER_USES_THEM_AFTER_": "Changes apply immediately where possible; initial inicio loader uses ellos después reload.", + "CHANGE_RTORRENT": "Cambiar rTorrent", + "CHANGE_THEME": "Cambiar Tema", + "CHANGING_RTORRENT_RELOADS_THE_LIVE_TORRENT_SNAPSHOT": "Cambio rTorrent reloads live Torrent instantánea.", + "CHECKING": "Comprobando", + "CHECK_NOW": "Comprobar ahora", + "CHECK_PORT_NOW": "Comprobar puerto ahora", + "CHECK_THIS_IF_YOU_WANT_TO_CONNECT_TO_A_REMOTE_RTORRENT_INSTANCE_INSTEAD_OF_LOCAL": "Comprobar este si usted quiere a conectar a Remoto rTorrent instancia en lugar de de localhost.", + "CHOOSE_COLUMNS_VISIBLE_IN_THE_TORRENT_LIST": "Elegir Columnas visible en Torrent lista.", + "CHOOSE_FILES": "Elegir Archivos", + "CHOOSE_RTORRENT": "Elegir rTorrent", + "CHOOSE_TORRENTS_IGNORED_BY_SMART_QUEUE_EXISTING_BEHAVIOR_STAYS_UNCHANGED_FOR_ALL": "Elegir Torrents ignored por Smart Queue. Existing behavior stays unchanged para Todos non-excluded Torrents.", + "CHOOSE_WHAT_THE_FOOTER_DISK_BAR_SHOULD_REPRESENT_AND_ADD_EXTRA_STORAGE_PATHS": "Elegir what Pie disk barra debe represent y Añadir extra storage rutas.", + "CHOOSE_WHICH_STATUS_ITEMS_ARE_VISIBLE_IN_THE_BOTTOM_BAR": "Elegir qué Estado items son visible en bottom barra.", + "CHUNKS": "Chunks", + "CLEANUP": "Limpieza", + "CLEANUP_RETENTION": "Limpieza / Retención", + "CLEAR": "Limpiar", + "CLEAR_CURRENT_FILTER": "Limpiar Actual filtro", + "CLEAR_FINISHED": "Limpiar finished", + "CLEAR_LABELS": "Limpiar Etiquetas", + "CLEAR_SELECTION": "Limpiar selection", + "CLEAR_VISIBLE": "Limpiar visible", + "CLOSE": "Cerrar", + "COLUMNS": "Columnas", + "COLUMNS_SAVED": "Columnas Guardado", + "COMMENT": "Comment", + "COMPACT_TORRENT_LIST": "Compact Torrent lista", + "COMPLETE": "Complete", + "COMPLETED": "Completado", + "CONFIGURED_RTORRENTS": "Configured rTorrents", + "CONNECTING_TO_RTORRENT_AND_PREPARING_DATA": "Connecting a rTorrent y preparing Datos.", + "CONNECTION_ADDRESS_IN_SCGI_HOST_PORT_RPC2_FORMAT": "Conexión address en scgi://host:Puerto/RPC2 format.", + "CONTROLS_THE_DEFAULT_CATEGORY_AND_JOB_LOG_VISIBILITY_USED_BY_THE_LOGS_MODAL": "Controls Predeterminado Categoría y Tarea Registro visibility used por Registros modal.", + "CONTROLS_WHAT_IS_SHOWN_IN_THE_BROWSER_TAB": "Controls what está shown en Navegador pestaña.", + "COOLDOWN_MINUTES": "Espera minutos", + "COPY": "Copiar", + "COPY_HASH": "Copiar Hash", + "COPY_NAME": "Copiar Nombre", + "COPY_PATH": "Copiar Ruta", + "CPU_RAM_USAGE": "CPU / RAM usage", + "CREATE": "Crear", + "CREATES_AND_RESTORES_SETTINGS_FOR_THE_CURRENTLY_SELECTED_PROFILE_USER_SCOPED_PRE": "Creates y restores Ajustes para actualmente seleccionado Perfil. Usuario-scoped Preferencias son remapped a Actual Usuario where needed.", + "CREATE_APPLICATION_BACKUP": "Crear Aplicación copia de seguridad", + "CREATE_ONE_RTORRENT_PROFILE_AT_A_TIME_MOVE_REMOVE_QUEUES_KEEP_THEIR_ORDER_FOR_EA": "Crear uno rTorrent Perfil at tiempo. Mover/Quitar queues keep sus order para cada Perfil.", + "CREATE_PROFILE_BACKUP": "Crear Perfil copia de seguridad", + "CREATE_REUSABLE_LABELS_AND_REMOVE_LABELS_THAT_ARE_NO_LONGER_NEEDED": "Crear reutilizables Etiquetas y Quitar Etiquetas que son Sin más tiempo needed.", + "CREATE_TORRENT": "Crear Torrent", + "CTRL_A_SELECT_VISIBLE": "Ctrl+ - Seleccionar visible", + "CTRL_I_INVERT_VISIBLE": "Ctrl+I - invert visible", + "CTRL_O_ADD": "Ctrl+O - Añadir", + "CTRL_S_DOWNLOAD_TORRENT": "Ctrl+S - Descarga .Torrent", + "CURRENT_TRANSFER_SPEED": "Actual transfer Velocidad", + "CUSTOM_DOWNLOAD": "Personalizado Descarga", + "CUSTOM_UPLOAD": "Personalizado Subida", + "DAYS_AND_LINE_COUNT": "Días y line count", + "DECREASE_OR_INCREASE_THE_WHOLE_INTERFACE_SIZE": "Decrease o increase whole interface Tamaño.", + "DEFAULT_LOG_CATEGORY": "Predeterminado Registro Categoría", + "DEFAULT_LOG_VIEW": "Predeterminado Registro view", + "DEFAULT_RTORRENT_PATH": "Predeterminado rTorrent Ruta", + "DEGRADED": "degraded", + "DELETE": "Eliminar", + "DELETE_REMOVE": "Eliminar - Quitar", + "DESKTOP": "Escritorio", + "DETAILS_WILL_APPEAR_AFTER_THE_FIRST_SUCCESSFUL_RESPONSE": "Detalles será appear después Primero correcta respuesta.", + "DIAGNOSTICS": "Diagnóstico", + "DISABLED": "Desactivado", + "DISK_MONITOR": "Disk monitor", + "DISK_USAGE_UNAVAILABLE": "Disk usage unavailable", + "DISPLAYS_CURRENT_SPEEDS_NEXT_TO_PYTORRENT_IN_THE_TAB_TITLE": "Displays Actual speeds Siguiente a pyTorrent en pestaña Título.", + "DOCS_API": "Docs API", + "DOWNLOADED": "Descargado", + "DOWNLOADING": "Descargando", + "DOWNLOADS": "Descargas", + "DOWNLOAD_KIB_S": "Descarga KiB/s", + "DOWNLOAD_STARTED": "Descarga iniciados", + "DOWNLOAD_TORRENT": "Descarga .Torrent", + "DOWNLOAD_TRACKER_FAVICONS": "Descarga Tracker favicons", + "DRAG_TO_RESIZE_DETAILS_PANEL": "Drag a resize Detalles Panel", + "EASTER_EGG": "Easter egg", + "EDIT": "Editar", + "EMERGENCY_CANCEL": "Emergency Cancelar", + "EMERGENCY_CLEAN_ALL": "Emergency clean Todos", + "ENABLED": "Activado", + "ENABLE_AUTOMATIC_APPLICATION_BACKUPS": "Activar Automático Aplicación copias de seguridad", + "ENABLE_AUTOMATIC_PROFILE_BACKUPS": "Activar Automático Perfil copias de seguridad", + "ENABLE_EASTER_EGG": "Activar easter egg", + "ENABLE_INCOMING_PORT_CHECK": "Activar incoming Puerto Comprobar", + "ENABLE_REVERSE_DNS_FOR_PEERS": "Activar reverse DNS para Peers", + "ENGLISH": "Inglés", + "EPISODE": "Episodio", + "ESC_CLEAR_SELECTION": "Esc - Limpiar selection", + "ETA": "ETA", + "EVERY_N_MINUTES": "Every N minutos", + "EVERY_X_HOURS": "Every X hours", + "EXCLUDE": "Excluir", + "EXCLUDE_FROM_SMART_QUEUE": "Excluir desde Smart Queue", + "EXCLUDE_PATTERN": "Excluir Patrón", + "EXISTING_GROUPS": "Existing Grupos", + "EXPORT": "Exportar", + "EXPORT_JSON": "Exportar JSON", + "EXTERNAL_AUTHENTICATION_IS_ENABLED_THROUGH_EXTERNAL_PROVIDER": "External authentication está Activado through {{ external_provider }}.", + "E_G_PUNKTY_KATALOGOWANIE": "e.g. Punkty katalogowanie", + "FEATURES": "Funciones", + "FEED": "Feed", + "FEEDS_ARE_CHECKED_BY_SCHEDULE_AND_EVERY_MATCH_IS_LOGGED_PER_FEED_RULE": "Feeds son comprobados por programación y every coincidencia está registrada per feed/Regla.", + "FEEDS_RULES_AND_MATCHES": "Feeds, Reglas y coincidencias", + "FEED_NAME": "Feed Nombre", + "FEED_URL": "Feed URL", + "FILES": "Archivos", + "FILE_OR_DIRECTORY_PATH": "Archivo o Directorio Ruta", + "FONT": "Fuente", + "FOOTER": "Pie", + "FORCE": "Forzar", + "FORCE_RECHECK": "Forzar Recomprobar", + "FRONTEND": "Frontend", + "FULL": "Full", + "GENERAL": "General", + "GENERATED_RTORRENT_CONFIG_CHANGES_WILL_APPEAR_HERE": "Generado rTorrent Configuración changes será appear here.", + "GENERATE_CONFIG": "Generate Configuración", + "GERMAN": "Alemán", + "GO": "Go", + "GROUPED_RTORRENT_RUNTIME_SETTINGS_WITH_INLINE_RECOMMENDATIONS_AND_COMPATIBILITY_": "Agrupados rTorrent Runtime Ajustes con inline recomendaciones y compatibilidad Estado.", + "GROUP_NAME": "Grupo Nombre", + "HASH": "Hash", + "HASHING": "Hashing", + "HEAVY_PARALLEL_JOBS": "Heavy parallel Tareas", + "HEAVY_TIMEOUT_SECONDS": "Heavy Timeout segundos", + "HIDE_JOB_LOGS": "Ocultar Tarea Registros", + "HIDE_JOB_LOGS_BY_DEFAULT": "Ocultar Tarea Registros por Predeterminado", + "HISTORY": "Historial", + "HOW_LONG_A_MATCHING_ACTIVE_TORRENT_MUST_STAY_STALLED_BEFORE_IT_CAN_BE_REPLACED": "Cuánto largo matching Activo Torrent debe stay atascadas antes it puede estar reemplazado.", + "IGNORE_MISSING_SEEDS_PEERS_FOR_STALLED_TIMER": "Ignorar missing Seeds/Peers para atascadas timer", + "IGNORE_SPEED_FOR_STALLED_TIMER": "Ignorar Velocidad para atascadas timer", + "IMPORT": "Importar", + "IMPORT_JSON": "Importar JSON", + "INCLUDE_PATTERN": "Incluir Patrón", + "INCOMING_CONNECTION_TEST_SEPARATE_FROM_VISUAL_PREFERENCES": "Incoming Conexión Prueba, separate desde visual Preferencias.", + "INTERFACE_SCALE": "Interface scale", + "INTERVAL_MINUTES": "Intervalo minutos", + "INVERT_VISIBLE": "invert visible", + "JOBS": "Tareas", + "JOB_DONE": "Tarea hecho", + "JOB_FAILED": "Tarea fallido", + "JOB_QUEUE": "Tarea Cola", + "JOB_SCHEDULING": "Tarea scheduling", + "JOB_STARTED": "Tarea iniciados", + "KEEP_LINES": "Keep lines", + "KEEP_SEEDING": "Keep Compartiendo", + "LABEL": "Etiqueta", + "LABELS": "Etiquetas", + "LABELS_SEPARATED_BY_COMMA": "Etiquetas separated por comma", + "LABEL_AFTER_SHARE": "Etiqueta después share", + "LABEL_EXISTS": "Etiqueta exists", + "LABEL_IS_MISSING": "Etiqueta está missing", + "LABEL_NAME_OR_SEVERAL_SEPARATED_BY_COMMA": "Etiqueta Nombre, o varios separated por comma", + "LANGUAGE": "Idioma", + "LANGUAGE_SAVED": "Idioma Guardado", + "LAST_OPERATIONS": "Último operations", + "LICENSE": "Licencia", + "LIGHTWEIGHT_WEB_PANEL_FOR_RTORRENT_MANAGEMENT_QUEUE_CONTROL_AND_LIVE_TORRENT_DIA": "Lightweight web Panel para rTorrent management, Cola control y live Torrent Diagnóstico.", + "LIGHT_PARALLEL_JOBS": "Light parallel Tareas", + "LIGHT_TIMEOUT_SECONDS": "Light Timeout segundos", + "LIMIT_DL": "Límite DL", + "LOADING": "Cargando", + "LOADING_CLEANUP_DATA": "Cargando Limpieza Datos...", + "LOADING_CONFIG": "Cargando Configuración...", + "LOADING_IMAGE_URL": "Cargando image URL", + "LOADING_JOBS": "Cargando Tareas...", + "LOADING_LOGS": "Cargando Registros...", + "LOADING_PROFILES": "Cargando Perfiles...", + "LOADING_STATISTICS": "Cargando Estadísticas...", + "LOADING_TORRENTS": "Cargando Torrents...", + "LOADING_TORRENT_DETAILS": "Cargando Torrent Detalles...", + "LOCAL_BROWSER_TIME": "Local Navegador tiempo", + "LOCATION": "Ubicación", + "LOG": "Registro", + "LOGS": "Registros", + "LOG_IN": "Iniciar sesión", + "LOG_OUT": "Cerrar sesión", + "LOG_STATISTICS": "Registro Estadísticas", + "MAGNET_AND_TORRENT_UPLOAD_FILE_PRIORITIES_LABELS_RATIO_GROUPS_SMART_QUEUE_AUTOMA": "Magnet y Torrent Subida, Archivo prioridades, Etiquetas, Ratio Grupos, Smart Queue, automation Reglas, RSS, tráfico gráficos, Puerto comprobador, system Estado.", + "MAGNET_LINKS": "Magnet links", + "MANAGE_EXCEPTIONS": "Manage exceptions", + "MANAGE_OPERATION_LOG_RETENTION_WITHOUT_CHANGING_TORRENT_DATA": "Manage operation Registro Retención sin Cambio Torrent Datos.", + "MANAGE_OPTIONAL_PYTORRENT_USERS_EMPTY_PROFILE_MEANS_ALL_PROFILES_R_O_BLOCKS_RTOR": "Manage opcional pyTorrent Usuarios. Empty Perfil means Todos Perfiles. R/O blocks rTorrent-Cambio Acciones; Full allows ellos.", + "MANUAL_CLEANUP_ONLY": "Manual Limpieza solo", + "MAXIMUM_HEAVY_JOBS_RUNNING_AT_ONCE_FOR_THIS_PROFILE_DEFAULT_5": "Máximo heavy Tareas running at once para este Perfil. Predeterminado: 5.", + "MAXIMUM_QUEUED_ACTIONS_RUNNING_AT_ONCE": "Máximo queued Acciones running at once.", + "MAXIMUM_STALLED_OVERFLOW_DOWNLOADS_SMART_QUEUE_MAY_STOP_IN_ONE_PASS": "Máximo atascadas/overflow Descargas Smart Queue may Detener en uno pass.", + "MAX_MB": "Max MB", + "MAX_RATIO": "Max Ratio", + "MAX_STOPS_PER_CHECK": "Max stops per Comprobar", + "MESSAGE": "Mensaje", + "MINUTES": "Minutos", + "MIN_MB": "Min MB", + "MIN_PEERS": "Min Peers", + "MIN_RATIO": "Min Ratio", + "MIN_SEEDS": "Min Seeds", + "MIN_SEED_MINUTES": "Min seed minutos", + "MIN_SPEED_KIB_S": "Min Velocidad KiB/s", + "MOBILE": "Móvil", + "MOBILE_COLUMNS": "Móvil Columnas", + "MOBILE_FILTER_GROUPS": "Móvil filtro Grupos", + "MOBILE_SIMPLE_MODE": "Móvil/simple mode", + "MOBILE_SORT_FILTERS": "Móvil sort filters", + "MODE": "Mode", + "MONITORED_PATHS": "Monitored rutas", + "MOVE": "Mover", + "MOVE_DATA": "Mover Datos", + "MOVE_DATA_FILES": "Mover Datos Archivos", + "MOVE_PATH": "Mover Ruta", + "MOVE_TO_PATH": "Mover a Ruta", + "MOVIES": "películas", + "MOVING": "Moving", + "M_MOVE": "M - Mover", + "NAME": "Nombre", + "NEGATE": "Negate", + "NEWLY_QUEUE_STARTED_TORRENTS_ARE_PROTECTED_FROM_STALLED_CLEANUP_DURING_THIS_WARM": "Recién Cola-iniciados Torrents son protegidos desde atascadas Limpieza durante este calentamiento-arriba.", + "NEW_LABEL": "Nuevo Etiqueta", + "NEXT_READY": "Siguiente: ready", + "NEXT_SMART_QUEUE_RUN": "Siguiente Smart Queue ejecución", + "NOTIFICATIONS": "Notificaciones", + "NOT_LOADED": "No cargado.", + "NO_CHANGES": "Sin cambios", + "NO_FILES_RETURNED_BY_RTORRENT": "Sin Archivos returned por rTorrent.", + "NO_FILES_SELECTED": "No hay archivos seleccionados.", + "NO_LABELS": "Sin Etiquetas.", + "NO_LABELS_SELECTED": "No hay etiquetas seleccionadas.", + "NO_PATH_LOADED": "Sin Ruta loaded.", + "NO_PEERS_RETURNED_BY_RTORRENT": "Sin Peers returned por rTorrent.", + "NO_RTORRENT_PROFILE_CONFIGURED": "Sin rTorrent Perfil configured.", + "NO_SAVED_LABELS": "Sin Guardado Etiquetas.", + "NO_TORRENTS": "Sin Torrents.", + "NO_TORRENTS_FOR_THIS_FILTER": "Sin Torrents para este filtro.", + "NO_TORRENTS_SELECTED": "No hay torrents seleccionados", + "NO_TORRENT_SELECTED": "No hay torrent seleccionado", + "NO_TRACKERS_RETURNED_BY_RTORRENT": "Sin Trackers returned por rTorrent.", + "OFF": "Off", + "OFFLINE": "sin conexión", + "ONE_PLACE_TO_CLEAR_LOGS_AND_ACTIVE_PROFILE_CACHES_PENDING_RUNNING_JOBS_RULES_SET": "Uno place a Limpiar Registros y Activo Perfil caches. Pendientes/running Tareas, Reglas, Ajustes y Torrents son preserved.", + "ONE_TRACKER_URL_PER_LINE": "Uno Tracker URL per line", + "ONLINE": "en línea", + "ONLY_SELECTED": "Solo seleccionado", + "OPEN_DOWNLOAD_PLANNER": "Abrir Descarga planner", + "OPEN_RTORRENT_FILES_MAX_OPEN_FILES": "Abrir rTorrent Archivos / max Abrir Archivos", + "OPEN_RTORRENT_HTTP_CONNECTIONS_MAX_HTTP_CONNECTIONS": "Abrir rTorrent HTTP connections / max HTTP connections", + "OPEN_RTORRENT_SOCKETS": "Abrir rTorrent sockets", + "OPEN_SOURCE": "Open source", + "OPEN_THIS_TAB_TO_LOAD_DIAGNOSTICS": "Abrir este pestaña a cargar Diagnóstico.", + "OPEN_THIS_TAB_TO_LOAD_STATISTICS": "Abrir este pestaña a cargar Estadísticas.", + "OPERATION_LOG_RETENTION": "Operation Registro Retención", + "OPTIONAL": "opcional", + "OPTIONAL_PEER_TABLE_HELPERS": "Opcional peer table helpers.", + "OPTIONAL_PRIVATE_SOURCE_TAG": "opcional Privado Fuente tag", + "OPTIONAL_VISUAL_EASTER_EGG_FOR_LOADING_STATES_AND_OCCASIONAL_BUTTON_CLICKS_DISAB": "Opcional visual easter egg para Cargando estados y ocasionales botón clics. Desactivado por Predeterminado.", + "PARALLEL_JOBS": "Parallel Tareas", + "PARENT_DIRECTORY": "Padre Directorio", + "PARTIAL_DETAILS_LOADED": "Partial Detalles loaded", + "PASSWORD": "Contraseña", + "PASSWORD_NEW_PASSWORD": "Contraseña / Nuevo Contraseña", + "PASTE_ONE_MAGNET_URI_PER_LINE": "Paste uno magnet URI per line.", + "PATH": "Ruta", + "PATH_CONTAINS": "Ruta contains", + "PATH_TEXT": "Ruta Texto", + "PATH_USED_FOR_SELECTED_MODE": "Ruta used para seleccionado mode", + "PAUSE": "Pausa", + "PAUSED": "Pausado", + "PEAK_S": "Peak S", + "PEAK_SPEED_UNAVAILABLE": "Peak Velocidad unavailable", + "PEERS": "Peers", + "PEERS_AUTO_REFRESH": "Peers auto Actualizar", + "PENDING_JOBS_OLDER_THAN_THIS_ARE_RESUBMITTED_IF_NO_WORKER_IS_CURRENTLY_HANDLING_": "Pendientes Tareas más antiguas que este son reenviadas si Sin worker está actualmente procesa ellos. Predeterminado: 900 segundos.", + "PENDING_RUNNING_DONE_FAILED_RETRY_AND_CANCEL_HISTORY": "Pendientes, running, hecho, fallido, Reintentar y Cancelar Historial.", + "PENDING_TIMEOUT_SECONDS": "Pendientes Timeout segundos", + "PIECE_SIZE": "Piece Tamaño", + "PLANNER": "Planner", + "POLISH": "Polaco", + "PORT": "Puerto", + "PORT_CHECKER": "Puerto comprobador", + "PORT_CHECK_DISABLED": "Puerto Comprobar Desactivado", + "PORT_UNKNOWN": "Puerto - unknown", + "POST_CHECK": "Post-Comprobar", + "PREFERENCES": "Preferencias", + "PREFERENCES_SAVED": "Preferencias Guardado", + "PRIORITY": "Prioridad", + "PRIVATE_TORRENT": "Privado Torrent", + "PROFILE_BACKUP": "Perfil copia de seguridad", + "PROFILE_BACKUP_NAME": "Perfil copia de seguridad Nombre", + "PROFILE_BACKUP_RESTORES_ONLY_THE_ACTIVE_PROFILE_CONTEXT_APPLICATION_BACKUP_RESTO": "Perfil copia de seguridad restores solo Activo Perfil contexto. Aplicación copia de seguridad restores global Aplicación Datos y está disponibles solo a administradores.", + "PROFILE_NAME": "Perfil Nombre", + "PROFILE_SCOPED_LOG_COUNTS_AND_CLEANUP_OVERVIEW": "Perfil-scoped Registro recuentos y Limpieza resumen.", + "PROGRESS": "Progreso", + "PROGRESS_IS_AT_LEAST": "Progreso está at least %", + "PROGRESS_IS_AT_MOST": "Progreso está at most %", + "PROGRESS_SOURCE": "Progreso Fuente", + "PROTECT_ACTIVE_COUNT_BELOW_CAP": "Protect Activo count below cap", + "PYTORRENT_EXPECTS_TRUSTED_REVERSE_PROXY_IDENTITY_HEADERS_IF_YOU_ARE_ALREADY_SIGN": "pyTorrent expects trusted reverse-proxy identity headers. Si usted son already signed en, Comprobar provider headers y Usuario mapping.", + "PYTORRENT_LOGIN": "pyTorrent login", + "PYTORRENT_STATUS": "pyTorrent Estado", + "P_PAUSE": "P - Pausa", + "QUALITY": "Calidad", + "QUEUE_REFILL_DURING_COOLDOWN": "Cola refill durante Espera", + "RANDOM_CLICK_IMAGE_URL": "Random click image URL", + "RATIO": "Ratio", + "RATIO_GROUP": "Ratio Grupo", + "RATIO_GROUPS": "Ratio Grupos", + "RATIO_IS_AT_LEAST": "Ratio está at least", + "RATIO_RULES": "Ratio Reglas", + "REANNOUNCE": "Reannounce", + "RECHECK": "Recomprobar", + "RECHECK_AFTER_MOVE": "Recomprobar después Mover", + "RECOMMENDED_COLUMNS": "Recomendado Columnas", + "RECOMMENDED_COLUMNS_APPLIED": "Recomendado Columnas aplicado", + "RECONNECTING": "reconnecting", + "REFERENCE_VALUE_IS_KEPT_FROM_THE_FIRST_OVERRIDE_SAVE_LATER_SAVES_ADD_OR_CLEAR_DI": "Reference valor está kept desde Primero override Guardar. Later saves Añadir o Limpiar differences sin replacing original reference.", + "REFRESH": "Actualizar", + "REFRESH_NOW": "Actualizar now", + "REGEX_TEXT": "Regex / Texto", + "RELOAD": "Reload", + "REMOTE_LOCATION": "Remoto Ubicación", + "REMOVE": "Quitar", + "REMOVE_DATA": "Quitar Datos", + "REMOVE_LABEL": "Quitar Etiqueta", + "REMOVE_SELECTED_TORRENTS": "Quitar seleccionado Torrents", + "REMOVE_WITH_DATA": "Quitar con Datos", + "REPOSITORY": "Repositorio", + "RESET": "Restablecer", + "RESET_UI_SETTINGS": "Restablecer UI Ajustes", + "RESET_VIEW_DEFAULTS": "Restablecer view defaults", + "RESIZE_TORRENT_DETAILS_PANEL": "Resize Torrent Detalles Panel", + "RESOLVE_PEER_IP_TO_REVERSE_DNS_HOST": "Resolve peer IP a reverse DNS host", + "RESUME": "Reanudar", + "RETENTION_DAYS": "Retención días", + "RETENTION_MODE": "Retención mode", + "RETRY": "Reintentar", + "REVERSE_DNS": "Reverse DNS", + "RSS_DOWNLOADER": "RSS downloader", + "RTORRENT": "rTorrent", + "RTORRENTS": "rTorrents", + "RTORRENT_CONFIG": "rTorrent Configuración", + "RTORRENT_INCOMING_PORT": "rTorrent incoming Puerto", + "RTORRENT_IS_STARTING_OR_NOT_RESPONDING_YET": "rTorrent está starting o no responding yet.", + "RTORRENT_PROFILES": "rTorrent Perfiles", + "RULE": "Regla", + "RULES": "Reglas", + "RULES_ARE_CHECKED_AUTOMATICALLY_EVERY_5_MINUTES_A_TORRENT_USES_THE_GROUP_STORED_": "Reglas son comprobados automatically every 5 minutos. Torrent uses Grupo stored en its rTorrent Personalizado Ratio field.", + "RULE_NAME": "Regla Nombre", + "RUNTIME": "Runtime", + "RUN_A_PROFILE_TEST_TO_SHOW_DIAGNOSTICS": "Ejecución Perfil Prueba a Mostrar Diagnóstico.", + "RUN_SMART_QUEUE_DURING_POLLING_STOPPED_TORRENTS_ARE_MANAGED_PAUSED_TORRENTS_STAY": "Ejecución Smart Queue durante polling. Detenido Torrents son gestionados; Pausado Torrents stay Usuario-controlled.", + "R_RESUME": "R - Reanudar", + "SAVE": "Guardar", + "SAVED_LABELS": "Guardado Etiquetas", + "SAVE_COLUMNS": "Guardar Columnas", + "SAVE_CONFIG": "Guardar Configuración", + "SAVE_EASTER_EGG": "Guardar easter egg", + "SAVE_EXCEPTIONS": "Guardar exceptions", + "SAVE_FEED": "Guardar feed", + "SAVE_FOOTER": "Guardar Pie", + "SAVE_GROUP": "Guardar Grupo", + "SAVE_JOB_SETTINGS": "Guardar Tarea Ajustes", + "SAVE_LIMITS": "Guardar Límites", + "SAVE_LOCATION": "Guardar Ubicación", + "SAVE_LOG_VIEW": "Guardar Registro view", + "SAVE_PATH": "Guardar Ruta", + "SAVE_PREFERENCES": "Guardar Preferencias", + "SAVE_RETENTION": "Guardar Retención", + "SAVE_RULE": "Guardar Regla", + "SAVE_SCHEDULE": "Guardar programación", + "SAVE_USER": "Guardar Usuario", + "SCGI_URL": "SCGI URL", + "SEARCH_LOGS": "Buscar Registros...", + "SEARCH_TORRENTS": "Buscar Torrents...", + "SEARCH_TORRENTS_TO_EXCLUDE": "Buscar Torrents a Excluir...", + "SEASON": "Temporada", + "SECONDS_TO_WAIT_FOR_RTORRENT_RESPONSE": "Segundos a esperar para rTorrent respuesta.", + "SEEDING": "Compartiendo", + "SEEDS": "Seeds", + "SEEDS_ARE_LOW_FOR_TIME": "Seeds son bajo para tiempo", + "SEED_MINUTES": "Seed minutos", + "SELECT": "Seleccionar", + "SELECTED": "seleccionado", + "SELECTED_LABELS": "Seleccionado Etiquetas", + "SELECTED_MONITORED_PATH": "Seleccionado monitored Ruta", + "SELECTED_TORRENTS_WILL_BE_REMOVED": "seleccionado Torrents será estar removed.", + "SELECT_A_MONITORED_PATH_FIRST": "Seleccionar monitored Ruta Primero.", + "SELECT_A_TORRENT": "Seleccionar Torrent.", + "SELECT_ONE_OR_MORE_TORRENT_FILES": "Seleccionar uno o more .Torrent Archivos.", + "SELECT_PATH": "Seleccionar Ruta", + "SELECT_TORRENTS_THAT_SMART_QUEUE_SHOULD_IGNORE_USE_SEARCH_TO_FILTER_BY_NAME_LABE": "Seleccionar Torrents que Smart Queue debe ignorar. Usar Buscar a filtro por Nombre, Etiqueta, Estado o Hash.", + "SELECT_VISIBLE": "Seleccionar visible", + "SEPARATE_SLOT_POOL_FOR_LIGHTWEIGHT_CONTROL_JOBS_SO_THEY_DO_NOT_WAIT_BEHIND_HEAVY": "Separate slot pool para lightweight control Tareas so they do no esperar detrás heavy IO trabajo. Predeterminado: 4.", + "SETTINGS": "Ajustes", + "SET_LABEL": "Set Etiqueta...", + "SET_LABELS": "Set Etiquetas", + "SET_RATIO_GROUP": "Set Ratio Grupo...", + "SHARE_AFTER_CREATING": "Share después creating", + "SHORTCUTS": "Shortcuts", + "SHOWN": "Shown", + "SHOWN_IN_LOADING_STATES_INSTEAD_OF_THE_STANDARD_SPINNER": "Shown en Cargando estados en lugar de de estándar spinner.", + "SHOWS_TRACKER_ICONS_IN_THE_SIDEBAR_TRACKER_FILTER_WHEN_AVAILABLE": "Muestra Tracker iconos en barra lateral Tracker filtro when disponibles.", + "SHOW_COMBINED_USAGE_SINGLE_PATH_SELECTION_IS_DISABLED_IN_THIS_MODE": "Mostrar combinada usage. Única Ruta selection está Desactivado en este mode.", + "SHOW_DL_UP_IN_BROWSER_TITLE": "Mostrar DL/UP en Navegador Título", + "SHOW_SMART_QUEUE_AUTOMATIC_RUN_MESSAGES": "Mostrar Smart Queue Automático ejecución mensajes.", + "SHOW_TOASTS_CREATED_BY_AUTOMATION_RUNS": "Mostrar toasts created por automation runs.", + "SIGN_IN": "Iniciar sesión", + "SIZE": "Tamaño", + "SKIP_ACTIVE_UPLOAD": "Skip Activo Subida", + "SKIP_PRIVATE_TORRENTS": "Skip Privado Torrents", + "SMART_FILTERS": "Smart filters", + "SMART_QUEUE": "Smart Queue", + "SMART_QUEUE_EXCEPTIONS": "Smart Queue exceptions", + "SMART_QUEUE_KEEPS_ONLY_THIS_MANY_ACTIVE_DOWNLOADS_OVERFLOW_IS_STOPPED": "Smart Queue keeps solo este many Activo Descargas; overflow está Detenido.", + "SMART_QUEUE_TOASTS": "Smart Queue toasts", + "SOCKETS": "Sockets", + "SOURCE": "Fuente", + "SPACE_START": "Space - Iniciar", + "SPEED": "Velocidad", + "SPEED_LIMITS": "Velocidad Límites", + "SPEED_TREND": "Velocidad trend", + "STALLED_AFTER_SECONDS": "Atascadas después segundos", + "START": "Iniciar", + "START_AFTER_ADD": "Iniciar después Añadir", + "START_GRACE_SECONDS": "Iniciar grace segundos", + "STATE": "Estado", + "STATUS": "Estado", + "STATUS_EQUALS": "Estado equals", + "STOP": "Detener", + "STOPPED": "Detenido", + "S_STOP": "S - Detener", + "TARGET_ACTIVE_DOWNLOADS": "Objetivo Activo Descargas", + "TARGET_PATH": "Objetivo Ruta", + "TEST_RULE": "Prueba Regla", + "TEST_SCGI": "Prueba SCGI", + "THEME_TYPOGRAPHY_AND_INTERFACE_SCALE": "Tema, typography y interface scale.", + "THE_FOOTER_TOOLTIP_ALWAYS_SHOWS_DETAILS_FOR_AVAILABLE_PATHS_THIS_SETTING_ONLY_DE": "Pie tooltip siempre muestra Detalles para disponibles rutas; este ajuste solo decide qué valor controla visible Progreso barra.", + "TIMEOUT": "Timeout", + "TOAST_NOTIFICATIONS_FROM_AUTOMATIC_SYSTEMS": "Toast Notificaciones desde Automático systems.", + "TOOLS": "Herramientas", + "TOOLS_RTORRENTS": "Herramientas & rTorrents", + "TOOLS_SECTIONS": "Herramientas sections", + "TORRENT_ADDED": "Torrent added", + "TORRENT_COMPLETED": "Torrent Completado", + "TORRENT_DETAILS": "Torrent Detalles", + "TORRENT_FILES": "Torrent Archivos", + "TORRENT_FILTERS": "Torrent filters", + "TORRENT_PROPERTIES": "Torrent properties", + "TORRENT_REMOVED": "Torrent removed", + "TORRENT_STATISTICS": "Torrent Estadísticas", + "TORRENT_STATS": "Torrent stats", + "TOTAL_DL_UP": "Total DL/UP", + "TO_DOWNLOAD": "A Descarga", + "TRACKERS": "Trackers", + "TRACKER_ICONS": "Tracker iconos", + "TRANSFER": "Transfer", + "TRANSFERRED_DATA": "Transferred Datos", + "TRANSFER_HISTORY": "Transfer Historial", + "UNDEFINED": "undefined", + "UNLIMITED": "Unlimited", + "UPLOADED": "Subido", + "UPLOADS": "Subidas", + "UPLOAD_KIB_S": "Subida KiB/s", + "USER": "Usuario", + "USERS": "Usuarios", + "USES_A_LIGHTWEIGHT_BUILT_IN_RESOLVER_WITH_CACHE_HOSTNAMES_APPEAR_ONLY_IN_THE_PEE": "Uses lightweight built-en resolvedor con caché. Nombres de host appear solo en Peers pestaña.", + "USES_LOWER_ROWS_AND_SMALLER_LIST_ELEMENTS_ON_DESKTOP_AND_MOBILE_SO_MORE_TORRENTS": "Uses más bajas filas y smaller lista elements on Escritorio y Móvil so more Torrents caben on pantalla.", + "USES_YOUGETSIGNAL_FIRST_MANUAL_CHECK_BYPASSES_THE_6H_CACHE": "Uses YouGetSignal Primero. Manual Comprobar bypasses 6h caché.", + "USE_ONE_CUSTOM_PATH_BELOW_AS_THE_FOOTER_PROGRESS_VALUE": "Usar uno Personalizado Ruta below como Pie Progreso valor.", + "USE_SELECTED": "Usar seleccionado", + "USE_THE_MAIN_DIRECTORY_FROM_THE_ACTIVE_RTORRENT_PROFILE": "Usar main Directorio desde Activo rTorrent Perfil.", + "VIEW_PREFERENCES_RESET": "View Preferencias Restablecer", + "VIEW_STATE_IS_SAVED_AUTOMATICALLY_IN_THE_DATABASE_CURRENT_TORRENT_FILTER_LAST_SO": "View Estado está Guardado automatically en database: Actual Torrent filtro, Último sort column y direction, visible Columnas, y Detalles Panel height.", + "VISIBLE_NAME_USED_IN_THE_PROFILE_SELECTOR": "Visible Nombre used en Perfil selector.", + "VISUAL_HELPER_FOR_TRACKER_FILTERS_IN_THE_SIDEBAR": "Visual ayudante para Tracker filters en barra lateral.", + "WAITING_FOR_DATA": "Esperando para Datos.", + "WAITING_FOR_TORRENT_DATA_FROM_THE_ACTIVE_PROFILE": "Esperando para Torrent Datos desde Activo Perfil.", + "WATCHDOG_MARKS_A_LIGHT_JOB_AS_FAILED_AFTER_THIS_TIME_DEFAULT_300_SECONDS": "Watchdog marks light Tarea como fallido después este tiempo. Predeterminado: 300 segundos.", + "WATCHDOG_TIMEOUT_FOR_MOVE_REMOVE_ADD_JOBS_DEFAULT_7200_SECONDS": "Watchdog Timeout para Mover/Quitar/Añadir Tareas. Predeterminado: 7200 segundos.", + "WHEN_DISABLED_THE_APPLICATION_USES_THE_NORMAL_PRODUCTION_UI": "When Desactivado, Aplicación uses normal producción UI.", + "WHEN_ENABLED_LOW_SPEED_IS_NOT_REQUIRED_WITH_SOURCE_AND_SPEED_IGNORES_ENABLED_ONL": "When Activado, bajo Velocidad está no required. Con Fuente y Velocidad ignores Activado, solo Atascadas después segundos decide.", + "WHEN_ENABLED_SMART_QUEUE_DOES_NOT_USE_SEED_PEER_COUNT_AS_A_STALLED_CRITERION": "When Activado, Smart Queue does no usar seed/peer count como atascadas criterio.", + "WITH_ERROR": "Con Error", + "WORKING": "Trabajando...", + "FRENCH": "Francés", + "CZECH": "Checo", + "SPANISH": "Español", + "NORWEGIAN": "Noruego", + "RUSSIAN": "Ruso" + } +} diff --git a/pytorrent/static/i18n/fr_FR.json b/pytorrent/static/i18n/fr_FR.json new file mode 100644 index 0000000..b6684d7 --- /dev/null +++ b/pytorrent/static/i18n/fr_FR.json @@ -0,0 +1,566 @@ +{ + "meta": { + "locale": "fr_FR", + "label": "Français", + "flag": "fr" + }, + "translations": { + "0_MEANS_ONLY_SEED_THRESHOLD_IS_REQUIRED": "0 means seulement seed threshold est required.", + "0_MEANS_UNLIMITED_SLIDERS_USE_MBIT_S_AND_SAVE_THROUGH_THE_EXISTING_SPEED_LIMITS_": "0 means unlimited. Sliders utiliser Mbit/s et Enregistrer through existing Vitesse Limites API.", + "0_SELECTED": "0 sélectionné", + "ABOUT_PYTORRENT": "About pyTorrent", + "ACTION": "Action", + "ACTIVE": "Actif", + "ACTIVE_RTORRENT_DOWNLOADS_MAX_GLOBAL_DOWNLOADS": "Actif rTorrent Téléchargements / max global Téléchargements", + "ACTIVE_RTORRENT_UPLOADS_MAX_GLOBAL_UPLOADS": "Actif rTorrent Envois / max global Envois", + "ADD": "Ajouter", + "ADDED": "Added", + "ADDS_REMOVALS_COMPLETIONS_AND_QUEUED_OPERATION_RESULTS": "Adds, removals, completions et queued operation results.", + "ADD_ACTION": "Ajouter Action", + "ADD_CONDITION": "Ajouter Condition", + "ADD_CREATE_TORRENT": "Ajouter / Créer Torrent", + "ADD_FIRST_LABEL_ABOVE": "Ajouter Premier Étiquette above.", + "ADD_LABEL": "Ajouter Étiquette", + "ADD_MAGNET_LINK": "Ajouter magnet link", + "ADD_NEW_LABEL": "Ajouter Nouveau Étiquette", + "ADD_OR_EDIT_GROUP": "Ajouter ou Modifier Groupe", + "ADD_PATH": "Ajouter Chemin", + "ADD_PROFILE": "Ajouter Profil", + "ADD_RTORRENT_PROFILE": "Ajouter rTorrent Profil", + "ADD_THE_FIRST_RTORRENT_PROFILE_TO_START_LOADING_TORRENTS": "Ajouter Premier rTorrent Profil à Démarrer Chargement Torrents.", + "ADD_TORRENT": "Ajouter Torrent", + "ADD_TORRENT_FILE": "Ajouter Torrent Fichier", + "ADMIN": "Administrateur", + "ADMIN_ONLY_FULL_APPLICATION_BACKUP_RESTORE_CAN_REPLACE_USERS_PERMISSIONS_PROFILE": "Administrateur-seulement full Application sauvegarde. Restaurer peut replace Utilisateurs, permissions, Profils et global Application Paramètres.", + "AGGREGATE_ALL_PATHS": "Aggregate Tous chemins", + "ALL": "Tous", + "ALL_NON_JOB_TYPES": "Tous non-Tâche types", + "ALL_PROFILES": "Tous Profils", + "ALL_TYPES": "Tous types", + "ANNOUNCE": "Announce", + "API_DOCS": "API docs", + "APPEARANCE": "Apparence", + "APPEARANCE_PREFERENCES_SAVED": "Apparence Préférences Enregistré", + "APPEARS_NEAR_CLICKED_BUTTONS_ONLY_SOMETIMES": "Appears near clicked buttons seulement sometimes.", + "APPLICATION_BACKUP": "Application sauvegarde", + "APPLICATION_BACKUP_NAME": "Application sauvegarde Nom", + "APPLY": "Apply", + "APPLY_RETENTION_NOW": "Apply Rétention now", + "APPLY_SAVED_CHANGES_60S_AFTER_PYTORRENT_START": "Apply Enregistré changes 60s après pyTorrent Démarrer", + "APP_STATUS": "App État", + "AUTHENTICATION_IS_ENABLED_FOR_THIS_PYTORRENT_INSTANCE": "Authentication est Activé pour ce pyTorrent instance.", + "AUTHOR": "Auteur", + "AUTOMATIC": "Automatique", + "AUTOMATIC_KEEPS_THE_CURRENT_POLLER_CADENCE_CUSTOM_RUNS_ONLY_AFTER_THE_SELECTED_N": "Automatique keeps Actuel poller cadence. Personnalisé runs seulement après sélectionné number de minutes. Off disables refill completely.", + "AUTOMATIC_QUEUE_BALANCING_FOR_SLOW_OR_STALLED_DOWNLOADS": "Automatique File équilibrage pour lents ou bloqués Téléchargements.", + "AUTOMATIC_RUNS_USE_THE_COOLDOWN_BELOW_MANUAL_CHECK_NOW_STILL_RUNS_IMMEDIATELY": "Automatique runs utiliser Délai below. Manuel Vérifier now still runs immediately.", + "AUTOMATIONS": "Automations", + "AUTOMATIONS_RULES": "Automations / Règles", + "AUTOMATION_TOASTS": "Automation toasts", + "AUTO_STOP_WHEN_IDLE": "Auto-Arrêter when idle", + "BACKEND": "Backend", + "BACKUP": "Sauvegarde", + "BACKUP_RESTORE": "Sauvegarde / Restaurer", + "BACK_TO_DASHBOARD": "Back à dashboard", + "BOOTSTRAP_THEME": "Bootstrap Thème", + "BROWSER": "Navigateur", + "BROWSER_TITLE": "Navigateur Titre", + "BUILD_A_RULE_AS_CONDITIONS_FIRST_THEN_ORDERED_ACTIONS_MATCHING_TORRENTS_ARE_HAND": "Build Règle comme: Conditions Premier, puis ordered Actions. Matching Torrents sont handled comme un batch et Délai est appliqué à whole Règle.", + "BUSY": "busy", + "BY_DAYS": "Par jours", + "BY_LINE_COUNT": "Par line count", + "CACHED_METADATA_SUMMARY_FILE_METADATA_IS_REFRESHED_EVERY_15_MINUTES_A_FEW_MINUTE": "Cached metadata summary. Fichier metadata est refreshed every 15 minutes, quelques minutes après démarrage, ou manually.", + "CANCEL": "Annuler", + "CANCEL_EDIT": "Annuler Modifier", + "CATEGORY": "Catégorie", + "CHANGES_APPLY_IMMEDIATELY_WHERE_POSSIBLE_INITIAL_STARTUP_LOADER_USES_THEM_AFTER_": "Changes apply immediately where possible; initial démarrage loader uses les après reload.", + "CHANGE_RTORRENT": "Changer rTorrent", + "CHANGE_THEME": "Changer Thème", + "CHANGING_RTORRENT_RELOADS_THE_LIVE_TORRENT_SNAPSHOT": "Changement rTorrent reloads live Torrent instantané.", + "CHECKING": "Vérification", + "CHECK_NOW": "Vérifier maintenant", + "CHECK_PORT_NOW": "Vérifier le port maintenant", + "CHECK_THIS_IF_YOU_WANT_TO_CONNECT_TO_A_REMOTE_RTORRENT_INSTANCE_INSTEAD_OF_LOCAL": "Vérifier ce si vous voulez à connecter à Distant rTorrent instance au lieu de de localhost.", + "CHOOSE_COLUMNS_VISIBLE_IN_THE_TORRENT_LIST": "Choisir Colonnes visible dans Torrent liste.", + "CHOOSE_FILES": "Choisir Fichiers", + "CHOOSE_RTORRENT": "Choisir rTorrent", + "CHOOSE_TORRENTS_IGNORED_BY_SMART_QUEUE_EXISTING_BEHAVIOR_STAYS_UNCHANGED_FOR_ALL": "Choisir Torrents ignored par Smart Queue. Existing behavior stays unchanged pour Tous non-excluded Torrents.", + "CHOOSE_WHAT_THE_FOOTER_DISK_BAR_SHOULD_REPRESENT_AND_ADD_EXTRA_STORAGE_PATHS": "Choisir what Pied de page disk barre doit represent et Ajouter extra storage chemins.", + "CHOOSE_WHICH_STATUS_ITEMS_ARE_VISIBLE_IN_THE_BOTTOM_BAR": "Choisir quelle État items sont visible dans bottom barre.", + "CHUNKS": "Chunks", + "CLEANUP": "Nettoyage", + "CLEANUP_RETENTION": "Nettoyage / Rétention", + "CLEAR": "Effacer", + "CLEAR_CURRENT_FILTER": "Effacer Actuel filtre", + "CLEAR_FINISHED": "Effacer finished", + "CLEAR_LABELS": "Effacer Étiquettes", + "CLEAR_SELECTION": "Effacer selection", + "CLEAR_VISIBLE": "Effacer visible", + "CLOSE": "Fermer", + "COLUMNS": "Colonnes", + "COLUMNS_SAVED": "Colonnes Enregistré", + "COMMENT": "Comment", + "COMPACT_TORRENT_LIST": "Compact Torrent liste", + "COMPLETE": "Complete", + "COMPLETED": "Terminé", + "CONFIGURED_RTORRENTS": "Configured rTorrents", + "CONNECTING_TO_RTORRENT_AND_PREPARING_DATA": "Connecting à rTorrent et preparing Données.", + "CONNECTION_ADDRESS_IN_SCGI_HOST_PORT_RPC2_FORMAT": "Connexion address dans scgi://host:Port/RPC2 format.", + "CONTROLS_THE_DEFAULT_CATEGORY_AND_JOB_LOG_VISIBILITY_USED_BY_THE_LOGS_MODAL": "Controls Défaut Catégorie et Tâche Journal visibility used par Journaux fenêtre.", + "CONTROLS_WHAT_IS_SHOWN_IN_THE_BROWSER_TAB": "Controls what est shown dans Navigateur onglet.", + "COOLDOWN_MINUTES": "Délai minutes", + "COPY": "Copier", + "COPY_HASH": "Copier Hash", + "COPY_NAME": "Copier Nom", + "COPY_PATH": "Copier Chemin", + "CPU_RAM_USAGE": "CPU / RAM usage", + "CREATE": "Créer", + "CREATES_AND_RESTORES_SETTINGS_FOR_THE_CURRENTLY_SELECTED_PROFILE_USER_SCOPED_PRE": "Creates et restores Paramètres pour actuellement sélectionné Profil. Utilisateur-scoped Préférences sont remapped à Actuel Utilisateur where needed.", + "CREATE_APPLICATION_BACKUP": "Créer Application sauvegarde", + "CREATE_ONE_RTORRENT_PROFILE_AT_A_TIME_MOVE_REMOVE_QUEUES_KEEP_THEIR_ORDER_FOR_EA": "Créer un rTorrent Profil at temps. Déplacer/Supprimer queues keep leur order pour chaque Profil.", + "CREATE_PROFILE_BACKUP": "Créer Profil sauvegarde", + "CREATE_REUSABLE_LABELS_AND_REMOVE_LABELS_THAT_ARE_NO_LONGER_NEEDED": "Créer réutilisables Étiquettes et Supprimer Étiquettes que sont Aucun plus longtemps needed.", + "CREATE_TORRENT": "Créer Torrent", + "CTRL_A_SELECT_VISIBLE": "Ctrl+ - Sélectionner visible", + "CTRL_I_INVERT_VISIBLE": "Ctrl+I - invert visible", + "CTRL_O_ADD": "Ctrl+O - Ajouter", + "CTRL_S_DOWNLOAD_TORRENT": "Ctrl+S - Téléchargement .Torrent", + "CURRENT_TRANSFER_SPEED": "Actuel transfer Vitesse", + "CUSTOM_DOWNLOAD": "Personnalisé Téléchargement", + "CUSTOM_UPLOAD": "Personnalisé Envoi", + "DAYS_AND_LINE_COUNT": "Jours et line count", + "DECREASE_OR_INCREASE_THE_WHOLE_INTERFACE_SIZE": "Decrease ou increase whole interface Taille.", + "DEFAULT_LOG_CATEGORY": "Défaut Journal Catégorie", + "DEFAULT_LOG_VIEW": "Défaut Journal view", + "DEFAULT_RTORRENT_PATH": "Défaut rTorrent Chemin", + "DEGRADED": "degraded", + "DELETE": "Supprimer", + "DELETE_REMOVE": "Supprimer - Supprimer", + "DESKTOP": "Bureau", + "DETAILS_WILL_APPEAR_AFTER_THE_FIRST_SUCCESSFUL_RESPONSE": "Détails sera appear après Premier réussie réponse.", + "DIAGNOSTICS": "Diagnostics", + "DISABLED": "Désactivé", + "DISK_MONITOR": "Disk monitor", + "DISK_USAGE_UNAVAILABLE": "Disk usage unavailable", + "DISPLAYS_CURRENT_SPEEDS_NEXT_TO_PYTORRENT_IN_THE_TAB_TITLE": "Displays Actuel speeds Suivant à pyTorrent dans onglet Titre.", + "DOCS_API": "Docs API", + "DOWNLOADED": "Téléchargé", + "DOWNLOADING": "Téléchargement", + "DOWNLOADS": "Téléchargements", + "DOWNLOAD_KIB_S": "Téléchargement KiB/s", + "DOWNLOAD_STARTED": "Téléchargement démarrés", + "DOWNLOAD_TORRENT": "Téléchargement .Torrent", + "DOWNLOAD_TRACKER_FAVICONS": "Téléchargement Tracker favicons", + "DRAG_TO_RESIZE_DETAILS_PANEL": "Drag à resize Détails Panneau", + "EASTER_EGG": "Easter egg", + "EDIT": "Modifier", + "EMERGENCY_CANCEL": "Emergency Annuler", + "EMERGENCY_CLEAN_ALL": "Emergency clean Tous", + "ENABLED": "Activé", + "ENABLE_AUTOMATIC_APPLICATION_BACKUPS": "Activer Automatique Application sauvegardes", + "ENABLE_AUTOMATIC_PROFILE_BACKUPS": "Activer Automatique Profil sauvegardes", + "ENABLE_EASTER_EGG": "Activer easter egg", + "ENABLE_INCOMING_PORT_CHECK": "Activer incoming Port Vérifier", + "ENABLE_REVERSE_DNS_FOR_PEERS": "Activer reverse DNS pour Pairs", + "ENGLISH": "Anglais", + "EPISODE": "Épisode", + "ESC_CLEAR_SELECTION": "Esc - Effacer selection", + "ETA": "ETA", + "EVERY_N_MINUTES": "Every N minutes", + "EVERY_X_HOURS": "Every X hours", + "EXCLUDE": "Exclure", + "EXCLUDE_FROM_SMART_QUEUE": "Exclure depuis Smart Queue", + "EXCLUDE_PATTERN": "Exclure Motif", + "EXISTING_GROUPS": "Existing Groupes", + "EXPORT": "Exporter", + "EXPORT_JSON": "Exporter JSON", + "EXTERNAL_AUTHENTICATION_IS_ENABLED_THROUGH_EXTERNAL_PROVIDER": "External authentication est Activé through {{ external_provider }}.", + "E_G_PUNKTY_KATALOGOWANIE": "e.g. Punkty katalogowanie", + "FEATURES": "Fonctions", + "FEED": "Feed", + "FEEDS_ARE_CHECKED_BY_SCHEDULE_AND_EVERY_MATCH_IS_LOGGED_PER_FEED_RULE": "Flux sont vérifiés par calendrier et every correspondance est journalisée per feed/Règle.", + "FEEDS_RULES_AND_MATCHES": "Flux, Règles et correspondances", + "FEED_NAME": "Feed Nom", + "FEED_URL": "Feed URL", + "FILES": "Fichiers", + "FILE_OR_DIRECTORY_PATH": "Fichier ou Répertoire Chemin", + "FONT": "Police", + "FOOTER": "Pied de page", + "FORCE": "Forcer", + "FORCE_RECHECK": "Forcer Revérifier", + "FRONTEND": "Frontend", + "FULL": "Full", + "GENERAL": "Général", + "GENERATED_RTORRENT_CONFIG_CHANGES_WILL_APPEAR_HERE": "Généré rTorrent Configuration changes sera appear here.", + "GENERATE_CONFIG": "Generate Configuration", + "GERMAN": "Allemand", + "GO": "Go", + "GROUPED_RTORRENT_RUNTIME_SETTINGS_WITH_INLINE_RECOMMENDATIONS_AND_COMPATIBILITY_": "Groupés rTorrent Runtime Paramètres avec inline recommandations et compatibilité État.", + "GROUP_NAME": "Groupe Nom", + "HASH": "Hash", + "HASHING": "Hashing", + "HEAVY_PARALLEL_JOBS": "Heavy parallel Tâches", + "HEAVY_TIMEOUT_SECONDS": "Heavy Timeout secondes", + "HIDE_JOB_LOGS": "Masquer Tâche Journaux", + "HIDE_JOB_LOGS_BY_DEFAULT": "Masquer Tâche Journaux par Défaut", + "HISTORY": "Historique", + "HOW_LONG_A_MATCHING_ACTIVE_TORRENT_MUST_STAY_STALLED_BEFORE_IT_CAN_BE_REPLACED": "Combien longtemps matching Actif Torrent doit stay bloqués avant it peut être remplacé.", + "IGNORE_MISSING_SEEDS_PEERS_FOR_STALLED_TIMER": "Ignorer missing Seeds/Pairs pour bloqués timer", + "IGNORE_SPEED_FOR_STALLED_TIMER": "Ignorer Vitesse pour bloqués timer", + "IMPORT": "Importer", + "IMPORT_JSON": "Importer JSON", + "INCLUDE_PATTERN": "Inclure Motif", + "INCOMING_CONNECTION_TEST_SEPARATE_FROM_VISUAL_PREFERENCES": "Incoming Connexion Test, separate depuis visual Préférences.", + "INTERFACE_SCALE": "Interface scale", + "INTERVAL_MINUTES": "Intervalle minutes", + "INVERT_VISIBLE": "invert visible", + "JOBS": "Tâches", + "JOB_DONE": "Tâche terminé", + "JOB_FAILED": "Tâche échoué", + "JOB_QUEUE": "Tâche File", + "JOB_SCHEDULING": "Tâche scheduling", + "JOB_STARTED": "Tâche démarrés", + "KEEP_LINES": "Keep lines", + "KEEP_SEEDING": "Keep Partage", + "LABEL": "Étiquette", + "LABELS": "Étiquettes", + "LABELS_SEPARATED_BY_COMMA": "Étiquettes separated par comma", + "LABEL_AFTER_SHARE": "Étiquette après share", + "LABEL_EXISTS": "Étiquette exists", + "LABEL_IS_MISSING": "Étiquette est missing", + "LABEL_NAME_OR_SEVERAL_SEPARATED_BY_COMMA": "Étiquette Nom, ou plusieurs separated par comma", + "LANGUAGE": "Langue", + "LANGUAGE_SAVED": "Langue Enregistré", + "LAST_OPERATIONS": "Dernier operations", + "LICENSE": "Licence", + "LIGHTWEIGHT_WEB_PANEL_FOR_RTORRENT_MANAGEMENT_QUEUE_CONTROL_AND_LIVE_TORRENT_DIA": "Lightweight web Panneau pour rTorrent management, File control et live Torrent Diagnostics.", + "LIGHT_PARALLEL_JOBS": "Light parallel Tâches", + "LIGHT_TIMEOUT_SECONDS": "Light Timeout secondes", + "LIMIT_DL": "Limite DL", + "LOADING": "Chargement", + "LOADING_CLEANUP_DATA": "Chargement Nettoyage Données...", + "LOADING_CONFIG": "Chargement Configuration...", + "LOADING_IMAGE_URL": "Chargement image URL", + "LOADING_JOBS": "Chargement Tâches...", + "LOADING_LOGS": "Chargement Journaux...", + "LOADING_PROFILES": "Chargement Profils...", + "LOADING_STATISTICS": "Chargement Statistiques...", + "LOADING_TORRENTS": "Chargement Torrents...", + "LOADING_TORRENT_DETAILS": "Chargement Torrent Détails...", + "LOCAL_BROWSER_TIME": "Local Navigateur temps", + "LOCATION": "Emplacement", + "LOG": "Journal", + "LOGS": "Journaux", + "LOG_IN": "Connexion", + "LOG_OUT": "Déconnexion", + "LOG_STATISTICS": "Journal Statistiques", + "MAGNET_AND_TORRENT_UPLOAD_FILE_PRIORITIES_LABELS_RATIO_GROUPS_SMART_QUEUE_AUTOMA": "Magnet et Torrent Envoi, Fichier priorités, Étiquettes, Ratio Groupes, Smart Queue, automation Règles, RSS, trafic graphiques, Port vérificateur, system État.", + "MAGNET_LINKS": "Magnet links", + "MANAGE_EXCEPTIONS": "Manage exceptions", + "MANAGE_OPERATION_LOG_RETENTION_WITHOUT_CHANGING_TORRENT_DATA": "Manage operation Journal Rétention sans Changement Torrent Données.", + "MANAGE_OPTIONAL_PYTORRENT_USERS_EMPTY_PROFILE_MEANS_ALL_PROFILES_R_O_BLOCKS_RTOR": "Manage optionnel pyTorrent Utilisateurs. Empty Profil means Tous Profils. R/O blocks rTorrent-Changement Actions; Full allows les.", + "MANUAL_CLEANUP_ONLY": "Manuel Nettoyage seulement", + "MAXIMUM_HEAVY_JOBS_RUNNING_AT_ONCE_FOR_THIS_PROFILE_DEFAULT_5": "Maximum heavy Tâches running at once pour ce Profil. Défaut: 5.", + "MAXIMUM_QUEUED_ACTIONS_RUNNING_AT_ONCE": "Maximum queued Actions running at once.", + "MAXIMUM_STALLED_OVERFLOW_DOWNLOADS_SMART_QUEUE_MAY_STOP_IN_ONE_PASS": "Maximum bloqués/overflow Téléchargements Smart Queue may Arrêter dans un pass.", + "MAX_MB": "Max MB", + "MAX_RATIO": "Max Ratio", + "MAX_STOPS_PER_CHECK": "Max stops per Vérifier", + "MESSAGE": "Message", + "MINUTES": "Minutes", + "MIN_MB": "Min MB", + "MIN_PEERS": "Min Pairs", + "MIN_RATIO": "Min Ratio", + "MIN_SEEDS": "Min Seeds", + "MIN_SEED_MINUTES": "Min seed minutes", + "MIN_SPEED_KIB_S": "Min Vitesse KiB/s", + "MOBILE": "Mobile", + "MOBILE_COLUMNS": "Mobile Colonnes", + "MOBILE_FILTER_GROUPS": "Mobile filtre Groupes", + "MOBILE_SIMPLE_MODE": "Mobile/simple mode", + "MOBILE_SORT_FILTERS": "Mobile sort filters", + "MODE": "Mode", + "MONITORED_PATHS": "Monitored chemins", + "MOVE": "Déplacer", + "MOVE_DATA": "Déplacer Données", + "MOVE_DATA_FILES": "Déplacer Données Fichiers", + "MOVE_PATH": "Déplacer Chemin", + "MOVE_TO_PATH": "Déplacer à Chemin", + "MOVIES": "films", + "MOVING": "Moving", + "M_MOVE": "M - Déplacer", + "NAME": "Nom", + "NEGATE": "Negate", + "NEWLY_QUEUE_STARTED_TORRENTS_ARE_PROTECTED_FROM_STALLED_CLEANUP_DURING_THIS_WARM": "Nouvellement File-démarrés Torrents sont protégés depuis bloqués Nettoyage pendant ce préchauffage-haut.", + "NEW_LABEL": "Nouveau Étiquette", + "NEXT_READY": "Suivant: ready", + "NEXT_SMART_QUEUE_RUN": "Suivant Smart Queue exécution", + "NOTIFICATIONS": "Notifications", + "NOT_LOADED": "Non chargé.", + "NO_CHANGES": "Aucun changement", + "NO_FILES_RETURNED_BY_RTORRENT": "Aucun Fichiers returned par rTorrent.", + "NO_FILES_SELECTED": "Aucun fichier sélectionné.", + "NO_LABELS": "Aucun Étiquettes.", + "NO_LABELS_SELECTED": "Aucune étiquette sélectionnée.", + "NO_PATH_LOADED": "Aucun Chemin loaded.", + "NO_PEERS_RETURNED_BY_RTORRENT": "Aucun Pairs returned par rTorrent.", + "NO_RTORRENT_PROFILE_CONFIGURED": "Aucun rTorrent Profil configured.", + "NO_SAVED_LABELS": "Aucun Enregistré Étiquettes.", + "NO_TORRENTS": "Aucun Torrents.", + "NO_TORRENTS_FOR_THIS_FILTER": "Aucun Torrents pour ce filtre.", + "NO_TORRENTS_SELECTED": "Aucun torrent sélectionné", + "NO_TORRENT_SELECTED": "Aucun torrent sélectionné", + "NO_TRACKERS_RETURNED_BY_RTORRENT": "Aucun Trackers returned par rTorrent.", + "OFF": "Off", + "OFFLINE": "hors ligne", + "ONE_PLACE_TO_CLEAR_LOGS_AND_ACTIVE_PROFILE_CACHES_PENDING_RUNNING_JOBS_RULES_SET": "Un place à Effacer Journaux et Actif Profil caches. En attente/running Tâches, Règles, Paramètres et Torrents sont preserved.", + "ONE_TRACKER_URL_PER_LINE": "Un Tracker URL per line", + "ONLINE": "en ligne", + "ONLY_SELECTED": "Seulement sélectionné", + "OPEN_DOWNLOAD_PLANNER": "Ouvrir Téléchargement planner", + "OPEN_RTORRENT_FILES_MAX_OPEN_FILES": "Ouvrir rTorrent Fichiers / max Ouvrir Fichiers", + "OPEN_RTORRENT_HTTP_CONNECTIONS_MAX_HTTP_CONNECTIONS": "Ouvrir rTorrent HTTP connections / max HTTP connections", + "OPEN_RTORRENT_SOCKETS": "Ouvrir rTorrent sockets", + "OPEN_SOURCE": "Open source", + "OPEN_THIS_TAB_TO_LOAD_DIAGNOSTICS": "Ouvrir ce onglet à charger Diagnostics.", + "OPEN_THIS_TAB_TO_LOAD_STATISTICS": "Ouvrir ce onglet à charger Statistiques.", + "OPERATION_LOG_RETENTION": "Operation Journal Rétention", + "OPTIONAL": "optionnel", + "OPTIONAL_PEER_TABLE_HELPERS": "Optionnel peer table helpers.", + "OPTIONAL_PRIVATE_SOURCE_TAG": "optionnel Privé Source tag", + "OPTIONAL_VISUAL_EASTER_EGG_FOR_LOADING_STATES_AND_OCCASIONAL_BUTTON_CLICKS_DISAB": "Optionnel visual easter egg pour Chargement états et occasionnels bouton clics. Désactivé par Défaut.", + "PARALLEL_JOBS": "Parallel Tâches", + "PARENT_DIRECTORY": "Parent Répertoire", + "PARTIAL_DETAILS_LOADED": "Partial Détails loaded", + "PASSWORD": "Mot de passe", + "PASSWORD_NEW_PASSWORD": "Mot de passe / Nouveau Mot de passe", + "PASTE_ONE_MAGNET_URI_PER_LINE": "Paste un magnet URI per line.", + "PATH": "Chemin", + "PATH_CONTAINS": "Chemin contains", + "PATH_TEXT": "Chemin Texte", + "PATH_USED_FOR_SELECTED_MODE": "Chemin used pour sélectionné mode", + "PAUSE": "Pause", + "PAUSED": "En pause", + "PEAK_S": "Peak S", + "PEAK_SPEED_UNAVAILABLE": "Peak Vitesse unavailable", + "PEERS": "Pairs", + "PEERS_AUTO_REFRESH": "Pairs auto Actualiser", + "PENDING_JOBS_OLDER_THAN_THIS_ARE_RESUBMITTED_IF_NO_WORKER_IS_CURRENTLY_HANDLING_": "En attente Tâches plus anciennes que ce sont renvoyées si Aucun worker est actuellement traite les. Défaut: 900 secondes.", + "PENDING_RUNNING_DONE_FAILED_RETRY_AND_CANCEL_HISTORY": "En attente, running, terminé, échoué, Réessayer et Annuler Historique.", + "PENDING_TIMEOUT_SECONDS": "En attente Timeout secondes", + "PIECE_SIZE": "Piece Taille", + "PLANNER": "Planner", + "POLISH": "Polonais", + "PORT": "Port", + "PORT_CHECKER": "Port vérificateur", + "PORT_CHECK_DISABLED": "Port Vérifier Désactivé", + "PORT_UNKNOWN": "Port - unknown", + "POST_CHECK": "Post-Vérifier", + "PREFERENCES": "Préférences", + "PREFERENCES_SAVED": "Préférences Enregistré", + "PRIORITY": "Priorité", + "PRIVATE_TORRENT": "Privé Torrent", + "PROFILE_BACKUP": "Profil sauvegarde", + "PROFILE_BACKUP_NAME": "Profil sauvegarde Nom", + "PROFILE_BACKUP_RESTORES_ONLY_THE_ACTIVE_PROFILE_CONTEXT_APPLICATION_BACKUP_RESTO": "Profil sauvegarde restores seulement Actif Profil contexte. Application sauvegarde restores global Application Données et est disponibles seulement à administrateurs.", + "PROFILE_NAME": "Profil Nom", + "PROFILE_SCOPED_LOG_COUNTS_AND_CLEANUP_OVERVIEW": "Profil-scoped Journal comptes et Nettoyage aperçu.", + "PROGRESS": "Progression", + "PROGRESS_IS_AT_LEAST": "Progression est at least %", + "PROGRESS_IS_AT_MOST": "Progression est at most %", + "PROGRESS_SOURCE": "Progression Source", + "PROTECT_ACTIVE_COUNT_BELOW_CAP": "Protect Actif count below cap", + "PYTORRENT_EXPECTS_TRUSTED_REVERSE_PROXY_IDENTITY_HEADERS_IF_YOU_ARE_ALREADY_SIGN": "pyTorrent expects trusted reverse-proxy identity headers. Si vous sont already signed dans, Vérifier provider headers et Utilisateur mapping.", + "PYTORRENT_LOGIN": "pyTorrent login", + "PYTORRENT_STATUS": "pyTorrent État", + "P_PAUSE": "P - Pause", + "QUALITY": "Qualité", + "QUEUE_REFILL_DURING_COOLDOWN": "File refill pendant Délai", + "RANDOM_CLICK_IMAGE_URL": "Random click image URL", + "RATIO": "Ratio", + "RATIO_GROUP": "Ratio Groupe", + "RATIO_GROUPS": "Ratio Groupes", + "RATIO_IS_AT_LEAST": "Ratio est at least", + "RATIO_RULES": "Ratio Règles", + "REANNOUNCE": "Reannounce", + "RECHECK": "Revérifier", + "RECHECK_AFTER_MOVE": "Revérifier après Déplacer", + "RECOMMENDED_COLUMNS": "Recommandé Colonnes", + "RECOMMENDED_COLUMNS_APPLIED": "Recommandé Colonnes appliqué", + "RECONNECTING": "reconnecting", + "REFERENCE_VALUE_IS_KEPT_FROM_THE_FIRST_OVERRIDE_SAVE_LATER_SAVES_ADD_OR_CLEAR_DI": "Reference valeur est kept depuis Premier override Enregistrer. Later saves Ajouter ou Effacer differences sans replacing original reference.", + "REFRESH": "Actualiser", + "REFRESH_NOW": "Actualiser now", + "REGEX_TEXT": "Regex / Texte", + "RELOAD": "Reload", + "REMOTE_LOCATION": "Distant Emplacement", + "REMOVE": "Supprimer", + "REMOVE_DATA": "Supprimer Données", + "REMOVE_LABEL": "Supprimer Étiquette", + "REMOVE_SELECTED_TORRENTS": "Supprimer sélectionné Torrents", + "REMOVE_WITH_DATA": "Supprimer avec Données", + "REPOSITORY": "Dépôt", + "RESET": "Réinitialiser", + "RESET_UI_SETTINGS": "Réinitialiser UI Paramètres", + "RESET_VIEW_DEFAULTS": "Réinitialiser view defaults", + "RESIZE_TORRENT_DETAILS_PANEL": "Resize Torrent Détails Panneau", + "RESOLVE_PEER_IP_TO_REVERSE_DNS_HOST": "Resolve peer IP à reverse DNS host", + "RESUME": "Reprendre", + "RETENTION_DAYS": "Rétention jours", + "RETENTION_MODE": "Rétention mode", + "RETRY": "Réessayer", + "REVERSE_DNS": "Reverse DNS", + "RSS_DOWNLOADER": "RSS downloader", + "RTORRENT": "rTorrent", + "RTORRENTS": "rTorrents", + "RTORRENT_CONFIG": "rTorrent Configuration", + "RTORRENT_INCOMING_PORT": "rTorrent incoming Port", + "RTORRENT_IS_STARTING_OR_NOT_RESPONDING_YET": "rTorrent est starting ou non responding yet.", + "RTORRENT_PROFILES": "rTorrent Profils", + "RULE": "Règle", + "RULES": "Règles", + "RULES_ARE_CHECKED_AUTOMATICALLY_EVERY_5_MINUTES_A_TORRENT_USES_THE_GROUP_STORED_": "Règles sont vérifiés automatically every 5 minutes. Torrent uses Groupe stored dans its rTorrent Personnalisé Ratio field.", + "RULE_NAME": "Règle Nom", + "RUNTIME": "Runtime", + "RUN_A_PROFILE_TEST_TO_SHOW_DIAGNOSTICS": "Exécution Profil Test à Afficher Diagnostics.", + "RUN_SMART_QUEUE_DURING_POLLING_STOPPED_TORRENTS_ARE_MANAGED_PAUSED_TORRENTS_STAY": "Exécution Smart Queue pendant polling. Arrêté Torrents sont gérés; En pause Torrents stay Utilisateur-controlled.", + "R_RESUME": "R - Reprendre", + "SAVE": "Enregistrer", + "SAVED_LABELS": "Enregistré Étiquettes", + "SAVE_COLUMNS": "Enregistrer Colonnes", + "SAVE_CONFIG": "Enregistrer Configuration", + "SAVE_EASTER_EGG": "Enregistrer easter egg", + "SAVE_EXCEPTIONS": "Enregistrer exceptions", + "SAVE_FEED": "Enregistrer feed", + "SAVE_FOOTER": "Enregistrer Pied de page", + "SAVE_GROUP": "Enregistrer Groupe", + "SAVE_JOB_SETTINGS": "Enregistrer Tâche Paramètres", + "SAVE_LIMITS": "Enregistrer Limites", + "SAVE_LOCATION": "Enregistrer Emplacement", + "SAVE_LOG_VIEW": "Enregistrer Journal view", + "SAVE_PATH": "Enregistrer Chemin", + "SAVE_PREFERENCES": "Enregistrer Préférences", + "SAVE_RETENTION": "Enregistrer Rétention", + "SAVE_RULE": "Enregistrer Règle", + "SAVE_SCHEDULE": "Enregistrer calendrier", + "SAVE_USER": "Enregistrer Utilisateur", + "SCGI_URL": "SCGI URL", + "SEARCH_LOGS": "Rechercher Journaux...", + "SEARCH_TORRENTS": "Rechercher Torrents...", + "SEARCH_TORRENTS_TO_EXCLUDE": "Rechercher Torrents à Exclure...", + "SEASON": "Saison", + "SECONDS_TO_WAIT_FOR_RTORRENT_RESPONSE": "Secondes à attendre pour rTorrent réponse.", + "SEEDING": "Partage", + "SEEDS": "Seeds", + "SEEDS_ARE_LOW_FOR_TIME": "Seeds sont faible pour temps", + "SEED_MINUTES": "Seed minutes", + "SELECT": "Sélectionner", + "SELECTED": "sélectionné", + "SELECTED_LABELS": "Sélectionné Étiquettes", + "SELECTED_MONITORED_PATH": "Sélectionné monitored Chemin", + "SELECTED_TORRENTS_WILL_BE_REMOVED": "sélectionné Torrents sera être removed.", + "SELECT_A_MONITORED_PATH_FIRST": "Sélectionner monitored Chemin Premier.", + "SELECT_A_TORRENT": "Sélectionner Torrent.", + "SELECT_ONE_OR_MORE_TORRENT_FILES": "Sélectionner un ou more .Torrent Fichiers.", + "SELECT_PATH": "Sélectionner Chemin", + "SELECT_TORRENTS_THAT_SMART_QUEUE_SHOULD_IGNORE_USE_SEARCH_TO_FILTER_BY_NAME_LABE": "Sélectionner Torrents que Smart Queue doit ignorer. Utiliser Rechercher à filtre par Nom, Étiquette, État ou Hash.", + "SELECT_VISIBLE": "Sélectionner visible", + "SEPARATE_SLOT_POOL_FOR_LIGHTWEIGHT_CONTROL_JOBS_SO_THEY_DO_NOT_WAIT_BEHIND_HEAVY": "Separate emplacement pool pour lightweight control Tâches so they do non attendre derrière heavy IO travail. Défaut: 4.", + "SETTINGS": "Paramètres", + "SET_LABEL": "Set Étiquette...", + "SET_LABELS": "Set Étiquettes", + "SET_RATIO_GROUP": "Set Ratio Groupe...", + "SHARE_AFTER_CREATING": "Share après creating", + "SHORTCUTS": "Shortcuts", + "SHOWN": "Shown", + "SHOWN_IN_LOADING_STATES_INSTEAD_OF_THE_STANDARD_SPINNER": "Shown dans Chargement états au lieu de de standard spinner.", + "SHOWS_TRACKER_ICONS_IN_THE_SIDEBAR_TRACKER_FILTER_WHEN_AVAILABLE": "Affiche Tracker icônes dans barre latérale Tracker filtre when disponibles.", + "SHOW_COMBINED_USAGE_SINGLE_PATH_SELECTION_IS_DISABLED_IN_THIS_MODE": "Afficher combinée usage. Unique Chemin selection est Désactivé dans ce mode.", + "SHOW_DL_UP_IN_BROWSER_TITLE": "Afficher DL/UP dans Navigateur Titre", + "SHOW_SMART_QUEUE_AUTOMATIC_RUN_MESSAGES": "Afficher Smart Queue Automatique exécution messages.", + "SHOW_TOASTS_CREATED_BY_AUTOMATION_RUNS": "Afficher toasts created par automation runs.", + "SIGN_IN": "Se connecter", + "SIZE": "Taille", + "SKIP_ACTIVE_UPLOAD": "Skip Actif Envoi", + "SKIP_PRIVATE_TORRENTS": "Skip Privé Torrents", + "SMART_FILTERS": "Smart filters", + "SMART_QUEUE": "Smart Queue", + "SMART_QUEUE_EXCEPTIONS": "Smart Queue exceptions", + "SMART_QUEUE_KEEPS_ONLY_THIS_MANY_ACTIVE_DOWNLOADS_OVERFLOW_IS_STOPPED": "Smart Queue keeps seulement ce many Actif Téléchargements; overflow est Arrêté.", + "SMART_QUEUE_TOASTS": "Smart Queue toasts", + "SOCKETS": "Sockets", + "SOURCE": "Source", + "SPACE_START": "Space - Démarrer", + "SPEED": "Vitesse", + "SPEED_LIMITS": "Vitesse Limites", + "SPEED_TREND": "Vitesse trend", + "STALLED_AFTER_SECONDS": "Bloqués après secondes", + "START": "Démarrer", + "START_AFTER_ADD": "Démarrer après Ajouter", + "START_GRACE_SECONDS": "Démarrer grace secondes", + "STATE": "État", + "STATUS": "État", + "STATUS_EQUALS": "État equals", + "STOP": "Arrêter", + "STOPPED": "Arrêté", + "S_STOP": "S - Arrêter", + "TARGET_ACTIVE_DOWNLOADS": "Cible Actif Téléchargements", + "TARGET_PATH": "Cible Chemin", + "TEST_RULE": "Test Règle", + "TEST_SCGI": "Test SCGI", + "THEME_TYPOGRAPHY_AND_INTERFACE_SCALE": "Thème, typography et interface scale.", + "THE_FOOTER_TOOLTIP_ALWAYS_SHOWS_DETAILS_FOR_AVAILABLE_PATHS_THIS_SETTING_ONLY_DE": "Pied de page infobulle toujours affiche Détails pour disponibles chemins; ce paramètre seulement décide quelle valeur pilote visible Progression barre.", + "TIMEOUT": "Timeout", + "TOAST_NOTIFICATIONS_FROM_AUTOMATIC_SYSTEMS": "Toast Notifications depuis Automatique systems.", + "TOOLS": "Outils", + "TOOLS_RTORRENTS": "Outils & rTorrents", + "TOOLS_SECTIONS": "Outils sections", + "TORRENT_ADDED": "Torrent added", + "TORRENT_COMPLETED": "Torrent Terminé", + "TORRENT_DETAILS": "Torrent Détails", + "TORRENT_FILES": "Torrent Fichiers", + "TORRENT_FILTERS": "Torrent filters", + "TORRENT_PROPERTIES": "Torrent properties", + "TORRENT_REMOVED": "Torrent removed", + "TORRENT_STATISTICS": "Torrent Statistiques", + "TORRENT_STATS": "Torrent stats", + "TOTAL_DL_UP": "Total DL/UP", + "TO_DOWNLOAD": "À Téléchargement", + "TRACKERS": "Trackers", + "TRACKER_ICONS": "Tracker icônes", + "TRANSFER": "Transfer", + "TRANSFERRED_DATA": "Transferred Données", + "TRANSFER_HISTORY": "Transfer Historique", + "UNDEFINED": "undefined", + "UNLIMITED": "Unlimited", + "UPLOADED": "Envoyé", + "UPLOADS": "Envois", + "UPLOAD_KIB_S": "Envoi KiB/s", + "USER": "Utilisateur", + "USERS": "Utilisateurs", + "USES_A_LIGHTWEIGHT_BUILT_IN_RESOLVER_WITH_CACHE_HOSTNAMES_APPEAR_ONLY_IN_THE_PEE": "Uses lightweight built-dans résolveur avec cache. Noms d’hôte appear seulement dans Pairs onglet.", + "USES_LOWER_ROWS_AND_SMALLER_LIST_ELEMENTS_ON_DESKTOP_AND_MOBILE_SO_MORE_TORRENTS": "Uses plus basses lignes et smaller liste elements on Bureau et Mobile so more Torrents tiennent on écran.", + "USES_YOUGETSIGNAL_FIRST_MANUAL_CHECK_BYPASSES_THE_6H_CACHE": "Uses YouGetSignal Premier. Manuel Vérifier bypasses 6h cache.", + "USE_ONE_CUSTOM_PATH_BELOW_AS_THE_FOOTER_PROGRESS_VALUE": "Utiliser un Personnalisé Chemin below comme Pied de page Progression valeur.", + "USE_SELECTED": "Utiliser sélectionné", + "USE_THE_MAIN_DIRECTORY_FROM_THE_ACTIVE_RTORRENT_PROFILE": "Utiliser main Répertoire depuis Actif rTorrent Profil.", + "VIEW_PREFERENCES_RESET": "View Préférences Réinitialiser", + "VIEW_STATE_IS_SAVED_AUTOMATICALLY_IN_THE_DATABASE_CURRENT_TORRENT_FILTER_LAST_SO": "View État est Enregistré automatically dans database: Actuel Torrent filtre, Dernier sort column et direction, visible Colonnes, et Détails Panneau height.", + "VISIBLE_NAME_USED_IN_THE_PROFILE_SELECTOR": "Visible Nom used dans Profil selector.", + "VISUAL_HELPER_FOR_TRACKER_FILTERS_IN_THE_SIDEBAR": "Visual assistant pour Tracker filters dans barre latérale.", + "WAITING_FOR_DATA": "Attente pour Données.", + "WAITING_FOR_TORRENT_DATA_FROM_THE_ACTIVE_PROFILE": "Attente pour Torrent Données depuis Actif Profil.", + "WATCHDOG_MARKS_A_LIGHT_JOB_AS_FAILED_AFTER_THIS_TIME_DEFAULT_300_SECONDS": "Watchdog marks light Tâche comme échoué après ce temps. Défaut: 300 secondes.", + "WATCHDOG_TIMEOUT_FOR_MOVE_REMOVE_ADD_JOBS_DEFAULT_7200_SECONDS": "Watchdog Timeout pour Déplacer/Supprimer/Ajouter Tâches. Défaut: 7200 secondes.", + "WHEN_DISABLED_THE_APPLICATION_USES_THE_NORMAL_PRODUCTION_UI": "When Désactivé, Application uses normale production UI.", + "WHEN_ENABLED_LOW_SPEED_IS_NOT_REQUIRED_WITH_SOURCE_AND_SPEED_IGNORES_ENABLED_ONL": "When Activé, faible Vitesse est non required. Avec Source et Vitesse ignores Activé, seulement Bloqués après secondes décide.", + "WHEN_ENABLED_SMART_QUEUE_DOES_NOT_USE_SEED_PEER_COUNT_AS_A_STALLED_CRITERION": "When Activé, Smart Queue does non utiliser seed/peer count comme bloqués critère.", + "WITH_ERROR": "Avec Erreur", + "WORKING": "Traitement...", + "FRENCH": "Français", + "CZECH": "Tchèque", + "SPANISH": "Espagnol", + "NORWEGIAN": "Norvégien", + "RUSSIAN": "Russe" + } +} diff --git a/pytorrent/static/i18n/nb_NO.json b/pytorrent/static/i18n/nb_NO.json new file mode 100644 index 0000000..ee78d04 --- /dev/null +++ b/pytorrent/static/i18n/nb_NO.json @@ -0,0 +1,566 @@ +{ + "meta": { + "locale": "nb_NO", + "label": "Norsk bokmål", + "flag": "no" + }, + "translations": { + "0_MEANS_ONLY_SEED_THRESHOLD_IS_REQUIRED": "0 means bare seed threshold er required.", + "0_MEANS_UNLIMITED_SLIDERS_USE_MBIT_S_AND_SAVE_THROUGH_THE_EXISTING_SPEED_LIMITS_": "0 means unlimited. Sliders bruk Mbit/s og Lagre through existing Hastighet Grenser API.", + "0_SELECTED": "0 valgt", + "ABOUT_PYTORRENT": "About pyTorrent", + "ACTION": "Handling", + "ACTIVE": "Aktiv", + "ACTIVE_RTORRENT_DOWNLOADS_MAX_GLOBAL_DOWNLOADS": "Aktiv rTorrent Nedlastinger / max global Nedlastinger", + "ACTIVE_RTORRENT_UPLOADS_MAX_GLOBAL_UPLOADS": "Aktiv rTorrent Opplastinger / max global Opplastinger", + "ADD": "Legg til", + "ADDED": "Added", + "ADDS_REMOVALS_COMPLETIONS_AND_QUEUED_OPERATION_RESULTS": "Adds, removals, completions og queued operation results.", + "ADD_ACTION": "Legg til Handling", + "ADD_CONDITION": "Legg til Betingelse", + "ADD_CREATE_TORRENT": "Legg til / Opprett Torrent", + "ADD_FIRST_LABEL_ABOVE": "Legg til Første Etikett above.", + "ADD_LABEL": "Legg til Etikett", + "ADD_MAGNET_LINK": "Legg til magnet link", + "ADD_NEW_LABEL": "Legg til Ny Etikett", + "ADD_OR_EDIT_GROUP": "Legg til eller Rediger Gruppe", + "ADD_PATH": "Legg til Sti", + "ADD_PROFILE": "Legg til Profil", + "ADD_RTORRENT_PROFILE": "Legg til rTorrent Profil", + "ADD_THE_FIRST_RTORRENT_PROFILE_TO_START_LOADING_TORRENTS": "Legg til Første rTorrent Profil til Start Laster Torrenter.", + "ADD_TORRENT": "Legg til Torrent", + "ADD_TORRENT_FILE": "Legg til Torrent Fil", + "ADMIN": "Administrator", + "ADMIN_ONLY_FULL_APPLICATION_BACKUP_RESTORE_CAN_REPLACE_USERS_PERMISSIONS_PROFILE": "Administrator-bare full Applikasjon sikkerhetskopi. Gjenopprett kan replace Brukere, permissions, Profiler og global Applikasjon Innstillinger.", + "AGGREGATE_ALL_PATHS": "Aggregate Alle stier", + "ALL": "Alle", + "ALL_NON_JOB_TYPES": "Alle non-Jobb types", + "ALL_PROFILES": "Alle Profiler", + "ALL_TYPES": "Alle types", + "ANNOUNCE": "Announce", + "API_DOCS": "API docs", + "APPEARANCE": "Utseende", + "APPEARANCE_PREFERENCES_SAVED": "Utseende Innstillinger Lagret", + "APPEARS_NEAR_CLICKED_BUTTONS_ONLY_SOMETIMES": "Appears near clicked buttons bare sometimes.", + "APPLICATION_BACKUP": "Applikasjon sikkerhetskopi", + "APPLICATION_BACKUP_NAME": "Applikasjon sikkerhetskopi Navn", + "APPLY": "Apply", + "APPLY_RETENTION_NOW": "Apply Oppbevaring now", + "APPLY_SAVED_CHANGES_60S_AFTER_PYTORRENT_START": "Apply Lagret changes 60s etter pyTorrent Start", + "APP_STATUS": "App Status", + "AUTHENTICATION_IS_ENABLED_FOR_THIS_PYTORRENT_INSTANCE": "Authentication er Aktivert for denne pyTorrent instans.", + "AUTHOR": "Forfatter", + "AUTOMATIC": "Automatisk", + "AUTOMATIC_KEEPS_THE_CURRENT_POLLER_CADENCE_CUSTOM_RUNS_ONLY_AFTER_THE_SELECTED_N": "Automatisk keeps Gjeldende poller cadence. Egendefinert runs bare etter valgt number minutter. Off disables refill completely.", + "AUTOMATIC_QUEUE_BALANCING_FOR_SLOW_OR_STALLED_DOWNLOADS": "Automatisk Kø balansering for trege eller stoppede Nedlastinger.", + "AUTOMATIC_RUNS_USE_THE_COOLDOWN_BELOW_MANUAL_CHECK_NOW_STILL_RUNS_IMMEDIATELY": "Automatisk runs bruk Nedkjøling below. Manuell Sjekk now still runs immediately.", + "AUTOMATIONS": "Automations", + "AUTOMATIONS_RULES": "Automations / Regler", + "AUTOMATION_TOASTS": "Automation toasts", + "AUTO_STOP_WHEN_IDLE": "Auto-Stopp when idle", + "BACKEND": "Backend", + "BACKUP": "Sikkerhetskopi", + "BACKUP_RESTORE": "Sikkerhetskopi / Gjenopprett", + "BACK_TO_DASHBOARD": "Back til dashboard", + "BOOTSTRAP_THEME": "Bootstrap Tema", + "BROWSER": "Nettleser", + "BROWSER_TITLE": "Nettleser Tittel", + "BUILD_A_RULE_AS_CONDITIONS_FIRST_THEN_ORDERED_ACTIONS_MATCHING_TORRENTS_ARE_HAND": "Build Regel som: Betingelser Første, deretter ordered Handlinger. Matching Torrenter er handled som én batch og Nedkjøling er brukt til whole Regel.", + "BUSY": "busy", + "BY_DAYS": "Etter dager", + "BY_LINE_COUNT": "Etter line count", + "CACHED_METADATA_SUMMARY_FILE_METADATA_IS_REFRESHED_EVERY_15_MINUTES_A_FEW_MINUTE": "Cached metadata summary. Fil metadata er refreshed every 15 minutter, noen minutter etter oppstart, eller manually.", + "CANCEL": "Avbryt", + "CANCEL_EDIT": "Avbryt Rediger", + "CATEGORY": "Kategori", + "CHANGES_APPLY_IMMEDIATELY_WHERE_POSSIBLE_INITIAL_STARTUP_LOADER_USES_THEM_AFTER_": "Changes apply immediately where possible; initial oppstart loader uses dem etter reload.", + "CHANGE_RTORRENT": "Endre rTorrent", + "CHANGE_THEME": "Endre Tema", + "CHANGING_RTORRENT_RELOADS_THE_LIVE_TORRENT_SNAPSHOT": "Endring rTorrent reloads live Torrent øyeblikksbilde.", + "CHECKING": "Sjekker", + "CHECK_NOW": "Sjekk nå", + "CHECK_PORT_NOW": "Sjekk port nå", + "CHECK_THIS_IF_YOU_WANT_TO_CONNECT_TO_A_REMOTE_RTORRENT_INSTANCE_INSTEAD_OF_LOCAL": "Sjekk denne hvis du vil til koble til til Ekstern rTorrent instans i stedet for localhost.", + "CHOOSE_COLUMNS_VISIBLE_IN_THE_TORRENT_LIST": "Velg Kolonner synlig i Torrent liste.", + "CHOOSE_FILES": "Velg Filer", + "CHOOSE_RTORRENT": "Velg rTorrent", + "CHOOSE_TORRENTS_IGNORED_BY_SMART_QUEUE_EXISTING_BEHAVIOR_STAYS_UNCHANGED_FOR_ALL": "Velg Torrenter ignored etter Smart Queue. Existing behavior stays unchanged for Alle non-excluded Torrenter.", + "CHOOSE_WHAT_THE_FOOTER_DISK_BAR_SHOULD_REPRESENT_AND_ADD_EXTRA_STORAGE_PATHS": "Velg what Bunnlinje disk linje skal represent og Legg til extra storage stier.", + "CHOOSE_WHICH_STATUS_ITEMS_ARE_VISIBLE_IN_THE_BOTTOM_BAR": "Velg hvilken Status items er synlig i bottom linje.", + "CHUNKS": "Chunks", + "CLEANUP": "Opprydding", + "CLEANUP_RETENTION": "Opprydding / Oppbevaring", + "CLEAR": "Tøm", + "CLEAR_CURRENT_FILTER": "Tøm Gjeldende filter", + "CLEAR_FINISHED": "Tøm finished", + "CLEAR_LABELS": "Tøm Etiketter", + "CLEAR_SELECTION": "Tøm selection", + "CLEAR_VISIBLE": "Tøm synlig", + "CLOSE": "Lukk", + "COLUMNS": "Kolonner", + "COLUMNS_SAVED": "Kolonner Lagret", + "COMMENT": "Comment", + "COMPACT_TORRENT_LIST": "Compact Torrent liste", + "COMPLETE": "Complete", + "COMPLETED": "Fullført", + "CONFIGURED_RTORRENTS": "Configured rTorrents", + "CONNECTING_TO_RTORRENT_AND_PREPARING_DATA": "Connecting til rTorrent og preparing Data.", + "CONNECTION_ADDRESS_IN_SCGI_HOST_PORT_RPC2_FORMAT": "Tilkobling address i scgi://host:Port/RPC2 format.", + "CONTROLS_THE_DEFAULT_CATEGORY_AND_JOB_LOG_VISIBILITY_USED_BY_THE_LOGS_MODAL": "Controls Standard Kategori og Jobb Logg visibility used etter Logger modal.", + "CONTROLS_WHAT_IS_SHOWN_IN_THE_BROWSER_TAB": "Controls what er shown i Nettleser fane.", + "COOLDOWN_MINUTES": "Nedkjøling minutter", + "COPY": "Kopier", + "COPY_HASH": "Kopier Hash", + "COPY_NAME": "Kopier Navn", + "COPY_PATH": "Kopier Sti", + "CPU_RAM_USAGE": "CPU / RAM usage", + "CREATE": "Opprett", + "CREATES_AND_RESTORES_SETTINGS_FOR_THE_CURRENTLY_SELECTED_PROFILE_USER_SCOPED_PRE": "Creates og restores Innstillinger for for øyeblikket valgt Profil. Bruker-scoped Innstillinger er remapped til Gjeldende Bruker where needed.", + "CREATE_APPLICATION_BACKUP": "Opprett Applikasjon sikkerhetskopi", + "CREATE_ONE_RTORRENT_PROFILE_AT_A_TIME_MOVE_REMOVE_QUEUES_KEEP_THEIR_ORDER_FOR_EA": "Opprett én rTorrent Profil at tid. Flytt/Fjern queues keep deres order for hver Profil.", + "CREATE_PROFILE_BACKUP": "Opprett Profil sikkerhetskopi", + "CREATE_REUSABLE_LABELS_AND_REMOVE_LABELS_THAT_ARE_NO_LONGER_NEEDED": "Opprett gjenbrukbare Etiketter og Fjern Etiketter at er Ingen lenger needed.", + "CREATE_TORRENT": "Opprett Torrent", + "CTRL_A_SELECT_VISIBLE": "Ctrl+ - Velg synlig", + "CTRL_I_INVERT_VISIBLE": "Ctrl+I - invert synlig", + "CTRL_O_ADD": "Ctrl+O - Legg til", + "CTRL_S_DOWNLOAD_TORRENT": "Ctrl+S - Nedlasting .Torrent", + "CURRENT_TRANSFER_SPEED": "Gjeldende transfer Hastighet", + "CUSTOM_DOWNLOAD": "Egendefinert Nedlasting", + "CUSTOM_UPLOAD": "Egendefinert Opplasting", + "DAYS_AND_LINE_COUNT": "Dager og line count", + "DECREASE_OR_INCREASE_THE_WHOLE_INTERFACE_SIZE": "Decrease eller increase whole interface Størrelse.", + "DEFAULT_LOG_CATEGORY": "Standard Logg Kategori", + "DEFAULT_LOG_VIEW": "Standard Logg view", + "DEFAULT_RTORRENT_PATH": "Standard rTorrent Sti", + "DEGRADED": "degraded", + "DELETE": "Slett", + "DELETE_REMOVE": "Slett - Fjern", + "DESKTOP": "Skrivebord", + "DETAILS_WILL_APPEAR_AFTER_THE_FIRST_SUCCESSFUL_RESPONSE": "Detaljer vil appear etter Første vellykket svar.", + "DIAGNOSTICS": "Diagnostikk", + "DISABLED": "Deaktivert", + "DISK_MONITOR": "Disk monitor", + "DISK_USAGE_UNAVAILABLE": "Disk usage unavailable", + "DISPLAYS_CURRENT_SPEEDS_NEXT_TO_PYTORRENT_IN_THE_TAB_TITLE": "Displays Gjeldende speeds Neste til pyTorrent i fane Tittel.", + "DOCS_API": "Docs API", + "DOWNLOADED": "Lastet ned", + "DOWNLOADING": "Laster ned", + "DOWNLOADS": "Nedlastinger", + "DOWNLOAD_KIB_S": "Nedlasting KiB/s", + "DOWNLOAD_STARTED": "Nedlasting startede", + "DOWNLOAD_TORRENT": "Nedlasting .Torrent", + "DOWNLOAD_TRACKER_FAVICONS": "Nedlasting Tracker favicons", + "DRAG_TO_RESIZE_DETAILS_PANEL": "Drag til resize Detaljer Panel", + "EASTER_EGG": "Easter egg", + "EDIT": "Rediger", + "EMERGENCY_CANCEL": "Emergency Avbryt", + "EMERGENCY_CLEAN_ALL": "Emergency clean Alle", + "ENABLED": "Aktivert", + "ENABLE_AUTOMATIC_APPLICATION_BACKUPS": "Aktiver Automatisk Applikasjon sikkerhetskopier", + "ENABLE_AUTOMATIC_PROFILE_BACKUPS": "Aktiver Automatisk Profil sikkerhetskopier", + "ENABLE_EASTER_EGG": "Aktiver easter egg", + "ENABLE_INCOMING_PORT_CHECK": "Aktiver incoming Port Sjekk", + "ENABLE_REVERSE_DNS_FOR_PEERS": "Aktiver reverse DNS for Peers", + "ENGLISH": "Engelsk", + "EPISODE": "Episode", + "ESC_CLEAR_SELECTION": "Esc - Tøm selection", + "ETA": "ETA", + "EVERY_N_MINUTES": "Every N minutter", + "EVERY_X_HOURS": "Every X hours", + "EXCLUDE": "Ekskluder", + "EXCLUDE_FROM_SMART_QUEUE": "Ekskluder fra Smart Queue", + "EXCLUDE_PATTERN": "Ekskluder Mønster", + "EXISTING_GROUPS": "Existing Grupper", + "EXPORT": "Eksport", + "EXPORT_JSON": "Eksport JSON", + "EXTERNAL_AUTHENTICATION_IS_ENABLED_THROUGH_EXTERNAL_PROVIDER": "External authentication er Aktivert through {{ external_provider }}.", + "E_G_PUNKTY_KATALOGOWANIE": "e.g. Punkty katalogowanie", + "FEATURES": "Funksjoner", + "FEED": "Feed", + "FEEDS_ARE_CHECKED_BY_SCHEDULE_AND_EVERY_MATCH_IS_LOGGED_PER_FEED_RULE": "Feeds er sjekkes etter plan og every treff er loggført per feed/Regel.", + "FEEDS_RULES_AND_MATCHES": "Feeds, Regler og treff", + "FEED_NAME": "Feed Navn", + "FEED_URL": "Feed URL", + "FILES": "Filer", + "FILE_OR_DIRECTORY_PATH": "Fil eller Mappe Sti", + "FONT": "Skrift", + "FOOTER": "Bunnlinje", + "FORCE": "Tving", + "FORCE_RECHECK": "Tving Sjekk på nytt", + "FRONTEND": "Frontend", + "FULL": "Full", + "GENERAL": "Generelt", + "GENERATED_RTORRENT_CONFIG_CHANGES_WILL_APPEAR_HERE": "Generert rTorrent Konfigurasjon changes vil appear here.", + "GENERATE_CONFIG": "Generate Konfigurasjon", + "GERMAN": "Tysk", + "GO": "Go", + "GROUPED_RTORRENT_RUNTIME_SETTINGS_WITH_INLINE_RECOMMENDATIONS_AND_COMPATIBILITY_": "Grupperte rTorrent Runtime Innstillinger med inline anbefalinger og kompatibilitet Status.", + "GROUP_NAME": "Gruppe Navn", + "HASH": "Hash", + "HASHING": "Hashing", + "HEAVY_PARALLEL_JOBS": "Heavy parallel Jobber", + "HEAVY_TIMEOUT_SECONDS": "Heavy Tidsavbrudd sekunder", + "HIDE_JOB_LOGS": "Skjul Jobb Logger", + "HIDE_JOB_LOGS_BY_DEFAULT": "Skjul Jobb Logger etter Standard", + "HISTORY": "Historikk", + "HOW_LONG_A_MATCHING_ACTIVE_TORRENT_MUST_STAY_STALLED_BEFORE_IT_CAN_BE_REPLACED": "Hvor lenge matching Aktiv Torrent må stay stoppede før it kan være erstattet.", + "IGNORE_MISSING_SEEDS_PEERS_FOR_STALLED_TIMER": "Ignorere missing Seeds/Peers for stoppede timer", + "IGNORE_SPEED_FOR_STALLED_TIMER": "Ignorere Hastighet for stoppede timer", + "IMPORT": "Import", + "IMPORT_JSON": "Import JSON", + "INCLUDE_PATTERN": "Inkluder Mønster", + "INCOMING_CONNECTION_TEST_SEPARATE_FROM_VISUAL_PREFERENCES": "Incoming Tilkobling Test, separate fra visual Innstillinger.", + "INTERFACE_SCALE": "Interface scale", + "INTERVAL_MINUTES": "Intervall minutter", + "INVERT_VISIBLE": "invert synlig", + "JOBS": "Jobber", + "JOB_DONE": "Jobb ferdig", + "JOB_FAILED": "Jobb mislyktes", + "JOB_QUEUE": "Jobb Kø", + "JOB_SCHEDULING": "Jobb scheduling", + "JOB_STARTED": "Jobb startede", + "KEEP_LINES": "Keep lines", + "KEEP_SEEDING": "Keep Seeding", + "LABEL": "Etikett", + "LABELS": "Etiketter", + "LABELS_SEPARATED_BY_COMMA": "Etiketter separated etter comma", + "LABEL_AFTER_SHARE": "Etikett etter share", + "LABEL_EXISTS": "Etikett exists", + "LABEL_IS_MISSING": "Etikett er missing", + "LABEL_NAME_OR_SEVERAL_SEPARATED_BY_COMMA": "Etikett Navn, eller flere separated etter comma", + "LANGUAGE": "Språk", + "LANGUAGE_SAVED": "Språk Lagret", + "LAST_OPERATIONS": "Siste operations", + "LICENSE": "Lisens", + "LIGHTWEIGHT_WEB_PANEL_FOR_RTORRENT_MANAGEMENT_QUEUE_CONTROL_AND_LIVE_TORRENT_DIA": "Lightweight web Panel for rTorrent management, Kø control og live Torrent Diagnostikk.", + "LIGHT_PARALLEL_JOBS": "Light parallel Jobber", + "LIGHT_TIMEOUT_SECONDS": "Light Tidsavbrudd sekunder", + "LIMIT_DL": "Grense DL", + "LOADING": "Laster", + "LOADING_CLEANUP_DATA": "Laster Opprydding Data...", + "LOADING_CONFIG": "Laster Konfigurasjon...", + "LOADING_IMAGE_URL": "Laster image URL", + "LOADING_JOBS": "Laster Jobber...", + "LOADING_LOGS": "Laster Logger...", + "LOADING_PROFILES": "Laster Profiler...", + "LOADING_STATISTICS": "Laster Statistikk...", + "LOADING_TORRENTS": "Laster Torrenter...", + "LOADING_TORRENT_DETAILS": "Laster Torrent Detaljer...", + "LOCAL_BROWSER_TIME": "Lokal Nettleser tid", + "LOCATION": "Plassering", + "LOG": "Logg", + "LOGS": "Logger", + "LOG_IN": "Logg inn", + "LOG_OUT": "Logg ut", + "LOG_STATISTICS": "Logg Statistikk", + "MAGNET_AND_TORRENT_UPLOAD_FILE_PRIORITIES_LABELS_RATIO_GROUPS_SMART_QUEUE_AUTOMA": "Magnet og Torrent Opplasting, Fil prioriteter, Etiketter, Ratio Grupper, Smart Queue, automation Regler, RSS, trafikk diagrammer, Port sjekker, system Status.", + "MAGNET_LINKS": "Magnet links", + "MANAGE_EXCEPTIONS": "Manage exceptions", + "MANAGE_OPERATION_LOG_RETENTION_WITHOUT_CHANGING_TORRENT_DATA": "Manage operation Logg Oppbevaring uten Endring Torrent Data.", + "MANAGE_OPTIONAL_PYTORRENT_USERS_EMPTY_PROFILE_MEANS_ALL_PROFILES_R_O_BLOCKS_RTOR": "Manage valgfritt pyTorrent Brukere. Empty Profil means Alle Profiler. R/O blocks rTorrent-Endring Handlinger; Full allows dem.", + "MANUAL_CLEANUP_ONLY": "Manuell Opprydding bare", + "MAXIMUM_HEAVY_JOBS_RUNNING_AT_ONCE_FOR_THIS_PROFILE_DEFAULT_5": "Maksimum heavy Jobber running at once for denne Profil. Standard: 5.", + "MAXIMUM_QUEUED_ACTIONS_RUNNING_AT_ONCE": "Maksimum queued Handlinger running at once.", + "MAXIMUM_STALLED_OVERFLOW_DOWNLOADS_SMART_QUEUE_MAY_STOP_IN_ONE_PASS": "Maksimum stoppede/overflow Nedlastinger Smart Queue may Stopp i én pass.", + "MAX_MB": "Max MB", + "MAX_RATIO": "Max Ratio", + "MAX_STOPS_PER_CHECK": "Max stops per Sjekk", + "MESSAGE": "Melding", + "MINUTES": "Minutter", + "MIN_MB": "Min MB", + "MIN_PEERS": "Min Peers", + "MIN_RATIO": "Min Ratio", + "MIN_SEEDS": "Min Seeds", + "MIN_SEED_MINUTES": "Min seed minutter", + "MIN_SPEED_KIB_S": "Min Hastighet KiB/s", + "MOBILE": "Mobil", + "MOBILE_COLUMNS": "Mobil Kolonner", + "MOBILE_FILTER_GROUPS": "Mobil filter Grupper", + "MOBILE_SIMPLE_MODE": "Mobil/simple mode", + "MOBILE_SORT_FILTERS": "Mobil sort filters", + "MODE": "Mode", + "MONITORED_PATHS": "Monitored stier", + "MOVE": "Flytt", + "MOVE_DATA": "Flytt Data", + "MOVE_DATA_FILES": "Flytt Data Filer", + "MOVE_PATH": "Flytt Sti", + "MOVE_TO_PATH": "Flytt til Sti", + "MOVIES": "filmer", + "MOVING": "Moving", + "M_MOVE": "M - Flytt", + "NAME": "Navn", + "NEGATE": "Negate", + "NEWLY_QUEUE_STARTED_TORRENTS_ARE_PROTECTED_FROM_STALLED_CLEANUP_DURING_THIS_WARM": "Nylig Kø-startede Torrenter er beskyttet fra stoppede Opprydding under denne oppvarming-opp.", + "NEW_LABEL": "Ny Etikett", + "NEXT_READY": "Neste: ready", + "NEXT_SMART_QUEUE_RUN": "Neste Smart Queue kjøring", + "NOTIFICATIONS": "Varsler", + "NOT_LOADED": "Ikke lastet.", + "NO_CHANGES": "Ingen endringer", + "NO_FILES_RETURNED_BY_RTORRENT": "Ingen Filer returned etter rTorrent.", + "NO_FILES_SELECTED": "Ingen filer valgt.", + "NO_LABELS": "Ingen Etiketter.", + "NO_LABELS_SELECTED": "Ingen etiketter valgt.", + "NO_PATH_LOADED": "Ingen Sti loaded.", + "NO_PEERS_RETURNED_BY_RTORRENT": "Ingen Peers returned etter rTorrent.", + "NO_RTORRENT_PROFILE_CONFIGURED": "Ingen rTorrent Profil configured.", + "NO_SAVED_LABELS": "Ingen Lagret Etiketter.", + "NO_TORRENTS": "Ingen Torrenter.", + "NO_TORRENTS_FOR_THIS_FILTER": "Ingen Torrenter for denne filter.", + "NO_TORRENTS_SELECTED": "Ingen torrenter valgt", + "NO_TORRENT_SELECTED": "Ingen torrent valgt", + "NO_TRACKERS_RETURNED_BY_RTORRENT": "Ingen Trackere returned etter rTorrent.", + "OFF": "Off", + "OFFLINE": "frakoblet", + "ONE_PLACE_TO_CLEAR_LOGS_AND_ACTIVE_PROFILE_CACHES_PENDING_RUNNING_JOBS_RULES_SET": "Én place til Tøm Logger og Aktiv Profil caches. Ventende/running Jobber, Regler, Innstillinger og Torrenter er preserved.", + "ONE_TRACKER_URL_PER_LINE": "Én Tracker URL per line", + "ONLINE": "på nett", + "ONLY_SELECTED": "Bare valgt", + "OPEN_DOWNLOAD_PLANNER": "Åpne Nedlasting planner", + "OPEN_RTORRENT_FILES_MAX_OPEN_FILES": "Åpne rTorrent Filer / max Åpne Filer", + "OPEN_RTORRENT_HTTP_CONNECTIONS_MAX_HTTP_CONNECTIONS": "Åpne rTorrent HTTP connections / max HTTP connections", + "OPEN_RTORRENT_SOCKETS": "Åpne rTorrent sockets", + "OPEN_SOURCE": "Open source", + "OPEN_THIS_TAB_TO_LOAD_DIAGNOSTICS": "Åpne denne fane til laste Diagnostikk.", + "OPEN_THIS_TAB_TO_LOAD_STATISTICS": "Åpne denne fane til laste Statistikk.", + "OPERATION_LOG_RETENTION": "Operation Logg Oppbevaring", + "OPTIONAL": "valgfritt", + "OPTIONAL_PEER_TABLE_HELPERS": "Valgfritt peer table helpers.", + "OPTIONAL_PRIVATE_SOURCE_TAG": "valgfritt Privat Kilde tag", + "OPTIONAL_VISUAL_EASTER_EGG_FOR_LOADING_STATES_AND_OCCASIONAL_BUTTON_CLICKS_DISAB": "Valgfritt visual easter egg for Laster tilstander og sporadiske knapp klikk. Deaktivert etter Standard.", + "PARALLEL_JOBS": "Parallel Jobber", + "PARENT_DIRECTORY": "Overordnet Mappe", + "PARTIAL_DETAILS_LOADED": "Partial Detaljer loaded", + "PASSWORD": "Passord", + "PASSWORD_NEW_PASSWORD": "Passord / Ny Passord", + "PASTE_ONE_MAGNET_URI_PER_LINE": "Paste én magnet URI per line.", + "PATH": "Sti", + "PATH_CONTAINS": "Sti contains", + "PATH_TEXT": "Sti Tekst", + "PATH_USED_FOR_SELECTED_MODE": "Sti used for valgt mode", + "PAUSE": "Pause", + "PAUSED": "Pauset", + "PEAK_S": "Peak S", + "PEAK_SPEED_UNAVAILABLE": "Peak Hastighet unavailable", + "PEERS": "Peers", + "PEERS_AUTO_REFRESH": "Peers auto Oppdater", + "PENDING_JOBS_OLDER_THAN_THIS_ARE_RESUBMITTED_IF_NO_WORKER_IS_CURRENTLY_HANDLING_": "Ventende Jobber eldre enn denne er sendes på nytt hvis Ingen worker er for øyeblikket håndterer dem. Standard: 900 sekunder.", + "PENDING_RUNNING_DONE_FAILED_RETRY_AND_CANCEL_HISTORY": "Ventende, running, ferdig, mislyktes, Prøv igjen og Avbryt Historikk.", + "PENDING_TIMEOUT_SECONDS": "Ventende Tidsavbrudd sekunder", + "PIECE_SIZE": "Piece Størrelse", + "PLANNER": "Planner", + "POLISH": "Polsk", + "PORT": "Port", + "PORT_CHECKER": "Port sjekker", + "PORT_CHECK_DISABLED": "Port Sjekk Deaktivert", + "PORT_UNKNOWN": "Port - unknown", + "POST_CHECK": "Post-Sjekk", + "PREFERENCES": "Innstillinger", + "PREFERENCES_SAVED": "Innstillinger Lagret", + "PRIORITY": "Prioritet", + "PRIVATE_TORRENT": "Privat Torrent", + "PROFILE_BACKUP": "Profil sikkerhetskopi", + "PROFILE_BACKUP_NAME": "Profil sikkerhetskopi Navn", + "PROFILE_BACKUP_RESTORES_ONLY_THE_ACTIVE_PROFILE_CONTEXT_APPLICATION_BACKUP_RESTO": "Profil sikkerhetskopi restores bare Aktiv Profil kontekst. Applikasjon sikkerhetskopi restores global Applikasjon Data og er tilgjengelige bare til administratorer.", + "PROFILE_NAME": "Profil Navn", + "PROFILE_SCOPED_LOG_COUNTS_AND_CLEANUP_OVERVIEW": "Profil-scoped Logg antall og Opprydding oversikt.", + "PROGRESS": "Fremdrift", + "PROGRESS_IS_AT_LEAST": "Fremdrift er at least %", + "PROGRESS_IS_AT_MOST": "Fremdrift er at most %", + "PROGRESS_SOURCE": "Fremdrift Kilde", + "PROTECT_ACTIVE_COUNT_BELOW_CAP": "Protect Aktiv count below cap", + "PYTORRENT_EXPECTS_TRUSTED_REVERSE_PROXY_IDENTITY_HEADERS_IF_YOU_ARE_ALREADY_SIGN": "pyTorrent expects trusted reverse-proxy identity headers. Hvis du er already signed i, Sjekk provider headers og Bruker mapping.", + "PYTORRENT_LOGIN": "pyTorrent login", + "PYTORRENT_STATUS": "pyTorrent Status", + "P_PAUSE": "P - Pause", + "QUALITY": "Kvalitet", + "QUEUE_REFILL_DURING_COOLDOWN": "Kø refill under Nedkjøling", + "RANDOM_CLICK_IMAGE_URL": "Random click image URL", + "RATIO": "Ratio", + "RATIO_GROUP": "Ratio Gruppe", + "RATIO_GROUPS": "Ratio Grupper", + "RATIO_IS_AT_LEAST": "Ratio er at least", + "RATIO_RULES": "Ratio Regler", + "REANNOUNCE": "Reannounce", + "RECHECK": "Sjekk på nytt", + "RECHECK_AFTER_MOVE": "Sjekk på nytt etter Flytt", + "RECOMMENDED_COLUMNS": "Anbefalt Kolonner", + "RECOMMENDED_COLUMNS_APPLIED": "Anbefalt Kolonner brukt", + "RECONNECTING": "reconnecting", + "REFERENCE_VALUE_IS_KEPT_FROM_THE_FIRST_OVERRIDE_SAVE_LATER_SAVES_ADD_OR_CLEAR_DI": "Reference verdi er kept fra Første override Lagre. Later saves Legg til eller Tøm differences uten replacing original reference.", + "REFRESH": "Oppdater", + "REFRESH_NOW": "Oppdater now", + "REGEX_TEXT": "Regex / Tekst", + "RELOAD": "Reload", + "REMOTE_LOCATION": "Ekstern Plassering", + "REMOVE": "Fjern", + "REMOVE_DATA": "Fjern Data", + "REMOVE_LABEL": "Fjern Etikett", + "REMOVE_SELECTED_TORRENTS": "Fjern valgt Torrenter", + "REMOVE_WITH_DATA": "Fjern med Data", + "REPOSITORY": "Repo", + "RESET": "Tilbakestill", + "RESET_UI_SETTINGS": "Tilbakestill UI Innstillinger", + "RESET_VIEW_DEFAULTS": "Tilbakestill view defaults", + "RESIZE_TORRENT_DETAILS_PANEL": "Resize Torrent Detaljer Panel", + "RESOLVE_PEER_IP_TO_REVERSE_DNS_HOST": "Resolve peer IP til reverse DNS host", + "RESUME": "Fortsett", + "RETENTION_DAYS": "Oppbevaring dager", + "RETENTION_MODE": "Oppbevaring mode", + "RETRY": "Prøv igjen", + "REVERSE_DNS": "Reverse DNS", + "RSS_DOWNLOADER": "RSS downloader", + "RTORRENT": "rTorrent", + "RTORRENTS": "rTorrents", + "RTORRENT_CONFIG": "rTorrent Konfigurasjon", + "RTORRENT_INCOMING_PORT": "rTorrent incoming Port", + "RTORRENT_IS_STARTING_OR_NOT_RESPONDING_YET": "rTorrent er starting eller ikke responding yet.", + "RTORRENT_PROFILES": "rTorrent Profiler", + "RULE": "Regel", + "RULES": "Regler", + "RULES_ARE_CHECKED_AUTOMATICALLY_EVERY_5_MINUTES_A_TORRENT_USES_THE_GROUP_STORED_": "Regler er sjekkes automatically every 5 minutter. Torrent uses Gruppe stored i its rTorrent Egendefinert Ratio field.", + "RULE_NAME": "Regel Navn", + "RUNTIME": "Runtime", + "RUN_A_PROFILE_TEST_TO_SHOW_DIAGNOSTICS": "Kjøring Profil Test til Vis Diagnostikk.", + "RUN_SMART_QUEUE_DURING_POLLING_STOPPED_TORRENTS_ARE_MANAGED_PAUSED_TORRENTS_STAY": "Kjøring Smart Queue under polling. Stoppet Torrenter er administrert; Pauset Torrenter stay Bruker-controlled.", + "R_RESUME": "R - Fortsett", + "SAVE": "Lagre", + "SAVED_LABELS": "Lagret Etiketter", + "SAVE_COLUMNS": "Lagre Kolonner", + "SAVE_CONFIG": "Lagre Konfigurasjon", + "SAVE_EASTER_EGG": "Lagre easter egg", + "SAVE_EXCEPTIONS": "Lagre exceptions", + "SAVE_FEED": "Lagre feed", + "SAVE_FOOTER": "Lagre Bunnlinje", + "SAVE_GROUP": "Lagre Gruppe", + "SAVE_JOB_SETTINGS": "Lagre Jobb Innstillinger", + "SAVE_LIMITS": "Lagre Grenser", + "SAVE_LOCATION": "Lagre Plassering", + "SAVE_LOG_VIEW": "Lagre Logg view", + "SAVE_PATH": "Lagre Sti", + "SAVE_PREFERENCES": "Lagre Innstillinger", + "SAVE_RETENTION": "Lagre Oppbevaring", + "SAVE_RULE": "Lagre Regel", + "SAVE_SCHEDULE": "Lagre plan", + "SAVE_USER": "Lagre Bruker", + "SCGI_URL": "SCGI URL", + "SEARCH_LOGS": "Søk Logger...", + "SEARCH_TORRENTS": "Søk Torrenter...", + "SEARCH_TORRENTS_TO_EXCLUDE": "Søk Torrenter til Ekskluder...", + "SEASON": "Sesong", + "SECONDS_TO_WAIT_FOR_RTORRENT_RESPONSE": "Sekunder til vente for rTorrent svar.", + "SEEDING": "Seeding", + "SEEDS": "Seeds", + "SEEDS_ARE_LOW_FOR_TIME": "Seeds er lav for tid", + "SEED_MINUTES": "Seed minutter", + "SELECT": "Velg", + "SELECTED": "valgt", + "SELECTED_LABELS": "Valgt Etiketter", + "SELECTED_MONITORED_PATH": "Valgt monitored Sti", + "SELECTED_TORRENTS_WILL_BE_REMOVED": "valgt Torrenter vil være removed.", + "SELECT_A_MONITORED_PATH_FIRST": "Velg monitored Sti Første.", + "SELECT_A_TORRENT": "Velg Torrent.", + "SELECT_ONE_OR_MORE_TORRENT_FILES": "Velg én eller more .Torrent Filer.", + "SELECT_PATH": "Velg Sti", + "SELECT_TORRENTS_THAT_SMART_QUEUE_SHOULD_IGNORE_USE_SEARCH_TO_FILTER_BY_NAME_LABE": "Velg Torrenter at Smart Queue skal ignorere. Bruk Søk til filter etter Navn, Etikett, Status eller Hash.", + "SELECT_VISIBLE": "Velg synlig", + "SEPARATE_SLOT_POOL_FOR_LIGHTWEIGHT_CONTROL_JOBS_SO_THEY_DO_NOT_WAIT_BEHIND_HEAVY": "Separate spor pool for lightweight control Jobber so they do ikke vente bak heavy IO arbeid. Standard: 4.", + "SETTINGS": "Innstillinger", + "SET_LABEL": "Set Etikett...", + "SET_LABELS": "Set Etiketter", + "SET_RATIO_GROUP": "Set Ratio Gruppe...", + "SHARE_AFTER_CREATING": "Share etter creating", + "SHORTCUTS": "Shortcuts", + "SHOWN": "Shown", + "SHOWN_IN_LOADING_STATES_INSTEAD_OF_THE_STANDARD_SPINNER": "Shown i Laster tilstander i stedet for standard spinner.", + "SHOWS_TRACKER_ICONS_IN_THE_SIDEBAR_TRACKER_FILTER_WHEN_AVAILABLE": "Viser Tracker ikoner i sidefelt Tracker filter when tilgjengelige.", + "SHOW_COMBINED_USAGE_SINGLE_PATH_SELECTION_IS_DISABLED_IN_THIS_MODE": "Vis kombinert usage. Enkelt Sti selection er Deaktivert i denne mode.", + "SHOW_DL_UP_IN_BROWSER_TITLE": "Vis DL/UP i Nettleser Tittel", + "SHOW_SMART_QUEUE_AUTOMATIC_RUN_MESSAGES": "Vis Smart Queue Automatisk kjøring meldinger.", + "SHOW_TOASTS_CREATED_BY_AUTOMATION_RUNS": "Vis toasts created etter automation runs.", + "SIGN_IN": "Logg inn", + "SIZE": "Størrelse", + "SKIP_ACTIVE_UPLOAD": "Skip Aktiv Opplasting", + "SKIP_PRIVATE_TORRENTS": "Skip Privat Torrenter", + "SMART_FILTERS": "Smart filters", + "SMART_QUEUE": "Smart Queue", + "SMART_QUEUE_EXCEPTIONS": "Smart Queue exceptions", + "SMART_QUEUE_KEEPS_ONLY_THIS_MANY_ACTIVE_DOWNLOADS_OVERFLOW_IS_STOPPED": "Smart Queue keeps bare denne many Aktiv Nedlastinger; overflow er Stoppet.", + "SMART_QUEUE_TOASTS": "Smart Queue toasts", + "SOCKETS": "Sockets", + "SOURCE": "Kilde", + "SPACE_START": "Space - Start", + "SPEED": "Hastighet", + "SPEED_LIMITS": "Hastighet Grenser", + "SPEED_TREND": "Hastighet trend", + "STALLED_AFTER_SECONDS": "Stoppede etter sekunder", + "START": "Start", + "START_AFTER_ADD": "Start etter Legg til", + "START_GRACE_SECONDS": "Start grace sekunder", + "STATE": "Status", + "STATUS": "Status", + "STATUS_EQUALS": "Status equals", + "STOP": "Stopp", + "STOPPED": "Stoppet", + "S_STOP": "S - Stopp", + "TARGET_ACTIVE_DOWNLOADS": "Mål Aktiv Nedlastinger", + "TARGET_PATH": "Mål Sti", + "TEST_RULE": "Test Regel", + "TEST_SCGI": "Test SCGI", + "THEME_TYPOGRAPHY_AND_INTERFACE_SCALE": "Tema, typography og interface scale.", + "THE_FOOTER_TOOLTIP_ALWAYS_SHOWS_DETAILS_FOR_AVAILABLE_PATHS_THIS_SETTING_ONLY_DE": "Bunnlinje tooltip alltid viser Detaljer for tilgjengelige stier; denne innstilling bare avgjør hvilken verdi styrer synlig Fremdrift linje.", + "TIMEOUT": "Tidsavbrudd", + "TOAST_NOTIFICATIONS_FROM_AUTOMATIC_SYSTEMS": "Toast Varsler fra Automatisk systems.", + "TOOLS": "Verktøy", + "TOOLS_RTORRENTS": "Verktøy & rTorrents", + "TOOLS_SECTIONS": "Verktøy sections", + "TORRENT_ADDED": "Torrent added", + "TORRENT_COMPLETED": "Torrent Fullført", + "TORRENT_DETAILS": "Torrent Detaljer", + "TORRENT_FILES": "Torrent Filer", + "TORRENT_FILTERS": "Torrent filters", + "TORRENT_PROPERTIES": "Torrent properties", + "TORRENT_REMOVED": "Torrent removed", + "TORRENT_STATISTICS": "Torrent Statistikk", + "TORRENT_STATS": "Torrent stats", + "TOTAL_DL_UP": "Total DL/UP", + "TO_DOWNLOAD": "Til Nedlasting", + "TRACKERS": "Trackere", + "TRACKER_ICONS": "Tracker ikoner", + "TRANSFER": "Transfer", + "TRANSFERRED_DATA": "Transferred Data", + "TRANSFER_HISTORY": "Transfer Historikk", + "UNDEFINED": "undefined", + "UNLIMITED": "Unlimited", + "UPLOADED": "Lastet opp", + "UPLOADS": "Opplastinger", + "UPLOAD_KIB_S": "Opplasting KiB/s", + "USER": "Bruker", + "USERS": "Brukere", + "USES_A_LIGHTWEIGHT_BUILT_IN_RESOLVER_WITH_CACHE_HOSTNAMES_APPEAR_ONLY_IN_THE_PEE": "Uses lightweight built-i resolver med cache. Vertsnavn appear bare i Peers fane.", + "USES_LOWER_ROWS_AND_SMALLER_LIST_ELEMENTS_ON_DESKTOP_AND_MOBILE_SO_MORE_TORRENTS": "Uses lavere rader og smaller liste elements on Skrivebord og Mobil so more Torrenter får plass on skjerm.", + "USES_YOUGETSIGNAL_FIRST_MANUAL_CHECK_BYPASSES_THE_6H_CACHE": "Uses YouGetSignal Første. Manuell Sjekk bypasses 6h cache.", + "USE_ONE_CUSTOM_PATH_BELOW_AS_THE_FOOTER_PROGRESS_VALUE": "Bruk én Egendefinert Sti below som Bunnlinje Fremdrift verdi.", + "USE_SELECTED": "Bruk valgt", + "USE_THE_MAIN_DIRECTORY_FROM_THE_ACTIVE_RTORRENT_PROFILE": "Bruk main Mappe fra Aktiv rTorrent Profil.", + "VIEW_PREFERENCES_RESET": "View Innstillinger Tilbakestill", + "VIEW_STATE_IS_SAVED_AUTOMATICALLY_IN_THE_DATABASE_CURRENT_TORRENT_FILTER_LAST_SO": "View Status er Lagret automatically i database: Gjeldende Torrent filter, Siste sort column og direction, synlig Kolonner, og Detaljer Panel height.", + "VISIBLE_NAME_USED_IN_THE_PROFILE_SELECTOR": "Synlig Navn used i Profil selector.", + "VISUAL_HELPER_FOR_TRACKER_FILTERS_IN_THE_SIDEBAR": "Visual hjelper for Tracker filters i sidefelt.", + "WAITING_FOR_DATA": "Venter for Data.", + "WAITING_FOR_TORRENT_DATA_FROM_THE_ACTIVE_PROFILE": "Venter for Torrent Data fra Aktiv Profil.", + "WATCHDOG_MARKS_A_LIGHT_JOB_AS_FAILED_AFTER_THIS_TIME_DEFAULT_300_SECONDS": "Watchdog marks light Jobb som mislyktes etter denne tid. Standard: 300 sekunder.", + "WATCHDOG_TIMEOUT_FOR_MOVE_REMOVE_ADD_JOBS_DEFAULT_7200_SECONDS": "Watchdog Tidsavbrudd for Flytt/Fjern/Legg til Jobber. Standard: 7200 sekunder.", + "WHEN_DISABLED_THE_APPLICATION_USES_THE_NORMAL_PRODUCTION_UI": "When Deaktivert, Applikasjon uses normal produksjon UI.", + "WHEN_ENABLED_LOW_SPEED_IS_NOT_REQUIRED_WITH_SOURCE_AND_SPEED_IGNORES_ENABLED_ONL": "When Aktivert, lav Hastighet er ikke required. Med Kilde og Hastighet ignores Aktivert, bare Stoppede etter sekunder avgjør.", + "WHEN_ENABLED_SMART_QUEUE_DOES_NOT_USE_SEED_PEER_COUNT_AS_A_STALLED_CRITERION": "When Aktivert, Smart Queue does ikke bruk seed/peer count som stoppede kriterium.", + "WITH_ERROR": "Med Feil", + "WORKING": "Arbeider...", + "FRENCH": "Fransk", + "CZECH": "Tsjekkisk", + "SPANISH": "Spansk", + "NORWEGIAN": "Norsk", + "RUSSIAN": "Russisk" + } +} diff --git a/pytorrent/static/i18n/pl_PL.json b/pytorrent/static/i18n/pl_PL.json new file mode 100644 index 0000000..231361f --- /dev/null +++ b/pytorrent/static/i18n/pl_PL.json @@ -0,0 +1,566 @@ +{ + "meta": { + "locale": "pl_PL", + "label": "Polski", + "flag": "pl" + }, + "translations": { + "0_MEANS_ONLY_SEED_THRESHOLD_IS_REQUIRED": "0 oznacza tylko seed próg jest wymagany.", + "0_MEANS_UNLIMITED_SLIDERS_USE_MBIT_S_AND_SAVE_THROUGH_THE_EXISTING_SPEED_LIMITS_": "0 oznacza bez limitu. Suwaki użyj Mbit/s i zapisz przez istniejące prędkość limity API.", + "0_SELECTED": "0 wybrane", + "ABOUT_PYTORRENT": "O pyTorrent", + "ACTION": "Akcja", + "ACTIVE": "Aktywne", + "ACTIVE_RTORRENT_DOWNLOADS_MAX_GLOBAL_DOWNLOADS": "Aktywne pobierania rTorrent / globalny limit pobierań", + "ACTIVE_RTORRENT_UPLOADS_MAX_GLOBAL_UPLOADS": "Aktywne wysyłania rTorrent / globalny limit wysyłań", + "ADD": "Dodaj", + "ADDED": "Dodano", + "ADDS_REMOVALS_COMPLETIONS_AND_QUEUED_OPERATION_RESULTS": "Adds, usunięcia, ukończenia i w kolejce operacja wyniki.", + "ADD_ACTION": "Dodaj akcja", + "ADD_CONDITION": "Dodaj warunek", + "ADD_CREATE_TORRENT": "Dodaj / utwórz torrent", + "ADD_FIRST_LABEL_ABOVE": "Dodaj pierwszą etykietę powyżej.", + "ADD_LABEL": "Dodaj etykieta", + "ADD_MAGNET_LINK": "Dodaj link magnet", + "ADD_NEW_LABEL": "Dodaj nowy etykieta", + "ADD_OR_EDIT_GROUP": "Dodaj lub edytuj grupa", + "ADD_PATH": "Dodaj ścieżkę", + "ADD_PROFILE": "Dodaj profil", + "ADD_RTORRENT_PROFILE": "Dodaj profil rTorrent", + "ADD_THE_FIRST_RTORRENT_PROFILE_TO_START_LOADING_TORRENTS": "Dodaj pierwszy profil rTorrent, aby zacząć ładować torrenty.", + "ADD_TORRENT": "Dodaj torrent", + "ADD_TORRENT_FILE": "Dodaj plik torrent", + "ADMIN": "administrator", + "ADMIN_ONLY_FULL_APPLICATION_BACKUP_RESTORE_CAN_REPLACE_USERS_PERMISSIONS_PROFILE": "Pełna kopia aplikacji tylko dla administratora. Przywracanie może zastąpić użytkowników, uprawnienia, profile i globalne ustawienia aplikacji.", + "AGGREGATE_ALL_PATHS": "Agreguj wszystkie ścieżki", + "ALL": "Wszystkie", + "ALL_NON_JOB_TYPES": "Wszystkie nie-zadanie typy", + "ALL_PROFILES": "Wszystkie profile", + "ALL_TYPES": "Wszystkie typy", + "ANNOUNCE": "Ogłoś", + "API_DOCS": "API dokumentacja", + "APPEARANCE": "Wygląd", + "APPEARANCE_PREFERENCES_SAVED": "Preferencje wyglądu zapisane", + "APPEARS_NEAR_CLICKED_BUTTONS_ONLY_SOMETIMES": "Czasami pojawia się przy klikniętych przyciskach.", + "APPLICATION_BACKUP": "Aplikacja kopia zapasowa", + "APPLICATION_BACKUP_NAME": "Aplikacja kopia zapasowa nazwa", + "APPLY": "Zastosuj", + "APPLY_RETENTION_NOW": "Zastosuj retencja teraz", + "APPLY_SAVED_CHANGES_60S_AFTER_PYTORRENT_START": "Zastosuj zapisane zmiany 60s po pyTorrent start", + "APP_STATUS": "Aplikacja status", + "AUTHENTICATION_IS_ENABLED_FOR_THIS_PYTORRENT_INSTANCE": "Uwierzytelnianie jest włączone dla ten pyTorrent instancja.", + "AUTHOR": "Autor", + "AUTOMATIC": "Automatyczne", + "AUTOMATIC_KEEPS_THE_CURRENT_POLLER_CADENCE_CUSTOM_RUNS_ONLY_AFTER_THE_SELECTED_N": "Tryb automatyczny zachowuje bieżący rytm odświeżania. Tryb własny uruchamia się dopiero po wybranej liczbie minut. Wyłączenie całkowicie wyłącza uzupełnianie.", + "AUTOMATIC_QUEUE_BALANCING_FOR_SLOW_OR_STALLED_DOWNLOADS": "Automatyczne kolejka równoważenie for wolne lub zatrzymane pobierania.", + "AUTOMATIC_RUNS_USE_THE_COOLDOWN_BELOW_MANUAL_CHECK_NOW_STILL_RUNS_IMMEDIATELY": "Automatyczne uruchomienia używają poniższego czasu odczekania. Ręczne „Sprawdź teraz” nadal uruchamia się od razu.", + "AUTOMATIONS": "Automatyzacje", + "AUTOMATIONS_RULES": "Automatyzacje / reguły", + "AUTOMATION_TOASTS": "Toasty automatyzacji", + "AUTO_STOP_WHEN_IDLE": "Auto-stop when bezczynność", + "BACKEND": "Backend", + "BACKUP": "Kopia zapasowa", + "BACKUP_RESTORE": "Kopia zapasowa / przywróć", + "BACK_TO_DASHBOARD": "Wróć to panel", + "BOOTSTRAP_THEME": "Motyw Bootstrap", + "BROWSER": "Przeglądarka", + "BROWSER_TITLE": "Tytuł przeglądarki", + "BUILD_A_RULE_AS_CONDITIONS_FIRST_THEN_ORDERED_ACTIONS_MATCHING_TORRENTS_ARE_HAND": "Zbuduj regułę: najpierw warunki, potem uporządkowane akcje. Pasujące torrenty są obsługiwane jako jedna partia, a czas odczekania dotyczy całej reguły.", + "BUSY": "zajęty", + "BY_DAYS": "Według dni", + "BY_LINE_COUNT": "Według linia liczba", + "CACHED_METADATA_SUMMARY_FILE_METADATA_IS_REFRESHED_EVERY_15_MINUTES_A_FEW_MINUTE": "Podsumowanie metadanych z pamięci podręcznej. Metadane plików są odświeżane co 15 minut, kilka minut po starcie lub ręcznie.", + "CANCEL": "Anuluj", + "CANCEL_EDIT": "Anuluj edytuj", + "CATEGORY": "Kategoria", + "CHANGES_APPLY_IMMEDIATELY_WHERE_POSSIBLE_INITIAL_STARTUP_LOADER_USES_THEM_AFTER_": "Zmiany są stosowane od razu tam, gdzie to możliwe; początkowy loader użyje ich po przeładowaniu.", + "CHANGE_RTORRENT": "Zmień rTorrent", + "CHANGE_THEME": "Zmień motyw", + "CHANGING_RTORRENT_RELOADS_THE_LIVE_TORRENT_SNAPSHOT": "Zmiana rTorrent przeładowuje bieżący torrent migawka.", + "CHECKING": "Sprawdzanie", + "CHECK_NOW": "Sprawdź teraz", + "CHECK_PORT_NOW": "Sprawdź port teraz", + "CHECK_THIS_IF_YOU_WANT_TO_CONNECT_TO_A_REMOTE_RTORRENT_INSTANCE_INSTEAD_OF_LOCAL": "Sprawdź ten jeśli chcesz chcesz do połączyć do a zdalna rTorrent instancja zamiast of localhost.", + "CHOOSE_COLUMNS_VISIBLE_IN_THE_TORRENT_LIST": "Wybierz kolumny widoczny w torrent lista.", + "CHOOSE_FILES": "Wybierz files", + "CHOOSE_RTORRENT": "Wybierz rTorrent", + "CHOOSE_TORRENTS_IGNORED_BY_SMART_QUEUE_EXISTING_BEHAVIOR_STAYS_UNCHANGED_FOR_ALL": "Wybierz torrenty ignorowane przez Smart Queue. Obecne działanie pozostaje bez zmian dla wszystkich niewykluczonych torrentów.", + "CHOOSE_WHAT_THE_FOOTER_DISK_BAR_SHOULD_REPRESENT_AND_ADD_EXTRA_STORAGE_PATHS": "Wybierz, co ma pokazywać pasek dysku w stopce, i dodaj dodatkowe ścieżki przechowywania.", + "CHOOSE_WHICH_STATUS_ITEMS_ARE_VISIBLE_IN_THE_BOTTOM_BAR": "Wybierz elementy statusu widoczne na dolnym pasku.", + "CHUNKS": "Części", + "CLEANUP": "Czyszczenie", + "CLEANUP_RETENTION": "Czyszczenie / retencja", + "CLEAR": "Wyczyść", + "CLEAR_CURRENT_FILTER": "Wyczyść bieżące filter", + "CLEAR_FINISHED": "Wyczyść ukończone", + "CLEAR_LABELS": "Wyczyść etykiety", + "CLEAR_SELECTION": "wyczyść zaznaczenie", + "CLEAR_VISIBLE": "Wyczyść widoczne", + "CLOSE": "Zamknij", + "COLUMNS": "Kolumny", + "COLUMNS_SAVED": "Kolumny zapisane", + "COMMENT": "Komentarz", + "COMPACT_TORRENT_LIST": "Kompaktowa lista torrentów", + "COMPLETE": "Ukończone", + "COMPLETED": "Ukończone", + "CONFIGURED_RTORRENTS": "Skonfigurowane rTorrents", + "CONNECTING_TO_RTORRENT_AND_PREPARING_DATA": "Łączenie z rTorrent i przygotowywanie danych.", + "CONNECTION_ADDRESS_IN_SCGI_HOST_PORT_RPC2_FORMAT": "Adres połączenia w formacie scgi://host:port/RPC2.", + "CONTROLS_THE_DEFAULT_CATEGORY_AND_JOB_LOG_VISIBILITY_USED_BY_THE_LOGS_MODAL": "Steruje domyślną kategorią i widocznością logów zadań w oknie logów.", + "CONTROLS_WHAT_IS_SHOWN_IN_THE_BROWSER_TAB": "Steruje tym, co widać w karcie przeglądarki.", + "COOLDOWN_MINUTES": "Czas odczekania minuty", + "COPY": "Kopiuj", + "COPY_HASH": "Kopiuj hash", + "COPY_NAME": "Kopiuj nazwa", + "COPY_PATH": "Kopiuj ścieżka", + "CPU_RAM_USAGE": "CPU / RAM użycie", + "CREATE": "Utwórz", + "CREATES_AND_RESTORES_SETTINGS_FOR_THE_CURRENTLY_SELECTED_PROFILE_USER_SCOPED_PRE": "Tworzy i przywraca ustawienia aktualnie wybranego profilu. Preferencje przypisane do użytkownika są w razie potrzeby przepinane na bieżącego użytkownika.", + "CREATE_APPLICATION_BACKUP": "Utwórz aplikacja kopia zapasowa", + "CREATE_ONE_RTORRENT_PROFILE_AT_A_TIME_MOVE_REMOVE_QUEUES_KEEP_THEIR_ORDER_FOR_EA": "Twórz po jednym profilu rTorrent naraz. Kolejki przenoszenia/usuwania zachowują kolejność dla każdego profilu.", + "CREATE_PROFILE_BACKUP": "Utwórz profil kopia zapasowa", + "CREATE_REUSABLE_LABELS_AND_REMOVE_LABELS_THAT_ARE_NO_LONGER_NEEDED": "Twórz etykiety wielokrotnego użytku i usuwaj te, które nie są już potrzebne.", + "CREATE_TORRENT": "Utwórz torrent", + "CTRL_A_SELECT_VISIBLE": "Ctrl+A - wybierz widoczne", + "CTRL_I_INVERT_VISIBLE": "Ctrl+I - odwróć widoczne", + "CTRL_O_ADD": "Ctrl+O - dodaj", + "CTRL_S_DOWNLOAD_TORRENT": "Ctrl+S - pobierz .torrent", + "CURRENT_TRANSFER_SPEED": "Aktualna prędkość transferu", + "CUSTOM_DOWNLOAD": "Własne pobierz", + "CUSTOM_UPLOAD": "Własne wyślij", + "DAYS_AND_LINE_COUNT": "Dni i linia liczba", + "DECREASE_OR_INCREASE_THE_WHOLE_INTERFACE_SIZE": "Zmniejsz lub zwiększ rozmiar całego interfejsu.", + "DEFAULT_LOG_CATEGORY": "Domyślne log kategoria", + "DEFAULT_LOG_VIEW": "Domyślne log view", + "DEFAULT_RTORRENT_PATH": "Domyślna ścieżka rTorrent", + "DEGRADED": "ograniczone", + "DELETE": "Usuń", + "DELETE_REMOVE": "Delete - usuń", + "DESKTOP": "Desktop", + "DETAILS_WILL_APPEAR_AFTER_THE_FIRST_SUCCESSFUL_RESPONSE": "Szczegóły pojawią się po pierwszej poprawnej odpowiedzi.", + "DIAGNOSTICS": "Diagnostyka", + "DISABLED": "wyłączone", + "DISK_MONITOR": "Monitor dysku", + "DISK_USAGE_UNAVAILABLE": "Dysk użycie niedostępna", + "DISPLAYS_CURRENT_SPEEDS_NEXT_TO_PYTORRENT_IN_THE_TAB_TITLE": "Pokazuje bieżące prędkości obok pyTorrent w tytule karty.", + "DOCS_API": "Dokumentacja API", + "DOWNLOADED": "Pobrano", + "DOWNLOADING": "Pobieranie", + "DOWNLOADS": "Pobierania", + "DOWNLOAD_KIB_S": "Pobierz KiB/s", + "DOWNLOAD_STARTED": "Pobieranie rozpoczęte", + "DOWNLOAD_TORRENT": "Pobierz .torrent", + "DOWNLOAD_TRACKER_FAVICONS": "Pobieraj favikony trackerów", + "DRAG_TO_RESIZE_DETAILS_PANEL": "Przeciągnij to zmień rozmiar szczegóły panel", + "EASTER_EGG": "Easter egg", + "EDIT": "Edytuj", + "EMERGENCY_CANCEL": "Awaryjnie anuluj", + "EMERGENCY_CLEAN_ALL": "Awaryjne wyczyść wszystkie", + "ENABLED": "Włączone", + "ENABLE_AUTOMATIC_APPLICATION_BACKUPS": "Enable automatyczne aplikacja backups", + "ENABLE_AUTOMATIC_PROFILE_BACKUPS": "Enable automatyczne profil backups", + "ENABLE_EASTER_EGG": "Włącz easter egg", + "ENABLE_INCOMING_PORT_CHECK": "Włącz sprawdzanie portu przychodzącego", + "ENABLE_REVERSE_DNS_FOR_PEERS": "Włącz Reverse DNS dla peerów", + "ENGLISH": "Angielski", + "EPISODE": "Odcinek", + "ESC_CLEAR_SELECTION": "Esc - wyczyść zaznaczenie", + "ETA": "ETA", + "EVERY_N_MINUTES": "Co N minuty", + "EVERY_X_HOURS": "Co X hours", + "EXCLUDE": "Wyklucz", + "EXCLUDE_FROM_SMART_QUEUE": "Wyklucz z Smart Queue", + "EXCLUDE_PATTERN": "Wyklucz wzorzec", + "EXISTING_GROUPS": "Istniejące groups", + "EXPORT": "Eksport", + "EXPORT_JSON": "Eksport JSON", + "EXTERNAL_AUTHENTICATION_IS_ENABLED_THROUGH_EXTERNAL_PROVIDER": "Zewnętrzne uwierzytelnianie jest włączone przez {{ external_provider }}.", + "E_G_PUNKTY_KATALOGOWANIE": "e.g. Punkty katalogowanie", + "FEATURES": "Funkcje", + "FEED": "Kanał", + "FEEDS_ARE_CHECKED_BY_SCHEDULE_AND_EVERY_MATCH_IS_LOGGED_PER_FEED_RULE": "Kanały są sprawdzane według harmonogramu, a każde dopasowanie jest zapisywane dla kanału/reguły.", + "FEEDS_RULES_AND_MATCHES": "Kanały, reguły i dopasowania", + "FEED_NAME": "Kanał nazwa", + "FEED_URL": "Kanał URL", + "FILES": "Pliki", + "FILE_OR_DIRECTORY_PATH": "Plik lub katalog ścieżka", + "FONT": "Czcionka", + "FOOTER": "Stopka", + "FORCE": "Wymuś", + "FORCE_RECHECK": "Wymuś sprawdź ponownie", + "FRONTEND": "Frontend", + "FULL": "Full", + "GENERAL": "Ogólne", + "GENERATED_RTORRENT_CONFIG_CHANGES_WILL_APPEAR_HERE": "Wygenerowane rTorrent konfiguracja zmiany będzie pojawi się tutaj.", + "GENERATE_CONFIG": "Generuj konfiguracje", + "GERMAN": "Niemiecki", + "GO": "Go", + "GROUPED_RTORRENT_RUNTIME_SETTINGS_WITH_INLINE_RECOMMENDATIONS_AND_COMPATIBILITY_": "Pogrupowane ustawienia runtime rTorrent z rekomendacjami inline i statusem zgodności.", + "GROUP_NAME": "Grupa nazwa", + "HASH": "Hash", + "HASHING": "Hashowanie", + "HEAVY_PARALLEL_JOBS": "Ciężkie równoległe zadania", + "HEAVY_TIMEOUT_SECONDS": "Ciężkie limit czasu sekundy", + "HIDE_JOB_LOGS": "Ukryj zadanie logi", + "HIDE_JOB_LOGS_BY_DEFAULT": "Ukryj zadanie logi według domyślne", + "HISTORY": "Historia", + "HOW_LONG_A_MATCHING_ACTIVE_TORRENT_MUST_STAY_STALLED_BEFORE_IT_CAN_BE_REPLACED": "Jak długo pasujący aktywny torrent musi pozostawać zatrzymany, zanim będzie można go zastąpić.", + "IGNORE_MISSING_SEEDS_PEERS_FOR_STALLED_TIMER": "Ignoruj brakujące seeds/peery for zatrzymane licznik", + "IGNORE_SPEED_FOR_STALLED_TIMER": "Ignoruj prędkość for zatrzymane licznik", + "IMPORT": "Import", + "IMPORT_JSON": "Import JSON", + "INCLUDE_PATTERN": "Uwzględnij wzorzec", + "INCOMING_CONNECTION_TEST_SEPARATE_FROM_VISUAL_PREFERENCES": "Przychodzący połączenie test, oddzielny z wizualne preferencje.", + "INTERFACE_SCALE": "Skala interfejsu", + "INTERVAL_MINUTES": "Interwał minuty", + "INVERT_VISIBLE": "odwróć widoczne", + "JOBS": "Zadania", + "JOB_DONE": "Zadanie ukończone", + "JOB_FAILED": "Zadanie nieudane", + "JOB_QUEUE": "Zadanie kolejka", + "JOB_SCHEDULING": "Zadanie planowanie", + "JOB_STARTED": "Zadanie rozpoczęto", + "KEEP_LINES": "Zachowaj lines", + "KEEP_SEEDING": "Zachowaj seedowanie", + "LABEL": "Etykieta", + "LABELS": "Etykiety", + "LABELS_SEPARATED_BY_COMMA": "Etykiety oddzielone według przecinek", + "LABEL_AFTER_SHARE": "Etykieta po udostępnij", + "LABEL_EXISTS": "Etykieta exists", + "LABEL_IS_MISSING": "Etykieta jest brakujące", + "LABEL_NAME_OR_SEVERAL_SEPARATED_BY_COMMA": "Etykieta nazwa, lub several oddzielone według przecinek", + "LANGUAGE": "Język", + "LANGUAGE_SAVED": "Język zapisane", + "LAST_OPERATIONS": "Ostatnie operacje", + "LICENSE": "Licencja", + "LIGHTWEIGHT_WEB_PANEL_FOR_RTORRENT_MANAGEMENT_QUEUE_CONTROL_AND_LIVE_TORRENT_DIA": "Lekki panel webowy do zarządzania rTorrent, kontroli kolejki i diagnostyki torrentów na żywo.", + "LIGHT_PARALLEL_JOBS": "Lekkie równoległe zadania", + "LIGHT_TIMEOUT_SECONDS": "Lekkie limit czasu sekundy", + "LIMIT_DL": "Limit DL", + "LOADING": "Ładowanie", + "LOADING_CLEANUP_DATA": "Ładowanie czyszczenie dane...", + "LOADING_CONFIG": "Ładowanie konfiguracja...", + "LOADING_IMAGE_URL": "Ładowanie obraz URL", + "LOADING_JOBS": "Ładowanie zadania...", + "LOADING_LOGS": "Ładowanie logi...", + "LOADING_PROFILES": "Ładowanie profile...", + "LOADING_STATISTICS": "Ładowanie statystyki...", + "LOADING_TORRENTS": "Ładowanie torrentów...", + "LOADING_TORRENT_DETAILS": "Ładowanie szczegółów torrenta...", + "LOCAL_BROWSER_TIME": "Local przeglądarka time", + "LOCATION": "Lokalizacja", + "LOG": "Log", + "LOGS": "Logi", + "LOG_IN": "Zaloguj", + "LOG_OUT": "Wyloguj", + "LOG_STATISTICS": "Log statystyki", + "MAGNET_AND_TORRENT_UPLOAD_FILE_PRIORITIES_LABELS_RATIO_GROUPS_SMART_QUEUE_AUTOMA": "Dodawanie magnet i plików torrent, priorytety plików, etykiety, grupy ratio, Smart Queue, reguły automatyzacji, RSS, wykresy transferu, sprawdzanie portu i status systemu.", + "MAGNET_LINKS": "Magnet links", + "MANAGE_EXCEPTIONS": "Zarządzaj exceptions", + "MANAGE_OPERATION_LOG_RETENTION_WITHOUT_CHANGING_TORRENT_DATA": "Zarządzaj operacja log retencja bez zmiana torrent dane.", + "MANAGE_OPTIONAL_PYTORRENT_USERS_EMPTY_PROFILE_MEANS_ALL_PROFILES_R_O_BLOCKS_RTOR": "Zarządzaj opcjonalnymi użytkownikami pyTorrent. Pusty profil oznacza wszystkie profile. R/O blokuje akcje zmieniające rTorrent; Full je dopuszcza.", + "MANUAL_CLEANUP_ONLY": "Ręczne czyszczenie tylko", + "MAXIMUM_HEAVY_JOBS_RUNNING_AT_ONCE_FOR_THIS_PROFILE_DEFAULT_5": "Maximum ciężkie zadania uruchomione at naraz dla ten profil. Domyślne: 5.", + "MAXIMUM_QUEUED_ACTIONS_RUNNING_AT_ONCE": "Maximum w kolejce akcje uruchomione at naraz.", + "MAXIMUM_STALLED_OVERFLOW_DOWNLOADS_SMART_QUEUE_MAY_STOP_IN_ONE_PASS": "Maksimum zatrzymane/nadmiarowe pobierania Smart Queue może stop w jedno przebieg.", + "MAX_MB": "Maks. MB", + "MAX_RATIO": "Maks. ratio", + "MAX_STOPS_PER_CHECK": "Maks. stops per sprawdź", + "MESSAGE": "Komunikat", + "MINUTES": "Minuty", + "MIN_MB": "Min. MB", + "MIN_PEERS": "Min. peery", + "MIN_RATIO": "Min. ratio", + "MIN_SEEDS": "Min. seeds", + "MIN_SEED_MINUTES": "Min. seed minuty", + "MIN_SPEED_KIB_S": "Min. prędkość KiB/s", + "MOBILE": "Mobile", + "MOBILE_COLUMNS": "Kolumny mobile", + "MOBILE_FILTER_GROUPS": "Grupy filtrów mobile", + "MOBILE_SIMPLE_MODE": "Mobile/prosty tryb", + "MOBILE_SORT_FILTERS": "Filtry sortowania mobile", + "MODE": "Tryb", + "MONITORED_PATHS": "Monitorowane ścieżki", + "MOVE": "Przenieś", + "MOVE_DATA": "Przenieś dane", + "MOVE_DATA_FILES": "Przenieś dane files", + "MOVE_PATH": "Przenieś ścieżka", + "MOVE_TO_PATH": "Przenieś to ścieżka", + "MOVIES": "filmy", + "MOVING": "Przenoszenie", + "M_MOVE": "M - przenieś", + "NAME": "Nazwa", + "NEGATE": "Zaneguj", + "NEWLY_QUEUE_STARTED_TORRENTS_ARE_PROTECTED_FROM_STALLED_CLEANUP_DURING_THIS_WARM": "Newly kolejka-rozpoczęto torrents są chronione z zatrzymane czyszczenie podczas ten rozgrzewka-up.", + "NEW_LABEL": "Nowy etykieta", + "NEXT_READY": "następne: gotowe", + "NEXT_SMART_QUEUE_RUN": "Następne Smart Queue uruchomienie", + "NOTIFICATIONS": "Powiadomienia", + "NOT_LOADED": "Nie załadowano.", + "NO_CHANGES": "Brak zmian", + "NO_FILES_RETURNED_BY_RTORRENT": "rTorrent nie zwrócił plików.", + "NO_FILES_SELECTED": "Nie zaznaczono plików", + "NO_LABELS": "Brak etykiet.", + "NO_LABELS_SELECTED": "Nie wybrano etykiet.", + "NO_PATH_LOADED": "Brak ścieżka załadowane.", + "NO_PEERS_RETURNED_BY_RTORRENT": "rTorrent nie zwrócił peerów.", + "NO_RTORRENT_PROFILE_CONFIGURED": "Brak skonfigurowanego profilu rTorrent.", + "NO_SAVED_LABELS": "Brak zapisanych etykiet.", + "NO_TORRENTS": "Brak torrentów.", + "NO_TORRENTS_FOR_THIS_FILTER": "Brak torrentów dla tego filtra.", + "NO_TORRENTS_SELECTED": "Nie zaznaczono torrentów", + "NO_TORRENT_SELECTED": "Nie zaznaczono torrenta", + "NO_TRACKERS_RETURNED_BY_RTORRENT": "rTorrent nie zwrócił trackerów.", + "OFF": "Wył.", + "OFFLINE": "offline", + "ONE_PLACE_TO_CLEAR_LOGS_AND_ACTIVE_PROFILE_CACHES_PENDING_RUNNING_JOBS_RULES_SET": "Jedno miejsce do czyszczenia logów i pamięci podręcznej aktywnego profilu. Oczekujące/uruchomione zadania, reguły, ustawienia i torrenty pozostają bez zmian.", + "ONE_TRACKER_URL_PER_LINE": "Jeden tracker URL per linia", + "ONLINE": "online", + "ONLY_SELECTED": "Tylko wybrane", + "OPEN_DOWNLOAD_PLANNER": "Otwórz Pobierz planer", + "OPEN_RTORRENT_FILES_MAX_OPEN_FILES": "Otwórz rTorrent files / maks. otwórz files", + "OPEN_RTORRENT_HTTP_CONNECTIONS_MAX_HTTP_CONNECTIONS": "Otwórz rTorrent HTTP connections / maks. HTTP connections", + "OPEN_RTORRENT_SOCKETS": "Otwórz rTorrent sockets", + "OPEN_SOURCE": "Open source", + "OPEN_THIS_TAB_TO_LOAD_DIAGNOSTICS": "Otwórz ten karta do załaduj diagnostyka.", + "OPEN_THIS_TAB_TO_LOAD_STATISTICS": "Otwórz ten karta do załaduj statystyki.", + "OPERATION_LOG_RETENTION": "Operacja log retencja", + "OPTIONAL": "opcjonalne", + "OPTIONAL_PEER_TABLE_HELPERS": "Opcjonalne peer table helpers.", + "OPTIONAL_PRIVATE_SOURCE_TAG": "opcjonalne prywatny źródło tag", + "OPTIONAL_VISUAL_EASTER_EGG_FOR_LOADING_STATES_AND_OCCASIONAL_BUTTON_CLICKS_DISAB": "Opcjonalne wizualne easter egg dla ładowanie stany i sporadyczne przycisk kliknięcia. Wyłączone według domyślne.", + "PARALLEL_JOBS": "Równoległe zadania", + "PARENT_DIRECTORY": "Nadrzędny katalog", + "PARTIAL_DETAILS_LOADED": "Załadowano część szczegółów", + "PASSWORD": "Hasło", + "PASSWORD_NEW_PASSWORD": "Hasło / nowy hasło", + "PASTE_ONE_MAGNET_URI_PER_LINE": "Wklej jeden magnet URI per linia.", + "PATH": "Ścieżka", + "PATH_CONTAINS": "Ścieżka zawiera", + "PATH_TEXT": "Ścieżka tekst", + "PATH_USED_FOR_SELECTED_MODE": "Ścieżka używana dla wybranego trybu", + "PAUSE": "Pauza", + "PAUSED": "Wstrzymane", + "PEAK_S": "Szczyt S", + "PEAK_SPEED_UNAVAILABLE": "Szczyt prędkość niedostępna", + "PEERS": "Peery", + "PEERS_AUTO_REFRESH": "Peery auto odśwież", + "PENDING_JOBS_OLDER_THAN_THIS_ARE_RESUBMITTED_IF_NO_WORKER_IS_CURRENTLY_HANDLING_": "Oczekujące zadania starsze niż ten są ponownie zgłaszane jeśli brak worker jest obecnie obsługuje je. Domyślne: 900 sekundy.", + "PENDING_RUNNING_DONE_FAILED_RETRY_AND_CANCEL_HISTORY": "Oczekujące, uruchomione, ukończone, nieudane, ponów i anuluj historia.", + "PENDING_TIMEOUT_SECONDS": "Oczekujące limit czasu sekundy", + "PIECE_SIZE": "Część size", + "PLANNER": "Planer", + "POLISH": "Polski", + "PORT": "Port", + "PORT_CHECKER": "Sprawdzanie portu", + "PORT_CHECK_DISABLED": "Port sprawdź wyłączone", + "PORT_UNKNOWN": "Port - unknown", + "POST_CHECK": "Po sprawdzeniu", + "PREFERENCES": "Preferencje", + "PREFERENCES_SAVED": "Preferencje zapisane", + "PRIORITY": "Priorytet", + "PRIVATE_TORRENT": "Prywatny torrent", + "PROFILE_BACKUP": "Profil kopia zapasowa", + "PROFILE_BACKUP_NAME": "Profil kopia zapasowa nazwa", + "PROFILE_BACKUP_RESTORES_ONLY_THE_ACTIVE_PROFILE_CONTEXT_APPLICATION_BACKUP_RESTO": "Profil kopia przywraca tylko aktywne profil kontekst. Aplikacja kopia przywraca globalne aplikacja dane i jest dostępne tylko do administratorzy.", + "PROFILE_NAME": "Profil nazwa", + "PROFILE_SCOPED_LOG_COUNTS_AND_CLEANUP_OVERVIEW": "Profil-zakresowe log liczby i czyszczenie przegląd.", + "PROGRESS": "Postęp", + "PROGRESS_IS_AT_LEAST": "Postęp jest at least %", + "PROGRESS_IS_AT_MOST": "Postęp jest at most %", + "PROGRESS_SOURCE": "Źródło postępu", + "PROTECT_ACTIVE_COUNT_BELOW_CAP": "Chroń aktywne liczba poniżej cap", + "PYTORRENT_EXPECTS_TRUSTED_REVERSE_PROXY_IDENTITY_HEADERS_IF_YOU_ARE_ALREADY_SIGN": "pyTorrent oczekuje zaufanych nagłówków tożsamości z reverse proxy. Jeśli jesteś już zalogowany, sprawdź nagłówki dostawcy i mapowanie użytkownika.", + "PYTORRENT_LOGIN": "pyTorrent login", + "PYTORRENT_STATUS": "pyTorrent status", + "P_PAUSE": "P - pause", + "QUALITY": "Jakość", + "QUEUE_REFILL_DURING_COOLDOWN": "Kolejka uzupełnianie podczas czas odczekania", + "RANDOM_CLICK_IMAGE_URL": "Losowy click obraz URL", + "RATIO": "Ratio", + "RATIO_GROUP": "Grupa ratio", + "RATIO_GROUPS": "Ratio groups", + "RATIO_IS_AT_LEAST": "Ratio jest at least", + "RATIO_RULES": "Reguły ratio", + "REANNOUNCE": "Reannounce", + "RECHECK": "Sprawdź ponownie", + "RECHECK_AFTER_MOVE": "Sprawdź ponownie po przenieś", + "RECOMMENDED_COLUMNS": "Rekomendowane kolumny", + "RECOMMENDED_COLUMNS_APPLIED": "Zastosowano rekomendowane kolumny", + "RECONNECTING": "ponowne łączenie", + "REFERENCE_VALUE_IS_KEPT_FROM_THE_FIRST_OVERRIDE_SAVE_LATER_SAVES_ADD_OR_CLEAR_DI": "Wartość referencyjna wartość jest zachowana z pierwszy nadpisanie zapisz. Późniejsze zapisy dodaj lub wyczyść różnice bez replacing oryginał wartość referencyjna.", + "REFRESH": "Odśwież", + "REFRESH_NOW": "Odśwież teraz", + "REGEX_TEXT": "Regex / tekst", + "RELOAD": "Przeładowanie", + "REMOTE_LOCATION": "Zdalna lokalizacja", + "REMOVE": "Usuń", + "REMOVE_DATA": "usuń dane", + "REMOVE_LABEL": "Usuń etykieta", + "REMOVE_SELECTED_TORRENTS": "Usuń wybrane torrents", + "REMOVE_WITH_DATA": "Usuń z dane", + "REPOSITORY": "Repozytorium", + "RESET": "Resetuj", + "RESET_UI_SETTINGS": "Resetuj ustawienia UI", + "RESET_VIEW_DEFAULTS": "Resetuj ustawienia widoków", + "RESIZE_TORRENT_DETAILS_PANEL": "Zmień rozmiar torrent szczegóły panel", + "RESOLVE_PEER_IP_TO_REVERSE_DNS_HOST": "Rozwiąż peer IP to reverse DNS host", + "RESUME": "Wznów", + "RETENTION_DAYS": "dni retencji", + "RETENTION_MODE": "tryb retencji", + "RETRY": "Ponów", + "REVERSE_DNS": "Reverse DNS", + "RSS_DOWNLOADER": "RSS pobieracz", + "RTORRENT": "rTorrent", + "RTORRENTS": "rTorrents", + "RTORRENT_CONFIG": "rTorrent konfiguracja", + "RTORRENT_INCOMING_PORT": "rTorrent przychodzący port", + "RTORRENT_IS_STARTING_OR_NOT_RESPONDING_YET": "rTorrent uruchamia się albo jeszcze nie odpowiada.", + "RTORRENT_PROFILES": "rTorrent profile", + "RULE": "Zasada", + "RULES": "Zasady", + "RULES_ARE_CHECKED_AUTOMATICALLY_EVERY_5_MINUTES_A_TORRENT_USES_THE_GROUP_STORED_": "Reguły są sprawdzane automatically co 5 minut. torrent używa grupa zapisana w its rTorrent własne ratio pole.", + "RULE_NAME": "Reguła nazwa", + "RUNTIME": "Runtime", + "RUN_A_PROFILE_TEST_TO_SHOW_DIAGNOSTICS": "Run a profil test to pokaż diagnostyka.", + "RUN_SMART_QUEUE_DURING_POLLING_STOPPED_TORRENTS_ARE_MANAGED_PAUSED_TORRENTS_STAY": "Uruchomienie Smart Queue podczas pollingu. Zatrzymane torrents są zarządzane; Wstrzymane torrents pozostają użytkownik-kontrolowane.", + "R_RESUME": "R - wznów", + "SAVE": "Zapisz", + "SAVED_LABELS": "Zapisane etykiety", + "SAVE_COLUMNS": "Zapisz kolumny", + "SAVE_CONFIG": "Zapisz konfiguracja", + "SAVE_EASTER_EGG": "Zapisz easter egg", + "SAVE_EXCEPTIONS": "Zapisz exceptions", + "SAVE_FEED": "Zapisz kanał", + "SAVE_FOOTER": "Zapisz stopka", + "SAVE_GROUP": "Zapisz grupa", + "SAVE_JOB_SETTINGS": "Zapisz zadanie ustawienia", + "SAVE_LIMITS": "Zapisz limity", + "SAVE_LOCATION": "Zapisz lokalizacja", + "SAVE_LOG_VIEW": "Zapisz log view", + "SAVE_PATH": "Zapisz ścieżka", + "SAVE_PREFERENCES": "Zapisz preferencje", + "SAVE_RETENTION": "Zapisz retencja", + "SAVE_RULE": "Zapisz reguła", + "SAVE_SCHEDULE": "Zapisz harmonogram", + "SAVE_USER": "Zapisz użytkownik", + "SCGI_URL": "SCGI URL", + "SEARCH_LOGS": "Szukaj logi...", + "SEARCH_TORRENTS": "Szukaj torrentów...", + "SEARCH_TORRENTS_TO_EXCLUDE": "Szukaj torrents to wyklucz...", + "SEASON": "Sezon", + "SECONDS_TO_WAIT_FOR_RTORRENT_RESPONSE": "Sekundy to czekać for rTorrent odpowiedź.", + "SEEDING": "Seedowanie", + "SEEDS": "Seedy", + "SEEDS_ARE_LOW_FOR_TIME": "Seeds are niska for time", + "SEED_MINUTES": "Seed minuty", + "SELECT": "Wybierz", + "SELECTED": "zaznaczono", + "SELECTED_LABELS": "Wybrane etykiety", + "SELECTED_MONITORED_PATH": "Wybrana monitorowana ścieżka", + "SELECTED_TORRENTS_WILL_BE_REMOVED": "wybrane torrents będzie be removed.", + "SELECT_A_MONITORED_PATH_FIRST": "Najpierw wybierz monitorowaną ścieżkę.", + "SELECT_A_TORRENT": "Wybierz a torrent.", + "SELECT_ONE_OR_MORE_TORRENT_FILES": "Wybierz jeden lub more .torrent files.", + "SELECT_PATH": "Wybierz ścieżka", + "SELECT_TORRENTS_THAT_SMART_QUEUE_SHOULD_IGNORE_USE_SEARCH_TO_FILTER_BY_NAME_LABE": "Wybierz torrents że Smart Queue powinien ignorować. Użyj szukaj do filtr według nazwa, etykieta, status lub hash.", + "SELECT_VISIBLE": "zaznacz widoczne", + "SEPARATE_SLOT_POOL_FOR_LIGHTWEIGHT_CONTROL_JOBS_SO_THEY_DO_NOT_WAIT_BEHIND_HEAVY": "Oddzielny slot pool for lekki kontrola zadania so they do nie czekać behind ciężkie IO work. Domyślne: 4.", + "SETTINGS": "Ustawienia", + "SET_LABEL": "Set etykieta...", + "SET_LABELS": "Set etykiety", + "SET_RATIO_GROUP": "Set ratio grupa...", + "SHARE_AFTER_CREATING": "Udostępnij po creating", + "SHORTCUTS": "Skróty", + "SHOWN": "Pokazane", + "SHOWN_IN_LOADING_STATES_INSTEAD_OF_THE_STANDARD_SPINNER": "Pokazane w ładowanie stany zamiast standardowy spinner.", + "SHOWS_TRACKER_ICONS_IN_THE_SIDEBAR_TRACKER_FILTER_WHEN_AVAILABLE": "Pokazuje tracker ikony w panel boczny tracker filtr when dostępne.", + "SHOW_COMBINED_USAGE_SINGLE_PATH_SELECTION_IS_DISABLED_IN_THIS_MODE": "Pokaż łączne użycie. Pojedynczy ścieżka zaznaczenie jest wyłączone zaloguj ten tryb.", + "SHOW_DL_UP_IN_BROWSER_TITLE": "Pokaż DL/UP w tytule przeglądarki", + "SHOW_SMART_QUEUE_AUTOMATIC_RUN_MESSAGES": "Pokaż Smart Queue automatyczne uruchomienie komunikaty.", + "SHOW_TOASTS_CREATED_BY_AUTOMATION_RUNS": "Pokaż toasty created według automation uruchomienia.", + "SIGN_IN": "Zaloguj", + "SIZE": "Rozmiar", + "SKIP_ACTIVE_UPLOAD": "Skip aktywne wyślij", + "SKIP_PRIVATE_TORRENTS": "Skip prywatny torrents", + "SMART_FILTERS": "Inteligentne filtry", + "SMART_QUEUE": "Smart Queue", + "SMART_QUEUE_EXCEPTIONS": "Smart Queue exceptions", + "SMART_QUEUE_KEEPS_ONLY_THIS_MANY_ACTIVE_DOWNLOADS_OVERFLOW_IS_STOPPED": "Smart Queue keeps tylko ten many aktywne pobierania; nadmiarowe jest zatrzymane.", + "SMART_QUEUE_TOASTS": "Smart Queue toasty", + "SOCKETS": "Sockets", + "SOURCE": "Źródło", + "SPACE_START": "Spacja - start", + "SPEED": "Prędkość", + "SPEED_LIMITS": "Prędkość limity", + "SPEED_TREND": "Prędkość trend", + "STALLED_AFTER_SECONDS": "Zatrzymane po sekundy", + "START": "Start", + "START_AFTER_ADD": "Start po dodaj", + "START_GRACE_SECONDS": "Start grace sekundy", + "STATE": "Stan", + "STATUS": "Status", + "STATUS_EQUALS": "Status równa się", + "STOP": "Stop", + "STOPPED": "Zatrzymane", + "S_STOP": "S - stop", + "TARGET_ACTIVE_DOWNLOADS": "Docelowy aktywne pobierania", + "TARGET_PATH": "Docelowy ścieżka", + "TEST_RULE": "Test reguła", + "TEST_SCGI": "Test SCGI", + "THEME_TYPOGRAPHY_AND_INTERFACE_SCALE": "Motyw, typografia i skala interfejsu.", + "THE_FOOTER_TOOLTIP_ALWAYS_SHOWS_DETAILS_FOR_AVAILABLE_PATHS_THIS_SETTING_ONLY_DE": "stopka podpowiedź zawsze pokazuje szczegóły dla dostępne ścieżki; ten ustawienie tylko decyduje która wartość steruje widoczny postęp pasek.", + "TIMEOUT": "Limit czasu", + "TOAST_NOTIFICATIONS_FROM_AUTOMATIC_SYSTEMS": "Toast powiadomienia z automatyczne systems.", + "TOOLS": "Narzędzia", + "TOOLS_RTORRENTS": "Narzędzia & rTorrents", + "TOOLS_SECTIONS": "Narzędzia sekcje", + "TORRENT_ADDED": "Torrent dodano", + "TORRENT_COMPLETED": "Torrent ukończone", + "TORRENT_DETAILS": "Szczegóły torrenta", + "TORRENT_FILES": "Torrent files", + "TORRENT_FILTERS": "Torrent filtry", + "TORRENT_PROPERTIES": "Torrent właściwości", + "TORRENT_REMOVED": "Torrent removed", + "TORRENT_STATISTICS": "Torrent statystyki", + "TORRENT_STATS": "Torrent statystyki", + "TOTAL_DL_UP": "Suma DL/UP", + "TO_DOWNLOAD": "Do pobrania", + "TRACKERS": "Trackery", + "TRACKER_ICONS": "Ikony trackerów", + "TRANSFER": "Transfer", + "TRANSFERRED_DATA": "Przesłane dane", + "TRANSFER_HISTORY": "Transfer historia", + "UNDEFINED": "niezdefiniowane", + "UNLIMITED": "Bez limitu", + "UPLOADED": "Wysłano", + "UPLOADS": "Wysyłania", + "UPLOAD_KIB_S": "Wyślij KiB/s", + "USER": "Użytkownik", + "USERS": "Użytkownicy", + "USES_A_LIGHTWEIGHT_BUILT_IN_RESOLVER_WITH_CACHE_HOSTNAMES_APPEAR_ONLY_IN_THE_PEE": "Używa lekki built-w resolver z cache. Nazwy hostów pojawi się tylko w Peery karta.", + "USES_LOWER_ROWS_AND_SMALLER_LIST_ELEMENTS_ON_DESKTOP_AND_MOBILE_SO_MORE_TORRENTS": "Używa niższe wiersze i smaller lista elements on desktop i mobile so more torrents zmieścić on ekran.", + "USES_YOUGETSIGNAL_FIRST_MANUAL_CHECK_BYPASSES_THE_6H_CACHE": "Używa YouGetSignal pierwszy. Ręczne sprawdź bypasses 6h cache.", + "USE_ONE_CUSTOM_PATH_BELOW_AS_THE_FOOTER_PROGRESS_VALUE": "Użyj jedno własne ścieżka poniżej jako stopka postęp wartość.", + "USE_SELECTED": "Używają wybrane", + "USE_THE_MAIN_DIRECTORY_FROM_THE_ACTIVE_RTORRENT_PROFILE": "Użyj main katalog z aktywne rTorrent profil.", + "VIEW_PREFERENCES_RESET": "Zresetowano ustawienia widoku", + "VIEW_STATE_IS_SAVED_AUTOMATICALLY_IN_THE_DATABASE_CURRENT_TORRENT_FILTER_LAST_SO": "Stan widoku jest zapisywany automatycznie w bazie: bieżący filtr torrentów, ostatnia kolumna sortowania i kierunek, widoczne kolumny oraz wysokość panelu szczegółów.", + "VISIBLE_NAME_USED_IN_THE_PROFILE_SELECTOR": "Widoczny nazwa używana w profil selector.", + "VISUAL_HELPER_FOR_TRACKER_FILTERS_IN_THE_SIDEBAR": "Wizualne pomocnik dla tracker filtry w panel boczny.", + "WAITING_FOR_DATA": "Oczekiwanie for dane.", + "WAITING_FOR_TORRENT_DATA_FROM_THE_ACTIVE_PROFILE": "Oczekiwanie na dane torrentów z aktywnego profilu.", + "WATCHDOG_MARKS_A_LIGHT_JOB_AS_FAILED_AFTER_THIS_TIME_DEFAULT_300_SECONDS": "Watchdog oznacza a lekkie zadanie jako nieudane po ten czas. Domyślne: 300 sekundy.", + "WATCHDOG_TIMEOUT_FOR_MOVE_REMOVE_ADD_JOBS_DEFAULT_7200_SECONDS": "Watchdog limit czasu for przenieś/usuń/dodaj zadania. Domyślne: 7200 sekundy.", + "WHEN_DISABLED_THE_APPLICATION_USES_THE_NORMAL_PRODUCTION_UI": "When wyłączone, aplikacja używa normalny produkcyjny UI.", + "WHEN_ENABLED_LOW_SPEED_IS_NOT_REQUIRED_WITH_SOURCE_AND_SPEED_IGNORES_ENABLED_ONL": "When włączone, niskie prędkość jest nie wymagany. Z źródło i prędkość ignores włączone, tylko Zatrzymane po sekund decyduje.", + "WHEN_ENABLED_SMART_QUEUE_DOES_NOT_USE_SEED_PEER_COUNT_AS_A_STALLED_CRITERION": "When włączone, Smart Queue does nie użyj seed/peer liczba jako zatrzymane kryterium.", + "WITH_ERROR": "Z błędem", + "WORKING": "Pracuję...", + "FRENCH": "Francuski", + "CZECH": "Czeski", + "SPANISH": "Hiszpański", + "NORWEGIAN": "Norweski", + "RUSSIAN": "Rosyjski" + } +} diff --git a/pytorrent/static/i18n/ru_RU.json b/pytorrent/static/i18n/ru_RU.json new file mode 100644 index 0000000..506e7bb --- /dev/null +++ b/pytorrent/static/i18n/ru_RU.json @@ -0,0 +1,566 @@ +{ + "meta": { + "locale": "ru_RU", + "label": "Русский", + "flag": "ru" + }, + "translations": { + "0_MEANS_ONLY_SEED_THRESHOLD_IS_REQUIRED": "0 означает, что требуется только порог раздачи.", + "0_MEANS_UNLIMITED_SLIDERS_USE_MBIT_S_AND_SAVE_THROUGH_THE_EXISTING_SPEED_LIMITS_": "0 означает без ограничений. Ползунки используют Mbit/s и сохраняют значения через существующий API лимитов скорости.", + "0_SELECTED": "0 выбрано", + "ABOUT_PYTORRENT": "О pyTorrent", + "ACTION": "Действие", + "ACTIVE": "Активные", + "ACTIVE_RTORRENT_DOWNLOADS_MAX_GLOBAL_DOWNLOADS": "Активные загрузки rTorrent / макс. глобальные загрузки", + "ACTIVE_RTORRENT_UPLOADS_MAX_GLOBAL_UPLOADS": "Активные отдачи rTorrent / макс. глобальные отдачи", + "ADD": "Добавить", + "ADDED": "Добавлено", + "ADDS_REMOVALS_COMPLETIONS_AND_QUEUED_OPERATION_RESULTS": "Добавления, удаления, завершения и результаты операций в очереди.", + "ADD_ACTION": "Добавить действие", + "ADD_CONDITION": "Добавить условие", + "ADD_CREATE_TORRENT": "Добавить / создать торрент", + "ADD_FIRST_LABEL_ABOVE": "Добавьте первую метку выше.", + "ADD_LABEL": "Добавить метку", + "ADD_MAGNET_LINK": "Добавить magnet-ссылку", + "ADD_NEW_LABEL": "Добавить новую метку", + "ADD_OR_EDIT_GROUP": "Добавить или изменить группу", + "ADD_PATH": "Добавить путь", + "ADD_PROFILE": "Добавить профиль", + "ADD_RTORRENT_PROFILE": "Добавить профиль rTorrent", + "ADD_THE_FIRST_RTORRENT_PROFILE_TO_START_LOADING_TORRENTS": "Добавьте первый профиль rTorrent, чтобы начать загрузку торрентов.", + "ADD_TORRENT": "Добавить торрент", + "ADD_TORRENT_FILE": "Добавить torrent-файл", + "ADMIN": "администратор", + "ADMIN_ONLY_FULL_APPLICATION_BACKUP_RESTORE_CAN_REPLACE_USERS_PERMISSIONS_PROFILE": "Полная резервная копия приложения только для администратора. Восстановление может заменить пользователей, разрешения, профили и глобальные настройки приложения.", + "AGGREGATE_ALL_PATHS": "Агрегировать все пути", + "ALL": "Все", + "ALL_NON_JOB_TYPES": "Все типы, кроме заданий", + "ALL_PROFILES": "Все профили", + "ALL_TYPES": "Все типы", + "ANNOUNCE": "Анонсировать", + "API_DOCS": "Документация API", + "APPEARANCE": "Внешний вид", + "APPEARANCE_PREFERENCES_SAVED": "Настройки внешнего вида сохранены", + "APPEARS_NEAR_CLICKED_BUTTONS_ONLY_SOMETIMES": "Иногда появляется рядом с нажатыми кнопками.", + "APPLICATION_BACKUP": "Резервная копия приложения", + "APPLICATION_BACKUP_NAME": "Имя резервной копии приложения", + "APPLY": "Применить", + "APPLY_RETENTION_NOW": "Применить хранение сейчас", + "APPLY_SAVED_CHANGES_60S_AFTER_PYTORRENT_START": "Применить сохранённые изменения через 60s после запуска pyTorrent", + "APP_STATUS": "Статус приложения", + "AUTHENTICATION_IS_ENABLED_FOR_THIS_PYTORRENT_INSTANCE": "Аутентификация включена для этого экземпляра pyTorrent.", + "AUTHOR": "Автор", + "AUTOMATIC": "Автоматически", + "AUTOMATIC_KEEPS_THE_CURRENT_POLLER_CADENCE_CUSTOM_RUNS_ONLY_AFTER_THE_SELECTED_N": "Автоматический режим сохраняет текущий ритм poller. Пользовательский режим запускается только после выбранного числа минут. Выключение полностью отключает пополнение очереди.", + "AUTOMATIC_QUEUE_BALANCING_FOR_SLOW_OR_STALLED_DOWNLOADS": "Автоматическая балансировка очереди для медленных или зависших загрузок.", + "AUTOMATIC_RUNS_USE_THE_COOLDOWN_BELOW_MANUAL_CHECK_NOW_STILL_RUNS_IMMEDIATELY": "Автоматические запуски используют паузу ниже. Ручная проверка всё равно запускается сразу.", + "AUTOMATIONS": "Автоматизации", + "AUTOMATIONS_RULES": "Автоматизации / правила", + "AUTOMATION_TOASTS": "Уведомления автоматизации", + "AUTO_STOP_WHEN_IDLE": "Автостоп при простое", + "BACKEND": "Backend", + "BACKUP": "Резервная копия", + "BACKUP_RESTORE": "Резервное копирование / восстановление", + "BACK_TO_DASHBOARD": "Назад к панели", + "BOOTSTRAP_THEME": "Тема Bootstrap", + "BROWSER": "Браузер", + "BROWSER_TITLE": "Заголовок браузера", + "BUILD_A_RULE_AS_CONDITIONS_FIRST_THEN_ORDERED_ACTIONS_MATCHING_TORRENTS_ARE_HAND": "Создайте правило так: сначала условия, затем действия по порядку. Подходящие торренты обрабатываются одной партией, а пауза применяется ко всему правилу.", + "BUSY": "занято", + "BY_DAYS": "По дням", + "BY_LINE_COUNT": "По числу строк", + "CACHED_METADATA_SUMMARY_FILE_METADATA_IS_REFRESHED_EVERY_15_MINUTES_A_FEW_MINUTE": "Сводка метаданных из кэша. Метаданные файлов обновляются каждые 15 минут, через несколько минут после запуска или вручную.", + "CANCEL": "Отмена", + "CANCEL_EDIT": "Отменить редактирование", + "CATEGORY": "Категория", + "CHANGES_APPLY_IMMEDIATELY_WHERE_POSSIBLE_INITIAL_STARTUP_LOADER_USES_THEM_AFTER_": "Изменения применяются сразу, где это возможно; начальный загрузчик применит их после перезагрузки.", + "CHANGE_RTORRENT": "Сменить rTorrent", + "CHANGE_THEME": "Сменить тему", + "CHANGING_RTORRENT_RELOADS_THE_LIVE_TORRENT_SNAPSHOT": "Смена rTorrent перезагружает текущий снимок торрентов.", + "CHECKING": "Проверка", + "CHECK_NOW": "Проверить сейчас", + "CHECK_PORT_NOW": "Проверить порт сейчас", + "CHECK_THIS_IF_YOU_WANT_TO_CONNECT_TO_A_REMOTE_RTORRENT_INSTANCE_INSTEAD_OF_LOCAL": "Отметьте это, если хотите подключиться к удалённому экземпляру rTorrent вместо localhost.", + "CHOOSE_COLUMNS_VISIBLE_IN_THE_TORRENT_LIST": "Выберите столбцы, видимые в списке торрентов.", + "CHOOSE_FILES": "Выбрать файлы", + "CHOOSE_RTORRENT": "Выбрать rTorrent", + "CHOOSE_TORRENTS_IGNORED_BY_SMART_QUEUE_EXISTING_BEHAVIOR_STAYS_UNCHANGED_FOR_ALL": "Выберите торренты, игнорируемые Smart Queue. Текущее поведение остаётся без изменений для всех не исключённых торрентов.", + "CHOOSE_WHAT_THE_FOOTER_DISK_BAR_SHOULD_REPRESENT_AND_ADD_EXTRA_STORAGE_PATHS": "Выберите, что должна показывать полоса диска внизу, и добавьте дополнительные пути хранения.", + "CHOOSE_WHICH_STATUS_ITEMS_ARE_VISIBLE_IN_THE_BOTTOM_BAR": "Выберите элементы статуса, видимые на нижней панели.", + "CHUNKS": "Части", + "CLEANUP": "Очистка", + "CLEANUP_RETENTION": "Очистка / хранение", + "CLEAR": "Очистить", + "CLEAR_CURRENT_FILTER": "Очистить текущий фильтр", + "CLEAR_FINISHED": "Очистить завершённые", + "CLEAR_LABELS": "Очистить метки", + "CLEAR_SELECTION": "очистить выбор", + "CLEAR_VISIBLE": "Очистить видимые", + "CLOSE": "Закрыть", + "COLUMNS": "Столбцы", + "COLUMNS_SAVED": "Столбцы сохранены", + "COMMENT": "Комментарий", + "COMPACT_TORRENT_LIST": "Компактный список торрентов", + "COMPLETE": "Завершено", + "COMPLETED": "Завершённые", + "CONFIGURED_RTORRENTS": "Настроенные rTorrent", + "CONNECTING_TO_RTORRENT_AND_PREPARING_DATA": "Подключение к rTorrent и подготовка данных.", + "CONNECTION_ADDRESS_IN_SCGI_HOST_PORT_RPC2_FORMAT": "Адрес подключения в формате scgi://host:port/RPC2.", + "CONTROLS_THE_DEFAULT_CATEGORY_AND_JOB_LOG_VISIBILITY_USED_BY_THE_LOGS_MODAL": "Управляет категорией по умолчанию и видимостью логов заданий в модальном окне логов.", + "CONTROLS_WHAT_IS_SHOWN_IN_THE_BROWSER_TAB": "Управляет тем, что отображается во вкладке браузера.", + "COOLDOWN_MINUTES": "Пауза, минуты", + "COPY": "Копировать", + "COPY_HASH": "Копировать hash", + "COPY_NAME": "Копировать имя", + "COPY_PATH": "Копировать путь", + "CPU_RAM_USAGE": "Использование CPU / RAM", + "CREATE": "Создать", + "CREATES_AND_RESTORES_SETTINGS_FOR_THE_CURRENTLY_SELECTED_PROFILE_USER_SCOPED_PRE": "Создаёт и восстанавливает настройки для текущего выбранного профиля. Пользовательские предпочтения при необходимости переназначаются на текущего пользователя.", + "CREATE_APPLICATION_BACKUP": "Создать резервную копию приложения", + "CREATE_ONE_RTORRENT_PROFILE_AT_A_TIME_MOVE_REMOVE_QUEUES_KEEP_THEIR_ORDER_FOR_EA": "Создавайте по одному профилю rTorrent за раз. Очереди перемещения/удаления сохраняют порядок для каждого профиля.", + "CREATE_PROFILE_BACKUP": "Создать резервную копию профиля", + "CREATE_REUSABLE_LABELS_AND_REMOVE_LABELS_THAT_ARE_NO_LONGER_NEEDED": "Создавайте многоразовые метки и удаляйте метки, которые больше не нужны.", + "CREATE_TORRENT": "Создать торрент", + "CTRL_A_SELECT_VISIBLE": "Ctrl+A - выбрать видимые", + "CTRL_I_INVERT_VISIBLE": "Ctrl+I - инвертировать видимые", + "CTRL_O_ADD": "Ctrl+O - добавить", + "CTRL_S_DOWNLOAD_TORRENT": "Ctrl+S - скачать .torrent", + "CURRENT_TRANSFER_SPEED": "Текущая скорость передачи", + "CUSTOM_DOWNLOAD": "Пользовательская загрузка", + "CUSTOM_UPLOAD": "Пользовательская отдача", + "DAYS_AND_LINE_COUNT": "Дни и число строк", + "DECREASE_OR_INCREASE_THE_WHOLE_INTERFACE_SIZE": "Уменьшите или увеличьте размер всего интерфейса.", + "DEFAULT_LOG_CATEGORY": "Категория логов по умолчанию", + "DEFAULT_LOG_VIEW": "Вид логов по умолчанию", + "DEFAULT_RTORRENT_PATH": "Путь rTorrent по умолчанию", + "DEGRADED": "ограничено", + "DELETE": "Удалить", + "DELETE_REMOVE": "Delete - удалить", + "DESKTOP": "Рабочий стол", + "DETAILS_WILL_APPEAR_AFTER_THE_FIRST_SUCCESSFUL_RESPONSE": "Подробности появятся после первого успешного ответа.", + "DIAGNOSTICS": "Диагностика", + "DISABLED": "отключено", + "DISK_MONITOR": "Монитор диска", + "DISK_USAGE_UNAVAILABLE": "Использование диска недоступно", + "DISPLAYS_CURRENT_SPEEDS_NEXT_TO_PYTORRENT_IN_THE_TAB_TITLE": "Показывает текущие скорости рядом с pyTorrent в заголовке вкладки.", + "DOCS_API": "Документация API", + "DOWNLOADED": "Скачано", + "DOWNLOADING": "Загрузка", + "DOWNLOADS": "Загрузки", + "DOWNLOAD_KIB_S": "Загрузка KiB/s", + "DOWNLOAD_STARTED": "Загрузка начата", + "DOWNLOAD_TORRENT": "Скачать .torrent", + "DOWNLOAD_TRACKER_FAVICONS": "Загружать favicon трекеров", + "DRAG_TO_RESIZE_DETAILS_PANEL": "Перетащите, чтобы изменить размер панели деталей", + "EASTER_EGG": "Easter egg", + "EDIT": "Редактировать", + "EMERGENCY_CANCEL": "Аварийная отмена", + "EMERGENCY_CLEAN_ALL": "Аварийно очистить всё", + "ENABLED": "Включено", + "ENABLE_AUTOMATIC_APPLICATION_BACKUPS": "Включить автоматические резервные копии приложения", + "ENABLE_AUTOMATIC_PROFILE_BACKUPS": "Включить автоматические резервные копии профиля", + "ENABLE_EASTER_EGG": "Включить easter egg", + "ENABLE_INCOMING_PORT_CHECK": "Включить проверку входящего порта", + "ENABLE_REVERSE_DNS_FOR_PEERS": "Включить reverse DNS для пиров", + "ENGLISH": "Английский", + "EPISODE": "Эпизод", + "ESC_CLEAR_SELECTION": "Esc - очистить выбор", + "ETA": "ETA", + "EVERY_N_MINUTES": "Каждые N минут", + "EVERY_X_HOURS": "Каждые X часов", + "EXCLUDE": "Исключить", + "EXCLUDE_FROM_SMART_QUEUE": "Исключить из Smart Queue", + "EXCLUDE_PATTERN": "Шаблон исключения", + "EXISTING_GROUPS": "Существующие группы", + "EXPORT": "Экспорт", + "EXPORT_JSON": "Экспорт JSON", + "EXTERNAL_AUTHENTICATION_IS_ENABLED_THROUGH_EXTERNAL_PROVIDER": "Внешняя аутентификация включена через {{ external_provider }}.", + "E_G_PUNKTY_KATALOGOWANIE": "например: Punkty katalogowanie", + "FEATURES": "Возможности", + "FEED": "Лента", + "FEEDS_ARE_CHECKED_BY_SCHEDULE_AND_EVERY_MATCH_IS_LOGGED_PER_FEED_RULE": "Ленты проверяются по расписанию, и каждое совпадение записывается для ленты/правила.", + "FEEDS_RULES_AND_MATCHES": "Ленты, правила и совпадения", + "FEED_NAME": "Имя ленты", + "FEED_URL": "URL ленты", + "FILES": "Файлы", + "FILE_OR_DIRECTORY_PATH": "Путь к файлу или каталогу", + "FONT": "Шрифт", + "FOOTER": "Нижняя панель", + "FORCE": "Принудительно", + "FORCE_RECHECK": "Принудительная перепроверка", + "FRONTEND": "Frontend", + "FULL": "Полный", + "GENERAL": "Общее", + "GENERATED_RTORRENT_CONFIG_CHANGES_WILL_APPEAR_HERE": "Сгенерированные изменения конфигурации rTorrent появятся здесь.", + "GENERATE_CONFIG": "Сгенерировать конфигурацию", + "GERMAN": "Немецкий", + "GO": "Перейти", + "GROUPED_RTORRENT_RUNTIME_SETTINGS_WITH_INLINE_RECOMMENDATIONS_AND_COMPATIBILITY_": "Сгруппированные runtime-настройки rTorrent с inline-рекомендациями и статусом совместимости.", + "GROUP_NAME": "Имя группы", + "HASH": "Hash", + "HASHING": "Хеширование", + "HEAVY_PARALLEL_JOBS": "Тяжёлые параллельные задания", + "HEAVY_TIMEOUT_SECONDS": "Таймаут тяжёлых заданий, секунды", + "HIDE_JOB_LOGS": "Скрыть логи заданий", + "HIDE_JOB_LOGS_BY_DEFAULT": "Скрывать логи заданий по умолчанию", + "HISTORY": "История", + "HOW_LONG_A_MATCHING_ACTIVE_TORRENT_MUST_STAY_STALLED_BEFORE_IT_CAN_BE_REPLACED": "Как долго подходящий активный торрент должен оставаться зависшим, прежде чем его можно заменить.", + "IGNORE_MISSING_SEEDS_PEERS_FOR_STALLED_TIMER": "Игнорировать отсутствие сидов/пиров для таймера зависания", + "IGNORE_SPEED_FOR_STALLED_TIMER": "Игнорировать скорость для таймера зависания", + "IMPORT": "Импорт", + "IMPORT_JSON": "Импорт JSON", + "INCLUDE_PATTERN": "Шаблон включения", + "INCOMING_CONNECTION_TEST_SEPARATE_FROM_VISUAL_PREFERENCES": "Проверка входящего соединения, отдельно от визуальных настроек.", + "INTERFACE_SCALE": "Масштаб интерфейса", + "INTERVAL_MINUTES": "Интервал, минуты", + "INVERT_VISIBLE": "инвертировать видимые", + "JOBS": "Задания", + "JOB_DONE": "Задание выполнено", + "JOB_FAILED": "Задание не удалось", + "JOB_QUEUE": "Очередь заданий", + "JOB_SCHEDULING": "Планирование заданий", + "JOB_STARTED": "Задание начато", + "KEEP_LINES": "Сохранять строки", + "KEEP_SEEDING": "Продолжать раздачу", + "LABEL": "Метка", + "LABELS": "Метки", + "LABELS_SEPARATED_BY_COMMA": "Метки через запятую", + "LABEL_AFTER_SHARE": "Метка после раздачи", + "LABEL_EXISTS": "Метка существует", + "LABEL_IS_MISSING": "Метка отсутствует", + "LABEL_NAME_OR_SEVERAL_SEPARATED_BY_COMMA": "Имя метки или несколько через запятую", + "LANGUAGE": "Язык", + "LANGUAGE_SAVED": "Язык сохранён", + "LAST_OPERATIONS": "Последние операции", + "LICENSE": "Лицензия", + "LIGHTWEIGHT_WEB_PANEL_FOR_RTORRENT_MANAGEMENT_QUEUE_CONTROL_AND_LIVE_TORRENT_DIA": "Лёгкая веб-панель для управления rTorrent, контроля очереди и живой диагностики торрентов.", + "LIGHT_PARALLEL_JOBS": "Лёгкие параллельные задания", + "LIGHT_TIMEOUT_SECONDS": "Таймаут лёгких заданий, секунды", + "LIMIT_DL": "Лимит DL", + "LOADING": "Загрузка", + "LOADING_CLEANUP_DATA": "Загрузка данных очистки...", + "LOADING_CONFIG": "Загрузка конфигурации...", + "LOADING_IMAGE_URL": "Загрузка URL изображения", + "LOADING_JOBS": "Загрузка заданий...", + "LOADING_LOGS": "Загрузка логов...", + "LOADING_PROFILES": "Загрузка профилей...", + "LOADING_STATISTICS": "Загрузка статистики...", + "LOADING_TORRENTS": "Загрузка торрентов...", + "LOADING_TORRENT_DETAILS": "Загрузка деталей торрента...", + "LOCAL_BROWSER_TIME": "Локальное время браузера", + "LOCATION": "Расположение", + "LOG": "Лог", + "LOGS": "Логи", + "LOG_IN": "Войти", + "LOG_OUT": "Выйти", + "LOG_STATISTICS": "Статистика логов", + "MAGNET_AND_TORRENT_UPLOAD_FILE_PRIORITIES_LABELS_RATIO_GROUPS_SMART_QUEUE_AUTOMA": "Загрузка magnet и torrent-файлов, приоритеты файлов, метки, группы ratio, Smart Queue, правила автоматизации, RSS, графики трафика, проверка порта и статус системы.", + "MAGNET_LINKS": "Magnet-ссылки", + "MANAGE_EXCEPTIONS": "Управлять исключениями", + "MANAGE_OPERATION_LOG_RETENTION_WITHOUT_CHANGING_TORRENT_DATA": "Управляйте хранением логов операций без изменения данных торрентов.", + "MANAGE_OPTIONAL_PYTORRENT_USERS_EMPTY_PROFILE_MEANS_ALL_PROFILES_R_O_BLOCKS_RTOR": "Управляйте дополнительными пользователями pyTorrent. Пустой профиль означает все профили. R/O блокирует действия, изменяющие rTorrent; Full разрешает их.", + "MANUAL_CLEANUP_ONLY": "Только ручная очистка", + "MAXIMUM_HEAVY_JOBS_RUNNING_AT_ONCE_FOR_THIS_PROFILE_DEFAULT_5": "Максимум тяжёлых заданий, выполняемых одновременно для этого профиля. По умолчанию: 5.", + "MAXIMUM_QUEUED_ACTIONS_RUNNING_AT_ONCE": "Максимум действий из очереди, выполняемых одновременно.", + "MAXIMUM_STALLED_OVERFLOW_DOWNLOADS_SMART_QUEUE_MAY_STOP_IN_ONE_PASS": "Максимум зависших/лишних загрузок, которые Smart Queue может остановить за один проход.", + "MAX_MB": "Макс. MB", + "MAX_RATIO": "Макс. ratio", + "MAX_STOPS_PER_CHECK": "Макс. остановок за проверку", + "MESSAGE": "Сообщение", + "MINUTES": "Минуты", + "MIN_MB": "Мин. MB", + "MIN_PEERS": "Мин. пиров", + "MIN_RATIO": "Мин. ratio", + "MIN_SEEDS": "Мин. сидов", + "MIN_SEED_MINUTES": "Мин. минут раздачи", + "MIN_SPEED_KIB_S": "Мин. скорость KiB/s", + "MOBILE": "Мобильный", + "MOBILE_COLUMNS": "Мобильные столбцы", + "MOBILE_FILTER_GROUPS": "Мобильные группы фильтров", + "MOBILE_SIMPLE_MODE": "Мобильный/простой режим", + "MOBILE_SORT_FILTERS": "Мобильные сортировки и фильтры", + "MODE": "Режим", + "MONITORED_PATHS": "Отслеживаемые пути", + "MOVE": "Переместить", + "MOVE_DATA": "Переместить данные", + "MOVE_DATA_FILES": "Переместить файлы данных", + "MOVE_PATH": "Путь перемещения", + "MOVE_TO_PATH": "Переместить в путь", + "MOVIES": "фильмы", + "MOVING": "Перемещение", + "M_MOVE": "M - переместить", + "NAME": "Имя", + "NEGATE": "Инвертировать", + "NEWLY_QUEUE_STARTED_TORRENTS_ARE_PROTECTED_FROM_STALLED_CLEANUP_DURING_THIS_WARM": "Торренты, недавно запущенные очередью, защищены от очистки зависших во время этого прогрева.", + "NEW_LABEL": "Новая метка", + "NEXT_READY": "далее: готово", + "NEXT_SMART_QUEUE_RUN": "Следующий запуск Smart Queue", + "NOTIFICATIONS": "Уведомления", + "NOT_LOADED": "Не загружено.", + "NO_CHANGES": "Нет изменений", + "NO_FILES_RETURNED_BY_RTORRENT": "rTorrent не вернул файлы.", + "NO_FILES_SELECTED": "Файлы не выбраны.", + "NO_LABELS": "Нет меток.", + "NO_LABELS_SELECTED": "Метки не выбраны.", + "NO_PATH_LOADED": "Путь не загружен.", + "NO_PEERS_RETURNED_BY_RTORRENT": "rTorrent не вернул пиров.", + "NO_RTORRENT_PROFILE_CONFIGURED": "Профиль rTorrent не настроен.", + "NO_SAVED_LABELS": "Нет сохранённых меток.", + "NO_TORRENTS": "Нет торрентов.", + "NO_TORRENTS_FOR_THIS_FILTER": "Нет торрентов для этого фильтра.", + "NO_TORRENTS_SELECTED": "Торренты не выбраны", + "NO_TORRENT_SELECTED": "Торрент не выбран", + "NO_TRACKERS_RETURNED_BY_RTORRENT": "rTorrent не вернул трекеры.", + "OFF": "Выкл.", + "OFFLINE": "офлайн", + "ONE_PLACE_TO_CLEAR_LOGS_AND_ACTIVE_PROFILE_CACHES_PENDING_RUNNING_JOBS_RULES_SET": "Одно место для очистки логов и кэшей активного профиля. Ожидающие/выполняющиеся задания, правила, настройки и торренты сохраняются.", + "ONE_TRACKER_URL_PER_LINE": "Один URL трекера на строку", + "ONLINE": "онлайн", + "ONLY_SELECTED": "Только выбранные", + "OPEN_DOWNLOAD_PLANNER": "Открыть планировщик загрузок", + "OPEN_RTORRENT_FILES_MAX_OPEN_FILES": "Открытые файлы rTorrent / макс. открытых файлов", + "OPEN_RTORRENT_HTTP_CONNECTIONS_MAX_HTTP_CONNECTIONS": "Открытые HTTP-соединения rTorrent / макс. HTTP-соединений", + "OPEN_RTORRENT_SOCKETS": "Открытые сокеты rTorrent", + "OPEN_SOURCE": "Open source", + "OPEN_THIS_TAB_TO_LOAD_DIAGNOSTICS": "Откройте эту вкладку, чтобы загрузить диагностику.", + "OPEN_THIS_TAB_TO_LOAD_STATISTICS": "Откройте эту вкладку, чтобы загрузить статистику.", + "OPERATION_LOG_RETENTION": "Хранение логов операций", + "OPTIONAL": "необязательно", + "OPTIONAL_PEER_TABLE_HELPERS": "Дополнительные помощники таблицы пиров.", + "OPTIONAL_PRIVATE_SOURCE_TAG": "необязательный приватный тег источника", + "OPTIONAL_VISUAL_EASTER_EGG_FOR_LOADING_STATES_AND_OCCASIONAL_BUTTON_CLICKS_DISAB": "Дополнительный визуальный easter egg для состояний загрузки и редких нажатий кнопок. По умолчанию отключён.", + "PARALLEL_JOBS": "Параллельные задания", + "PARENT_DIRECTORY": "Родительский каталог", + "PARTIAL_DETAILS_LOADED": "Загружены частичные детали", + "PASSWORD": "Пароль", + "PASSWORD_NEW_PASSWORD": "Пароль / новый пароль", + "PASTE_ONE_MAGNET_URI_PER_LINE": "Вставьте по одному magnet URI на строку.", + "PATH": "Путь", + "PATH_CONTAINS": "Путь содержит", + "PATH_TEXT": "Текст пути", + "PATH_USED_FOR_SELECTED_MODE": "Путь, используемый для выбранного режима", + "PAUSE": "Пауза", + "PAUSED": "На паузе", + "PEAK_S": "Пик S", + "PEAK_SPEED_UNAVAILABLE": "Пиковая скорость недоступна", + "PEERS": "Пиры", + "PEERS_AUTO_REFRESH": "Автообновление пиров", + "PENDING_JOBS_OLDER_THAN_THIS_ARE_RESUBMITTED_IF_NO_WORKER_IS_CURRENTLY_HANDLING_": "Ожидающие задания старше этого времени отправляются повторно, если ни один worker их сейчас не обрабатывает. По умолчанию: 900 секунд.", + "PENDING_RUNNING_DONE_FAILED_RETRY_AND_CANCEL_HISTORY": "История ожидающих, выполняющихся, выполненных, неудачных, повторных и отменённых заданий.", + "PENDING_TIMEOUT_SECONDS": "Таймаут ожидания, секунды", + "PIECE_SIZE": "Размер части", + "PLANNER": "Планировщик", + "POLISH": "Польский", + "PORT": "Порт", + "PORT_CHECKER": "Проверка порта", + "PORT_CHECK_DISABLED": "Проверка порта отключена", + "PORT_UNKNOWN": "Порт - неизвестен", + "POST_CHECK": "Проверка после", + "PREFERENCES": "Предпочтения", + "PREFERENCES_SAVED": "Предпочтения сохранены", + "PRIORITY": "Приоритет", + "PRIVATE_TORRENT": "Приватный торрент", + "PROFILE_BACKUP": "Резервная копия профиля", + "PROFILE_BACKUP_NAME": "Имя резервной копии профиля", + "PROFILE_BACKUP_RESTORES_ONLY_THE_ACTIVE_PROFILE_CONTEXT_APPLICATION_BACKUP_RESTO": "Резервная копия профиля восстанавливает только контекст активного профиля. Резервная копия приложения восстанавливает глобальные данные приложения и доступна только администраторам.", + "PROFILE_NAME": "Имя профиля", + "PROFILE_SCOPED_LOG_COUNTS_AND_CLEANUP_OVERVIEW": "Количество логов и обзор очистки в рамках профиля.", + "PROGRESS": "Прогресс", + "PROGRESS_IS_AT_LEAST": "Прогресс не менее %", + "PROGRESS_IS_AT_MOST": "Прогресс не более %", + "PROGRESS_SOURCE": "Источник прогресса", + "PROTECT_ACTIVE_COUNT_BELOW_CAP": "Защитить активное число ниже лимита", + "PYTORRENT_EXPECTS_TRUSTED_REVERSE_PROXY_IDENTITY_HEADERS_IF_YOU_ARE_ALREADY_SIGN": "pyTorrent ожидает доверенные заголовки идентификации от reverse proxy. Если вы уже вошли, проверьте заголовки провайдера и сопоставление пользователя.", + "PYTORRENT_LOGIN": "Вход в pyTorrent", + "PYTORRENT_STATUS": "Статус pyTorrent", + "P_PAUSE": "P - пауза", + "QUALITY": "Качество", + "QUEUE_REFILL_DURING_COOLDOWN": "Пополнение очереди во время паузы", + "RANDOM_CLICK_IMAGE_URL": "URL изображения случайного клика", + "RATIO": "Ratio", + "RATIO_GROUP": "Группа ratio", + "RATIO_GROUPS": "Группы ratio", + "RATIO_IS_AT_LEAST": "Ratio не менее", + "RATIO_RULES": "Правила ratio", + "REANNOUNCE": "Повторный announce", + "RECHECK": "Перепроверить", + "RECHECK_AFTER_MOVE": "Перепроверить после перемещения", + "RECOMMENDED_COLUMNS": "Рекомендуемые столбцы", + "RECOMMENDED_COLUMNS_APPLIED": "Рекомендуемые столбцы применены", + "RECONNECTING": "переподключение", + "REFERENCE_VALUE_IS_KEPT_FROM_THE_FIRST_OVERRIDE_SAVE_LATER_SAVES_ADD_OR_CLEAR_DI": "Эталонное значение сохраняется из первого сохранения переопределения. Последующие сохранения добавляют или очищают различия без замены исходного эталона.", + "REFRESH": "Обновить", + "REFRESH_NOW": "Обновить сейчас", + "REGEX_TEXT": "Regex / текст", + "RELOAD": "Перезагрузить", + "REMOTE_LOCATION": "Удалённое расположение", + "REMOVE": "Удалить", + "REMOVE_DATA": "удалить данные", + "REMOVE_LABEL": "Удалить метку", + "REMOVE_SELECTED_TORRENTS": "Удалить выбранные торренты", + "REMOVE_WITH_DATA": "Удалить с данными", + "REPOSITORY": "Репозиторий", + "RESET": "Сбросить", + "RESET_UI_SETTINGS": "Сбросить настройки UI", + "RESET_VIEW_DEFAULTS": "Сбросить настройки видов", + "RESIZE_TORRENT_DETAILS_PANEL": "Изменить размер панели деталей торрента", + "RESOLVE_PEER_IP_TO_REVERSE_DNS_HOST": "Разрешать IP пира в host reverse DNS", + "RESUME": "Возобновить", + "RETENTION_DAYS": "Дни хранения", + "RETENTION_MODE": "Режим хранения", + "RETRY": "Повторить", + "REVERSE_DNS": "Reverse DNS", + "RSS_DOWNLOADER": "RSS-загрузчик", + "RTORRENT": "rTorrent", + "RTORRENTS": "rTorrent", + "RTORRENT_CONFIG": "Конфигурация rTorrent", + "RTORRENT_INCOMING_PORT": "Входящий порт rTorrent", + "RTORRENT_IS_STARTING_OR_NOT_RESPONDING_YET": "rTorrent запускается или пока не отвечает.", + "RTORRENT_PROFILES": "Профили rTorrent", + "RULE": "Правило", + "RULES": "Правила", + "RULES_ARE_CHECKED_AUTOMATICALLY_EVERY_5_MINUTES_A_TORRENT_USES_THE_GROUP_STORED_": "Правила автоматически проверяются каждые 5 минут. Торрент использует группу, сохранённую в пользовательском поле ratio rTorrent.", + "RULE_NAME": "Имя правила", + "RUNTIME": "Runtime", + "RUN_A_PROFILE_TEST_TO_SHOW_DIAGNOSTICS": "Запустите тест профиля, чтобы показать диагностику.", + "RUN_SMART_QUEUE_DURING_POLLING_STOPPED_TORRENTS_ARE_MANAGED_PAUSED_TORRENTS_STAY": "Запускать Smart Queue во время polling. Остановленные торренты управляются системой; торренты на паузе остаются под контролем пользователя.", + "R_RESUME": "R - возобновить", + "SAVE": "Сохранить", + "SAVED_LABELS": "Сохранённые метки", + "SAVE_COLUMNS": "Сохранить столбцы", + "SAVE_CONFIG": "Сохранить конфигурацию", + "SAVE_EASTER_EGG": "Сохранить easter egg", + "SAVE_EXCEPTIONS": "Сохранить исключения", + "SAVE_FEED": "Сохранить ленту", + "SAVE_FOOTER": "Сохранить нижнюю панель", + "SAVE_GROUP": "Сохранить группу", + "SAVE_JOB_SETTINGS": "Сохранить настройки заданий", + "SAVE_LIMITS": "Сохранить лимиты", + "SAVE_LOCATION": "Сохранить расположение", + "SAVE_LOG_VIEW": "Сохранить вид логов", + "SAVE_PATH": "Сохранить путь", + "SAVE_PREFERENCES": "Сохранить предпочтения", + "SAVE_RETENTION": "Сохранить хранение", + "SAVE_RULE": "Сохранить правило", + "SAVE_SCHEDULE": "Сохранить расписание", + "SAVE_USER": "Сохранить пользователя", + "SCGI_URL": "SCGI URL", + "SEARCH_LOGS": "Искать в логах...", + "SEARCH_TORRENTS": "Искать торренты...", + "SEARCH_TORRENTS_TO_EXCLUDE": "Искать торренты для исключения...", + "SEASON": "Сезон", + "SECONDS_TO_WAIT_FOR_RTORRENT_RESPONSE": "Сколько секунд ждать ответа rTorrent.", + "SEEDING": "Раздача", + "SEEDS": "Сиды", + "SEEDS_ARE_LOW_FOR_TIME": "Мало сидов в течение времени", + "SEED_MINUTES": "Минуты раздачи", + "SELECT": "Выбрать", + "SELECTED": "выбрано", + "SELECTED_LABELS": "Выбранные метки", + "SELECTED_MONITORED_PATH": "Выбранный отслеживаемый путь", + "SELECTED_TORRENTS_WILL_BE_REMOVED": "выбранные торренты будут удалены.", + "SELECT_A_MONITORED_PATH_FIRST": "Сначала выберите отслеживаемый путь.", + "SELECT_A_TORRENT": "Выберите торрент.", + "SELECT_ONE_OR_MORE_TORRENT_FILES": "Выберите один или несколько .torrent файлов.", + "SELECT_PATH": "Выбрать путь", + "SELECT_TORRENTS_THAT_SMART_QUEUE_SHOULD_IGNORE_USE_SEARCH_TO_FILTER_BY_NAME_LABE": "Выберите торренты, которые Smart Queue должна игнорировать. Используйте поиск для фильтрации по имени, метке, статусу или hash.", + "SELECT_VISIBLE": "Выбрать видимые", + "SEPARATE_SLOT_POOL_FOR_LIGHTWEIGHT_CONTROL_JOBS_SO_THEY_DO_NOT_WAIT_BEHIND_HEAVY": "Отдельный пул слотов для лёгких управляющих заданий, чтобы они не ждали за тяжёлой I/O работой. По умолчанию: 4.", + "SETTINGS": "Настройки", + "SET_LABEL": "Установить метку...", + "SET_LABELS": "Установить метки", + "SET_RATIO_GROUP": "Установить группу ratio...", + "SHARE_AFTER_CREATING": "Раздавать после создания", + "SHORTCUTS": "Горячие клавиши", + "SHOWN": "Показано", + "SHOWN_IN_LOADING_STATES_INSTEAD_OF_THE_STANDARD_SPINNER": "Показывается в состояниях загрузки вместо стандартного spinner.", + "SHOWS_TRACKER_ICONS_IN_THE_SIDEBAR_TRACKER_FILTER_WHEN_AVAILABLE": "Показывает иконки трекеров в фильтре трекеров на боковой панели, когда они доступны.", + "SHOW_COMBINED_USAGE_SINGLE_PATH_SELECTION_IS_DISABLED_IN_THIS_MODE": "Показывать суммарное использование. В этом режиме выбор одного пути отключён.", + "SHOW_DL_UP_IN_BROWSER_TITLE": "Показывать DL/UP в заголовке браузера", + "SHOW_SMART_QUEUE_AUTOMATIC_RUN_MESSAGES": "Показывать сообщения автоматических запусков Smart Queue.", + "SHOW_TOASTS_CREATED_BY_AUTOMATION_RUNS": "Показывать уведомления, созданные автоматизациями.", + "SIGN_IN": "Войти", + "SIZE": "Размер", + "SKIP_ACTIVE_UPLOAD": "Пропускать активную отдачу", + "SKIP_PRIVATE_TORRENTS": "Пропускать приватные торренты", + "SMART_FILTERS": "Умные фильтры", + "SMART_QUEUE": "Smart Queue", + "SMART_QUEUE_EXCEPTIONS": "Исключения Smart Queue", + "SMART_QUEUE_KEEPS_ONLY_THIS_MANY_ACTIVE_DOWNLOADS_OVERFLOW_IS_STOPPED": "Smart Queue оставляет только столько активных загрузок; лишние останавливаются.", + "SMART_QUEUE_TOASTS": "Уведомления Smart Queue", + "SOCKETS": "Сокеты", + "SOURCE": "Источник", + "SPACE_START": "Space - старт", + "SPEED": "Скорость", + "SPEED_LIMITS": "Лимиты скорости", + "SPEED_TREND": "Тренд скорости", + "STALLED_AFTER_SECONDS": "Завис после секунд", + "START": "Старт", + "START_AFTER_ADD": "Запускать после добавления", + "START_GRACE_SECONDS": "Защитные секунды после старта", + "STATE": "Состояние", + "STATUS": "Статус", + "STATUS_EQUALS": "Статус равен", + "STOP": "Стоп", + "STOPPED": "Остановлено", + "S_STOP": "S - остановить", + "TARGET_ACTIVE_DOWNLOADS": "Целевые активные загрузки", + "TARGET_PATH": "Целевой путь", + "TEST_RULE": "Тестировать правило", + "TEST_SCGI": "Тестировать SCGI", + "THEME_TYPOGRAPHY_AND_INTERFACE_SCALE": "Тема, типографика и масштаб интерфейса.", + "THE_FOOTER_TOOLTIP_ALWAYS_SHOWS_DETAILS_FOR_AVAILABLE_PATHS_THIS_SETTING_ONLY_DE": "Подсказка нижней панели всегда показывает детали доступных путей; эта настройка определяет только значение, управляющее видимой полосой прогресса.", + "TIMEOUT": "Таймаут", + "TOAST_NOTIFICATIONS_FROM_AUTOMATIC_SYSTEMS": "Toast-уведомления от автоматических систем.", + "TOOLS": "Инструменты", + "TOOLS_RTORRENTS": "Инструменты и rTorrent", + "TOOLS_SECTIONS": "Разделы инструментов", + "TORRENT_ADDED": "Торрент добавлен", + "TORRENT_COMPLETED": "Торрент завершён", + "TORRENT_DETAILS": "Детали торрента", + "TORRENT_FILES": "Файлы торрента", + "TORRENT_FILTERS": "Фильтры торрентов", + "TORRENT_PROPERTIES": "Свойства торрента", + "TORRENT_REMOVED": "Торрент удалён", + "TORRENT_STATISTICS": "Статистика торрента", + "TORRENT_STATS": "Статистика торрентов", + "TOTAL_DL_UP": "Всего DL/UP", + "TO_DOWNLOAD": "К загрузке", + "TRACKERS": "Трекеры", + "TRACKER_ICONS": "Иконки трекеров", + "TRANSFER": "Передача", + "TRANSFERRED_DATA": "Переданные данные", + "TRANSFER_HISTORY": "История передачи", + "UNDEFINED": "не определено", + "UNLIMITED": "Без ограничений", + "UPLOADED": "Отдано", + "UPLOADS": "Отдачи", + "UPLOAD_KIB_S": "Отдача KiB/s", + "USER": "Пользователь", + "USERS": "Пользователи", + "USES_A_LIGHTWEIGHT_BUILT_IN_RESOLVER_WITH_CACHE_HOSTNAMES_APPEAR_ONLY_IN_THE_PEE": "Использует лёгкий встроенный resolver с кэшем. Имена host появляются только на вкладке пиров.", + "USES_LOWER_ROWS_AND_SMALLER_LIST_ELEMENTS_ON_DESKTOP_AND_MOBILE_SO_MORE_TORRENTS": "Использует более низкие строки и меньшие элементы списка на desktop и mobile, чтобы на экране помещалось больше торрентов.", + "USES_YOUGETSIGNAL_FIRST_MANUAL_CHECK_BYPASSES_THE_6H_CACHE": "Сначала использует YouGetSignal. Ручная проверка обходит кэш 6h.", + "USE_ONE_CUSTOM_PATH_BELOW_AS_THE_FOOTER_PROGRESS_VALUE": "Использовать один пользовательский путь ниже как значение прогресса в нижней панели.", + "USE_SELECTED": "Использовать выбранное", + "USE_THE_MAIN_DIRECTORY_FROM_THE_ACTIVE_RTORRENT_PROFILE": "Использовать основной каталог активного профиля rTorrent.", + "VIEW_PREFERENCES_RESET": "Настройки вида сброшены", + "VIEW_STATE_IS_SAVED_AUTOMATICALLY_IN_THE_DATABASE_CURRENT_TORRENT_FILTER_LAST_SO": "Состояние вида автоматически сохраняется в базе данных: текущий фильтр торрентов, последний столбец сортировки и направление, видимые столбцы и высота панели деталей.", + "VISIBLE_NAME_USED_IN_THE_PROFILE_SELECTOR": "Видимое имя, используемое в селекторе профиля.", + "VISUAL_HELPER_FOR_TRACKER_FILTERS_IN_THE_SIDEBAR": "Визуальная помощь для фильтров трекеров на боковой панели.", + "WAITING_FOR_DATA": "Ожидание данных.", + "WAITING_FOR_TORRENT_DATA_FROM_THE_ACTIVE_PROFILE": "Ожидание данных торрентов из активного профиля.", + "WATCHDOG_MARKS_A_LIGHT_JOB_AS_FAILED_AFTER_THIS_TIME_DEFAULT_300_SECONDS": "Watchdog помечает лёгкое задание как неудачное после этого времени. По умолчанию: 300 секунд.", + "WATCHDOG_TIMEOUT_FOR_MOVE_REMOVE_ADD_JOBS_DEFAULT_7200_SECONDS": "Таймаут watchdog для заданий move/remove/add. По умолчанию: 7200 секунд.", + "WHEN_DISABLED_THE_APPLICATION_USES_THE_NORMAL_PRODUCTION_UI": "Когда отключено, приложение использует обычный production UI.", + "WHEN_ENABLED_LOW_SPEED_IS_NOT_REQUIRED_WITH_SOURCE_AND_SPEED_IGNORES_ENABLED_ONL": "Когда включено, низкая скорость не требуется. При включённом игнорировании источника и скорости решает только „Завис после секунд”.", + "WHEN_ENABLED_SMART_QUEUE_DOES_NOT_USE_SEED_PEER_COUNT_AS_A_STALLED_CRITERION": "Когда включено, Smart Queue не использует число сидов/пиров как критерий зависания.", + "WITH_ERROR": "С ошибкой", + "WORKING": "Работаю...", + "FRENCH": "Французский", + "CZECH": "Чешский", + "SPANISH": "Испанский", + "NORWEGIAN": "Норвежский", + "RUSSIAN": "Русский" + } +} diff --git a/pytorrent/static/js/app.js b/pytorrent/static/js/app.js index 9a29ad7..cef45e7 100644 --- a/pytorrent/static/js/app.js +++ b/pytorrent/static/js/app.js @@ -1,4 +1,5 @@ import { stateSource } from './state.js'; +import { i18nSource } from './i18n.js'; import { torrentsSource } from './torrents.js'; import { mobileSource } from './mobile.js'; import { messagesSource } from './messages.js'; @@ -20,6 +21,7 @@ import { bootstrapSource } from './bootstrap.js'; export const moduleSources = [ stateSource, + i18nSource, torrentsSource, mobileSource, messagesSource, diff --git a/pytorrent/static/js/i18n.js b/pytorrent/static/js/i18n.js new file mode 100644 index 0000000..d801369 --- /dev/null +++ b/pytorrent/static/js/i18n.js @@ -0,0 +1 @@ +export const i18nSource = "\n const I18N_DEFAULT_LANGUAGE = 'en_US';\n const I18N_ATTRIBUTE_NAMES = ['title', 'placeholder', 'aria-label', 'alt'];\n let currentLanguage = String(window.PYTORRENT?.language || I18N_DEFAULT_LANGUAGE);\n let currentTranslations = {};\n let i18nObserver = null;\n let i18nApplying = false;\n\n function i18nKey(text) {\n return String(text ?? '')\n .replace(/<[^>]+>/g, ' ')\n .replace(/[%/\\\\.]+/g, ' ')\n .replace(/[^A-Za-z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .toUpperCase();\n }\n\n function isTechnicalI18nText(text) {\n const value = String(text ?? '').trim();\n if (!value) return true;\n if (/^[A-Z]{1,4}$/.test(value)) return true;\n if (/^[a-z][a-z0-9+.-]*:\\/\\/\\S+$/i.test(value)) return true;\n if (/^\\/[\\w./:-]+$/.test(value)) return true;\n if (/^\\d+(?:\\.\\d+)?\\s*(?:B|KiB|MiB|GiB|TiB|B\\/s|KiB\\/s|MiB\\/s|GiB\\/s|Mbit\\/s|Gbit\\/s)$/i.test(value)) return true;\n if (/^\\d+\\s*B\\/s\\s*\\/\\s*\\d+\\s*B\\/s$/i.test(value)) return true;\n if (/^\\d+(?:s|m|h|d)$/i.test(value)) return true;\n return false;\n }\n\n function interpolateI18n(text, params = {}) {\n return String(text).replace(/\\{([A-Za-z0-9_]+)\\}/g, (_, key) => params[key] ?? '');\n }\n\n function t(key, params = {}) {\n const rawKey = String(key || '');\n if (isTechnicalI18nText(rawKey)) return interpolateI18n(rawKey, params);\n const normalized = rawKey.includes('.') ? rawKey.split('.').pop() : rawKey;\n const upper = i18nKey(normalized) || rawKey;\n const value = currentTranslations[rawKey] ?? currentTranslations[upper] ?? currentTranslations[i18nKey(rawKey)] ?? rawKey;\n return interpolateI18n(value, params);\n }\n\n function translatePlainText(text) {\n const raw = String(text ?? '');\n const trimmed = raw.trim();\n if (!trimmed || !/[A-Za-z]/.test(trimmed) || isTechnicalI18nText(trimmed)) return raw;\n const translated = currentTranslations[i18nKey(trimmed)];\n if (!translated || translated === trimmed) return raw;\n return raw.replace(trimmed, translated);\n }\n\n function shouldSkipI18nNode(node) {\n const parent = node.parentElement;\n if (!parent) return true;\n return !!parent.closest('script, style, code, pre, textarea, input, select, option, .fi, [data-i18n-skip]');\n }\n\n function applyI18n(root = document.body) {\n if (!root || i18nApplying || currentLanguage === I18N_DEFAULT_LANGUAGE) return;\n i18nApplying = true;\n try {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n acceptNode(node) {\n if (shouldSkipI18nNode(node)) return NodeFilter.FILTER_REJECT;\n return /[A-Za-z]/.test(node.nodeValue || '') ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;\n }\n });\n const textNodes = [];\n while (walker.nextNode()) textNodes.push(walker.currentNode);\n textNodes.forEach(node => {\n const next = translatePlainText(node.nodeValue);\n if (next !== node.nodeValue) node.nodeValue = next;\n });\n root.querySelectorAll?.('[title], [placeholder], [aria-label], [alt]').forEach(el => {\n if (el.closest('script, style, code, pre, [data-i18n-skip]')) return;\n I18N_ATTRIBUTE_NAMES.forEach(attr => {\n if (!el.hasAttribute(attr)) return;\n const value = el.getAttribute(attr);\n const next = translatePlainText(value);\n if (next !== value) el.setAttribute(attr, next);\n });\n });\n } finally {\n i18nApplying = false;\n }\n }\n\n async function loadLanguage(language) {\n const safeLanguage = window.PYTORRENT?.supportedLanguages?.[language] ? language : I18N_DEFAULT_LANGUAGE;\n const response = await fetch(`/static/i18n/${encodeURIComponent(safeLanguage)}.json`, { cache: 'no-store' });\n const data = await response.json();\n currentLanguage = safeLanguage;\n currentTranslations = data.translations || {};\n document.documentElement.lang = safeLanguage.replace('_', '-');\n window.PYTORRENT.language = safeLanguage;\n return safeLanguage;\n }\n\n function scheduleI18n(root = document.body) {\n clearTimeout(window.__pyTorrentI18nTimer);\n window.__pyTorrentI18nTimer = setTimeout(() => applyI18n(root), 0);\n }\n\n function startI18nObserver() {\n if (i18nObserver || currentLanguage === I18N_DEFAULT_LANGUAGE) return;\n i18nObserver = new MutationObserver(mutations => {\n if (i18nApplying) return;\n for (const mutation of mutations) {\n if (mutation.type === 'childList' || mutation.type === 'attributes') {\n scheduleI18n(document.body);\n return;\n }\n }\n });\n i18nObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: I18N_ATTRIBUTE_NAMES });\n }\n\n async function setLanguage(language) {\n await loadLanguage(language);\n if (i18nObserver) { i18nObserver.disconnect(); i18nObserver = null; }\n if (currentLanguage !== I18N_DEFAULT_LANGUAGE) {\n applyI18n(document.body);\n startI18nObserver();\n } else {\n window.location.reload();\n }\n }\n\n function updateLanguageFlagHint() {\n const select = $('languageSelect');\n const hint = $('languageFlagHint');\n if (!select || !hint) return;\n const info = window.PYTORRENT?.supportedLanguages?.[select.value] || window.PYTORRENT?.supportedLanguages?.[I18N_DEFAULT_LANGUAGE] || {flag:'us'};\n const flag = String(info.flag || 'us').toLowerCase();\n hint.innerHTML = ` /static/libs/flag-icons/7.2.3/flags/4x3/${esc(flag)}.svg`;\n }\n\n loadLanguage(currentLanguage).then(() => {\n updateLanguageFlagHint();\n if (currentLanguage !== I18N_DEFAULT_LANGUAGE) {\n applyI18n(document.body);\n startI18nObserver();\n }\n }).catch(() => {\n currentLanguage = I18N_DEFAULT_LANGUAGE;\n currentTranslations = {};\n });\n"; diff --git a/pytorrent/static/js/smartQueue.js b/pytorrent/static/js/smartQueue.js index a18e1b8..20a3263 100644 --- a/pytorrent/static/js/smartQueue.js +++ b/pytorrent/static/js/smartQueue.js @@ -1 +1 @@ -export const smartQueueSource = " function smartHistoryDetails(row){ try{ return typeof row.details_json==='string'?JSON.parse(row.details_json||'{}'):(row.details_json||{}); }catch(e){ return {}; } }\n function smartQueueToastMessage(r){ const pending=r.start_pending_confirmation?.length||0; const requested=r.start_requested?.length||0; const stopFailed=r.stop_failed?.length||0; const startFailed=r.start_failed?.length||0; const limit=r.max_active_downloads||r.settings?.max_active_downloads||''; const activeBefore=r.active_before; const activeAfter=r.active_after_stop ?? r.active_after_expected; const activeTail=activeBefore!==undefined?`, active ${esc(activeBefore)}->${esc(activeAfter ?? '?')}${limit?`/${esc(limit)}`:''}`:''; const cap=r.rtorrent_cap?.updated?`, cap ${r.rtorrent_cap.current}->${r.rtorrent_cap.new}`:''; const waiting=r.waiting_labeled||0; const stalled=r.stalled_labeled?.length||0; const ignoredSpeed=(r.ignore_speed||r.settings?.ignore_speed)?Number(r.ignored_speed_count||0):0; const tail=pending?`, pending confirm ${pending}`:requested?`, requested ${requested}`:''; const waitTail=waiting?`, waiting labeled ${waiting}`:''; const stalledTail=stalled?`, stalled ${stalled}`:''; const ignoredSpeedTail=(r.ignore_speed||r.settings?.ignore_speed)?`, ignored speed ${ignoredSpeed}`:''; const failTail=`${stopFailed?`, stop failed ${stopFailed}`:''}${startFailed?`, start failed ${startFailed}`:''}`; return `Smart Queue: stopped ${r.stopped?.length||r.paused?.length||0}, started ${r.started?.length||r.resumed?.length||0}${activeTail}${tail}${waitTail}${stalledTail}${ignoredSpeedTail}${failTail}${cap}`; }\n function buildSmartQueueNerdStats(hist=[], totalHistory=0){\n // Note: Small Smart Queue telemetry for automation nerds; it reads history only and does not affect queue behavior.\n const stats=hist.reduce((acc,h)=>{\n const details=smartHistoryDetails(h);\n const stopped=Number(h.paused_count||0);\n const started=Number(h.resumed_count||0);\n const checked=Number(h.checked_count||0);\n const over=Number(details.over_limit||0);\n const stopFailed=Array.isArray(details.stop_failed)?details.stop_failed.length:0;\n acc.checked += checked;\n acc.stopped += stopped;\n acc.started += started;\n acc.overLimit += over;\n acc.stopFailed += stopFailed;\n if(over>0) acc.overEvents += 1;\n return acc;\n },{checked:0,stopped:0,started:0,overLimit:0,overEvents:0,stopFailed:0});\n const latest=hist[0]||null;\n return {...stats,total:Number(totalHistory||hist.length||0),sample:hist.length,latestEvent:smartHistoryDetails(latest||{}).decision||latest?.event||'-',latestAt:latest?.created_at||''};\n }\n\n function renderSmartQueueNerdStats(stats){\n // Note: Compact cards keep the extra diagnostics readable above Automation history without changing the history table.\n if(!stats) return '
No Smart Queue stats yet.
';\n const cards=[\n ['Runs',stats.total,`${stats.sample} loaded`],\n ['Checked',stats.checked,'torrent scans'],\n ['Stopped',stats.stopped,'queue trims'],\n ['Started',stats.started,'queue fills'],\n ['Over limit',stats.overEvents,`${stats.overLimit} total over`],\n ['Stop failed',stats.stopFailed,'rTorrent rejects'],\n ['Latest',stats.latestEvent,stats.latestAt?dateCell(stats.latestAt):'no timestamp'],\n ];\n return `
${cards.map(([label,value,hint])=>`
${esc(label)}${esc(value)}${hint}
`).join('')}
`;\n }\n function formatDurationLeft(seconds){ seconds=Math.max(0,Math.floor(Number(seconds||0))); if(!seconds) return \"ready\"; const m=Math.floor(seconds/60), s=seconds%60; return m?`${m}m ${String(s).padStart(2,\"0\")}s`:`${s}s`; }\n function updateCooldownBadge(id, seconds){\n const el=$(id); if(!el) return;\n const value=Math.max(0,Math.floor(Number(seconds||0)));\n el.dataset.seconds=String(value);\n el.textContent=`next: ${formatDurationLeft(value)}`;\n }\n function tickCooldowns(){\n document.querySelectorAll(\".cooldown-live\").forEach(el=>{\n let v=Math.max(0,Number(el.dataset.seconds||0));\n if(v>0){ v-=1; el.dataset.seconds=String(v); }\n el.textContent=`next: ${formatDurationLeft(v)}`;\n });\n }\n setInterval(tickCooldowns,1000);\n\n function smartQueueTorrentLabel(t){\n const bits=[t.name || t.hash, t.label ? `label: ${t.label}` : '', t.status || '', t.size_h || ''].filter(Boolean);\n return bits.join(' · ');\n }\n function smartQueueExcludedSet(){\n return new Set([...document.querySelectorAll('.smart-exclusion-choice:checked')].map(input=>input.value).filter(Boolean));\n }\n function updateSmartQueueExclusionCounter(){\n // Note: The counter is UI-only and does not change how exceptions are saved.\n const counter=$('smartExclusionCounter');\n if(!counter) return;\n const selected=smartQueueExcludedSet().size;\n const visible=[...document.querySelectorAll('.smart-exclusion-choice-row')].filter(row=>!row.classList.contains('d-none')).length;\n counter.textContent=`${selected} selected · ${visible} visible`;\n }\n function smartQueueVisibleExceptionRows(){\n return [...document.querySelectorAll('.smart-exclusion-choice-row')].filter(row=>!row.classList.contains('d-none'));\n }\n function setSmartQueueVisibleExceptions(checked){\n // Note: Bulk actions affect only visible filtered rows, preserving hidden selections.\n smartQueueVisibleExceptionRows().forEach(row=>{\n const input=row.querySelector('.smart-exclusion-choice');\n if(input) input.checked=checked;\n });\n updateSmartQueueExclusionCounter();\n }\n function renderSmartQueueExclusionChoices(exclusions=[]){\n const list=$('smartExclusionChoiceList');\n if(!list) return;\n const excluded=new Set((exclusions||[]).map(x=>String(x.torrent_hash||'')));\n selectedHashes().forEach(hash=>excluded.add(String(hash)));\n const rows=[...torrents.values()].sort((a,b)=>String(a.name||'').localeCompare(String(b.name||'')));\n const fallback=(exclusions||[])\n .filter(x=>x.torrent_hash && !torrents.has(x.torrent_hash))\n .map(x=>({hash:x.torrent_hash,name:`Missing from current list: ${x.torrent_hash}`,label:x.reason||'manual exception'}));\n const all=[...rows, ...fallback];\n list.innerHTML=all.length ? all.map(t=>{\n const hash=String(t.hash||'');\n const checked=excluded.has(hash) ? 'checked' : '';\n return ``;\n }).join('') : '
No torrents are loaded for this profile.
';\n list.querySelectorAll('.smart-exclusion-choice').forEach(input=>input.addEventListener('change', updateSmartQueueExclusionCounter));\n filterSmartQueueExclusionChoices();\n }\n function filterSmartQueueExclusionChoices(){\n const query=($('smartExclusionSearch')?.value||'').trim().toLowerCase();\n const onlySelected=!!$('smartExclusionOnlySelected')?.checked;\n document.querySelectorAll('.smart-exclusion-choice-row').forEach(row=>{\n const matchesQuery=!query || row.textContent.toLowerCase().includes(query);\n const matchesSelected=!onlySelected || !!row.querySelector('.smart-exclusion-choice')?.checked;\n row.classList.toggle('d-none', !(matchesQuery && matchesSelected));\n });\n updateSmartQueueExclusionCounter();\n }\n async function openSmartQueueExclusionModal(){\n await loadSmartQueue();\n const modalEl=$('smartExclusionModal');\n if(!modalEl) return;\n const current=await fetch('/api/smart-queue?history_limit=1').then(r=>r.json()).catch(()=>({exclusions:[]}));\n if($('smartExclusionOnlySelected')) $('smartExclusionOnlySelected').checked=false;\n renderSmartQueueExclusionChoices(current.exclusions||[]);\n $('smartExclusionSearch')?.focus();\n bootstrap.Modal.getOrCreateInstance(modalEl).show();\n }\n async function saveSmartQueueExclusionChoices(){\n const current=await fetch('/api/smart-queue?history_limit=1').then(r=>r.json()).catch(()=>({exclusions:[]}));\n const before=new Set((current.exclusions||[]).map(x=>String(x.torrent_hash||'')));\n const after=smartQueueExcludedSet();\n const add=[...after].filter(hash=>!before.has(hash));\n const remove=[...before].filter(hash=>!after.has(hash));\n if(!add.length && !remove.length){\n bootstrap.Modal.getInstance($('smartExclusionModal'))?.hide();\n return toast('Smart Queue exceptions unchanged','secondary');\n }\n setBusy(true);\n try{\n for(const hash of add) await post('/api/smart-queue/exclusion',{hash,excluded:true,reason:'manual'});\n for(const hash of remove) await post('/api/smart-queue/exclusion',{hash,excluded:false,reason:'manual'});\n bootstrap.Modal.getInstance($('smartExclusionModal'))?.hide();\n toast('Smart Queue exceptions saved','success');\n await loadSmartQueue();\n }catch(e){\n toast(e.message,'danger');\n }finally{\n setBusy(false);\n }\n }\n async function loadSmartQueue(){\n if($('smartManager')) $('smartManager').innerHTML=loadingMarkup('Loading Smart Queue...');\n if($('smartHistory')) $('smartHistory').innerHTML=loadingMarkup('Loading Smart Queue history...');\n const historyLimit=smartHistoryExpanded?100:10;\n const j=await (await fetch(`/api/smart-queue?history_limit=${historyLimit}`)).json();\n if(!j.ok) return;\n const st=j.settings||{}, ex=j.exclusions||[], hist=j.history||[];\n const totalHistory=Number(j.history_total ?? hist.length);\n if($('smartEnabled')) $('smartEnabled').checked=!!st.enabled;\n if($('smartMaxActive')) $('smartMaxActive').value=st.max_active_downloads||5;\n if($('smartStalled')) $('smartStalled').value=st.stalled_seconds||300;\n if($('smartStopBatch')) $('smartStopBatch').value=st.stop_batch_size||50;\n if($('smartStartGrace')) $('smartStartGrace').value=st.start_grace_seconds||900;\n if($('smartProtectActiveBelowCap')) $('smartProtectActiveBelowCap').checked=st.protect_active_below_cap!==0;\n if($('smartAutoStopIdle')) $('smartAutoStopIdle').checked=!!st.auto_stop_idle;\n if($('smartMinSpeed')) $('smartMinSpeed').value=Math.round((st.min_speed_bytes||0)/1024);\n if($('smartMinSeeds')) $('smartMinSeeds').value=st.min_seeds||1;\n if($('smartMinPeers')) $('smartMinPeers').value=st.min_peers||0;\n if($('smartIgnoreSeedPeer')) $('smartIgnoreSeedPeer').checked=!!st.ignore_seed_peer;\n if($('smartIgnoreSpeed')) $('smartIgnoreSpeed').checked=!!st.ignore_speed;\n if($('smartCooldown')) $('smartCooldown').value=st.cooldown_minutes||10;\n const refillMode=!Number(st.refill_enabled ?? 1) ? 'off' : (Number(st.refill_interval_minutes||0)>0 ? 'custom' : 'auto');\n if($('smartRefillMode')) $('smartRefillMode').value=refillMode;\n if($('smartRefillInterval')) $('smartRefillInterval').value=Number(st.refill_interval_minutes||0)>0 ? st.refill_interval_minutes : 5;\n updateSmartRefillControls();\n updateCooldownBadge('smartCooldownBadge', Number(j.cooldown_remaining_seconds||0));\n if($('smartCooldownHint')) $('smartCooldownHint').textContent=st.enabled ? `Automatic run every ${st.cooldown_minutes||10} minute(s). Manual check ignores cooldown.` : 'Smart Queue is disabled; timer starts after it is enabled and runs once.';\n if($('smartRefillHint')) $('smartRefillHint').textContent=smartRefillHintText(refillMode, Number(st.refill_interval_minutes||0), Number(j.refill_remaining_seconds||0));\n if($('smartManager')){\n const nameForHash=hash=>torrents.get(hash)?.name || hash;\n $('smartManager').innerHTML=ex.length\n ? responsiveTable(['Torrent','Hash','Reason','Created','Action'],ex.map(x=>[esc(nameForHash(x.torrent_hash)),esc(x.torrent_hash),esc(x.reason||''),dateCell(x.created_at),``]),'smart-exclusions-table')\n : '
No Smart Queue exceptions. Use Manage exceptions to choose torrents ignored by Smart Queue.
';\n }\n if($('smartHistory')){\n const body=hist.length\n ? responsiveTable(['Time','Event','Checked','Active','Slot details','Limit','Over','Stopped','Requested','Verified','Pending','Stalled'],hist.map(h=>{\n // Note: Pending and Stalled are separate audit columns so delayed starts and stopped stalled torrents are visible independently.\n const d=smartHistoryDetails(h);\n const activeBefore=d.active_before ?? '-';\n const activeAfter=d.active_after_expected ?? d.active_after_stop ?? '-';\n const limit=d.max_active_downloads ?? '-';\n const requested=Number(d.start_requested_count ?? (d.start_requested||[]).length ?? 0);\n const verified=Number(d.active_verified_count ?? (d.active_verified||[]).length ?? 0);\n const pending=Number(d.pending_confirmation_count ?? (d.start_pending_confirmation||[]).length ?? 0);\n const stalledDetected=Number(d.stalled_detected||0);\n const stalledStopped=Number(d.stalled_stopped||0);\n const stalledProtected=Number(d.protected_stalled||0);\n const stalledText=stalledDetected?`${stalledStopped}/${stalledDetected}${stalledProtected?` protected ${stalledProtected}`:''}`:'-';\n const slotNote=d.cooldown_refill ? `state ${d.active_state_count ?? '-'} / rT active ${d.active_rtorrent_count ?? '-'} / transferring ${d.active_transferring_count ?? '-'}` : '-';\n return [dateCell(h.created_at),esc(d.decision||h.event||'-'),esc(h.checked_count||d.checked||0),esc(`${activeBefore}->${activeAfter}`),esc(slotNote),esc(limit),esc(d.over_limit||0),esc(h.paused_count||0),esc(requested),esc(verified),esc(pending||'-'),esc(stalledText)];\n }),'smart-history-table')\n : '
No Smart Queue operations yet.
';\n const canToggle=totalHistory>10;\n const toggle=canToggle?``:'';\n const clear=totalHistory?``:'';\n $('smartHistory').innerHTML=`${body}${toggle}${clear}`;\n }\n }\n function smartRefillHintText(mode, minutes, remainingSeconds){\n // Note: Refill mode controls only the lightweight slot top-up during cooldown, not the full Smart Queue pass.\n if(mode==='off') return 'Refill is disabled. Smart Queue will only fill slots during full checks or manual checks.';\n if(mode==='custom'){\n const wait=Number(remainingSeconds||0)>0 ? ` Next refill in ${formatDurationLeft(remainingSeconds)}.` : '';\n return `Refill runs at most every ${Math.max(1, Number(minutes||5))} minute(s) while Smart Queue is in cooldown.${wait}`;\n }\n return 'Refill uses the current automatic poller cadence during cooldown, usually about every 2 minutes.';\n }\n function updateSmartRefillControls(){\n const mode=$('smartRefillMode')?.value||'auto';\n const interval=$('smartRefillInterval');\n if(interval) interval.disabled=mode!=='custom';\n }\n async function setSmartException(hashes, excluded, reason='manual'){ const list=[...new Set(hashes||[])].filter(Boolean); if(!list.length) return toastMessage('toast.noTorrentsSelected','warning'); setBusy(true); try{ for(const h of list) await post('/api/smart-queue/exclusion',{hash:h,excluded,reason}); toast(excluded?'Smart Queue exception added':'Smart Queue exception removed','success'); await loadSmartQueue(); }catch(e){toast(e.message,'danger');} finally{setBusy(false);} }\n async function saveSmartQueue(){ await post('/api/smart-queue',{enabled:$('smartEnabled')?.checked,max_active_downloads:$('smartMaxActive')?.value,stalled_seconds:$('smartStalled')?.value,stop_batch_size:$('smartStopBatch')?.value||50,start_grace_seconds:$('smartStartGrace')?.value||900,protect_active_below_cap:$('smartProtectActiveBelowCap')?.checked,auto_stop_idle:$('smartAutoStopIdle')?.checked,min_speed_bytes:Math.round(Number($('smartMinSpeed')?.value||0)*1024),min_seeds:$('smartMinSeeds')?.value,min_peers:$('smartMinPeers')?.value,ignore_seed_peer:$('smartIgnoreSeedPeer')?.checked,ignore_speed:$('smartIgnoreSpeed')?.checked,cooldown_minutes:$('smartCooldown')?.value||10,refill_mode:$('smartRefillMode')?.value||'auto',refill_interval_minutes:$('smartRefillInterval')?.value||5}); toast('Smart Queue saved','success'); await loadSmartQueue(); }\n\n function normalizeRtConfigValue(value, type='text'){\n const raw=String(value ?? '').trim();\n if(type==='bool') return ['1','true','yes','on'].includes(raw.toLowerCase()) ? '1' : '0';\n if(type==='number'){\n if(raw==='') return '0';\n const normalized=Number(raw.replace(',', '.'));\n return Number.isFinite(normalized) ? String(Math.trunc(normalized)) : raw;\n }\n return raw;\n }\n function rtConfigInputValue(input){\n const type=input.dataset.type || rtConfigFieldTypes.get(input.dataset.key) || 'text';\n const value=type==='bool' && input.type==='checkbox' ? (input.checked?'1':'0') : input.value;\n return normalizeRtConfigValue(value, type);\n }\n function rtConfigOriginalValue(input){\n const key=input.dataset.key;\n return normalizeRtConfigValue(input.dataset.original ?? rtConfigOriginal.get(key), input.dataset.type || rtConfigFieldTypes.get(key) || 'text');\n }\n function collectRtConfigChanges(){\n const values={};\n document.querySelectorAll('.rt-config-input').forEach(input=>{\n if(input.disabled) return;\n const cur=rtConfigInputValue(input);\n const orig=rtConfigOriginalValue(input);\n if(cur!==orig) values[input.dataset.key]=cur;\n });\n return values;\n }\n function collectRtConfigClearKeys(){\n const keys=[];\n document.querySelectorAll('.rt-config-input').forEach(input=>{\n if(input.disabled || input.dataset.saved!=='true') return;\n const cur=rtConfigInputValue(input);\n const orig=rtConfigOriginalValue(input);\n if(cur===orig) keys.push(input.dataset.key);\n });\n return keys;\n }\n function updateRtConfigDirty(){\n const changed=collectRtConfigChanges();\n const clearKeys=collectRtConfigClearKeys();\n document.querySelectorAll('.rt-config-input').forEach(input=>{\n const row=input.closest('.rt-config-row');\n if(row) row.classList.toggle('changed', Object.prototype.hasOwnProperty.call(changed,input.dataset.key));\n });\n const configChanges=Object.keys(changed).length;\n const applyChanged=!!$('rtConfigApplyOnStart') && $('rtConfigApplyOnStart').checked!==rtConfigOriginalApplyOnStart;\n const total=configChanges + clearKeys.length + (applyChanged ? 1 : 0);\n if($('rtConfigChangedCount')) $('rtConfigChangedCount').textContent=total?`${total} changed`:'No changes';\n if($('rtConfigGenerateBtn')) $('rtConfigGenerateBtn').disabled=!configChanges;\n if($('rtConfigSaveBtn')) $('rtConfigSaveBtn').disabled=!total;\n }\n function rtConfigHelpText(field){\n const parts = [];\n if(field.description) parts.push(field.description);\n if(field.recommendation) parts.push(`Recommendation: ${field.recommendation}`);\n if(field.error) parts.push(`Runtime note: ${field.error}`);\n return parts.join(' ');\n }\n function rtConfigGroupIntro(group){\n const notes = {\n 'Directories': 'Paths used by rTorrent for downloads, state and runtime context.',\n 'Network': 'Connectivity limits, listening ports and HTTP/XML-RPC behavior.',\n 'Peers': 'Peer discovery and peer count targets for downloading and seeding.',\n 'Throttle': 'Global speed and active slot limits used by the rTorrent scheduler.',\n 'DHT / PEX': 'Distributed peer discovery options; verify private tracker rules before enabling.',\n 'Protocol': 'Advanced peer protocol behavior. Keep defaults unless you know the tracker/network requirement.',\n 'Files': 'Disk, hashing and piece cache behavior. Tune carefully on busy storage.',\n 'System': 'Runtime identity and filesystem permissions.'\n };\n return notes[group] || 'Additional rTorrent runtime settings.';\n }\n function rtConfigFieldState(field){\n if(!field.ok) return 'Unavailable';\n if(field.readonly) return 'Read only';\n if(field.saved) return 'Saved override';\n return 'Live';\n }\n function rtConfigFieldMarkup(field){\n const disabled=(!field.ok||field.readonly)?'disabled':'';\n const type=['bool','number'].includes(field.type)?field.type:'text';\n const originalValue=normalizeRtConfigValue(field.baseline_value ?? field.current_value ?? field.value, type);\n const displayValue=normalizeRtConfigValue(field.saved ? field.saved_value : (field.value ?? field.current_value), type);\n rtConfigOriginal.set(field.key, originalValue);\n rtConfigFieldTypes.set(field.key, type);\n const originalAttr=esc(originalValue);\n const help=rtConfigHelpText(field);\n const valueNote=field.saved?`Reference: ${esc(originalValue)} → saved: ${esc(displayValue)}`:'';\n const input=type==='bool'\n ? `${displayValue==='1'?'On':'Off'}`\n : ``;\n // Note: Help text is exposed only through the question-mark tooltip to avoid duplicated descriptions under every option.\n return ``;\n }\n function renderRtConfigGroups(fields){\n const groups = new Map();\n fields.forEach(field=>{\n const group=field.group||'Other';\n if(!groups.has(group)) groups.set(group, []);\n groups.get(group).push(field);\n });\n return [...groups.entries()].map(([group, items])=>`
${esc(group)}${esc(rtConfigGroupIntro(group))}
${items.map(rtConfigFieldMarkup).join('')}
`).join('');\n }\n\n async function loadRtConfig(){\n const box=$('rtConfigManager');\n if(!box)return;\n box.innerHTML=' Loading config...';\n try{\n const j=await (await fetch('/api/rtorrent-config')).json();\n if(!j.ok) throw new Error(j.error||'Config load failed');\n const fields=j.config?.fields||[];\n rtConfigOriginal=new Map();\n rtConfigFieldTypes=new Map();\n rtConfigOriginalApplyOnStart=!!j.config?.apply_on_start;\n // Note: rTorrent settings are rendered as grouped cards, keeping the old save/reset/generate flow intact while removing the noisy summary block.\n box.innerHTML=`
${renderRtConfigGroups(fields)}
`;\n if($('rtConfigApplyOnStart')) $('rtConfigApplyOnStart').checked=rtConfigOriginalApplyOnStart;\n updateRtConfigDirty();\n document.querySelectorAll('#rtConfigManager [data-bs-toggle=\"tooltip\"]').forEach(el=>bootstrap.Tooltip.getOrCreateInstance(el));\n }catch(e){ box.innerHTML=`
${esc(e.message)}
`; }\n }\n async function saveRtConfig(){\n const values=collectRtConfigChanges();\n const clear_keys=collectRtConfigClearKeys();\n clear_keys.forEach(key=>{\n const input=document.querySelector(`.rt-config-input[data-key=\"${CSS.escape(key)}\"]`);\n if(input) values[key]=rtConfigOriginalValue(input);\n });\n setBusy(true);\n try{\n const j=await post('/api/rtorrent-config',{values,clear_keys,apply_on_start:!!$('rtConfigApplyOnStart')?.checked,apply_now:true});\n toastMessage('toast.rtorrentConfigSaved','success',{updated:j.result?.updated?.length});\n await loadRtConfig();\n }catch(e){\n toast(e.message,'danger');\n } finally{\n setBusy(false);\n }\n }\n async function resetRtConfig(){\n // Note: Reset clears only saved UI overrides, then reloads the live state from rTorrent.\n if(!confirm('Clear all saved rTorrent UI overrides and reload current rTorrent values?')) return;\n setBusy(true);\n try{\n const j=await post('/api/rtorrent-config/reset',{});\n toastMessage('toast.rtorrentConfigReset','success',{removed:j.config?.reset_removed});\n await loadRtConfig();\n }catch(e){\n toast(e.message,'danger');\n } finally{\n setBusy(false);\n }\n }\n async function generateRtConfig(){ const values=collectRtConfigChanges(); try{ const res=await fetch('/api/rtorrent-config/generate',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({values})}); const j=await res.json(); if(!j.ok) throw new Error(j.error||'Generate failed'); if($('rtConfigOutput')) $('rtConfigOutput').value=j.config_text||''; toast('Config generated','success'); }catch(e){ toast(e.message,'danger'); } }\n\n function bootstrapThemeUrl(theme){ /* Note: Themes use the URL map generated by the backend, so they also work offline. */ const key=theme||\"default\"; return window.PYTORRENT?.bootstrapThemeUrls?.[key] || window.PYTORRENT?.bootstrapThemeUrls?.default || \"\"; }\n function applyBootstrapTheme(theme){\n // Note: Custom Bootstrap 2-inspired themes are normal selectable themes and keep light/dark compatibility through data-bs-theme.\n bootstrapTheme = theme || \"default\";\n document.documentElement.dataset.bootstrapSkin = bootstrapTheme;\n const link=$(\"bootstrapThemeStylesheet\");\n if(link) link.href = bootstrapThemeUrl(bootstrapTheme);\n if($(\"bootstrapThemeSelect\")) $(\"bootstrapThemeSelect\").value = bootstrapTheme;\n }\n function applyFontFamily(font){ fontFamily = font || \"default\"; document.documentElement.dataset.appFont = fontFamily; if($(\"fontFamilySelect\")) $(\"fontFamilySelect\").value = fontFamily; }\n function clampInterfaceScale(value){ value = Number(value || 100); if(!Number.isFinite(value)) value = 100; return Math.max(80, Math.min(140, Math.round(value / 5) * 5)); }\n function applyInterfaceScale(value){ interfaceScale = clampInterfaceScale(value); document.documentElement.style.setProperty(\"--ui-scale\", String(interfaceScale / 100)); if($(\"interfaceScaleRange\")) $(\"interfaceScaleRange\").value = interfaceScale; if($(\"interfaceScaleValue\")) $(\"interfaceScaleValue\").textContent = `${interfaceScale}%`; scheduleRender(false); }\n function torrentRowHeight(){ return compactTorrentListEnabled ? COMPACT_ROW_HEIGHT : ROW_HEIGHT; }\n function applyCompactTorrentList(value){\n // Note: The compact switch changes density only; filtering, sorting and existing row actions stay unchanged.\n compactTorrentListEnabled = !!value;\n document.body.classList.toggle(\"compact-torrent-list\", compactTorrentListEnabled);\n if($(\"compactTorrentListEnabled\")) $(\"compactTorrentListEnabled\").checked = compactTorrentListEnabled;\n scheduleRender(true);\n }\n async function saveAppearancePreferences(){ applyBootstrapTheme($(\"bootstrapThemeSelect\")?.value || \"default\"); applyFontFamily($(\"fontFamilySelect\")?.value || \"default\"); applyInterfaceScale($(\"interfaceScaleRange\")?.value || interfaceScale); applyCompactTorrentList($(\"compactTorrentListEnabled\")?.checked); try{ await post(\"/api/preferences\",{bootstrap_theme:bootstrapTheme,font_family:fontFamily,interface_scale:interfaceScale,compact_torrent_list_enabled:compactTorrentListEnabled}); toast(\"Appearance preferences saved\",\"success\"); }catch(e){ toast(e.message,\"danger\"); } }\n if($(\"titleSpeedEnabled\")) $(\"titleSpeedEnabled\").checked=titleSpeedEnabled;\n applyBootstrapTheme(bootstrapTheme);\n applyCompactTorrentList(compactTorrentListEnabled);\n\n function setupPeersRefresh(tab=activeTab()){ clearInterval(peersRefreshTimer); peersRefreshTimer=null; if($('peersRefreshSelect')) $('peersRefreshSelect').value=String(peersRefreshSeconds||0); if(tab==='peers' && peersRefreshSeconds>0){ peersRefreshTimer=setInterval(()=>{ if(activeTab()==='peers' && selectedHash) loadDetails('peers'); }, peersRefreshSeconds*1000); } }\n function refreshPeersOnceForReverseDns(){\n // Note: Reverse DNS can resolve after the first peers fetch, so trigger one silent follow-up even when auto-refresh is disabled.\n if(activeTab()==='peers' && selectedHash){\n loadDetails('peers');\n setTimeout(()=>{ if(activeTab()==='peers' && selectedHash) loadDetails('peers',{silent:true}); }, 1200);\n }\n }\n function syncMobileMode(){ const auto=window.matchMedia&&window.matchMedia(\"(max-width: 900px)\").matches; document.body.classList.toggle(\"mobile-mode\", auto || document.body.classList.contains(\"mobile-mode-manual\")); scheduleRender(true); }\n\n\n let automationRulesCache=[];\n let automationConditions=[];\n let automationEffects=[];\n\n function automationCondition(){\n const type=$('autoConditionType')?.value||'completed';\n const cond={type, negate:!!$('autoCondNegate')?.checked};\n if(type==='no_seeds'){ cond.seeds=Number($('autoCondSeeds')?.value||0); cond.minutes=Number($('autoCondMinutes')?.value||0); }\n if(type==='ratio_gte') cond.ratio=Number($('autoCondRatio')?.value||1);\n // Note: Progress conditions compare the torrent completion percentage stored in the live torrent row.\n if(type==='progress_gte'||type==='progress_lte') cond.progress=Number($('autoCondProgress')?.value||0);\n if(type==='label_missing'||type==='label_has') cond.label=$('autoCondLabel')?.value||'';\n if(type==='status') cond.status=$('autoCondStatus')?.value||'Seeding';\n if(type==='path_contains') cond.text=$('autoCondText')?.value||'';\n return cond;\n }\n\n function automationEffect(){\n const type=$('autoEffectType')?.value||'add_label';\n const eff={type};\n if(type==='move'){\n eff.path=$('autoEffectPath')?.value||'';\n eff.move_data=!!$('autoMoveData')?.checked;\n eff.recheck=!!$('autoMoveRecheck')?.checked;\n eff.keep_seeding=!!$('autoMoveKeepSeeding')?.checked;\n }\n if(type==='add_label'||type==='remove_label') eff.label=$('autoEffectLabel')?.value||'';\n if(type==='set_labels') eff.labels=$('autoEffectLabels')?.value||'';\n return eff;\n }\n\n function updateAutomationForm(){\n const ct=$('autoConditionType')?.value||'';\n document.querySelectorAll('[data-auto-cond]').forEach(el=>el.classList.toggle('d-none', !el.dataset.autoCond.split(',').includes(ct)));\n const et=$('autoEffectType')?.value||'';\n document.querySelectorAll('[data-auto-effect]').forEach(el=>el.classList.toggle('d-none', !el.dataset.autoEffect.split(',').includes(et)));\n }\n\n function conditionText(c={}){\n const base=c.type==='no_seeds'?`seeds <= ${c.seeds||0} for ${c.minutes||0} min`:c.type==='ratio_gte'?`ratio >= ${c.ratio}`:c.type==='progress_gte'?`progress >= ${c.progress||0}%`:c.type==='progress_lte'?`progress <= ${c.progress||0}%`:c.type==='label_missing'?`missing label ${c.label||''}`:c.type==='label_has'?`has label ${c.label||''}`:c.type==='status'?`status = ${c.status||''}`:c.type==='path_contains'?`path contains ${c.text||''}`:'completed';\n return c.negate?`NOT (${base})`:base;\n }\n function effectText(e={}){\n if(e.type==='move'){\n const flags=[];\n if(e.move_data) flags.push('move data');\n if(e.recheck) flags.push('recheck');\n if(e.keep_seeding) flags.push('keep seeding');\n return `move to ${e.path||'default path'}${flags.length?` (${flags.join(', ')})`:''}`;\n }\n return e.type==='add_label'?`add label ${e.label||''}`:e.type==='remove_label'?`remove label ${e.label||''}`:e.type==='set_labels'?`set labels ${e.labels||''}`:e.type;\n }\n function ruleSummary(r){\n const cs=(r.conditions||[]).map(conditionText).join(' + ')||'no conditions';\n const es=(r.effects||[]).map(effectText).join(' → ')||'no actions';\n return `${cs} → ${es}`;\n }\n\n function renderAutomationBuilder(){\n const cBox=$('automationConditionList');\n if(cBox) cBox.innerHTML=automationConditions.length?automationConditions.map((c,i)=>`IF ${esc(conditionText(c))}`).join(''):'No conditions added yet.';\n const eBox=$('automationEffectList');\n if(eBox) eBox.innerHTML=automationEffects.length?automationEffects.map((e,i)=>`${i+1} ${esc(effectText(e))}`).join(''):'No actions added yet.';\n }\n function resetAutomationForm(){\n if($('autoEditId')) $('autoEditId').value='';\n if($('autoName')) $('autoName').value='';\n if($('autoEnabled')) $('autoEnabled').checked=true;\n if($('autoCooldown')) $('autoCooldown').value='60';\n automationConditions=[]; automationEffects=[];\n $('automationCancelEditBtn')?.classList.add('d-none');\n if($('automationSaveBtn')) $('automationSaveBtn').innerHTML=' Save rule';\n renderAutomationBuilder(); updateAutomationForm();\n }\n function editAutomationRule(rule){\n if(!rule) return;\n if($('autoEditId')) $('autoEditId').value=rule.id||'';\n if($('autoName')) $('autoName').value=rule.name||'';\n if($('autoEnabled')) $('autoEnabled').checked=!!rule.enabled;\n if($('autoCooldown')) $('autoCooldown').value=rule.cooldown_minutes ?? 60;\n automationConditions=Array.isArray(rule.conditions)?JSON.parse(JSON.stringify(rule.conditions)):[];\n automationEffects=Array.isArray(rule.effects)?JSON.parse(JSON.stringify(rule.effects)):[];\n $('automationCancelEditBtn')?.classList.remove('d-none');\n if($('automationSaveBtn')) $('automationSaveBtn').innerHTML=' Update rule';\n renderAutomationBuilder();\n }\n\n function summarizeActionObject(a={}){\n if(a.error) return `${esc(a.error)}`;\n const count=a.count || a.result?.count || a.result?.results?.length || '';\n const parts=[];\n if(a.type) parts.push(a.type);\n if(count) parts.push(`${count} torrent(s)`);\n if(a.path) parts.push(a.path);\n if(a.label) parts.push(`label ${a.label}`);\n if(a.labels) parts.push(`labels ${a.labels}`);\n if(a.move_data) parts.push('move data');\n if(a.recheck) parts.push('recheck');\n if(a.keep_seeding) parts.push('keep seeding');\n return `${esc(parts.join(' · ')||'action')}`;\n }\n function automationHistoryActions(raw){\n let actions=[];\n try{ actions=JSON.parse(raw||'[]'); }catch(e){ return `
${esc(raw||'')}
`; }\n if(!Array.isArray(actions)) actions=[actions];\n const summary=actions.map(summarizeActionObject).join(' ');\n const details=esc(JSON.stringify(actions,null,2));\n // Note: Large automation payloads are collapsed so JSON never stretches the modal width.\n return `
${summary||'No actions'}
${details}
`;\n }\n\n function renderAutomationHistory(hist=[]){\n if(!$('automationHistory')) return;\n const toolbar='
';\n const rows=hist.map(h=>[humanDateCell(h.created_at),esc(h.rule_name||''),esc(h.torrent_name||h.torrent_hash||''),automationHistoryActions(h.actions_json||'')]);\n // Note: Automation history uses the shared responsive table wrapper so it stays inside narrow mobile modals.\n const body=hist.length?responsiveTable(['Time','Rule','Torrent / batch','Actions'],rows,'automation-history-table'):'
No automation history yet.
';\n $('automationHistory').innerHTML=toolbar+body;\n }\n\n async function clearAutomationHistory(){\n if(!confirm('Clear automation history?')) return;\n setBusy(true);\n try{ const j=await fetch('/api/automations/history',{method:'DELETE'}).then(r=>r.json()); if(!j.ok) throw new Error(j.error||'Clear automation history failed'); toastMessage('toast.automationLogsDeleted','success',{deleted:j.deleted}); renderAutomationHistory(j.history||[]); }\n catch(e){ toast(e.message,'danger'); }\n finally{ setBusy(false); }\n }\n\n async function exportAutomations(){\n try{ const j=await (await fetch('/api/automations/export')).json(); if(!j.ok) throw new Error(j.error||'Automation export failed'); downloadJson(`pytorrent-automation-rules-${new Date().toISOString().slice(0,10)}.json`, j.export||j); toast(`Exported ${j.count||0} automation rule(s)`,'success'); }\n catch(e){ toast(e.message,'danger'); }\n }\n\n async function importAutomations(file){\n if(!file) return;\n try{ const payload=JSON.parse(await file.text()); const j=await post('/api/automations/import',payload); toast(`Imported ${j.imported||0} automation rule(s)`,'success'); await loadAutomations(); }\n catch(e){ toast(e.message||'Automation import failed','danger'); }\n finally{ if($('automationImportFile')) $('automationImportFile').value=''; }\n }\n\n async function loadAutomations(){\n const j=await fetch('/api/automations').then(r=>r.json());\n const rules=j.rules||[], hist=j.history||[];\n automationRulesCache=rules;\n if($('automationManager')) $('automationManager').innerHTML=rules.length?rules.map(r=>{\n const enabled=!!r.enabled;\n const toggleTitle=enabled?'Disable automation':'Enable automation';\n const toggleIcon=enabled?'fa-toggle-on':'fa-toggle-off';\n const toggleClass=enabled?'btn-outline-warning':'btn-outline-success';\n return `
${esc(r.name)} ${enabled?'on':'off'}
${esc(ruleSummary(r))} · cooldown ${esc(r.cooldown_minutes||0)} min
`;\n }).join(''):'
No automation rules.
';\n renderAutomationHistory(hist);\n }\n\n async function toggleAutomationRule(rule){\n if(!rule) return;\n const payload={...rule, enabled:!rule.enabled};\n // Note: Toggle keeps the rule definition unchanged and only switches automatic execution on or off.\n setBusy(true);\n try{ await post('/api/automations',payload); toast(payload.enabled?'Automation enabled':'Automation disabled','success'); await loadAutomations(); }\n catch(e){ toast(e.message,'danger'); }\n finally{ setBusy(false); }\n }\n\n async function saveAutomation(){\n const currentCond=automationCondition();\n const currentEff=automationEffect();\n const conditions=automationConditions.length?automationConditions:[currentCond];\n const effects=automationEffects.length?automationEffects:[currentEff];\n const payload={id:Number($('autoEditId')?.value||0)||undefined,name:$('autoName')?.value||'Automation rule',enabled:!!$('autoEnabled')?.checked,cooldown_minutes:Number($('autoCooldown')?.value||60),conditions,effects};\n setBusy(true);\n try{ await post('/api/automations',payload); toast(payload.id?'Automation rule updated':'Automation rule saved','success'); resetAutomationForm(); await loadAutomations(); }\n catch(e){toast(e.message,'danger');}\n finally{setBusy(false);}\n }\n\n\n\n function cleanupCountCard(label, value, note=''){\n return `
${esc(label)}${esc(value ?? 0)}${note?`${esc(note)}`:''}
`;\n }\n function cleanupRetentionDaysNote(value){ return `retention ${value || '-'} days`; }\n function cleanupOperationLogRetentionNote(data){\n const settings = data.operation_log_retention || {};\n if(data.retention_labels?.operation_logs) return data.retention_labels.operation_logs;\n if(settings.retention_mode === 'lines') return `retention ${settings.retention_lines || '-'} lines`;\n if(settings.retention_mode === 'both') return `retention ${settings.retention_days || '-'} days and ${settings.retention_lines || '-'} lines`;\n if(settings.retention_mode === 'manual') return 'manual cleanup only';\n return cleanupRetentionDaysNote((data.retention_days || {}).operation_logs);\n }\n function renderCleanup(data={}){\n const box=$('cleanupManager'); if(!box) return;\n const retention=data.retention_days||{};\n const db=data.database||{};\n const cache=data.cache||{};\n const cards=[\n cleanupCountCard('Job logs total', data.jobs_total, cleanupRetentionDaysNote(retention.jobs)),\n cleanupCountCard('Job logs clearable', data.jobs_clearable, 'done / failed / cancelled'),\n cleanupCountCard('Smart Queue logs', data.smart_queue_history_total, cleanupRetentionDaysNote(retention.smart_queue_history)),\n cleanupCountCard('Operation logs', data.operation_logs_total, cleanupOperationLogRetentionNote(data)),\n cleanupCountCard('Planner logs', data.planner_history_total, cleanupRetentionDaysNote(retention.planner_history)),\n cleanupCountCard('Automation logs', data.automation_history_total, cleanupRetentionDaysNote(retention.automation_history)),\n cleanupCountCard('Profile cache rows', cache.profile_rows ?? 0, 'tracker + torrent stats cache'),\n cleanupCountCard('Runtime cache', cache.runtime_items ?? 0, 'memory-only profile cache'),\n cleanupCountCard('Database size', db.size_h||db.size||'-', db.path||'')\n ];\n const poller=data.poller_runtime||{};\n const pollerCards=[\n cleanupCountCard('Live poll counter', poller.live_poll_count ?? 0, 'lightweight speed/status loop'),\n cleanupCountCard('List poll counter', poller.list_poll_count ?? 0, 'full snapshot/diff loop'),\n cleanupCountCard('Poller skipped emits', poller.skipped_emissions ?? 0, 'diagnostic counter only')\n ];\n box.innerHTML=`
${cards.join('')}${pollerCards.join('')}
Profile cacheClears only the active profile runtime/DB cache. It does not remove torrents, rules, settings or logs.
Poller diagnosticsResets in-memory live/list poller counters only. Polling, saved settings and torrent data stay unchanged.
Logs and historyPending and running jobs are preserved. Operation log cleanup removes only profile-scoped log entries.
`;\n }\n async function loadCleanup(){\n const box=$('cleanupManager'); if(!box) return;\n box.innerHTML=' Loading cleanup data...';\n try{\n const j=await (await fetch('/api/cleanup/summary')).json();\n if(!j.ok) throw new Error(j.error||'Cleanup summary failed');\n renderCleanup(j.cleanup||{});\n }catch(e){ box.innerHTML=`
${esc(e.message)}
`; }\n }\n async function runCleanupAction(endpoint, label){\n if(!confirm(`${label}?`)) return;\n setBusy(true);\n try{\n const j=await post(endpoint,{});\n const deleted=typeof j.deleted==='object' ? Object.entries(j.deleted).map(([k,v])=>`${k}: ${v}`).join(', ') : String(j.deleted ?? 0);\n toastMessage('toast.cleanupDone','success',{deleted});\n renderCleanup(j.cleanup||{});\n if(endpoint.includes('/jobs')){ jobsPage=0; loadJobs(0).catch(()=>{}); }\n if(endpoint.includes('/smart-queue') || endpoint.includes('/all')) loadSmartQueue().catch(()=>{});\n if(endpoint.includes('/operation-logs') || endpoint.includes('/all')) loadOperationLogs(true).catch(()=>{});\n if(endpoint.includes('/planner') || endpoint.includes('/all')) loadPlannerPreview().catch(()=>{});\n if(endpoint.includes('/automations') || endpoint.includes('/all')) loadAutomations().catch(()=>{});\n }catch(e){ toast(e.message,'danger'); }\n finally{ setBusy(false); }\n }\n\n function diagCard(label,value,extra=''){ return `
${esc(label)}${esc(value ?? '-')}
`; }\n\n // Note: Centralizes footer visibility so Preferences can hide items without removing existing status logic.\n function applyFooterPreferences(){\n document.querySelectorAll('[data-footer-item]').forEach(el=>{\n const key=el.dataset.footerItem;\n el.classList.toggle('footer-pref-hidden', footerItems[key] === false);\n });\n }\n function renderFooterPreferences(){\n const box=$('footerPreferences');\n if(!box) return;\n box.innerHTML=FOOTER_ITEM_DEFS.map(([key,label])=>``).join('');\n }\n async function saveFooterPreferences(){\n document.querySelectorAll('.footer-pref-toggle').forEach(cb=>{ footerItems[cb.dataset.footerKey] = !!cb.checked; });\n applyFooterPreferences();\n renderFooterPreferences();\n try{ await post('/api/preferences',{footer_items_json:footerItems}); toast('Footer preferences saved','success'); }\n catch(e){ toast(e.message,'danger'); }\n }\n function compactSpeedText(value){\n // Note: The footer has limited space, so it removes spaces only from speed labels.\n return String(value || '0 B/s').replace(/\\s+(?=[KMGT]?i?B\\/s$|B\\/s$)/, '');\n }\n function speedPairText(down, up){\n // Note: Consistent DL/UL pair formatting is used in the footer and diagnostics.\n return `${compactSpeedText(down)} / ${compactSpeedText(up)}`;\n }\n function peakDateText(value){\n // Note: Shortens the ISO timestamp from the database into a readable tooltip label.\n return value ? String(value).replace('T',' ').replace(/\\+00:00$/, ' UTC') : '-';\n }\n function updateSpeedPeaks(peaks={}){\n // Note: Shows the session and all-time record next to current speeds in the footer.\n const session=peaks.session||{};\n const allTime=peaks.all_time||{};\n const sessionText=speedPairText(session.down_h, session.up_h);\n const allTimeText=speedPairText(allTime.down_h, allTime.up_h);\n if($('statPeakSession')) $('statPeakSession').textContent=sessionText;\n if($('statPeakAllTime')) $('statPeakAllTime').textContent=allTimeText;\n const box=$('statusSpeedPeaks');\n if(box){\n box.title=`Peak speed DL/UL\\nSession: ${sessionText}\\nSession DL at: ${peakDateText(session.down_at)}\\nSession UL at: ${peakDateText(session.up_at)}\\nAll-time: ${allTimeText}\\nAll-time DL at: ${peakDateText(allTime.down_at)}\\nAll-time UL at: ${peakDateText(allTime.up_at)}`;\n }\n }\n function browserSpeedSnapshot(){\n // Note: Browser title speed can fall back to the live torrent snapshot when system_stats is delayed or reports zero.\n let down=0, up=0;\n torrents.forEach(t=>{\n down += Number(t.down_rate || 0);\n up += Number(t.up_rate || 0);\n });\n return {down, up, down_h: humanRateLabel(down), up_h: humanRateLabel(up)};\n }\n function humanRateLabel(value){\n const units=['B/s','KiB/s','MiB/s','GiB/s','TiB/s'];\n let n=Math.max(0, Number(value || 0));\n let i=0;\n while(n>=1024 && i=10 || i===0 ? Math.round(n) : n.toFixed(1)} ${units[i]}`;\n }\n function numericSpeed(value){\n // Note: Accepts both raw bytes/s and human labels, so zero checks work for \"0\", \"0 B/s\" and \"0.0 KiB/s\".\n if(typeof value === 'number') return Math.max(0, value);\n const text=String(value ?? '').trim();\n if(!text) return 0;\n const match=text.match(/^([0-9]+(?:\\.[0-9]+)?)\\s*(B\\/s|KiB\\/s|MiB\\/s|GiB\\/s|TiB\\/s)?$/i);\n if(!match) return 0;\n const units=['B/s','KiB/s','MiB/s','GiB/s','TiB/s'];\n const unit=(match[2] || 'B/s').replace(/kib/i,'KiB').replace(/mib/i,'MiB').replace(/gib/i,'GiB').replace(/tib/i,'TiB').replace(/b\\/s/i,'B/s');\n return Number(match[1] || 0) * Math.pow(1024, Math.max(0, units.indexOf(unit)));\n }\n function applyLiveSpeedStats(stats={}){\n // Note: Fast-poller speed updates drive the tab title and peak speed UI without waiting for system_stats.\n const downRaw=Number(stats.down_rate || 0);\n const upRaw=Number(stats.up_rate || 0);\n const downH=stats.down_rate_h || humanRateLabel(downRaw);\n const upH=stats.up_rate_h || humanRateLabel(upRaw);\n if($('statDl')) $('statDl').textContent=downH || '0 B/s';\n if($('statUl')) $('statUl').textContent=upH || '0 B/s';\n if($('mobileSpeedDl')) $('mobileSpeedDl').textContent=downH || '0 B/s';\n if($('mobileSpeedUl')) $('mobileSpeedUl').textContent=upH || '0 B/s';\n if(stats.speed_peaks) updateSpeedPeaks(stats.speed_peaks);\n updateBrowserSpeedTitle(downH, upH, downRaw, upRaw);\n }\n function updateBrowserSpeedTitle(downH, upH, downRaw=null, upRaw=null){\n // Note: Keeps the browser tab title accurate even when system_stats is delayed or reports a stale zero.\n const fallback=browserSpeedSnapshot();\n const downValue=downRaw == null ? numericSpeed(downH) : Number(downRaw || 0);\n const upValue=upRaw == null ? numericSpeed(upH) : Number(upRaw || 0);\n const useFallbackDown=(downH == null || (downValue <= 0 && fallback.down>0));\n const useFallbackUp=(upH == null || (upValue <= 0 && fallback.up>0));\n lastBrowserSpeed.down=useFallbackDown ? fallback.down_h : (downH || '0 B/s');\n lastBrowserSpeed.up=useFallbackUp ? fallback.up_h : (upH || '0 B/s');\n const speedTitle=`DL ${lastBrowserSpeed.down} / UL ${lastBrowserSpeed.up}`;\n document.title=titleSpeedEnabled ? `${speedTitle} - ${BASE_TITLE}` : BASE_TITLE;\n try{ window.status=titleSpeedEnabled ? speedTitle : ''; }catch(e){}\n }\n async function saveTitleSpeedPreference(){\n // Note: The change applies immediately and is saved as a user preference.\n titleSpeedEnabled=!!$('titleSpeedEnabled')?.checked;\n updateBrowserSpeedTitle();\n try{ await post('/api/preferences',{title_speed_enabled:titleSpeedEnabled}); toast('Browser title speed saved','success'); }\n catch(e){ toast(e.message,'danger'); }\n }\n async function saveTrackerFaviconsPreference(){\n // Note: Tracker favicon toggle changes only icon rendering; tracker filter counts and actions stay untouched.\n trackerFaviconsEnabled=!!$('trackerFaviconsEnabled')?.checked;\n renderTrackerFilters();\n try{ await post('/api/preferences',{tracker_favicons_enabled:trackerFaviconsEnabled}); toast('Tracker favicon preference saved','success'); }\n catch(e){ toast(e.message,'danger'); }\n }\n async function saveReverseDnsPreference(){\n // Note: Reverse DNS remains opt-in and refreshes only the peers pane, leaving other torrent data untouched.\n reverseDnsEnabled=!!$('reverseDnsEnabled')?.checked;\n try{ await post('/api/preferences',{reverse_dns_enabled:reverseDnsEnabled}); refreshPeersOnceForReverseDns(); toast('Reverse DNS preference saved','success'); }\n catch(e){ toast(e.message,'danger'); }\n }\n function updateFooterClock(){\n const el=$('statClock');\n if(el) el.textContent=new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit', second:'2-digit'});\n }\n function updateSocketStatus(s={}){\n const el=$('statSockets');\n if(!el) return;\n const open=s.open_sockets;\n const max=s.max_open_sockets;\n el.textContent=open == null ? '-' : (max == null ? String(open) : `${open}/${max}`);\n const box=$('statusSockets');\n if(box) box.title=open == null ? 'Open sockets unavailable from this rTorrent build' : `Open rTorrent sockets${max == null ? '' : ' / max'}: ${el.textContent}`;\n }\n\n function portStatusLabel(st){ return st==='open'?'open':st==='closed'?'closed':st==='disabled'?'disabled':st==='error'?'error':'unknown'; }\n function portStatusClass(st){ return st==='open'?'port-ok':st==='closed'?'port-bad':'port-secondary'; }\n function portStatusIcon(st){ return st==='open'?'fa-circle-check':st==='closed'?'fa-circle-xmark':'fa-circle-question'; }\n function portStatusBadge(data={},attrs='',withPort=false){ const st=portStatusLabel(data.status); const active=data.open_port||data.port; const port=active?String(active):'-'; const label=withPort?`Port ${port} ${st}`:st; return ` ${esc(label)}`; }\n function portCheckedAt(data={}){ if(data.checked_at) return String(data.checked_at).replace('T',' ').replace(/\\+00:00$/,' UTC'); if(data.checked_at_epoch) return new Date(Number(data.checked_at_epoch)*1000).toLocaleString(); return ''; }\n function portCheckDetails(data={}){ const bits=[]; if(data.open_port) bits.push(`Open port: ${data.open_port}`); else if(data.port) bits.push(`First port: ${data.port}`); if(Array.isArray(data.ports)&&data.ports.length>1) bits.push(`Candidates: ${data.ports.join(', ')}`); if(Array.isArray(data.checked_ports)&&data.checked_ports.length) bits.push(`Checked: ${data.checked_ports.join(', ')}`); if(data.ports_truncated) bits.push('Port list truncated to safety limit'); if(data.public_ip) bits.push(`Public IP: ${data.public_ip}`); if(data.remote) bits.push('Remote profile'); if(data.source) bits.push(`Source: ${data.source}`); const checked=portCheckedAt(data); if(checked) bits.push(`Last check: ${checked}`); if(data.cached) bits.push('Cached result'); if(data.error) bits.push(data.error); if(data.fallback_error) bits.push(data.fallback_error); return bits; }\n function renderPortCheck(data={}){\n if($('portCheckEnabled')) $('portCheckEnabled').checked=!!data.enabled;\n const details=portCheckDetails(data);\n const title=details.join(' · ') || 'Port check disabled';\n if($('portCheckBadge')) $('portCheckBadge').outerHTML=portStatusBadge(data,'id=\"portCheckBadge\" ');\n if($('portCheckInfo')) $('portCheckInfo').textContent=details.join(' · ') || 'Uses YouGetSignal first. Manual check bypasses the 6h cache.';\n if($('statusPortCheck')){\n $('statusPortCheck').classList.toggle('d-none', !data.enabled);\n $('statusPortCheck').title=title;\n }\n if($('statusPortCheckBadge')) $('statusPortCheckBadge').outerHTML=portStatusBadge(data,'id=\"statusPortCheckBadge\" ',true);\n }\n async function loadPreferences(){\n try{\n const j=await (await fetch(`/api/preferences?_=${Date.now()}`, {cache:'no-store'})).json();\n const prefs=j.preferences||{};\n portCheckEnabled=!!Number(prefs.port_check_enabled ?? portCheckEnabled);\n reverseDnsEnabled=!!Number(prefs.reverse_dns_enabled ?? (reverseDnsEnabled?1:0));\n if($('reverseDnsEnabled')) $('reverseDnsEnabled').checked=reverseDnsEnabled;\n automationToastsEnabled=Number(prefs.automation_toasts_enabled ?? (automationToastsEnabled?1:0))!==0;\n smartQueueToastsEnabled=Number(prefs.smart_queue_toasts_enabled ?? (smartQueueToastsEnabled?1:0))!==0;\n easterEggEnabled=Number(prefs.easter_egg_enabled ?? (easterEggEnabled?1:0))!==0;\n easterEggLoadingImageUrl=String(prefs.easter_egg_loading_image_url ?? easterEggLoadingImageUrl ?? '').trim();\n easterEggClickImageUrl=String(prefs.easter_egg_click_image_url ?? easterEggClickImageUrl ?? '').trim();\n diskMonitorMode=prefs.disk_monitor_mode||diskMonitorMode;\n diskMonitorSelectedPath=prefs.disk_monitor_selected_path||'';\n try{ diskMonitorPaths=JSON.parse(prefs.disk_monitor_paths_json||'[]'); }catch(_){ diskMonitorPaths=[]; }\n bootstrapTheme=prefs.bootstrap_theme||bootstrapTheme;\n fontFamily=prefs.font_family||fontFamily;\n interfaceScale=Number(prefs.interface_scale||interfaceScale||100);\n compactTorrentListEnabled=Number(prefs.compact_torrent_list_enabled ?? (compactTorrentListEnabled?1:0))!==0;\n try{ footerItems={...DEFAULT_FOOTER_ITEMS,...JSON.parse(prefs.footer_items_json||'{}')}; }catch(_){ footerItems={...DEFAULT_FOOTER_ITEMS}; }\n }catch(e){ console.warn('Preference load failed', e); }\n if($('portCheckEnabled')) $('portCheckEnabled').checked=portCheckEnabled; if($('automationToastsEnabled')) $('automationToastsEnabled').checked=automationToastsEnabled; if($('smartQueueToastsEnabled')) $('smartQueueToastsEnabled').checked=smartQueueToastsEnabled; if($('easterEggEnabled')) $('easterEggEnabled').checked=easterEggEnabled; if($('easterEggLoadingImageUrl')) $('easterEggLoadingImageUrl').value=easterEggLoadingImageUrl; if($('easterEggClickImageUrl')) $('easterEggClickImageUrl').value=easterEggClickImageUrl; if($('diskMonitorMode')) $('diskMonitorMode').value=diskMonitorMode; if($('diskMonitorSelectedPath')) $('diskMonitorSelectedPath').value=diskMonitorSelectedPath; renderDiskMonitorPaths(); applyInitialLoaderEasterEgg(); scheduleRender(true); applyBootstrapTheme(bootstrapTheme); applyFontFamily(fontFamily); applyInterfaceScale(interfaceScale); applyCompactTorrentList(compactTorrentListEnabled); renderFooterPreferences(); applyFooterPreferences(); await loadPortCheck(false); }\n function updateDiskMonitorUi(){\n // Note: Disk monitor radio switches are mirrored into the shared diskMonitorMode state.\n const mode=['default','selected','aggregate'].includes(diskMonitorMode)?diskMonitorMode:'default';\n if($('diskMonitorMode')) $('diskMonitorMode').value=mode;\n document.querySelectorAll('.disk-monitor-mode').forEach(input=>{ input.checked=input.value===mode; });\n const selectedDisabled=mode!=='selected' || !diskMonitorPaths.length;\n if($('diskMonitorSelectedPath')) $('diskMonitorSelectedPath').disabled=selectedDisabled;\n document.querySelectorAll('.disk-path-select').forEach(btn=>{ btn.disabled=mode==='aggregate'; btn.classList.toggle('active', btn.dataset.path===diskMonitorSelectedPath && mode==='selected'); });\n const hint=$('diskMonitorSelectedHint');\n if(hint){\n hint.textContent=mode==='aggregate' ? 'Aggregate mode uses all monitored paths, so one-path selection is locked.' : mode==='default' ? 'Default mode uses the rTorrent path, custom selection is optional.' : diskMonitorPaths.length ? 'This path drives the footer progress bar.' : 'Add at least one monitored path to use selected mode.';\n }\n }\n function renderDiskMonitorPaths(){\n const select=$('diskMonitorSelectedPath');\n if(select){\n const fallback=diskMonitorPaths.length?'Choose monitored path':'No custom paths yet';\n select.innerHTML=``+diskMonitorPaths.map(p=>``).join('');\n select.value=diskMonitorSelectedPath||'';\n }\n const box=$('diskMonitorPaths');\n if(box){\n box.innerHTML=diskMonitorPaths.length?diskMonitorPaths.map(p=>`
${esc(p)}${p===diskMonitorSelectedPath?'Selected for footer progress':'Used in aggregate tooltip and available for selected mode'}
`).join(''):'
No extra disk paths. Add a path above to monitor another storage directory.
';\n }\n updateDiskMonitorUi();\n }\n async function saveNotificationPrefs(){ automationToastsEnabled=!!$('automationToastsEnabled')?.checked; smartQueueToastsEnabled=!!$('smartQueueToastsEnabled')?.checked; try{ await post('/api/preferences',{automation_toasts_enabled:automationToastsEnabled,smart_queue_toasts_enabled:smartQueueToastsEnabled}); toast('Notification preferences saved','success'); }catch(e){ toast(e.message,'danger'); } }\n async function saveEasterEggPrefs(){ easterEggEnabled=!!$('easterEggEnabled')?.checked; easterEggLoadingImageUrl=String($('easterEggLoadingImageUrl')?.value||'').trim(); easterEggClickImageUrl=String($('easterEggClickImageUrl')?.value||'').trim(); try{ const res=await post('/api/preferences',{easter_egg_enabled:easterEggEnabled,easter_egg_loading_image_url:easterEggLoadingImageUrl,easter_egg_click_image_url:easterEggClickImageUrl}); const prefs=res.preferences||{}; easterEggEnabled=Number(prefs.easter_egg_enabled ?? (easterEggEnabled?1:0))!==0; easterEggLoadingImageUrl=String(prefs.easter_egg_loading_image_url||'').trim(); easterEggClickImageUrl=String(prefs.easter_egg_click_image_url||'').trim(); if($('easterEggEnabled')) $('easterEggEnabled').checked=easterEggEnabled; if($('easterEggLoadingImageUrl')) $('easterEggLoadingImageUrl').value=easterEggLoadingImageUrl; if($('easterEggClickImageUrl')) $('easterEggClickImageUrl').value=easterEggClickImageUrl; applyInitialLoaderEasterEgg(); scheduleRender(true); toast('Easter egg preferences saved','success'); }catch(e){ toast(e.message,'danger'); } }\n async function saveDiskMonitorPrefs(){\n // Note: Disk monitor mode is controlled by radio switches, so keep the in-memory mode instead of reading a removed select.\n const checkedMode=document.querySelector('.disk-monitor-mode:checked')?.value;\n diskMonitorMode=['default','selected','aggregate'].includes(checkedMode) ? checkedMode : (['default','selected','aggregate'].includes(diskMonitorMode) ? diskMonitorMode : 'default');\n diskMonitorSelectedPath=$('diskMonitorSelectedPath')?.value||diskMonitorSelectedPath||'';\n try{\n const res=await post('/api/preferences',{disk_monitor_paths_json:diskMonitorPaths,disk_monitor_mode:diskMonitorMode,disk_monitor_selected_path:diskMonitorSelectedPath});\n const prefs=res.preferences||{};\n // Note: Sync saved values back from the API so the footer uses the persisted disk source, not a stale UI guess.\n diskMonitorMode=prefs.disk_monitor_mode||diskMonitorMode;\n diskMonitorSelectedPath=prefs.disk_monitor_selected_path||diskMonitorSelectedPath||'';\n try{ diskMonitorPaths=JSON.parse(prefs.disk_monitor_paths_json||'[]'); }catch(_){ }\n renderDiskMonitorPaths();\n await refreshUserDiskUsage(true);\n toast('Disk monitor saved','success');\n }catch(e){ toast(e.message,'danger'); }\n }\n async function savePortCheckPref(){ portCheckEnabled=!!$('portCheckEnabled')?.checked; try{ await post('/api/preferences',{port_check_enabled:portCheckEnabled}); toast('Preferences saved','success'); await loadPortCheck(false); }catch(e){ toast(e.message,'danger'); } }\n async function loadPortCheck(force=false){ try{ const res=force?await post('/api/port-check',{}):await (await fetch('/api/port-check')).json(); if(!res.ok) throw new Error(res.error||'Port check failed'); renderPortCheck(res.port_check||{}); }catch(e){ renderPortCheck({status:'error',enabled:portCheckEnabled,error:e.message}); } }\n async function loadAppStatus(){\n const box=$('appStatusManager'); if(!box) return;\n box.innerHTML=' Loading diagnostics...';\n try{\n const [status,poller]=await Promise.all([\n fetch('/api/app/status').then(r=>r.json()),\n fetch('/api/poller/settings').then(r=>r.json()).catch(()=>({}))\n ]);\n if(!status.ok) throw new Error(status.error||'Failed to load diagnostics');\n const st=status.status||{}, py=st.pytorrent||{}, scgi=st.scgi||{}, profile=st.profile||{};\n const rt=poller.runtime||{}, ps=poller.settings||{};\n // Note: App status now keeps only unique operational diagnostics; storage, jobs, planner and queue details stay in their dedicated tools.\n const processCards=[\n diagCard('PID', py.pid),\n diagCard('Uptime', `${py.uptime_seconds||0}s`),\n diagCard('Memory RSS', py.memory_rss_h||py.memory_rss),\n diagCard('Threads', py.threads),\n diagCard('CPU', `${py.cpu_percent ?? '-'}%`),\n diagCard('Python', py.python||'-'),\n diagCard('Worker threads', py.worker_threads ?? '-'),\n diagCard('Jobs total', py.jobs_total ?? '-')\n ];\n const pollerCards=[\n diagCard('Adaptive', ps.adaptive_enabled===false?'off':'on'),\n diagCard('Mode', rt.adaptive_mode||'-'),\n diagCard('Live interval', `${rt.live_stats_interval_seconds ?? ps.live_stats_interval_seconds ?? '-'}s`),\n diagCard('List interval', `${rt.torrent_list_interval_seconds ?? ps.torrent_list_interval_seconds ?? '-'}s`),\n diagCard('Last tick', `${rt.duration_ms||rt.last_tick_ms||0} ms`),\n diagCard('Tick gap', `${rt.last_tick_gap_ms||0} ms`),\n diagCard('Payload', fmtBytes(rt.emitted_payload_size||0)),\n diagCard('rTorrent calls', rt.rtorrent_call_count||0)\n ];\n const connectionCards=[\n diagCard('Active profile', profile.name||profile.id||'-'),\n diagCard('API response time', `${st.api_ms ?? '-'} ms`),\n diagCard('SCGI status', scgi.ok?'OK':'ERROR', scgi.ok?'':'diag-error'),\n diagCard('SCGI URL', scgi.url||'-'),\n diagCard('SCGI connect', scgi.connect_ms!=null?`${scgi.connect_ms} ms`:'-'),\n diagCard('SCGI first byte', scgi.first_byte_ms!=null?`${scgi.first_byte_ms} ms`:'-'),\n diagCard('SCGI total', scgi.total_ms!=null?`${scgi.total_ms} ms`:'-'),\n diagCard('Request bytes', scgi.request_bytes),\n diagCard('Response bytes', scgi.response_bytes),\n diagCard('XML bytes', scgi.xml_bytes),\n diagCard('rTorrent version', scgi.client_version||'-')\n ];\n const panes=[\n ['process','Process', `${diagnosticsSection('pyTorrent process', processCards)}${diagnosticsSection('Runtime poller', pollerCards)}`],\n ['connection','Connection', diagnosticsSection('Profile and rTorrent', connectionCards)]\n ];\n const tabs=`
`;\n if($('appStatusTabs')) $('appStatusTabs').innerHTML=tabs;\n box.innerHTML=`${panes.map((p,i)=>`
${p[2]}
`).join('')}${scgi.error?`
${esc(scgi.error)}
`:''}`;\n }catch(e){ box.innerHTML=`
${esc(e.message)}
`; }\n }\n\n\n\n const TORRENT_STATS_PANE_STORAGE_KEY = 'pytorrent.torrentStatsPane.v1';\n function torrentStatsCard(label, value, note=''){\n return `
${esc(label)}${esc(value ?? '-')}${note?`${esc(note)}`:''}
`;\n }\n function activeTorrentStatsPane(){\n const value=localStorage.getItem(TORRENT_STATS_PANE_STORAGE_KEY)||'overview';\n return ['overview','storage','sources','speed','cache'].includes(value) ? value : 'overview';\n }\n function setTorrentStatsPane(pane){\n const box=$('torrentStatsManager');\n if(!box) return;\n localStorage.setItem(TORRENT_STATS_PANE_STORAGE_KEY, pane);\n box.querySelectorAll('[data-torrentstats-pane]').forEach(x=>x.classList.toggle('active',x.dataset.torrentstatsPane===pane));\n box.querySelectorAll('[data-torrentstats-panel]').forEach(x=>x.classList.toggle('d-none',x.dataset.torrentstatsPanel!==pane));\n }\n function renderTorrentStats(stats={}){\n const box=$('torrentStatsManager');\n if(!box) return;\n const age=Number(stats.age_seconds||0);\n const updated=stats.updated_at ? String(stats.updated_at).replace('T',' ').replace(/\\+00:00$/,' UTC') : '-';\n const active=activeTorrentStatsPane();\n const panes=[\n ['overview','Overview', [\n torrentStatsCard('Torrents', stats.torrent_count, `${stats.complete_count||0} complete / ${stats.incomplete_count||0} incomplete`),\n torrentStatsCard('Sampled', stats.sampled_torrents ?? 0, stats.stale?'cache is stale':'cache is fresh')\n ]],\n ['storage','Storage', [\n torrentStatsCard('Torrent size', stats.total_torrent_size_h || fmtBytes(stats.total_torrent_size)),\n torrentStatsCard('Files size', stats.total_file_size_h || fmtBytes(stats.total_file_size), `${stats.file_count||0} files`)\n ]],\n ['sources','Seeds / peers', [\n torrentStatsCard('Seeds / peers', `${stats.seeds_total||0} / ${stats.peers_total||0}`, 'current sum from last sample')\n ]],\n ['speed','Speed', [\n torrentStatsCard('Speed DL / UL', `${stats.down_rate_total_h||'0 B/s'} / ${stats.up_rate_total_h||'0 B/s'}`)\n ]],\n ['cache','Cache', [\n torrentStatsCard('Updated', updated),\n torrentStatsCard('Age', `${age}s`)\n ]]\n ];\n if($('torrentStatsMeta')) $('torrentStatsMeta').textContent=`Updated: ${updated}, age: ${age}s`;\n const errors=Array.isArray(stats.errors)&&stats.errors.length ? `
File metadata warnings: ${esc(stats.errors.length)} torrent(s). ${esc(stats.error||'')}
` : '';\n box.innerHTML=`
${panes.map(p=>`
${p[2].join('')}
`).join('')}${errors}`;\n }\n async function loadTorrentStats(force=false){\n const box=$('torrentStatsManager');\n if(!box) return;\n box.innerHTML=' Loading torrent statistics...';\n try{\n const j=await (await fetch(`/api/torrent-stats${force?'?force=1':''}`)).json();\n if(!j.ok) throw new Error(j.error||'Torrent statistics failed');\n renderTorrentStats(j.stats||{});\n if(force) toast('Torrent statistics refreshed','success');\n }catch(e){ box.innerHTML=`
${esc(e.message)}
`; }\n }\n\n\n function addToolTab(tool, icon, label, beforeTool='appstatus'){\n if(document.querySelector(`.tool-tab[data-tool=\"${tool}\"]`)) return;\n const nav=document.querySelector('#toolsModal .nav.nav-pills');\n if(!nav) return;\n const li=document.createElement('li');\n li.className='nav-item';\n li.innerHTML=``;\n const before=document.querySelector(`#toolsModal .tool-tab[data-tool=\"${beforeTool}\"]`)?.closest('.nav-item');\n nav.insertBefore(li,before||null);\n li.querySelector('.tool-tab')?.addEventListener('click',()=>activateToolTab(tool));\n }\n function inlineSwitch(id,label='Enable',extraClass=''){\n return ``;\n }\n function plannerToggleRow(id,title,description){\n return `
${title}${description}
${inlineSwitch(id)}
`;\n }\n function plannerSpeedCard(prefix,title,sub){\n return `
\n ${title}\n ${sub}\n
Unlimited
\n
\n \n \n \n \n \n \n
\n
\n \n \n \n \n
\n Slider uses Mbit/s. Numeric fields store B/s for rTorrent.\n
`;\n }\n"; +export const smartQueueSource = " function smartHistoryDetails(row){ try{ return typeof row.details_json==='string'?JSON.parse(row.details_json||'{}'):(row.details_json||{}); }catch(e){ return {}; } }\n function smartQueueToastMessage(r){ const pending=r.start_pending_confirmation?.length||0; const requested=r.start_requested?.length||0; const stopFailed=r.stop_failed?.length||0; const startFailed=r.start_failed?.length||0; const limit=r.max_active_downloads||r.settings?.max_active_downloads||''; const activeBefore=r.active_before; const activeAfter=r.active_after_stop ?? r.active_after_expected; const activeTail=activeBefore!==undefined?`, active ${esc(activeBefore)}->${esc(activeAfter ?? '?')}${limit?`/${esc(limit)}`:''}`:''; const cap=r.rtorrent_cap?.updated?`, cap ${r.rtorrent_cap.current}->${r.rtorrent_cap.new}`:''; const waiting=r.waiting_labeled||0; const stalled=r.stalled_labeled?.length||0; const ignoredSpeed=(r.ignore_speed||r.settings?.ignore_speed)?Number(r.ignored_speed_count||0):0; const tail=pending?`, pending confirm ${pending}`:requested?`, requested ${requested}`:''; const waitTail=waiting?`, waiting labeled ${waiting}`:''; const stalledTail=stalled?`, stalled ${stalled}`:''; const ignoredSpeedTail=(r.ignore_speed||r.settings?.ignore_speed)?`, ignored speed ${ignoredSpeed}`:''; const failTail=`${stopFailed?`, stop failed ${stopFailed}`:''}${startFailed?`, start failed ${startFailed}`:''}`; return `Smart Queue: stopped ${r.stopped?.length||r.paused?.length||0}, started ${r.started?.length||r.resumed?.length||0}${activeTail}${tail}${waitTail}${stalledTail}${ignoredSpeedTail}${failTail}${cap}`; }\n function buildSmartQueueNerdStats(hist=[], totalHistory=0){\n // Note: Small Smart Queue telemetry for automation nerds; it reads history only and does not affect queue behavior.\n const stats=hist.reduce((acc,h)=>{\n const details=smartHistoryDetails(h);\n const stopped=Number(h.paused_count||0);\n const started=Number(h.resumed_count||0);\n const checked=Number(h.checked_count||0);\n const over=Number(details.over_limit||0);\n const stopFailed=Array.isArray(details.stop_failed)?details.stop_failed.length:0;\n acc.checked += checked;\n acc.stopped += stopped;\n acc.started += started;\n acc.overLimit += over;\n acc.stopFailed += stopFailed;\n if(over>0) acc.overEvents += 1;\n return acc;\n },{checked:0,stopped:0,started:0,overLimit:0,overEvents:0,stopFailed:0});\n const latest=hist[0]||null;\n return {...stats,total:Number(totalHistory||hist.length||0),sample:hist.length,latestEvent:smartHistoryDetails(latest||{}).decision||latest?.event||'-',latestAt:latest?.created_at||''};\n }\n\n function renderSmartQueueNerdStats(stats){\n // Note: Compact cards keep the extra diagnostics readable above Automation history without changing the history table.\n if(!stats) return '
No Smart Queue stats yet.
';\n const cards=[\n ['Runs',stats.total,`${stats.sample} loaded`],\n ['Checked',stats.checked,'torrent scans'],\n ['Stopped',stats.stopped,'queue trims'],\n ['Started',stats.started,'queue fills'],\n ['Over limit',stats.overEvents,`${stats.overLimit} total over`],\n ['Stop failed',stats.stopFailed,'rTorrent rejects'],\n ['Latest',stats.latestEvent,stats.latestAt?dateCell(stats.latestAt):'no timestamp'],\n ];\n return `
${cards.map(([label,value,hint])=>`
${esc(label)}${esc(value)}${hint}
`).join('')}
`;\n }\n function formatDurationLeft(seconds){ seconds=Math.max(0,Math.floor(Number(seconds||0))); if(!seconds) return \"ready\"; const m=Math.floor(seconds/60), s=seconds%60; return m?`${m}m ${String(s).padStart(2,\"0\")}s`:`${s}s`; }\n function updateCooldownBadge(id, seconds){\n const el=$(id); if(!el) return;\n const value=Math.max(0,Math.floor(Number(seconds||0)));\n el.dataset.seconds=String(value);\n el.textContent=`next: ${formatDurationLeft(value)}`;\n }\n function tickCooldowns(){\n document.querySelectorAll(\".cooldown-live\").forEach(el=>{\n let v=Math.max(0,Number(el.dataset.seconds||0));\n if(v>0){ v-=1; el.dataset.seconds=String(v); }\n el.textContent=`next: ${formatDurationLeft(v)}`;\n });\n }\n setInterval(tickCooldowns,1000);\n\n function smartQueueTorrentLabel(t){\n const bits=[t.name || t.hash, t.label ? `label: ${t.label}` : '', t.status || '', t.size_h || ''].filter(Boolean);\n return bits.join(' · ');\n }\n function smartQueueExcludedSet(){\n return new Set([...document.querySelectorAll('.smart-exclusion-choice:checked')].map(input=>input.value).filter(Boolean));\n }\n function updateSmartQueueExclusionCounter(){\n // Note: The counter is UI-only and does not change how exceptions are saved.\n const counter=$('smartExclusionCounter');\n if(!counter) return;\n const selected=smartQueueExcludedSet().size;\n const visible=[...document.querySelectorAll('.smart-exclusion-choice-row')].filter(row=>!row.classList.contains('d-none')).length;\n counter.textContent=`${selected} selected · ${visible} visible`;\n }\n function smartQueueVisibleExceptionRows(){\n return [...document.querySelectorAll('.smart-exclusion-choice-row')].filter(row=>!row.classList.contains('d-none'));\n }\n function setSmartQueueVisibleExceptions(checked){\n // Note: Bulk actions affect only visible filtered rows, preserving hidden selections.\n smartQueueVisibleExceptionRows().forEach(row=>{\n const input=row.querySelector('.smart-exclusion-choice');\n if(input) input.checked=checked;\n });\n updateSmartQueueExclusionCounter();\n }\n function renderSmartQueueExclusionChoices(exclusions=[]){\n const list=$('smartExclusionChoiceList');\n if(!list) return;\n const excluded=new Set((exclusions||[]).map(x=>String(x.torrent_hash||'')));\n selectedHashes().forEach(hash=>excluded.add(String(hash)));\n const rows=[...torrents.values()].sort((a,b)=>String(a.name||'').localeCompare(String(b.name||'')));\n const fallback=(exclusions||[])\n .filter(x=>x.torrent_hash && !torrents.has(x.torrent_hash))\n .map(x=>({hash:x.torrent_hash,name:`Missing from current list: ${x.torrent_hash}`,label:x.reason||'manual exception'}));\n const all=[...rows, ...fallback];\n list.innerHTML=all.length ? all.map(t=>{\n const hash=String(t.hash||'');\n const checked=excluded.has(hash) ? 'checked' : '';\n return ``;\n }).join('') : '
No torrents are loaded for this profile.
';\n list.querySelectorAll('.smart-exclusion-choice').forEach(input=>input.addEventListener('change', updateSmartQueueExclusionCounter));\n filterSmartQueueExclusionChoices();\n }\n function filterSmartQueueExclusionChoices(){\n const query=($('smartExclusionSearch')?.value||'').trim().toLowerCase();\n const onlySelected=!!$('smartExclusionOnlySelected')?.checked;\n document.querySelectorAll('.smart-exclusion-choice-row').forEach(row=>{\n const matchesQuery=!query || row.textContent.toLowerCase().includes(query);\n const matchesSelected=!onlySelected || !!row.querySelector('.smart-exclusion-choice')?.checked;\n row.classList.toggle('d-none', !(matchesQuery && matchesSelected));\n });\n updateSmartQueueExclusionCounter();\n }\n async function openSmartQueueExclusionModal(){\n await loadSmartQueue();\n const modalEl=$('smartExclusionModal');\n if(!modalEl) return;\n const current=await fetch('/api/smart-queue?history_limit=1').then(r=>r.json()).catch(()=>({exclusions:[]}));\n if($('smartExclusionOnlySelected')) $('smartExclusionOnlySelected').checked=false;\n renderSmartQueueExclusionChoices(current.exclusions||[]);\n $('smartExclusionSearch')?.focus();\n bootstrap.Modal.getOrCreateInstance(modalEl).show();\n }\n async function saveSmartQueueExclusionChoices(){\n const current=await fetch('/api/smart-queue?history_limit=1').then(r=>r.json()).catch(()=>({exclusions:[]}));\n const before=new Set((current.exclusions||[]).map(x=>String(x.torrent_hash||'')));\n const after=smartQueueExcludedSet();\n const add=[...after].filter(hash=>!before.has(hash));\n const remove=[...before].filter(hash=>!after.has(hash));\n if(!add.length && !remove.length){\n bootstrap.Modal.getInstance($('smartExclusionModal'))?.hide();\n return toast('Smart Queue exceptions unchanged','secondary');\n }\n setBusy(true);\n try{\n for(const hash of add) await post('/api/smart-queue/exclusion',{hash,excluded:true,reason:'manual'});\n for(const hash of remove) await post('/api/smart-queue/exclusion',{hash,excluded:false,reason:'manual'});\n bootstrap.Modal.getInstance($('smartExclusionModal'))?.hide();\n toast('Smart Queue exceptions saved','success');\n await loadSmartQueue();\n }catch(e){\n toast(e.message,'danger');\n }finally{\n setBusy(false);\n }\n }\n async function loadSmartQueue(){\n if($('smartManager')) $('smartManager').innerHTML=loadingMarkup('Loading Smart Queue...');\n if($('smartHistory')) $('smartHistory').innerHTML=loadingMarkup('Loading Smart Queue history...');\n const historyLimit=smartHistoryExpanded?100:10;\n const j=await (await fetch(`/api/smart-queue?history_limit=${historyLimit}`)).json();\n if(!j.ok) return;\n const st=j.settings||{}, ex=j.exclusions||[], hist=j.history||[];\n const totalHistory=Number(j.history_total ?? hist.length);\n if($('smartEnabled')) $('smartEnabled').checked=!!st.enabled;\n if($('smartMaxActive')) $('smartMaxActive').value=st.max_active_downloads||5;\n if($('smartStalled')) $('smartStalled').value=st.stalled_seconds||300;\n if($('smartStopBatch')) $('smartStopBatch').value=st.stop_batch_size||50;\n if($('smartStartGrace')) $('smartStartGrace').value=st.start_grace_seconds||900;\n if($('smartProtectActiveBelowCap')) $('smartProtectActiveBelowCap').checked=st.protect_active_below_cap!==0;\n if($('smartAutoStopIdle')) $('smartAutoStopIdle').checked=!!st.auto_stop_idle;\n if($('smartMinSpeed')) $('smartMinSpeed').value=Math.round((st.min_speed_bytes||0)/1024);\n if($('smartMinSeeds')) $('smartMinSeeds').value=st.min_seeds||1;\n if($('smartMinPeers')) $('smartMinPeers').value=st.min_peers||0;\n if($('smartIgnoreSeedPeer')) $('smartIgnoreSeedPeer').checked=!!st.ignore_seed_peer;\n if($('smartIgnoreSpeed')) $('smartIgnoreSpeed').checked=!!st.ignore_speed;\n if($('smartCooldown')) $('smartCooldown').value=st.cooldown_minutes||10;\n const refillMode=!Number(st.refill_enabled ?? 1) ? 'off' : (Number(st.refill_interval_minutes||0)>0 ? 'custom' : 'auto');\n if($('smartRefillMode')) $('smartRefillMode').value=refillMode;\n if($('smartRefillInterval')) $('smartRefillInterval').value=Number(st.refill_interval_minutes||0)>0 ? st.refill_interval_minutes : 5;\n updateSmartRefillControls();\n updateCooldownBadge('smartCooldownBadge', Number(j.cooldown_remaining_seconds||0));\n if($('smartCooldownHint')) $('smartCooldownHint').textContent=st.enabled ? `Automatic run every ${st.cooldown_minutes||10} minute(s). Manual check ignores cooldown.` : 'Smart Queue is disabled; timer starts after it is enabled and runs once.';\n if($('smartRefillHint')) $('smartRefillHint').textContent=smartRefillHintText(refillMode, Number(st.refill_interval_minutes||0), Number(j.refill_remaining_seconds||0));\n if($('smartManager')){\n const nameForHash=hash=>torrents.get(hash)?.name || hash;\n $('smartManager').innerHTML=ex.length\n ? responsiveTable(['Torrent','Hash','Reason','Created','Action'],ex.map(x=>[esc(nameForHash(x.torrent_hash)),esc(x.torrent_hash),esc(x.reason||''),dateCell(x.created_at),``]),'smart-exclusions-table')\n : '
No Smart Queue exceptions. Use Manage exceptions to choose torrents ignored by Smart Queue.
';\n }\n if($('smartHistory')){\n const body=hist.length\n ? responsiveTable(['Time','Event','Checked','Active','Slot details','Limit','Over','Stopped','Requested','Verified','Pending','Stalled'],hist.map(h=>{\n // Note: Pending and Stalled are separate audit columns so delayed starts and stopped stalled torrents are visible independently.\n const d=smartHistoryDetails(h);\n const activeBefore=d.active_before ?? '-';\n const activeAfter=d.active_after_expected ?? d.active_after_stop ?? '-';\n const limit=d.max_active_downloads ?? '-';\n const requested=Number(d.start_requested_count ?? (d.start_requested||[]).length ?? 0);\n const verified=Number(d.active_verified_count ?? (d.active_verified||[]).length ?? 0);\n const pending=Number(d.pending_confirmation_count ?? (d.start_pending_confirmation||[]).length ?? 0);\n const stalledDetected=Number(d.stalled_detected||0);\n const stalledStopped=Number(d.stalled_stopped||0);\n const stalledProtected=Number(d.protected_stalled||0);\n const stalledText=stalledDetected?`${stalledStopped}/${stalledDetected}${stalledProtected?` protected ${stalledProtected}`:''}`:'-';\n const slotNote=d.cooldown_refill ? `state ${d.active_state_count ?? '-'} / rT active ${d.active_rtorrent_count ?? '-'} / transferring ${d.active_transferring_count ?? '-'}` : '-';\n return [dateCell(h.created_at),esc(d.decision||h.event||'-'),esc(h.checked_count||d.checked||0),esc(`${activeBefore}->${activeAfter}`),esc(slotNote),esc(limit),esc(d.over_limit||0),esc(h.paused_count||0),esc(requested),esc(verified),esc(pending||'-'),esc(stalledText)];\n }),'smart-history-table')\n : '
No Smart Queue operations yet.
';\n const canToggle=totalHistory>10;\n const toggle=canToggle?``:'';\n const clear=totalHistory?``:'';\n $('smartHistory').innerHTML=`${body}${toggle}${clear}`;\n }\n }\n function smartRefillHintText(mode, minutes, remainingSeconds){\n // Note: Refill mode controls only the lightweight slot top-up during cooldown, not the full Smart Queue pass.\n if(mode==='off') return 'Refill is disabled. Smart Queue will only fill slots during full checks or manual checks.';\n if(mode==='custom'){\n const wait=Number(remainingSeconds||0)>0 ? ` Next refill in ${formatDurationLeft(remainingSeconds)}.` : '';\n return `Refill runs at most every ${Math.max(1, Number(minutes||5))} minute(s) while Smart Queue is in cooldown.${wait}`;\n }\n return 'Refill uses the current automatic poller cadence during cooldown, usually about every 2 minutes.';\n }\n function updateSmartRefillControls(){\n const mode=$('smartRefillMode')?.value||'auto';\n const interval=$('smartRefillInterval');\n if(interval) interval.disabled=mode!=='custom';\n }\n async function setSmartException(hashes, excluded, reason='manual'){ const list=[...new Set(hashes||[])].filter(Boolean); if(!list.length) return toastMessage('toast.noTorrentsSelected','warning'); setBusy(true); try{ for(const h of list) await post('/api/smart-queue/exclusion',{hash:h,excluded,reason}); toast(excluded?'Smart Queue exception added':'Smart Queue exception removed','success'); await loadSmartQueue(); }catch(e){toast(e.message,'danger');} finally{setBusy(false);} }\n async function saveSmartQueue(){ await post('/api/smart-queue',{enabled:$('smartEnabled')?.checked,max_active_downloads:$('smartMaxActive')?.value,stalled_seconds:$('smartStalled')?.value,stop_batch_size:$('smartStopBatch')?.value||50,start_grace_seconds:$('smartStartGrace')?.value||900,protect_active_below_cap:$('smartProtectActiveBelowCap')?.checked,auto_stop_idle:$('smartAutoStopIdle')?.checked,min_speed_bytes:Math.round(Number($('smartMinSpeed')?.value||0)*1024),min_seeds:$('smartMinSeeds')?.value,min_peers:$('smartMinPeers')?.value,ignore_seed_peer:$('smartIgnoreSeedPeer')?.checked,ignore_speed:$('smartIgnoreSpeed')?.checked,cooldown_minutes:$('smartCooldown')?.value||10,refill_mode:$('smartRefillMode')?.value||'auto',refill_interval_minutes:$('smartRefillInterval')?.value||5}); toast('Smart Queue saved','success'); await loadSmartQueue(); }\n\n function normalizeRtConfigValue(value, type='text'){\n const raw=String(value ?? '').trim();\n if(type==='bool') return ['1','true','yes','on'].includes(raw.toLowerCase()) ? '1' : '0';\n if(type==='number'){\n if(raw==='') return '0';\n const normalized=Number(raw.replace(',', '.'));\n return Number.isFinite(normalized) ? String(Math.trunc(normalized)) : raw;\n }\n return raw;\n }\n function rtConfigInputValue(input){\n const type=input.dataset.type || rtConfigFieldTypes.get(input.dataset.key) || 'text';\n const value=type==='bool' && input.type==='checkbox' ? (input.checked?'1':'0') : input.value;\n return normalizeRtConfigValue(value, type);\n }\n function rtConfigOriginalValue(input){\n const key=input.dataset.key;\n return normalizeRtConfigValue(input.dataset.original ?? rtConfigOriginal.get(key), input.dataset.type || rtConfigFieldTypes.get(key) || 'text');\n }\n function collectRtConfigChanges(){\n const values={};\n document.querySelectorAll('.rt-config-input').forEach(input=>{\n if(input.disabled) return;\n const cur=rtConfigInputValue(input);\n const orig=rtConfigOriginalValue(input);\n if(cur!==orig) values[input.dataset.key]=cur;\n });\n return values;\n }\n function collectRtConfigClearKeys(){\n const keys=[];\n document.querySelectorAll('.rt-config-input').forEach(input=>{\n if(input.disabled || input.dataset.saved!=='true') return;\n const cur=rtConfigInputValue(input);\n const orig=rtConfigOriginalValue(input);\n if(cur===orig) keys.push(input.dataset.key);\n });\n return keys;\n }\n function updateRtConfigDirty(){\n const changed=collectRtConfigChanges();\n const clearKeys=collectRtConfigClearKeys();\n document.querySelectorAll('.rt-config-input').forEach(input=>{\n const row=input.closest('.rt-config-row');\n if(row) row.classList.toggle('changed', Object.prototype.hasOwnProperty.call(changed,input.dataset.key));\n });\n const configChanges=Object.keys(changed).length;\n const applyChanged=!!$('rtConfigApplyOnStart') && $('rtConfigApplyOnStart').checked!==rtConfigOriginalApplyOnStart;\n const total=configChanges + clearKeys.length + (applyChanged ? 1 : 0);\n if($('rtConfigChangedCount')) $('rtConfigChangedCount').textContent=total?`${total} changed`:'No changes';\n if($('rtConfigGenerateBtn')) $('rtConfigGenerateBtn').disabled=!configChanges;\n if($('rtConfigSaveBtn')) $('rtConfigSaveBtn').disabled=!total;\n }\n function rtConfigHelpText(field){\n const parts = [];\n if(field.description) parts.push(field.description);\n if(field.recommendation) parts.push(`Recommendation: ${field.recommendation}`);\n if(field.error) parts.push(`Runtime note: ${field.error}`);\n return parts.join(' ');\n }\n function rtConfigGroupIntro(group){\n const notes = {\n 'Directories': 'Paths used by rTorrent for downloads, state and runtime context.',\n 'Network': 'Connectivity limits, listening ports and HTTP/XML-RPC behavior.',\n 'Peers': 'Peer discovery and peer count targets for downloading and seeding.',\n 'Throttle': 'Global speed and active slot limits used by the rTorrent scheduler.',\n 'DHT / PEX': 'Distributed peer discovery options; verify private tracker rules before enabling.',\n 'Protocol': 'Advanced peer protocol behavior. Keep defaults unless you know the tracker/network requirement.',\n 'Files': 'Disk, hashing and piece cache behavior. Tune carefully on busy storage.',\n 'System': 'Runtime identity and filesystem permissions.'\n };\n return notes[group] || 'Additional rTorrent runtime settings.';\n }\n function rtConfigFieldState(field){\n if(!field.ok) return 'Unavailable';\n if(field.readonly) return 'Read only';\n if(field.saved) return 'Saved override';\n return 'Live';\n }\n function rtConfigFieldMarkup(field){\n const disabled=(!field.ok||field.readonly)?'disabled':'';\n const type=['bool','number'].includes(field.type)?field.type:'text';\n const originalValue=normalizeRtConfigValue(field.baseline_value ?? field.current_value ?? field.value, type);\n const displayValue=normalizeRtConfigValue(field.saved ? field.saved_value : (field.value ?? field.current_value), type);\n rtConfigOriginal.set(field.key, originalValue);\n rtConfigFieldTypes.set(field.key, type);\n const originalAttr=esc(originalValue);\n const help=rtConfigHelpText(field);\n const valueNote=field.saved?`Reference: ${esc(originalValue)} → saved: ${esc(displayValue)}`:'';\n const input=type==='bool'\n ? `${displayValue==='1'?'On':'Off'}`\n : ``;\n // Note: Help text is exposed only through the question-mark tooltip to avoid duplicated descriptions under every option.\n return ``;\n }\n function renderRtConfigGroups(fields){\n const groups = new Map();\n fields.forEach(field=>{\n const group=field.group||'Other';\n if(!groups.has(group)) groups.set(group, []);\n groups.get(group).push(field);\n });\n return [...groups.entries()].map(([group, items])=>`
${esc(group)}${esc(rtConfigGroupIntro(group))}
${items.map(rtConfigFieldMarkup).join('')}
`).join('');\n }\n\n async function loadRtConfig(){\n const box=$('rtConfigManager');\n if(!box)return;\n box.innerHTML=' Loading config...';\n try{\n const j=await (await fetch('/api/rtorrent-config')).json();\n if(!j.ok) throw new Error(j.error||'Config load failed');\n const fields=j.config?.fields||[];\n rtConfigOriginal=new Map();\n rtConfigFieldTypes=new Map();\n rtConfigOriginalApplyOnStart=!!j.config?.apply_on_start;\n // Note: rTorrent settings are rendered as grouped cards, keeping the old save/reset/generate flow intact while removing the noisy summary block.\n box.innerHTML=`
${renderRtConfigGroups(fields)}
`;\n if($('rtConfigApplyOnStart')) $('rtConfigApplyOnStart').checked=rtConfigOriginalApplyOnStart;\n updateRtConfigDirty();\n document.querySelectorAll('#rtConfigManager [data-bs-toggle=\"tooltip\"]').forEach(el=>bootstrap.Tooltip.getOrCreateInstance(el));\n }catch(e){ box.innerHTML=`
${esc(e.message)}
`; }\n }\n async function saveRtConfig(){\n const values=collectRtConfigChanges();\n const clear_keys=collectRtConfigClearKeys();\n clear_keys.forEach(key=>{\n const input=document.querySelector(`.rt-config-input[data-key=\"${CSS.escape(key)}\"]`);\n if(input) values[key]=rtConfigOriginalValue(input);\n });\n setBusy(true);\n try{\n const j=await post('/api/rtorrent-config',{values,clear_keys,apply_on_start:!!$('rtConfigApplyOnStart')?.checked,apply_now:true});\n toastMessage('toast.rtorrentConfigSaved','success',{updated:j.result?.updated?.length});\n await loadRtConfig();\n }catch(e){\n toast(e.message,'danger');\n } finally{\n setBusy(false);\n }\n }\n async function resetRtConfig(){\n // Note: Reset clears only saved UI overrides, then reloads the live state from rTorrent.\n if(!confirm('Clear all saved rTorrent UI overrides and reload current rTorrent values?')) return;\n setBusy(true);\n try{\n const j=await post('/api/rtorrent-config/reset',{});\n toastMessage('toast.rtorrentConfigReset','success',{removed:j.config?.reset_removed});\n await loadRtConfig();\n }catch(e){\n toast(e.message,'danger');\n } finally{\n setBusy(false);\n }\n }\n async function generateRtConfig(){ const values=collectRtConfigChanges(); try{ const res=await fetch('/api/rtorrent-config/generate',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({values})}); const j=await res.json(); if(!j.ok) throw new Error(j.error||'Generate failed'); if($('rtConfigOutput')) $('rtConfigOutput').value=j.config_text||''; toast('Config generated','success'); }catch(e){ toast(e.message,'danger'); } }\n\n function bootstrapThemeUrl(theme){ /* Note: Themes use the URL map generated by the backend, so they also work offline. */ const key=theme||\"default\"; return window.PYTORRENT?.bootstrapThemeUrls?.[key] || window.PYTORRENT?.bootstrapThemeUrls?.default || \"\"; }\n function applyBootstrapTheme(theme){\n // Note: Custom Bootstrap 2-inspired themes are normal selectable themes and keep light/dark compatibility through data-bs-theme.\n bootstrapTheme = theme || \"default\";\n document.documentElement.dataset.bootstrapSkin = bootstrapTheme;\n const link=$(\"bootstrapThemeStylesheet\");\n if(link) link.href = bootstrapThemeUrl(bootstrapTheme);\n if($(\"bootstrapThemeSelect\")) $(\"bootstrapThemeSelect\").value = bootstrapTheme;\n }\n function applyFontFamily(font){ fontFamily = font || \"default\"; document.documentElement.dataset.appFont = fontFamily; if($(\"fontFamilySelect\")) $(\"fontFamilySelect\").value = fontFamily; }\n function clampInterfaceScale(value){ value = Number(value || 100); if(!Number.isFinite(value)) value = 100; return Math.max(80, Math.min(140, Math.round(value / 5) * 5)); }\n function applyInterfaceScale(value){ interfaceScale = clampInterfaceScale(value); document.documentElement.style.setProperty(\"--ui-scale\", String(interfaceScale / 100)); if($(\"interfaceScaleRange\")) $(\"interfaceScaleRange\").value = interfaceScale; if($(\"interfaceScaleValue\")) $(\"interfaceScaleValue\").textContent = `${interfaceScale}%`; scheduleRender(false); }\n function torrentRowHeight(){ return compactTorrentListEnabled ? COMPACT_ROW_HEIGHT : ROW_HEIGHT; }\n function applyCompactTorrentList(value){\n // Note: The compact switch changes density only; filtering, sorting and existing row actions stay unchanged.\n compactTorrentListEnabled = !!value;\n document.body.classList.toggle(\"compact-torrent-list\", compactTorrentListEnabled);\n if($(\"compactTorrentListEnabled\")) $(\"compactTorrentListEnabled\").checked = compactTorrentListEnabled;\n scheduleRender(true);\n }\n async function saveAppearancePreferences(){ applyBootstrapTheme($(\"bootstrapThemeSelect\")?.value || \"default\"); applyFontFamily($(\"fontFamilySelect\")?.value || \"default\"); const language=String($(\"languageSelect\")?.value || currentLanguage || \"en_US\"); applyInterfaceScale($(\"interfaceScaleRange\")?.value || interfaceScale); applyCompactTorrentList($(\"compactTorrentListEnabled\")?.checked); try{ await post(\"/api/preferences\",{bootstrap_theme:bootstrapTheme,font_family:fontFamily,language,interface_scale:interfaceScale,compact_torrent_list_enabled:compactTorrentListEnabled}); await setLanguage(language); updateLanguageFlagHint(); toast(\"Appearance preferences saved\",\"success\"); }catch(e){ toast(e.message,\"danger\"); } }\n updateLanguageFlagHint();\n $(\"languageSelect\")?.addEventListener('change',()=>{ updateLanguageFlagHint(); saveAppearancePreferences(); });\n if($(\"titleSpeedEnabled\")) $(\"titleSpeedEnabled\").checked=titleSpeedEnabled;\n applyBootstrapTheme(bootstrapTheme);\n applyCompactTorrentList(compactTorrentListEnabled);\n\n function setupPeersRefresh(tab=activeTab()){ clearInterval(peersRefreshTimer); peersRefreshTimer=null; if($('peersRefreshSelect')) $('peersRefreshSelect').value=String(peersRefreshSeconds||0); if(tab==='peers' && peersRefreshSeconds>0){ peersRefreshTimer=setInterval(()=>{ if(activeTab()==='peers' && selectedHash) loadDetails('peers'); }, peersRefreshSeconds*1000); } }\n function refreshPeersOnceForReverseDns(){\n // Note: Reverse DNS can resolve after the first peers fetch, so trigger one silent follow-up even when auto-refresh is disabled.\n if(activeTab()==='peers' && selectedHash){\n loadDetails('peers');\n setTimeout(()=>{ if(activeTab()==='peers' && selectedHash) loadDetails('peers',{silent:true}); }, 1200);\n }\n }\n function syncMobileMode(){ const auto=window.matchMedia&&window.matchMedia(\"(max-width: 900px)\").matches; document.body.classList.toggle(\"mobile-mode\", auto || document.body.classList.contains(\"mobile-mode-manual\")); scheduleRender(true); }\n\n\n let automationRulesCache=[];\n let automationConditions=[];\n let automationEffects=[];\n\n function automationCondition(){\n const type=$('autoConditionType')?.value||'completed';\n const cond={type, negate:!!$('autoCondNegate')?.checked};\n if(type==='no_seeds'){ cond.seeds=Number($('autoCondSeeds')?.value||0); cond.minutes=Number($('autoCondMinutes')?.value||0); }\n if(type==='ratio_gte') cond.ratio=Number($('autoCondRatio')?.value||1);\n // Note: Progress conditions compare the torrent completion percentage stored in the live torrent row.\n if(type==='progress_gte'||type==='progress_lte') cond.progress=Number($('autoCondProgress')?.value||0);\n if(type==='label_missing'||type==='label_has') cond.label=$('autoCondLabel')?.value||'';\n if(type==='status') cond.status=$('autoCondStatus')?.value||'Seeding';\n if(type==='path_contains') cond.text=$('autoCondText')?.value||'';\n return cond;\n }\n\n function automationEffect(){\n const type=$('autoEffectType')?.value||'add_label';\n const eff={type};\n if(type==='move'){\n eff.path=$('autoEffectPath')?.value||'';\n eff.move_data=!!$('autoMoveData')?.checked;\n eff.recheck=!!$('autoMoveRecheck')?.checked;\n eff.keep_seeding=!!$('autoMoveKeepSeeding')?.checked;\n }\n if(type==='add_label'||type==='remove_label') eff.label=$('autoEffectLabel')?.value||'';\n if(type==='set_labels') eff.labels=$('autoEffectLabels')?.value||'';\n return eff;\n }\n\n function updateAutomationForm(){\n const ct=$('autoConditionType')?.value||'';\n document.querySelectorAll('[data-auto-cond]').forEach(el=>el.classList.toggle('d-none', !el.dataset.autoCond.split(',').includes(ct)));\n const et=$('autoEffectType')?.value||'';\n document.querySelectorAll('[data-auto-effect]').forEach(el=>el.classList.toggle('d-none', !el.dataset.autoEffect.split(',').includes(et)));\n }\n\n function conditionText(c={}){\n const base=c.type==='no_seeds'?`seeds <= ${c.seeds||0} for ${c.minutes||0} min`:c.type==='ratio_gte'?`ratio >= ${c.ratio}`:c.type==='progress_gte'?`progress >= ${c.progress||0}%`:c.type==='progress_lte'?`progress <= ${c.progress||0}%`:c.type==='label_missing'?`missing label ${c.label||''}`:c.type==='label_has'?`has label ${c.label||''}`:c.type==='status'?`status = ${c.status||''}`:c.type==='path_contains'?`path contains ${c.text||''}`:'completed';\n return c.negate?`NOT (${base})`:base;\n }\n function effectText(e={}){\n if(e.type==='move'){\n const flags=[];\n if(e.move_data) flags.push('move data');\n if(e.recheck) flags.push('recheck');\n if(e.keep_seeding) flags.push('keep seeding');\n return `move to ${e.path||'default path'}${flags.length?` (${flags.join(', ')})`:''}`;\n }\n return e.type==='add_label'?`add label ${e.label||''}`:e.type==='remove_label'?`remove label ${e.label||''}`:e.type==='set_labels'?`set labels ${e.labels||''}`:e.type;\n }\n function ruleSummary(r){\n const cs=(r.conditions||[]).map(conditionText).join(' + ')||'no conditions';\n const es=(r.effects||[]).map(effectText).join(' → ')||'no actions';\n return `${cs} → ${es}`;\n }\n\n function renderAutomationBuilder(){\n const cBox=$('automationConditionList');\n if(cBox) cBox.innerHTML=automationConditions.length?automationConditions.map((c,i)=>`IF ${esc(conditionText(c))}`).join(''):'No conditions added yet.';\n const eBox=$('automationEffectList');\n if(eBox) eBox.innerHTML=automationEffects.length?automationEffects.map((e,i)=>`${i+1} ${esc(effectText(e))}`).join(''):'No actions added yet.';\n }\n function resetAutomationForm(){\n if($('autoEditId')) $('autoEditId').value='';\n if($('autoName')) $('autoName').value='';\n if($('autoEnabled')) $('autoEnabled').checked=true;\n if($('autoCooldown')) $('autoCooldown').value='60';\n automationConditions=[]; automationEffects=[];\n $('automationCancelEditBtn')?.classList.add('d-none');\n if($('automationSaveBtn')) $('automationSaveBtn').innerHTML=' Save rule';\n renderAutomationBuilder(); updateAutomationForm();\n }\n function editAutomationRule(rule){\n if(!rule) return;\n if($('autoEditId')) $('autoEditId').value=rule.id||'';\n if($('autoName')) $('autoName').value=rule.name||'';\n if($('autoEnabled')) $('autoEnabled').checked=!!rule.enabled;\n if($('autoCooldown')) $('autoCooldown').value=rule.cooldown_minutes ?? 60;\n automationConditions=Array.isArray(rule.conditions)?JSON.parse(JSON.stringify(rule.conditions)):[];\n automationEffects=Array.isArray(rule.effects)?JSON.parse(JSON.stringify(rule.effects)):[];\n $('automationCancelEditBtn')?.classList.remove('d-none');\n if($('automationSaveBtn')) $('automationSaveBtn').innerHTML=' Update rule';\n renderAutomationBuilder();\n }\n\n function summarizeActionObject(a={}){\n if(a.error) return `${esc(a.error)}`;\n const count=a.count || a.result?.count || a.result?.results?.length || '';\n const parts=[];\n if(a.type) parts.push(a.type);\n if(count) parts.push(`${count} torrent(s)`);\n if(a.path) parts.push(a.path);\n if(a.label) parts.push(`label ${a.label}`);\n if(a.labels) parts.push(`labels ${a.labels}`);\n if(a.move_data) parts.push('move data');\n if(a.recheck) parts.push('recheck');\n if(a.keep_seeding) parts.push('keep seeding');\n return `${esc(parts.join(' · ')||'action')}`;\n }\n function automationHistoryActions(raw){\n let actions=[];\n try{ actions=JSON.parse(raw||'[]'); }catch(e){ return `
${esc(raw||'')}
`; }\n if(!Array.isArray(actions)) actions=[actions];\n const summary=actions.map(summarizeActionObject).join(' ');\n const details=esc(JSON.stringify(actions,null,2));\n // Note: Large automation payloads are collapsed so JSON never stretches the modal width.\n return `
${summary||'No actions'}
${details}
`;\n }\n\n function renderAutomationHistory(hist=[]){\n if(!$('automationHistory')) return;\n const toolbar='
';\n const rows=hist.map(h=>[humanDateCell(h.created_at),esc(h.rule_name||''),esc(h.torrent_name||h.torrent_hash||''),automationHistoryActions(h.actions_json||'')]);\n // Note: Automation history uses the shared responsive table wrapper so it stays inside narrow mobile modals.\n const body=hist.length?responsiveTable(['Time','Rule','Torrent / batch','Actions'],rows,'automation-history-table'):'
No automation history yet.
';\n $('automationHistory').innerHTML=toolbar+body;\n }\n\n async function clearAutomationHistory(){\n if(!confirm('Clear automation history?')) return;\n setBusy(true);\n try{ const j=await fetch('/api/automations/history',{method:'DELETE'}).then(r=>r.json()); if(!j.ok) throw new Error(j.error||'Clear automation history failed'); toastMessage('toast.automationLogsDeleted','success',{deleted:j.deleted}); renderAutomationHistory(j.history||[]); }\n catch(e){ toast(e.message,'danger'); }\n finally{ setBusy(false); }\n }\n\n async function exportAutomations(){\n try{ const j=await (await fetch('/api/automations/export')).json(); if(!j.ok) throw new Error(j.error||'Automation export failed'); downloadJson(`pytorrent-automation-rules-${new Date().toISOString().slice(0,10)}.json`, j.export||j); toast(`Exported ${j.count||0} automation rule(s)`,'success'); }\n catch(e){ toast(e.message,'danger'); }\n }\n\n async function importAutomations(file){\n if(!file) return;\n try{ const payload=JSON.parse(await file.text()); const j=await post('/api/automations/import',payload); toast(`Imported ${j.imported||0} automation rule(s)`,'success'); await loadAutomations(); }\n catch(e){ toast(e.message||'Automation import failed','danger'); }\n finally{ if($('automationImportFile')) $('automationImportFile').value=''; }\n }\n\n async function loadAutomations(){\n const j=await fetch('/api/automations').then(r=>r.json());\n const rules=j.rules||[], hist=j.history||[];\n automationRulesCache=rules;\n if($('automationManager')) $('automationManager').innerHTML=rules.length?rules.map(r=>{\n const enabled=!!r.enabled;\n const toggleTitle=enabled?'Disable automation':'Enable automation';\n const toggleIcon=enabled?'fa-toggle-on':'fa-toggle-off';\n const toggleClass=enabled?'btn-outline-warning':'btn-outline-success';\n return `
${esc(r.name)} ${enabled?'on':'off'}
${esc(ruleSummary(r))} · cooldown ${esc(r.cooldown_minutes||0)} min
`;\n }).join(''):'
No automation rules.
';\n renderAutomationHistory(hist);\n }\n\n async function toggleAutomationRule(rule){\n if(!rule) return;\n const payload={...rule, enabled:!rule.enabled};\n // Note: Toggle keeps the rule definition unchanged and only switches automatic execution on or off.\n setBusy(true);\n try{ await post('/api/automations',payload); toast(payload.enabled?'Automation enabled':'Automation disabled','success'); await loadAutomations(); }\n catch(e){ toast(e.message,'danger'); }\n finally{ setBusy(false); }\n }\n\n async function saveAutomation(){\n const currentCond=automationCondition();\n const currentEff=automationEffect();\n const conditions=automationConditions.length?automationConditions:[currentCond];\n const effects=automationEffects.length?automationEffects:[currentEff];\n const payload={id:Number($('autoEditId')?.value||0)||undefined,name:$('autoName')?.value||'Automation rule',enabled:!!$('autoEnabled')?.checked,cooldown_minutes:Number($('autoCooldown')?.value||60),conditions,effects};\n setBusy(true);\n try{ await post('/api/automations',payload); toast(payload.id?'Automation rule updated':'Automation rule saved','success'); resetAutomationForm(); await loadAutomations(); }\n catch(e){toast(e.message,'danger');}\n finally{setBusy(false);}\n }\n\n\n\n function cleanupCountCard(label, value, note=''){\n return `
${esc(label)}${esc(value ?? 0)}${note?`${esc(note)}`:''}
`;\n }\n function cleanupRetentionDaysNote(value){ return `retention ${value || '-'} days`; }\n function cleanupOperationLogRetentionNote(data){\n const settings = data.operation_log_retention || {};\n if(data.retention_labels?.operation_logs) return data.retention_labels.operation_logs;\n if(settings.retention_mode === 'lines') return `retention ${settings.retention_lines || '-'} lines`;\n if(settings.retention_mode === 'both') return `retention ${settings.retention_days || '-'} days and ${settings.retention_lines || '-'} lines`;\n if(settings.retention_mode === 'manual') return 'manual cleanup only';\n return cleanupRetentionDaysNote((data.retention_days || {}).operation_logs);\n }\n function renderCleanup(data={}){\n const box=$('cleanupManager'); if(!box) return;\n const retention=data.retention_days||{};\n const db=data.database||{};\n const cache=data.cache||{};\n const cards=[\n cleanupCountCard('Job logs total', data.jobs_total, cleanupRetentionDaysNote(retention.jobs)),\n cleanupCountCard('Job logs clearable', data.jobs_clearable, 'done / failed / cancelled'),\n cleanupCountCard('Smart Queue logs', data.smart_queue_history_total, cleanupRetentionDaysNote(retention.smart_queue_history)),\n cleanupCountCard('Operation logs', data.operation_logs_total, cleanupOperationLogRetentionNote(data)),\n cleanupCountCard('Planner logs', data.planner_history_total, cleanupRetentionDaysNote(retention.planner_history)),\n cleanupCountCard('Automation logs', data.automation_history_total, cleanupRetentionDaysNote(retention.automation_history)),\n cleanupCountCard('Profile cache rows', cache.profile_rows ?? 0, 'tracker + torrent stats cache'),\n cleanupCountCard('Runtime cache', cache.runtime_items ?? 0, 'memory-only profile cache'),\n cleanupCountCard('Database size', db.size_h||db.size||'-', db.path||'')\n ];\n const poller=data.poller_runtime||{};\n const pollerCards=[\n cleanupCountCard('Live poll counter', poller.live_poll_count ?? 0, 'lightweight speed/status loop'),\n cleanupCountCard('List poll counter', poller.list_poll_count ?? 0, 'full snapshot/diff loop'),\n cleanupCountCard('Poller skipped emits', poller.skipped_emissions ?? 0, 'diagnostic counter only')\n ];\n box.innerHTML=`
${cards.join('')}${pollerCards.join('')}
Profile cacheClears only the active profile runtime/DB cache. It does not remove torrents, rules, settings or logs.
Poller diagnosticsResets in-memory live/list poller counters only. Polling, saved settings and torrent data stay unchanged.
Logs and historyPending and running jobs are preserved. Operation log cleanup removes only profile-scoped log entries.
`;\n }\n async function loadCleanup(){\n const box=$('cleanupManager'); if(!box) return;\n box.innerHTML=' Loading cleanup data...';\n try{\n const j=await (await fetch('/api/cleanup/summary')).json();\n if(!j.ok) throw new Error(j.error||'Cleanup summary failed');\n renderCleanup(j.cleanup||{});\n }catch(e){ box.innerHTML=`
${esc(e.message)}
`; }\n }\n async function runCleanupAction(endpoint, label){\n if(!confirm(`${label}?`)) return;\n setBusy(true);\n try{\n const j=await post(endpoint,{});\n const deleted=typeof j.deleted==='object' ? Object.entries(j.deleted).map(([k,v])=>`${k}: ${v}`).join(', ') : String(j.deleted ?? 0);\n toastMessage('toast.cleanupDone','success',{deleted});\n renderCleanup(j.cleanup||{});\n if(endpoint.includes('/jobs')){ jobsPage=0; loadJobs(0).catch(()=>{}); }\n if(endpoint.includes('/smart-queue') || endpoint.includes('/all')) loadSmartQueue().catch(()=>{});\n if(endpoint.includes('/operation-logs') || endpoint.includes('/all')) loadOperationLogs(true).catch(()=>{});\n if(endpoint.includes('/planner') || endpoint.includes('/all')) loadPlannerPreview().catch(()=>{});\n if(endpoint.includes('/automations') || endpoint.includes('/all')) loadAutomations().catch(()=>{});\n }catch(e){ toast(e.message,'danger'); }\n finally{ setBusy(false); }\n }\n\n function diagCard(label,value,extra=''){ return `
${esc(label)}${esc(value ?? '-')}
`; }\n\n // Note: Centralizes footer visibility so Preferences can hide items without removing existing status logic.\n function applyFooterPreferences(){\n document.querySelectorAll('[data-footer-item]').forEach(el=>{\n const key=el.dataset.footerItem;\n el.classList.toggle('footer-pref-hidden', footerItems[key] === false);\n });\n }\n function renderFooterPreferences(){\n const box=$('footerPreferences');\n if(!box) return;\n box.innerHTML=FOOTER_ITEM_DEFS.map(([key,label])=>``).join('');\n }\n async function saveFooterPreferences(){\n document.querySelectorAll('.footer-pref-toggle').forEach(cb=>{ footerItems[cb.dataset.footerKey] = !!cb.checked; });\n applyFooterPreferences();\n renderFooterPreferences();\n try{ await post('/api/preferences',{footer_items_json:footerItems}); toast('Footer preferences saved','success'); }\n catch(e){ toast(e.message,'danger'); }\n }\n function compactSpeedText(value){\n // Note: The footer has limited space, so it removes spaces only from speed labels.\n return String(value || '0 B/s').replace(/\\s+(?=[KMGT]?i?B\\/s$|B\\/s$)/, '');\n }\n function speedPairText(down, up){\n // Note: Consistent DL/UL pair formatting is used in the footer and diagnostics.\n return `${compactSpeedText(down)} / ${compactSpeedText(up)}`;\n }\n function peakDateText(value){\n // Note: Shortens the ISO timestamp from the database into a readable tooltip label.\n return value ? String(value).replace('T',' ').replace(/\\+00:00$/, ' UTC') : '-';\n }\n function updateSpeedPeaks(peaks={}){\n // Note: Shows the session and all-time record next to current speeds in the footer.\n const session=peaks.session||{};\n const allTime=peaks.all_time||{};\n const sessionText=speedPairText(session.down_h, session.up_h);\n const allTimeText=speedPairText(allTime.down_h, allTime.up_h);\n if($('statPeakSession')) $('statPeakSession').textContent=sessionText;\n if($('statPeakAllTime')) $('statPeakAllTime').textContent=allTimeText;\n const box=$('statusSpeedPeaks');\n if(box){\n box.title=`Peak speed DL/UL\\nSession: ${sessionText}\\nSession DL at: ${peakDateText(session.down_at)}\\nSession UL at: ${peakDateText(session.up_at)}\\nAll-time: ${allTimeText}\\nAll-time DL at: ${peakDateText(allTime.down_at)}\\nAll-time UL at: ${peakDateText(allTime.up_at)}`;\n }\n }\n function browserSpeedSnapshot(){\n // Note: Browser title speed can fall back to the live torrent snapshot when system_stats is delayed or reports zero.\n let down=0, up=0;\n torrents.forEach(t=>{\n down += Number(t.down_rate || 0);\n up += Number(t.up_rate || 0);\n });\n return {down, up, down_h: humanRateLabel(down), up_h: humanRateLabel(up)};\n }\n function humanRateLabel(value){\n const units=['B/s','KiB/s','MiB/s','GiB/s','TiB/s'];\n let n=Math.max(0, Number(value || 0));\n let i=0;\n while(n>=1024 && i=10 || i===0 ? Math.round(n) : n.toFixed(1)} ${units[i]}`;\n }\n function numericSpeed(value){\n // Note: Accepts both raw bytes/s and human labels, so zero checks work for \"0\", \"0 B/s\" and \"0.0 KiB/s\".\n if(typeof value === 'number') return Math.max(0, value);\n const text=String(value ?? '').trim();\n if(!text) return 0;\n const match=text.match(/^([0-9]+(?:\\.[0-9]+)?)\\s*(B\\/s|KiB\\/s|MiB\\/s|GiB\\/s|TiB\\/s)?$/i);\n if(!match) return 0;\n const units=['B/s','KiB/s','MiB/s','GiB/s','TiB/s'];\n const unit=(match[2] || 'B/s').replace(/kib/i,'KiB').replace(/mib/i,'MiB').replace(/gib/i,'GiB').replace(/tib/i,'TiB').replace(/b\\/s/i,'B/s');\n return Number(match[1] || 0) * Math.pow(1024, Math.max(0, units.indexOf(unit)));\n }\n function applyLiveSpeedStats(stats={}){\n // Note: Fast-poller speed updates drive the tab title and peak speed UI without waiting for system_stats.\n const downRaw=Number(stats.down_rate || 0);\n const upRaw=Number(stats.up_rate || 0);\n const downH=stats.down_rate_h || humanRateLabel(downRaw);\n const upH=stats.up_rate_h || humanRateLabel(upRaw);\n if($('statDl')) $('statDl').textContent=downH || '0 B/s';\n if($('statUl')) $('statUl').textContent=upH || '0 B/s';\n if($('mobileSpeedDl')) $('mobileSpeedDl').textContent=downH || '0 B/s';\n if($('mobileSpeedUl')) $('mobileSpeedUl').textContent=upH || '0 B/s';\n if(stats.speed_peaks) updateSpeedPeaks(stats.speed_peaks);\n updateBrowserSpeedTitle(downH, upH, downRaw, upRaw);\n }\n function updateBrowserSpeedTitle(downH, upH, downRaw=null, upRaw=null){\n // Note: Keeps the browser tab title accurate even when system_stats is delayed or reports a stale zero.\n const fallback=browserSpeedSnapshot();\n const downValue=downRaw == null ? numericSpeed(downH) : Number(downRaw || 0);\n const upValue=upRaw == null ? numericSpeed(upH) : Number(upRaw || 0);\n const useFallbackDown=(downH == null || (downValue <= 0 && fallback.down>0));\n const useFallbackUp=(upH == null || (upValue <= 0 && fallback.up>0));\n lastBrowserSpeed.down=useFallbackDown ? fallback.down_h : (downH || '0 B/s');\n lastBrowserSpeed.up=useFallbackUp ? fallback.up_h : (upH || '0 B/s');\n const speedTitle=`DL ${lastBrowserSpeed.down} / UL ${lastBrowserSpeed.up}`;\n document.title=titleSpeedEnabled ? `${speedTitle} - ${BASE_TITLE}` : BASE_TITLE;\n try{ window.status=titleSpeedEnabled ? speedTitle : ''; }catch(e){}\n }\n async function saveTitleSpeedPreference(){\n // Note: The change applies immediately and is saved as a user preference.\n titleSpeedEnabled=!!$('titleSpeedEnabled')?.checked;\n updateBrowserSpeedTitle();\n try{ await post('/api/preferences',{title_speed_enabled:titleSpeedEnabled}); toast('Browser title speed saved','success'); }\n catch(e){ toast(e.message,'danger'); }\n }\n async function saveTrackerFaviconsPreference(){\n // Note: Tracker favicon toggle changes only icon rendering; tracker filter counts and actions stay untouched.\n trackerFaviconsEnabled=!!$('trackerFaviconsEnabled')?.checked;\n renderTrackerFilters();\n try{ await post('/api/preferences',{tracker_favicons_enabled:trackerFaviconsEnabled}); toast('Tracker favicon preference saved','success'); }\n catch(e){ toast(e.message,'danger'); }\n }\n async function saveReverseDnsPreference(){\n // Note: Reverse DNS remains opt-in and refreshes only the peers pane, leaving other torrent data untouched.\n reverseDnsEnabled=!!$('reverseDnsEnabled')?.checked;\n try{ await post('/api/preferences',{reverse_dns_enabled:reverseDnsEnabled}); refreshPeersOnceForReverseDns(); toast('Reverse DNS preference saved','success'); }\n catch(e){ toast(e.message,'danger'); }\n }\n function updateFooterClock(){\n const el=$('statClock');\n if(el) el.textContent=new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit', second:'2-digit'});\n }\n function updateSocketStatus(s={}){\n const el=$('statSockets');\n if(!el) return;\n const open=s.open_sockets;\n const max=s.max_open_sockets;\n el.textContent=open == null ? '-' : (max == null ? String(open) : `${open}/${max}`);\n const box=$('statusSockets');\n if(box) box.title=open == null ? 'Open sockets unavailable from this rTorrent build' : `Open rTorrent sockets${max == null ? '' : ' / max'}: ${el.textContent}`;\n }\n\n function portStatusLabel(st){ return st==='open'?'open':st==='closed'?'closed':st==='disabled'?'disabled':st==='error'?'error':'unknown'; }\n function portStatusClass(st){ return st==='open'?'port-ok':st==='closed'?'port-bad':'port-secondary'; }\n function portStatusIcon(st){ return st==='open'?'fa-circle-check':st==='closed'?'fa-circle-xmark':'fa-circle-question'; }\n function portStatusBadge(data={},attrs='',withPort=false){ const st=portStatusLabel(data.status); const active=data.open_port||data.port; const port=active?String(active):'-'; const label=withPort?`Port ${port} ${st}`:st; return ` ${esc(label)}`; }\n function portCheckedAt(data={}){ if(data.checked_at) return String(data.checked_at).replace('T',' ').replace(/\\+00:00$/,' UTC'); if(data.checked_at_epoch) return new Date(Number(data.checked_at_epoch)*1000).toLocaleString(); return ''; }\n function portCheckDetails(data={}){ const bits=[]; if(data.open_port) bits.push(`Open port: ${data.open_port}`); else if(data.port) bits.push(`First port: ${data.port}`); if(Array.isArray(data.ports)&&data.ports.length>1) bits.push(`Candidates: ${data.ports.join(', ')}`); if(Array.isArray(data.checked_ports)&&data.checked_ports.length) bits.push(`Checked: ${data.checked_ports.join(', ')}`); if(data.ports_truncated) bits.push('Port list truncated to safety limit'); if(data.public_ip) bits.push(`Public IP: ${data.public_ip}`); if(data.remote) bits.push('Remote profile'); if(data.source) bits.push(`Source: ${data.source}`); const checked=portCheckedAt(data); if(checked) bits.push(`Last check: ${checked}`); if(data.cached) bits.push('Cached result'); if(data.error) bits.push(data.error); if(data.fallback_error) bits.push(data.fallback_error); return bits; }\n function renderPortCheck(data={}){\n if($('portCheckEnabled')) $('portCheckEnabled').checked=!!data.enabled;\n const details=portCheckDetails(data);\n const title=details.join(' · ') || 'Port check disabled';\n if($('portCheckBadge')) $('portCheckBadge').outerHTML=portStatusBadge(data,'id=\"portCheckBadge\" ');\n if($('portCheckInfo')) $('portCheckInfo').textContent=details.join(' · ') || 'Uses YouGetSignal first. Manual check bypasses the 6h cache.';\n if($('statusPortCheck')){\n $('statusPortCheck').classList.toggle('d-none', !data.enabled);\n $('statusPortCheck').title=title;\n }\n if($('statusPortCheckBadge')) $('statusPortCheckBadge').outerHTML=portStatusBadge(data,'id=\"statusPortCheckBadge\" ',true);\n }\n async function loadPreferences(){\n try{\n const j=await (await fetch(`/api/preferences?_=${Date.now()}`, {cache:'no-store'})).json();\n const prefs=j.preferences||{};\n portCheckEnabled=!!Number(prefs.port_check_enabled ?? portCheckEnabled);\n reverseDnsEnabled=!!Number(prefs.reverse_dns_enabled ?? (reverseDnsEnabled?1:0));\n if($('reverseDnsEnabled')) $('reverseDnsEnabled').checked=reverseDnsEnabled;\n automationToastsEnabled=Number(prefs.automation_toasts_enabled ?? (automationToastsEnabled?1:0))!==0;\n smartQueueToastsEnabled=Number(prefs.smart_queue_toasts_enabled ?? (smartQueueToastsEnabled?1:0))!==0;\n if($('languageSelect')) $('languageSelect').value=String(prefs.language || currentLanguage || 'en_US');\n updateLanguageFlagHint();\n easterEggEnabled=Number(prefs.easter_egg_enabled ?? (easterEggEnabled?1:0))!==0;\n easterEggLoadingImageUrl=String(prefs.easter_egg_loading_image_url ?? easterEggLoadingImageUrl ?? '').trim();\n easterEggClickImageUrl=String(prefs.easter_egg_click_image_url ?? easterEggClickImageUrl ?? '').trim();\n diskMonitorMode=prefs.disk_monitor_mode||diskMonitorMode;\n diskMonitorSelectedPath=prefs.disk_monitor_selected_path||'';\n try{ diskMonitorPaths=JSON.parse(prefs.disk_monitor_paths_json||'[]'); }catch(_){ diskMonitorPaths=[]; }\n bootstrapTheme=prefs.bootstrap_theme||bootstrapTheme;\n fontFamily=prefs.font_family||fontFamily;\n interfaceScale=Number(prefs.interface_scale||interfaceScale||100);\n compactTorrentListEnabled=Number(prefs.compact_torrent_list_enabled ?? (compactTorrentListEnabled?1:0))!==0;\n try{ footerItems={...DEFAULT_FOOTER_ITEMS,...JSON.parse(prefs.footer_items_json||'{}')}; }catch(_){ footerItems={...DEFAULT_FOOTER_ITEMS}; }\n }catch(e){ console.warn('Preference load failed', e); }\n if($('portCheckEnabled')) $('portCheckEnabled').checked=portCheckEnabled; if($('automationToastsEnabled')) $('automationToastsEnabled').checked=automationToastsEnabled; if($('smartQueueToastsEnabled')) $('smartQueueToastsEnabled').checked=smartQueueToastsEnabled; if($('easterEggEnabled')) $('easterEggEnabled').checked=easterEggEnabled; if($('easterEggLoadingImageUrl')) $('easterEggLoadingImageUrl').value=easterEggLoadingImageUrl; if($('easterEggClickImageUrl')) $('easterEggClickImageUrl').value=easterEggClickImageUrl; if($('diskMonitorMode')) $('diskMonitorMode').value=diskMonitorMode; if($('diskMonitorSelectedPath')) $('diskMonitorSelectedPath').value=diskMonitorSelectedPath; renderDiskMonitorPaths(); applyInitialLoaderEasterEgg(); scheduleRender(true); applyBootstrapTheme(bootstrapTheme); applyFontFamily(fontFamily); applyInterfaceScale(interfaceScale); applyCompactTorrentList(compactTorrentListEnabled); renderFooterPreferences(); applyFooterPreferences(); await loadPortCheck(false); }\n function updateDiskMonitorUi(){\n // Note: Disk monitor radio switches are mirrored into the shared diskMonitorMode state.\n const mode=['default','selected','aggregate'].includes(diskMonitorMode)?diskMonitorMode:'default';\n if($('diskMonitorMode')) $('diskMonitorMode').value=mode;\n document.querySelectorAll('.disk-monitor-mode').forEach(input=>{ input.checked=input.value===mode; });\n const selectedDisabled=mode!=='selected' || !diskMonitorPaths.length;\n if($('diskMonitorSelectedPath')) $('diskMonitorSelectedPath').disabled=selectedDisabled;\n document.querySelectorAll('.disk-path-select').forEach(btn=>{ btn.disabled=mode==='aggregate'; btn.classList.toggle('active', btn.dataset.path===diskMonitorSelectedPath && mode==='selected'); });\n const hint=$('diskMonitorSelectedHint');\n if(hint){\n hint.textContent=mode==='aggregate' ? 'Aggregate mode uses all monitored paths, so one-path selection is locked.' : mode==='default' ? 'Default mode uses the rTorrent path, custom selection is optional.' : diskMonitorPaths.length ? 'This path drives the footer progress bar.' : 'Add at least one monitored path to use selected mode.';\n }\n }\n function renderDiskMonitorPaths(){\n const select=$('diskMonitorSelectedPath');\n if(select){\n const fallback=diskMonitorPaths.length?'Choose monitored path':'No custom paths yet';\n select.innerHTML=``+diskMonitorPaths.map(p=>``).join('');\n select.value=diskMonitorSelectedPath||'';\n }\n const box=$('diskMonitorPaths');\n if(box){\n box.innerHTML=diskMonitorPaths.length?diskMonitorPaths.map(p=>`
${esc(p)}${p===diskMonitorSelectedPath?'Selected for footer progress':'Used in aggregate tooltip and available for selected mode'}
`).join(''):'
No extra disk paths. Add a path above to monitor another storage directory.
';\n }\n updateDiskMonitorUi();\n }\n async function saveNotificationPrefs(){ automationToastsEnabled=!!$('automationToastsEnabled')?.checked; smartQueueToastsEnabled=!!$('smartQueueToastsEnabled')?.checked; try{ await post('/api/preferences',{automation_toasts_enabled:automationToastsEnabled,smart_queue_toasts_enabled:smartQueueToastsEnabled}); toast('Notification preferences saved','success'); }catch(e){ toast(e.message,'danger'); } }\n async function saveEasterEggPrefs(){ easterEggEnabled=!!$('easterEggEnabled')?.checked; easterEggLoadingImageUrl=String($('easterEggLoadingImageUrl')?.value||'').trim(); easterEggClickImageUrl=String($('easterEggClickImageUrl')?.value||'').trim(); try{ const res=await post('/api/preferences',{easter_egg_enabled:easterEggEnabled,easter_egg_loading_image_url:easterEggLoadingImageUrl,easter_egg_click_image_url:easterEggClickImageUrl}); const prefs=res.preferences||{}; easterEggEnabled=Number(prefs.easter_egg_enabled ?? (easterEggEnabled?1:0))!==0; easterEggLoadingImageUrl=String(prefs.easter_egg_loading_image_url||'').trim(); easterEggClickImageUrl=String(prefs.easter_egg_click_image_url||'').trim(); if($('easterEggEnabled')) $('easterEggEnabled').checked=easterEggEnabled; if($('easterEggLoadingImageUrl')) $('easterEggLoadingImageUrl').value=easterEggLoadingImageUrl; if($('easterEggClickImageUrl')) $('easterEggClickImageUrl').value=easterEggClickImageUrl; applyInitialLoaderEasterEgg(); scheduleRender(true); toast('Easter egg preferences saved','success'); }catch(e){ toast(e.message,'danger'); } }\n async function saveDiskMonitorPrefs(){\n // Note: Disk monitor mode is controlled by radio switches, so keep the in-memory mode instead of reading a removed select.\n const checkedMode=document.querySelector('.disk-monitor-mode:checked')?.value;\n diskMonitorMode=['default','selected','aggregate'].includes(checkedMode) ? checkedMode : (['default','selected','aggregate'].includes(diskMonitorMode) ? diskMonitorMode : 'default');\n diskMonitorSelectedPath=$('diskMonitorSelectedPath')?.value||diskMonitorSelectedPath||'';\n try{\n const res=await post('/api/preferences',{disk_monitor_paths_json:diskMonitorPaths,disk_monitor_mode:diskMonitorMode,disk_monitor_selected_path:diskMonitorSelectedPath});\n const prefs=res.preferences||{};\n // Note: Sync saved values back from the API so the footer uses the persisted disk source, not a stale UI guess.\n diskMonitorMode=prefs.disk_monitor_mode||diskMonitorMode;\n diskMonitorSelectedPath=prefs.disk_monitor_selected_path||diskMonitorSelectedPath||'';\n try{ diskMonitorPaths=JSON.parse(prefs.disk_monitor_paths_json||'[]'); }catch(_){ }\n renderDiskMonitorPaths();\n await refreshUserDiskUsage(true);\n toast('Disk monitor saved','success');\n }catch(e){ toast(e.message,'danger'); }\n }\n async function savePortCheckPref(){ portCheckEnabled=!!$('portCheckEnabled')?.checked; try{ await post('/api/preferences',{port_check_enabled:portCheckEnabled}); toast('Preferences saved','success'); await loadPortCheck(false); }catch(e){ toast(e.message,'danger'); } }\n async function loadPortCheck(force=false){ try{ const res=force?await post('/api/port-check',{}):await (await fetch('/api/port-check')).json(); if(!res.ok) throw new Error(res.error||'Port check failed'); renderPortCheck(res.port_check||{}); }catch(e){ renderPortCheck({status:'error',enabled:portCheckEnabled,error:e.message}); } }\n async function loadAppStatus(){\n const box=$('appStatusManager'); if(!box) return;\n box.innerHTML=' Loading diagnostics...';\n try{\n const [status,poller]=await Promise.all([\n fetch('/api/app/status').then(r=>r.json()),\n fetch('/api/poller/settings').then(r=>r.json()).catch(()=>({}))\n ]);\n if(!status.ok) throw new Error(status.error||'Failed to load diagnostics');\n const st=status.status||{}, py=st.pytorrent||{}, scgi=st.scgi||{}, profile=st.profile||{};\n const rt=poller.runtime||{}, ps=poller.settings||{};\n // Note: App status now keeps only unique operational diagnostics; storage, jobs, planner and queue details stay in their dedicated tools.\n const processCards=[\n diagCard('PID', py.pid),\n diagCard('Uptime', `${py.uptime_seconds||0}s`),\n diagCard('Memory RSS', py.memory_rss_h||py.memory_rss),\n diagCard('Threads', py.threads),\n diagCard('CPU', `${py.cpu_percent ?? '-'}%`),\n diagCard('Python', py.python||'-'),\n diagCard('Worker threads', py.worker_threads ?? '-'),\n diagCard('Jobs total', py.jobs_total ?? '-')\n ];\n const pollerCards=[\n diagCard('Adaptive', ps.adaptive_enabled===false?'off':'on'),\n diagCard('Mode', rt.adaptive_mode||'-'),\n diagCard('Live interval', `${rt.live_stats_interval_seconds ?? ps.live_stats_interval_seconds ?? '-'}s`),\n diagCard('List interval', `${rt.torrent_list_interval_seconds ?? ps.torrent_list_interval_seconds ?? '-'}s`),\n diagCard('Last tick', `${rt.duration_ms||rt.last_tick_ms||0} ms`),\n diagCard('Tick gap', `${rt.last_tick_gap_ms||0} ms`),\n diagCard('Payload', fmtBytes(rt.emitted_payload_size||0)),\n diagCard('rTorrent calls', rt.rtorrent_call_count||0)\n ];\n const connectionCards=[\n diagCard('Active profile', profile.name||profile.id||'-'),\n diagCard('API response time', `${st.api_ms ?? '-'} ms`),\n diagCard('SCGI status', scgi.ok?'OK':'ERROR', scgi.ok?'':'diag-error'),\n diagCard('SCGI URL', scgi.url||'-'),\n diagCard('SCGI connect', scgi.connect_ms!=null?`${scgi.connect_ms} ms`:'-'),\n diagCard('SCGI first byte', scgi.first_byte_ms!=null?`${scgi.first_byte_ms} ms`:'-'),\n diagCard('SCGI total', scgi.total_ms!=null?`${scgi.total_ms} ms`:'-'),\n diagCard('Request bytes', scgi.request_bytes),\n diagCard('Response bytes', scgi.response_bytes),\n diagCard('XML bytes', scgi.xml_bytes),\n diagCard('rTorrent version', scgi.client_version||'-')\n ];\n const panes=[\n ['process','Process', `${diagnosticsSection('pyTorrent process', processCards)}${diagnosticsSection('Runtime poller', pollerCards)}`],\n ['connection','Connection', diagnosticsSection('Profile and rTorrent', connectionCards)]\n ];\n const tabs=`
    ${panes.map((p,i)=>`
  • `).join('')}
`;\n if($('appStatusTabs')) $('appStatusTabs').innerHTML=tabs;\n box.innerHTML=`${panes.map((p,i)=>`
${p[2]}
`).join('')}${scgi.error?`
${esc(scgi.error)}
`:''}`;\n }catch(e){ box.innerHTML=`
${esc(e.message)}
`; }\n }\n\n\n\n const TORRENT_STATS_PANE_STORAGE_KEY = 'pytorrent.torrentStatsPane.v1';\n function torrentStatsCard(label, value, note=''){\n return `
${esc(label)}${esc(value ?? '-')}${note?`${esc(note)}`:''}
`;\n }\n function activeTorrentStatsPane(){\n const value=localStorage.getItem(TORRENT_STATS_PANE_STORAGE_KEY)||'overview';\n return ['overview','storage','sources','speed','cache'].includes(value) ? value : 'overview';\n }\n function setTorrentStatsPane(pane){\n const box=$('torrentStatsManager');\n if(!box) return;\n localStorage.setItem(TORRENT_STATS_PANE_STORAGE_KEY, pane);\n box.querySelectorAll('[data-torrentstats-pane]').forEach(x=>x.classList.toggle('active',x.dataset.torrentstatsPane===pane));\n box.querySelectorAll('[data-torrentstats-panel]').forEach(x=>x.classList.toggle('d-none',x.dataset.torrentstatsPanel!==pane));\n }\n function renderTorrentStats(stats={}){\n const box=$('torrentStatsManager');\n if(!box) return;\n const age=Number(stats.age_seconds||0);\n const updated=stats.updated_at ? String(stats.updated_at).replace('T',' ').replace(/\\+00:00$/,' UTC') : '-';\n const active=activeTorrentStatsPane();\n const panes=[\n ['overview','Overview', [\n torrentStatsCard('Torrents', stats.torrent_count, `${stats.complete_count||0} complete / ${stats.incomplete_count||0} incomplete`),\n torrentStatsCard('Sampled', stats.sampled_torrents ?? 0, stats.stale?'cache is stale':'cache is fresh')\n ]],\n ['storage','Storage', [\n torrentStatsCard('Torrent size', stats.total_torrent_size_h || fmtBytes(stats.total_torrent_size)),\n torrentStatsCard('Files size', stats.total_file_size_h || fmtBytes(stats.total_file_size), `${stats.file_count||0} files`)\n ]],\n ['sources','Seeds / peers', [\n torrentStatsCard('Seeds / peers', `${stats.seeds_total||0} / ${stats.peers_total||0}`, 'current sum from last sample')\n ]],\n ['speed','Speed', [\n torrentStatsCard('Speed DL / UL', `${stats.down_rate_total_h||'0 B/s'} / ${stats.up_rate_total_h||'0 B/s'}`)\n ]],\n ['cache','Cache', [\n torrentStatsCard('Updated', updated),\n torrentStatsCard('Age', `${age}s`)\n ]]\n ];\n if($('torrentStatsMeta')) $('torrentStatsMeta').textContent=`Updated: ${updated}, age: ${age}s`;\n const errors=Array.isArray(stats.errors)&&stats.errors.length ? `
File metadata warnings: ${esc(stats.errors.length)} torrent(s). ${esc(stats.error||'')}
` : '';\n box.innerHTML=`
    ${panes.map(p=>`
  • `).join('')}
${panes.map(p=>`
${p[2].join('')}
`).join('')}${errors}`;\n }\n async function loadTorrentStats(force=false){\n const box=$('torrentStatsManager');\n if(!box) return;\n box.innerHTML=' Loading torrent statistics...';\n try{\n const j=await (await fetch(`/api/torrent-stats${force?'?force=1':''}`)).json();\n if(!j.ok) throw new Error(j.error||'Torrent statistics failed');\n renderTorrentStats(j.stats||{});\n if(force) toast('Torrent statistics refreshed','success');\n }catch(e){ box.innerHTML=`
${esc(e.message)}
`; }\n }\n\n\n function addToolTab(tool, icon, label, beforeTool='appstatus'){\n if(document.querySelector(`.tool-tab[data-tool=\"${tool}\"]`)) return;\n const nav=document.querySelector('#toolsModal .nav.nav-pills');\n if(!nav) return;\n const li=document.createElement('li');\n li.className='nav-item';\n li.innerHTML=``;\n const before=document.querySelector(`#toolsModal .tool-tab[data-tool=\"${beforeTool}\"]`)?.closest('.nav-item');\n nav.insertBefore(li,before||null);\n li.querySelector('.tool-tab')?.addEventListener('click',()=>activateToolTab(tool));\n }\n function inlineSwitch(id,label='Enable',extraClass=''){\n return ``;\n }\n function plannerToggleRow(id,title,description){\n return `
${title}${description}
${inlineSwitch(id)}
`;\n }\n function plannerSpeedCard(prefix,title,sub){\n return `
\n ${title}\n ${sub}\n
Unlimited
\n
\n \n \n \n \n \n \n
\n
\n \n \n \n \n
\n Slider uses Mbit/s. Numeric fields store B/s for rTorrent.\n
`;\n }\n"; diff --git a/pytorrent/static/libs/pytorrent-themes/bootstrap5-soft/bootstrap.min.css b/pytorrent/static/libs/pytorrent-themes/bootstrap5-soft/bootstrap.min.css deleted file mode 100644 index bebe9a0..0000000 --- a/pytorrent/static/libs/pytorrent-themes/bootstrap5-soft/bootstrap.min.css +++ /dev/null @@ -1,146 +0,0 @@ -/* Note: Bootstrap 5 Soft keeps the modern variable palette with stronger action hover contrast. */ -:root { - --bs-border-radius: .5rem; - --bs-border-radius-sm: .375rem; - --bs-border-radius-lg: .75rem; - --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; -} - -[data-bs-theme="light"] { - --bs-body-bg: #f6f8fb; - --bs-body-color: #1f2937; - --bs-primary: #0d6efd; - --bs-primary-rgb: 13, 110, 253; - --bs-success: #198754; - --bs-danger: #dc3545; - --bs-warning: #ffc107; - --bs-info: #0dcaf0; - --bs-secondary-bg: #edf2f7; - --bs-secondary-bg-rgb: 237, 242, 247; - --bs-secondary-color: #64748b; - --bs-tertiary-bg: #ffffff; - --bs-border-color: #d9e2ec; - --bs-link-color: #0d6efd; -} - -[data-bs-theme="dark"] { - --bs-body-bg: #101827; - --bs-body-color: #e5e7eb; - --bs-primary: #60a5fa; - --bs-primary-rgb: 96, 165, 250; - --bs-success: #34d399; - --bs-danger: #f87171; - --bs-warning: #fbbf24; - --bs-info: #22d3ee; - --bs-secondary-bg: #1e293b; - --bs-secondary-bg-rgb: 30, 41, 59; - --bs-secondary-color: #cbd5e1; - --bs-tertiary-bg: #172033; - --bs-border-color: #334155; - --bs-link-color: #93c5fd; -} - -.card, -.surface-section, -.modal-content, -.dropdown-menu { - border-radius: .75rem; - box-shadow: 0 .35rem 1rem rgba(15, 23, 42, .08); -} - -.btn { - border-radius: .5rem; -} - -.btn-primary:hover, -.btn-primary:focus-visible { - background-color: #0b5ed7; - border-color: #0a58ca; -} - -[data-bs-theme="dark"] .btn-primary:hover, -[data-bs-theme="dark"] .btn-primary:focus-visible { - background-color: #3b82f6; - border-color: #2563eb; -} - -.nav-pills .nav-link.active, -.nav-pills .show > .nav-link { - background-color: var(--bs-primary); - color: #ffffff; -} - -.btn { - border-width: 1px; - font-weight: 600; - transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease, color .15s ease, filter .15s ease; -} - -.btn:hover, -.btn:focus-visible { - filter: none; - text-decoration: none; -} - -.btn-primary, -.btn-success, -.btn-danger, -.btn-warning, -.btn-info { - color: #ffffff; -} - -.btn-outline-primary, -.btn-outline-success, -.btn-outline-danger, -.btn-outline-warning, -.btn-outline-info, -.btn-outline-secondary { - background-color: var(--bs-body-bg); -} - -.btn-outline-primary:hover, -.btn-outline-primary:focus-visible { - background-color: var(--bs-primary); - border-color: var(--bs-primary); - color: #ffffff; -} - -.btn-outline-secondary:hover, -.btn-outline-secondary:focus-visible { - background-color: var(--bs-secondary-color); - border-color: var(--bs-secondary-color); - color: var(--bs-body-bg); -} - -.btn-outline-success:hover, -.btn-outline-success:focus-visible { - background-color: var(--bs-success); - border-color: var(--bs-success); - color: #ffffff; -} - -.btn-outline-danger:hover, -.btn-outline-danger:focus-visible { - background-color: var(--bs-danger); - border-color: var(--bs-danger); - color: #ffffff; -} - -.btn-outline-warning:hover, -.btn-outline-warning:focus-visible { - background-color: var(--bs-warning); - border-color: var(--bs-warning); - color: #111111; -} - -.btn-outline-info:hover, -.btn-outline-info:focus-visible { - background-color: var(--bs-info); - border-color: var(--bs-info); - color: #111111; -} - -.btn:focus-visible { - box-shadow: 0 0 0 .2rem rgba(var(--bs-primary-rgb), .32); -} diff --git a/pytorrent/static/styles.css b/pytorrent/static/styles.css index e4de0ec..efc6493 100644 --- a/pytorrent/static/styles.css +++ b/pytorrent/static/styles.css @@ -5493,3 +5493,16 @@ body.compact-torrent-list .mobile-progress .torrent-progress { border-radius: 10px; filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.28)); } + +/* i18n preference controls: keeps the language selector aligned with existing form fields. */ +.language-preference-field .language-flag-hint { + align-items: center; + display: inline-flex; + gap: .4rem; + margin-top: .25rem; +} + +.language-preference-field .fi { + border-radius: 2px; + box-shadow: 0 0 0 1px rgb(0 0 0 / 12%); +} diff --git a/pytorrent/templates/index.html b/pytorrent/templates/index.html index 266f5e0..2bc7aa5 100644 --- a/pytorrent/templates/index.html +++ b/pytorrent/templates/index.html @@ -295,7 +295,7 @@
rTorrent profiles
Loading profiles...
Diagnostics
Run a profile test to show diagnostics.
Add profile
Create one rTorrent profile at a time. Move/remove queues keep their order for each profile.
Torrent statistics
Cached metadata summary. File metadata is refreshed every 15 minutes, a few minutes after startup, or manually.
Not loaded.
Open this tab to load statistics.
-
Appearance
Theme, typography and interface scale. Torrent view preferences also remember the selected filter, sorting and the height of the General / Files / Trackers panel.
View state is saved automatically in the database: current torrent filter, last sort column and direction, visible columns, and details panel height.
Browser title
Controls what is shown in the browser tab.
Tracker icons
Visual helper for tracker filters in the sidebar.
Notifications
Toast notifications from automatic systems.
Disk monitor
Choose what the footer disk bar should represent and add extra storage paths.
Progress source
Monitored paths
The footer tooltip always shows details for available paths; this setting only decides which value drives the visible progress bar.
Port checker
Incoming connection test, separate from visual preferences.
disabled
Uses YouGetSignal first. Manual check bypasses the 6h cache.
Peers
Optional peer table helpers.
Easter egg
Optional visual easter egg for loading states and occasional button clicks. Disabled by default.
Changes apply immediately where possible; initial startup loader uses them after reload.
+
Appearance
Theme, typography and interface scale. Torrent view preferences also remember the selected filter, sorting and the height of the General / Files / Trackers panel.
View state is saved automatically in the database: current torrent filter, last sort column and direction, visible columns, and details panel height.
Browser title
Controls what is shown in the browser tab.
Tracker icons
Visual helper for tracker filters in the sidebar.
Notifications
Toast notifications from automatic systems.
Disk monitor
Choose what the footer disk bar should represent and add extra storage paths.
Progress source
Monitored paths
The footer tooltip always shows details for available paths; this setting only decides which value drives the visible progress bar.
Port checker
Incoming connection test, separate from visual preferences.
disabled
Uses YouGetSignal first. Manual check bypasses the 6h cache.
Peers
Optional peer table helpers.
Easter egg
Optional visual easter egg for loading states and occasional button clicks. Disabled by default.
Changes apply immediately where possible; initial startup loader uses them after reload.
Job scheduling
These settings are stored per active rTorrent profile. Light jobs are control actions such as start, stop, pause, resume, labels, ratio assignment, reannounce and speed limits. Heavy jobs are long or destructive actions such as move, remove and adding torrents.
Operation log retention
Manage operation log retention without changing torrent data.
Default log view
Controls the default category and job log visibility used by the Logs modal.
Log statistics
Profile-scoped log counts and cleanup overview.
Loading statistics...
@@ -407,7 +407,7 @@
- +