1179 lines
64 KiB
Ucode
1179 lines
64 KiB
Ucode
// Telegram bot i18n — string tables for en/ru
|
||
// Usage: let i18n = require("service.i18n"); let t = i18n.bind(lang);
|
||
|
||
let strings = {
|
||
en: {
|
||
// ─── Setting schema labels ───
|
||
dns_type: "DNS Type",
|
||
dns_server: "DNS Servers",
|
||
dns_upstream_mode: "DNS Upstream Mode",
|
||
dns_fallback_server: "Fallback DNS Servers",
|
||
bootstrap_dns_server: "Bootstrap DNS",
|
||
dns_strategy: "DNS Strategy",
|
||
dns_detour_enabled: "DNS Detour",
|
||
routed_dns_enabled: "Routed DNS",
|
||
routed_dns_type: "Routed DNS Protocol",
|
||
routed_dns_server: "Routed DNS Servers",
|
||
source_network_interfaces: "Inbound Interfaces",
|
||
enable_output_network_interface: "Bind to WAN",
|
||
enable_badwan_interface_monitoring: "WAN Monitoring",
|
||
enable_yacd: "YACD Panel",
|
||
disable_quic: "Block QUIC",
|
||
block_doh: "Block DoH",
|
||
list_update_enabled: "List Updates",
|
||
component_update_check_enabled: "Core Updates",
|
||
download_lists_via_proxy: "Lists via Proxy",
|
||
download_components_via_proxy: "Core via Proxy",
|
||
dont_touch_dhcp: "Don't Touch DHCP",
|
||
isolate_p2p: "Isolate P2P",
|
||
log_level: "Log Level",
|
||
exclude_ntp: "Exclude NTP",
|
||
route_router_traffic: "Route Router Traffic",
|
||
route_router_traffic_section: "Router Traffic Section",
|
||
shutdown_correctly: "Clean Shutdown",
|
||
smart_detect: "Smart Detect",
|
||
smart_detect_sections: "Smart Detect Sections",
|
||
enabled: "Bot Enabled",
|
||
bot_token: "Token",
|
||
admin_ids: "Admin IDs",
|
||
poll_interval: "Poll Interval",
|
||
notify_crash: "Core Crashes",
|
||
notify_restart: "Restarts",
|
||
notify_server_switch: "Server Switches",
|
||
notify_subscription: "Subscription Status",
|
||
notify_cert: "Certificates",
|
||
notify_dns_leak: "DNS Leaks",
|
||
daily_report_enabled: "Daily Report",
|
||
daily_report_hour: "Report Time (hour)",
|
||
quiet_hours_enabled: "Quiet Hours",
|
||
quiet_hours_start: "Quiet Hours Start",
|
||
quiet_hours_end: "Quiet Hours End",
|
||
fallback_socks: "Fallback SOCKS5",
|
||
language: "Language",
|
||
section: "Section",
|
||
auto_user_agent: "Auto User-Agent",
|
||
user_agent: "User-Agent",
|
||
auto_hwid: "Auto HWID",
|
||
subscription_update_enabled: "Auto Update",
|
||
subscription_update_interval: "Update Interval",
|
||
download_via_proxy_enabled: "Via Proxy",
|
||
show_dashboard_metadata: "Subscription Metadata",
|
||
prefix_nodes: "Node Prefix",
|
||
node_prefix: "Prefix String",
|
||
include_urltest_groups: "URL-Test Groups",
|
||
hide_urltest_group_outbounds: "Hide Group Nodes",
|
||
hide_detour_outbounds: "Hide Detour Nodes",
|
||
label: "Name",
|
||
protocol: "Protocol",
|
||
routing_mode: "Routing Mode",
|
||
|
||
// ─── Navigation ───
|
||
nav_next: "Next ▶️",
|
||
nav_prev: "◀️ Prev",
|
||
nav_back: "◀️ Back",
|
||
nav_menu: "🏠 Menu",
|
||
nav_settings: "⚙️ Settings",
|
||
|
||
// ─── Menu ───
|
||
menu_all_settings: "⚙️ All Settings",
|
||
menu_choose_cat: "Select category to edit:",
|
||
menu_global: "🌍 Global Settings",
|
||
menu_telegram: "🤖 Telegram Settings",
|
||
menu_subscriptions: "📋 Subscriptions",
|
||
menu_servers: "🖥️ Custom Servers",
|
||
menu_servers_short: "🖥 Custom Servers",
|
||
menu_dns_presets: "🌐 DNS Servers (Presets)",
|
||
menu_quiet_hours: "🔕 Quiet Hours",
|
||
menu_test_rule: "🔍 Test Rule",
|
||
menu_export_config: "📤 Export Config",
|
||
menu_help: "📖 Help",
|
||
menu_status: "📊 System Status",
|
||
menu_diagnostic: "🩺 Diagnostics",
|
||
menu_logs: "📝 Logs",
|
||
menu_connections: "🔌 Connections",
|
||
menu_outbounds: "🚀 Proxy Servers",
|
||
menu_sections: "📁 Routing Sections",
|
||
menu_speed: "⚡ Speed Test",
|
||
menu_ping: "📡 Ping",
|
||
menu_restart: "🔄 Restart Tachyon",
|
||
menu_language: "🌐 Language",
|
||
menu_extras: "🔧 Extras",
|
||
menu_info: "ℹ️ System Info",
|
||
menu_close_conn: "🗑️ Close All Connections",
|
||
menu_check_updates: "🔄 Check Updates",
|
||
menu_doctor: "🩺 Doctor",
|
||
menu_test_rule: "🔍 Test Rule",
|
||
menu_devices: "💻 Network Devices",
|
||
menu_instances: "Live Servers",
|
||
menu_categories: "🔙 Categories",
|
||
menu_qos: "🎮 Gaming & Voice QoS",
|
||
menu_heal: "🤖 AI Self-Healing",
|
||
choose_section: "Select section to manage:",
|
||
|
||
// ─── Status ───
|
||
status_version: "Version",
|
||
status_uptime: "Uptime",
|
||
status_cpu: "Router CPU",
|
||
status_active_servers: "Active servers:",
|
||
status_no_server: "No server selected",
|
||
status_enabled: "Enabled ✅",
|
||
status_disabled: "Disabled ❌",
|
||
status_target: "Target",
|
||
status_running: "🟢 Running",
|
||
status_stopped: "🔴 Stopped",
|
||
status_unknown: "Unknown",
|
||
status_normal: "All systems are operating normally! 🟢",
|
||
status_pause: "Paused",
|
||
status_header: "System Status",
|
||
status_sections: "Sections",
|
||
|
||
// ─── Stats ───
|
||
stat_download: "Downloaded",
|
||
stat_upload: "Uploaded",
|
||
stat_memory: "Memory",
|
||
stat_connections: "Connections",
|
||
|
||
// ─── Section management ───
|
||
section_type: "Type",
|
||
section_status: "Status",
|
||
section_choose_group: "Select a group to configure the server:",
|
||
section_group: "Group",
|
||
section_server: "Server",
|
||
section_check_singbox: "Check if sing-box is running and Clash API is accessible.",
|
||
section_domains: "Domains",
|
||
section_sources: "Sources",
|
||
section_section: "Section",
|
||
section_edit: "Editing",
|
||
section_create: "➕ Create section",
|
||
section_action: "Action",
|
||
section_list: "List",
|
||
section_empty: "Empty",
|
||
section_showing_partial: "(Showing not all items for deletion)",
|
||
btn_rename: "✏️ Rename",
|
||
btn_delete: "❌ Delete",
|
||
btn_add: "➕ Add",
|
||
btn_clear_all: "➖ Clear all",
|
||
btn_add_items: "➕ Add items",
|
||
btn_clear_list: "➖ Clear list",
|
||
btn_back_to_section: "🔙 Back to section",
|
||
|
||
// ─── Diagnostics ───
|
||
diag_running: "Diagnostics already running by another process.",
|
||
diag_issues: "Issues: %s",
|
||
diag_issues_count: "Issues: %s",
|
||
diag_fixed_count: ", fixed: %s",
|
||
diag_planned_count: ", planned: %d",
|
||
diag_clean: "No issues detected.",
|
||
diag_no_output: "No diagnostic output.",
|
||
diag_error: "Failed to start diagnostics.",
|
||
diag_empty: "Empty diagnostics report.",
|
||
diag_all_fixed: "All systems restored to normal! 🟢",
|
||
diag_starting: "Running diagnostics...",
|
||
diag_results: "Tachyon Doctor Results:",
|
||
report_truncated: "report truncated",
|
||
|
||
// ─── Logs ───
|
||
logs_no_records: "No records for this level.\n",
|
||
logs_read_error: "Failed to read logs.\n",
|
||
|
||
// ─── Connections ───
|
||
conn_none: "No active connections.",
|
||
|
||
// ─── Subscriptions ───
|
||
sub_none: "No subscriptions. Add a subscription URL to download rules.",
|
||
sub_found: "Found subscriptions: ",
|
||
|
||
// ─── Latency ───
|
||
latency_no_data: "No latency data. Press «Refresh».",
|
||
latency_none: "No latency data available.",
|
||
|
||
// ─── Servers ───
|
||
servers_none: "No servers found or sing-box is not running.",
|
||
servers_api_error: "API parsing error: ",
|
||
|
||
// ─── QoS ───
|
||
qos_status: "Status",
|
||
qos_enabled: "🟢 Enabled",
|
||
qos_disabled: "❌ Disabled",
|
||
qos_start: "Start",
|
||
qos_end: "End",
|
||
qos_quiet_hint: "During quiet hours, the bot only sends critical notifications.",
|
||
|
||
// ─── Errors ───
|
||
err_invalid_format: "Invalid command format",
|
||
err_not_allowed: "Command '%s' is not in the allowed list",
|
||
err_args_mismatch: "Arguments don't match the allowed template",
|
||
err_wrong_arg_count: "Wrong number of arguments",
|
||
err_arg_not_allowed: "Argument not allowed: %s",
|
||
err_subcmd_not_allowed: "Subcommand '%s' is not in the whitelist",
|
||
err_host_unknown: "Unknown",
|
||
err_api_parse: "Failed to read info: ",
|
||
err_status_fetch: "Failed to get status.",
|
||
err_no_data: "No data.",
|
||
err_log_read: "Failed to read logs.",
|
||
err_no_output: "No output",
|
||
|
||
// ─── Notifications ───
|
||
notif_restart_services: "Tachyon services restarted",
|
||
notif_nft_cleared: "nftables rules table cleared or corrupted",
|
||
notif_nft_regenerated: "TachyonTable and TPROXY chain rules regenerated",
|
||
notif_qos_not_found: "Gaming & Voice QoS Accelerator rules not found in nftables",
|
||
notif_qos_applied: "High-priority DSCP labels applied: EF (0x2e) for Voice/RTC, AF41 (0x22) for Gaming",
|
||
notif_restart_skipped: "Restart skipped: rate limit or active block",
|
||
notif_singbox_hung: "Proxy port hang or incomplete response sing-box",
|
||
notif_singbox_restarted: "sing-box restarted",
|
||
notif_cache_cleared: "cache.db cleared; restart skipped by rate limit",
|
||
notif_sets_empty: "Empty nftables sets (community) — data not loaded on reload",
|
||
notif_sets_restored: "nftables sets restored from persistent cache",
|
||
notif_fw_reload: "reload_firewall executed to restore TPROXY rules",
|
||
notif_config_invalid: "Restart cancelled: sing-box config fails validation",
|
||
notif_restart_rate: "Restart skipped by rate limit",
|
||
notif_rpcd_restarted: "rpcd restarted to free file descriptors",
|
||
|
||
// ─── Route failure ───
|
||
route_proxy_alive: "proxy port is listening, but requests through it are failing",
|
||
route_proxy_down: "proxy port not listening (sing-box mixed-inbound not up)",
|
||
route_hint: "Reason: %s.\nDirect API access enabled as fallback — commands may respond with delay.\nRun /test to check connectivity.",
|
||
route_alert_title: "Tachyon Telegram bot",
|
||
route_alert_consecutive: "consecutive API poll failures",
|
||
route_reason: "Reason:",
|
||
route_fallback_hint: "Direct API access enabled as fallback — commands may respond with delay.",
|
||
route_heal_hint: "Watchdog will try to restore proxy automatically.",
|
||
|
||
// ─── Command descriptions (for setMyCommands) ───
|
||
cmd_menu: "Main menu",
|
||
cmd_status: "System status",
|
||
cmd_runtime: "Traffic stats",
|
||
cmd_outbounds: "Proxy servers",
|
||
cmd_sections: "Routing sections",
|
||
cmd_speed: "Speed test",
|
||
cmd_ping: "Server latency",
|
||
cmd_test: "Quick diagnostics",
|
||
cmd_logs: "View logs",
|
||
cmd_info: "System info",
|
||
cmd_connections: "Active connections",
|
||
cmd_test_rule: "Test rule",
|
||
cmd_help: "Help",
|
||
cmd_check_updates: "Check for updates",
|
||
cmd_close_connections: "Close all connections",
|
||
cmd_doctor: "Diagnostics",
|
||
cmd_restart: "Restart Tachyon services",
|
||
cmd_instances: "Live servers",
|
||
cmd_lang: "Change language",
|
||
cmd_guest: "Guest mode",
|
||
menu_guest: "👥 Guest Mode",
|
||
guest_title: "Guest Mode",
|
||
guest_enabled: "Guest mode enabled",
|
||
guest_disabled: "Guest mode disabled",
|
||
guest_status_active: "🟢 Active",
|
||
guest_status_inactive: "⚪ Inactive",
|
||
guest_mode_selected: "Selected devices",
|
||
guest_mode_inverted: "All except trusted",
|
||
guest_devices_count: "Guest devices: %d",
|
||
guest_trusted_count: "Trusted devices: %d",
|
||
guest_time_limit: "Daily time limit: %d min",
|
||
guest_traffic_limit: "Daily traffic limit: %s",
|
||
guest_lan_isolated: "LAN isolation: Active (RFC1918 & router management blocked)",
|
||
guest_time_spent: "Time spent today: %d min",
|
||
guest_traffic_spent: "Traffic used today: %s",
|
||
guest_limit_reached_time: "⏳ Guest device %s reached daily time limit (%d min). Access blocked until midnight.",
|
||
guest_limit_reached_traffic: "📊 Guest device %s reached daily traffic limit (%s). Access blocked until midnight.",
|
||
btn_guest_toggle: "👥 Guest Mode",
|
||
|
||
// ─── Misc ───
|
||
exec_done: "<b>Done (code %s):</b>\n<pre>%s</pre>",
|
||
hour_enter: "⏰ Enter the hour for %s (0-23):",
|
||
hour_start: "start",
|
||
hour_end: "end",
|
||
blocked_activity: "Blocked Activity",
|
||
blocked_attempts: "Attempts to access blocked sites",
|
||
daily_digest_title: "🌅 Morning Tachyon Digest",
|
||
daily_rx: "Current RX",
|
||
daily_tx: "Current TX",
|
||
daily_connections: "Connections",
|
||
daily_memory: "Memory",
|
||
choose_language: "Select language:",
|
||
lang_current: "Current language: %s",
|
||
lang_saved: "Language saved!",
|
||
ping_enter_host: "Enter a domain or IP to check:",
|
||
test_rule_prompt: "Enter the rule to test:",
|
||
rule_label: "Rule",
|
||
|
||
// ─── Speed test ───
|
||
speed_starting: "⚡ <b>Starting Speedtest...</b>\n\nTesting via Cloudflare. Takes up to 30 seconds.",
|
||
speed_result: "⚡ Speedtest Result",
|
||
speed_direct: "📥 Direct:",
|
||
speed_proxy: "📤 Via proxy:",
|
||
speed_fail_measure: "❌ failed to measure",
|
||
speed_error: "❌ Failed to run test. Check if sing-box is running.",
|
||
speed_check_hint: "Check internet access and sing-box.",
|
||
|
||
// ─── Ping ───
|
||
ping_api_error: "❌ Failed to get data from Clash API.",
|
||
|
||
// ─── Quick test ───
|
||
test_title: "Quick Diagnostics",
|
||
test_direct: "Direct connection",
|
||
test_proxy: "Proxy connection",
|
||
test_service: "Tachyon service",
|
||
test_nft: "nftables rules",
|
||
test_pause: "Pause:",
|
||
test_rule: "Rule check:",
|
||
test_match: "Match",
|
||
test_no_match: "No matches found. Traffic goes through default route.",
|
||
|
||
// ─── Connections ───
|
||
conn_total_down: "Total downloaded",
|
||
conn_total_up: "Total uploaded",
|
||
conn_closed: "All active connections closed.",
|
||
|
||
// ─── Devices ───
|
||
device_block: "🚫 Block device",
|
||
device_unblock: "🔓 Unblock device",
|
||
device_blocked: "blocked",
|
||
device_unblocked: "unblocked",
|
||
|
||
// ─── AI Doctor ───
|
||
ai_doctor_title: "Tachyon AI Doctor",
|
||
ai_status_collecting: "Collecting full AI Watchdog status...",
|
||
ai_incident: "⚠️ Incident resolved:",
|
||
ai_resolution: "🔧 Auto-fix:",
|
||
ai_all_ok: "All network services, DNS, nftables and memory are working perfectly.",
|
||
ai_diag_ok: "Diagnostics completed successfully.",
|
||
ai_diag_done: "Diagnostics completed.",
|
||
|
||
// ─── Buttons ───
|
||
btn_refresh: "🔄 Refresh",
|
||
btn_retry: "🔄 Retry",
|
||
btn_again: "🔄 Again",
|
||
btn_speed_again: "⚡ Again",
|
||
btn_back_to_groups: "🔙 Groups",
|
||
btn_back_to_sections: "🔙 Sections",
|
||
btn_close_all: "❌ Close All",
|
||
btn_test: "🩺 Test",
|
||
nav_cancel: "⬅️ Cancel",
|
||
restart_confirm: "⚠️ <b>Restart Tachyon services?</b>\nCurrent connections will be interrupted during restart.",
|
||
restart_yes: "✅ Yes, restart",
|
||
restart_in_progress: "Restarting Tachyon services...",
|
||
restart_success: "Restart completed successfully!",
|
||
restart_error: "Restart failed.",
|
||
conn_closed: "All active connections closed.",
|
||
|
||
// ─── Outbounds ───
|
||
servers_not_found: "Servers not found or sing-box not running.",
|
||
outbounds_hint: "Press the button to switch servers.",
|
||
|
||
// ─── Logs ───
|
||
logs_level: "level",
|
||
|
||
// ─── Info ───
|
||
info_device: "Device",
|
||
err_info_read: "Failed to read info:",
|
||
|
||
// ─── Updates ───
|
||
update_new_build: "New release build available!",
|
||
update_available: "Component update available!",
|
||
build_label: "Build",
|
||
|
||
// ─── Healer ───
|
||
heal_running: "AI Doctor running diagnostics and self-healing...",
|
||
// ─── Batch i18n additions ───
|
||
msg_truncated: "... (message truncated)",
|
||
menu_version: "Version",
|
||
menu_cpu: "Router CPU",
|
||
list_header: "⚙️ <b>List:</b>",
|
||
outbound_groups_not_found: "Proxy groups not found.",
|
||
outbound_switch_failed: "Failed to switch server",
|
||
outbound_group: "Group",
|
||
outbound_server: "Server",
|
||
outbound_check_hint: "Check if sing-box is running and Clash API is accessible.",
|
||
section_ips: "IP addresses",
|
||
section_list_header: "⚙️ <b>Section:</b>",
|
||
backup_archive_empty: "Archive is empty or corrupted.",
|
||
backup_archive_unsafe: "Unsafe archive:",
|
||
backup_restoring: "Checking and restoring backup...",
|
||
backup_extract_failed: "Failed to extract archive.",
|
||
backup_not_valid_uci: "config/tachyon in archive is not a valid UCI.",
|
||
backup_no_config: "Archive contains neither config/tachyon nor tachyon/ directory.",
|
||
backup_save_config_failed: "Failed to save current config.",
|
||
backup_save_data_failed: "Failed to save current /etc/tachyon data.",
|
||
backup_write_config_error: "Write error /etc/config/tachyon.",
|
||
backup_uci_validation_failed: "Restored config failed UCI validation. Rolled back.",
|
||
backup_write_data_error: "Write error /etc/tachyon. Rolled back.",
|
||
backup_restored: "Backup restored. Restarting Tachyon...",
|
||
backup_done: "Done!",
|
||
backup_collecting: "Collecting backup...",
|
||
backup_create_error: "Backup creation error.",
|
||
support_bundle_collecting: "Generating Support Bundle...",
|
||
support_bundle_error: "Bundle generation error.",
|
||
conn_closed_msg: "All active connections closed.\nThey will be re-established along new routes.",
|
||
conn_close_error: "Connection reset error.\nsing-box Clash API is unavailable.",
|
||
updates_title: "Component Updates",
|
||
updates_disabled: "Update check is disabled in settings.",
|
||
updates_cache_empty: "Cache is empty. Check later.",
|
||
update_check_error: "Check error",
|
||
update_new_release_build: "new release build",
|
||
update_dev_build: "dev build",
|
||
update_all_current: "All components up to date.",
|
||
update_cache_parse_error: "Cache parse error:",
|
||
update_cache_unavailable: "Check cache empty or unavailable.",
|
||
btn_refresh_cache: "Refresh cache",
|
||
api_parse_error: "API parsing error:",
|
||
api_connect_failed: "Failed to connect to sing-box API.",
|
||
logs_header: "Tachyon Logs",
|
||
info_title: "System Information",
|
||
info_device_label: "Device",
|
||
info_fetch_failed: "Failed to get system information.",
|
||
sub_empty_url: "(empty)",
|
||
btn_sub_delete: " 🗑 Delete",
|
||
btn_add_subscription: "Add subscription",
|
||
sub_section_subs: "Subscriptions",
|
||
sub_found_count: "Subscriptions found:",
|
||
sub_enter_url: "Enter subscription URL:\n\n<i>Send /cancel to cancel</i>",
|
||
sub_url_empty: "URL cannot be empty.",
|
||
sub_added: "Subscription added to section",
|
||
sub_not_found: "Subscription not found.",
|
||
sub_removed: "Subscription removed from section",
|
||
help_title: "Command Help",
|
||
help_main_section: "Main:",
|
||
help_diag_section: "Diagnostics:",
|
||
help_manage_section: "Management:",
|
||
help_settings_section: "Settings:",
|
||
help_this: "This help",
|
||
quiet_hours_title: "Quiet Hours",
|
||
quiet_status: "Status",
|
||
quiet_enabled_label: "Enabled",
|
||
quiet_disabled_label: "Disabled",
|
||
quiet_start_label: "Start:",
|
||
quiet_end_label: "End:",
|
||
quiet_hint: "During quiet hours, the bot only sends critical notifications.",
|
||
btn_enable: "Enable",
|
||
btn_disable: "Disable",
|
||
quiet_hour_start: "start",
|
||
quiet_hour_end: "end",
|
||
quiet_enter_hour: "⏰ Enter the hour for %s quiet hours (0–23):\n\n<i>Send /cancel to cancel</i>",
|
||
test_rule_header: "Rule check:",
|
||
test_match: "Match:",
|
||
test_action: "Action:",
|
||
export_title: "Exporting config...",
|
||
export_done: "Config exported.\n\n⚠️ File contains sensitive data. Do not publish it.",
|
||
export_failed: "Failed to export config.",
|
||
mac_invalid: "Invalid MAC address.",
|
||
mac_firewall_open_failed: "Failed to open firewall configuration.",
|
||
mac_block_rule_failed: "Failed to create block rule.",
|
||
mac_blocked: "blocked.",
|
||
mac_unblocked: "unblocked.",
|
||
mac_firewall_bg: "Firewall rules are applying in background (a few seconds).",
|
||
devices_title: "Network Devices:",
|
||
device_hostname_unknown: "Unknown",
|
||
devices_not_found: "No devices found.",
|
||
watchdog_stop_btn: "Stop Watchdog",
|
||
ai_full_status_btn: "Full AI Status",
|
||
watchdog_start_btn: "Start Watchdog",
|
||
ai_incident: "⚠️ Incident resolved:",
|
||
ai_resolution: "🔧 Auto-fix:",
|
||
ai_all_ok: "All network services, DNS, nftables and memory are working perfectly.",
|
||
ai_diag_ok: "Diagnostics completed successfully.",
|
||
ai_diag_done: "Diagnostics completed.",
|
||
ai_status_collecting: "Collecting full AI Watchdog status...",
|
||
ai_status_error: "Status fetch error.",
|
||
ai_data_truncated: "data truncated",
|
||
ai_full_status_header: "AI Watchdog — Full Status:",
|
||
qos_title: "Gaming & Voice QoS Accelerator",
|
||
qos_enabled_detail: "Enabled (DSCP EF + AF41 Priority)",
|
||
qos_disabled_detail: "Disabled",
|
||
qos_priority_rules: "Priority rules:",
|
||
btn_qos_disable: "Disable QoS",
|
||
btn_qos_enable: "Enable QoS",
|
||
cb_obsolete: "Button obsolete — open the list again.",
|
||
update_component_title: "Starting update",
|
||
update_bg_hint: "Process started in background. Check later.",
|
||
err_unknown_component: "Unknown component:",
|
||
admin_invalid_chat_id: "Invalid Chat ID.",
|
||
admin_user_added: "User added to admin list.",
|
||
admin_user_already: "User is already an admin.",
|
||
sec_enter_name: "Enter a Latin name for the new section (e.g. <code>my_vpn</code>):\n\n<i>Send /cancel to cancel</i>",
|
||
sec_enter_label: "Enter a new human-readable name (Label) for section",
|
||
sec_enter_target: "Enter outbound interface (target) for section",
|
||
sec_not_found: "Section not found.",
|
||
sec_deleted: "Section deleted.",
|
||
sec_add_items_prompt: "Send items to add (one per line or space-separated):\n\n<i>Send /cancel to cancel</i>",
|
||
sec_sub_add_prompt: "Enter section name and subscription URL separated by a space:\n<code>/sec_sub_add Main https://...</code>\n\n<i>Send /cancel to cancel</i>",
|
||
sec_enter_value: "Enter new value for",
|
||
sec_add_list_prompt: "Send items to add to the list (space or newline separated):\n\n<i>Send /cancel to cancel</i>",
|
||
dns_all_protocols: "All protocols",
|
||
dns_servers_applied: "DNS servers set:",
|
||
dns_restart_hint: "Restart to apply.",
|
||
dns_bootstrap_applied: "Bootstrap DNS servers set:",
|
||
exec_cmd_error: "Command execution error:",
|
||
exec_access_denied: "Access denied. Your Chat ID:",
|
||
backup_downloading: "Downloading backup...",
|
||
backup_download_error: "File download error.",
|
||
backup_url_error: "File URL error.",
|
||
backup_format_hint: "Please send the backup in .tar.gz format.",
|
||
admin_forward_prompt: "Forwarded a message from user",
|
||
btn_admin_add: "Add",
|
||
exec_whitelist_msg: "Executing from whitelist:",
|
||
exec_no_output: "No output",
|
||
action_cancelled: "Action cancelled.",
|
||
err_text_expected: "A text message is expected. Try again or /cancel.",
|
||
value_saved: "Value saved.",
|
||
items_added: "items added.",
|
||
section_created: "Section created!",
|
||
err_invalid_section_name: "Invalid name. Only letters, numbers, and underscores allowed.",
|
||
label_changed: "Name changed.",
|
||
target_changed: "Target changed.",
|
||
items_added_count: "Added",
|
||
nothing_added: "Nothing added.",
|
||
err_format_section_url: "Format: <code>section URL</code>\nExample: <code>Main https://...</code>",
|
||
err_invalid_hour: "Enter an integer from 0 to 23.",
|
||
saved: "Saved.",
|
||
daily_unknown: "unknown",
|
||
daily_uptime: "OS Uptime:",
|
||
daily_rx: "Current RX:",
|
||
daily_tx: "Current TX:",
|
||
build_label: "Build:",
|
||
blocked_activity: "Blocked Activity",
|
||
blocked_rule_label: "Rule:",
|
||
blocked_rule: "Rule:",
|
||
blocked_attempts: "Attempts to access blocked sites",
|
||
info_read_error: "Error reading info:",
|
||
quiet_start_word: "start",
|
||
quiet_end_word: "end",
|
||
quiet_saved: "Settings saved.",
|
||
sec_created: "Section created!",
|
||
sec_invalid_name: "Invalid name. Only Latin letters, digits, underscores.",
|
||
sec_invalid_hour: "Invalid hour.",
|
||
sec_changed_to: "changed to",
|
||
exec_value_saved: "Value saved. Restart needed for changes.",
|
||
exec_items_added: "Added",
|
||
exec_items_added_count: "Added",
|
||
exec_nothing_added: "Nothing added.",
|
||
exec_changed_to: "changed to",
|
||
exec_format_hint: "Format: domain.com or [ip]/prefix.",
|
||
update_new_release_header: "New build of current release!",
|
||
update_build_label: "Build",
|
||
critical_keyword_fallen: "Down",
|
||
critical_keyword_error: "Error",
|
||
btn_update_component: "Update",
|
||
fptn_token_title: "FPTN Access Token",
|
||
fptn_token_prompt: "Send the new FPTN access token (copy/forward from @fptn_bot):",
|
||
fptn_token_invalid: "Invalid or empty FPTN token. Please provide a valid token.",
|
||
fptn_token_no_section: "Token saved, but no section with action 'fptn' was found.",
|
||
fptn_restarting: "Updating token and connecting FPTN...",
|
||
fptn_token_updated_title: "FPTN Token Updated and Connected!",
|
||
fptn_token_saved_connecting: "Token saved. Connecting to FPTN...",
|
||
fptn_token_retry_hint: "Connecting in background; routing will be applied automatically.",
|
||
fptn_token_change_btn: "FPTN Token",
|
||
fptn_token_btn: "FPTN Token",
|
||
},
|
||
|
||
ru: {
|
||
// ─── Setting schema labels ───
|
||
dns_type: "Тип DNS",
|
||
dns_server: "DNS Серверы",
|
||
dns_upstream_mode: "Режим DNS Upstream",
|
||
dns_fallback_server: "Резервные DNS Серверы",
|
||
bootstrap_dns_server: "Bootstrap DNS",
|
||
dns_strategy: "Стратегия DNS",
|
||
dns_detour_enabled: "DNS Detour",
|
||
routed_dns_enabled: "Маршрутизированный DNS",
|
||
routed_dns_type: "Протокол маршрутизированного DNS",
|
||
routed_dns_server: "Серверы маршрутизированного DNS",
|
||
source_network_interfaces: "Входящие интерфейсы",
|
||
enable_output_network_interface: "Привязка к WAN",
|
||
enable_badwan_interface_monitoring: "Мониторинг WAN",
|
||
enable_yacd: "Панель YACD",
|
||
disable_quic: "Блокировать QUIC",
|
||
block_doh: "Блокировать DoH",
|
||
list_update_enabled: "Обновление списков",
|
||
component_update_check_enabled: "Обновление ядра",
|
||
download_lists_via_proxy: "Списки через прокси",
|
||
download_components_via_proxy: "Ядро через прокси",
|
||
dont_touch_dhcp: "Не трогать DHCP",
|
||
isolate_p2p: "Изолировать P2P",
|
||
log_level: "Уровень логов",
|
||
exclude_ntp: "Исключить NTP",
|
||
route_router_traffic: "Маршрутизировать трафик роутера",
|
||
route_router_traffic_section: "Секция трафика роутера",
|
||
shutdown_correctly: "Корректное завершение",
|
||
smart_detect: "Smart Detect",
|
||
smart_detect_sections: "Секции Smart Detect",
|
||
enabled: "Бот Включен",
|
||
bot_token: "Токен",
|
||
admin_ids: "Admin IDs",
|
||
poll_interval: "Интервал опроса",
|
||
notify_crash: "Сбои ядра",
|
||
notify_restart: "Перезапуски",
|
||
notify_server_switch: "Переключение серверов",
|
||
notify_subscription: "Статус подписок",
|
||
notify_cert: "Сертификаты",
|
||
notify_dns_leak: "Утечки DNS",
|
||
daily_report_enabled: "Ежедневный отчет",
|
||
daily_report_hour: "Время отчета (час)",
|
||
quiet_hours_enabled: "Тихие часы",
|
||
quiet_hours_start: "Начало тихих часов",
|
||
quiet_hours_end: "Конец тихих часов",
|
||
fallback_socks: "Резервный SOCKS5",
|
||
language: "Язык",
|
||
section: "Секция",
|
||
auto_user_agent: "Auto User-Agent",
|
||
user_agent: "User-Agent",
|
||
auto_hwid: "Auto HWID",
|
||
subscription_update_enabled: "Автообновление",
|
||
subscription_update_interval: "Интервал обновления",
|
||
download_via_proxy_enabled: "Через прокси",
|
||
show_dashboard_metadata: "Метаданные подписки",
|
||
prefix_nodes: "Префикс узлов",
|
||
node_prefix: "Строка префикса",
|
||
include_urltest_groups: "Группы URL-Test",
|
||
hide_urltest_group_outbounds: "Скрыть узлы групп",
|
||
hide_detour_outbounds: "Скрыть Detour узлы",
|
||
label: "Название",
|
||
enabled: "Включен",
|
||
protocol: "Протокол",
|
||
routing_mode: "Режим",
|
||
|
||
// ─── Navigation ───
|
||
nav_next: "След ▶️",
|
||
nav_prev: "◀️ Пред",
|
||
nav_back: "◀️ Назад",
|
||
nav_menu: "🏠 Меню",
|
||
nav_settings: "⚙️ Настройки",
|
||
|
||
// ─── Menu ───
|
||
menu_all_settings: "⚙️ Все Настройки",
|
||
menu_choose_cat: "Выберите категорию для редактирования:",
|
||
menu_global: "🌍 Глобальные настройки",
|
||
menu_telegram: "🤖 Настройки Telegram",
|
||
menu_subscriptions: "📋 Подписки",
|
||
menu_servers: "🖥️ Пользовательские серверы",
|
||
menu_servers_short: "🖥 Кастомные серверы",
|
||
menu_dns_presets: "🌐 DNS Серверы (Пресеты)",
|
||
menu_quiet_hours: "🔕 Тихие часы",
|
||
menu_test_rule: "🔍 Проверка правила",
|
||
menu_export_config: "📤 Экспорт конфига",
|
||
menu_help: "📖 Справка",
|
||
menu_status: "📊 Статус системы",
|
||
menu_diagnostic: "🩺 Диагностика",
|
||
menu_logs: "📝 Логи",
|
||
menu_connections: "🔌 Подключения",
|
||
menu_outbounds: "🚀 Прокси серверы",
|
||
menu_sections: "📁 Секции маршрутизации",
|
||
menu_speed: "⚡ Тест скорости",
|
||
menu_ping: "📡 Задержка",
|
||
menu_restart: "🔄 Перезапуск Tachyon",
|
||
menu_language: "🌐 Язык",
|
||
menu_extras: "🔧 Дополнительно",
|
||
menu_info: "ℹ️ Информация о системе",
|
||
menu_close_conn: "🗑️ Закрыть все соединения",
|
||
menu_check_updates: "🔄 Проверить обновления",
|
||
menu_doctor: "🩺 Диагностика",
|
||
menu_test_rule: "🔍 Проверка правила",
|
||
menu_devices: "💻 Устройства в сети",
|
||
menu_instances: "Live серверы",
|
||
menu_categories: "🔙 Категории",
|
||
menu_qos: "🎮 Игровой QoS",
|
||
menu_heal: "🤖 ИИ-Самолечение",
|
||
choose_section: "Выберите раздел для управления:",
|
||
|
||
// ─── Status ───
|
||
status_version: "Версия",
|
||
status_uptime: "Аптайм",
|
||
status_cpu: "Роутер CPU",
|
||
status_active_servers: "Активные серверы:",
|
||
status_no_server: "Активный сервер: <code>Не выбран</code>",
|
||
status_enabled: "Включена ✅",
|
||
status_disabled: "Выключена ❌",
|
||
status_target: "Цель (Target)",
|
||
status_running: "🟢 Запущен",
|
||
status_stopped: "🔴 Остановлен",
|
||
status_unknown: "Неизвестно",
|
||
status_normal: "Все системы приведены в штатную норму! 🟢",
|
||
status_pause: "Пауза",
|
||
status_header: "Статус Системы",
|
||
status_sections: "Секции",
|
||
|
||
// ─── Stats ───
|
||
stat_download: "Скачано",
|
||
stat_upload: "Отдано",
|
||
stat_memory: "Память",
|
||
stat_connections: "Соединений",
|
||
|
||
// ─── Section management ───
|
||
section_type: "Тип",
|
||
section_status: "Статус",
|
||
section_choose_group: "Выберите группу для настройки сервера:\n\n",
|
||
section_group: "Группа",
|
||
section_server: "Сервер",
|
||
section_check_singbox: "Проверьте, запущен ли sing-box и доступен ли Clash API.",
|
||
section_domains: "Домены",
|
||
section_sources: "Источники (Source)",
|
||
section_section: "Секция",
|
||
section_edit: "Редактирование",
|
||
section_create: "➕ Создать секцию",
|
||
section_action: "Действие",
|
||
section_list: "Список",
|
||
section_empty: "Пусто",
|
||
section_showing_partial: "(Показаны не все элементы для удаления)",
|
||
btn_rename: "✏️ Имя",
|
||
btn_delete: "❌ Удалить",
|
||
btn_add: "➕ Добавить",
|
||
btn_clear_all: "➖ Очистить все",
|
||
btn_add_items: "➕ Добавить элементы",
|
||
btn_clear_list: "➖ Очистить список",
|
||
btn_back_to_section: "🔙 Назад к секции",
|
||
|
||
// ─── Diagnostics ───
|
||
diag_running: "Диагностика уже выполняется другим процессом.",
|
||
diag_issues: "Проблем: %s",
|
||
diag_issues_count: "Проблем: %s",
|
||
diag_fixed_count: ", исправлено: %s",
|
||
diag_planned_count: ", планируется к исправлению: %d\n(применение: tachyon doctor --fix или кнопка в LuCI)",
|
||
diag_clean: "Проблем не обнаружено.",
|
||
diag_no_output: "Нет вывода диагностики.",
|
||
diag_error: "Ошибка запуска диагностики.",
|
||
diag_empty: "Пустой отчёт диагностики.",
|
||
diag_all_fixed: "Все системы приведены в штатную норму! 🟢",
|
||
diag_starting: "Запуск диагностики...",
|
||
diag_results: "Результаты Tachyon Doctor:",
|
||
report_truncated: "отчёт сокращён",
|
||
|
||
// ─── Logs ───
|
||
logs_no_records: "Нет записей для данного уровня.\n",
|
||
logs_read_error: "Не удалось прочитать логи.\n",
|
||
|
||
// ─── Connections ───
|
||
conn_none: "Нет активных подключений.",
|
||
|
||
// ─── Subscriptions ───
|
||
sub_none: "Нет подписок. Добавьте URL подписки для скачивания правил.",
|
||
sub_found: "Найдено подписок: ",
|
||
|
||
// ─── Latency ───
|
||
latency_no_data: "Нет данных о задержках. Нажмите «Обновить».",
|
||
latency_none: "Нет данных о задержках.",
|
||
|
||
// ─── Servers ───
|
||
servers_none: "Серверы не найдены или sing-box не запущен.",
|
||
servers_api_error: "Ошибка парсинга API: ",
|
||
|
||
// ─── QoS ───
|
||
qos_status: "Статус",
|
||
qos_enabled: "🟢 Включены",
|
||
qos_disabled: "❌ Выключены",
|
||
qos_start: "Начало",
|
||
qos_end: "Конец",
|
||
qos_quiet_hint: "В тихие часы бот отправляет только критические уведомления.",
|
||
|
||
// ─── Errors ───
|
||
err_invalid_format: "Неверный формат команды",
|
||
err_not_allowed: "Команда '%s' не входит в список разрешённых",
|
||
err_args_mismatch: "Аргументы не совпадают с разрешённым шаблоном",
|
||
err_wrong_arg_count: "Неверное число аргументов",
|
||
err_arg_not_allowed: "Аргумент не разрешён: %s",
|
||
err_subcmd_not_allowed: "Подкоманда '%s' не входит в whitelist",
|
||
err_host_unknown: "Неизвестно",
|
||
err_api_parse: "Ошибка чтения информации: ",
|
||
err_status_fetch: "Ошибка получения статуса.",
|
||
err_no_data: "Нет данных.",
|
||
err_log_read: "Не удалось прочитать логи.",
|
||
err_no_output: "Нет вывода",
|
||
|
||
// ─── Notifications ───
|
||
notif_restart_services: "Выполнен перезапуск служб Tachyon",
|
||
notif_nft_cleared: "Таблица правил nftables очищена или повреждена",
|
||
notif_nft_regenerated: "Выполнена быстрая регенерация правил TachyonTable и цепочки TPROXY",
|
||
notif_qos_not_found: "Правила Игрового & Голосового QoS Ускорителя не найдены в nftables",
|
||
notif_qos_applied: "Применены высокоприоритетные метки DSCP EF (0x2e) для Voice/RTC и DSCP AF41 (0x22) для Gaming",
|
||
notif_restart_skipped: "Перезапуск не выполнен: лимит частоты или активная блокировка",
|
||
notif_singbox_hung: "Зависание или неполный отклик прокси-порту sing-box",
|
||
notif_singbox_restarted: "Выполнен перезапуск sing-box",
|
||
notif_cache_cleared: "Очищена база cache.db; перезапуск пропущен по лимиту частоты",
|
||
notif_sets_empty: "Пустые nftables sets подсетей (community) — данные не были загружены при reload",
|
||
notif_sets_restored: "Восстановлены nftables sets из persistent кеша",
|
||
notif_fw_reload: "Выполнен reload_firewall для восстановления TPROXY правил",
|
||
notif_config_invalid: "Перезапуск отменён: конфигурация sing-box не проходит валидацию",
|
||
notif_restart_rate: "Перезапуск пропущен по лимиту частоты",
|
||
notif_rpcd_restarted: "Выполнен перезапуск rpcd для освобождения файловых дескрипторов",
|
||
|
||
// ─── Route failure ───
|
||
route_proxy_alive: "прокси-порт слушается, но запросы через него не проходят",
|
||
route_proxy_down: "прокси-порт не слушается (mixed-inbound sing-box не поднялся)",
|
||
route_hint: "Причина: %s.\nВключён прямой доступ к API как запасной путь — команды могут отвечать с задержкой.\nВыполните /test для проверки связи.",
|
||
route_alert_title: "Tachyon Telegram бот",
|
||
route_alert_consecutive: "неудачных попыток связи с API подряд",
|
||
route_reason: "Причина:",
|
||
route_fallback_hint: "Включён прямой доступ к API как запасной путь — команды могут отвечать с задержкой.",
|
||
route_heal_hint: "Watchdog попробует восстановить прокси автоматически.",
|
||
|
||
// ─── Command descriptions ───
|
||
cmd_menu: "Главное меню",
|
||
cmd_status: "Статус системы",
|
||
cmd_runtime: "Статистика трафика",
|
||
cmd_outbounds: "Прокси серверы",
|
||
cmd_sections: "Секции маршрутизации",
|
||
cmd_speed: "Тест скорости",
|
||
cmd_ping: "Задержка до серверов",
|
||
cmd_test: "Быстрая диагностика",
|
||
cmd_logs: "Просмотр логов",
|
||
cmd_info: "Информация о системе",
|
||
cmd_connections: "Активные подключения",
|
||
cmd_test_rule: "Проверка правила",
|
||
cmd_help: "Справка",
|
||
cmd_check_updates: "Проверить обновления",
|
||
cmd_close_connections: "Закрыть все соединения",
|
||
cmd_doctor: "Диагностика",
|
||
cmd_restart: "Перезапуск служб Tachyon",
|
||
cmd_instances: "Live серверы",
|
||
cmd_lang: "Сменить язык",
|
||
cmd_guest: "Гостевой режим",
|
||
menu_guest: "👥 Гостевой режим",
|
||
guest_title: "Гостевой режим",
|
||
guest_enabled: "Гостевой режим включён",
|
||
guest_disabled: "Гостевой режим выключен",
|
||
guest_status_active: "🟢 Активен",
|
||
guest_status_inactive: "⚪ Отключен",
|
||
guest_mode_selected: "Выбранные устройства",
|
||
guest_mode_inverted: "Все, кроме доверенных",
|
||
guest_devices_count: "Гостевых устройств: %d",
|
||
guest_trusted_count: "Доверенных устройств: %d",
|
||
guest_time_limit: "Дневной лимит времени: %d мин",
|
||
guest_traffic_limit: "Дневной лимит трафика: %s",
|
||
guest_lan_isolated: "Изоляция LAN: Активна (доступ к локальной сети и роутеру заблокирован)",
|
||
guest_time_spent: "Времени сегодня: %d мин",
|
||
guest_traffic_spent: "Трафика сегодня: %s",
|
||
guest_limit_reached_time: "⏳ Гостевое устройство %s исчерпало дневной лимит времени (%d мин). Доступ заблокирован до полуночи.",
|
||
guest_limit_reached_traffic: "📊 Гостевое устройство %s исчерпало дневной лимит трафика (%s). Доступ заблокирован до полуночи.",
|
||
btn_guest_toggle: "👥 Гостевой режим",
|
||
|
||
// ─── Misc ───
|
||
exec_done: "<b>Выполнено (код %s):</b>\n<pre>%s</pre>",
|
||
hour_enter: "⏰ Введите час %s (0-23):",
|
||
hour_start: "начала",
|
||
hour_end: "окончания",
|
||
blocked_activity: "Заблокированная активность",
|
||
blocked_attempts: "Попыток доступа к заблокированным сайтам",
|
||
daily_digest_title: "🌅 Утренний дайджест Tachyon",
|
||
daily_rx: "Текущий RX",
|
||
daily_tx: "Текущий TX",
|
||
daily_connections: "Соединений",
|
||
daily_memory: "Память",
|
||
choose_language: "Выберите язык:",
|
||
lang_current: "Текущий язык: %s",
|
||
lang_saved: "Язык сохранён!",
|
||
ping_enter_host: "Введите домен или IP для проверки:",
|
||
test_rule_prompt: "Введите правило для проверки:",
|
||
rule_label: "Правило",
|
||
|
||
// ─── Speed test ───
|
||
speed_starting: "⚡ <b>Запуск Speedtest...</b>\n\nТестирую скорость через Cloudflare. Это займёт до 30 секунд.",
|
||
speed_result: "⚡ Результат Speedtest",
|
||
speed_direct: "📥 Прямое соединение:",
|
||
speed_proxy: "📤 Через прокси:",
|
||
speed_fail_measure: "❌ не удалось измерить",
|
||
speed_error: "❌ Не удалось выполнить тест. Проверьте, запущен ли sing-box.",
|
||
speed_check_hint: "Проверьте доступ в интернет и работу sing-box.",
|
||
|
||
// ─── Ping ───
|
||
ping_api_error: "❌ Не удалось получить данные из Clash API.",
|
||
|
||
// ─── Quick test ───
|
||
test_title: "Быстрая диагностика",
|
||
test_direct: "Прямое соединение",
|
||
test_proxy: "Прокси соединение",
|
||
test_service: "Tachyon сервис",
|
||
test_nft: "nftables правила",
|
||
test_pause: "Пауза:",
|
||
test_rule: "Проверка правила:",
|
||
test_match: "Совпадение",
|
||
test_no_match: "Совпадений не найдено. Трафик пойдёт через default route.",
|
||
|
||
// ─── Connections ───
|
||
conn_total_down: "Всего скачано",
|
||
conn_total_up: "Всего отдано",
|
||
conn_closed: "Все активные соединения сброшены.",
|
||
|
||
// ─── Devices ───
|
||
device_block: "🚫 Заблокировать",
|
||
device_unblock: "🔓 Разблокировать",
|
||
device_blocked: "заблокировано",
|
||
device_unblocked: "разблокировано",
|
||
|
||
// ─── AI Doctor ───
|
||
ai_doctor_title: "ИИ-Автомеханик Tachyon",
|
||
ai_status_collecting: "Сбор полного AI Watchdog статуса...",
|
||
ai_incident: "⚠️ Устранён инцидент:",
|
||
ai_resolution: "🔧 Авто-решение:",
|
||
ai_all_ok: "Все сетевые службы, DNS, nftables и память работают идеально.",
|
||
ai_diag_ok: "Диагностика завершена успешно.",
|
||
ai_diag_done: "Диагностика завершена.",
|
||
|
||
// ─── Buttons ───
|
||
btn_refresh: "🔄 Обновить",
|
||
btn_retry: "🔄 Повторить",
|
||
btn_again: "🔄 Ещё раз",
|
||
btn_speed_again: "⚡ Ещё раз",
|
||
btn_back_to_groups: "🔙 К списку групп",
|
||
btn_back_to_sections: "🔙 К списку секций",
|
||
btn_close_all: "❌ Закрыть все",
|
||
btn_test: "🩺 Тест",
|
||
nav_cancel: "⬅️ Отмена",
|
||
restart_confirm: "⚠️ <b>Перезапустить службы Tachyon?</b>\nТекущие соединения будут разорваны на время перезапуска.",
|
||
restart_yes: "✅ Да, перезапустить",
|
||
restart_in_progress: "Перезапускаю службы Tachyon...",
|
||
restart_success: "Перезапуск выполнен успешно!",
|
||
restart_error: "Ошибка при перезапуске.",
|
||
conn_closed: "Все активные соединения сброшены.",
|
||
|
||
// ─── Outbounds ───
|
||
servers_not_found: "Серверы не найдены или sing-box не запущен.",
|
||
outbounds_hint: "Нажмите кнопку, чтобы переключить сервер.",
|
||
|
||
// ─── Logs ───
|
||
logs_level: "уровень",
|
||
|
||
// ─── Info ───
|
||
info_device: "Устройство",
|
||
err_info_read: "Ошибка чтения информации:",
|
||
|
||
// ─── Updates ───
|
||
update_new_build: "Новая сборка текущего релиза!",
|
||
update_available: "Доступно обновление компонента!",
|
||
build_label: "Сборка",
|
||
|
||
// ─── Healer ───
|
||
heal_running: "ИИ-Автомеханик выполняет диагностику и самолечение...",
|
||
// ─── Batch i18n additions ───
|
||
msg_truncated: "... (сообщение сокращено)",
|
||
menu_version: "Версия",
|
||
menu_cpu: "Роутер CPU",
|
||
list_header: "⚙️ <b>Список:</b>",
|
||
outbound_groups_not_found: "Группы прокси не найдены.",
|
||
outbound_switch_failed: "Не удалось переключить сервер",
|
||
outbound_group: "Группа",
|
||
outbound_server: "Сервер",
|
||
outbound_check_hint: "Проверьте, запущен ли sing-box и доступен ли Clash API.",
|
||
section_ips: "IP адреса",
|
||
section_list_header: "⚙️ <b>Секция:</b>",
|
||
backup_archive_empty: "Архив пуст или повреждён.",
|
||
backup_archive_unsafe: "Небезопасный архив:",
|
||
backup_restoring: "Проверяю и восстанавливаю бэкап...",
|
||
backup_extract_failed: "Не удалось распаковать архив.",
|
||
backup_not_valid_uci: "config/tachyon в архиве не похож на валидный UCI.",
|
||
backup_no_config: "В архиве нет ни config/tachyon, ни каталога tachyon/.",
|
||
backup_save_config_failed: "Не удалось сохранить текущий конфиг.",
|
||
backup_save_data_failed: "Не удалось сохранить текущие данные /etc/tachyon.",
|
||
backup_write_config_error: "Ошибка записи /etc/config/tachyon.",
|
||
backup_uci_validation_failed: "Восстановленный конфиг не прошёл проверку UCI. Выполнен откат.",
|
||
backup_write_data_error: "Ошибка записи /etc/tachyon. Выполнен откат.",
|
||
backup_restored: "Бэкап восстановлен. Перезапускаю Tachyon...",
|
||
backup_done: "Готово!",
|
||
backup_collecting: "Собираю бэкап...",
|
||
backup_create_error: "Ошибка создания бэкапа.",
|
||
support_bundle_collecting: "Формирую Support Bundle...",
|
||
support_bundle_error: "Ошибка генерации Bundle.",
|
||
conn_closed_msg: "Все активные соединения сброшены.\nОни будут переустановлены по новым маршрутам.",
|
||
conn_close_error: "Ошибка сброса соединений.\nsing-box Clash API недоступен.",
|
||
updates_title: "Обновления компонентов",
|
||
updates_disabled: "Проверка обновлений отключена в настройках.",
|
||
updates_cache_empty: "Кэш пуст. Зайдите позже.",
|
||
update_check_error: "Ошибка проверки",
|
||
update_new_release_build: "новая сборка релиза",
|
||
update_dev_build: "dev-сборка",
|
||
update_all_current: "Все компоненты актуальны.",
|
||
update_cache_parse_error: "Ошибка парсинга кэша:",
|
||
update_cache_unavailable: "Кэш проверок пуст или недоступен.",
|
||
btn_refresh_cache: "Обновить кэш",
|
||
api_parse_error: "Ошибка парсинга API:",
|
||
api_connect_failed: "Не удалось подключиться к API sing-box.",
|
||
logs_header: "Логи Tachyon",
|
||
info_title: "Информация о системе",
|
||
info_device_label: "Устройство",
|
||
info_fetch_failed: "Не удалось получить информацию о системе.",
|
||
sub_empty_url: "(пусто)",
|
||
btn_sub_delete: " 🗑 Удалить",
|
||
btn_add_subscription: "Добавить подписку",
|
||
sub_section_subs: "Подписки секции",
|
||
sub_found_count: "Найдено подписок:",
|
||
sub_enter_url: "Введите URL подписки:\n\n<i>Отправьте /cancel для отмены</i>",
|
||
sub_url_empty: "URL не может быть пустым.",
|
||
sub_added: "Подписка добавлена в секцию",
|
||
sub_not_found: "Подписка не найдена.",
|
||
sub_removed: "Подписка удалена из секции",
|
||
help_title: "Справка по командам",
|
||
help_main_section: "Основные:",
|
||
help_diag_section: "Диагностика:",
|
||
help_manage_section: "Управление:",
|
||
help_settings_section: "Настройка:",
|
||
help_this: "Эта справка",
|
||
quiet_hours_title: "Тихие часы",
|
||
quiet_status: "Статус",
|
||
quiet_enabled_label: "Включены",
|
||
quiet_disabled_label: "Выключены",
|
||
quiet_start_label: "Начало:",
|
||
quiet_end_label: "Конец:",
|
||
quiet_hint: "В тихие часы бот отправляет только критические уведомления.",
|
||
btn_enable: "Включить",
|
||
btn_disable: "Выключить",
|
||
quiet_hour_start: "начала",
|
||
quiet_hour_end: "окончания",
|
||
quiet_enter_hour: "⏰ Введите час %s тихих часов (0–23):\n\n<i>Отправьте /cancel для отмены</i>",
|
||
test_rule_header: "Проверка правила:",
|
||
test_match: "Совпадение:",
|
||
test_action: "Действие:",
|
||
export_title: "Экспорт конфига...",
|
||
export_done: "Конфиг экспортирован.\n\n⚠️ Файл содержит чувствительные данные. Не публикуйте его.",
|
||
export_failed: "Не удалось экспортировать конфиг.",
|
||
mac_invalid: "Некорректный MAC-адрес.",
|
||
mac_firewall_open_failed: "Не удалось открыть конфигурацию firewall.",
|
||
mac_block_rule_failed: "Не удалось создать правило блокировки.",
|
||
mac_blocked: "заблокировано.",
|
||
mac_unblocked: "разблокировано.",
|
||
mac_firewall_bg: "Правила firewall применяются в фоне (несколько секунд).",
|
||
devices_title: "Устройства в сети:",
|
||
device_hostname_unknown: "Неизвестно",
|
||
devices_not_found: "Устройства не найдены.",
|
||
watchdog_stop_btn: "Остановить Watchdog",
|
||
ai_full_status_btn: "Полный статус AI",
|
||
watchdog_start_btn: "Запустить Watchdog",
|
||
ai_incident: "⚠️ Устранён инцидент:",
|
||
ai_resolution: "🔧 Авто-решение:",
|
||
ai_all_ok: "Все сетевые службы, DNS, nftables и память работают идеально.",
|
||
ai_diag_ok: "Диагностика завершена успешно.",
|
||
ai_diag_done: "Диагностика завершена.",
|
||
ai_status_collecting: "Сбор полного AI Watchdog статуса...",
|
||
ai_status_error: "Ошибка получения статуса.",
|
||
ai_data_truncated: "данные сокращены",
|
||
ai_full_status_header: "AI Watchdog — Полный статус:",
|
||
qos_title: "Игровой & Голосовой QoS Ускоритель",
|
||
qos_enabled_detail: "Включен (DSCP EF + AF41 Priority)",
|
||
qos_disabled_detail: "Выключен",
|
||
qos_priority_rules: "Приоритетные правила:",
|
||
btn_qos_disable: "Отключить QoS",
|
||
btn_qos_enable: "Включить QoS",
|
||
cb_obsolete: "Кнопка устарела — откройте список заново.",
|
||
update_component_title: "Запуск обновления",
|
||
update_bg_hint: "Процесс запущен в фоне. Зайдите позже.",
|
||
err_unknown_component: "Неизвестный компонент:",
|
||
admin_invalid_chat_id: "Неверный Chat ID.",
|
||
admin_user_added: "Пользователь добавлен в список администраторов.",
|
||
admin_user_already: "Пользователь уже является администратором.",
|
||
sec_enter_name: "Введите латинское имя для новой секции (например, <code>my_vpn</code>):\n\n<i>Отправьте /cancel для отмены</i>",
|
||
sec_enter_label: "Введите новое понятное имя (Label) для секции",
|
||
sec_enter_target: "Введите имя исходящего интерфейса (target) для секции",
|
||
sec_not_found: "Секция не найдена.",
|
||
sec_deleted: "Секция удалена.",
|
||
sec_add_items_prompt: "Отправьте элементы для добавления (по одному в строке или через пробел):\n\n<i>Отправьте /cancel для отмены</i>",
|
||
sec_sub_add_prompt: "Введите имя секции и URL подписки через пробел:\n<code>/sec_sub_add Main https://...</code>\n\n<i>Отправьте /cancel для отмены</i>",
|
||
sec_enter_value: "Введите новое значение для",
|
||
sec_add_list_prompt: "Отправьте элементы для добавления в список (через пробел или с новой строки):\n\n<i>Отправьте /cancel для отмены</i>",
|
||
dns_all_protocols: "Все протоколы",
|
||
dns_servers_applied: "DNS серверы установлены:",
|
||
dns_restart_hint: "Выполните перезапуск для применения.",
|
||
dns_bootstrap_applied: "Bootstrap DNS серверы установлены:",
|
||
exec_cmd_error: "Ошибка выполнения команды:",
|
||
exec_access_denied: "Доступ запрещен. Ваш Chat ID:",
|
||
backup_downloading: "Скачиваю бэкап...",
|
||
backup_download_error: "Ошибка загрузки файла.",
|
||
backup_url_error: "Ошибка получения URL файла.",
|
||
backup_format_hint: "Пожалуйста, отправьте бэкап в формате `.tar.gz`.",
|
||
admin_forward_prompt: "Вы переслали сообщение от пользователя",
|
||
btn_admin_add: "Добавить",
|
||
exec_whitelist_msg: "Выполняю из разрешённого набора (whitelist):",
|
||
exec_no_output: "Нет вывода",
|
||
action_cancelled: "Действие отменено.",
|
||
err_text_expected: "Ожидается текстовое сообщение. Попробуйте ещё раз или /cancel.",
|
||
value_saved: "Значение сохранено.",
|
||
items_added: "элементов.",
|
||
section_created: "Секция создана!",
|
||
err_invalid_section_name: "Неверное имя. Разрешены только буквы, цифры и подчеркивания.",
|
||
label_changed: "Имя изменено.",
|
||
target_changed: "Цель изменена.",
|
||
items_added_count: "Добавлено",
|
||
nothing_added: "Ничего не добавлено.",
|
||
err_format_section_url: "Формат: <code>секция URL</code>\nНапример: <code>Main https://...</code>",
|
||
err_invalid_hour: "Введите целое число от 0 до 23.",
|
||
saved: "Сохранено.",
|
||
daily_unknown: "неизвестно",
|
||
daily_uptime: "Аптайм ОС:",
|
||
daily_rx: "Текущий RX:",
|
||
daily_tx: "Текущий TX:",
|
||
build_label: "Сборка:",
|
||
blocked_activity: "Заблокированная активность",
|
||
blocked_rule_label: "Правило:",
|
||
blocked_rule: "Правило:",
|
||
blocked_attempts: "Попыток доступа к заблокированным сайтам",
|
||
info_read_error: "Ошибка чтения информации:",
|
||
quiet_start_word: "начала",
|
||
quiet_end_word: "окончания",
|
||
quiet_saved: "Настройки сохранены.",
|
||
sec_created: "Секция создана!",
|
||
sec_invalid_name: "Некорректное имя. Только латиница, цифры и _.",
|
||
sec_invalid_hour: "Некорректное время.",
|
||
sec_changed_to: "изменено на",
|
||
exec_value_saved: "Значение сохранено. Для вступления изменений в силу необходим перезапуск.",
|
||
exec_items_added: "Добавлено",
|
||
exec_items_added_count: "Добавлено",
|
||
exec_nothing_added: "Ничего не добавлено.",
|
||
exec_changed_to: "изменено на",
|
||
exec_format_hint: "Формат: domain.com или [ip]/prefix.",
|
||
update_new_release_header: "Новая сборка текущего релиза!",
|
||
update_build_label: "Сборка",
|
||
critical_keyword_fallen: "Упал",
|
||
critical_keyword_error: "Ошибка",
|
||
btn_update_component: "Обновить",
|
||
fptn_token_title: "FPTN Access Token",
|
||
fptn_token_prompt: "Пришлите новый токен доступа FPTN (скопируйте или перешлите из @fptn_bot):",
|
||
fptn_token_invalid: "Некорректный или пустой токен FPTN. Попробуйте ещё раз.",
|
||
fptn_token_no_section: "Токен сохранён, но секция с действием 'fptn' не найдена в конфиге.",
|
||
fptn_restarting: "Обновляю токен и запускаю FPTN...",
|
||
fptn_token_updated_title: "FPTN токен успешно обновлён и подключён!",
|
||
fptn_token_saved_connecting: "Токен сохранён, но FPTN пока подключается.",
|
||
fptn_token_retry_hint: "Подключение продолжится в фоне; маршрутизация применится автоматически.",
|
||
fptn_token_change_btn: "Сменить токен FPTN",
|
||
fptn_token_btn: "Токен FPTN",
|
||
}
|
||
};
|
||
|
||
// Resolve language: UCI setting → fallback to "en"
|
||
function resolve_lang(cfg_lang) {
|
||
let lang = cfg_lang || "en";
|
||
if (type(lang) != "string") lang = "en";
|
||
// trim whitespace
|
||
lang = replace(lang, /^\s+|\s+$/g, "");
|
||
if (lang == "" || (lang != "en" && lang != "ru")) lang = "en";
|
||
return lang;
|
||
}
|
||
|
||
// Return a translation function bound to the given language.
|
||
// Usage: let t = i18n.bind(lang); t("key") → translated string.
|
||
// Strings with %s placeholders use sprintf for substitution.
|
||
function bind(lang) {
|
||
lang = resolve_lang(lang);
|
||
return function(key, ...args) {
|
||
let table = strings[lang];
|
||
let val = table ? table[key] : null;
|
||
if (val == null) val = strings.en[key];
|
||
if (val == null) return key;
|
||
// sprintf-style substitution: pass extra args to t("key", arg1, arg2)
|
||
if (length(args) > 0) {
|
||
try { return sprintf(val, ...args); } catch(e) { return val; }
|
||
}
|
||
return val;
|
||
};
|
||
}
|
||
|
||
// Return available languages as [{code, label, available}]
|
||
function available_languages(cfg_lang) {
|
||
let current = resolve_lang(cfg_lang);
|
||
let langs = [
|
||
{ code: "en", label: "English", available: true },
|
||
{ code: "ru", label: "Русский", available: true }
|
||
];
|
||
return langs;
|
||
}
|
||
|
||
// Module exports
|
||
return { resolve_lang, bind, available_languages, strings };
|