{
  "common": {
    "save": "Save",
    "cancel": "Cancel",
    "delete": "Delete",
    "edit": "Edit",
    "add": "Add",
    "create": "Create",
    "back": "Back",
    "backToList": "Back to list",
    "loading": "Loading...",
    "error": "Error",
    "success": "Success",
    "confirm": "Confirm",
    "yes": "Yes",
    "no": "No",
    "enabled": "Enabled",
    "disabled": "Disabled",
    "enable": "Enable",
    "disable": "Disable",
    "active": "Active",
    "inactive": "Inactive",
    "expired": "Expired",
    "actions": "Actions",
    "status": "Status",
    "name": "Name",
    "description": "Description",
    "settings": "Settings",
    "online": "Online",
    "offline": "Offline",
    "unknown": "Unknown",
    "unlimited": "Unlimited",
    "none": "None",
    "all": "All",
    "search": "Search",
    "filter": "Filter",
    "refresh": "Refresh",
    "sync": "Sync",
    "download": "Download",
    "upload": "Upload",
    "close": "Close",
    "copied": "Copied!",
    "copy": "Copy",
    "total": "Total",
    "of": "of",
    "now": "now",
    "connections": "connections",
    "server": "Server",
    "ports": "Ports",
    "clear": "Clear"
  },
  "nav": {
    "dashboard": "Dashboard",
    "stats": "Statistics",
    "nodes": "Nodes",
    "network": "Network",
    "users": "Users",
    "groups": "Groups",
    "settings": "Settings",
    "logout": "Logout"
  },
  "auth": {
    "login": "Login",
    "password": "Password",
    "loginTitle": "Panel Login",
    "loginButton": "Sign In",
    "enterLogin": "Enter login",
    "enterPassword": "Enter password",
    "invalidCredentials": "Invalid username or password",
    "sessionExpired": "Session expired, please login again",
    "totpTitle": "Two-factor verification",
    "totpSetupTitle": "Set up two-factor authentication",
    "totpSettingsTitle": "Confirm TOTP setup",
    "totpPasswordChangeTitle": "Confirm password change",
    "totpPasswordChangeDescription": "Enter your current TOTP code to apply the new password.",
    "totpDisableTitle": "Confirm TOTP disable",
    "totpDisableDescription": "Enter your current TOTP code to disable two-factor authentication.",
    "totpRotateCurrentTitle": "Confirm current TOTP code",
    "totpRotateCurrentDescription": "Enter your current TOTP code to continue secret rotation.",
    "totpSetupDescription": "Scan the QR code in your authenticator app and enter the 6-digit code.",
    "totpLoginDescription": "Enter the code from your authenticator app to finish login.",
    "totpCode": "Verification code",
    "totpCodePlaceholder": "123456",
    "totpVerifyButton": "Verify",
    "totpApplyPasswordButton": "Apply new password",
    "totpDisableButton": "Disable TOTP",
    "totpContinueButton": "Continue",
    "totpQrHint": "If the QR code does not scan, use the manual secret.",
    "totpManualSecret": "Manual secret",
    "totpRequired": "Enter verification code",
    "invalidTotp": "Invalid verification code",
    "totpPendingExpired": "Verification session expired, please sign in again",
    "tooManyAttempts": "Too many login attempts. Try again in 15 minutes.",
    "tooManyTotpAttempts": "Too many verification attempts. Try again later.",
    "totpLoginLockoutMessage": "Login is temporarily blocked due to too many invalid TOTP codes.",
    "totpLockoutUntilLabel": "Unlocks at",
    "totpLockoutRemainingLabel": "Time remaining",
    "totpLockoutExpired": "Expired",
    "invalidCurrentPassword": "Invalid current password",
    "enterCurrentPassword": "Enter current password",
    "enterCurrentTotp": "Enter current TOTP code",
    "invalidCurrentTotp": "Invalid current TOTP code",
    "enterPasswordAndTotp": "Enter current password and TOTP code",
    "totpConfigError": "TOTP configuration error. Contact administrator",
    "totpFlowError": "Error starting TOTP flow",
    "totpConfirmError": "TOTP confirmation error",
    "totpDisableError": "Error disabling TOTP",
    "totpAlreadyEnabled": "TOTP is already enabled",
    "totpAlreadyDisabled": "TOTP is already disabled",
    "totpRequiredForRotate": "TOTP must be enabled to rotate secret",
    "totpDisabled": "TOTP successfully disabled",
    "totpEnabled": "TOTP successfully enabled",
    "totpRotated": "New TOTP secret successfully configured",
    "passwordChanged": "Password successfully changed"
  },
  "dashboard": {
    "title": "Dashboard",
    "totalUsers": "Total Users",
    "activeUsers": "active",
    "totalNodes": "Total Nodes",
    "onlineNodes": "online",
    "totalTraffic": "Total Traffic",
    "total": "total",
    "systemInfo": "System Info",
    "cpu": "CPU",
    "memory": "Memory",
    "uptime": "Uptime",
    "panelVersion": "Panel Version",
    "quickActions": "Quick Actions",
    "createBackup": "Create Backup",
    "restoreBackup": "Restore Backup",
    "recentLogs": "Logs",
    "nodesStatus": "Nodes Status",
    "load": "Load",
    "speed": "Speed",
    "node": "Node",
    "addNode": "Add Node",
    "noNodes": "No nodes",
    "noLogs": "No logs",
    "loadError": "Loading error",
    "panel": "Panel",
    "addUser": "Create User",
    "syncStarted": "Sync started...",
    "syncSuccess": "Sync started",
    "nodeRestarted": "Node restarted",
    "restartError": "Restart error",
    "creatingBackup": "Creating backup...",
    "backupDownloaded": "Backup downloaded",
    "backupError": "Backup error",
    "restoringDb": "Restoring database...",
    "dbRestored": "Database restored! Reloading...",
    "restoreConfirm": "Restore database from \"{filename}\"?\n\n⚠️ Current data will be replaced!",
    "backupDb": "Backup DB",
    "restoreDb": "Restore DB",
    "showAll": "Show all",
    "pauseLogs": "Pause logs",
    "resumeLogs": "Resume logs",
    "logsConnected": "Live",
    "logsDisconnected": "Disconnected"
  },
  "nodes": {
    "title": "Nodes",
    "addNode": "Add Node",
    "editNode": "Edit Node",
    "newNode": "New Node",
    "nodeName": "Name *",
    "nodeNamePlaceholder": "Germany, Netherlands...",
    "nodeNameHint": "Displayed in client subscription",
    "ipAddress": "IP Address *",
    "domain": "Domain (for SNI)",
    "domainHint": "Optional. Used for TLS certificate (ACME)",
    "sni": "SNI (Server Name Indication)",
    "sniHint": "Custom SNI for client connections (domain fronting). Only works with self-signed certificates (no domain). If domain is set, SNI must match it",
    "flag": "Flag (emoji)",
    "flagPlaceholder": "🇩🇪",
    "flagHint": "Country flag emoji",
    "comment": "Comment",
    "commentPlaceholder": "Provider, location, notes…",
    "commentHint": "Free-form note shown in the node list and dashboard (up to 500 characters)",
    "port": "Main Port",
    "portRange": "Port Hopping Range",
    "portRangeHint": "Clients will connect to these ports",
    "statsPort": "Stats API Port",
    "statsSecret": "API Secret",
    "sectionStatsApi": "Stats API",
    "sectionStatsHint": "Traffic stats API settings.",
    "docsLink": "Open documentation",
    "groups": "Server Groups",
    "groupsHint": "Users of these groups will have access to this node. If not selected — available to all.",
    "noGroups": "No groups.",
    "createGroup": "Create a group",
    "sshSettings": "SSH Access (optional)",
    "sshSettingsHint": "For automatic node configuration management",
    "sshPort": "SSH Port",
    "sshUsername": "Username",
    "sshPassword": "SSH Password",
    "sshPasswordSet": "(set)",
    "sshPasswordPlaceholder": "Enter password",
    "sshPasswordKeep": "Leave empty to keep current",
    "sshPasswordEncrypted": "Password is stored encrypted",
    "sshPrivateKey": "Private Key",
    "sshPrivateKeySet": "(set)",
    "sshPrivateKeyHint": "Paste your private key (OpenSSH or PEM format). Leave empty to keep current.",
    "sshPrivateKeyEncrypted": "Private key is stored encrypted",
    "sshPrivateKeyClear": "Remove key",
    "sshPrivateKeyUpload": "Upload file",
    "generateSshKey": "Generate & Install SSH Key",
    "generateSshKeyHint": "Generates an ed25519 keypair and installs the public key on the server via SSH (requires password or existing key).",
    "generateSshKeyWarning": "Generate and install a new SSH key on this node?\n\nThis will:\n• Generate a new ed25519 keypair\n• Add the public key to ~/.ssh/authorized_keys\n• Save the private key to the panel (encrypted)\n\nThe existing password will remain unchanged.",
    "sshKeyGenerating": "Generating and installing key...",
    "sshKeyInstalled": "SSH key generated and installed!",
    "sshKeyError": "Key generation error",
    "downloadSshKey": "Download SSH Key",
    "downloadSshKeyMissing": "SSH private key is not configured for this node",
    "initScript": "Init Script",
    "initScriptHint": "Bash script executed before auto-setup via SSH (e.g. enable BBR, configure swap, install packages)",
    "initScriptUseLast": "Use last script",
    "initScriptRunning": "Running init script...",
    "initScriptDone": "Init script completed",
    "initScriptFailed": "Init script failed (non-fatal, setup continues)",
    "maxOnlineUsers": "Online Users Limit",
    "maxOnlineHint": "0 = unlimited. If exceeded, node is hidden from subscription (if enabled).",
    "rankingCoefficient": "Priority (ranking)",
    "rankingHint": "Lower = higher in subscription. Drag-and-drop on nodes page will overwrite this value",
    "sortByPriority": "By priority",
    "sortByName": "By name",
    "sortByOnline": "By online",
    "sortByStatus": "By status",
    "reorderSaved": "Order saved",
    "reorderFailed": "Failed to save order",
    "lbDragHint": "Load balancing is active — drag sets tiebreaker priority when nodes have equal load",
    "dragToReorder": "Drag to reorder",
    "hysteriaConfig": "Hysteria Configuration",
    "useCustomConfig": "Use custom config",
    "customConfigHint": "If enabled — this config will be used during sync instead of auto-generation",
    "customConfigLabel": "Config config.yaml",
    "customConfigFormat": "YAML format. Use 'Generate' button to fill with base config.",
    "generateConfig": "Generate base config",
    "loadCurrentConfig": "Load current from node",
    "cascadeRole": "Cascade Role",
    "cascadeRoleHint": "Defines the node's role in the cascade topology. Bridge nodes are hidden from user subscriptions.",
    "roleStandalone": "Regular standalone node",
    "rolePortal": "Accepts clients and tunnels traffic through the cascade",
    "roleBridge": "Internet exit point, hidden from user subscriptions",
    "roleRelay": "Intermediate hop, forwards traffic further down the chain",
    "country": "Country",
    "countryHint": "Country code for grouping on the network map",
    "bridgeNodeHint": "Bridge nodes are NOT visible in user subscriptions. Auto Setup will only install Xray (no Agent, no Reality). The actual bridge config is deployed when you create a cascade link.",
    "portalNodeHint": "Portal node — users connect here. Auto Setup works as usual (Xray + Agent + Reality). After setup, create a cascade link to connect to a Bridge node.",
    "nodeActive": "Node active",
    "activeColumn": "Active",
    "activeEnabled": "Node enabled",
    "activeDisabled": "Node disabled",
    "activeToggleError": "Failed to update node runtime state",
    "enableActiveTitle": "Start service and enable node",
    "disableActiveTitle": "Stop service and disable node",
    "enableActiveAria": "Start service and enable node",
    "disableActiveAria": "Stop service and disable node",
    "createNode": "Create Node",
    "saveNode": "Save",
    "management": "Management",
    "autoSetup": "Setup Automatically",
    "autoSetupConfirm": "Setup node automatically via SSH?\n\nThis will:\n• Install Hysteria (if not installed)\n• Generate certificate\n• Upload configuration\n• Setup port hopping\n• Restart service",
    "autoSetupConfirmXray": "Setup node automatically via SSH?\n\nThis will:\n• Install Xray-core (latest version)\n• Generate Reality keys (if needed)\n• Install CC Agent (no-SSH management)\n• Configure firewall\n• Start services",
    "setupRunning": "Setup in progress... This may take 1-2 minutes.",
    "terminal": "SSH Terminal",
    "broadcastTerminal": "Broadcast",
    "viewLogs": "View Logs",
    "checkStatus": "Check Status",
    "resetStatus": "Reset Status",
    "executionLogs": "Execution logs:",
    "loadingLogs": "Loading logs...",
    "checking": "Checking...",
    "resettingStatus": "Resetting status...",
    "statusReset": "Status reset to online",
    "nodeConfig": "Config for Node",
    "configHint": "Copy this config to <code>/etc/hysteria/config.yaml</code> on the server:",
    "loadConfigConfirm": "Load current config from node via SSH?",
    "configLoaded": "Config loaded!",
    "saveFirst": "Save the node first",
    "syncNode": "Sync Node",
    "nodeStatus": "Node Status",
    "onlineUsers": "Online",
    "lastSync": "Last Sync",
    "customConfig": "Custom Config",
    "confirmDelete": "Delete node?",
    "confirmDeleteFull": "Are you sure you want to delete this node?",
    "setupInProgress": "Setup in progress...",
    "setupComplete": "Setup completed!",
    "setupFailed": "Setup failed",
    "noNodes": "No nodes added",
    "addFirstNode": "Add first node",
    "ipAlreadyExists": "A node with this IP already exists",
    "ipTypeConflict": "A {protocol} node with this IP already exists",
    "addPairedProtocol": "Add second protocol on this server",
    "dualProtocol": "Dual protocol",
    "siblingNodeDetected": "SSH settings will sync automatically from the existing node.",
    "siblingExistsHint": "{protocol} node already exists at this IP — SSH credentials will be synced automatically.",
    "nameAndIpRequired": "Name and IP address are required",
    "sectionProtocol": "Protocol",
    "virtualName": "Virtual",
    "virtualDesc": "Balancer · auto-routes between real nodes",
    "virtualSection": "Virtual / balancer settings",
    "virtualSectionHint": "A virtual node aggregates several real servers into one balanced subscription entry. The client's Xray core picks the best server based on the chosen strategy. No remote setup is needed.",
    "virtualSelectMode": "Source nodes",
    "virtualSelectModeManual": "Manual",
    "virtualSelectModeManualHint": "Pick specific nodes to aggregate.",
    "virtualSelectModeGroup": "By group",
    "virtualSelectModeGroupHint": "All active nodes from the selected group are picked up automatically.",
    "virtualSources": "Pick source nodes",
    "virtualSourcesHint": "Only checked nodes will participate in this balancer. The client always sees one entry — Xray decides which source to route through.",
    "virtualNoCandidates": "No candidate nodes available. Create some hysteria/xray nodes first.",
    "virtualSourceGroup": "Source group",
    "virtualSourceGroupHint": "All active non-virtual nodes from this group will be balanced. Nodes added to the group later are picked up automatically.",
    "virtualSourceGroupPlaceholder": "— Select group —",
    "virtualStrategy": "Selection strategy",
    "virtualStrategyHint": "How Xray on the client picks an outbound. leastLoad/leastPing require the observatory below.",
    "virtualStrategyRandom": "Random",
    "virtualStrategyRandomDesc": "Picks a random source on each connection. No probes. Good when servers are equivalent.",
    "virtualStrategyRoundRobin": "Round Robin",
    "virtualStrategyRoundRobinDesc": "Cycles through sources. Even distribution, no quality awareness.",
    "virtualStrategyLeastPing": "Least Ping",
    "virtualStrategyLeastPingDesc": "Picks the source with the lowest probed latency. Requires the observatory below.",
    "virtualStrategyLeastLoad": "Least Load",
    "virtualStrategyLeastLoadDesc": "Picks the most stable source (lowest jitter). Recommended for VPN. Requires burstObservatory.",
    "virtualObservatory": "Observatory (probe config)",
    "virtualObservatoryHint": "Xray pings each source periodically to evaluate its health. Defaults work well for most cases.",
    "virtualObsDestination": "Probe URL",
    "virtualObsDestinationHint": "URL probed via each source. Should return HTTP 204 quickly. Default — Google.",
    "virtualObsConnectivity": "Connectivity URL",
    "virtualObsConnectivityHint": "Optional. A probe is treated as failed only if this URL is also unreachable directly. Leave empty to disable.",
    "virtualObsConnectivityPlaceholder": "leave empty for default",
    "virtualObsInterval": "Interval",
    "virtualObsIntervalHint": "How often to probe. Smaller = faster reaction, larger = lower battery cost.",
    "virtualObsTimeout": "Timeout",
    "virtualObsTimeoutHint": "How long to wait for the probe before marking as slow.",
    "virtualObsSampling": "Samples",
    "virtualObsSamplingHint": "How many recent probes to consider. More samples = more stable choice.",
    "virtualFallbackToFirst": "Fallback to the first source",
    "virtualFallbackToFirstHint": "When all sources fail probing, route through the first source instead of dropping traffic.",
    "virtualNoStatus": "Virtual nodes don't connect to a server — they aggregate other nodes",
    "sectionNetwork": "Network",
    "sectionObfuscation": "Obfuscation (obfs)",
    "sectionObfuscationHint": "Salamander hides QUIC traffic from DPI. Enable only if your ISP blocks Hysteria — may perform worse on mobile networks. Note: when enabled, the server is no longer compatible with standard QUIC and no longer a valid HTTP/3 server.",
    "sectionLimits": "Limits & Priority",
    "hopInterval": "Port Hopping Interval",
    "hopIntervalHint": "Port hopping interval (`hopInterval`). Default: 30s, minimum: 5s.",
    "sectionAcmeAdvanced": "ACME",
    "sectionAcmeAdvancedHint": "Advanced ACME options.",
    "acmeAdvancedToggle": "Advanced ACME options",
    "optionalSuffix": "optional",
    "advancedSettings": "Advanced Parameters (optional)",
    "acmeEmail": "ACME Email",
    "acmeCa": "ACME CA",
    "acmeListenHost": "ACME Listen Host",
    "acmeType": "ACME Challenge Type",
    "acmeTypeAuto": "auto (default)",
    "acmeDisableHttpChallenge": "Disable HTTP challenge",
    "acmeDisableTlsAlpnChallenge": "Disable TLS-ALPN challenge",
    "acmeHttpAltPort": "HTTP Alt Port",
    "acmeTlsAltPort": "TLS Alt Port",
    "acmeDnsName": "DNS Provider",
    "acmeDnsProviderHint": "Available provider names are listed in ACME DNS config docs.",
    "acmeDnsConfig": "DNS Provider Config (JSON)",
    "acmeDnsConfigHint": "Raw JSON object for provider-specific credentials/options.",
    "sectionMasquerade": "Masquerade",
    "sectionMasqueradeHint": "Masquerade modes from docs: `proxy` and `string` (`file` mode is intentionally not exposed in UI).",
    "masqueradeType": "Masquerade Mode",
    "masqueradeProxyUrl": "Proxy URL",
    "masqueradeProxyRewriteHost": "Rewrite the Host header",
    "masqueradeProxyInsecure": "Disable TLS verification for the proxied website",
    "masqueradeStringContent": "String to return",
    "masqueradeStringStatusCode": "Status Code",
    "masqueradeStringHeaders": "Response Headers",
    "masqueradeStringHeadersHint": "One header per line: key: value",
    "masqueradeListenHttp": "HTTP (TCP) Listen Address",
    "masqueradeListenHttps": "HTTPS (TCP) Listen Address",
    "masqueradeForceHttps": "Force HTTPS (redirect all HTTP requests)",
    "sectionBandwidth": "Bandwidth",
    "sectionBandwidthHint": "Server-side upload/download limits and client limit policy.",
    "sectionSpeedTest": "Speed Test",
    "sectionSpeedTestHint": "Enables built-in speed test responses for Hysteria clients.",
    "sectionUdp": "UDP tweaks",
    "sectionUdpHint": "UDP forwarding behavior and idle timeout.",
    "sectionSniff": "Protocol Sniffing",
    "sectionSniffHint": "Protocol sniffing parameters.",
    "sectionQuic": "QUIC Parameters",
    "sectionQuicHint": "Advanced QUIC transport parameters.",
    "optionalSectionHint": "Optional.",
    "enableOptionalSection": "Enable optional parameters",
    "sectionPerformance": "Bandwidth, Speed Test, and UDP",
    "bandwidthUp": "Server upload bandwidth limit (up)",
    "bandwidthDown": "Server download bandwidth limit (down)",
    "ignoreClientBandwidth": "Ignore client bandwidth",
    "speedTest": "Enable Speed Test",
    "enableAcl": "Enable ACL",
    "enableBandwidth": "Enable Bandwidth",
    "enableUdpTweaks": "Enable UDP tweaks",
    "disableUdp": "Disable UDP forwarding",
    "udpIdleTimeout": "UDP idle timeout",
    "sectionSniffQuic": "Protocol Sniffing & QUIC parameters",
    "sectionSniffQuicHint": "Advanced options from Full Server Config.",
    "sniffDocsLink": "Protocol Sniffing docs",
    "quicDocsLink": "QUIC parameters docs",
    "sniffEnable": "Enable protocol sniffing",
    "sniffRewriteDomain": "Rewrite requests that are already domain-based",
    "sniffTimeout": "Sniffing timeout",
    "sniffTcpPorts": "TCP port list",
    "sniffUdpPorts": "UDP port list",
    "sniffPortsHint": "Same format as Port Hopping: comma-separated ports/ranges, or `all`.",
    "quicInitStreamReceiveWindow": "Initial QUIC stream receive window",
    "quicMaxStreamReceiveWindow": "Maximum QUIC stream receive window",
    "quicInitConnReceiveWindow": "Initial QUIC connection receive window",
    "quicMaxConnReceiveWindow": "Maximum QUIC connection receive window",
    "quicMaxIdleTimeout": "Maximum idle timeout",
    "quicMaxIncomingStreams": "Maximum concurrent incoming streams",
    "quicDisablePathMtuDiscovery": "Disable QUIC path MTU discovery",
    "sectionResolver": "Resolver",
    "sectionResolverHint": "DNS resolver settings used by the server.",
    "resolverEnabled": "Enable custom resolver",
    "resolverType": "Resolver type",
    "resolverAddr": "Resolver address",
    "resolverTimeout": "DNS query timeout",
    "resolverSni": "Resolver SNI",
    "resolverInsecure": "Skip TLS verification",
    "sectionAcl": "ACL",
    "sectionAclHint": "Use either `inline` or `file` (not both). GeoIP/GeoSite options are optional.",
    "aclType": "ACL source type",
    "aclFile": "ACL File Path",
    "aclInlineRules": "ACL inline rules",
    "aclInlineRulesHint": "One rule per line. If empty, legacy default ACL rules are used.",
    "aclGeoip": "GeoIP database path",
    "aclGeosite": "GeoSite database path",
    "aclGeoUpdateInterval": "Geo database update interval",
    "aclRulesEditorHint": "Inline ACL rules are edited on the",
    "aclRulesEditorLink": "Outbounds / ACL page",
    "domainHintHysteria": "If set — TLS certificate will be issued automatically (ACME). Also used in subscription URLs instead of IP.",
    "sniHintHysteria": "Custom SNI for clients. Works ONLY without domain (self-signed cert). If domain is set — this field is ignored.",
    "outboundsAclLockedDisabled": "Outbounds ACL editor is unavailable because ACL is disabled for this node.",
    "hintDomain": "Domain for SNI and ACME certificates",
    "hintPortRange": "UDP port range for port hopping (e.g., 20000-50000)",
    "hintMaxOnline": "0 = unlimited. Used for load balancing",
    "hintRanking": "Lower value = higher priority in subscription",
    "off": "off",
    "deleteError": "Delete error",
    "restart": "Restart",
    "reconnect": "Reconnect",
    "sshNotConfigured": "SSH not configured. Auto-setup and terminal require SSH credentials.",
    "allStatuses": "All Statuses",
    "statusOnline": "Online",
    "statusOffline": "Offline",
    "statusError": "Error",
    "restartSuccess": "Node restarted",
    "restartFailed": "Restart failed",
    "xraySettings": "Xray VLESS Settings",
    "xrayTransport": "Transport",
    "xraySecurity": "Security",
    "xraySecurityReality": "Reality (no cert needed)",
    "xraySecurityTls": "TLS (cert files)",
    "xraySecurityNone": "None",
    "xrayFingerprint": "TLS Fingerprint",
    "xrayFingerprintHint": "uTLS fingerprint for TLS handshake (Reality/TLS)",
    "xrayFingerprintPoolHint": "The published fingerprint is chosen at random from the selected ones.",
    "xrayFingerprintModeSingle": "Single fingerprint",
    "xrayFingerprintModeSingleHint": "Always publish one fixed fingerprint.",
    "xrayFingerprintModePool": "Random from a set",
    "xrayFingerprintModePoolHint": "Pick several; a random one is published and rotates when the subscription cache refreshes (per cache TTL).",
    "xrayAlpn": "ALPN",
    "xrayAlpnHint": "Comma-separated: h3, h2, http/1.1 (TLS only)",
    "xrayFlow": "Flow (XTLS)",
    "xrayFlowHint": "Only for TCP + Reality/TLS. Leave empty for WebSocket/gRPC/XHTTP.",
    "xrayRealityDest": "Reality Destination",
    "xrayRealityDestHint": "TLS 1.3 + H2 website to impersonate (host:port)",
    "xrayRealitySni": "Reality SNI (serverNames)",
    "xrayRealitySniHint": "Comma-separated. Must match destination certificate",
    "sniScan": "Find SNI",
    "sniScanTitle": "SNI Scanner",
    "sniScanHint": "Scans the /24 subnet of the node IP for hosts that support TLS 1.3 + H2 — suitable as Reality destination & SNI.",
    "sniScanPortLabel": "Port",
    "sniScanThreads": "Threads",
    "sniScanTimeout": "Timeout (s)",
    "sniScanStart": "Scan",
    "sniScanStop": "Stop",
    "sniScanResults": "Results",
    "sniScanNoResults": "No suitable SNI hosts found in this subnet.",
    "sniScanApply": "Use",
    "sniScanDomain": "Domain",
    "sniScanPing": "Ping",
    "sniScanIp": "IP",
    "sniScanIssuer": "Issuer",
    "sniScanNeighborHint": "Same /24 subnet as your node — ideal for Reality",
    "sniScanOtherHint": "Domain's real IP is outside the scanned subnet",
    "sniScanFound": "found",
    "sniScanScanning": "Scanning…",
    "sniScanVerifying": "Verifying domains…",
    "sniScanDone": "Done",
    "sniScanErrIp": "Enter a valid IPv4 address",
    "xrayPrivateKey": "Private Key",
    "xrayPublicKey": "Public Key",
    "xrayShortIds": "Short IDs",
    "xrayShortIdsHint": "Comma-separated hex strings (0-16 chars). Empty string is valid.",
    "xraySpiderX": "Spider X (spider start path)",
    "xraySpiderXHint": "Starting URL for the REALITY spider on active probe. Best left empty (REALITY uses a random path) or set to a realistic path matching your SNI (e.g. /r/programming/ for www.reddit.com, /search?q=cloud for www.bing.com). Avoid identical values across nodes — that creates a signature.",
    "xrayWsPath": "WebSocket Path",
    "xrayWsHost": "WebSocket Host Header",
    "xrayWsHostHint": "For CDN (Cloudflare). Leave empty if not using CDN.",
    "xrayGrpcService": "gRPC Service Name",
    "xrayXhttpPath": "XHTTP Path",
    "xrayXhttpHost": "XHTTP Host Header",
    "xrayXhttpHostHint": "For CDN. Leave empty if not using CDN.",
    "xrayXhttpMode": "XHTTP Mode",
    "xrayXhttpModeHint": "auto (recommended), packet-up (strict CDN), stream-up (H2/H3), stream-one (single bidirectional stream)",
    "xrayTlsSourceLabel": "TLS certificate source",
    "xrayTlsSourceScopeHint": "One certificate strategy per node — applies to every TLS inbound (main and extras).",
    "xrayTlsSourcePanel": "Panel domain",
    "xrayTlsSourcePanelHint": "Masquerade under the panel domain — its Let's Encrypt certificate is inlined into the node config and rotated automatically.",
    "xrayTlsSourceAcme": "Auto ACME (separate node domain)",
    "xrayTlsSourceAcmeHint": "Panel installs acme.sh on the node, issues a Let's Encrypt cert for the node's own domain via HTTP-01, and lets acme.sh's cron renew it. Xray hot-reloads the cert on rotation — no panel push needed.",
    "xrayTlsAcmeInfoLine": "Make sure the node's domain DNS A-record points to the node IP and port 80 is free. Auto Setup installs acme.sh, issues the cert and registers the renewal cron.",
    "xrayTlsAcmeEmailLabel": "Let's Encrypt email",
    "xrayTlsAcmeEmailHint": "Used to register the ACME account. Leave empty to fall back to the panel-wide ACME_EMAIL env var.",
    "xrayTlsSourceManual": "Manual (custom domain + PEM)",
    "xrayTlsSourceManualHint": "Use a separate domain for the node and paste a full certificate chain and private key. The PEM is inlined into the node config.",
    "xrayTlsSourceSelfSigned": "Self-signed",
    "xrayTlsSourceSelfSignedHint": "A throwaway certificate is generated on the node. Clients must enable allowInsecure — testing only.",
    "xrayTlsRecommended": "Recommended",
    "xrayTlsTesting": "Testing",
    "xrayTlsEffectiveSni": "Effective SNI",
    "xrayTlsPanelDomainUnset": "PANEL_DOMAIN is not set — clients will fall back to node domain or IP",
    "xrayTlsPanelInfoLine": "No certificate file is created on the node — the panel ships its current LE cert in config.json on every sync.",
    "xrayTlsManualDomainHint": "Set the node domain in the Network section above (it doubles as the TLS server name).",
    "xrayTlsSelfSignedWarning": "Self-signed certificates are easy to fingerprint and require allowInsecure on every client.",
    "xrayTlsSelfSignedHint": "Use a real certificate (panel or manual) for production deployments.",
    "xrayManualCertLabel": "Certificate (PEM, full chain)",
    "xrayManualKeyLabel": "Private key (PEM)",
    "xrayManualCertHint": "Paste the full chain: leaf certificate followed by intermediates, each in its own BEGIN/END block.",
    "xrayManualKeyHint": "Paste the PKCS8/EC/RSA private key. Stored encrypted-at-rest by Mongo and never returned via the API.",
    "xrayManualKeyMaskedHint": "An existing private key is stored. Replace it by pasting a new PEM block, or leave the *** placeholder to keep the current key.",
    "xrayPemValid": "Valid PEM block",
    "xrayPemInvalid": "Not a valid PEM block — check BEGIN/END markers",
    "xrayPemStored": "Existing key kept",
    "domainHintXrayManual": "Domain used as the TLS server name and as the Host header for ws/xhttp transports.",
    "xrayApiPort": "Xray API Port (local)",
    "xrayApiPortHint": "Local port for management API (not public, default 61000)",
    "xrayFallbackDestLabel": "Fallback destination (optional)",
    "xrayFallbackDestHint": "Where to redirect non-VLESS traffic (active probes). Accepts port (8080), host:port (127.0.0.1:8080), [v6]:port or unix:/path. TCP+TLS only — Reality has its own dest masquerade.",
    "xrayFallbackDestPlaceholder": "127.0.0.1:8080",
    "xrayExtraInboundsTitle": "Additional inbounds",
    "xrayExtraInboundsHint": "Run extra VLESS inbounds on different ports/transports — clients receive every entry in their subscription.",
    "xrayAddInbound": "Add inbound",
    "xrayRemoveInbound": "Remove inbound",
    "xrayRemoveInboundConfirm": "Remove this inbound? Connected clients on this port will be disconnected on the next sync.",
    "xrayExtraInbound": "Extra inbound",
    "xrayInboundLabel": "Label",
    "xrayInboundLabelPlaceholder": "e.g. Mobile, CDN, Backup",
    "xrayInboundUniqueName": "Unique name",
    "xrayInboundUniqueNameHint": "When enabled, the subscription uses just the label instead of \"Node name (label)\"",
    "xrayInboundTag": "Inbound tag",
    "xrayInboundPortConflict": "This port is already used by another inbound or the API",
    "xrayInboundTagConflict": "This tag is already used by another inbound",
    "agentOutdatedTitle": "cc-agent is outdated",
    "agentOutdatedMessage": "Extra inbounds are configured, but the agent on this node is older than 1.2.0 — it cannot manage users on the additional inbounds. Re-run the node setup from the management section to upgrade the agent.",
    "xrayGenerateKeys": "Generate keys",
    "xrayKeysGenerated": "Keys generated!",
    "xrayAutoGenerated": "Auto-generated on setup",
    "nodeInfo": "Node Info",
    "xrayVersion": "Xray Version",
    "agentVersion": "Agent Version",
    "agentStatus": "Agent Status",
    "agentOnline": "Online",
    "agentOffline": "Offline",
    "usersInMemory": "Users in Memory",
    "agentLastSeen": "Last Seen",
    "agentPort": "Agent Port",
    "installAgent": "Install Agent",
    "cascadeLinks": "Cascade Links",
    "portalColumn": "Portal",
    "bridgeColumn": "Bridge",
    "thisNode": "this",
    "portConflictTitle": "Port conflict",
    "portConflictDesc": "Port 443/80 is used by the panel (Caddy). Xray on the same server must use a different port (e.g. 8443). Otherwise Xray will break the panel after a server reboot.",
    "obfsType": "Obfuscation type",
    "obfsPassword": "Obfs password",
    "obfsPasswordHint": "Same password must be set on both server and client.",
    "statsSecretAutoHint": "Leave empty — a secret will be generated automatically.",
    "xrayAutoGeneratedSetupHint": "Generated automatically during auto-setup.",
    "confirmDeployCascade": "Deploy this cascade link?",
    "confirmUndeployCascade": "Undeploy this cascade link?",
    "confirmDeleteCascade": "Delete cascade link \"{name}\"? This will also undeploy it.",
    "xrayGenerateKeysConfirm": "Generate new x25519 Reality keys via SSH? This will overwrite existing keys.",
    "xrayKeysSuccess": "Keys generated! Public key: {key}",
    "goToNetworkMap": "Network Map",
    "addCascadeLink": "Add Cascade Link"
  },
  "users": {
    "title": "Users",
    "addUser": "Add User",
    "editUser": "Edit User",
    "newUser": "New User",
    "userId": "User ID *",
    "userIdPlaceholder": "Telegram ID or unique ID",
    "userIdHint": "Unique user identifier",
    "username": "Username",
    "usernamePlaceholder": "@username",
    "usernameHint": "Optional, for display",
    "hysteriaPassword": "Hysteria Password",
    "password": "Password",
    "subscriptionUrl": "Subscription URL",
    "subscriptionLink": "Subscription Link",
    "universalLink": "Universal link (apps + browser):",
    "copySubscription": "Copy Subscription",
    "openSubscription": "Open Subscription",
    "groups": "Server Groups",
    "groupsHint": "User will have access to nodes from these groups. If not selected — access to all nodes without groups.",
    "trafficLimit": "Traffic Limit (GB)",
    "trafficLimitHint": "0 = unlimited",
    "trafficUsed": "Traffic Used",
    "traffic": "Traffic",
    "maxDevices": "Device Limit",
    "maxDevicesHint": "0 = group limit, -1 = unlimited",
    "devices": "Devices",
    "deviceFromGroup": "(group)",
    "expireDays": "Validity Period (days)",
    "expireDaysHint": "0 = unlimited",
    "expireModeLabel": "Expiration mode",
    "expireModeDays": "Days",
    "expireModeDatetime": "Date/time",
    "expireAtLabel": "Expiration date and time",
    "expireAtHint": "Select local date and time",
    "expireAtPastError": "Expiration date/time cannot be in the past",
    "expireAtInvalidError": "Invalid expiration date/time format",
    "expireAt": "Expires At",
    "expires": "Expires",
    "forever": "Forever",
    "createdAt": "Created At",
    "activateNow": "Activate now",
    "createUser": "Create User",
    "enable": "Enable",
    "disable": "Disable",
    "enableUser": "Enable User",
    "disableUser": "Disable User",
    "resetTraffic": "Reset Traffic",
    "deleteUser": "Delete User",
    "deleteSelected": "Delete selected",
    "selectVisible": "Select all visible users",
    "selectUser": "Select user",
    "confirmDelete": "Delete user",
    "confirmDeleteFull": "Are you sure you want to delete this user?",
    "confirmBulkDelete": "Delete selected users: {count}?",
    "bulkDeleteSuccess": "Deleted users: {count}",
    "bulkDeletePartial": "Deleted users: {count}. Issues: {issues}",
    "bulkDeleteError": "Bulk delete error",
    "noUsers": "No users",
    "createFirst": "Create first",
    "filterByGroup": "Filter by group",
    "filterByStatus": "Filter by status",
    "allGroups": "All Groups",
    "allStatuses": "All Statuses",
    "activeFilter": "Active",
    "inactiveFilter": "○ Inactive",
    "searchPlaceholder": "Search by userId, username...",
    "user": "User",
    "limits": "Limits",
    "availableNodes": "Available Nodes",
    "noNodes": "No nodes",
    "noGroupsAccess": "No groups (access to all nodes without groups)",
    "linkCopied": "Link copied",
    "copyError": "Copy error",
    "hintUserId": "Unique identifier (e.g., Telegram ID)",
    "hintTrafficLimit": "0 = unlimited, in GB",
    "hintMaxDevices": "0 = group limit, -1 = unlimited",
    "hintExpireAt": "Leave empty for no expiration",
    "txRx": "TX / RX",
    "groupsCount": "groups",
    "subscription": "Subscription",
    "details": "Details",
    "turnedOn": "Enabled",
    "turnedOff": "○ Disabled",
    "hwidDevices": "HWID devices",
    "hwidDevicesSummary": "HWID devices (via subscription):",
    "hwidModel": "Model",
    "hwidLastSeen": "Last seen",
    "unlinkDevice": "Unlink",
    "unlinkAllHwidDevices": "Unlink all HWID devices",
    "noHwidDevices": "No HWID devices yet. They appear when the user loads the subscription from a client that sends x-hwid.",
    "hwidMode": "HWID policy",
    "hwidModeHint": "Override panel HAPP HWID mode for this user.",
    "hwidModeInherit": "Inherit (panel)",
    "hwidModeOff": "Off",
    "hwidModeStrict": "Strict (require HWID)",
    "hwidEnforceFrom": "Enforce HWID limit from",
    "hwidEnforceFromHint": "Optional. Until this time, new HWIDs are recorded but not blocked. Empty = enforce when HWID applies.",
    "confirmUnlinkHwid": "Remove this HWID registration?",
    "confirmUnlinkAllHwid": "Remove all HWID registrations for this user?"
  },
  "groups": {
    "title": "Server Groups",
    "pageHint": "Groups allow flexible control of user access to servers",
    "addGroup": "Create Group",
    "editGroup": "Edit Group",
    "createGroup": "Create",
    "groupName": "Group Name",
    "groupNamePlaceholder": "Group name",
    "subscriptionTitle": "Name in App",
    "subscriptionTitlePlaceholder": "Name in app",
    "subscriptionTitleHint": "Displayed in client apps",
    "color": "Color",
    "colorHint": "Group color",
    "maxDevices": "Max Devices",
    "maxDevicesPlaceholder": "0",
    "maxDevicesHint": "Device limit (0 = unlimited)",
    "formHint": "Name in app — displayed in subscription list for clients. Device limit = 0 means unlimited.",
    "allGroups": "All Groups",
    "nodesCount": "nodes",
    "usersCount": "users",
    "isActive": "Active",
    "save": "Save",
    "confirmDelete": "Delete group {name}? It will be unlinked from all nodes and users.",
    "noGroups": "No groups yet. Create the first group above.",
    "noGroupsHint": "Groups help organize servers by regions, plans, or other criteria."
  },
  "settings": {
    "title": "Settings",
    "tabSystem": "System",
    "tabSubscription": "Subscription",
    "tabSecurity": "Security",
    "tabBackup": "Backups",
    "tabMaintenance": "Maintenance",
    "tabMigration": "Migration",
    "tabSystemDesc": "Performance, caching, rate limits and SSH pool.",
    "tabSubscriptionDesc": "Branding, buttons and client app behavior.",
    "tabSecurityDesc": "Administrator, 2FA, API keys, MCP and webhooks.",
    "tabBackupDesc": "Local and S3 backups, schedule, restore.",
    "tabMaintenanceDesc": "Maintenance tasks, cache, counters and danger zone.",
    "tabMigrationDesc": "Seamless import from a Marzban panel — old subscription links keep working.",
    "subBrandingTitle": "Page branding",
    "subProfileLinksTitle": "Hiddify profile",
    "sslNotConfigured": "SSL not configured",
    "general": "General Settings",
    "baseUrl": "Base URL",
    "port": "Port",
    "mongodb": "MongoDB",
    "systemSettings": "System Settings",
    "loadBalancing": "Load Balancing",
    "loadBalancingEnabled": "Sort by load",
    "loadBalancingHint": "Less loaded nodes will be first in subscription",
    "hideOverloaded": "Hide overloaded",
    "hideOverloadedHint": "Nodes with online ≥ limit won't be included in subscription",
    "hideOffline": "Hide unreachable",
    "hideOfflineHint": "Nodes marked offline/error by the health checker won't be served in subscriptions.",
    "deviceLimit": "Device Limit",
    "gracePeriod": "Grace period (min)",
    "gracePeriodHint": "How long to remember a client IP after the last Hysteria connection. Larger values smooth WiFi↔LTE switches; smaller values catch sharing faster.",
    "hyLimitTitle": "Hysteria connection limit",
    "hyLimitDesc": "Realtime cap on the number of distinct client IPs that may hold a Hysteria session. Hysteria 2 only — does not apply to VLESS / Xray nodes.",
    "howItWorks": "How it works:",
    "howItWorksDesc": "Devices are counted by unique IP addresses. If user connects from new IP and old one was active less than {minutes} minutes ago — both IPs count toward the limit.",
    "caching": "Caching (Redis)",
    "subscriptionsTTL": "Subscriptions (sec)",
    "subscriptionsTTLHint": "Ready configs. Reset on node changes",
    "usersTTL": "Users (sec)",
    "usersTTLHint": "Authorization. Reset on disconnect",
    "onlineSessionsTTL": "Online Sessions (sec)",
    "onlineSessionsTTLHint": "For device limit. Less = more accurate",
    "activeNodesTTL": "Active Nodes (sec)",
    "activeNodesTTLHint": "Faster reaction to node changes",
    "rateLimiting": "Rate Limiting",
    "subscriptionsPerMinute": "Subscriptions/min per IP",
    "subscriptionsPerMinuteHint": "Protection from token brute force. Norm: 60-100",
    "sshPool": "SSH Connection Pool",
    "sshPoolEnabled": "Enable SSH connection pool",
    "sshPoolHint": "Reuses SSH connections for faster operations. Saves ~200-500ms per operation.",
    "sshPoolIdleTime": "Idle timeout (sec)",
    "sshPoolIdleTimeHint": "Close connection after inactivity",
    "sshPoolTimeout": "Connect timeout (sec)",
    "sshPoolTimeoutHint": "Max time to establish connection",
    "sshPoolKeepalive": "Keepalive interval (sec)",
    "sshPoolKeepaliveHint": "Send keepalive packets to prevent NAT timeout",
    "sshPoolRetries": "Max retries",
    "sshPoolRetriesHint": "Reconnection attempts on failure",
    "sshPoolDisableWarning": "Disabling is not recommended. Without the pool, network instability can saturate CPU with direct SSH handshakes. Direct mode is now capped at 3 parallel connections, but the pool is more reliable.",
    "nodeAuth": "Node Auth API",
    "nodeAuthInsecure": "Allow self-signed certificates",
    "nodeAuthInsecureHint": "Enable if panel uses HTTP or self-signed SSL. Nodes will accept any certificate when connecting to auth API. Disable for production with valid SSL.",
    "homepage": "Domain Decoy",
    "homepageHint": "What to serve at the domain root (https://domain/). Instead of a giveaway redirect to /panel, visitors see a regular page.",
    "homepageModeNginx": "nginx welcome page (decoy)",
    "homepageModeCustom": "Custom HTML page",
    "homepageNoCustom": "no file uploaded",
    "homepageSaveMode": "Save mode",
    "homepageUpload": "Upload HTML file",
    "homepageUploadHint": "Max {kb} KB. After upload the mode is switched to Custom HTML automatically.",
    "homepageReset": "Reset to default",
    "homepageResetConfirm": "Delete uploaded page and revert to default?",
    "saveAllSettings": "Save All Settings",
    "security": "Security",
    "administrator": "Administrator",
    "lastLogin": "Last Login",
    "twoFactorStatus": "Two-factor authentication",
    "totpManagementTitle": "TOTP management",
    "totpStatusLabel": "TOTP status",
    "totpEnabledAtLabel": "Enabled at",
    "totpEnableHint": "Confirm your current password, then connect the new device with a QR code on the next screen.",
    "totpProtectedHint": "Confirm your password here, then enter the current TOTP code on the next screen to disable or rotate.",
    "totpEnableVerifyDescription": "Scan the QR code and enter the code from your authenticator app to finish enabling TOTP.",
    "totpRotateVerifyDescription": "Scan the new QR code and enter the code from your new device to complete secret rotation.",
    "totpCurrentCodeLabel": "Current TOTP code",
    "totpEnableAction": "Enable TOTP",
    "totpRotateAction": "Rotate secret",
    "totpDisableAction": "Disable TOTP",
    "never": "Never",
    "ipWhitelist": "IP Whitelist",
    "ipWhitelistDisabled": "Disabled (access for all)",
    "changePassword": "Change Password",
    "currentPassword": "Current password",
    "newPassword": "New password (min. 6 chars)",
    "confirmPassword": "Confirm password",
    "changePasswordBtn": "Change Password",
    "passwordTotpNextStepHint": "After password verification, you will be asked for the current TOTP code on a separate screen.",
    "sslCertificate": "SSL Certificate",
    "httpsActive": "HTTPS Active",
    "httpMode": "HTTP Mode",
    "httpModeHint": "To enable HTTPS set variables:",
    "letsEncryptAuto": "Let's Encrypt auto-renewal",
    "systemStatus": "System Status",
    "dangerZone": "Danger Zone",
    "resetStats": "Reset Statistics",
    "resetStatsDesc": "Delete all historical statistics data (online, traffic, nodes charts). This action is irreversible!",
    "resetStatsBtn": "Clear Statistics",
    "resetStatsConfirm": "⚠️ Delete all statistics history?\n\nThis will clear all charts and tables on the Statistics page.\n\nContinue?",
    "statsReset": "Statistics cleared ({count} records)",
    "resetTrafficCounter": "Reset Traffic Counter",
    "resetTrafficDesc": "Resets used traffic counter (tx/rx) for all users. This action is irreversible!",
    "resetAllTraffic": "Reset All Traffic",
    "resetConfirm": "⚠️ WARNING!\n\nAre you sure you want to reset traffic counter for ALL users?\n\nThis action is irreversible!",
    "resetConfirmFinal": "Final confirmation.\n\nCounters tx/rx will be reset for all users.\n\nContinue?",
    "resetting": "Resetting...",
    "trafficReset": "Traffic reset for {count} users",
    "backup": "Backup",
    "autoBackup": "Automatic Backup",
    "autoBackupHint": "Automatically create database backups on schedule",
    "backupHowItWorksTitle": "How it works",
    "backupHowItWorks": "Automatic backup is checked once per hour. The interval is counted from the last successful local backup. For automatic S3 upload, both \"Automatic Backup\" and \"Upload to S3\" must be enabled.",
    "backupInterval": "Interval (hours)",
    "backupIntervalHint": "How often to create backups (recommended: 24)",
    "keepLast": "Keep last",
    "keepLastHint": "How many local backups to keep (old ones are deleted automatically)",
    "lastBackup": "Last Backup",
    "s3Settings": "Upload to S3 (optional)",
    "s3Enabled": "Upload to S3",
    "s3EnabledHint": "Additionally send backups to S3-compatible storage",
    "s3Endpoint": "Endpoint (for MinIO)",
    "s3EndpointHint": "Leave empty for AWS S3",
    "s3Region": "Region",
    "s3Bucket": "Bucket",
    "s3Prefix": "Prefix",
    "s3PrefixHint": "Folder in bucket for backups",
    "s3AccessKey": "Access Key ID",
    "s3SecretKey": "Secret Access Key",
    "s3KeepLast": "Keep in S3",
    "s3KeepLastHint": "How many backups to keep in S3",
    "testS3": "Test S3 Write Access",
    "testingS3": "Testing...",
    "s3TestSuccess": "S3 write and delete permissions confirmed",
    "s3TestError": "Connection error: {error}",
    "s3UploadFailed": "S3 upload failed: {error}",
    "backupActions": "Quick Actions",
    "createBackupNow": "Create Backup Now",
    "creatingBackup": "Creating...",
    "backupCreated": "Backup created: {filename} ({size} MB)",
    "backupError": "Backup creation error",
    "backupsList": "Available Backups",
    "clickRefresh": "Click \"Refresh\" to load the list",
    "noBackups": "No backups available",
    "localBackups": "Local",
    "s3Backups": "S3 (cloud)",
    "restoreConfirm": "Restore from this backup?\n\n⚠️ Current data will be replaced!",
    "restoring": "Restoring...",
    "restored": "Database restored! Reloading...",
    "restoreError": "Restore error",
    "restoreBtn": "Restore",
    "downloadBtn": "Download",
    "downloadError": "Download error",
    "saved": "Settings saved",
    "hintLoadBalancing": "Sort nodes by current load in subscriptions",
    "hintHideOverloaded": "Don't show nodes that reached max online users",
    "cacheManagement": "Cache Management",
    "flushCache": "Flush Cache",
    "flushCacheDesc": "Clears all cached data in Redis (subscriptions, users, sessions). May temporarily increase server load.",
    "flushCacheBtn": "Flush Cache",
    "flushCacheConfirm": "Clear all cached data?\n\nThis will temporarily increase server load as cache rebuilds.",
    "flushing": "Flushing...",
    "cacheFlushed": "Cache cleared successfully",
    "tabSubscriptionTitle": "Subscription Settings",
    "subClientApps": "Client Applications",
    "subLogoUrl": "Logo URL",
    "subLogoUrlHint": "Link to an image (PNG/SVG/WebP). Leave empty to use the default icon.",
    "subPageTitle": "Page Title",
    "subPageTitleHint": "Text above the logo on the subscription page. Default: \"Connection\".",
    "subSupportUrl": "Support URL",
    "subSupportUrlHint": "Shown as a \"Support\" button in Hiddify. Example: https://t.me/yoursupport",
    "subWebPageUrl": "Web Page URL",
    "subWebPageUrlHint": "Shown as an \"Open Web Page\" button in Hiddify. Example: landing or user portal.",
    "subHappProviderId": "HAPP Provider ID",
    "subHappProviderIdHint": "Optional 8-character code from happ-proxy.com. Unlocks statistics and feedback button.",
    "subUpdateInterval": "Update Interval (hours)",
    "subUpdateIntervalHint": "How often clients auto-refresh the subscription. Sent as the Profile-Update-Interval response header. Range: 1–168 hours.",
    "subButtons": "Buttons on subscription page",
    "subButtonsHint": "Use {url} in the URL field to insert the subscription link (e.g. hiddify://import/{url}). For Shadowrocket use sub://{url_b64}. For query params use {url_encoded}. Icons: tabler.io/icons (e.g. ti-download).",
    "subAddButton": "Add button",
    "subLogoDefault": "Default",
    "subHiddifyProfileHint": "The links below appear in Hiddify / Clash as profile card buttons.",
    "subPageTitlePlaceholder": "Connection",
    "subTemplate": "Template",
    "subTplClients": "Clients",
    "subTplLinks": "Links",
    "subTplSupport": "Support",
    "subTplWebsite": "Website",
    "subIconSearch": "Search…",
    "subBtnLabelPlaceholder": "Hiddify",
    "subBtnUrlPlaceholder": "hiddify://import/{url}",
    "subBtnLabelTitle": "Button label",
    "subBtnUrlTitle": "URL — placeholders: {url}, {url_b64}, {url_encoded}",
    "subPickIcon": "Choose icon",
    "subDeleteBtn": "Remove",
    "happTitle": "HAPP Integration",
    "happDesc": "Settings delivered exclusively to HAPP clients via HTTP headers on every subscription update.",
    "happAnnounce": "Announcement",
    "happAnnounceHint": "Short message shown to users inside the app (max 200 characters). Non-ASCII text (e.g. Cyrillic) is encoded automatically.",
    "happAnnounceCounter": "{n}/200",
    "happAdvancedToggle": "Advanced settings (requires Provider ID)",
    "happAdvancedHint": "Fill in HAPP Provider ID in the subscription settings above to enable advanced HAPP features.",
    "happHideSettings": "Hide server configuration",
    "happHideSettingsHint": "Users cannot view or copy server connection details from the app.",
    "happNotifyExpire": "Notify before expiration",
    "happNotifyExpireHint": "Push notification 3 days before the subscription expires.",
    "happAlwaysHwid": "Force hardware ID (HWID)",
    "happAlwaysHwidHint": "User cannot disable HWID transmission in app settings.",
    "happHwidTitle": "HWID device limit",
    "happHwidIntro": "Limit how many physical devices a single subscription can be used on, by the x-hwid header sent by the client. Enforced at subscription fetch.",
    "happHwidMode": "Mode",
    "happHwidModeOff": "Off",
    "happHwidModePermissive": "Soft",
    "happHwidModeStrict": "Hard",
    "happHwidExplainOff": "Disabled. The panel does not track HWIDs and ignores the x-hwid header. No subscription-level device limit is enforced.",
    "happHwidExplainPermissive": "Clients that send the x-hwid header are tracked and capped by maxDevices when fetching the subscription. Clients that do not send x-hwid receive the regular subscription and are not counted at fetch time.",
    "happHwidExplainStrict": "Same as Soft, but clients without the x-hwid header are soft-blocked at subscription fetch: they receive a structurally valid subscription containing fake servers whose names are the “No HWID support” text below.",
    "happHwidExplainSoftBlock": "When a client that sends x-hwid exceeds the device limit, it receives the same soft-block: a subscription with fake servers named after the “Limit reached” text. HAPP additionally shows an in-app popup. No 4xx/5xx is returned, so clients do not break.",
    "happHwidCleanupDays": "Remove inactive HWIDs after (days)",
    "happHwidUpsertRate": "Upserts per device per minute",
    "happHwidUpsertRateHint": "Higher values shorten the cooldown before another DB upsert for the same HWID.",
    "happHwidNotSupportedRemark": "Fake server names — no HWID support",
    "happHwidNotSupportedRemarkHint": "Used in Hard mode for clients that do not send x-hwid. Each non-empty line becomes a separate fake server in the client UI. Up to 12 lines, 32 characters per line.",
    "happHwidMaxDevicesRemark": "Fake server names — limit reached",
    "happHwidMaxDevicesRemarkHint": "Shown to any client whose device limit is reached. Each non-empty line becomes a separate fake server. Up to 12 lines, 32 characters per line.",
    "happHwidAnnounce": "HAPP popup text — limit reached",
    "happHwidAnnounceHint": "Sent as the HAPP `announce` header in addition to the fake server. HAPP shows it as an in-app popup. Max 300 characters. Non-ASCII is base64-encoded automatically.",
    "happHwidTopUsers": "Top users by HWID count",
    "happHwidDeviceCount": "HWID rows",
    "happPingType": "Ping method",
    "happPingTypeHint": "How the app measures server latency.",
    "happPingTypeAuto": "Auto (app default)",
    "happPingTypeProxy": "Via Proxy (GET)",
    "happPingTypeProxyHead": "Via Proxy (HEAD)",
    "happPingTypeTcp": "TCP",
    "happPingTypeIcmp": "ICMP",
    "happPingUrl": "Ping check URL",
    "happPingUrlHint": "URL used for proxy ping check. Only applies when ping method is Via Proxy.",
    "happColorProfile": "Color theme (iOS)",
    "happColorProfileHint": "Custom color theme JSON. Create a theme in the HAPP iOS app (long-press Appearance Theme), export to clipboard, then paste here.",
    "happColorPresetViolet": "Violet",
    "happColorPresetTurquoise": "Turquoise",
    "happColorPresetClear": "Clear",
    "routingTitle": "Client-side Routing (Split Tunneling)",
    "routingDesc": "Configure which websites and services your users access directly (bypassing VPN) and which go through the VPN tunnel.",
    "routingEnabled": "Enable routing rules",
    "routingEnabledHint": "When disabled, subscriptions are generated without routing rules — all traffic goes through VPN.",
    "routingHowItWorks": "How does it work?",
    "routingHowItWorksDesc": "Routing rules are embedded into subscription configs delivered to VPN clients. When a user opens a website or app, the client checks the destination against these rules:<br>• <strong>direct</strong> — traffic goes directly, bypassing the VPN (e.g. local banking, government services).<br>• <strong>block</strong> — traffic is dropped (e.g. ads, trackers).<br>• Everything else goes through the VPN tunnel as usual.<br><br>Rules also configure <strong>Split DNS</strong>: domains matching direct rules are resolved via the domestic DNS server, while all other queries go through the encrypted remote DNS.",
    "routingPresets": "Presets",
    "routingPresetsHint": "Presets are additive — click multiple presets to combine them. For example, \"Bypass RU\" + \"Block Ads\" will add both rule sets. Duplicate rules are skipped automatically.",
    "presetBypassRu": "Bypass RU",
    "presetBypassRuDesc": "Russian sites & IPs direct",
    "presetBypassCn": "Bypass CN",
    "presetBypassCnDesc": "Chinese sites & IPs direct",
    "presetBlockAds": "Block Ads",
    "presetBlockAdsDesc": "Block ad & tracker networks",
    "presetBypassLan": "Bypass LAN",
    "presetBypassLanDesc": "Local network direct",
    "presetClear": "Clear all",
    "presetClearDesc": "Remove all rules",
    "routingRules": "Rules",
    "routingRulesHint": "Rules are applied top to bottom. First match wins. Disabled rules are skipped.",
    "routingNoRules": "No rules yet. Add manually or pick a preset above.",
    "routingAddRule": "Add rule",
    "routingAction": "Action",
    "routingType": "Type",
    "routingValue": "Value",
    "routingComment": "Comment",
    "routingEnabled2": "On",
    "routingActionDirect": "direct",
    "routingActionBlock": "block",
    "routingTypeDomainSuffix": "domain suffix",
    "routingTypeDomainKeyword": "keyword",
    "routingTypeDomain": "domain",
    "routingTypeGeosite": "geosite",
    "routingTypeGeoip": "geoip",
    "routingTypeIpCidr": "IP CIDR",
    "routingDns": "Split DNS",
    "routingDnsHint": "Domains matching \"direct\" rules are resolved via the domestic DNS. Everything else is resolved through the remote (encrypted) DNS via proxy tunnel.",
    "routingDnsDomestic": "Domestic DNS",
    "routingDnsDomesticHint": "Plain UDP DNS for direct domains (e.g. Yandex DNS: 77.88.8.8)",
    "routingDnsRemote": "Remote DNS",
    "routingDnsRemoteHint": "Encrypted DNS for proxied traffic (e.g. Cloudflare DoT: tls://1.1.1.1)",
    "routingClientSupport": "Client compatibility",
    "routingClientSupportDesc": "<strong>Full support:</strong> HAPP (native routing protocol), Clash Meta / Stash (YAML rules).<br><strong>Partial support:</strong> Hiddify / SFA / NekoBox (sing-box JSON — some clients may override rules with their own templates).<br><strong>No support:</strong> v2rayNG, Streisand, Shadowrocket — these clients use URI subscriptions which cannot carry routing rules. Users need to configure routing manually.",
    "clearRulesConfirm": "Remove all routing rules?"
  },
  "setup": {
    "title": "Initial Setup",
    "header": "Create the first administrator account and prepare the panel for a secure launch.",
    "createAdmin": "Create administrator account.",
    "createAdminTitle": "Administrator account",
    "createAdminCopy": "Create the first administrator account for this panel. You can enable two-factor authentication immediately to protect the control plane from the first sign-in.",
    "credentialsEncrypted": "Login and password will be stored encrypted.",
    "adminLogin": "Administrator Login",
    "minChars3": "Minimum 3 characters",
    "password": "Password",
    "minChars6": "Minimum 6 characters",
    "confirmPassword": "Confirm Password",
    "repeatPassword": "Repeat password",
    "securityOptionsTitle": "Security options",
    "enableTotpLabel": "Enable two-factor authentication (TOTP)",
    "enableTotpHint": "After account creation you will need to confirm setup in an authenticator app.",
    "noRecoveryWarning": "Version 1 has no self-service recovery. Save the secret in a safe place.",
    "createAccount": "Create Account",
    "rememberWarning": "Remember credentials — recovery is impossible!",
    "passwordsMismatch": "Passwords don't match!",
    "usernameTooShort": "Administrator username must be at least 3 characters long.",
    "passwordTooShort": "Password must be at least 6 characters long.",
    "featureSecurityTitle": "Secure access",
    "featureSecurityDesc": "Administrator credentials are protected, and TOTP can be enabled immediately during setup.",
    "featureFlowTitle": "Guided launch",
    "featureFlowDesc": "After sign-in you will continue to the onboarding flow to prepare the first nodes and starter access.",
    "featureRecoveryTitle": "Save recovery data",
    "featureRecoveryDesc": "Store the administrator credentials and the TOTP secret in a safe place before you continue."
  },
  "terminal": {
    "title": "SSH Terminal",
    "connecting": "Connecting...",
    "connectingTo": "Connecting to",
    "connected": "Connected",
    "disconnected": "Disconnected",
    "connectionClosed": "[Connection closed]",
    "connectionError": "Connection error",
    "wsError": "WebSocket connection error",
    "tryAgain": "Try Again"
  },
  "broadcast": {
    "title": "Broadcast Terminal",
    "nodes": "Nodes:",
    "selectAll": "Select All",
    "deselectAll": "Deselect All",
    "execute": "Execute",
    "cancel": "Cancel",
    "commandPlaceholder": "Enter command or paste a script...",
    "running": "Running...",
    "done": "Done",
    "noSSHNodes": "No nodes with SSH configured",
    "timeout": "Timed out",
    "exitCode": "exit",
    "empty": "Execute a command to see output from nodes",
    "summaryTotal": "Total:",
    "summaryOk": "OK:",
    "summaryFailed": "Failed:"
  },
  "backup": {
    "creating": "Creating backup...",
    "created": "Backup created",
    "restoring": "Restoring...",
    "restored": "Database restored",
    "selectFile": "Select backup file (.tar.gz)",
    "confirmRestore": "This will replace all data. Continue?"
  },
  "errors": {
    "notFound": "Not found",
    "serverError": "Server error",
    "networkError": "Network error",
    "unauthorized": "Unauthorized",
    "forbidden": "Access denied",
    "validationError": "Validation error",
    "error": "Error",
    "deleteError": "Delete error"
  },
  "time": {
    "days": "d",
    "hours": "h",
    "minutes": "m",
    "seconds": "s",
    "ago": "ago",
    "never": "Never"
  },
  "units": {
    "bytes": "B",
    "kb": "KB",
    "mb": "MB",
    "gb": "GB",
    "tb": "TB"
  },
  "outbounds": {
    "title": "Traffic Filtering",
    "pageDesc": "Rules determine what to block, allow, or redirect through a proxy.",
    "presets": "Presets",
    "presetsHint": "— click to apply",
    "blockAds": "Block Ads",
    "blockAdsDesc": "doubleclick, googlesyndication, etc.",
    "blockCn": "Block CN / Private",
    "blockCnDesc": "Chinese and private IP addresses",
    "directAll": "All Direct",
    "directAllDesc": "No restrictions, all traffic allowed",
    "reset": "Reset",
    "resetDesc": "Remove all rules, return to default",
    "rules": "Rules",
    "rulesHint": "One rule per line. Two built-in actions: <code>reject(…)</code> — block, <code>direct(…)</code> — allow through server. Rules apply <strong>top to bottom</strong>, first match wins.",
    "aclInlineDisabled": "ACL inline editor is disabled: ACL is turned off in node settings.",
    "aclInlineDisabledFile": "ACL inline editor is disabled: ACL source type is set to file mode in node settings.",
    "noProxyWarning": "Proxy exists but no rules — proxy won't be used. Add a rule like:",
    "proxyChipsHint": "Your proxies — click to insert into rule:",
    "templates": "Templates",
    "defaultRulesWarning": "If you set rules, server defaults (<code>reject(geoip:cn)</code>, <code>reject(geoip:private)</code>) will be disabled. Add them manually if needed.",
    "yamlPreview": "YAML Preview",
    "proxyServers": "Proxy Servers",
    "proxyServersHint": "for routing traffic through SOCKS5/HTTP proxy",
    "proxyDesc": "Only needed if you want to route some traffic through <strong>your own proxy server</strong>. Add proxy here, then use its name in rules above: <code>proxy_name(condition)</code>",
    "proxyName": "Name",
    "proxyType": "Type",
    "proxyAddr": "Address (host:port)",
    "proxyLogin": "Login",
    "proxyPassword": "Password",
    "proxyOptional": "(optional)",
    "addProxy": "+ Add",
    "saveAndApply": "Save & Apply to Node",
    "applying": "Applying...",
    "applied": "Applied",
    "applyError": "Apply error",
    "replaceRules": "Replace current rules?",
    "noRulesDefault": "(no rules — using default config)",
    "backToNode": "Back to node"
  },
  "stats": {
    "title": "Statistics",
    "onlineNow": "Online Now",
    "peakOnline": "Peak Online",
    "last24h": "last 24h",
    "nodesOnline": "nodes online",
    "active": "active",
    "onlineConnections": "Online Connections",
    "traffic": "Traffic",
    "nodesUsage": "Nodes Usage",
    "nodesStats": "Nodes Statistics",
    "allNodes": "All Nodes",
    "node": "Node",
    "currentOnline": "Current",
    "avgOnline": "Average",
    "online": "Online",
    "upload": "Upload",
    "download": "Download",
    "tx": "TX (upload)",
    "rx": "RX (download)",
    "nodesTraffic": "Traffic by node",
    "noData": "No data",
    "hourChange": "hour change",
    "h": "h",
    "d": "d",
    "hint": "Data updates every 5 minutes. Select a period to view history.",
    "clientsTitle": "VPN Clients",
    "clientsDesc": "Unique users per VPN client app, based on subscription requests. Counted by unique subscription token per day.",
    "clientName": "Client",
    "uniqueUsers": "unique users",
    "percentage": "%",
    "clientsNoData": "No subscription requests recorded yet",
    "serverCpu": "CPU",
    "serverLoad": "Load 1m",
    "serverMemory": "Memory",
    "serverRss": "Process RSS",
    "serverRpm": "Requests per minute"
  },
  "apiKeys": {
    "title": "API Keys",
    "create": "Create Key",
    "createTitle": "Create API Key",
    "name": "Name",
    "namePlaceholder": "e.g. Telegram Bot",
    "prefix": "Key Prefix",
    "scopes": "Scopes",
    "scopesHint": "No scopes selected = no access.",
    "rateLimit": "Rate Limit (req/min)",
    "allowedIPs": "Allowed IPs (one per line, empty = all)",
    "expiresAt": "Expires At (optional)",
    "lastUsed": "Last Used",
    "expires": "Expires",
    "empty": "No API keys yet. Create one to enable external integrations.",
    "created": "Key Created",
    "revealWarning": "Copy this key now. It will never be shown again.",
    "copy": "Copy",
    "done": "Done, I copied it",
    "confirmDisable": "Disable this key?",
    "confirmEnable": "Enable this key?",
    "confirmDelete": "Delete key"
  },
  "webhooks": {
    "title": "Webhooks",
    "enabled": "Enable webhooks",
    "url": "Webhook URL",
    "secret": "Secret (HMAC-SHA256)",
    "secretPlaceholder": "Leave empty to skip signature verification",
    "secretHint": "Verify via X-Webhook-Signature header: sha256=HMAC-SHA256(secret, timestamp.body)",
    "events": "Events",
    "eventsHint": "empty = all events",
    "test": "Test",
    "urlRequired": "Enter a URL first",
    "testEventDefault": "Generic test",
    "testEventHint": "Send a sample payload for this event"
  },
  "network": {
    "title": "Network Map",
    "nodes": "nodes",
    "links": "links",
    "addLink": "Add Link",
    "createLink": "Create Link",
    "autoLayout": "Auto Layout",
    "fitView": "Fit View",
    "refresh": "Refresh",
    "linkName": "Link Name",
    "portalNode": "Portal Node (Entry)",
    "bridgeNode": "Bridge Node (Exit)",
    "tunnelPort": "Tunnel Port",
    "tunnelProtocol": "Protocol",
    "tunnelTransport": "Transport",
    "tunnelSecurity": "Security",
    "deploy": "Deploy",
    "status": "Status",
    "selectPortal": "— Select Portal —",
    "selectBridge": "— Select Bridge —",
    "errorLoadingNodes": "Error loading nodes",
    "fillRequired": "Please fill in all required fields",
    "loadingTopology": "Loading topology...",
    "noNodesOrLinks": "No nodes or cascade links yet. Add nodes and create links.",
    "drawerStatus": "Status",
    "drawerIP": "IP Address",
    "drawerType": "Type",
    "drawerRole": "Role",
    "drawerOnline": "Online Users",
    "drawerPort": "Port",
    "openNode": "Open Node",
    "drawerTunnelPort": "Tunnel Port",
    "drawerProtocolTransport": "Protocol / Transport",
    "drawerLatency": "Latency",
    "confirmDeploy": "Deploy this cascade link?",
    "confirmDeleteLink": "Delete this cascade link? This will also undeploy it.",
    "deploying": "Deploying...",
    "deleting": "Deleting...",
    "reconnecting": "Reconnecting...",
    "deploySuccess": "Cascade link deployed",
    "deleteSuccess": "Cascade link deleted",
    "reconnectSuccess": "Link reconnected",
    "reconnectFailed": "Reconnect failed",
    "changeBridge": "Change Bridge",
    "changePortal": "Change Portal",
    "reconnectModal": "Reconnect Link",
    "newBridgeNode": "New Bridge Node",
    "newPortalNode": "New Portal Node",
    "dragToCreateHint": "Drag from any node to another to create a cascade link",
    "quickLinkTitle": "Create Cascade Link",
    "quickLinkPortal": "Portal",
    "quickLinkBridge": "Bridge",
    "swapNodes": "Swap",
    "deployFailed": "Deploy failed",
    "networkError": "Network error",
    "rolePortal": "PORTAL",
    "roleBridge": "BRIDGE",
    "roleRelay": "RELAY",
    "roleStandalone": "",
    "legendTitle": "Legend",
    "legendOnline": "Online",
    "legendOffline": "Offline",
    "legendDeployed": "Deployed",
    "legendPending": "Pending",
    "legendPortal": "Portal",
    "legendBridge": "Bridge",
    "legendRelay": "Relay",
    "legendForwardLine": "Solid line — Forward Chain",
    "legendReverseLine": "Dashed line — Reverse Proxy",
    "betaBadge": "BETA",
    "betaTitle": "Cascade links are in beta",
    "betaDescription": "Verify the resulting route, hop status, and exit IP after every deploy or sync.",
    "modeReverseFlow": "Traffic path: Client → Portal → Bridge → Internet. The tunnel is initiated by the Bridge.",
    "modeForwardFlow": "Traffic path: Client → Portal → (Relay →) Bridge → Internet. All nodes need a public IP.",
    "modeForwardWarning": "Forward Chain requires all hops to have a public IP. Verify the exit node after each sync.",
    "modeReverseWarning": "After deploy, confirm the tunnel is up and traffic exits from the expected Bridge node.",
    "tunnelPortReverseHint": "In Reverse mode this port is listened on the Portal node.",
    "tunnelPortForwardHint": "In Forward Chain this port is listened on the Bridge/Relay side of this hop.",
    "realityTunnelHint": "These REALITY settings apply only to the node-to-node tunnel, not to the client-facing inbound of the Portal node.",
    "portConflictClientHint": "This tunnel port is already used by another active link on the listening side.",
    "routeEntry": "Entry",
    "routeExit": "Exit",
    "routeEncryption": "Tunnel encryption",
    "routePath": "Traffic path",
    "undeployLink": "Undeploy",
    "linkMode": "Link Mode",
    "modeReverse": "Reverse Proxy",
    "modeForward": "Forward Chain",
    "modeReverseHint": "Bridge initiates tunnel to Portal. Bridge can be behind NAT.",
    "modeForwardHint": "Portal connects to Bridge directly. All nodes need public IP.",
    "muxEnabled": "Enable MUX",
    "muxConcurrency": "Concurrency",
    "geoRoutingEnabled": "Enable Geo Routing",
    "geoRoutingDomains": "Domains (geosite tags)",
    "geoRoutingGeoip": "GeoIP tags",
    "realityDest": "Destination",
    "realitySni": "Server Names",
    "realityPublicKey": "Public Key",
    "realityPrivateKey": "Private Key",
    "realityShortIds": "Short IDs",
    "realityFingerprint": "Fingerprint",
    "autoDeploy": "Auto Deploy",
    "advancedOptions": "Advanced Options",
    "priority": "Priority",
    "tunnelDomain": "Tunnel Domain",
    "confirmDeployChain": "Deploy entire chain? This will sync all connected nodes in the correct order.",
    "syncingChain": "Syncing chain...",
    "chainDeploySuccess": "Chain synced",
    "chainDeployFailed": "Chain sync failed",
    "syncChain": "Sync Chain",
    "confirmUndeploy": "Undeploy this cascade link?",
    "undeploying": "Undeploying...",
    "undeploySuccess": "Undeployed",
    "internetDesc": "Traffic exits to the Internet from connected nodes",
    "internetExitDesc": "Internet exit point",
    "internetExit": "Internet Exit"
  },
  "mcp": {
    "title": "MCP Integration",
    "subtitle": "Connect AI assistants to manage your panel",
    "motto": "Censor uses AI to block? Time to get your own.",
    "badge": "AI",
    "endpoint": "Endpoint",
    "copyEndpoint": "Copy Endpoint",
    "endpointCopied": "Endpoint copied",
    "setupGuide": "Setup Guide",
    "claudeDesktop": "Claude Desktop",
    "cursorIde": "Cursor IDE",
    "customClient": "Custom Client",
    "claudeConfigPath": "Add to your Claude Desktop config file:",
    "cursorConfigPath": "Add to .cursor/mcp.json in your project root:",
    "customConfigDesc": "Any HTTP client with SSE support:",
    "copyConfig": "Copy Config",
    "configCopied": "Copied",
    "availableTools": "Available Tools",
    "toolsCount": "tools",
    "createKey": "Create MCP API Key",
    "keyModalTitle": "Create MCP API Key",
    "keyModalDesc": "Creates a key with mcp:enabled + all read scopes.",
    "keyName": "Key Name",
    "keyNamePlaceholder": "e.g. Claude Assistant",
    "writeAccess": "Write Access",
    "writeAccessHint": "Select additional write permissions (read-only by default)",
    "createKeyBtn": "Create Key",
    "toolQuery": "Read data (users, nodes, groups, stats, logs)",
    "toolManageUser": "Manage users (create, update, delete, enable/disable)",
    "toolManageNode": "Manage nodes (create, update, delete, setup)",
    "toolManageGroup": "Manage server groups",
    "toolManageCascade": "Manage cascade links",
    "toolExecuteSsh": "Execute SSH command on a node",
    "toolSshSession": "Interactive SSH session",
    "toolSystemAction": "System operations (sync, cache, backup)",
    "toolGetTopology": "Network topology",
    "toolHealthCheck": "Panel health check",
    "scopeRequired": "Requires scope: mcp:enabled",
    "promptOverview": "Full panel overview: nodes, users, health",
    "promptAuditNodes": "Find and fix offline/broken nodes",
    "promptUserReport": "Detailed report for a specific user",
    "promptSetupNode": "Interactive guide to add a new node",
    "promptTroubleshoot": "Diagnose a node via SSH",
    "promptExpiredUsers": "Find and manage expired user accounts"
  },
  "wizard": {
    "title": "Setup Wizard",
    "subtitle": "Prepare the panel, the first nodes, and the initial access bundle in one guided flow.",
    "stepScenario": "Scenario",
    "stepNodes": "Infrastructure",
    "stepFinish": "Provisioning",
    "scenarioTitle": "Choose a starting point",
    "scenarioHint": "Select the deployment model that best matches your infrastructure. This only prepares the initial layout, and you can still add or change nodes later.",
    "selfHostTitle": "Deploy on this server",
    "selfHostDesc": "Install Hysteria 2 and / or Xray on the same server as the panel and prepare the starter access layout immediately.",
    "remoteTitle": "Manage remote nodes",
    "remoteDesc": "Use the panel as a control plane for proxy nodes running on separate VPS or dedicated servers.",
    "continue": "Continue",
    "skipPrompt": "Want to configure everything manually?",
    "skipLink": "Skip wizard",
    "protocols": "Protocols to install",
    "hysteriaSettings": "Hysteria 2 Settings",
    "xraySettings": "Xray Settings",
    "selfHostHint": "Choose the protocols to deploy, provide SSH access to the target server, and the wizard will prepare the starter group and first user automatically.",
    "starterBundleTitle": "Starter access bundle",
    "starterBundleDesc": "The wizard will create a starter server group, attach the new nodes to it, and prepare the first VPN user admin so the subscription layout is ready immediately after deployment.",
    "hysteriaChoiceDesc": "High-performance UDP transport with QUIC and port hopping support.",
    "xrayChoiceDesc": "TCP transport with REALITY camouflage and managed runtime updates through the built-in agent.",
    "hyDomainHint": "Uses the panel domain. Hysteria shares the panel TLS certificate.",
    "xrayPortHint": "Port 443/tcp is used by the panel (Caddy). Xray defaults to 8443.",
    "sshAccess": "SSH access to the target server",
    "sshAccessHint": "Provide an address the panel can reach over SSH. Root access is recommended for unattended installation.",
    "sshIp": "Target server address",
    "sshAuth": "Authentication",
    "sshPassword": "Password",
    "sshPrivateKey": "Private Key",
    "sshPasswordPlaceholder": "SSH password",
    "install": "Install & Continue",
    "installing": "Provisioning nodes, preparing starter access, and validating services. Please wait...",
    "installSuccess": "Installation complete!",
    "installPartial": "Provisioning finished with errors. Fix the issue and retry setup, or continue manually.",
    "streamError": "Connection lost. Refresh to check status.",
    "goToDashboard": "Go to Dashboard",
    "goToNodes": "View Nodes",
    "noProtocolSelected": "Please select at least one protocol.",
    "credentialsTitle": "Admin starter subscription",
    "credentialsDesc": "Use this subscription link for the automatically prepared admin starter access.",
    "credentialsUserLabel": "User ID",
    "credentialsPasswordLabel": "Subscription link",
    "copyCredentials": "Copy link",
    "retrySetup": "Retry setup",
    "continueManual": "Go to Panel"
  },
  "migration": {
    "armed": "Legacy compatibility is ARMED.",
    "armedDetail": "Path: {path} · finalized {date} · imported {imported}, skipped {skipped}, errors {errors}",
    "off": "Legacy compatibility is OFF. Complete the wizard below to import users and arm the compat route.",
    "disableBtn": "Disable compat",
    "disableConfirm": "Disable the Marzban compat route? Old links stop resolving until re-enabled.",
    "step1": "1. Connect",
    "step2": "2. Configure",
    "step3": "3. Import",
    "step4": "4. Finalize",
    "connectTitle": "Connect to the source Marzban panel",
    "connectDesc": "Provide the panel URL and the credentials of a sudo (or owning) admin. We never store these — they only live in this browser session until the import finishes.",
    "marzbanUrl": "Marzban URL",
    "marzbanUrlHint": "Include the protocol. Trailing slashes are stripped automatically.",
    "adminUsername": "Admin username",
    "adminPassword": "Admin password",
    "testBtn": "Test connection",
    "testing": "Testing…",
    "continueBtn": "Continue",
    "backBtn": "← Back",
    "marzbanUsers": "Marzban users",
    "admins": "Admins",
    "sudoAccess": "Sudo access",
    "status": "Status",
    "sudo": "sudo",
    "limited": "limited",
    "configureTitle": "Migration options",
    "configureDesc": "Choose which Celerity ServerGroup each Marzban admin's users land in, set the legacy subscription path, and paste the Marzban JWT secret so old links can be verified.",
    "pathLabel": "Subscription path (XRAY_SUBSCRIPTION_PATH)",
    "pathHint": "Must match the source panel's XRAY_SUBSCRIPTION_PATH. Default is sub. Reserved: api, panel, health, sse, docs, public, static.",
    "acceptSalt": "Accept random URL salt (only if Marzban used XRAY_SUBSCRIPTION_URL_PREFIX with a *).",
    "jwtSecret": "Marzban JWT secret",
    "jwtSecretPlaceholder": "64-char hex string from `SELECT secret_key FROM jwt;`",
    "jwtSecretHint": "The command below runs inside the Marzban container and reads the secret through Marzban's own Python/SQLAlchemy layer. That makes it work with SQLite, MySQL, or any other database configured in the panel. Celerity stores the secret AES-encrypted.",
    "jwtSecretCommandTitle": "Command to get the JWT secret",
    "jwtSecretCommandDesc": "Run it on the server where Marzban is running. The command automatically finds the Marzban container by image or name.",
    "copyCommand": "Copy command",
    "copied": "Copied",
    "mappingTitle": "Admin → ServerGroup mapping",
    "mappingDesc": "Each Marzban admin's users join the chosen Celerity ServerGroup. The dropdown lists active groups only.",
    "thAdmin": "Marzban admin",
    "thGroup": "Celerity ServerGroup",
    "skipUsers": "— skip users of this admin —",
    "fallbackGroup": "Fallback ServerGroup (for users whose admin is unmapped)",
    "fallbackNone": "— none —",
    "onlyActive": "Import only active / on_hold users (recommended).",
    "importVless": "Re-use Marzban VLESS UUIDs (keeps Xray identity stable for users who already had VLESS).",
    "startBtn": "Start import",
    "starting": "Starting…",
    "runTitle": "Import in progress",
    "runDesc": "Do not close this page until the import finishes — the task lives in panel memory and a restart will abort progress.",
    "processed": "processed",
    "total": "total",
    "imported": "imported",
    "skipped": "skipped",
    "errors": "errors",
    "conflicts": "conflicts",
    "finalizeTitle": "Activate legacy compatibility",
    "finalizeDesc": "Imported users are already in Celerity. The last step enables the /{path}/{token} route so old subscription links keep working.",
    "conflictsTitle": "Conflicts (manual review)",
    "thReason": "Reason",
    "activateBtn": "Activate compat route",
    "activating": "Activating…",
    "editOptions": "← Edit options",
    "startFailed": "Start failed: {error}",
    "activateFailed": "Activation failed: {error}",
    "activateSuccess": "Compat route armed. Old links should resolve now.",
    "disableFailed": "Failed: {error}"
  }
}
