精简版第四轮补裁(P4): 页面层摘除 + Xray更新端点下线 + 本机核心监管下线
CI / go-test (push) Canceled after 0s
CI / postgres-durable-first (push) Canceled after 0s
CI / codegen (push) Canceled after 0s
CI / govulncheck (push) Canceled after 0s
CI / race (push) Canceled after 0s
CI / fuzz-smoke (push) Canceled after 0s
CI / golangci (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CodeQL Advanced / Analyze (go) (push) Canceled after 0s
CodeQL Advanced / Analyze (actions) (push) Canceled after 0s
CodeQL Advanced / Analyze (javascript-typescript) (push) Canceled after 0s
Release 3X-UI / build (386) (push) Canceled after 0s
Release 3X-UI / build (amd64) (push) Canceled after 0s
Release 3X-UI / build (arm64) (push) Canceled after 0s
Release 3X-UI / build (armv5) (push) Canceled after 0s
Release 3X-UI / build (armv6) (push) Canceled after 0s
Release 3X-UI / build (armv7) (push) Canceled after 0s
Release 3X-UI / build (s390x) (push) Canceled after 0s
Release 3X-UI / Build for Windows (amd64) (push) Canceled after 0s
Release 3X-UI / Publish rolling dev release (push) Canceled after 0s

页面层(用户真机截图发现前两轮漏裁):
- 设置: 摘除 Telegram机器人/邮件菜单与页面, 及页内残留入口(通知页/外部流量/LDAP/2FA设置页)
- Xray配置: 摘除负载均衡/DNS/高级配置菜单与页面; 基础配置(出站+路由)完好
- 总览: 摘除 Xray更新弹窗(VersionModal+GeodataSection)全部入口, 版本号改为静态展示
- 13个locale同步摘除461个已删功能专属翻译键(逐键核查前后端引用为零; i18n-dead-keys测试全绿)

Xray更新后端(经调查确认仅服务本机bin/xray, 与agent下发/订阅无关):
- 删除 getXrayVersion/installXray/updateGeofile 路由与handler(访问返回404)
- 删除 ServerService 对应实现与校验和函数; 同步api-docs/monitor白名单/openapi

本机核心监管下线(设计: 主控永不运行本机xray, 入站全在agent):
- XrayService.RestartXray 降级为no-op(一次性Warning说明日志); StopXray无进程时幂等返回
- web.go 摘除启动拉起本机核心/CheckXrayRunning看门狗(1s)/ApplyPendingRestart cron(30s)/XrayTrafficJob/CheckClientIpJob 注册
- ApplyPendingRestart 降级为消费即清, 其测试更新为新语义
- XrayMetricsService.Sample 短路: 不再每2s探本机/debug/vars, 状态优雅置为不可用
- 配置生成(纯JSON)/agent链路/订阅/入站CRUD未动; 状态读数优雅归零(stop/Unknown)

注: TestGetXrayConfig_EnabledClientsStillEmitted 在基线945b3a5同样失败(既有问题, 非本轮引入)
This commit is contained in:
Muse
2026-10-20 23:39:38 +08:00
parent 945b3a56a2
commit a654a96c38
56 changed files with 149 additions and 11458 deletions
+7 -481
View File
@@ -67,16 +67,12 @@
"success": "Success",
"lastOnline": "Last Online",
"lastSubFetch": "Last Subscription Fetch",
"getVersion": "Get Version",
"install": "Install",
"clients": "Clients",
"usage": "Usage",
"twoFactorCode": "Code",
"remained": "Remaining",
"security": "Security",
"emptyDnsDesc": "No added DNS servers.",
"emptyFakeDnsDesc": "No added Fake DNS servers.",
"emptyBalancersDesc": "No added balancers.",
"somethingWentWrong": "Something went wrong",
"subscription": {
"title": "Subscription info",
@@ -87,7 +83,6 @@
"uploaded": "Uploaded",
"expiry": "Expiry",
"totalQuota": "Total quota",
"individualLinks": "Individual links",
"active": "Active",
"inactive": "Inactive",
"unlimited": "Unlimited",
@@ -136,9 +131,6 @@
"xrayStatus": "Xray",
"stopXray": "Stop",
"restartXray": "Restart",
"xraySwitch": "Version",
"xrayUpdates": "Xray Updates",
"xraySwitchClickDesk": "Choose carefully, as older versions may not be compatible with current configurations.",
"updatePanel": "Update Panel",
"panelUpdateDesc": "This will update 3X-UI itself to the latest release and restart the panel service.",
"currentPanelVersion": "Current panel version",
@@ -200,9 +192,6 @@
"download": "Download",
"sent": "Sent",
"received": "Received",
"xraySwitchVersionDialog": "Do you really want to change the Xray version?",
"xraySwitchVersionDialogDesc": "This will change the Xray version to #version#.",
"xraySwitchVersionPopover": "Xray updated successfully",
"panelUpdateDialog": "Do you really want to update the panel?",
"panelUpdateDialogDesc": "This will update 3X-UI to #version# and restart the panel service.",
"panelUpdateStartedPopover": "Panel update started",
@@ -210,24 +199,6 @@
"panelUpdateFailedDesc": "The update did not finish successfully. Check the server logs, or run 'x-ui update' from the command line.",
"panelUpdateUnknownTitle": "Couldn't confirm the update finished",
"panelUpdateUnknownDesc": "The panel didn't report a result in time. Reload to check the current version, or check the server logs.",
"geofileUpdateDialog": "Do you really want to update the geofile?",
"geofileUpdateDialogDesc": "This will update the #filename# file.",
"geofilesUpdateDialogDesc": "This will update all geofiles.",
"geofilesUpdateAll": "Update all",
"geofileUpdatePopover": "Geofile updated successfully",
"geodataTitle": "Geodata Auto-Update",
"geodataHint": "Xray downloads these files on schedule and hot-reloads them without a restart. URLs must be HTTPS. Each file must already exist in the bin folder once before Xray can update it.",
"geodataCron": "Schedule (cron)",
"geodataOutbound": "Download through outbound (optional)",
"geodataFile": "File name",
"geodataAddFile": "Add file",
"geodataSaveRestart": "Save & Restart Xray",
"geodataConfirmTitle": "Save geodata settings?",
"geodataConfirmContent": "This updates the Xray config template and restarts Xray.",
"geodataInvalidUrl": "Each file needs an HTTPS URL.",
"geodataInvalidFile": "File names must be plain names like geosite_custom.dat (no paths).",
"geodataInvalidCron": "Cron must have 5 fields, e.g. 0 4 * * *",
"geodataEmpty": "No files configured. Reference files in routing rules as ext:geosite_custom.dat:category.",
"dontRefresh": "Installation is in progress, please do not refresh this page",
"logs": "Logs",
"accessLogs": "Access Logs",
@@ -1179,19 +1150,7 @@
"pinnedCertPlaceholder": "base64 or hex SHA-256",
"fetchPin": "Fetch",
"pinFetched": "Fetched the node's current certificate",
"pinFetchFailed": "Could not fetch the certificate",
"nodeType": "Node Type",
"nodeTypeTraditional": "Traditional Panel Node",
"nodeTypeAgent": "Agent Lightweight Node",
"agentHint": "Agent nodes connect out to the master; no address, port or API token needed. An install command is generated on creation.",
"agentTokenTitle": "Agent Node Setup",
"agentTokenCreated": "Node {{name}} created successfully",
"agentTokenHint": "Copy the command below and run it on the node machine. This token is shown only once!",
"agentTokenInstructions": "The command downloads the installer, configures the master URL and token. The node comes online in ~30s.",
"agentTokenCopied": "Install command copied",
"agentTokenCopyFailed": "Copy failed, please copy manually",
"copyToken": "Copy Install Command",
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
"pinFetchFailed": "Could not fetch the certificate"
},
"settings": {
"defaultTag": "Default",
@@ -1212,7 +1171,6 @@
"warnDefaultBasePath": "Default base path \"/\" is well-known — change it to a random path.",
"warnDefaultSubPath": "Default subscription path \"/sub/\" is well-known — change it.",
"warnDefaultJsonPath": "Default JSON subscription path \"/json/\" is well-known — change it.",
"TGBotSettings": "Telegram Bot",
"panelListeningIP": "Listen IP",
"panelListeningIPDesc": "The IP address for the web panel. (leave blank to listen on all IPs)",
"panelListeningDomain": "Listen Domain",
@@ -1241,43 +1199,12 @@
"currentPassword": "Current Password",
"newUsername": "New Username",
"newPassword": "New Password",
"telegramBotEnable": "Enable Telegram Bot",
"telegramBotEnableDesc": "Enables the Telegram bot.",
"telegramToken": "Telegram Token",
"telegramTokenDesc": "The Telegram bot token obtained from '{'@'}BotFather'.",
"telegramProxy": "SOCKS Proxy",
"telegramProxyDesc": "Enables SOCKS5 proxy for connecting to Telegram. (adjust settings as per guide)",
"telegramAPIServer": "Telegram API Server",
"telegramAPIServerDesc": "The Telegram API server to use. Leave blank to use the default server.",
"telegramChatId": "Admin Chat ID",
"telegramChatIdDesc": "The Telegram Admin Chat ID(s). (comma-separated)(get it here {'@'}userinfobot) or (use '/id' command in the bot)",
"telegramNotifyTime": "Notification Time",
"telegramNotifyTimeDesc": "How often the Telegram bot sends periodic reports. Pick a preset interval, or choose Custom to enter a raw crontab expression.",
"notifyTime": {
"every": "@every — repeat at an interval",
"hourly": "@hourly — every hour",
"daily": "@daily — every day at 00:00",
"weekly": "@weekly — every week",
"monthly": "@monthly — every month",
"custom": "Custom (crontab)",
"seconds": "Seconds",
"minutes": "Minutes",
"hours": "Hours",
"interval": "Interval",
"unit": "Unit"
},
"tgNotifyBackup": "Database Backup",
"tgNotifyBackupDesc": "Send a database backup file with a report.",
"tgNotifyLogin": "Login Notification",
"tgNotifyLoginDesc": "Get notified about the username, IP address, and time whenever someone attempts to log into your web panel.",
"sessionMaxAge": "Session Duration",
"sessionMaxAgeDesc": "The duration for which you can stay logged in. (unit: minute)",
"expireTimeDiff": "Expiration Date Notification",
"expireTimeDiffDesc": "Get notified about expiration date when reaching this threshold. (unit: day)",
"trafficDiff": "Traffic Cap Notification",
"trafficDiffDesc": "Get notified about traffic cap when reaching this threshold. (unit: GB)",
"tgNotifyCpu": "CPU Load Notification",
"tgNotifyCpuDesc": "Get notified if CPU load exceeds this threshold. (unit: %)",
"timeZone": "Time Zone",
"timeZoneDesc": "Scheduled tasks will run based on this time zone.",
"subSettings": "Subscription",
@@ -1342,10 +1269,6 @@
"subEncryptDesc": "The returned content of subscription service will be Base64 encoded.",
"subURI": "Reverse Proxy URI",
"subURIDesc": "The full base URL (scheme://domain[:port]/path/) for the subscription link and QR code, used instead of Listen Domain/Listen Port. Set this whenever the subscription is reached through a reverse proxy or a domain/port different from the ones above.",
"externalTrafficInformEnable": "External Traffic Inform",
"externalTrafficInformEnableDesc": "Inform external API on every traffic update.",
"externalTrafficInformURI": "External Traffic Inform URI",
"externalTrafficInformURIDesc": "Traffic updates are sent to this URI.",
"restartXrayOnClientDisable": "Restart Xray After Auto Disable",
"restartXrayOnClientDisableDesc": "When a client is automatically disabled due to expiration or traffic limit, restart Xray.",
"fragment": "Fragmentation",
@@ -1355,38 +1278,6 @@
"noisesSett": "Noises Settings",
"trustedProxyCidrs": "Trusted proxy CIDRs",
"trustedProxyCidrsDesc": "Comma-separated IPs/CIDRs allowed to set forwarded host, proto, and client IP headers.",
"ldap": {
"enable": "Enable LDAP sync",
"host": "LDAP host",
"port": "LDAP port",
"useTls": "Use TLS (LDAPS)",
"skipTlsVerify": "Skip TLS certificate verification",
"skipTlsVerifyDesc": "Insecure — disables server certificate validation. Use only with internal/untrusted CAs.",
"bindDn": "Bind DN",
"passwordConfigured": "Configured; leave blank to keep current password.",
"passwordUnconfigured": "Not configured.",
"passwordPlaceholder": "Configured - enter a new value to replace",
"baseDn": "Base DN",
"userFilter": "User filter",
"userAttr": "User attribute (username/email)",
"vlessField": "VLESS flag attribute",
"flagField": "Generic flag attribute (optional)",
"flagFieldDesc": "If set, overrides VLESS flag — e.g. shadowInactive.",
"truthyValues": "Truthy values",
"truthyValuesDesc": "Comma-separated; default: true,1,yes,on",
"invertFlag": "Invert flag",
"invertFlagDesc": "Enable when the attribute means disabled (e.g. shadowInactive).",
"syncSchedule": "Sync schedule",
"syncScheduleDesc": "Cron-like string, e.g. @every 1m",
"inboundTags": "Inbound tags",
"inboundTagsDesc": "Inbounds that LDAP sync may auto-create or auto-delete clients on.",
"noInbounds": "No inbounds found. Create one in Inbounds first.",
"autoCreate": "Auto create clients",
"autoDelete": "Auto delete clients",
"defaultTotalGb": "Default total (GB)",
"defaultExpiryDays": "Default expiry (days)",
"defaultIpLimit": "Default IP limit"
},
"subFormats": {
"finalMask": "Final Mask",
"finalMaskDesc": "Inject Xray finalmask TCP/UDP masks and QUIC parameters into every generated Xray JSON profile. Requires a client app that supports Xray JSON subscriptions and a recent Xray core.",
@@ -1410,31 +1301,15 @@
"muxSett": "Mux Settings",
"direct": "Direct Connection",
"directDesc": "Directly establishes connections with domains or IP ranges of a specific country.",
"notifications": "Notifications",
"certs": "Certificates",
"externalTraffic": "External Traffic",
"dateAndTime": "Date and Time",
"proxyAndServer": "Proxy and Server",
"intervals": "Intervals",
"information": "Information",
"profile": "Profile",
"language": "Language",
"telegramBotLanguage": "Telegram Bot Language",
"security": {
"admin": "Admin credentials",
"twoFactor": "Two-factor authentication",
"twoFactorEnable": "Enable 2FA",
"twoFactorEnableDesc": "Adds an additional layer of authentication to provide more security.",
"twoFactorModalSetTitle": "Enable two-factor authentication",
"twoFactorModalDeleteTitle": "Disable two-factor authentication",
"twoFactorModalSteps": "To set up two-factor authentication, perform a few steps:",
"twoFactorModalFirstStep": "1. Scan this QR code in the app for authentication or copy the token near the QR code and paste it into the app",
"twoFactorModalSecondStep": "2. Enter the code from the app",
"twoFactorModalRemoveStep": "Enter the code from the application to remove two-factor authentication.",
"twoFactorModalChangeCredentialsTitle": "Change credentials",
"twoFactorModalChangeCredentialsStep": "Enter the code from the application to change administrator credentials.",
"twoFactorModalSetSuccess": "Two-factor authentication has been successfully established",
"twoFactorModalDeleteSuccess": "Two-factor authentication has been successfully deleted",
"twoFactorModalError": "Wrong code",
"show": "Show",
"hide": "Hide",
@@ -1457,36 +1332,6 @@
"getOutboundTrafficError": "Error getting traffic",
"resetOutboundTrafficError": "Error resetting outbound traffic"
},
"smtpSettings": "SMTP Settings",
"smtpEnable": "Enable Email Notifications",
"smtpEnableDesc": "Enable email notifications via SMTP",
"smtpHost": "SMTP Host",
"smtpHostDesc": "SMTP server hostname (e.g. smtp.gmail.com)",
"smtpPort": "SMTP Port",
"smtpPortDesc": "SMTP server port (default: 587)",
"smtpUsername": "SMTP Username",
"smtpUsernameDesc": "SMTP authentication username",
"smtpFrom": "SMTP From Address",
"smtpFromDesc": "Sender address used in the email From header. Leave empty to use the username.",
"smtpFromName": "SMTP Sender Name",
"smtpFromNameDesc": "Optional display name shown before the sender address in the From header.",
"smtpPassword": "SMTP Password",
"smtpPasswordDesc": "SMTP authentication password",
"smtpTo": "Recipients",
"smtpToDesc": "Comma-separated recipient email addresses",
"emailSettings": "Email",
"emailNotifications": "Notifications",
"smtpEventBusNotify": "Email Event Notifications",
"smtpEventBusNotifyDesc": "Select which events trigger email notifications",
"tgEventBusNotify": "Telegram Event Notifications",
"tgEventBusNotifyDesc": "Select which events trigger Telegram notifications",
"testSmtp": "Send Test Email",
"testTgBot": "Send Test Message",
"eventGroupOutbound": "Outbound",
"eventGroupXray": "Xray Core",
"eventGroupSystem": "System",
"eventGroupSecurity": "Security",
"eventGroupNode": "Nodes",
"eventOutboundDown": "Down",
"eventOutboundUp": "Up",
"eventXrayCrash": "Crash",
@@ -1494,36 +1339,7 @@
"eventNodeUp": "Up",
"eventCPUHigh": "CPU high (%)",
"requestFailed": "Request failed",
"smtpEncryption": "Encryption",
"smtpEncryptionDesc": "SMTP connection encryption method",
"smtpEncryptionNone": "None (plain text)",
"smtpEncryptionStartTLS": "STARTTLS",
"smtpEncryptionTLS": "TLS (implicit)",
"smtpStageConnect": "Connection",
"smtpStageAuth": "Authentication",
"smtpStageSend": "Send",
"smtpTestSuccess": "Test email sent successfully",
"smtpHostNotConfigured": "SMTP host not configured",
"smtpNoRecipients": "No recipients configured",
"smtpFromNotConfigured": "SMTP sender address not configured",
"eventLoginAttempt": "Login attempt",
"telegramTokenConfigured": "Configured; leave blank to keep current token.",
"telegramTokenPlaceholder": "Configured - enter a new token to replace",
"smtpPasswordConfigured": "Configured; leave blank to keep current password.",
"smtpPasswordPlaceholder": "Configured - enter a new password to replace",
"smtpNotInitialized": "SMTP not initialized",
"tgBotNotEnabled": "Telegram bot is not enabled",
"tgTestFailed": "Telegram test failed",
"tgTestSuccess": "Test message sent to Telegram",
"tgBotNotRunning": "Telegram bot not running",
"smtpErrorAuth": "Authentication failed — check username and password",
"smtpErrorStarttls": "Server requires STARTTLS — change encryption type",
"smtpErrorTls": "Server requires TLS — change encryption type",
"smtpErrorRefused": "Connection refused — check host and port",
"smtpErrorTimeout": "Connection timeout — host unreachable",
"smtpErrorRelay": "Server rejects sending from this address",
"smtpErrorEof": "Connection closed by server",
"smtpErrorUnknown": "SMTP error: {{ .Error }}",
"eventMemoryHigh": "Memory high (%)",
"validation": {
"pathLeadingSlash": "Path must start with /"
@@ -1605,8 +1421,6 @@
"directdomains": "Direct Domains",
"ipv4Routing": "IPv4 Routing",
"ipv4RoutingDesc": "These options will route traffic based on a specific destination via IPv4.",
"Template": "Advanced Xray Configuration Template",
"TemplateDesc": "The final Xray config file will be generated based on this template.",
"FreedomStrategy": "Freedom Protocol Strategy",
"FreedomStrategyDesc": "Set the output strategy for the network in the Freedom Protocol.",
"FreedomHappyEyeballs": "Freedom Happy Eyeballs (IPv4/IPv6)",
@@ -1622,11 +1436,6 @@
"Balancers": "Balancers",
"balancerTagRequired": "Tag is required",
"balancerSelectorRequired": "Pick at least one outbound",
"balancerLive": "Live Target",
"balancerOverride": "Override",
"balancerOverridePh": "Auto (strategy)",
"balancerLiveRefresh": "Refresh live balancer state",
"balancerNotRunning": "This balancer is not active in the running Xray — save your changes or start Xray first",
"routeTester": "Route Tester",
"routeTesterDesc": "Ask the running Xray which outbound would handle a connection. No traffic is sent — the decision comes straight from the live routing engine.",
"routeTesterDest": "Domain or IP",
@@ -1643,7 +1452,6 @@
"importOutbounds": "Import Outbounds",
"exportOutbounds": "Export Outbounds",
"importInvalidJson": "Invalid JSON — expected an array or an object with a matching key.",
"completeTemplate": "All",
"logLevel": "Log Level",
"logLevelDesc": "The log level for error logs, indicating the information that needs to be recorded.",
"accessLog": "Access Log",
@@ -1674,7 +1482,6 @@
"source": "Source",
"dest": "Destination",
"inbound": "Inbound",
"balancer": "Balancer",
"useComma": "Comma-separated list"
},
"routing": {
@@ -1855,32 +1662,7 @@
"alreadyAdded": "This server is already in the outbound list. Use {reset} to renew its key.",
"provisionFailed": "Could not build the PIA outbound. Try again."
},
"tabBalancerSettings": "Balancer Settings",
"tabObservatory": "Observatory",
"observatory": {
"autoManaged": "Observers are managed automatically from your balancers. Tune how they probe below — the watched outbounds follow your balancer selectors.",
"emptyHint": "No connection observer is active. One is added automatically when you create a Least Ping or Least Load balancer — or a Random / Round-robin balancer with a fallback — so observer-backed balancers can check outbound health before choosing a target.",
"mixedLegacy": "This config contains both Observatory and Burst Observatory. Xray uses one global observer, so this mixed legacy state is not supported; saving balancers will normalize it to one observer.",
"subjectSelector": "Watched Outbounds",
"subjectSelectorDesc": "Outbound tags this observer probes. Managed automatically from your balancers.",
"probeURL": "Probe URL",
"probeURLDesc": "URL fetched to measure each outbound. Should return HTTP 204.",
"probeInterval": "Probe Interval",
"probeIntervalDesc": "How often to probe each outbound, e.g. 30s, 1m, 2h45m.",
"enableConcurrency": "Concurrent Probing",
"enableConcurrencyDesc": "Probe all watched outbounds at once instead of one-by-one. Faster, but more visible on the network.",
"destination": "Probe Destination",
"destinationDesc": "URL fetched to measure each outbound. Should return HTTP 204.",
"connectivity": "Connectivity Check",
"connectivityDesc": "Optional local-network check URL, tried only after the destination fails. Leave empty to skip.",
"interval": "Probe Interval",
"intervalDesc": "Average time between probes per outbound, e.g. 1m. Minimum 10s.",
"timeout": "Probe Timeout",
"timeoutDesc": "How long to wait for a probe before it counts as failed, e.g. 5s.",
"sampling": "Sampling Count",
"samplingDesc": "Number of recent probe results kept to score each outbound.",
"httpMethod": "HTTP Method",
"httpMethodDesc": "HTTP method used for probes.",
"deleteAlsoObservatory": "This is the last balancer using the Observatory, so it will be removed too.",
"deleteAlsoBurst": "This is the last balancer using the Burst Observatory, so it will be removed too."
},
@@ -1892,26 +1674,8 @@
},
"balancer": {
"balancerStrategy": "Strategy",
"tag": "Tag",
"tagDuplicate": "Tag already used by another balancer",
"tagPlaceholder": "unique balancer tag",
"selector": "Selector",
"fallback": "Fallback",
"fallbackBalancerHint": "Select another balancer as fallback",
"balancerFallbackInfo": "Traffic will be routed through: Balancer → Loopback → Server → Target Balancer → Outbound. This adds an extra hop through the server, which may introduce slight delays.",
"balancerFallbackCycle": "Cannot set this balancer as fallback — it would create a circular dependency.",
"balancerDeleteInUse": "Cannot delete this balancer — it is used as fallback by: {names}",
"reservedPrefix": "_bl_ prefix is reserved for internal balancer loopback objects",
"cycleTooltip": "Cycle: {path} → (back to {start})",
"expected": "Expected",
"expectedPlaceholder": "optimal node count",
"maxRtt": "Max RTT",
"tolerance": "Tolerance",
"baselines": "Baselines",
"costs": "Costs",
"costMatch": "Tag pattern",
"costValue": "Weight",
"costRegexp": "Regular expression match"
"reservedPrefix": "_bl_ prefix is reserved for internal balancer loopback objects"
},
"wireguard": {
"secretKey": "Secret Key",
@@ -2013,252 +1777,14 @@
"usage": "Usage",
"addOutbound": "Add outbound"
},
"dns": {
"enable": "Enable DNS",
"enableDesc": "Enable built-in DNS server",
"tag": "DNS Inbound Tag",
"tagDesc": "This tag will be available as an Inbound tag in routing rules.",
"clientIp": "Client IP",
"clientIpDesc": "Used to notify the server of the specified IP location during DNS queries",
"disableCache": "Disable cache",
"disableCacheDesc": "Disables DNS caching",
"disableFallback": "Disable Fallback",
"disableFallbackDesc": "Disables fallback DNS queries",
"disableFallbackIfMatch": "Disable Fallback If Match",
"disableFallbackIfMatchDesc": "Disables fallback DNS queries when the matching domain list of the DNS server is hit",
"enableParallelQuery": "Enable Parallel Query",
"enableParallelQueryDesc": "Enable parallel DNS queries to multiple servers for faster resolution",
"strategy": "Query Strategy",
"strategyDesc": "Overall strategy to resolve domain names",
"add": "Add Server",
"edit": "Edit Server",
"domains": "Domains",
"expectIPs": "Expect IPs",
"unexpectIPs": "Unexpected IPs",
"useSystemHosts": "Use System Hosts",
"useSystemHostsDesc": "Use the operating system's hosts file",
"serveStale": "Serve Stale",
"serveStaleDesc": "Return expired cached results while refreshing in the background",
"serveExpiredTTL": "Serve Expired TTL",
"serveExpiredTTLDesc": "Validity (seconds) of stale cache entries; 0 = never expire",
"timeoutMs": "Timeout (ms)",
"skipFallback": "Skip Fallback",
"finalQuery": "Final Query",
"hosts": "Hosts",
"hostsAdd": "Add Host",
"hostsEmpty": "No host overrides defined",
"hostsDomain": "Domain (e.g. domain:example.com)",
"hostsValues": "IP or domain — type and press Enter",
"usePreset": "Use Preset",
"dnsPresetTitle": "DNS Presets",
"dnsPresetFamily": "Family",
"clearAll": "Delete All",
"clearAllTitle": "Delete all DNS servers?",
"clearAllConfirm": "This removes every DNS server from the list. This cannot be undone.",
"dnsLeakWarning": "DNS can leak through localhost, plain UDP/TCP, local-mode DoH/DoQ, fallback queries, or EDNS client IP. Use routed DoH, hosts pins, and disable fallback when privacy matters."
},
"fakedns": {
"add": "Add Fake DNS",
"ipPool": "IP Pool Subnet",
"poolSize": "Pool Size"
},
"dns": {},
"fakedns": {},
"defaultOutbound": "Default Outbound",
"defaultOutboundDesc": "Traffic that does not match any routing rule uses this outbound (Xray uses the first outbound in the list)."
}
},
"tgbot": {
"keyboardClosed": "❌ Custom keyboard closed!",
"noResult": "❗ No result!",
"noQuery": "❌ Query not found! Please use the command again!",
"wentWrong": "❌ Something went wrong!",
"noIpRecord": "❗ No IP Record!",
"noInbounds": "❗ No inbound found!",
"unlimited": "♾ Unlimited(Reset)",
"add": "Add",
"month": "Month",
"months": "Months",
"days": "Days",
"hours": "Hours",
"minutes": "Minutes",
"unknown": "Unknown",
"inbounds": "Inbounds",
"clients": "Clients",
"offline": "🔴 Offline",
"online": "🟢 Online",
"commands": {
"unknown": "❗ Unknown command.",
"pleaseChoose": "👇 Please choose:\r\n",
"help": "🤖 Welcome to this bot! It's designed to offer specific data from the web panel and allows you to make modifications as needed.\r\n\r\n",
"start": "👋 Hello <i>{{ .Firstname }}</i>.\r\n",
"welcome": "🤖 Welcome to <b>{{ .Hostname }}</b> management bot.\r\n",
"status": "✅ Bot is OK!",
"usage": "❗ Please provide a text to search!",
"getID": "🆔 Your ID: <code>{{ .ID }}</code>",
"helpAdminCommands": "To restart Xray Core:\r\n<code>/restart</code>\r\n\r\nTo search for a client email:\r\n<code>/usage [Email]</code>\r\n\r\nTo search for inbounds (with client stats):\r\n<code>/inbound [Remark]</code>\r\n\r\nTelegram Chat ID:\r\n<code>/id</code>",
"helpClientCommands": "To search for statistics, use the following command:\r\n\r\n<code>/usage [Email]</code>\r\n\r\nTelegram Chat ID:\r\n<code>/id</code>",
"restartUsage": "\r\n\r\n<code>/restart</code>",
"restartSuccess": "✅ Operation successful!",
"restartFailed": "❗ Error in operation.\r\n\r\n<code>Error: {{ .Error }}</code>.",
"xrayNotRunning": "❗ Xray Core is not running.",
"startDesc": "Show the main menu",
"helpDesc": "Bot help",
"statusDesc": "Check bot status",
"idDesc": "Show your Telegram ID",
"usageDesc": "Show client usage: /usage email",
"inboundDesc": "Search inbounds: /inbound remark (admin)",
"restartDesc": "Restart Xray core (admin)",
"clearallDesc": "Reset all clients' traffic (admin)"
},
"messages": {
"cpuThreshold": "CPU Load {{ .Percent }}% exceeds the threshold of {{ .Threshold }}%",
"selectUserFailed": "❌ Error in user selection!",
"userSaved": "✅ Telegram User saved.",
"loginSuccess": "✅ Logged in to the panel successfully.\r\n",
"loginFailed": "❗️Login attempt to the panel failed.\r\n",
"report": "🕰 Scheduled Reports: {{ .RunTime }}\r\n",
"datetime": "⏰ Date&Time: {{ .DateTime }}\r\n",
"hostname": "💻 Host: {{ .Hostname }}\r\n",
"version": "🚀 3X-UI Version: {{ .Version }}\r\n",
"xrayVersion": "📡 Xray Version: {{ .XrayVersion }}\r\n",
"ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
"ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
"ip": "🌐 IP: {{ .IP }}\r\n",
"ips": "🔢 IPs:\r\n{{ .IPs }}\r\n",
"serverUpTime": "⏳ Uptime: {{ .UpTime }} {{ .Unit }}\r\n",
"serverLoad": "📈 System Load: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
"serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
"tcpCount": "🔹 TCP: {{ .Count }}\r\n",
"udpCount": "🔸 UDP: {{ .Count }}\r\n",
"traffic": "🚦 Traffic: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
"xrayStatus": "ℹ️ Status: {{ .State }}\r\n",
"username": "👤 Username: {{ .Username }}\r\n",
"reason": "❗️ Reason: {{ .Reason }}\r\n",
"time": "⏰ Time: {{ .Time }}\r\n",
"inbound": "📍 Inbound: {{ .Remark }}\r\n",
"port": "🔌 Port: {{ .Port }}\r\n",
"expire": "📅 Expire Date: {{ .Time }}\r\n",
"expireIn": "📅 Expire In: {{ .Time }}\r\n",
"active": "💡 Active: {{ .Enable }}\r\n",
"enabled": "🚨 Enabled: {{ .Enable }}\r\n",
"online": "🌐 Connection status: {{ .Status }}\r\n",
"lastOnline": "🔙 Last online: {{ .Time }}\r\n",
"email": "📧 Email: {{ .Email }}\r\n",
"upload": "🔼 Upload: ↑{{ .Upload }}\r\n",
"download": "🔽 Download: ↓{{ .Download }}\r\n",
"total": "📊 Total: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
"TGUser": "👤 Telegram User: {{ .TelegramID }}\r\n",
"exhaustedCount": "🚨 Exhausted {{ .Type }} count:\r\n",
"onlinesCount": "🌐 Online Clients: {{ .Count }}\r\n",
"disabled": "🛑 Disabled: {{ .Disabled }}\r\n",
"depleteSoon": "🔜 Deplete Soon: {{ .Deplete }}\r\n\r\n",
"backupTime": "🗄 Backup Time: {{ .Time }}\r\n",
"refreshedOn": "\r\n📋🔄 Refreshed On: {{ .Time }}\r\n\r\n",
"yes": "✅ Yes",
"no": "❌ No",
"received_email": "📧📥 Email updated.",
"received_comment": "💬📥 Comment updated.",
"email_prompt": "📧 Default Email: {{ .ClientEmail }}\n\nEnter your email.",
"comment_prompt": "💬 Default Comment: {{ .ClientComment }}\n\nEnter your comment.",
"cancel": "❌ Process Canceled! \n\nYou can /start again anytime. 🔄",
"error_add_client": "⚠️ Error:\n\n {{ .error }}",
"using_default_value": "Okay, I'll stick with the default value. 😊",
"incorrect_input": "Your input is not valid.\nThe phrases should be continuous without spaces.\nCorrect example: aaaaaa\nIncorrect example: aaa aaa 🚫",
"AreYouSure": "Are you sure? 🤔",
"SuccessResetTraffic": "📧 Email: {{ .ClientEmail }}\n🏁 Result: ✅ Success",
"FailedResetTraffic": "📧 Email: {{ .ClientEmail }}\n🏁 Result: ❌ Failed \n\n🛠️ Error: [ {{ .ErrorMessage }} ]",
"FinishProcess": "🔚 Traffic reset process finished for all clients.",
"eventOutboundDown": "Outbound {{ .Tag }} is DOWN",
"eventOutboundUp": "Outbound {{ .Tag }} is UP",
"eventErrorDetail": "Error: {{ .Error }}",
"eventDelayDetail": "Delay: {{ .Delay }}ms",
"eventXrayCrash": "Xray CRASHED",
"eventXrayCrashError": "Error: {{ .Error }}",
"eventNodeDown": "Node {{ .Name }} is DOWN",
"eventNodeUp": "Node {{ .Name }} is UP",
"eventLoginFallback": "Login failed from {{ .Source }}",
"memoryThreshold": "Memory Load {{ .Percent }}% exceeds the threshold of {{ .Threshold }}%"
},
"buttons": {
"closeKeyboard": "❌ Close Keyboard",
"cancel": "❌ Cancel",
"cancelReset": "❌ Cancel Reset",
"cancelIpLimit": "❌ Cancel IP Limit",
"confirmResetTraffic": "✅ Confirm Reset Traffic?",
"confirmClearIps": "✅ Confirm Clear IPs?",
"confirmRemoveTGUser": "✅ Confirm Remove Telegram User?",
"confirmToggle": "✅ Confirm Enable/Disable User?",
"dbBackup": "Get DB Backup",
"serverUsage": "Server Usage",
"getInbounds": "Get Inbounds",
"depleteSoon": "Deplete Soon",
"clientUsage": "Get Usage",
"onlines": "Online Clients",
"commands": "Commands",
"refresh": "🔄 Refresh",
"clearIPs": "❌ Clear IPs",
"removeTGUser": "❌ Remove Telegram User",
"selectTGUser": "👤 Select Telegram User",
"selectOneTGUser": "👤 Select a Telegram User:",
"resetTraffic": "📈 Reset Traffic",
"resetExpire": "📅 Change Expiry Date",
"ipLog": "🔢 IP Log",
"ipLimit": "🔢 IP Limit",
"setTGUser": "👤 Set Telegram User",
"toggle": "🔘 Enable / Disable",
"custom": "🔢 Custom",
"confirmNumber": "✅ Confirm: {{ .Num }}",
"confirmNumberAdd": "✅ Confirm adding: {{ .Num }}",
"limitTraffic": "🚧 Traffic Limit",
"getBanLogs": "Get Ban Logs",
"allClients": "All Clients",
"addClient": "Add Client",
"submitDisable": "Submit As Disable ☑️",
"submitEnable": "Submit As Enable ✅",
"use_default": "🏷️ Use default",
"change_email": "⚙️📧 Email",
"change_comment": "⚙️💬 Comment",
"ResetAllTraffics": "Reset All Traffic",
"SortedTrafficUsageReport": "Sorted Traffic Usage Report"
},
"answers": {
"successfulOperation": "✅ Operation successful!",
"errorOperation": "❗ Error in operation.",
"getInboundsFailed": "❌ Failed to get inbounds.",
"getClientsFailed": "❌ Failed to get clients.",
"canceled": "❌ {{ .Email }}: Operation canceled.",
"clientRefreshSuccess": "✅ {{ .Email }}: Client refreshed successfully.",
"IpRefreshSuccess": "✅ {{ .Email }}: IPs refreshed successfully.",
"TGIdRefreshSuccess": "✅ {{ .Email }}: Client's Telegram User refreshed successfully.",
"resetTrafficSuccess": "✅ {{ .Email }}: Traffic reset successfully.",
"setTrafficLimitSuccess": "✅ {{ .Email }}: Traffic limit saved successfully.",
"expireResetSuccess": "✅ {{ .Email }}: Expire days reset successfully.",
"resetIpSuccess": "✅ {{ .Email }}: IP limit {{ .Count }} saved successfully.",
"clearIpSuccess": "✅ {{ .Email }}: IPs cleared successfully.",
"getIpLog": "✅ {{ .Email }}: Get IP Log.",
"getUserInfo": "✅ {{ .Email }}: Get Telegram User Info.",
"removedTGUserSuccess": "✅ {{ .Email }}: Telegram User removed successfully.",
"enableSuccess": "✅ {{ .Email }}: Enabled successfully.",
"disableSuccess": "✅ {{ .Email }}: Disabled successfully.",
"askToAddUserId": "Your configuration is not found!\r\nPlease ask your admin to use your Telegram ChatID in your configuration(s).\r\n\r\nYour ChatID: <code>{{ .TgUserID }}</code>",
"chooseClient": "Choose a Client for Inbound {{ .Inbound }}",
"chooseInbound": "Choose an Inbound"
}
"noIpRecord": "❗ No IP Record!"
},
"email": {
"labelStatus": "Status",
"labelOutbound": "Outbound",
"labelNode": "Node",
"labelError": "Error",
"labelDelay": "Delay",
"labelUsername": "Username",
"labelIP": "IP",
"labelReason": "Reason",
"labelSource": "Source",
"statusCrashed": "CRASHED",
"statusHigh": "HIGH",
"statusSuccess": "SUCCESS",
"statusFailed": "FAILED",
"statusDown": "DOWN",
"statusUp": "UP"
}
}
"email": {}
}