settings trim: remove dead settings, upstream remnants, JSON/Clash subscriptions

Per SETTINGS-AUDIT (all three tiers approved 2026-10-23):

Dead settings:
- panelOutbound, ipLimitAllowlist (+ orphan parser job), outboundDownThreshold
- tg fake events outbound.down/outbound.up/xray.crash (no publisher in lite)
- phantom routing sub-tabs (Happ/Clash/Incy) and subJsonRules direct-rules tab
  (no backend keys); subHideSettings moved to the subscription info tab first

Upstream remnants:
- ldap* / smtp* model+schema keys, EmailNotifications orphan component
- twoFactorEnable/twoFactorToken + login-page probe (no backend handler)
- externalTrafficInform*

Newly approved removals:
- JSON subscription family (producer, routes, UA auto-detect, mux/finalmask/
  observatory) and Clash subscription family (producer, routes, UA detect)
- SubBalancer (table, service, controller, settings tab)
- subThemeDir (subscription page falls back to the built-in template)
- datepicker jalalian option (gregorian only; Persian picker removed)

JSON/Clash endpoints now 404; link-format output pinned by regression tests.
Guarded keys untouched: webListen/webPort/webBasePath/certs, tg* chain,
expireDiff/trafficDiff/tgBotProxy, subHideSettings, pageSize/tgLang.
This commit is contained in:
Muse
2026-10-22 19:21:07 +00:00
parent 8e89960474
commit 1bd63e6625
110 changed files with 479 additions and 11313 deletions
+1 -108
View File
@@ -70,7 +70,6 @@
"install": "Install",
"clients": "Clients",
"usage": "Usage",
"twoFactorCode": "Code",
"remained": "Remaining",
"security": "Security",
"somethingWentWrong": "Something went wrong",
@@ -106,8 +105,7 @@
"docs": "Documentation",
"openMenu": "Open menu",
"pinSidebar": "Pin sidebar",
"unpinSidebar": "Unpin sidebar",
"subFormats": "Sub Formats"
"unpinSidebar": "Unpin sidebar"
},
"pages": {
"login": {
@@ -742,7 +740,6 @@
"detachFromInboundsResultMixed": "Detached {detached}, skipped {skipped}, errors {errors}.",
"subLinksTitle": "Sub links ({count})",
"subLinkColumn": "Subscription URL",
"subJsonLinkColumn": "Subscription JSON URL",
"subLinksCopyAll": "Copy all",
"subLinksCopiedAll": "Copied {count} link(s)",
"subLinksEmpty": "None of the selected clients have a subscription ID.",
@@ -1086,7 +1083,6 @@
"warnDefaultPort": "Default port 2053 is well-known — change it to a random port.",
"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.",
"panelListeningIP": "Listen IP",
"panelListeningIPDesc": "The IP address for the web panel. (leave blank to listen on all IPs)",
"panelListeningDomain": "Listen Domain",
@@ -1101,16 +1097,11 @@
"panelUrlPathDesc": "The URI path for the web panel. (begins with ‘/‘ and concludes with ‘/‘)",
"pageSize": "Pagination Size",
"pageSizeDesc": "Define page size for inbounds table. (0 = disable)",
"panelOutbound": "Panel Traffic Outbound",
"panelOutboundDesc": "Routes the panel's own requests — panel/Xray version checks and downloads, Telegram, and the normal geo-file update — through this Xray outbound to bypass server-side filtering of GitHub/Telegram. A loopback bridge inbound is added to the running config automatically and applied live. The Xray-native Geodata Auto-Update is not affected; it has its own download outbound. Leave empty for a direct connection.",
"panelOutboundPh": "Direct connection",
"remarkTemplate": "Remark Template",
"remarkTemplateDesc": "When set, this replaces the remark model for every subscription link — write your own format with the variable tokens (use the button to insert them). Leave empty to use the model above.",
"subShowIdentityOnAllLinks": "Show identity on every link",
"subShowIdentityOnAllLinksDesc": "When enabled, {{EMAIL}} and {{USERNAME}} stay on every subscription-body remark. Usage tokens still appear on the first link only.",
"datepicker": "Calendar Type",
"datepickerPlaceholder": "Select date",
"datepickerDescription": "Scheduled tasks will run based on this calendar.",
"oldUsername": "Current Username",
"currentPassword": "Current Password",
"newUsername": "New Username",
@@ -1126,22 +1117,6 @@
"subSettings": "Subscription",
"subEnable": "Subscription Service",
"subEnableDesc": "Enable/Disable the subscription service.",
"subJsonEnable": "Enable/Disable the JSON subscription endpoint independently.",
"subJsonEnableTitle": "JSON subscription",
"subClashEnableTitle": "Clash / Mihomo subscription",
"subFormatsTipTitle": "Format-specific subscription settings",
"subFormatsTipDesc": "Configure JSON and Clash / Mihomo URL paths, reverse URLs, and client auto-detection separately.",
"subFormatsTipAction": "Open Sub Formats",
"subJsonAutoDetect": "Auto-detect Xray JSON clients",
"subJsonAutoDetectDesc": "When enabled, recognized compatible clients requesting the standard subscription URL receive an Xray JSON configuration array automatically. Other clients keep the raw/base64 response. Requires JSON subscription to be enabled and a panel restart to apply.",
"subJsonAlwaysArray": "Always return a JSON array",
"subJsonAlwaysArrayDesc": "Return the explicit JSON subscription endpoint as an array even when it contains one profile, as required by the XTLS subscription standard. Auto-detected JSON responses always use arrays. Leave disabled to preserve the legacy single-object response.",
"subJsonUserAgentRegex": "Xray JSON User-Agent regex",
"subJsonUserAgentRegexDesc": "Go RE2 regular expression matched against the client's User-Agent to auto-select the Xray JSON format on the standard subscription URL. Empty by default, so auto-detection stays off until you set a pattern for the clients you want to serve. Other clients keep the raw/base64 response. Restart the panel after changes.",
"subClashAutoDetect": "Auto-detect Clash/Mihomo clients",
"subClashAutoDetectDesc": "When enabled, recognized Clash/Mihomo clients requesting the standard subscription URL receive Clash YAML automatically. Browsers still show the subscription page, other clients keep the raw/base64 response, and the explicit JSON and Clash URLs remain available. Requires Clash/Mihomo subscription to be enabled and a panel restart to apply.",
"subClashUserAgentRegex": "Clash/Mihomo User-Agent regex",
"subClashUserAgentRegexDesc": "Go RE2 regular expression matched against the client's User-Agent to recognize Clash/Mihomo clients on the standard subscription URL. Leave empty to use the default pattern. Restart the panel after changes.",
"subTitle": "Subscription Title",
"subTitleDesc": "Title shown in VPN client. Supports client identity tokens: {{EMAIL}}, {{ID}}, {{SHORT_ID}}, {{SUB_ID}}, {{TELEGRAM_ID}}.",
"subSupportUrl": "Support URL",
@@ -1150,23 +1125,8 @@
"subProfileUrlDesc": "A link to your website displayed in the VPN client. Supports client identity tokens: {{EMAIL}}, {{ID}}, {{SHORT_ID}}, {{SUB_ID}}, {{TELEGRAM_ID}}.",
"subAnnounce": "Announce",
"subAnnounceDesc": "The announcement text displayed in the VPN client. Supports client identity tokens: {{EMAIL}}, {{ID}}, {{SHORT_ID}}, {{SUB_ID}}, {{TELEGRAM_ID}}.",
"subThemeDir": "Sub Theme Directory",
"subThemeDirDesc": "Absolute path to a folder containing a custom index.html/sub.html subscription page template (e.g. /etc/3x-ui/sub_templates/my-theme/). Leave empty to use the default page.",
"subThemeDirDocs": "Template guide ↗",
"subEnableRouting": "Enable routing",
"subEnableRoutingDesc": "Global setting to enable routing in the VPN client. (Only for Happ)",
"subRoutingRules": "Routing rules",
"subRoutingRulesDesc": "Paste a ready happ:// deeplink or one permanent HTTPS URL returning a deeplink or JSON. The panel refreshes remote rules in the background and keeps the last valid value, so subscription requests never wait for the source. (Happ only)",
"subHideSettings": "Hide server settings",
"subHideSettingsDesc": "Hide the ability to view and edit server configurations in the VPN client. (Only for Happ)",
"subIncyEnableRouting": "Enable routing",
"subIncyEnableRoutingDesc": "Inject a routing profile into the subscription body for the Incy client. (Only for Incy)",
"subIncyRoutingRules": "Routing rules",
"subIncyRoutingRulesDesc": "Paste a ready incy:// deeplink or one permanent HTTPS URL returning JSON. An HTTPS URL becomes an autorouting profile refreshed by Incy itself. (Incy only)",
"subClashEnableRouting": "Enable routing",
"subClashEnableRoutingDesc": "Include global Clash/Mihomo routing rules in generated YAML subscriptions.",
"subClashRoutingRules": "Global routing rules",
"subClashRoutingRulesDesc": "Paste inline rules/YAML or one permanent HTTPS URL. The panel refreshes it in the background, imports only groups/providers/rules, preserves generated VPN nodes and keeps the last valid value.",
"subListen": "Listen IP",
"subListenDesc": "The IP address for the subscription service. (leave blank to listen on all IPs)",
"subPort": "Listen Port",
@@ -1195,8 +1155,6 @@
"trustedProxyCidrs": "Trusted proxy CIDRs",
"trustedProxyCidrsDesc": "Comma-separated IPs/CIDRs allowed to set forwarded host, proto, and client IP headers.",
"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.",
"packets": "Packets",
"length": "Length",
"interval": "Interval",
@@ -1207,16 +1165,12 @@
"packet": "Packet",
"delayMs": "Delay (ms)",
"applyTo": "Apply to",
"addNoise": "+ Noise",
"concurrency": "Concurrency",
"xudpConcurrency": "xudp concurrency",
"xudpUdp443": "xudp UDP 443"
},
"mux": "Mux",
"muxDesc": "Transmit multiple independent data streams within an established data stream.",
"muxSett": "Mux Settings",
"direct": "Direct Connection",
"directDesc": "Directly establishes connections with domains or IP ranges of a specific country.",
"certs": "Certificates",
"dateAndTime": "Date and Time",
"proxyAndServer": "Proxy and Server",
@@ -1226,7 +1180,6 @@
"language": "Language",
"security": {
"admin": "Admin credentials",
"twoFactorModalError": "Wrong code",
"show": "Show",
"hide": "Hide",
"apiTokenNew": "New token",
@@ -1248,9 +1201,6 @@
"getOutboundTrafficError": "Error getting traffic",
"resetOutboundTrafficError": "Error resetting outbound traffic"
},
"eventOutboundDown": "Down",
"eventOutboundUp": "Up",
"eventXrayCrash": "Crash",
"eventNodeDown": "Down",
"eventNodeUp": "Up",
"eventCPUHigh": "CPU high (%)",
@@ -1262,59 +1212,6 @@
},
"secretClear": "Clear",
"secretClearUndo": "Undo clear",
"calendarGregorian": "Gregorian (Standard)",
"calendarJalalian": "Jalalian (شمسی)",
"ipLimitAllowlist": "IP limit allowlist",
"ipLimitAllowlistDesc": "Addresses and networks that the IP limit never counts and never bans, so a shared office or campus address cannot use up a client's limit. Comma-separated, IP or CIDR.",
"subBalancers": {
"menu": "Sub Balancers",
"title": "Subscription balancer",
"add": "Add balancer",
"desc": "Each enabled balancer is added to the JSON subscription as one extra profile that automatically picks the best of the selected inbounds' endpoints (routing.balancers + burstObservatory in the client config).",
"remark": "Remark",
"remarkPlaceholder": "Auto · fastest",
"strategy": "Strategy",
"strategyLeastLoad": "Least load",
"strategyLeastPing": "Least ping",
"strategyRandom": "Random",
"strategyRoundRobin": "Round robin",
"sortOrder": "Order",
"sortOrderHelp": "Position in the subscription list, interleaved with the inbounds' own order; on equal numbers the balancer comes after the inbound.",
"inbounds": "Inbounds",
"inboundsCount": "{count} Inbounds",
"enabled": "Enabled",
"empty": "No balancers yet",
"deleteConfirm": "Delete this balancer?",
"errRemarkRequired": "Remark is required",
"errInboundsRequired": "Select at least one inbound",
"errSortOrder": "Order must be a whole number ≥ 1",
"toasts": {
"list": "Failed to list subscription balancers",
"create": "Failed to create subscription balancer",
"update": "Failed to update subscription balancer",
"delete": "Failed to delete subscription balancer",
"invalidId": "Invalid id"
},
"tabBalancers": "Balancers",
"tabObservatory": "Observatory",
"observatory": {
"title": "Balancer observatory",
"desc": "Probe parameters for the burst observatory emitted into each leastPing/leastLoad balancer profile. random/roundRobin balancers get no observatory. Stored as a panel-wide JSON-sub setting.",
"destination": "Probe URL",
"destinationDesc": "URL the client pings to measure each member outbound.",
"connectivity": "Connectivity URL",
"connectivityDesc": "Optional URL checked once to confirm the member can reach the probe destination. Leave empty to skip.",
"interval": "Probe interval",
"intervalDesc": "Time between probe rounds, e.g. 1m.",
"timeout": "Probe timeout",
"timeoutDesc": "Per-probe timeout, e.g. 5s.",
"sampling": "Sampling",
"samplingDesc": "Number of consecutive probes averaged for stability.",
"httpMethod": "HTTP method",
"httpMethodDesc": "Method used for probe requests.",
"note": "leastPing/leastLoad balancers always carry a burst observatory. This switch customises its probe parameters — turn it off to use the built-in defaults. Changes apply after a panel restart."
}
},
"TGBotSettings": "Telegram Bot",
"notifications": "Notifications",
"notifyTime": {
@@ -1822,12 +1719,8 @@
"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 }}",