Files
3x-ui/internal/web/translation/zh-TW.json
T
Sanaei 5e1cb7693b Repo-wide self-correcting audit: 54 verified bug fixes (#5970)
* fix(email): resolve a name-addr smtpFrom into bare envelope address and display name

The save-time validator accepts any RFC 5322 address form, so a value
like '3x-ui Panel <panel(at)example.com>' passes validation, but Send and
TestConnection fed that raw string to MAIL FROM, which strict servers
reject with 501, and buildMessage mangled it into a quoted local part.
Parse the configured sender at the point of use: the envelope gets the
bare address and, when no explicit sender name is set, the display name
embedded in the setting is used for the From header.

* fix(email): report a missing sender address from the SMTP connection test

TestConnection skipped the empty-from guard that Send enforces, so with
no sender and no username configured the test issued the null reverse-path
and could report success against a lenient relay while every real
notification send kept failing with the missing-sender error. Guard the
test path the same way and surface a dedicated translated message.

* fix(sub): fall back to the raw subscription when an auto-detected format has no content

With format auto-detection enabled, a client whose User-Agent matched the
Clash or JSON regex was routed straight to that format handler. For a
subscription whose entries convert to neither format (an MTProto-only
subscription, for example) the handler returns an empty document and the
request ended as 404, breaking a URL that served the raw list before the
toggle. The auto-detect branches now serve the detected format only when
it produces content and otherwise continue to the raw response; the
explicit format endpoints keep answering 404 for empty documents.

* fix(node): match prefixed central tags when filtering a selected-mode node snapshot

FilterNodeSnapshot compared a node snapshot's inbound tags against the
raw selected-tag list with an exact match, while its two siblings
(SnapshotHasUnadoptedInbounds and the reconcile tagToCentral map) expand
each selected tag to both its bare node-side form and its n<id>- prefixed
central form. A panel-created node inbound is recorded in the selected
list under the central prefixed tag but reported by the node under the
bare tag, so the exact match dropped it from every snapshot and the
orphan sweep then deleted its central row one tick after creation. Expand
the allowed set with the same prefix flip the siblings use.

* fix(client): refuse a bulk quota reduction that would fall to or below zero

BulkAdjust clamped a client's new traffic limit with max(total+addBytes, 0).
Because 0 is the unlimited sentinel, reducing a client's quota by more than
it had left silently granted that client unlimited traffic. The sibling
expiry branch already refuses an over-reduction; mirror it for quota so the
adjustment is skipped with a clear reason instead of crossing the sentinel.

* fix(client): persist a bulk adjustment's applied field even when the sibling field is skipped

In a mixed BulkAdjust (both a days delta and a bytes delta), a per-field
planning skip such as "unlimited expiry" or "unlimited traffic" was recorded
in the same map that gated the client_traffics write. The applied field was
already written to the inbound JSON and the clients table, but the enforcement
row was left untouched, so the depletion job cut the client on the old limit
while the panel showed the new one. Gate the traffic-row write on an actual
inbound-processing failure rather than on any planning-phase skip note.

* fix(inbound): always create in AddInbound instead of overwriting a row whose id was posted

The add controller binds the inbound model's id form field and never clears
it, and AddInbound persisted with GORM Save, which updates in place when the
primary key is non-zero. A client that reused an existing id (for instance by
duplicating an inbound fetched from /get and changing the port) silently
overwrote that stored row instead of creating a new inbound. Zero the id at
the top of AddInbound, matching how it already zeroes the client-stat ids.

* fix(inbound): accept WireGuard clients when creating an inbound

AddInbound's per-client validation switch had cases for every protocol
except WireGuard, so a WireGuard client fell through to the default branch
that requires a non-empty id. WireGuard clients are keyed by their public
key and carry no id, so importing a WireGuard inbound or re-adding one to a
reconciling node was rejected with "empty client ID". Add a wireguard case
that validates the client key, mirroring addInboundClient.

* fix(client): stop holding the inbound-lock registry mutex while waiting on one inbound

lockInbound acquired the global registry mutex and then blocked on the
per-inbound mutex without releasing the registry first. A slow client
operation holding one inbound's mutex (for example a bulk delete pushing to
an unreachable node) made the next waiter park on that inbound while still
holding the registry mutex, which in turn blocked lockInbound for every
other inbound — freezing client mutations panel-wide. Release the registry
mutex before taking the per-inbound lock.

* fix(client): honor keepTraffic when deleting a client that is attached to inbounds

Delete, DeleteByEmail and BulkDelete all pass keepTraffic to their final
cleanup transaction, but each called the per-inbound delete helper with a
hardcoded false. That helper purges the client's traffic, IP and stat rows
before the gated cleanup runs, so keepTraffic=true still destroyed all
traffic history for any client actually attached to an inbound (the pinned
test only covered a record with no inbound mappings). Thread the caller's
keepTraffic through to the per-inbound helper at all three call sites.

* fix(inbound): defer a local MTProto inbound edit's sidecar push until after commit

UpdateInbound applied a local MTProto inbound change by calling the runtime
UpdateInbound (which stops/starts the mtg sidecar or talks to it) from inside
runSerializedTx. That runs process and network I/O on the single traffic-writer
goroutine while a DB transaction is open, so a slow sidecar stalls traffic
accounting and every concurrent client mutation, and a later step failing the
transaction leaves the sidecar ahead of the rolled-back row. Move the push into
the post-commit hook, matching the xray branch. Adds a SetLocalRuntimeOverride
test seam mirroring the existing node override so the deferral is regression
tested.

* fix(client): delete external-link rows when bulk-deleting clients

The single-client Delete path removes a client's client_external_links rows,
but BulkDelete (and the DelDepleted reaper that routes through it) deleted the
record, mappings and traffic while leaving the external-link rows keyed by the
now-dead client id, so they accumulated as orphans. Delete them in the same
cleanup transaction, keyed by client id like the single path.

* fix(inbound): request an xray restart when toggling a routed MTProto inbound

AddInbound, DelInbound and UpdateInbound all flag needRestart when an inbound
routes MTProto through xray, so the egress SOCKS bridge is regenerated. Only
SetInboundEnable's local path omitted it, so toggling a routed MTProto inbound
off then on left the bridge out of the running config while the sidecar dialed
its loopback port, blackholing that inbound until an unrelated restart. Flag the
restart on the local enable path too.

* fix(client): apply enable-by-email to every inbound a client is attached to

ToggleClientEnableByEmail (Telegram bot) and SetClientEnableByEmail (LDAP sync)
resolved a single inbound via the legacy client_traffics pointer and flipped
enable only there. A client attached to several inbounds kept connecting through
the siblings' running Xray after being disabled, and the next edit could
re-enable it everywhere from a stale sibling. Route both through the
applyClientFieldByEmail fan-out (the #5039 fix path) so the whole multi-inbound
identity is toggled at once, dropping the circular Set/Toggle dependency.

* fix(traffic): commit a traffic tick even when a best-effort maintenance helper fails

addTrafficLocked stages the inbound and client deltas, then runs three helpers
(auto-renew, disable depleted clients, disable depleted inbounds) that are meant
to log and continue. All three reused the function-scope err that the deferred
commit/rollback inspects, so the last helper's error decided the whole tick: a
failure in disableInvalidInbounds rolled back the already-staged traffic while
AddTraffic reported success, and because xray had already advanced its counter
baseline that traffic was lost for good. Give each best-effort helper its own
error variable so only a genuine staging failure rolls the tick back.

* fix(traffic): re-enable clients and serialize the write in Reset All Client Traffic

ClientService.ResetAllTraffics zeroed up/down but, unlike every sibling reset
path, never restored enable=true, so clients that had been auto-disabled for
exceeding their quota stayed cut with zero usage after a reset. It also wrote
client_traffics directly on the shared DB handle instead of through the serial
traffic writer, reintroducing the cross-transaction lock-order deadlock the
writer exists to prevent. Restore enable and run the reset inside
submitTrafficWrite within one transaction.

* fix(traffic): keep node reset propagation out of the serial traffic writer

ResetAllTraffics and ResetInboundTraffic performed their remote-node reset HTTP
calls inside submitTrafficWrite. Each call can block up to the remote timeout,
and Reset All Traffics loops every node serially, so the single traffic-writer
goroutine was held for seconds — long enough that the concurrent 5s traffic poll
timed out submitting its own write and dropped the deltas it had already drained
from xray. Do the DB reset inside the writer, then propagate to the nodes after
it returns, matching how the mtproto quota reset is already sequenced.

* fix(sub): stop the subscription from 500ing on valid-but-unusual stream settings

The raw share-link generators used unchecked type assertions and unguarded
array indexing: an empty Reality shortIds/serverNames array (random.Num(0)
panics), a tcp-http header with no request block or an empty request.path, a
grpc block missing its keys, empty stream settings, and a non-string Host
header all panicked mid-generation. Because getSubs loops every client's link
with no recover, one such client 500s the entire subscription for everyone. The
sibling JSON, Clash and frontend generators already guard these; make the raw
generators match with comma-ok assertions and length checks.

* fix(sub): tolerate a hysteria inbound without hysteriaSettings in the JSON subscription

genHy asserted stream["hysteriaSettings"].(map[string]any) without the comma-ok
form, so a hysteria inbound whose StreamSettings omit the hysteriaSettings key
(a valid, representable shape the raw generator renders fine) panicked and 500ed
the entire JSON subscription. Use comma-ok; the downstream reads already guard
each key, so a nil map degrades gracefully.

* fix(sub): emit the pinned peer cert sha256 in Clash subscriptions

The Clash stream builder computed tlsSettings["pin-sha256"] from the inbound's
pinnedPeerCertSha256, but applySecurity's tls case never copied it onto the
proxy, so it was written with no reader and silently dropped. Clash subscribers
lost certificate pinning while JSON subscribers kept it. Surface pin-sha256 on
the proxy in the tls case, matching the JSON emitter.

* fix(link): parse the snake_case and extra-blob xhttp fields when importing a share link

The panel's share-link emitters (Go and TS) carry advanced xhttp knobs as a
snake_case x_padding_bytes plus an extra=<json> payload, but the Go parser's
xhttp branch read only top-level camelCase params, so importing an xhttp link
via the outbound-subscription feature dropped xPaddingBytes, scMaxEachPostBytes
and the rest, silently reverting them to the stream defaults and producing a
non-working outbound. Mirror the TS parser: read the snake_case alias, merge the
extra JSON blob, then let explicit camelCase params win.

* fix(frontend): decode URL-safe base64 when parsing an imported share link

Base64.decode called window.atob directly, which rejects the base64url
alphabet (- and _) and unpadded input. But the panel's own share-link emitter
uses Base64.encode(x, true) (URL-safe, unpadded), and real SIP002 links do too,
so importing a Shadowsocks link whose method:password encodes with a - or _ threw,
fell back to the raw undecoded string, and produced a wrong method and garbage
password (the vmess parser shared the same limitation). Normalize base64url and
re-pad before atob so decode round-trips every emitted link.

* fix(link): honor the vmess ws path and hysteria2 vcn params on import

Two Go/TS parser parity gaps in the outbound share-link import path: parseVmess
only applied a ws link's path when the inner JSON also carried a host key, so a
generator that omits host dropped the path back to the default; and parseHysteria2
hardcoded verifyPeerCertByName to empty, ignoring the vcn param the panel emits,
so a hysteria2 outbound with a decoy SNI and a distinct cert name failed TLS
verification after import. The TS parser handles both; make the Go parser match.

* fix(ui): stop the sniffing form island from clobbering unrendered fields

antd's Form.useWatch only reports registered fields, so while the
sniffing toggle was off the island emitted { enabled: false } upward and
replaced the full Sniffing object in form state. Saving a VLESS reverse
outbound then crashed in sniffingToWire on the missing ipsExcluded
array; the loopback outbound and the inbound sniffing tab shared the
same hole. Watch the store with preserve: true so unrendered fields
keep their values, and seed a missing value from the schema defaults
instead of an empty cast.

* fix(sub): drop empty remark segments instead of leaving a stray separator

expandSegment dropped a "|" segment only when its tokens rendered the unlimited
mark, so a segment whose only token resolved to the empty string (a client with
no comment, an unlimited client's expiry date) was kept as bare decoration,
leaving a trailing "|" or a dangling emoji on every share link's remark. Drop a
token-bearing segment whenever none of its tokens produce a real value, while
still keeping pure-literal segments.

* fix(xray): keep source- and domains-scoped routing rules when an inbound is deleted

removeInboundTagFromRules drops a routing rule whose inboundTag list becomes
empty only if the rule has no other matcher, but routingMatcherKeys omitted
xray-core's canonical source and domains keys. A rule scoped by source or domains
(common in hand-authored or imported configs) therefore lost its whole body —
including a security-relevant block — when its single listed inbound was deleted,
instead of just having the tag trimmed. Recognize source and domains as live
matchers.

* fix(xray): guard RemoveUser against an uninitialized handler client

Every XrayAPI handler method returns an error when HandlerServiceClient is nil,
except RemoveUser, which dereferenced it directly. A depletion sweep runs Init
with the port ignored and, during a restart window where the fresh process's
api port is still 0, Init fails and leaves the client nil — so RemoveUser
panicked (recovered by the traffic writer, but re-thrown every poll) instead of
returning an error. Add the same nil guard the siblings have.

* fix(xray): do not revive a manually stopped Xray on a background restart

RestartXray cleared isManuallyStopped unconditionally at its top, so the @30s
pending-config cron (and warp/ldap/outbound reconcile jobs) that call
RestartXray(false) resurrected an Xray the admin had deliberately stopped —
unlike the crash-detector, which honors the manual-stop flag. Skip a non-forced
restart while the stop flag is set; only an explicit forced restart clears it.

* fix(xray): retry a failed pending-restart instead of dropping the config change

The 30s cron consumed the need-restart flag with IsNeedRestartAndSetFalse before
calling RestartXray and only logged a failure. If RestartXray failed early (a
transient GetXrayConfig DB error) the old process kept running the old config,
the crash detector saw a running process and never retried, and the flag stayed
cleared — so an admin's saved change silently never reached the core. Move the
consume/restart/retry into ApplyPendingRestart, which re-arms the flag on
failure so the next tick retries.

* fix(xray): synchronize the process version and apiPort fields

Start writes p.version and p.apiPort (via refreshVersion/refreshAPIPort) after
flipping the process to running, while GetXrayVersion and GetAPIPort read them
lock-free from the status and traffic poll goroutines. The struct mutex
deliberately excluded these fields, so a restart racing a poll was a real data
race — a torn read of the version string header can crash. Extend the mutex to
cover version and apiPort, doing the blocking version probe before taking the
lock.

* fix(settings): detect a wildcard listen collision between the web and sub ports

The web/sub same-port check compared the two listen addresses as raw strings, so
binding both on all interfaces with different spellings (webListen 0.0.0.0 vs an
empty subListen) slipped past validation and only failed at startup with an
opaque bind error. Treat any wildcard listen ('', 0.0.0.0, ::) as overlapping so
the clash is reported up front, while still allowing two distinct specific
addresses to share a port.

* fix(db): mark the IP-limit cleanup seeder done on a fresh install

ResetIpLimitNoFail2ban is a one-time migration that, on a host without fail2ban,
zeroes every existing client's limitIp because the limit can't be enforced. It
was missing from the fresh-install fast-path seeder list, so on a brand-new DB it
did not run on the first boot but fired on the second — wiping any IP limits the
admin had set in between. Add it to the fast-path so a truly fresh install marks
it done up front (there is nothing to clean), leaving later admin-set limits
intact.

* fix(security): dial outbound subscriptions through the SSRF guard

The outbound-subscription fetch validated the URL host once (resolving DNS and
rejecting private targets) but then fetched with a plain HTTP client that
re-resolves the host at dial time, so a subscription domain the attacker controls
could pass validation as a public IP and rebind to 127.0.0.1 / a cloud metadata
endpoint / an internal host for the actual dial — a blind SSRF into the panel's
network. Route the direct fetch (and its redirects) through
netsafe.SSRFGuardedDialContext, which resolves, checks and dials the same IP
atomically, carrying the subscription's AllowPrivate flag on the request context;
a configured egress proxy still dials its loopback bridge unguarded.

* fix(security): bound the login-limiter attempts map

The login rate limiter keys its records on the caller-supplied username and only
evicted a record when that exact key was revisited or the login succeeded. An
unauthenticated attacker replaying one CSRF token while rotating a fresh username
per request seeded a record that was never revisited, growing the map without
bound until the panel OOMs. Cap the map: before inserting a new record, reclaim
records whose block has lapsed and whose failures aged out, and if the map is
still at the ceiling under a broad flood, drop one so memory can never grow past
the cap.

* fix(tgbot): require admin for privileged callbacks, not just the first switch

answerCallback wraps only its first callback switch in an isAdmin guard; the
second switch (server usage, inbound/online enumeration, database backup export,
ban logs, mass traffic reset, client creation) ran for every caller. Telegram
delivers a callback with the tapping user's id, so a non-admin who can see an
admin's inline keyboard — as when the bot runs in a group — could tap Backup and
receive the full database and config, or reset all traffic. Default-deny before
the second switch: a non-admin may only run the per-user client_* callbacks that
resolve their own data from their Telegram id.

* fix(eventbus): dispatch each subscriber in its own goroutine

The fan-out loop called every subscriber's handler sequentially on the
single dispatch goroutine. The email and Telegram notifiers block on
network I/O for tens of seconds (or minutes when the remote is slow), so
one slow subscriber stalled the whole loop: the 256-slot channel then
filled and Publish silently dropped later events — including high-value
xray.crash and node.down notifications unrelated to the slow handler.

Hand each delivered event to every handler in its own goroutine so a
blocking subscriber can no longer stall delivery to the others. safeCall
already recovers panics, so a detached handler cannot take down the bus.

* fix(integration): cap WARP API response body size

doWarpRequest read the response with an unbounded io.ReadAll, unlike the
sibling NordVPN client which already caps every read at maxResponseSize.
A hostile panel egress proxy or a MITM on the Cloudflare WARP endpoint
could stream an arbitrarily large body and force the panel into an
unbounded allocation. Wrap the body in an io.LimitReader(maxResponseSize)
to match the NordVPN client.

* fix(email): bound every SMTP step with a connection deadline

The "starttls"/"none" transport delivered through net/smtp.SendMail, which
dials with an untimed net.Dial and never sets a socket deadline. When an
SMTP server accepted the TCP connection but then stalled (or was a
blackhole), the caller was released by Send's 30s select, but the sender
goroutine and its socket stayed blocked until the OS TCP timeout — minutes
per notification, leaking a goroutine and a connection each time.
sendWithTLS dialed with a timeout but likewise armed no deadline on the
protocol phase, and TestConnection (called synchronously from the settings
handler, with no select guard) could hang the request indefinitely.

Replace SendMail with sendPlain, which dials with smtpConnectTimeout and
arms conn.SetDeadline(smtpDeadline) before the greeting read, preserving
SendMail's opportunistic STARTTLS upgrade. Arm the same deadline in
sendWithTLS and TestConnection so every SMTP step is bounded.

* fix(server): guard access-log parser against malformed lines

GetXrayLogs split each Xray access-log line on whitespace and then read
fixed offsets — parts[1] for the timestamp and parts[i+1] after the "from",
"accepted" and "email:" markers — without checking the line had that many
fields. A truncated or malformed line (the logged destination is
attacker-influenced) indexed past the slice and panicked; the panel handler
returned a 500 via Gin's recovery.

Extract the per-line field parsing into parseAccessLogFields and length
guard every positional lookup so a short line yields a partial entry
instead of panicking.

* fix(server): guard xray key-generator output parsing

GetNewX25519Cert, GetNewmldsa65 and GetNewmlkem768 parsed xray's stdout by
reading lines[0], lines[1] and each line's second colon-separated field
without any length check — unlike GetNewEchCert, which already guards its
line count. If the xray binary printed fewer than two lines or reformatted
its labels (a version change, or a silent failure that emitted nothing),
the fixed slice index panicked and the handler 500'd.

Extract the shared parsing into parseXrayKeyPairOutput, which length guards
the line count and each label split and returns an error instead of
panicking, then route all three generators through it.

* fix(tgbot): stop auto-deleted messages from resetting wizard state

SendMsgToTgbotDeleteAfter spawns a goroutine that, after the display delay,
deleted the transient message and then unconditionally cleared the chat's
conversation state. Every caller that ends a wizard step already clears the
state synchronously, so that call was redundant — and harmful: if within
the delay the user advanced to the next step (a callback sets a fresh
awaiting_* state), the late goroutine wiped it, and the user's next message
fell through unrecognized, silently dropping their input.

Move the delayed deletion into deleteMessageAfterDelay, which only removes
the message and no longer touches the conversation state. Guard
deleteMessageTgBot against a nil bot so the deletion path is unit-testable.

* fix(frontend): refetch a fresh CSRF token on 403 instead of reusing the stale meta tag

On a 403 to an unsafe method the client cleared its cached CSRF token and
called ensureCsrfToken to retry. But ensureCsrfToken prefers the
<meta name="csrf-token"> tag baked into the page, which the production
panel always injects, so the "refresh" re-read the same stale token and the
/csrf-token refetch was never reached — the retry re-sent the token that had
just been rejected and the save failed with an error toast.

The token lives in the session and rotates when the session is regenerated
(for example re-login in another tab), leaving the tab's baked-in meta token
stale. Fetch the current token straight from /csrf-token in the 403 branch so
the retry uses the authoritative server value. The existing tests only passed
because they strip the meta tag; the new test keeps a stale tag present.

* fix(frontend): surface backend error text from failed requests

HttpUtil.get/post read the thrown HttpError body as response.data.message,
but the backend error envelope (entity.Msg) serializes its text as msg. On
any non-2xx JSON response the real reason was therefore dropped and the
operator saw only the generic "Request failed with status N" toast.

Read response.data.msg first (keeping message and the native error text as
fallbacks). The sibling test had pinned the wrong body shape ({ message });
correct it to the real backend shape ({ success:false, msg }) so it exercises
the actual envelope.

* fix(frontend): share one WebSocket connection across bridge and hooks

websocketBridge.ts and useWebSocket.ts each declared their own
module-scoped sharedClient plus an identical getSharedClient, so the
"shared" client was not shared between them: whenever a page using
useWebSocket (Clients/Inbounds) mounted alongside the always-mounted
bridge, the panel opened two sockets to /ws. The server then pushed every
traffic/stats/nodes/inbounds snapshot to both, doubling WebSocket bandwidth
and running two independent reconnect loops, and the hook's socket was never
disconnected on unmount.

Hoist a single getSharedWebSocketClient into api/websocket.ts and route both
the bridge and the hook through it, so exactly one connection is opened.

* fix(frontend): guard the outbounds WebSocket handler against non-array payloads

onOutbounds wrote the raw WebSocket payload straight into the
outboundsTraffic cache, unlike the sibling onNodes/onInbounds handlers which
first check Array.isArray. A malformed non-array push (for example an object)
would land in the cache with staleTime Infinity; consumers that call
.find()/.map() on the outbounds list would then throw and crash the Outbounds
tab. Add the same Array.isArray guard so a bad push is ignored.

* fix(frontend): key the node table by the computed row key, not id

The desktop node table used rowKey="id", but transitive sub-nodes (the
read-only rows surfaced from downstream nodes) all carry id 0, so a topology
with two or more transitive rows gave React duplicate keys. antd's rowKey
prop overrides the row object's own computed `key` (`t-${guid}` for
transitive rows, the numeric id otherwise), so the unique key the code
already builds was ignored — causing row-state/DOM mis-association on any
re-render (heartbeat refetch, address-eye toggle). The mobile card path
already keyed by record.key.

Key the table by "key" so transitive rows get their distinct t-${guid}
identity; direct nodes keep key === id, so row selection (filtered to numeric
keys) is unchanged.

* fix(frontend): map routing row actions through the rule's real index

The routing table hides balancer-loopback rules (`_bl_*`) but keeps each
visible row's original index in `key`, then handed antd's positional row
index straight to edit/delete/toggle/move/drag — all of which mutate the
full, unfiltered routing.rules array. Once a hidden loopback rule precedes a
visible one (e.g. a balancer whose fallback is another balancer, plus any
rule added afterwards), the positional index no longer matches the array
index, so deleting or editing a rule silently hit the wrong one — including
destroying the loopback rule that keeps the balancer alive.

Add originalRuleIndex to translate a positional row index back through the
row's `key`, and route every mutating handler (openEdit, confirmDelete,
toggleRule, moveUp/moveDown, drag) through it. When no loopback rows are
hidden the mapping is the identity, so ordinary configs are unaffected.

* fix(frontend): map outbound row actions through the outbound's real index

The outbounds table hides balancer-loopback outbounds (`_bl_*`) but keeps
each visible row's original index in `key`, then passed antd's positional
row index to edit/delete/move and to the per-row probe (onTest) and its
result lookup — all of which address the full, unfiltered outbounds array.
Once a hidden loopback outbound precedes a visible one, the positional index
diverges from the array index, so deleting or editing an outbound hit the
wrong one (its deletion-impact plan and removal targeting the wrong entry),
and the test button probed / showed results against the wrong outbound.

Add originalOutboundIndex and route the mutating handlers through it; key
the probe trigger and test-result columns by record.key. With no loopback
rows hidden the mapping is the identity, so ordinary configs are unaffected.

* fix(frontend): tolerate a malformed happyEyeballs value in the Xray Basics tab

BasicsTab derived directHappyEyeballs by calling HappyEyeballsSchema.parse
during render, guarding only against null/non-object. A wrong-typed field
(e.g. happyEyeballs.tryDelayMs as a string) or any other shape mismatch —
reachable via the Complete Template JSON editor or an imported config — threw
straight out of render, white-screening the default Xray landing tab.

Use safeParse and fall back to null so a bad value degrades to "no override"
instead of crashing the page.

* fix(frontend): preserve routing-rule fields the form does not surface

The rule form rebuilt the rule from a fixed literal of only the fields it
edits, and RoutingTab replaces the rule wholesale on confirm. Fields the
form never exposes — localPort, localIP, process, ruleTag, webhook — are in
the rule schema and can arrive via the advanced JSON editor or Import Rules;
opening such a rule in the form and saving silently dropped them.

Carry over every key of the original rule the form does not manage before
applying the form-derived fields, so an edit only touches what it surfaces.

* fix(frontend): re-sync the sniffing island when its value changes externally

The sniffing config editor froze its seed value at mount and only watched
its own inner AntD form, never reflecting a later change to the shared RHF
`sniffing` path. Because the inbound form mounts every tab with
forceRender, the friendly Sniffing tab and the Advanced JSON editor are live
at once: editing sniffing in the JSON editor updated the RHF value but not
the frozen island, so the next interaction with the friendly tab emitted the
stale value and silently discarded the JSON edit.

Add an effect that pushes an external value change into the inner form,
guarded by the same lastEmitted marker the emit path uses so the island
never re-seeds from its own echo and no update loop forms.

* fix(frontend): don't drift a client's byte quota on a no-op save

The quota field shows the total in GB rounded to two decimals; editing a
client and saving converted that display value straight back to bytes. A
byte total not aligned to 0.01 GB — one set via the API or an import — was
therefore rewritten to the rounded value on any save that never touched the
field, losing a few MB each time.

Add resolveTotalBytes: keep the original byte total when the displayed GB
still matches it, and only re-derive from GB when the user actually changed
the field.

* fix(eventbus): deliver events on a bounded per-subscriber worker

The previous fix dispatched each event to every subscriber with a bare
`go safeCall`. That unblocked the dispatch loop, but removed the bus's
backpressure: under a login-attempt flood (which both notifier subscribers
process without rate-limiting) with email/Telegram enabled, every attempt
spawned handler goroutines that each block on network I/O for up to ~30s,
with no bound — a goroutine and outbound-connection storm. It also let a
subscriber's handler run concurrently with itself, racing the Telegram
notifier's lazily-cached hostname.

Give each subscriber its own bounded queue drained by a single worker
goroutine. Dispatch does a non-blocking send per subscriber (dropping only
that subscriber's event when its queue is full), so a slow subscriber still
can't stall the others, concurrency is bounded to one in-flight handler per
subscriber, per-subscriber event order is preserved, and Stop again waits
for in-flight handlers to finish.

* fix(frontend): map outbound mobile-card actions through the real index too

The desktop outbounds table was keyed by the outbound's real index, but the
mobile card list was left keying the probe trigger and every test-state
lookup by the positional row index. With a hidden balancer-loopback outbound
present, tapping Check on a mobile card probed the wrong outbound and the
Test-All results landed on the wrong card. Key onTest and the
testResult/isTesting reads by record.key, matching the desktop columns.

* fix(frontend): meet WCAG AA contrast on the config-block link text

The Storybook accessibility test flagged the share-link <code> block: with no
explicit color it inherited a muted grey that renders as #888888 on the
#f8f8f8 tertiary-fill background in CI's Chromium — a 3.33:1 contrast, below
the 4.5:1 AA threshold. Set the text to the theme's primary text token so the
colour is explicit and high-contrast in both light and dark themes instead of
depending on an inherited value that varies by browser.

* style(sub): simplify a negated conjunction to satisfy staticcheck QF1001

golangci-lint (staticcheck QF1001) flagged the `!(a && b)` guard in
expandSegment. Rewrite it via De Morgan's law to the equivalent
`!a || !b` form so the linter passes; behavior is unchanged.

* fix: close panics and races the audit's own fixes left nearby

Second-pass review of the 54-commit self-correcting audit. Each item below
was confirmed by reading the surrounding source (and, where practical, the
pre-fix code) before being changed; regression tests are included for every
behavioral fix.

Concurrency:
- eventbus: Bus.Subscribe called wg.Add with no synchronization against a
  concurrent Bus.Stop's wg.Wait, a real "WaitGroup misuse" panic risk (e.g. a
  Telegram-bot settings save racing panel shutdown/restart). Stop now flips a
  mu-guarded `stopped` flag before waiting, and Subscribe checks it under the
  same lock, so Add and Wait can no longer race.

Security:
- login_limiter: evictForRoom's fallback eviction picked an arbitrary map
  key, including ones still under an active cooldown - an attacker flooding
  /login with fresh usernames could evict their own (or anyone's) blocked
  record and reset the lockout. The fallback now skips actively-blocked
  records, only falling back to an unconditional evict if the map is
  somehow entirely full of active blocks (preserves the hard memory cap).

Subscription-endpoint panics (reachable by any client hitting /sub):
- internal/sub/service.go: applyPathAndHostParams/Obj (ws/httpupgrade/xhttp
  with no path settings object) and the TLS alpn readers in three places
  used unchecked type assertions - exactly the bug class abab7cd0 patched
  elsewhere in the same switch statements, just not these call sites.
- internal/sub/json_service.go, clash_service.go: the externalProxy loops
  in the JSON and Clash generators used unchecked assertions on a
  legacy/admin-supplied field (missing "port", non-object entry, etc.).
- internal/sub/json_service.go: realityData's shortId/serverName selection
  could assert a non-string array element.

Other correctness:
- client_traffic.go: ResetAllTraffics (touched by 3eb214d0) still skipped
  clearing NodeClientTraffic node-sync baselines, unlike its sibling reset
  paths in the same file - a node's next sync would re-add pre-reset delta
  on top of the freshly-zeroed counter.
- inbound_traffic.go: the traffic-tick tx's Commit/Rollback errors were
  silently discarded; now logged so a backend-level commit failure (e.g. an
  aborted Postgres tx from a best-effort helper) doesn't masquerade as a
  successful tick.
- outbound_subscription.go: the new subscriptionFetchClient doc comment was
  wedged between fetchAndStore's existing comment and fetchAndStore itself,
  leaving fetchAndStore undocumented and the comment describing the wrong
  function.

Convention cleanup:
- Removed narrative // comments added by the audit that violate this repo's
  no-inline-comment rule (mostly narrating the specific bug/fix rather than
  a lasting contract, and mostly on new Test functions, which this repo's
  existing tests never comment) - calibrated against this exact codebase's
  own pre-existing comment style so legitimate godoc-style doc comments
  were left alone.

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
2026-07-17 00:33:06 +02:00

2241 lines
118 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"username": "使用者名稱",
"password": "密碼",
"login": "登入",
"confirm": "確定",
"cancel": "取消",
"close": "關閉",
"save": "儲存",
"logout": "登出",
"create": "建立",
"add": "新增",
"remove": "移除",
"update": "更新",
"copy": "複製",
"copied": "已複製",
"more": "更多",
"download": "下載",
"regenerate": "重新產生",
"jsonEditor": "JSON 編輯器",
"downloadImage": "下載圖片",
"sort": "排序",
"remark": "備註",
"enable": "啟用",
"protocol": "協議",
"search": "搜尋",
"filter": "篩選",
"all": "全部",
"from": "從",
"to": "到",
"done": "完成",
"loading": "載入中...",
"refresh": "重新整理",
"clear": "清除",
"second": "秒",
"minute": "分鐘",
"hour": "小時",
"day": "天",
"check": "檢視",
"indefinite": "無限期",
"unlimited": "無限制",
"none": "無",
"qrCode": "二維碼",
"info": "更多資訊",
"edit": "編輯",
"delete": "刪除",
"reset": "重置",
"noData": "無數據。",
"copySuccess": "複製成功",
"sure": "確定",
"encryption": "加密",
"useIPv4ForHost": "使用 IPv4 連接主機",
"transmission": "傳輸",
"host": "主機",
"path": "路徑",
"camouflage": "混淆",
"status": "狀態",
"enabled": "開啟",
"disabled": "關閉",
"depleted": "耗盡",
"depletingSoon": "即將耗盡",
"offline": "離線",
"online": "上線",
"domainName": "域名",
"monitor": "監聽",
"certificate": "憑證",
"fail": "失敗",
"comment": "評論",
"success": "成功",
"lastOnline": "上次上線",
"getVersion": "獲取版本",
"install": "安裝",
"clients": "客戶端",
"usage": "使用情況",
"twoFactorCode": "代碼",
"remained": "剩餘",
"security": "安全",
"secAlertTitle": "安全警報",
"secAlertSsl": "此連線不安全。在啟用 TLS 進行資料保護之前,請勿輸入敏感資訊。",
"secAlertConf": "某些設定易受攻擊。建議加強安全協議以防止潛在漏洞。",
"secAlertSSL": "面板缺少安全連線。請安裝 TLS 證書以保護資料安全。",
"secAlertPanelPort": "面板預設埠存在安全風險。請配置隨機埠或特定埠。",
"secAlertPanelURI": "面板預設 URI 路徑不安全。請配置複雜的 URI 路徑。",
"secAlertSubURI": "訂閱預設 URI 路徑不安全。請配置複雜的 URI 路徑。",
"secAlertSubJsonURI": "訂閱 JSON 預設 URI 路徑不安全。請配置複雜的 URI 路徑。",
"emptyDnsDesc": "未添加DNS伺服器。",
"emptyFakeDnsDesc": "未添加Fake DNS伺服器。",
"emptyBalancersDesc": "未添加負載平衡器。",
"emptyReverseDesc": "未添加反向代理。",
"somethingWentWrong": "發生錯誤",
"subscription": {
"title": "訂閱資訊",
"subId": "訂閱 ID",
"status": "狀態",
"downloaded": "已下載",
"uploaded": "已上傳",
"expiry": "到期",
"totalQuota": "總配額",
"individualLinks": "個別連結",
"active": "啟用",
"inactive": "停用",
"unlimited": "無限制",
"noExpiry": "無到期",
"copyAllConfigs": "複製全部配置",
"copyAllConfigsCopied": "已複製全部配置",
"email": "電子郵件"
},
"menu": {
"theme": "主題",
"dark": "深色",
"ultraDark": "超深色",
"dashboard": "系統狀態",
"inbounds": "入站",
"clients": "客戶端",
"groups": "群組",
"nodes": "節點",
"settings": "面板設定",
"xray": "Xray 設定",
"routing": "路由",
"outbounds": "出站",
"apiDocs": "API 文件",
"logout": "退出登入",
"link": "管理",
"donate": "捐贈",
"hosts": "Hosts",
"docs": "文件",
"openMenu": "開啟選單"
},
"pages": {
"login": {
"hello": "你好",
"title": "歡迎",
"loginAgain": "登入時效已過,請重新登入",
"toasts": {
"invalidFormData": "資料格式錯誤",
"emptyUsername": "請輸入使用者名稱",
"emptyPassword": "請輸入密碼",
"wrongUsernameOrPassword": "用戶名、密碼或雙重驗證碼無效。",
"successLogin": "您已成功登入您的帳戶。"
}
},
"index": {
"title": "系統狀態",
"cpu": "CPU",
"logicalProcessors": "邏輯處理器",
"frequency": "頻率",
"swap": "交換空間",
"storage": "儲存",
"memory": "記憶體",
"threads": "執行緒",
"xrayStatus": "Xray",
"stopXray": "停止",
"restartXray": "重新啟動",
"xraySwitch": "版本",
"xrayUpdates": "Xray 更新",
"xraySwitchClick": "選擇你要切換到的版本",
"xraySwitchClickDesk": "請謹慎選擇,因為較舊版本可能與當前配置不相容",
"updatePanel": "更新面板",
"panelUpdateDesc": "這將把 3X-UI 更新到最新版本並重新啟動面板服務。",
"currentPanelVersion": "目前面板版本",
"latestPanelVersion": "最新面板版本",
"panelUpToDate": "面板已是最新",
"devChannel": "開發通道",
"devChannelWarning": "開發版會追蹤 main 的每次提交,並非穩定版本,且無法自動降級。",
"currentCommit": "目前提交",
"latestCommit": "最新提交",
"updateChannelChanged": "更新通道已切換",
"upToDate": "已是最新",
"xrayStatusUnknown": "未知",
"xrayStatusRunning": "運行中",
"xrayStatusStop": "停止",
"xrayStatusError": "錯誤",
"xrayErrorPopoverTitle": "執行Xray時發生錯誤",
"operationHours": "系統正常執行時間",
"systemHistoryTitle": "系統歷史",
"historyTitleCpu": "CPU 使用率",
"historyTitleMem": "記憶體使用率",
"historyTitleNetwork": "網路頻寬",
"historyTitlePackets": "網路封包",
"historyTitleDisk": "磁碟 I/O",
"historyTitleOnline": "線上用戶端",
"historyTitleLoad": "系統平均負載(1 分鐘 / 5 分鐘 / 15 分鐘)",
"historyTitleConnections": "使用中的連線 (TCP / UDP)",
"historyTitleDiskUsage": "磁碟空間使用率",
"historyTabBandwidth": "頻寬",
"historyTabPackets": "封包",
"historyTabDisk": "磁碟 I/O",
"historyTabOnline": "線上",
"historyTabLoad": "負載",
"historyTabConnections": "連線數",
"historyTabDiskUsage": "磁碟使用量",
"charts": "圖表",
"xrayMetricsTitle": "Xray 指標",
"xrayTitleHeap": "已配置的堆積記憶體",
"xrayTitleSys": "向作業系統保留的記憶體",
"xrayTitleObjects": "存活的堆積物件",
"xrayTitleGcCount": "已完成的 GC 週期",
"xrayTitleGcPause": "GC 暫停時間",
"xrayTitleObservatory": "出站連線健康狀態",
"xrayTabHeap": "堆積",
"xrayTabSys": "系統",
"xrayTabObjects": "物件",
"xrayTabGcCount": "GC 次數",
"xrayTabGcPause": "GC 暫停",
"xrayTabObservatory": "觀測站",
"xrayMetricsDisabled": "未設定 Xray 指標端點",
"xrayMetricsHint": "在 xray 設定中加入頂層 metrics 區塊,tag 為 metrics_out,listen 為 127.0.0.1:11111,然後重啟 xray。",
"xrayObservatoryEmpty": "尚無 Observatory 資料",
"xrayObservatoryHint": "在 xray 設定中加入 observatory 區塊,列出要探測的出站 tag,然後重啟 xray。",
"xrayObservatoryTagPlaceholder": "選擇出站",
"xrayObservatoryAlive": "在線",
"xrayObservatoryDead": "離線",
"xrayObservatoryLastSeen": "最後在線",
"xrayObservatoryLastTry": "最後嘗試",
"trendLast2Min": "最近 2 分鐘",
"systemLoad": "系統負載",
"systemLoadDesc": "過去 1、5 和 15 分鐘的系統平均負載",
"connectionCount": "連線數",
"ipAddresses": "IP地址",
"toggleIpVisibility": "切換IP可見性",
"overallSpeed": "整體速度",
"upload": "上傳",
"download": "下載",
"totalData": "總數據",
"sent": "已發送",
"received": "已接收",
"documentation": "文件",
"xraySwitchVersionDialog": "您確定要變更Xray版本嗎?",
"xraySwitchVersionDialogDesc": "這將會把Xray版本變更為#version#。",
"xraySwitchVersionPopover": "Xray 更新成功",
"panelUpdateDialog": "您確定要更新面板嗎?",
"panelUpdateDialogDesc": "這將把 3X-UI 更新到 #version# 並重新啟動面板服務。",
"panelUpdateCheckPopover": "面板更新檢查失敗",
"panelUpdateStartedPopover": "面板更新已開始",
"panelUpdateFailedTitle": "面板更新失敗",
"panelUpdateFailedDesc": "更新未成功完成。請檢查伺服器日誌,或在命令列執行「x-ui update」。",
"panelUpdateUnknownTitle": "無法確認更新是否已完成",
"panelUpdateUnknownDesc": "面板未能及時回報結果。請重新整理以檢查目前版本,或檢查伺服器日誌。",
"geofileUpdateDialog": "您確定要更新地理檔案嗎?",
"geofileUpdateDialogDesc": "這將更新 #filename# 檔案。",
"geofilesUpdateDialogDesc": "這將更新所有文件。",
"geofilesUpdateAll": "全部更新",
"geofileUpdatePopover": "地理檔案更新成功",
"geodataTitle": "Geodata 自動更新",
"geodataHint": "Xray 會按排程下載這些檔案並熱重載,無需重啟。URL 必須為 HTTPS。檔案必須已存在於 bin 目錄中,Xray 才能對其更新。",
"geodataCron": "更新排程 (cron)",
"geodataOutbound": "透過出站下載(可選)",
"geodataFile": "檔案名稱",
"geodataAddFile": "新增檔案",
"geodataSaveRestart": "儲存並重啟 Xray",
"geodataConfirmTitle": "儲存 geodata 設定?",
"geodataConfirmContent": "將更新 Xray 設定範本並重啟 Xray。",
"geodataInvalidUrl": "每個檔案都需要 HTTPS 位址。",
"geodataInvalidFile": "檔案名稱必須是純檔名,例如 geosite_custom.dat(不能包含路徑)。",
"geodataInvalidCron": "Cron 必須為 5 段,例如 0 4 * * *",
"geodataEmpty": "尚未設定檔案。路由規則中可透過 ext:geosite_custom.dat:category 引用檔案。",
"dontRefresh": "安裝中,請勿重新整理此頁面",
"logs": "記錄",
"accessLogs": "存取記錄",
"autoUpdate": "自動更新",
"config": "配置",
"backup": "備份",
"backupTitle": "備份和恢復",
"exportDatabase": "備份",
"exportDatabaseDesc": "點擊下載包含當前資料庫備份的 .db 文件到您的設備。同一檔案也可以還原到執行 PostgreSQL 的面板中。",
"importDatabase": "恢復",
"importDatabaseDesc": "點擊選擇並上傳設備中的 .db 備份或遷移匯出檔(.dump)以還原資料庫。",
"importDatabaseSuccess": "資料庫匯入成功",
"importDatabaseError": "匯入資料庫時發生錯誤",
"readDatabaseError": "讀取資料庫時發生錯誤",
"getDatabaseError": "檢索資料庫時發生錯誤",
"getConfigError": "檢索設定檔時發生錯誤",
"backupPostgresNote": "此面板執行於 PostgreSQL 上。「備份」會下載一個 pg_dump 封存檔(.dump),「還原」會透過 pg_restore 重新載入。「還原」也接受 SQLite 資料庫(.db)或 SQLite 遷移匯出檔,並將其資料匯入 PostgreSQL。伺服器需要安裝 PostgreSQL 用戶端工具(pg_dump 與 pg_restore)。",
"exportDatabasePgDesc": "點擊將目前資料庫的 PostgreSQL 傾印(.dump)下載到您的裝置。",
"importDatabasePgDesc": "點擊選擇並上傳 PostgreSQL 備份(.dump)、SQLite 資料庫(.db)或 SQLite 遷移匯出檔以還原您的資料庫。此操作將取代所有目前的資料。",
"migrationDownload": "下載遷移檔案",
"migrationDownloadPgDesc": "點擊下載由 PostgreSQL 資料建立的 .db SQLite 資料庫,可用於在 SQLite 上執行本面板。"
},
"inbounds": {
"title": "入站",
"totalDownUp": "總上傳 / 下載",
"totalUsage": "總用量",
"inboundCount": "入站數量",
"operate": "選單",
"enable": "啟用",
"remark": "備註",
"node": "節點",
"deployTo": "部署到",
"localPanel": "本機面板",
"fallbacks": {
"title": "Fallbacks",
"help": "當此入站的連線未匹配任何用戶時,將其路由到其他位置。在下方選擇一個子入站,可從其傳輸方式自動填入路由欄位(SNI / ALPN / Path / xver);或將選擇框留空並直接設定 Dest(例如 8080 或 127.0.0.1:8080),以路由到 Nginx 等外部伺服器。每個子入站應監聽 127.0.0.1security=none。",
"empty": "尚未新增回落",
"add": "新增回落",
"pickInbound": "選擇一個入站",
"matchAny": "任何",
"destPlaceholder": "自動(子入站 listen:port",
"rederive": "從子入站重新填入",
"rederived": "已從子入站重新填入",
"editAdvanced": "編輯路由欄位",
"hideAdvanced": "隱藏進階",
"quickAddAll": "一鍵新增所有符合的入站",
"quickAdded": "已新增 {n} 個回落",
"quickAddedNone": "沒有可新增的新入站",
"routesWhen": "當條件成立時路由",
"defaultCatchAll": "預設 — 兜底匹配其餘",
"needsTls": "在「安全」分頁選擇 TLS 或 Reality 後即可設定回落(僅限 RAW 上的 VLESS/Trojan)。"
},
"protocol": "協議",
"port": "連接埠",
"portMap": "連接埠對應",
"traffic": "流量",
"speed": "速度",
"details": "詳細資訊",
"transportConfig": "傳輸",
"expireDate": "到期時間",
"createdAt": "建立時間",
"updatedAt": "更新時間",
"resetTraffic": "重置流量",
"addInbound": "新增入站",
"generalActions": "通用操作",
"modifyInbound": "修改入站",
"deleteInbound": "刪除入站",
"deleteInboundContent": "確定要刪除入站嗎?",
"deleteConfirmTitle": "刪除入站「{remark}」?",
"deleteConfirmContent": "將刪除此入站及其所有客戶端。此操作無法復原。",
"resetConfirmTitle": "重置「{remark}」的流量?",
"resetConfirmContent": "將此入站的上/下行計數器歸零。",
"selectedCount": "已選 {count} 項",
"selectAll": "全選",
"bulkDeleteConfirmTitle": "刪除 {count} 個入站?",
"bulkDeleteConfirmContent": "將刪除所選入站及其所有客戶端。此操作無法復原。",
"cloneConfirmTitle": "複製入站「{remark}」?",
"cloneConfirmContent": "使用新連接埠和空客戶端清單建立副本。",
"delAllClients": "刪除所有客戶端",
"delAllClientsConfirmTitle": "從「{remark}」中刪除全部 {count} 個客戶端?",
"delAllClientsConfirmContent": "從此入站中移除每個客戶端並捨棄其流量記錄。入站本身將保留。此操作無法復原。",
"attachClients": "附加客戶端到…",
"addClientsToGroup": "將客戶端加入群組…",
"attachClientsTitle": "從「{remark}」附加客戶端",
"attachClientsDesc": "將相同的 {count} 個客戶端(相同 UUID/密碼與共享流量)附加到選定入站。它們仍保留於此入站。",
"attachClientsTargets": "目標入站",
"attachClientsNoTargets": "沒有可附加的其他相容入站。",
"attachClientsResult": "已附加 {attached},已略過 {skipped}。",
"attachClientsResultMixed": "已附加 {attached},已略過 {skipped},錯誤 {errors}。",
"attachClientsSelectLabel": "要附加的客戶端",
"attachClientsSearchPlaceholder": "搜尋電子郵件或備註",
"attachClientsStatusDisabled": "已停用",
"attachClientsSelectedCount": "已選 {selected}/{total}",
"attachExistingClients": "附加現有客戶端…",
"attachExistingTitle": "將現有客戶端附加到「{remark}」",
"attachExistingDesc": "將現有客戶端(可用 {count} 個)附加到此入站 — 相同 UUID/密碼與共享流量。已在此入站的客戶端將被略過。",
"attachExistingNoClients": "尚無客戶端。請先建立客戶端,然後在此附加。",
"attachExistingStatusAttached": "已附加",
"detachClients": "分離客戶端",
"detachClientsTitle": "從「{remark}」分離客戶端",
"detachClientsDesc": "僅從此入站移除選取的客戶端。客戶端記錄保留(用 Delete 完全移除)。來源共有 {count} 個客戶端。",
"detachClientsResult": "已分離 {detached},已略過 {skipped}。",
"detachClientsResultMixed": "已分離 {detached},已略過 {skipped},錯誤 {errors}。",
"detachClientsSelectLabel": "要分離的客戶端",
"exportLinksTitle": "匯出入站連結",
"exportSubsTitle": "匯出訂閱連結",
"exportAllLinksTitle": "匯出所有入站連結",
"exportAllSubsTitle": "匯出所有訂閱連結",
"exportAllLinksFileName": "所有入站",
"exportAllSubsFileName": "所有入站-Subs",
"inboundJsonTitle": "入站 JSON",
"deleteClient": "刪除客戶端",
"deleteClientContent": "確定要刪除客戶端嗎?",
"resetTrafficContent": "確定要重置流量嗎?",
"copyLink": "複製連結",
"address": "地址",
"network": "網路",
"destinationPort": "目標埠",
"targetAddress": "目標地址",
"monitorDesc": "留空表示監聽所有 IP",
"meansNoLimit": "= 無限制。(單位: GB)",
"totalFlow": "總流量",
"leaveBlankToNeverExpire": "留空表示永不過期",
"noRecommendKeepDefault": "建議保留預設值",
"certificatePath": "檔案路徑",
"certificateContent": "檔案內容",
"publicKey": "公鑰",
"privatekey": "私鑰",
"clickOnQRcode": "點選二維碼複製",
"client": "客戶",
"export": "匯出連結",
"clone": "複製",
"cloneInbound": "複製",
"cloneInboundContent": "此入站規則除埠(Port)、監聽 IP(Listening IP)和客戶端(Clients)以外的所有配置都將應用於克隆",
"cloneInboundOk": "建立克隆",
"resetAllTraffic": "重置所有入站流量",
"resetAllTrafficTitle": "重置所有入站流量",
"resetAllTrafficContent": "確定要重置所有入站流量嗎?",
"resetInboundClientTraffics": "重置客戶端流量",
"resetInboundClientTrafficTitle": "重置所有客戶端流量",
"resetInboundClientTrafficContent": "確定要重置此入站客戶端的所有流量嗎?",
"resetAllClientTraffics": "重置所有客戶端流量",
"resetAllClientTrafficTitle": "重置所有客戶端流量",
"resetAllClientTrafficContent": "確定要重置所有客戶端的所有流量嗎?",
"delDepletedClients": "刪除流量耗盡的客戶端",
"delDepletedClientsTitle": "刪除流量耗盡的客戶端",
"delDepletedClientsContent": "確定要刪除所有流量耗盡的客戶端嗎?",
"email": "電子郵件",
"emailDesc": "電子郵件必須完全唯一",
"IPLimit": "IP 限制",
"IPLimitDesc": "如果數量超過設定值,則禁用入站流量。(0 = 禁用)",
"IPLimitlog": "IP 日誌",
"IPLimitlogDesc": "IP 歷史日誌(要啟用被禁用的入站流量,請清除日誌)",
"IPLimitlogclear": "清除日誌",
"setDefaultCert": "從面板設定證書",
"setDefaultCertEmpty": "面板尚未設定憑證。請先在「設定」中設定。",
"streamTab": "傳輸",
"securityTab": "安全",
"sniffingTab": "嗅探",
"sniffingMetadataOnly": "僅中繼資料",
"sniffingRouteOnly": "僅路由",
"sniffingIpsExcluded": "排除的 IP",
"sniffingDomainsExcluded": "排除的網域",
"decryption": "解密",
"encryption": "加密",
"vlessAuthX25519": "X25519 (native)",
"vlessAuthMlkem768": "ML-KEM-768 (native)",
"vlessAuthX25519Xorpub": "X25519 (xorpub)",
"vlessAuthX25519Random": "X25519 (random)",
"vlessAuthMlkem768Xorpub": "ML-KEM-768 (xorpub)",
"vlessAuthMlkem768Random": "ML-KEM-768 (random)",
"vlessAuthCustom": "自訂",
"vlessAuthSelected": "已選擇:{auth}",
"vlessAuthGenerate": "生成密鑰",
"vlessAuthGenerateButton": "生成",
"advanced": {
"title": "入站 JSON 部分",
"subtitle": "完整入站 JSON 以及針對 settings、sniffing 和 streamSettings 的專用編輯器。",
"all": "全部",
"allHelp": "在單一編輯器中編輯包含所有欄位的完整入站物件。",
"settings": "設定",
"settingsHelp": "Xray settings 區塊包裝:",
"sniffing": "Sniffing",
"sniffingHelp": "Xray sniffing 區塊包裝:",
"stream": "Stream",
"streamHelp": "Xray stream 區塊包裝:",
"jsonErrorPrefix": "進階 JSON"
},
"telegramDesc": "請提供Telegram聊天ID。(在機器人中使用'/id'命令)或({'@'}userinfobot",
"subscriptionDesc": "要找到你的訂閱 URL,請導航到“詳細資訊”。此外,你可以為多個客戶端使用相同的名稱。",
"subSortIndex": "訂閱排序",
"same": "相同",
"inboundInfo": "入站資訊",
"exportInbound": "匯出入站規則",
"import": "匯入",
"importInbound": "匯入入站規則",
"periodicTrafficResetTitle": "流量重置",
"periodicTrafficResetDesc": "按指定間隔自動重置流量計數器",
"lastReset": "上次重置",
"periodicTrafficReset": {
"never": "從不",
"daily": "每日",
"weekly": "每週",
"monthly": "每月",
"hourly": "每小時"
},
"toasts": {
"obtain": "獲取",
"updateSuccess": "更新成功",
"logCleanSuccess": "日誌已清除",
"inboundsUpdateSuccess": "入站連接已成功更新",
"inboundUpdateSuccess": "入站連接已成功更新",
"inboundCreateSuccess": "入站連接已成功建立",
"bulkDeleted": "已刪除 {count} 個入站",
"bulkDeletedMixed": "已刪除 {ok} 個,失敗 {failed} 個",
"inboundDeleteSuccess": "入站連接已成功刪除",
"inboundClientAddSuccess": "已新增入站客戶端",
"inboundClientDeleteSuccess": "入站客戶端已刪除",
"inboundClientUpdateSuccess": "入站客戶端已更新",
"savedNodeOfflineWillSync": "已在本機儲存。某個支撐節點離線或已停用——重新連線後將同步此變更。",
"delDepletedClientsSuccess": "所有耗盡客戶端已刪除",
"resetAllClientTrafficSuccess": "客戶端所有流量已重置",
"resetAllTrafficSuccess": "所有流量已重置",
"resetInboundClientTrafficSuccess": "流量已重置",
"resetInboundTrafficSuccess": "入站流量已重置",
"trafficGetError": "取得流量資料時發生錯誤",
"getNewX25519CertError": "取得X25519憑證時發生錯誤。",
"getNewmldsa65Error": "取得mldsa65憑證時發生錯誤。",
"getNewVlessEncError": "取得VlessEnc憑證時發生錯誤。",
"scanRealityTargetError": "掃描 REALITY 目標失敗。",
"scanRealityTargetFeasible": "目標可用 — 已填入目標與 SNI。",
"scanRealityTargetNotFeasible": "目標可達,但不適用於 REALITY。",
"invalidClientField": "用戶端 {client}:欄位 {field} — {reason}",
"invalidField": "{field} — {reason}",
"moreIssues": "{message} (另有 {count} 項)"
},
"form": {
"moveUp": "上移",
"moveDown": "下移",
"addAll": "全部新增",
"addAllFallbackTooltip": "為每個尚未連線的符合條件入站新增一個 fallback 列",
"peers": "Peers",
"addPeer": "新增 peer",
"keepAlive": "Keep-alive",
"autoSystemRoutesTooltip": "僅 Windows。CIDR 會自動加入系統路由表,使匹配的流量通過 TUN。",
"autoOutboundsInterface": "自動出站介面",
"autoOutboundsInterfaceTooltip": "出站流量的實體介面。使用 'auto' 進行偵測;設定 Auto system routes 時自動啟用。",
"rewriteAddress": "改寫地址",
"rewritePort": "改寫連接埠",
"allowedNetwork": "允許的網路",
"followRedirect": "跟隨重新導向",
"accounts": "帳號",
"allowTransparent": "允許透明",
"encryptionMethod": "加密方法",
"fakeTlsDomain": "FakeTLS 網域 (SNI)",
"mtprotoSecret": "金鑰",
"mtgDomainFrontingIp": "網域前置 IP",
"mtgDomainFrontingPort": "網域前置連接埠",
"mtgDomainFrontingProxyProtocol": "網域前置 PROXY 協定",
"mtgDomainFrontingHint": "mtg 轉發非 Telegram 流量的目標——例如你的 NGINX 偽裝站台。IP 留空則透過 DNS 解析 FakeTLS 網域;預設連接埠為 443。",
"mtgProxyProtocolListener": "接受 PROXY 協定(監聽器)",
"mtgPreferIp": "IP 偏好",
"mtgDebug": "除錯日誌",
"mtgRouteThroughXray": "透過 Xray 路由",
"mtgRouteThroughXrayHint": "讓此代理的 Telegram 流量經過 Xray,以套用您的路由規則。mtg 附屬程序會透過帶有此入站標籤的本機 SOCKS 橋接出站;在路由分頁中引用該標籤即可設定進階規則。",
"mtgRouteOutbound": "出站",
"mtgRouteOutboundHint": "選填。強制 Telegram 流量經由此出站(或負載平衡器)送出。留空則由您的路由規則決定。",
"mtgRouteOutboundPlaceholder": "使用路由規則",
"mtprotoFakeTlsDomainHint": "產生新用戶端金鑰時使用的預設 FakeTLS 網域。每個用戶端可使用各自的網域。",
"mtgThrottleMaxConnections": "最大連線數",
"mtgThrottleMaxConnectionsHint": "以公平分配限制所有使用者的並行連線數。0 表示不限制。",
"mtgAdTagInvalid": "廣告標籤必須為 32 位十六進位字元。",
"mtgPublicIpv4": "公網 IPv4",
"mtgPublicIpv6": "公網 IPv6",
"mtgPublicIpHint": "本伺服器可存取的公網位址,供廣告標籤的中間代理使用。留空則由 mtg 自動偵測。",
"visionTestseed": "Vision testseed",
"version": "版本",
"udpIdleTimeout": "UDP 閒置逾時 (s)",
"masquerade": "偽裝",
"type": "類型",
"upstreamUrl": "Upstream URL",
"rewriteHost": "改寫 Host",
"skipTlsVerify": "略過 TLS 驗證",
"directory": "目錄",
"statusCode": "狀態碼",
"body": "Body",
"headers": "標頭",
"proxyProtocol": "Proxy Protocol",
"requestVersion": "請求版本",
"requestMethod": "請求方法",
"requestPath": "請求路徑",
"requestHeaders": "請求標頭",
"responseVersion": "回應版本",
"responseStatus": "回應狀態",
"responseReason": "回應原因",
"responseHeaders": "回應標頭",
"heartbeatPeriod": "心跳週期",
"serviceName": "服務名稱",
"authority": "Authority",
"multiMode": "多模式",
"maxBufferedUpload": "最大緩衝上傳",
"maxUploadSize": "最大上傳大小 (位元組)",
"streamUpServer": "Stream-Up 伺服器",
"serverMaxHeaderBytes": "伺服器最大標頭位元組",
"paddingBytes": "Padding 位元組",
"uplinkHttpMethod": "Uplink HTTP 方法",
"paddingObfsMode": "Padding 混淆模式",
"paddingKey": "Padding Key",
"paddingHeader": "Padding Header",
"paddingPlacement": "Padding 位置",
"paddingMethod": "Padding 方法",
"sessionPlacement": "Session 位置",
"sessionKey": "Session Key",
"sessionIDTable": "工作階段 ID 字元表",
"sessionIDTableHint": "產生工作階段 ID 使用的字元集:預定義名稱(ALPHABET、Base62、hex、number 等)或字面 ASCII 字串。留空則使用 xray-core 預設值。",
"sessionIDLength": "工作階段 ID 長度",
"sessionIDLengthHint": "產生工作階段 ID 的長度或範圍(如 8-16)。僅在設定了工作階段 ID 字元表時生效;最小值必須大於 0。",
"sequencePlacement": "Sequence 位置",
"sequenceKey": "Sequence Key",
"uplinkDataPlacement": "Uplink 資料位置",
"uplinkDataKey": "Uplink 資料 Key",
"noSseHeader": "無 SSE 標頭",
"ttiMs": "TTI (ms)",
"uplinkMbps": "上行 (MB/s)",
"downlinkMbps": "下行 (MB/s)",
"cwndMultiplier": "CWND 倍數",
"maxSendingWindow": "最大發送視窗",
"externalProxy": "外部代理",
"forceTls": "強制 TLS",
"fingerprint": "指紋",
"defaultOption": "預設",
"routeMark": "Route Mark",
"tcpKeepAliveInterval": "TCP Keep Alive 間隔",
"tcpKeepAliveIdle": "TCP Keep Alive Idle",
"tcpMaxSeg": "TCP Max Seg",
"tcpUserTimeout": "TCP User Timeout",
"tcpWindowClamp": "TCP Window Clamp",
"tcpWindowClampHint": "留 0 使用作業系統預設值。非零值會限制通告的 TCP 接收視窗;像 600 這樣的值(來自 Xray 文件範例)在高延遲連結上可能導致吞吐量驟降。",
"tcpFastOpen": "TCP Fast Open",
"multipathTcp": "Multipath TCP",
"penetrate": "Penetrate",
"v6Only": "僅 V6",
"tcpCongestion": "TCP Congestion",
"dialerProxy": "Dialer Proxy",
"trustedXForwardedFor": "信任的 X-Forwarded-For",
"trustedXForwardedForHint": "信任此請求標頭以取得真實用戶端 IP(例如 Cloudflare CDN 後的 CF-Connecting-IP)。僅在 WebSocket、HTTPUpgrade、XHTTP 和 gRPC 傳輸上生效。留空則忽略轉發標頭。",
"proxyProtocolHint": "接受 PROXY protocol 標頭,從上游 L4 隧道或中繼(HAProxy、gost、nginx-stream、Xray dokodemo-door)或 Cloudflare Spectrum 取得真實用戶端 IP。上游必須傳送 PROXY protocol。適用於 TCP、WebSocket、HTTPUpgrade 和 gRPC;不適用於 mKCP。",
"realClientIp": "真實用戶端 IP",
"realClientIpHint": "當流量透過 CDN 或中繼到達此入站時,取得訪客的真實 IP,而非記錄中間節點的位址。選擇一個預設以自動填入下方對應的 sockopt 欄位。這些欄位絕不會在訂閱中傳送給用戶端。",
"realClientIpPresetOff": "關閉 / 直連",
"realClientIpPresetCloudflare": "Cloudflare CDN",
"realClientIpPresetProxyProtocol": "L4 中繼 / Spectrum (PROXY)",
"realClientIpTrustedHeaderTransportWarn": "Trusted X-Forwarded-For 僅在 WebSocket、HTTPUpgrade 和 XHTTP 上生效。在目前的傳輸上此標頭將被忽略。",
"realClientIpProxyProtocolTransportWarn": "PROXY protocol 不支援此傳輸(mKCP)。請使用 TCP/RAW、WebSocket、HTTPUpgrade、gRPC 或 XHTTP。",
"addressPortStrategy": "地址+連接埠策略",
"tryDelayMs": "嘗試延遲 (ms)",
"prioritizeIPv6": "IPv6 優先",
"interleave": "Interleave",
"maxConcurrentTry": "最大並發嘗試",
"customSockopt": "自訂 sockopt",
"addCustomOption": "新增自訂選項",
"serverNameIndication": "SNI",
"cipherSuites": "Cipher Suites",
"autoOption": "自動",
"minMaxVersion": "最小/最大版本",
"rejectUnknownSni": "拒絕未知 SNI",
"disableSystemRoot": "停用系統根",
"sessionResumption": "工作階段恢復",
"oneTimeLoading": "一次性載入",
"usageOption": "使用選項",
"buildChain": "建立憑證鏈",
"echKey": "ECH key",
"echConfig": "ECH 設定",
"pinnedPeerCertSha256": "釘選對端憑證 SHA-256",
"pinnedPeerCertSha256Tip": "對端憑證的 SHA-256 雜湊(十六進位字串,如 e8e2d3…),以逗號分隔。僅面板使用 — 不寫入伺服器的 xray 設定,但會包含在分享連結中,以便用戶端釘選憑證。",
"pinnedPeerCertSha256Placeholder": "十六進位雜湊,以逗號分隔",
"getNewEchCert": "取得新 ECH 憑證",
"show": "顯示",
"xver": "Xver",
"target": "目標",
"maxTimeDiff": "最大時間差 (ms)",
"minClientVer": "最小客戶端版本",
"maxClientVer": "最大客戶端版本",
"shortIds": "Short IDs",
"realityTargetHint": "必填。必須包含連接埠(例如 example.com:443)。沒有連接埠時 Xray-core 將無法啟動。",
"realityTargetRequired": "REALITY 目標為必填項",
"realityTargetNeedsPort": "REALITY 目標必須包含連接埠(例如 example.com:443",
"realityTargetInvalidPort": "REALITY 目標的連接埠無效",
"scan": "掃描",
"findTargets": "尋找目標",
"scanModalTitle": "REALITY 目標掃描器",
"scanModalDesc": "驗證某個網域,或掃描 IP / CIDR 範圍,從憑證中探索新的 REALITY 目標。留空則探測常用候選。",
"scanDiscoverPlaceholder": "IP、CIDR 或網域 — 留空使用常用候選",
"scanStatus": "狀態",
"scanFeasible": "可用",
"scanNotFeasible": "不可用",
"scanCurve": "金鑰交換",
"scanCert": "憑證",
"scanCertInvalid": "不受信任",
"scanLatency": "延遲",
"scanUse": "使用",
"scanRescan": "重新掃描",
"spiderX": "SpiderX",
"spiderXHint": "各客戶端的種子——面板據此為每個客戶端衍生唯一的 spx 路徑;重新產生可輪換所有客戶端的路徑",
"getNewCert": "取得新憑證",
"mldsa65Seed": "mldsa65 Seed",
"mldsa65Verify": "mldsa65 Verify",
"getNewSeed": "取得新 Seed",
"echSockopt": "ECH Sockopt",
"echSockoptTip": "Xray 用來取得 ECH 設定清單的連線之通訊端選項(例如讓查詢透過 dialerProxy 出站)。停用則使用預設值。",
"curvePreferences": "曲線偏好",
"curvePreferencesTip": "依偏好順序限制伺服器提供的 TLS 金鑰交換曲線(例如 X25519MLKEM768、X25519)。留空則使用 Xray-core 預設值。",
"masterKeyLog": "主金鑰日誌",
"masterKeyLogTip": "寫入 TLS 主金鑰的路徑(SSLKEYLOGFILE 格式),用於以 Wireshark 除錯。正式環境請留空——擁有該檔案的任何人都能解密流量。",
"verifyPeerCertByName": "依名稱驗證對端憑證",
"verifyPeerCertByNameTip": "要求客戶端以此名稱(而非 SNI)驗證伺服器憑證。以逗號分隔多個名稱。僅面板使用——會包含在分享連結中(vcn)。這是 allowInsecure 的新式替代方案,Xray 已於 2026-06-01 之後移除 allowInsecure。",
"pinFromCert": "從此入站的憑證填入",
"pinFromRemote": "透過 ping SNI 取得雜湊值(xray tls ping",
"pinFromRemoteNoSni": "請先設定 SNIserverName)才能 ping 遠端憑證。",
"pinFromRemoteFailed": "無法取得遠端憑證雜湊值。",
"limitFallback": "限制 Fallback",
"limitFallbackUpload": "限制 Fallback 上傳",
"limitFallbackDownload": "限制 Fallback 下載",
"afterBytes": "起算位元組",
"afterBytesTip": "讓 fallback 以全速傳輸此數量的位元組後,再開始限速。0 = 從第一個位元組起即限速。",
"bytesPerSec": "每秒位元組",
"bytesPerSecTip": "在達到門檻後套用於 fallback 流量的速度上限(位元組/秒),使探測無法將你的伺服器當成通往目標的免費頻寬。0 = 不限制(停用此方向)。",
"burstBytesPerSec": "每秒突發位元組",
"burstBytesPerSecTip": "允許短暫超出穩定速率的額度(token-bucket 大小)。若低於「每秒位元組」,則會提升至與其相同。",
"listenHelp": "也可以填寫 Unix socket 路徑(例如 /run/xray/in.sock),或以 @ 為前綴的抽象通訊端名稱(例如 @xray/in.sock),以使用通訊端而非 TCP 連接埠監聽——此時請將連接埠設為 0。",
"shareAddrStrategy": "分享地址策略",
"shareAddrStrategyHelp": "控制匯出分享連結、QR Code 和訂閱輸出時寫入哪個地址。",
"shareAddr": "自訂分享地址",
"shareAddrHelp": "僅在分享地址策略為自訂時使用。填寫不帶協定和連接埠的網域或 IP。",
"subSortIndex": "訂閱排序",
"subSortIndexHelp": "此入站的連結在訂閱輸出(訂閱頁面和客戶端應用)中的位置。數值越小越靠前;數值相同時保持建立順序。不影響面板中的入站清單。",
"shareAddrStrategyOptions": {
"node": "節點地址",
"listen": "入站監聽地址",
"custom": "自訂"
}
},
"info": {
"mode": "模式",
"grpcServiceName": "grpc serviceName",
"grpcMultiMode": "grpc multiMode",
"interfaceName": "介面名稱",
"mtu": "MTU",
"gateway": "Gateway",
"dns": "DNS",
"outboundsInterface": "出站介面",
"autoSystemRoutes": "自動系統路由",
"followRedirect": "FollowRedirect",
"auth": "認證",
"noKernelTun": "非核心 TUN",
"keepAlive": "Keep alive",
"peerNumber": "Peer {n}",
"peerNumberConfig": "Peer {n} 設定"
},
"stream": {
"general": {
"request": "請求",
"response": "響應",
"name": "名稱",
"value": "值"
},
"tcp": {
"version": "版本",
"method": "方法",
"path": "路徑",
"status": "狀態",
"statusDescription": "狀態說明",
"requestHeader": "請求頭",
"responseHeader": "響應頭"
}
},
"sniffingDestOverride": "目標覆寫"
},
"clients": {
"tabBasics": "基本",
"tabCredentials": "認證資訊",
"tabLinks": "連結",
"wireguardConfig": "WireGuard 設定",
"config": "設定",
"linksHint": "新增第三方分享連結和遠端訂閱網址,將其包含在此用戶端的訂閱中。",
"addExternalLink": "新增外部連結",
"addExternalSubscription": "新增外部訂閱",
"noExternalLinks": "尚無外部連結。",
"noExternalSubscriptions": "尚無外部訂閱。",
"add": "新增客戶端",
"edit": "編輯客戶端",
"submitAdd": "新增客戶端",
"submitEdit": "儲存變更",
"clientCount": "客戶端數量",
"bulk": "批次新增",
"copyFromInbound": "從入站複製客戶端",
"copyToInbound": "複製客戶端至",
"copySelected": "複製所選",
"copySource": "來源",
"copyEmailPreview": "產生的信箱預覽",
"copySelectSourceFirst": "請先選擇一個來源入站。",
"copyResult": "複製結果",
"copyResultSuccess": "複製成功",
"copyResultNone": "沒有內容可複製:未選取客戶端或來源為空",
"copyResultErrors": "複製錯誤",
"copyFlowLabel": "新客戶端的 Flow (VLESS)",
"copyFlowHint": "套用至所有被複製的客戶端。留空則略過。",
"selectAll": "全選",
"clearAll": "全部清除",
"method": "方法",
"first": "首個",
"last": "末位",
"ipLog": "IP 日誌",
"prefix": "前綴",
"postfix": "後綴",
"delayedStart": "首次使用後開始",
"expireDays": "時長 (天)",
"days": "天",
"renew": "自動續期",
"renewDesc": "到期後自動續期。(0 = 停用) (單位: 天)",
"renewDays": "自動續期 (天)",
"searchPlaceholder": "搜尋電子郵件、備註、sub ID、UUID、密碼、auth、Telegram ID…",
"filterTitle": "篩選客戶端",
"clearAllFilters": "清除全部",
"filters": {
"nodes": "節點",
"localPanel": "本機(此面板)"
},
"showingCount": "顯示 {shown} / {total}",
"sortOldest": "最舊優先",
"sortNewest": "最新優先",
"sortRecentlyUpdated": "最近更新",
"sortRecentlyOnline": "最近上線",
"sortEmailAZ": "電子郵件 A→Z",
"sortEmailZA": "電子郵件 Z→A",
"sortMostTraffic": "流量最多",
"sortHighestRemaining": "剩餘最多",
"sortExpiringSoonest": "即將到期",
"has": "擁有",
"hasNot": "不擁有",
"title": "客戶端",
"actions": "操作",
"totalGB": "流量上限 (GB)",
"totalGBDesc": "該客戶端的流量配額。0 = 不限制。",
"expiryTime": "到期時間",
"addClients": "新增客戶端",
"limitIp": "IP 限制",
"limitIpDesc": "最大同時連線 IP 數。0 = 不限制。",
"limitIpFail2banMissing": "未安裝 Fail2ban,無法實施 IP 限制。請從 x-ui 命令列選單安裝 Fail2ban 以啟用此選項。",
"limitIpFail2banWindows": "Windows 上不支援 Fail2ban,無法實施 IP 限制。",
"limitIpDisabled": "此伺服器已停用 IP 限制功能。",
"password": "密碼",
"passwordDesc": "僅 Trojan 與 Shadowsocks 用戶端使用;VLESS、VMess、Hysteria 和 WireGuard 會忽略此項。",
"subId": "訂閱 ID",
"online": "上線",
"email": "電子郵件",
"emailInvalidChars": "電子郵件不能包含空格、'/'、'\\' 或控制字元",
"subIdInvalidChars": "訂閱ID不能包含空格、'/'、'\\' 或控制字元",
"group": "群組",
"groupDesc": "用於將相關客戶端歸類的邏輯標籤(如團隊、客戶、地區)。可從工具列篩選。",
"groupPlaceholder": "如 customer-a",
"comment": "備註",
"traffic": "流量",
"speed": "速度",
"offline": "離線",
"addClient": "新增客戶端",
"qrCode": "QR 碼",
"clientInfo": "客戶端資訊",
"delete": "刪除",
"reset": "重設流量",
"editClient": "編輯客戶端",
"client": "客戶端",
"enabled": "已啟用",
"remaining": "剩餘",
"duration": "時長",
"attachedInbounds": "關聯入站",
"selectInbound": "選擇一個或多個入站",
"selectAllInbounds": "全選",
"clearAllInbounds": "全部清除",
"noSubId": "此客戶端沒有 subId,無法產生共享連結。",
"noLinks": "沒有可共享的連結 — 請先將此客戶端關聯至支援協定的入站。",
"link": "連結",
"resetNotPossible": "請先將此客戶端關聯至入站。",
"general": "一般",
"resetAllTraffics": "重設所有客戶端流量",
"resetAllTrafficsTitle": "重設所有客戶端流量?",
"resetAllTrafficsContent": "所有客戶端的上下行計數器將歸零。配額與到期時間不受影響。此操作無法復原。",
"deleteConfirmTitle": "刪除客戶端 {email}",
"deleteConfirmContent": "將從所有關聯入站中移除該客戶端並刪除其流量紀錄。此操作無法復原。",
"deleteSelected": "刪除 ({count})",
"adjustSelected": "調整 ({count})",
"subLinksSelected": "訂閱連結 ({count})",
"addToGroupTitle": "將 {count} 個客戶端加入群組",
"addToGroupTooltip": "選擇現有群組或輸入新名稱。使用 Ungroup 操作從當前群組移除客戶端。",
"groupName": "群組名稱",
"addToGroupSuccessToast": "已將 {count} 個客戶端加入 {group}",
"ungroupSuccessToast": "已清除 {count} 個客戶端的群組",
"ungroup": "取消群組",
"ungroupConfirmTitle": "將 {count} 個客戶端從其群組中移除?",
"ungroupConfirmContent": "清除每個選取客戶端的群組標籤。客戶端本身保留(用 Delete 完全移除)。",
"addToGroup": "加入群組",
"attach": "附加",
"adjust": "調整",
"subLinks": "訂閱連結",
"enable": "啟用",
"disable": "停用",
"bulkEnableConfirmTitle": "啟用 {count} 個客戶端?",
"bulkEnableConfirmContent": "在每個已附加的入站上啟用所選的客戶端。配額已用盡或已過期的客戶端將被自動重新停用。",
"bulkDisableConfirmTitle": "停用 {count} 個客戶端?",
"bulkDisableConfirmContent": "在每個已附加的入站上停用所選的客戶端。他們將立即失去存取權限,但其記錄與流量將被保留。",
"selectedCount": "已選 {count} 項",
"attachSelected": "附加 ({count})",
"attachToInboundsTitle": "將 {count} 個客戶端附加到入站",
"attachToInboundsDesc": "將選取的 {count} 個客戶端(相同 UUID/密碼與共享流量)附加到選定入站。它們保留現有附加關係。",
"attachToInboundsTargets": "目標入站",
"attachToInboundsNoTargets": "沒有可供附加的多用戶入站。",
"detachSelected": "分離 ({count})",
"detach": "分離",
"detachFromInboundsTitle": "從入站分離 {count} 個客戶端",
"detachFromInboundsDesc": "從選定入站中移除選取的 {count} 個客戶端。客戶端未附加的配對會被靜默略過。客戶端記錄保留(用 Delete 完全移除)。",
"detachFromInboundsTargets": "要分離的入站",
"detachFromInboundsNoTargets": "沒有可用的多用戶入站。",
"detachFromInboundsResult": "已分離 {detached},已略過 {skipped}。",
"detachFromInboundsResultMixed": "已分離 {detached},已略過 {skipped},錯誤 {errors}。",
"subLinksTitle": "訂閱連結 ({count})",
"subLinkColumn": "訂閱 URL",
"subJsonLinkColumn": "訂閱 JSON URL",
"subLinksCopyAll": "全部複製",
"subLinksCopiedAll": "已複製 {count} 條連結",
"subLinksEmpty": "選取的客戶端皆無訂閱 ID。",
"subLinksDisabled": "訂閱服務已停用。",
"subLinksDisabledHint": "在面板設定 → 訂閱中啟用訂閱以產生連結。",
"bulkDeleteConfirmTitle": "刪除 {count} 個客戶端?",
"bulkDeleteConfirmContent": "每個所選客戶端都會從關聯的入站中被移除,其流量紀錄也會被刪除。此操作無法復原。",
"bulkAdjustTitle": "調整 {count} 個客戶端",
"bulkAdjustHint": "正值延長,負值減少。具有無限期限或流量的客戶端將跳過該欄位。",
"bulkAdjustNothing": "套用前請設定天數或流量。",
"addDays": "新增天數",
"addTrafficGB": "新增流量 (GB)",
"bulkFlow": "設定 flow",
"bulkFlowNoChange": "不變更",
"bulkFlowDisable": "停用(清除 flow",
"delDepleted": "刪除已耗盡",
"delDepletedConfirmTitle": "刪除已耗盡的客戶端?",
"delDepletedConfirmContent": "刪除所有流量配額已用盡或已過期的客戶端。此操作無法復原。",
"exportClients": "匯出客戶端",
"importClients": "匯入客戶端",
"import": "匯入",
"delOrphans": "刪除未關聯的客戶端",
"delOrphansConfirmTitle": "刪除沒有入站的客戶端?",
"delOrphansConfirmContent": "移除所有未關聯任何入站的客戶端,連同其流量紀錄一併刪除。此操作無法復原。",
"auth": "認證",
"hysteriaAuth": "Hysteria 認證",
"hysteriaAuthDesc": "僅 Hysteria 用戶端使用的憑證。Trojan 與 Shadowsocks 請改用上方的「密碼」欄位。",
"uuid": "UUID",
"flow": "Flow",
"vmessSecurity": "VMess 加密",
"wireguardPrivateKey": "WireGuard 私鑰",
"wireguardPublicKey": "WireGuard 公鑰",
"wireguardPreSharedKey": "WireGuard 預共用金鑰",
"wireguardAllowedIPs": "WireGuard 允許的 IP",
"wireguardAllowedIPsHint": "留空則自動分配;多個條目用逗號分隔",
"mtprotoSecret": "MTProto 金鑰",
"mtprotoSecretHint": "該用戶端的 FakeTLS 金鑰。重新產生即可更換。",
"mtprotoAdTag": "廣告標籤(贊助頻道)",
"mtprotoAdTagHint": "選填的 32 位十六進位標籤,從 Telegram 代理註冊處取得。設定後,該用戶端會透過 Telegram 中間代理路由,贊助頻道會顯示在其聊天清單頂端。",
"reverseTag": "反向標籤",
"reverseTagPlaceholder": "選用 Reverse tag",
"telegramId": "Telegram 使用者 ID",
"telegramIdPlaceholder": "數字形式的 Telegram 使用者 ID (0 = 無)",
"created": "建立時間",
"updated": "更新時間",
"ipLimit": "IP 限制",
"toasts": {
"deleted": "客戶端已刪除",
"trafficReset": "流量已重設",
"allTrafficsReset": "所有客戶端流量已重設",
"bulkDeleted": "已刪除 {count} 個客戶端",
"bulkDeletedMixed": "已刪除 {ok} 個,失敗 {failed} 個",
"bulkEnabled": "已啟用 {count} 個客戶端",
"bulkEnabledMixed": "已啟用 {ok} 個,失敗 {failed} 個",
"bulkDisabled": "已停用 {count} 個客戶端",
"bulkDisabledMixed": "已停用 {ok} 個,失敗 {failed} 個",
"bulkCreated": "已建立 {count} 個客戶端",
"bulkCreatedMixed": "已建立 {ok} 個,失敗 {failed} 個",
"bulkAdjusted": "已調整 {count} 個客戶端",
"bulkAdjustedMixed": "已調整 {ok} 個,跳過 {skipped} 個",
"delDepleted": "已刪除 {count} 個已耗盡的客戶端",
"delOrphans": "已刪除 {count} 個未關聯的客戶端",
"imported": "已匯入 {count} 個客戶端",
"importedMixed": "已匯入 {ok} 個,跳過 {failed} 個"
}
},
"groups": {
"title": "群組",
"name": "名稱",
"clientCount": "客戶端",
"totalGroups": "群組總數",
"totalGroupedClients": "有群組的客戶端",
"trafficUsed": "已用流量",
"upload": "上傳",
"download": "下載",
"totalTraffic": "總流量",
"totalUpDown": "總上傳 / 下載",
"addGroup": "新增群組",
"createSuccess": "已建立群組「{name}」。",
"rename": "重新命名",
"renameTitle": "重新命名 {name}",
"renameCollision": "已存在名為「{name}」的群組。",
"renameSuccess": "已為 {count} 個客戶端重新命名群組。",
"deleteConfirmTitle": "刪除群組 {name}?",
"deleteConfirmContent": "這將刪除群組並清除 {count} 個客戶端的標籤。客戶端本身不會被刪除。",
"deleteSuccess": "已清除 {count} 個客戶端的群組。",
"resetTraffic": "重置流量",
"resetConfirmTitle": "重置群組 {name} 的流量?",
"resetConfirmContent": "這只會將此群組的流量計數器歸零,不影響各個客戶端的計數器。",
"resetSuccess": "已重置群組 {name} 的流量。",
"adjustSuccess": "已調整 {name} 中的 {count} 個客戶端。",
"emptyForAction": "此群組尚無客戶端。",
"deleteGroupOnly": "刪除群組(保留客戶端)",
"deleteClients": "刪除群組中的客戶端",
"deleteClientsConfirmTitle": "刪除 {name} 中的所有客戶端?",
"deleteClientsConfirmContent": "這將永久刪除 {count} 個客戶端及其流量記錄。群組標籤亦會被清除。此操作無法復原。",
"deleteClientsSuccess": "已刪除 {count} 個客戶端。",
"deleteClientsMixed": "已刪除 {ok},已略過 {failed}",
"addToGroup": "新增客戶端…",
"addToGroupTitle": "將客戶端加入群組「{name}」",
"addToGroupDesc": "選擇要加入此群組的客戶端。保留其現有入站附加;僅更改群組標籤。已在此群組中的客戶端不會列出。",
"addToGroupEmpty": "沒有其他可加入的客戶端。",
"addToGroupResult": "已將 {count} 個客戶端加入 {name}。",
"removeFromGroup": "移除客戶端…",
"removeFromGroupTitle": "從群組「{name}」移除客戶端",
"removeFromGroupDesc": "選擇要從此群組移除的成員。客戶端本身保留(用「刪除群組中的客戶端」完全移除)。",
"removeFromGroupResult": "已從 {name} 移除 {count} 個客戶端。"
},
"nodes": {
"title": "節點",
"addNode": "新增節點",
"editNode": "編輯節點",
"totalNodes": "節點總數",
"onlineNodes": "上線",
"offlineNodes": "離線",
"avgLatency": "平均延遲",
"name": "名稱",
"namePlaceholder": "例如:de-frankfurt-1",
"addressPlaceholder": "panel.example.com 或 1.2.3.4",
"remark": "備註",
"scheme": "協議",
"address": "位址",
"port": "連接埠",
"basePath": "基礎路徑",
"apiToken": "API 權杖",
"apiTokenPlaceholder": "遠端面板設定頁中的權杖",
"apiTokenHint": "遠端面板在 安全設定 → API 權杖 中顯示其 API 權杖。",
"regenerate": "重新產生權杖",
"regenerateConfirm": "重新產生會使目前的權杖失效。任何使用該權杖的中央面板將失去存取權,直到更新為止。是否繼續?",
"allowPrivateAddress": "允許私有地址",
"allowPrivateAddressHint": "僅對私有網路或VPN上的節點啟用。",
"outboundTag": "連線出站",
"outboundTagHint": "透過選定的 Xray 出站路由此節點的面板 API 流量。系統會自動將迴環橋接入站加入執行中的設定並即時套用。留空表示直接連線。",
"outboundTagPlaceholder": "直接連線",
"inboundSyncMode": "入站匯入",
"inboundSyncModeHint": "選擇要從此節點匯入的入站。現有節點預設匯入所有入站。",
"allInbounds": "所有入站",
"selectedInbounds": "選取的入站",
"inboundTags": "入站",
"inboundTagsHint": "依入站標籤比對。空白選取不會匯入任何入站。",
"inboundTagsPlaceholder": "載入並選取入站",
"loadInbounds": "從節點載入入站",
"inboundsLoaded": "已載入 {{count}} 個入站",
"inboundsLoadFailed": "載入入站失敗",
"enable": "已啟用",
"status": "狀態",
"cpu": "CPU",
"mem": "記憶體",
"netUp": "網路上行 (KB/s)",
"netDown": "網路下行 (KB/s)",
"uptime": "運行時間",
"latency": "延遲",
"lastHeartbeat": "上次心跳",
"xrayVersion": "Xray 版本",
"panelVersion": "面板版本",
"actions": "操作",
"probe": "立即探測",
"updatePanel": "更新面板",
"updateSelected": "更新所選 ({count})",
"updateAvailable": "有可用更新",
"upToDate": "已是最新",
"updateConfirmTitle": "將 {count} 個節點更新到最新版本?",
"updateConfirmContent": "每個所選節點會下載最新版本並重新啟動。僅更新已啟用且在線的節點。",
"updateDevChannel": "更新到開發通道(最新提交)",
"testConnection": "測試連線",
"connectionOk": "連線正常 ({ms} ms)",
"connectionFailed": "連線失敗",
"never": "從未",
"justNow": "剛剛",
"subNode": "子節點",
"subNodeTip": "唯讀:透過 {parent} 連接的下游節點。請在 {parent} 自己的面板中管理。",
"deleteConfirmTitle": "刪除節點「{name}」?",
"deleteConfirmContent": "這將停止監控該節點。遠端面板本身不受影響。",
"statusValues": {
"online": "上線",
"offline": "離線",
"unknown": "未知",
"xrayError": "Xray 錯誤",
"xrayStopped": "已停止"
},
"toasts": {
"list": "載入節點失敗",
"obtain": "載入節點失敗",
"add": "新增節點",
"update": "更新節點",
"delete": "刪除節點",
"deleted": "節點已刪除",
"test": "測試連線",
"fillRequired": "名稱、位址、埠與 API 權杖為必填",
"probeFailed": "探測失敗",
"updateStarted": "已開始更新面板",
"updateResult": "已在 {ok} 個節點上觸發更新,{failed} 個失敗",
"updateNoneEligible": "請至少選擇一個在線且已啟用的節點",
"saveMtls": "儲存節點 mTLS"
},
"tlsVerifyMode": "TLS 驗證",
"tlsVerifyModeHint": "面板如何驗證節點的 HTTPS 憑證。釘選或略過用於自簽憑證(僅 https 節點)。",
"tlsVerify": "驗證(預設 CA",
"tlsPin": "釘選憑證(SHA-256",
"tlsSkip": "略過驗證",
"tlsMtls": "雙向 TLS(用戶端憑證)",
"mtlsFormHint": "此節點使用用戶端憑證對面板進行驗證。請從「節點 mTLS」區域複製本面板的 CA 到該節點,設定其受信任的 CA,然後重新啟動該節點。",
"mtls": {
"title": "節點 mTLS",
"intro": "雙向 TLS 在節點間呼叫的 API 權杖之上增加用戶端憑證驗證。此為選用項目:留空則僅使用權杖驗證。",
"copyCa": "複製此面板的 CA",
"copyCaHint": "將此 CA 提供給本面板管理的節點,然後將它們的 TLS 驗證設定為雙向 TLS。",
"caCopied": "CA 憑證已複製到剪貼簿",
"caFailed": "取得 CA 憑證失敗",
"trustLabel": "受信任的上層 CA",
"trustHint": "當本面板自身作為節點時,將管理它的面板的 CA 貼到此處以要求其用戶端憑證。重新啟動面板後生效。",
"trustPlaceholder": "-----BEGIN CERTIFICATE-----",
"save": "儲存受信任的 CA",
"saved": "受信任的 CA 已儲存 — 重新啟動面板後生效"
},
"tlsSkipWarning": "略過驗證會失去對中間人攻擊的防護,API 權杖可能被攔截。建議改用釘選憑證。",
"pinnedCert": "釘選憑證的 SHA-256",
"pinnedCertHint": "節點憑證的 SHA-256base64 或 hex)。點選「取得」可立即從節點讀取。",
"pinnedCertPlaceholder": "base64 或 hex 的 SHA-256",
"fetchPin": "取得",
"pinFetched": "已取得節點目前憑證",
"pinFetchFailed": "無法取得憑證"
},
"settings": {
"title": "面板設定",
"save": "儲存",
"infoDesc": "此處的所有更改都需要儲存並重啟面板才能生效",
"restartPanel": "重新啟動面板",
"restartPanelDesc": "確定要重啟面板嗎?若重啟後無法訪問面板,請前往伺服器檢視面板日誌資訊",
"restartPanelSuccess": "面板已成功重新啟動",
"actions": "操作",
"resetDefaultConfig": "重置為預設配置",
"panelSettings": "常規",
"securitySettings": "安全設定",
"securityWarnings": "安全警告",
"panelExposed": "您的面板可能已暴露:",
"warnHttp": "面板透過明文 HTTP 提供服務 — 生產環境請設定 TLS。",
"warnDefaultPort": "預設連接埠 2053 廣為人知 — 請更改為隨機連接埠。",
"warnDefaultBasePath": "預設根路徑 \"/\" 廣為人知 — 請更改為隨機路徑。",
"warnDefaultSubPath": "預設訂閱路徑 \"/sub/\" 廣為人知 — 請更改。",
"warnDefaultJsonPath": "預設 JSON 訂閱路徑 \"/json/\" 廣為人知 — 請更改。",
"TGBotSettings": "Telegram 機器人",
"panelListeningIP": "面板監聽 IP",
"panelListeningIPDesc": "預設留空監聽所有 IP",
"panelListeningDomain": "面板監聽域名",
"panelListeningDomainDesc": "預設情況下留空以監視所有域名和 IP 地址",
"panelPort": "面板監聽埠",
"panelPortDesc": "重啟面板生效",
"publicKeyPath": "面板證書公鑰檔案路徑",
"publicKeyPathDesc": "填寫一個 '/' 開頭的絕對路徑",
"privateKeyPath": "面板證書金鑰檔案路徑",
"privateKeyPathDesc": "填寫一個 '/' 開頭的絕對路徑",
"panelUrlPath": "URI 路徑",
"panelUrlPathDesc": "必須以 '/' 開頭,以 '/' 結尾",
"pageSize": "分頁大小",
"pageSizeDesc": "定義入站表的頁面大小。設定 0 表示禁用",
"panelOutbound": "面板流量出站",
"panelOutboundDesc": "透過此 Xray 出站路由面板自身的請求(面板/Xray 版本檢查與下載、Telegram、一般 geo 檔案更新),以繞過伺服器端對 GitHub/Telegram 的過濾。本地橋接入站會自動加入執行中的設定並即時生效。Xray 原生的 Geodata 自動更新不受影響,它有自己的下載出站。留空表示直連。",
"panelOutboundPh": "直連",
"datepicker": "日期選擇器",
"datepickerPlaceholder": "選擇日期",
"datepickerDescription": "選擇器日曆類型指定到期日期",
"oldUsername": "原使用者名稱",
"currentPassword": "原密碼",
"newUsername": "新使用者名稱",
"newPassword": "新密碼",
"telegramBotEnable": "啟用 Telegram 機器人",
"telegramBotEnableDesc": "啟用 Telegram 機器人功能",
"telegramToken": "Telegram Token",
"telegramTokenDesc": "從 '{'@'}BotFather' 獲取的 Telegram 機器人令牌",
"telegramProxy": "SOCKS 代理",
"telegramProxyDesc": "啟用 SOCKS5 代理連線到 Telegram(根據指南調整設定)",
"telegramAPIServer": "Telegram API 伺服器",
"telegramAPIServerDesc": "要使用的 Telegram API 伺服器。留空以使用預設伺服器。",
"telegramChatId": "管理員聊天 ID",
"telegramChatIdDesc": "Telegram 管理員聊天 ID (多個以逗號分隔)(可通過 {'@'}userinfobot 獲取,或在機器人中使用 '/id' 命令獲取)",
"telegramNotifyTime": "通知時間",
"telegramNotifyTimeDesc": "Telegram 機器人傳送週期性報告的頻率。選擇預設間隔,或選擇「自訂」以輸入 crontab 運算式。",
"notifyTime": {
"every": "@every — 依間隔重複",
"hourly": "@hourly — 每小時",
"daily": "@daily — 每天 00:00",
"weekly": "@weekly — 每週",
"monthly": "@monthly — 每月",
"custom": "自訂 (crontab)",
"seconds": "秒",
"minutes": "分鐘",
"hours": "小時",
"interval": "間隔",
"unit": "單位"
},
"tgNotifyBackup": "資料庫備份",
"tgNotifyBackupDesc": "傳送帶有報告的資料庫備份檔案",
"tgNotifyLogin": "登入通知",
"tgNotifyLoginDesc": "當有人試圖登入你的面板時顯示使用者名稱、IP 地址和時間",
"sessionMaxAge": "會話時長",
"sessionMaxAgeDesc": "保持登入狀態的時長(單位:分鐘)",
"expireTimeDiff": "到期通知閾值",
"expireTimeDiffDesc": "達到此閾值時,將收到有關到期時間的通知(單位:天)",
"trafficDiff": "流量耗盡閾值",
"trafficDiffDesc": "達到此閾值時,將收到有關流量耗盡的通知(單位:GB)",
"tgNotifyCpu": "CPU 負載通知閾值",
"tgNotifyCpuDesc": "CPU 負載超過此閾值時,將收到通知(單位:%)",
"timeZone": "時區",
"timeZoneDesc": "定時任務將按照該時區的時間執行",
"subSettings": "訂閱設定",
"subEnable": "啟用訂閱服務",
"subEnableDesc": "啟用訂閱服務功能",
"subJsonEnable": "獨立啟用/停用 JSON 訂閱端點。",
"subJsonEnableTitle": "JSON 訂閱",
"subClashEnableTitle": "Clash / Mihomo 訂閱",
"subFormatsTipTitle": "特定格式的訂閱設定",
"subFormatsTipDesc": "分別設定 JSON 和 Clash / Mihomo 的 URL 路徑、反向代理 URL 與用戶端自動識別。",
"subFormatsTipAction": "開啟訂閱格式",
"subJsonAutoDetect": "自動識別 Xray JSON 用戶端",
"subJsonAutoDetectDesc": "啟用後,使用標準訂閱 URL 的已識別相容用戶端將自動取得 Xray JSON 設定陣列。其他用戶端繼續取得原始/Base64 回應。需要啟用 JSON 訂閱並重新啟動面板才能生效。",
"subJsonAlwaysArray": "始終回傳 JSON 陣列",
"subJsonAlwaysArrayDesc": "即使只有一個設定,也將明確 JSON 訂閱端點回傳為陣列,以符合 XTLS 訂閱標準。自動識別的 JSON 回應始終使用陣列。停用時保留舊版單一物件回應。",
"subJsonUserAgentRegex": "Xray JSON User-Agent 正規表示式",
"subJsonUserAgentRegexDesc": "用於與用戶端 User-Agent 進行比對,以便在標準訂閱 URL 上自動選擇 Xray JSON 格式的 Go RE2 正規表示式。預設留空,因此在為要服務的用戶端設定規則之前,自動辨識會保持關閉。其他用戶端繼續取得原始/Base64 回應。變更後請重新啟動面板。",
"subClashAutoDetect": "自動識別 Clash/Mihomo 用戶端",
"subClashAutoDetectDesc": "啟用後,使用標準訂閱 URL 的已識別 Clash/Mihomo 用戶端將自動取得 Clash YAML。瀏覽器仍會顯示訂閱頁面,其他用戶端繼續取得原始/Base64 回應,獨立的 JSON 和 Clash URL 仍可使用。需要啟用 Clash/Mihomo 訂閱並重新啟動面板才能生效。",
"subClashUserAgentRegex": "Clash/Mihomo User-Agent 正規表示式",
"subClashUserAgentRegexDesc": "用於與用戶端 User-Agent 進行比對,以便在標準訂閱 URL 上識別 Clash/Mihomo 用戶端的 Go RE2 正規表示式。留空則使用預設規則。變更後請重新啟動面板。",
"subTitle": "訂閱標題",
"subTitleDesc": "在VPN客戶端中顯示的標題",
"subSupportUrl": "支援連結",
"subSupportUrlDesc": "VPN 用戶端中顯示的技術支援連結",
"subProfileUrl": "個人資料連結",
"subProfileUrlDesc": "VPN 用戶端中顯示的網站連結",
"subAnnounce": "公告",
"subAnnounceDesc": "VPN 用戶端中顯示的公告文字",
"subThemeDir": "訂閱主題目錄",
"subThemeDirDesc": "包含自訂訂閱頁面範本 (index.html/sub.html) 的資料夾的絕對路徑(例如 /etc/3x-ui/sub_templates/my-theme/)。留空則使用預設頁面。",
"subThemeDirDocs": "範本指南 ↗",
"subEnableRouting": "啟用路由",
"subEnableRoutingDesc": "在 VPN 用戶端中啟用路由的全域設定。(僅限 Happ)",
"subRoutingRules": "路由規則",
"subRoutingRulesDesc": "VPN 用戶端的全域路由規則。(僅限 Happ)",
"subHideSettings": "隱藏伺服器設定",
"subHideSettingsDesc": "在 VPN 用戶端中隱藏查看和編輯伺服器配置的功能。(僅限 Happ)",
"subIncyEnableRouting": "啟用路由",
"subIncyEnableRoutingDesc": "為 Incy 用戶端將路由設定檔注入訂閱內容中。(僅限 Incy)",
"subIncyRoutingRules": "路由規則",
"subIncyRoutingRulesDesc": "加入訂閱內容的 Incy 路由深層連結,例如 incy://routing/onadd/<base64>。(僅限 Incy",
"subClashEnableRouting": "啟用路由",
"subClashEnableRoutingDesc": "在產生的 YAML 訂閱中包含 Clash/Mihomo 全域路由規則。",
"subClashRoutingRules": "全域路由規則",
"subClashRoutingRulesDesc": "加入到每個 YAML 訂閱開頭、MATCH,PROXY 之前的 Clash/Mihomo 規則。",
"subListen": "監聽 IP",
"subListenDesc": "訂閱服務監聽的 IP 地址(留空表示監聽所有 IP)",
"subPort": "監聽埠",
"subPortDesc": "訂閱服務監聽的埠號(必須是未使用的埠)。當下方「反向代理 URI」為空時,也會用來產生面板中顯示的訂閱連結/QR 碼——如果訂閱是透過反向代理的其他埠存取的,請改為設定「反向代理 URI」。",
"subCertPath": "公鑰路徑",
"subCertPathDesc": "訂閱服務使用的公鑰檔案路徑(以 '/' 開頭)",
"subKeyPath": "私鑰路徑",
"subKeyPathDesc": "訂閱服務使用的私鑰檔案路徑(以 '/' 開頭)",
"subPath": "URI 路徑",
"subPathDesc": "訂閱服務使用的 URI 路徑(以 '/' 開頭,以 '/' 結尾)",
"subDomain": "監聽域名",
"subDomainDesc": "訂閱服務監聽的域名(留空表示監聽所有域名和 IP)。當「反向代理 URI」為空時,也會作為顯示的訂閱連結的備援域名——如果面板和訂閱透過不同的域名存取(例如位於反向代理之後),請設定「反向代理 URI」。",
"subUpdates": "更新間隔",
"subUpdatesDesc": "客戶端應用中訂閱 URL 的更新間隔(單位:小時)",
"subEncrypt": "編碼",
"subEncryptDesc": "訂閱服務返回的內容將採用 Base64 編碼",
"subURI": "反向代理 URI",
"subURIDesc": "用於訂閱連結和 QR 碼的完整基礎 URL(scheme://域名[:埠]/路徑/),會取代監聽域名/監聽埠使用。當訂閱透過反向代理存取,或使用與上面不同的域名/埠存取時,請設定此項。",
"externalTrafficInformEnable": "外部交通通知",
"externalTrafficInformEnableDesc": "每次流量更新時通知外部 API。",
"externalTrafficInformURI": "外部流量通知 URI",
"externalTrafficInformURIDesc": "流量更新將會傳送到此 URI",
"restartXrayOnClientDisable": "用戶自動停用後重新啟動 Xray",
"restartXrayOnClientDisableDesc": "當用戶因到期或流量上限而被自動停用時,重新啟動 Xray。",
"fragment": "分片",
"fragmentDesc": "啟用 TLS hello 資料包分片",
"fragmentSett": "設定",
"noisesDesc": "啟用 Noises.",
"noisesSett": "Noises 設定",
"trustedProxyCidrs": "信任代理 CIDR",
"trustedProxyCidrsDesc": "允許設定轉發 host、proto 與客戶端 IP 標頭的 IP/CIDR(逗號分隔)。",
"ldap": {
"enable": "啟用 LDAP 同步",
"host": "LDAP host",
"port": "LDAP 連接埠",
"useTls": "使用 TLS (LDAPS)",
"skipTlsVerify": "略過 TLS 憑證驗證",
"skipTlsVerifyDesc": "不安全 — 停用伺服器憑證驗證。僅用於內部/不受信任的 CA。",
"bindDn": "Bind DN",
"passwordConfigured": "已設定;留空以保留目前密碼。",
"passwordUnconfigured": "未設定。",
"passwordPlaceholder": "已設定 - 輸入新值以取代",
"baseDn": "Base DN",
"userFilter": "使用者篩選",
"userAttr": "使用者屬性 (username/email)",
"vlessField": "VLESS flag 屬性",
"flagField": "通用 flag 屬性 (選用)",
"flagFieldDesc": "若設定,將覆寫 VLESS flag — 如 shadowInactive。",
"truthyValues": "Truthy 值",
"truthyValuesDesc": "以逗號分隔;預設: true,1,yes,on",
"invertFlag": "反轉 flag",
"invertFlagDesc": "當屬性表示已停用時啟用 (如 shadowInactive)。",
"syncSchedule": "同步排程",
"syncScheduleDesc": "類 cron 字串,如 @every 1m",
"inboundTags": "入站標籤",
"inboundTagsDesc": "允許 LDAP 同步自動建立或刪除客戶端的入站。",
"noInbounds": "未找到入站。請先在「入站」中建立。",
"autoCreate": "自動建立客戶端",
"autoDelete": "自動刪除客戶端",
"defaultTotalGb": "預設總流量 (GB)",
"defaultExpiryDays": "預設到期 (天)",
"defaultIpLimit": "預設 IP 限制"
},
"subFormats": {
"finalMask": "Final Mask",
"finalMaskDesc": "將 Xray finalmask TCP/UDP 遮罩和 QUIC 參數注入每個產生的 Xray JSON 設定。需要支援 Xray JSON 訂閱的用戶端應用程式和較新的 Xray 核心。",
"packets": "封包",
"length": "長度",
"interval": "間隔",
"maxSplit": "最大分割",
"noises": "雜訊",
"noiseItem": "雜訊 №{n}",
"type": "類型",
"packet": "封包",
"delayMs": "延遲 (ms)",
"applyTo": "套用至",
"addNoise": "+ 雜訊",
"concurrency": "並發",
"xudpConcurrency": "xudp 並發",
"xudpUdp443": "xudp UDP 443"
},
"mux": "Mux",
"muxDesc": "在已建立的資料流內傳輸多個獨立的資料流",
"muxSett": "複用器設定",
"direct": "直接連線",
"directDesc": "直接與特定國家的域或IP範圍建立連線",
"notifications": "通知",
"certs": "證書",
"externalTraffic": "外部流量",
"dateAndTime": "日期和時間",
"proxyAndServer": "代理和伺服器",
"intervals": "間隔",
"information": "資訊",
"profile": "資料",
"language": "語言",
"telegramBotLanguage": "Telegram 機器人語言",
"security": {
"admin": "管理員憑證",
"twoFactor": "雙重驗證",
"twoFactorEnable": "啟用2FA",
"twoFactorEnableDesc": "增加額外的驗證層以提高安全性。",
"twoFactorModalSetTitle": "啟用雙重認證",
"twoFactorModalDeleteTitle": "停用雙重認證",
"twoFactorModalSteps": "要設定雙重認證,請執行以下步驟:",
"twoFactorModalFirstStep": "1. 在認證應用程式中掃描此QR碼,或複製QR碼附近的令牌並貼到應用程式中",
"twoFactorModalSecondStep": "2. 輸入應用程式中的驗證碼",
"twoFactorModalRemoveStep": "輸入應用程式中的驗證碼以移除雙重認證。",
"twoFactorModalChangeCredentialsTitle": "更改憑證",
"twoFactorModalChangeCredentialsStep": "輸入應用程式中的代碼以更改管理員憑證。",
"twoFactorModalSetSuccess": "雙重身份驗證已成功建立",
"twoFactorModalDeleteSuccess": "雙重身份驗證已成功刪除",
"twoFactorModalError": "驗證碼錯誤",
"show": "顯示",
"hide": "隱藏",
"apiTokenNew": "新增令牌",
"apiTokenName": "名稱",
"apiTokenNamePlaceholder": "例如 central-panel-a",
"apiTokenNameRequired": "名稱必填",
"apiTokenEmpty": "尚無令牌 — 建立一個以認證機器人或遠端面板。",
"apiTokenDeleteWarning": "使用此令牌的任何呼叫方將立即無法認證。",
"apiTokenCreatedTitle": "權杖已建立",
"apiTokenCreatedNotice": "請立即複製此權杖。基於安全考量,它不會以可讀形式儲存,也不會再次顯示。"
},
"toasts": {
"modifySettings": "參數已更改。",
"getSettings": "取得參數時發生錯誤",
"modifyUserError": "變更管理員憑證時發生錯誤。",
"modifyUser": "您已成功變更管理員憑證。",
"originalUserPassIncorrect": "原使用者名稱或原密碼錯誤",
"userPassMustBeNotEmpty": "新使用者名稱和新密碼不能為空",
"getOutboundTrafficError": "取得出站流量錯誤",
"resetOutboundTrafficError": "重設出站流量錯誤"
},
"smtpSettings": "SMTP 設定",
"smtpEnable": "啟用電子郵件通知",
"smtpEnableDesc": "透過 SMTP 啟用電子郵件通知",
"smtpHost": "SMTP 主機",
"smtpHostDesc": "SMTP 伺服器主機名稱(例如 smtp.gmail.com",
"smtpPort": "SMTP 連接埠",
"smtpPortDesc": "SMTP 伺服器連接埠(預設:587",
"smtpUsername": "SMTP 使用者名稱",
"smtpUsernameDesc": "SMTP 驗證使用者名稱",
"smtpFrom": "寄件者位址 (From)",
"smtpFromDesc": "郵件 From 標頭使用的位址。留空則使用使用者名稱。",
"smtpFromName": "寄件者名稱 (From)",
"smtpFromNameDesc": "From 標頭中顯示在位址前的可選顯示名稱。",
"smtpPassword": "SMTP 密碼",
"smtpPasswordDesc": "SMTP 驗證密碼",
"smtpTo": "收件人",
"smtpToDesc": "以逗號分隔的收件人電子郵件地址",
"emailSettings": "電子郵件",
"emailNotifications": "通知",
"smtpEventBusNotify": "電子郵件事件通知",
"smtpEventBusNotifyDesc": "選擇觸發電子郵件通知的事件",
"tgEventBusNotify": "Telegram 事件通知",
"tgEventBusNotifyDesc": "選擇觸發 Telegram 通知的事件",
"testSmtp": "傳送測試郵件",
"testTgBot": "傳送測試訊息",
"eventGroupOutbound": "出站",
"eventGroupXray": "Xray 核心",
"eventGroupSystem": "系統",
"eventGroupSecurity": "安全性",
"eventGroupNode": "節點",
"eventOutboundDown": "中斷",
"eventOutboundUp": "恢復",
"eventXrayCrash": "當機",
"eventNodeDown": "離線",
"eventNodeUp": "上線",
"eventCPUHigh": "CPU 偏高(%",
"requestFailed": "請求失敗",
"smtpEncryption": "加密",
"smtpEncryptionDesc": "SMTP 連線加密方式",
"smtpEncryptionNone": "無(純文字)",
"smtpEncryptionStartTLS": "STARTTLS",
"smtpEncryptionTLS": "TLS(隱含)",
"smtpStageConnect": "連線",
"smtpStageAuth": "驗證",
"smtpStageSend": "傳送",
"smtpTestSuccess": "測試郵件已成功傳送",
"smtpHostNotConfigured": "尚未設定 SMTP 主機",
"smtpNoRecipients": "尚未設定收件人",
"smtpFromNotConfigured": "未設定 SMTP 寄件人地址",
"eventLoginAttempt": "登入嘗試",
"telegramTokenConfigured": "已設定;留空以保留目前的權杖。",
"telegramTokenPlaceholder": "已設定 - 輸入新權杖以取代",
"smtpPasswordConfigured": "已設定;留空以保留目前的密碼。",
"smtpPasswordPlaceholder": "已設定 - 輸入新密碼以取代",
"smtpNotInitialized": "SMTP 尚未初始化",
"tgBotNotEnabled": "Telegram 機器人未啟用",
"tgTestFailed": "Telegram 測試失敗",
"tgTestSuccess": "測試訊息已傳送至 Telegram",
"tgBotNotRunning": "Telegram 機器人未執行",
"smtpErrorAuth": "驗證失敗 — 請檢查使用者名稱和密碼",
"smtpErrorStarttls": "伺服器需要 STARTTLS — 請變更加密類型",
"smtpErrorTls": "伺服器需要 TLS — 請變更加密類型",
"smtpErrorRefused": "連線遭拒 — 請檢查主機和連接埠",
"smtpErrorTimeout": "連線逾時 — 無法連線至主機",
"smtpErrorRelay": "伺服器拒絕從此地址傳送",
"smtpErrorEof": "連線已被伺服器關閉",
"smtpErrorUnknown": "SMTP 錯誤:{{ .Error }}",
"eventMemoryHigh": "記憶體使用率高 (%)",
"remarkTemplate": "備註範本",
"remarkTemplateDesc": "設定後,這將取代每個訂閱連結的備註模型——使用變數標記撰寫您自己的格式(使用按鈕來插入)。留空則使用上方的模型。",
"validation": {
"pathLeadingSlash": "路徑必須以 / 開頭"
},
"secretClear": "清除",
"secretClearUndo": "復原清除"
},
"xray": {
"title": "Xray 配置",
"save": "儲存",
"restart": "重新啟動 Xray",
"restartSuccess": "Xray 已成功重新啟動",
"restartOutputTitle": "Xray 重新啟動輸出",
"restartConfirmTitle": "重新啟動 xray?",
"restartConfirmContent": "使用已儲存的設定重新載入 xray 服務。",
"stopSuccess": "Xray 已成功停止",
"restartError": "重新啟動Xray時發生錯誤。",
"stopError": "停止Xray時發生錯誤。",
"importRules": "匯入規則",
"exportRules": "匯出規則",
"importOutbounds": "匯入出站",
"exportOutbounds": "匯出出站",
"importInvalidJson": "無效的 JSON——預期為陣列或含有相符鍵的物件。",
"metricsListen": "Metrics 端點",
"metricsListenDesc": "在此 address:port 上公開 Xray 的 Prometheus 風格 metrics(例如 127.0.0.1:11111)。留空則停用。請綁定 localhost 並以反向代理轉發——此端點未經驗證。",
"metricsTag": "Metrics 標籤",
"basicTemplate": "基礎配置",
"advancedTemplate": "高階配置",
"generalConfigs": "常規配置",
"generalConfigsDesc": "這些選項將決定常規配置",
"logConfigs": "記錄",
"logConfigsDesc": "日誌可能會影響伺服器的效能,建議僅在需要時啟用",
"blockConfigsDesc": "這些選項將阻止使用者連線到特定協議和網站",
"basicRouting": "基本路由",
"blockConnectionsConfigsDesc": "這些選項將根據特定的請求國家阻止流量。",
"directConnectionsConfigsDesc": "直接連線確保特定的流量不會通過其他伺服器路由。",
"blockips": "阻止IP",
"blockdomains": "阻止域名",
"directips": "直接IP",
"directdomains": "直接域名",
"ipv4Routing": "IPv4 路由",
"ipv4RoutingDesc": "此選項將僅通過 IPv4 路由到目標域",
"warpRouting": "WARP 路由",
"warpRoutingDesc": "注意:在使用這些選項之前,請按照面板 GitHub 上的步驟在你的伺服器上以 socks5 代理模式安裝 WARP。WARP 將通過 Cloudflare 伺服器將流量路由到網站。",
"nordRouting": "NordVPN 路由",
"nordRoutingDesc": "這些選項將根據特定目的地通過 NordVPN 路由流量。",
"Template": "高階 Xray 配置模板",
"TemplateDesc": "最終的 Xray 配置檔案將基於此模板生成",
"FreedomStrategy": "Freedom 協議策略",
"FreedomStrategyDesc": "設定 Freedom 協議中網路的輸出策略",
"FreedomHappyEyeballs": "Freedom Happy Eyeballs (IPv4/IPv6)",
"FreedomHappyEyeballsDesc": "為直連(freedom)出站啟用雙協定堆疊撥號——在同時具備 IPv4 與 IPv6 的出口伺服器上很有用。",
"FreedomHappyEyeballsTryDelayDesc": "嘗試備用位址族之前等待的毫秒數。150–250 毫秒是不錯的起點。",
"RoutingStrategy": "配置路由域策略",
"RoutingStrategyDesc": "設定 DNS 解析的整體路由策略",
"outboundTestUrl": "出站測試 URL",
"outboundTestUrlDesc": "測試出站連線時使用的 URL",
"Torrent": "遮蔽 BitTorrent 協議",
"Inbounds": "入站",
"InboundsDesc": "接受來自特定客戶端的流量",
"Outbounds": "出站",
"OutboundSubscriptions": "出站訂閱",
"OutboundSubscriptionsDesc": "從遠端訂閱 URLvmess/vless/trojan/ss/...)匯入出站。標籤會保持穩定,以便在負載均衡與路由規則中使用。系統會自動更新。",
"Balancers": "負載均衡",
"balancerTagRequired": "標籤為必填",
"balancerSelectorRequired": "至少選擇一個出站",
"balancerLive": "目前目標",
"balancerOverride": "強制指定",
"balancerOverridePh": "自動(策略)",
"balancerLiveRefresh": "重新整理負載均衡器即時狀態",
"balancerNotRunning": "此負載均衡器在執行中的 Xray 未啟用 — 請先儲存變更或啟動 Xray",
"routeTester": "路由測試",
"routeTesterDesc": "向執行中的 Xray 查詢某個連線將使用哪個出站。不會傳送真實流量 — 結果直接來自即時路由引擎。",
"routeTesterDest": "網域或 IP",
"routeTesterPort": "埠號",
"routeTesterInbound": "入站",
"routeTesterProtocol": "嗅探協議",
"routeTesterTest": "測試路由",
"routeTesterMatchedOutbound": "匹配出站",
"routeTesterViaBalancer": "經由負載均衡器",
"routeTesterDefaultOutbound": "無路由規則匹配 — 流量將導向預設(第一個)出站。",
"OutboundsDesc": "設定出站流量傳出方式",
"Routings": "路由規則",
"RoutingsDesc": "每條規則的優先順序都很重要",
"completeTemplate": "全部",
"logLevel": "日誌級別",
"logLevelDesc": "錯誤日誌的日誌級別,用於指示需要記錄的資訊",
"accessLog": "訪問日誌",
"accessLogDesc": "訪問日誌的檔案路徑。特殊值 'none' 禁用訪問日誌",
"errorLog": "錯誤日誌",
"errorLogDesc": "錯誤日誌的檔案路徑。特殊值 'none' 禁用錯誤日誌",
"dnsLog": "DNS 日誌",
"dnsLogDesc": "是否啟用 DNS 查詢日誌",
"maskAddress": "隱藏地址",
"maskAddressDesc": "IP 地址掩碼,啟用時會自動替換日誌中出現的 IP 地址。",
"statistics": "統計",
"statsInboundUplink": "入站上傳統計",
"statsInboundUplinkDesc": "啟用所有入站代理的上行流量統計收集。",
"statsInboundDownlink": "入站下載統計",
"statsInboundDownlinkDesc": "啟用所有入站代理的下行流量統計收集。",
"statsOutboundUplink": "出站上傳統計",
"statsOutboundUplinkDesc": "啟用所有出站代理的上行流量統計收集。",
"statsOutboundDownlink": "出站下載統計",
"statsOutboundDownlinkDesc": "啟用所有出站代理的下行流量統計收集。",
"connectionLimits": "連線限制",
"connectionLimitsDesc": "使用者等級 0 的連線層級原則。留空則使用 Xray 的預設值。",
"connIdle": "閒置逾時",
"connIdleDesc": "連線閒置達到該秒數後將被關閉。在繁忙的伺服器上調低此值可更快釋放記憶體和檔案描述符(Xray 預設值:300)。",
"bufferSize": "緩衝區大小",
"bufferSizeDesc": "每個連線的內部緩衝區大小(KB)。在低記憶體伺服器上設為 0 可最大限度減少記憶體佔用(Xray 預設值取決於平台)。",
"bufferSizePlaceholder": "自動",
"seconds": "秒",
"rules": {
"first": "置頂",
"last": "置底",
"up": "向上",
"down": "向下",
"source": "來源",
"dest": "目的地址",
"inbound": "入站",
"outbound": "出站",
"balancer": "負載均衡",
"info": "資訊",
"add": "新增規則",
"edit": "編輯規則",
"useComma": "逗號分隔的項目"
},
"routing": {
"dragToReorder": "拖曳以重新排序"
},
"ruleForm": {
"sourceIps": "來源 IP",
"sourcePort": "來源連接埠",
"vlessRoute": "VLESS 路由",
"attributes": "屬性",
"value": "值",
"user": "使用者",
"inboundTags": "入站標籤",
"outboundTag": "出站標籤",
"balancerTag": "均衡器標籤",
"balancerTagTooltip": "透過其中一個已設定的負載均衡器路由流量"
},
"outboundForm": {
"tagDuplicate": "該標籤已被其他出站使用",
"tagRequired": "標籤為必填",
"tagPlaceholder": "唯一標籤",
"localIpPlaceholder": "本地 IP",
"dialerProxyPlaceholder": "選擇要串接的出站",
"dialerProxyHint": "讓此出站透過另一個出站(以標籤指定)連線,以建立代理鏈。留空則直接連線。",
"targetStrategyHint": "連線前如何解析目標網域:AsIs(預設)原樣傳送,UseIP… 解析失敗時回退,ForceIP… 必須解析成功。",
"addressRequired": "地址為必填",
"portRequired": "連接埠為必填",
"optional": "選用",
"udpOverTcp": "UDP over TCP",
"uotVersion": "UoT 版本",
"inboundTag": "入站標籤",
"inboundTagPlaceholder": "用於路由規則的入站標籤",
"responseType": "回應類型",
"rewriteNetwork": "改寫網路",
"unchanged": "(未變更)",
"unchangedAddress": "(未變更) 如 1.1.1.1",
"rules": "規則",
"ruleN": "規則 {n}",
"action": "動作",
"redirect": "Redirect",
"fragment": "Fragment",
"finalRules": "最終規則",
"overrideXrayPrivateIp": "覆寫 Xray 預設的私有 IP 封鎖",
"blockDelay": "阻斷延遲 (ms)",
"reverseSniffing": "反向 sniffing",
"reserved": "保留",
"minUploadInterval": "最小上傳間隔 (ms)",
"maxUploadSizeBytes": "最大上傳大小 (位元組)",
"uplinkChunkSize": "Uplink chunk 大小",
"noGrpcHeader": "無 gRPC 標頭",
"maxConcurrency": "最大並發",
"maxConnections": "最大連線",
"maxReuseTimes": "最大重用次數",
"maxRequestTimes": "最大請求次數",
"maxReusableSecs": "最大可重用秒數",
"keepAlivePeriod": "keep alive 週期",
"authPassword": "認證密碼",
"visionTestpre": "Vision testpre",
"serverNamePlaceholder": "伺服器名稱",
"verifyPeerName": "驗證 peer 名稱",
"pinnedSha256": "Pinned SHA256",
"shortId": "Short ID",
"sockopts": "Sockopts",
"keepAliveInterval": "keep alive 間隔",
"markFwmark": "Mark (fwmark)",
"interface": "介面",
"ipv6Only": "僅 IPv6",
"acceptProxyProtocol": "接受 proxy protocol",
"proxyProtocol": "Proxy protocol",
"tcpUserTimeoutMs": "TCP user timeout (ms)",
"tcpKeepAliveIdleS": "TCP keep-alive idle (s)"
},
"outbound": {
"addOutbound": "新增出站",
"addReverse": "新增反向",
"editOutbound": "編輯出站",
"editReverse": "編輯反向",
"reverseTag": "反向標籤",
"reverseTagDesc": "VLESS 簡易反向代理出站標籤。留空則停用。設定後,此客戶端的連線可作為反向代理隧道。",
"reverseTagPlaceholder": "出站標籤(留空則停用)",
"tag": "標籤",
"tagDesc": "唯一標籤",
"address": "地址",
"egress": "Egress",
"egressHint": "Run an HTTP test to show egress IP and country.",
"reverse": "反向",
"domain": "網域",
"type": "類型",
"bridge": "Bridge",
"portal": "Portal",
"link": "連結",
"intercon": "互連",
"settings": "設定",
"accountInfo": "帳戶資訊",
"outboundStatus": "出站狀態",
"sendThrough": "傳送通過",
"targetStrategy": "目標解析策略",
"test": "測試",
"testResult": "測試結果",
"testing": "正在測試連接...",
"testSuccess": "測試成功",
"testFailed": "測試失敗",
"testError": "測試出站失敗",
"modeRealDelay": "真實延遲",
"testModeTooltip": "TCP: 快速 dial-only 探測。HTTP: 透過 xray 的完整請求。真實延遲: 含建立連線的總耗時。",
"testAll": "全部測試",
"httpStatus": "HTTP 狀態",
"breakdownConnect": "代理連線",
"breakdownTls": "經由出站的 TLS",
"breakdownTtfb": "首位元組",
"nordvpn": "NordVPN",
"accessToken": "訪問令牌",
"country": "國家",
"server": "伺服器",
"city": "城市",
"allCities": "所有城市",
"privateKey": "私密金鑰",
"load": "負載",
"moveToTop": "移到頂部"
},
"outboundSub": {
"manage": "訂閱",
"title": "出站訂閱",
"remark": "備註(選填)",
"remarkPlaceholder": "例如:香港節點",
"url": "訂閱 URL",
"urlPlaceholder": "https://...base64 連結清單)",
"tagPrefix": "標籤前綴",
"tagPrefixPlaceholder": "hk-",
"interval": "更新間隔",
"hours": "時",
"minutes": "分",
"intervalHint": "預設為 10 分鐘。背景工作會頻繁檢查;每個訂閱只在自己的間隔到期後才重新抓取。",
"enabled": "啟用",
"allowPrivate": "允許私有位址",
"allowPrivateHint": "允許此訂閱的 URL 使用 localhost/區域網路(LAN)/私有 IP。基於安全考量預設為關閉,請僅在來源為受信任的本機時才啟用。",
"prepend": "置於手動出站之前",
"prependHint": "將此訂閱的出站排在您手動設定的出站之前,讓其中之一可成為預設出站。",
"preview": "預覽",
"previewEmpty": "在此 URL 找不到任何出站。",
"refreshAll": "全部重新整理",
"statusOk": "正常",
"toastUpdated": "訂閱已更新",
"addButton": "新增",
"active": "啟用中的訂閱",
"empty": "尚無訂閱。請從上方新增。",
"colRemark": "備註",
"colPrefix": "前綴",
"colInterval": "間隔",
"colLastFetch": "上次抓取",
"colEnabled": "啟用",
"auto": "自動",
"never": "從不",
"yes": "是",
"no": "否",
"refreshNow": "立即重新整理",
"lastError": "上次錯誤",
"deleteConfirm": "確定要刪除此訂閱嗎?",
"restartHint": "新增或重新整理後,請重新啟動 Xray(或等待下次自動重新載入),讓出站生效。",
"fromSubsTitle": "來自出站訂閱(唯讀)",
"fromSubsDesc": "從您啟用中的訂閱匯入。請於上方的「訂閱」面板中管理。",
"toastLoadFailed": "載入訂閱失敗",
"toastUrlRequired": "訂閱 URL 為必填",
"toastAdded": "訂閱已新增",
"toastAddFailed": "新增訂閱失敗",
"toastRefreshed": "已重新整理",
"toastRefreshFailed": "重新整理失敗",
"toastDeleted": "已刪除",
"toastDeleteFailed": "刪除失敗"
},
"tabBalancerSettings": "負載平衡設定",
"tabObservatory": "觀測器",
"observatory": {
"title": "觀測器",
"burstTitle": "突發觀測器",
"autoManaged": "觀測器會根據你的負載平衡器自動管理。可在下方調整探測方式;被觀測的出站會跟隨負載平衡器的選擇器。",
"emptyHint": "目前沒有作用中的連線觀測器。當你建立 Least Ping 或 Least Load 負載平衡器,或帶有 fallback 的 Random / Round-robin 負載平衡器時,會自動新增一個,讓依賴觀測器的負載平衡器能在選擇目標前檢查出站健康狀態。",
"mixedLegacy": "此設定同時包含 Observatory 與 Burst Observatory。Xray 只使用一個全域觀測器,因此不支援這種舊式混合狀態;儲存負載平衡器時會將其正規化為單一觀測器。",
"subjectSelector": "被觀測的出站",
"subjectSelectorDesc": "此觀測器探測的出站標籤。會根據你的負載平衡器自動管理。",
"probeURL": "探測 URL",
"probeURLDesc": "用於量測每個出站而請求的 URL,應回傳 HTTP 204。",
"probeInterval": "探測間隔",
"probeIntervalDesc": "每個出站的探測頻率,例如 30s、1m、2h45m。",
"enableConcurrency": "並行探測",
"enableConcurrencyDesc": "一次探測所有被觀測的出站,而非逐一探測。較快,但在網路上更明顯。",
"destination": "探測目標",
"destinationDesc": "用於量測每個出站而請求的 URL,應回傳 HTTP 204。",
"connectivity": "連線檢查",
"connectivityDesc": "選用的本機網路檢查 URL,僅在目標失敗後才嘗試。留空則略過。",
"interval": "探測間隔",
"intervalDesc": "每個出站兩次探測之間的平均時間,例如 1m。最小 10s。",
"timeout": "探測逾時",
"timeoutDesc": "判定探測失敗前的等待時間,例如 5s。",
"sampling": "取樣數量",
"samplingDesc": "為每個出站評分而保留的最近探測結果數量。",
"httpMethod": "HTTP 方法",
"httpMethodDesc": "探測所用的 HTTP 方法。",
"deleteAlsoObservatory": "這是最後一個使用 Observatory 的負載平衡器,因此它也會一併被移除。",
"deleteAlsoBurst": "這是最後一個使用 Burst Observatory 的負載平衡器,因此它也會一併被移除。"
},
"refCleanup": {
"header": "刪除此項也會更新你的路由:",
"ruleRemoved": "規則 {label} — 已移除(沒有剩餘出口)",
"ruleModified": "規則 {label} — 已保留(現使用 {keeps}",
"balancerRemoved": "負載平衡器 {tag} — 已移除(沒有剩餘目標)"
},
"balancer": {
"addBalancer": "新增負載均衡",
"editBalancer": "編輯負載均衡",
"balancerStrategy": "策略",
"balancerSelectors": "選擇器",
"tag": "標籤",
"tagDesc": "唯一標籤",
"tagDuplicate": "該標籤已被其他均衡器使用",
"tagPlaceholder": "唯一均衡器標籤",
"selector": "選擇器",
"fallback": "Fallback",
"cycleTooltip": "循環: {path} → (回到 {start})",
"expected": "期望",
"expectedPlaceholder": "最佳節點數",
"maxRtt": "最大 RTT",
"tolerance": "容差",
"baselines": "Baselines",
"costs": "Costs",
"balancerDesc": "無法同時使用 balancerTag 和 outboundTag。如果同時使用,則只有 outboundTag 會生效。",
"costMatch": "標籤比對模式",
"costValue": "權重",
"costRegexp": "正規表示式比對",
"balancerDeleteInUse": "無法刪除此負載平衡器 — 它被用作以下負載平衡器的備用:{names}",
"balancerFallbackCycle": "無法將此負載平衡器設定為備用 — 這會建立循環依賴。",
"balancerFallbackInfo": "流量將透過以下路徑路由:負載平衡器 → Loopback → 伺服器 → 目標負載平衡器 → 出站連線。這會增加一個經過伺服器的額外跳轉,可能會引入輕微延遲。",
"fallbackBalancerHint": "選擇另一個負載平衡器作為備用",
"reservedPrefix": "_bl_ 前綴保留給內部負載均衡器迴圈物件"
},
"wireguard": {
"secretKey": "金鑰",
"publicKey": "公鑰",
"allowedIPs": "允許的 IP",
"endpoint": "端點",
"psk": "共享金鑰",
"domainStrategy": "域策略"
},
"tun": {
"nameDesc": "TUN 介面的名稱。預設值為 'xray0'",
"mtuDesc": "最大傳輸單元。資料包的最大大小。預設值為 1500",
"userLevel": "用戶級別",
"userLevelDesc": "通過此入站的所有連接都將使用此用戶級別。預設值為 0"
},
"nord": {
"accessToken": "Access token",
"privateKey": "私鑰",
"noServers": "未找到選定國家/地區的伺服器",
"noPublicKey": "選定的伺服器未公布 NordLynx 公鑰。",
"outboundAdded": "NordVPN 出站已新增",
"outboundUpdated": "NordVPN 出站已更新"
},
"warp": {
"changeIp": "更換 IP",
"changeIpSuccess": "WARP IP 更換成功!",
"autoUpdateIp": "自動更新 IP 位址",
"intervalDays": "間隔(天)",
"intervalDesc": "設為 0 停用。自動更換 IP 位址。",
"licenseError": "設定 WARP 授權失敗。",
"fetchFirst": "請先取得 WARP 設定。",
"createAccount": "建立 WARP 帳號",
"accessToken": "Access token",
"deviceId": "裝置 ID",
"licenseKey": "授權金鑰",
"privateKey": "私鑰",
"deleteAccount": "刪除帳號",
"settings": "設定",
"licenseKeyLabel": "WARP / WARP+ 授權金鑰",
"key": "金鑰",
"keyPlaceholder": "26 位 WARP+ 金鑰",
"accountInfo": "帳號資訊",
"deviceName": "裝置名稱",
"deviceModel": "裝置型號",
"deviceEnabled": "裝置已啟用",
"accountType": "帳號類型",
"role": "角色",
"warpPlusData": "WARP+ 資料",
"quota": "配額",
"usage": "使用",
"addOutbound": "新增出站"
},
"dns": {
"enable": "啟用 DNS",
"enableDesc": "啟用內建 DNS 伺服器",
"tag": "DNS 入站標籤",
"tagDesc": "此標籤將在路由規則中可用作入站標籤",
"clientIp": "客戶端IP",
"clientIpDesc": "用於在DNS查詢期間通知伺服器指定的IP位置",
"disableCache": "禁用快取",
"disableCacheDesc": "禁用DNS快取",
"disableFallback": "禁用回退",
"disableFallbackDesc": "禁用回退DNS查詢",
"disableFallbackIfMatch": "匹配時禁用回退",
"disableFallbackIfMatchDesc": "當DNS伺服器的匹配域名列表命中時,禁用回退DNS查詢",
"enableParallelQuery": "啟用並行查詢",
"enableParallelQueryDesc": "啟用並行DNS查詢到多個伺服器以實現更快的解析",
"strategy": "查詢策略",
"strategyDesc": "解析域名的總體策略",
"add": "新增伺服器",
"edit": "編輯伺服器",
"domains": "網域",
"expectIPs": "預期 IP",
"unexpectIPs": "意外IP",
"useSystemHosts": "使用系統Hosts",
"useSystemHostsDesc": "使用已安裝系統的hosts檔案",
"serveStale": "提供過期結果",
"serveStaleDesc": "在背景重新整理時傳回過期的快取結果",
"serveExpiredTTL": "過期TTL",
"serveExpiredTTLDesc": "過期快取項目的有效期(秒);0 = 永不過期",
"timeoutMs": "逾時 (毫秒)",
"skipFallback": "跳過回退",
"finalQuery": "最終查詢",
"hosts": "Hosts",
"hostsAdd": "新增 Host",
"hostsEmpty": "未定義任何 Host",
"hostsDomain": "網域 (例如 domain:example.com)",
"hostsValues": "IP 或網域 — 輸入後按 Enter",
"usePreset": "使用範本",
"dnsPresetTitle": "DNS範本",
"dnsPresetFamily": "家庭",
"clearAll": "全部刪除",
"clearAllTitle": "刪除所有 DNS 伺服器?",
"clearAllConfirm": "此操作將從清單中刪除所有 DNS 伺服器,無法復原。",
"dnsLeakWarning": "DNS 可能透過 localhost、明文 UDP/TCP、本機模式 DoH/DoQ、回退查詢或 EDNS client IP 洩漏。重視隱私時請使用經路由的 DoH、在 hosts 固定解析器,並停用回退。"
},
"fakedns": {
"add": "新增假 DNS",
"edit": "編輯假 DNS",
"ipPool": "IP 池子網",
"poolSize": "池大小"
},
"defaultOutbound": "預設出站",
"defaultOutboundDesc": "未符合任何路由規則的流量走此出站(清單中的第一個出站)。"
},
"hosts": {
"addHost": "新增 Host",
"editHost": "編輯 Host",
"selectInbound": "選擇一個入站",
"selectedCount": "已選 {count} 項",
"summary": {
"total": "總數",
"enabled": "已啟用",
"disabled": "已停用"
},
"moveUp": "上移",
"moveDown": "下移",
"bulkEnable": "啟用",
"bulkDisable": "停用",
"bulkDelete": "刪除",
"bulkDeleteConfirm": "刪除所選的 {count} 個 Host",
"deleteConfirmTitle": "刪除 Host「{name}」?",
"sections": {
"basic": "基本",
"security": "安全",
"advanced": "進階",
"general": "一般",
"clash": "Clash (mihomo)"
},
"fields": {
"remark": "備註",
"serverDescription": "描述",
"inbound": "入站",
"address": "地址",
"port": "連接埠",
"endpoint": "端點",
"enable": "啟用",
"actions": "操作",
"security": "安全",
"sni": "SNI",
"overrideSniFromAddress": "使用地址作為 SNI",
"keepSniBlank": "保持 SNI 留空",
"hostHeader": "Host 標頭",
"path": "路徑",
"alpn": "ALPN",
"fingerprint": "指紋",
"pins": "釘選憑證 SHA-256",
"verifyPeerCertByName": "依名稱驗證對端憑證",
"allowInsecure": "允許不安全連線",
"echConfigList": "ECH 設定清單",
"muxParams": "Mux",
"sockoptParams": "Sockopt",
"finalMask": "Final Mask",
"vlessRoute": "VLESS 路由",
"mihomoIpVersion": "IP 版本",
"mihomoX25519": "Mihomo X25519",
"shuffleHost": "隨機排序 Host",
"tags": "標籤",
"nodeGuids": "節點",
"excludeFromSubTypes": "從格式中排除",
"inheritAddress": "繼承地址"
},
"hints": {
"address": "留空以繼承入站本身的地址。",
"port": "0 表示繼承入站的連接埠。",
"tags": "對終端使用者不可見;僅隨 RAW 訂閱傳送。只能使用大寫字母、數字、_ 和 :。",
"nodeGuids": "選擇由此 Host 解析而來的節點。僅為視覺上的指派。",
"serverDescription": "顯示於備註下方的選填註記。",
"allowInsecure": "略過 TLS 憑證驗證(allowInsecure / skip-cert-verify)。",
"vlessRoute": "嵌入 UUID 的單一 VLESS 路由值(0-65535),例如 443。留空表示無。",
"remark": "此 Host 的純文字標籤。僅當入站本身沒有備註時,才作為配置名稱顯示。"
},
"remarkVars": {
"title": "範本變數",
"intro": "點擊變數以加入。產生訂閱時會針對每個客戶端進行替換。",
"preview": "預覽",
"groups": {
"client": "客戶端",
"traffic": "流量",
"time": "時間與狀態",
"connection": "連線"
},
"descEMAIL": "客戶端電子郵件",
"descINBOUND": "入站本身的備註(配置名稱)",
"descHOST": "Host 備註",
"descID": "客戶端 UUID",
"descSHORT_ID": "UUID 的前 8 個字元",
"descTELEGRAM_ID": "客戶端的 Telegram ID(未設定則為空)",
"descSUB_ID": "訂閱 ID",
"descCOMMENT": "客戶端備註",
"descTRAFFIC_USED": "已用流量(易讀格式)",
"descTRAFFIC_LEFT": "剩餘流量(無限制時隱藏)",
"descTRAFFIC_TOTAL": "總流量(無限制時隱藏)",
"descTRAFFIC_USED_BYTES": "已用流量(位元組)",
"descTRAFFIC_LEFT_BYTES": "剩餘流量(位元組)",
"descTRAFFIC_TOTAL_BYTES": "總流量(位元組)",
"descUP": "上傳流量",
"descDOWN": "下載流量",
"descSTATUS": "active / expired / disabled / depleted",
"descSTATUS_EMOJI": "以表情符號表示的狀態(✅ ⏳ 🚫)",
"descDAYS_LEFT": "距到期天數(無限制時隱藏)",
"descTIME_LEFT": "剩餘時間(例如 12d 4h 30m",
"descUSAGE_PERCENTAGE": "已用流量百分比(無限制時隱藏)",
"descEXPIRE_DATE": "到期日期(YYYY-MM-DD",
"descJALALI_EXPIRE_DATE": "Jalali 曆的到期日期(YYYY/MM/DD",
"descEXPIRE_UNIX": "到期時間(Unix 時間戳記,秒)",
"descCREATED_UNIX": "建立時間(Unix 時間戳記,秒)",
"descRESET_DAYS": "流量重置週期(天)",
"descPROTOCOL": "入站協定(VLESS、VMess、Trojan…)",
"descTRANSPORT": "傳輸網路(tcp、ws、grpc…)",
"descSECURITY": "傳輸安全(TLS、REALITY、NONE"
},
"toasts": {
"list": "載入 Host 失敗",
"obtain": "載入 Host 失敗",
"add": "新增 Host",
"update": "更新 Host",
"delete": "刪除 Host",
"badTag": "無效的標籤",
"badVlessRoute": "請輸入 0 到 65535 之間的單一數字"
}
}
},
"tgbot": {
"keyboardClosed": "❌ 自定義鍵盤已關閉!",
"noResult": "❗ 沒有結果!",
"noQuery": "❌ 未找到查詢!請再次使用該命令!",
"wentWrong": "❌ 出了點問題!",
"noIpRecord": "❗ 沒有IP記錄!",
"noInbounds": "❗ 未找到入站!",
"unlimited": "♾ 無限(重置)",
"add": "添加",
"month": "月",
"months": "月",
"day": "天",
"days": "天",
"hours": "小時",
"minutes": "分鐘",
"unknown": "未知",
"inbounds": "入站",
"clients": "客戶端",
"offline": "🔴 離線",
"online": "🟢 上線",
"commands": {
"unknown": "❗ 未知命令",
"pleaseChoose": "👇 請選擇:\r\n",
"help": "🤖 歡迎使用本機器人!它旨在為您提供來自伺服器的特定資料,並允許您進行必要的修改。\r\n\r\n",
"start": "👋 你好,<i>{{ .Firstname }}</i>。\r\n",
"welcome": "🤖 歡迎來到 <b>{{ .Hostname }}</b> 管理機器人。\r\n",
"status": "✅ 機器人正常執行!",
"usage": "❗ 請輸入要搜尋的文字!",
"getID": "🆔 您的 ID 為:<code>{{ .ID }}</code>",
"helpAdminCommands": "要重新啟動 Xray Core\r\n<code>/restart</code>\r\n\r\n要搜尋客戶電子郵件:\r\n<code>/usage [電子郵件]</code>\r\n\r\n要搜尋入站(帶有客戶統計資料):\r\n<code>/inbound [備註]</code>\r\n\r\nTelegram聊天ID\r\n<code>/id</code>",
"helpClientCommands": "要搜尋統計資料,請使用以下命令:\r\n<code>/usage [電子郵件]</code>\r\n\r\nTelegram聊天ID\r\n<code>/id</code>",
"restartUsage": "\r\n\r\n<code>/restart</code>",
"restartSuccess": "✅ 操作成功!",
"restartFailed": "❗ 操作錯誤。\r\n\r\n<code>錯誤: {{ .Error }}</code>.",
"xrayNotRunning": "❗ Xray Core 未運行。",
"startDesc": "顯示主選單",
"helpDesc": "機器人幫助",
"statusDesc": "檢查機器人狀態",
"idDesc": "顯示您的 Telegram ID",
"usageDesc": "查看客戶端用量:/usage 郵箱",
"inboundDesc": "搜尋入站:/inbound 備註(管理員)",
"restartDesc": "重啟 Xray 核心(管理員)",
"clearallDesc": "重置所有客戶端流量(管理員)"
},
"messages": {
"cpuThreshold": "CPU 使用率為 {{ .Percent }}%,超過閾值 {{ .Threshold }}%",
"selectUserFailed": "❌ 使用者選擇錯誤!",
"userSaved": "✅ 電報使用者已儲存。",
"loginSuccess": "✅ 成功登入到面板。\r\n",
"loginFailed": "❗️ 面板登入失敗。\r\n",
"2faFailed": "2FA 失敗",
"report": "🕰 定時報告:{{ .RunTime }}\r\n",
"datetime": "⏰ 日期時間:{{ .DateTime }}\r\n",
"hostname": "💻 主機: {{ .Hostname }}\r\n",
"version": "🚀 X-UI 版本:{{ .Version }}\r\n",
"xrayVersion": "📡 Xray 版本: {{ .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 }} {{ .Unit }}\r\n",
"serverLoad": "📈 伺服器負載:{{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
"serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
"tcpCount": "🔹 TCP: {{ .Count }}\r\n",
"udpCount": "🔸 UDP: {{ .Count }}\r\n",
"traffic": "🚦 流量:{{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
"xrayStatus": "️ 狀態: {{ .State }}\r\n",
"username": "👤 使用者名稱:{{ .Username }}\r\n",
"reason": "❗️ 原因:{{ .Reason }}\r\n",
"time": "⏰ 時間:{{ .Time }}\r\n",
"inbound": "📍 入站: {{ .Remark }}\r\n",
"port": "🔌 連接埠: {{ .Port }}\r\n",
"expire": "📅 過期日期:{{ .Time }}\r\n",
"expireIn": "📅 剩餘時間:{{ .Time }}\r\n",
"active": "💡 啟用:{{ .Enable }}\r\n",
"enabled": "🚨 已啟用:{{ .Enable }}\r\n",
"online": "🌐 連線狀態:{{ .Status }}\r\n",
"lastOnline": "🔙 上次上線: {{ .Time }}\r\n",
"email": "📧 電子郵件: {{ .Email }}\r\n",
"upload": "🔼 上傳: ↑{{ .Upload }}\r\n",
"download": "🔽 下載: ↓{{ .Download }}\r\n",
"total": "📊 總計: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
"TGUser": "👤 電報使用者:{{ .TelegramID }}\r\n",
"exhaustedMsg": "🚨 耗盡的 {{ .Type }}\r\n",
"exhaustedCount": "🚨 耗盡的 {{ .Type }} 數量:\r\n",
"onlinesCount": "🌐 線上客戶:{{ .Count }}\r\n",
"disabled": "🛑 禁用:{{ .Disabled }}\r\n",
"depleteSoon": "🔜 即將耗盡:{{ .Deplete }}\r\n\r\n",
"backupTime": "🗄 備份時間:{{ .Time }}\r\n",
"refreshedOn": "\r\n📋🔄 重新整理時間:{{ .Time }}\r\n\r\n",
"yes": "✅ 是的",
"no": "❌ 否",
"received_id": "🔑📥 ID 已更新。",
"received_password": "🔑📥 密碼已更新。",
"received_email": "📧📥 電子郵件已更新。",
"received_comment": "💬📥 評論已更新。",
"id_prompt": "🔑 預設 ID: {{ .ClientId }}\n\n請輸入您的 ID。",
"pass_prompt": "🔑 預設密碼: {{ .ClientPassword }}\n\n請輸入您的密碼。",
"email_prompt": "📧 預設電子郵件: {{ .ClientEmail }}\n\n請輸入您的電子郵件。",
"comment_prompt": "💬 預設評論: {{ .ClientComment }}\n\n請輸入您的評論。",
"inbound_client_data_id": "🔄 入站: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 電子郵件: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日: {{ .ClientExp }}\n🌐 IP 限制: {{ .IpLimit }}\n💬 備註: {{ .ClientComment }}\n\n你現在可以將客戶加入入站了!",
"inbound_client_data_pass": "🔄 入站: {{ .InboundRemark }}\n\n🔑 密碼: {{ .ClientPass }}\n📧 電子郵件: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日: {{ .ClientExp }}\n🌐 IP 限制: {{ .IpLimit }}\n💬 備註: {{ .ClientComment }}\n\n你現在可以將客戶加入入站了!",
"cancel": "❌ 程序已取消!\n\n您可以隨時使用 /start 重新開始。 🔄",
"error_add_client": "⚠️ 錯誤:\n\n {{ .error }}",
"using_default_value": "好的,我會使用預設值。 😊",
"incorrect_input": "您的輸入無效。\n短語應連續輸入,不能有空格。\n正確示例: aaaaaa\n錯誤示例: aaa aaa 🚫",
"AreYouSure": "你確定嗎?🤔",
"SuccessResetTraffic": "📧 電子郵件: {{ .ClientEmail }}\n🏁 結果: ✅ 成功",
"FailedResetTraffic": "📧 電子郵件: {{ .ClientEmail }}\n🏁 結果: ❌ 失敗 \n\n🛠️ 錯誤: [ {{ .ErrorMessage }} ]",
"FinishProcess": "🔚 所有客戶的流量重置已完成。",
"eventOutboundDown": "出站 {{ .Tag }} 已中斷",
"eventOutboundUp": "出站 {{ .Tag }} 已恢復",
"eventErrorDetail": "錯誤:{{ .Error }}",
"eventDelayDetail": "延遲:{{ .Delay }} 毫秒",
"eventXrayCrash": "Xray 已當機",
"eventXrayCrashError": "錯誤:{{ .Error }}",
"eventNodeDown": "節點 {{ .Name }} 已離線",
"eventNodeUp": "節點 {{ .Name }} 已上線",
"eventCPUHigh": "CPU 偏高",
"eventCPUHighDetail": "CPU{{ .Detail }}",
"eventLoginFallback": "來自 {{ .Source }} 的登入失敗",
"memoryThreshold": "記憶體使用率 {{ .Percent }}% 超過閾值 {{ .Threshold }}%"
},
"buttons": {
"closeKeyboard": "❌ 關閉鍵盤",
"cancel": "❌ 取消",
"cancelReset": "❌ 取消重置",
"cancelIpLimit": "❌ 取消 IP 限制",
"confirmResetTraffic": "✅ 確認重置流量?",
"confirmClearIps": "✅ 確認清除 IP",
"confirmRemoveTGUser": "✅ 確認移除 Telegram 使用者?",
"confirmToggle": "✅ 確認啟用/禁用使用者?",
"dbBackup": "獲取資料庫備份",
"serverUsage": "伺服器使用情況",
"getInbounds": "獲取入站資訊",
"depleteSoon": "即將耗盡",
"clientUsage": "獲取使用情況",
"onlines": "線上客戶端",
"commands": "命令",
"refresh": "🔄 重新整理",
"clearIPs": "❌ 清除 IP",
"removeTGUser": "❌ 移除 Telegram 使用者",
"selectTGUser": "👤 選擇 Telegram 使用者",
"selectOneTGUser": "👤 選擇一個 Telegram 使用者:",
"resetTraffic": "📈 重置流量",
"resetExpire": "📅 更改到期日期",
"ipLog": "🔢 IP 日誌",
"ipLimit": "🔢 IP 限制",
"setTGUser": "👤 設定 Telegram 使用者",
"toggle": "🔘 啟用/禁用",
"custom": "🔢 自訂",
"confirmNumber": "✅ 確認: {{ .Num }}",
"confirmNumberAdd": "✅ 確認新增:{{ .Num }}",
"limitTraffic": "🚧 流量限制",
"getBanLogs": "禁止日誌",
"allClients": "所有客戶",
"addClient": "新增客戶",
"submitDisable": "以停用方式送出 ☑️",
"submitEnable": "以啟用方式送出 ✅",
"use_default": "🏷️ 使用預設值",
"change_id": "⚙️🔑 ID",
"change_password": "⚙️🔑 密碼",
"change_email": "⚙️📧 電子郵件",
"change_comment": "⚙️💬 評論",
"change_flow": "⚙️🚦 Flow",
"ResetAllTraffics": "重設所有流量",
"SortedTrafficUsageReport": "排序過的流量使用報告"
},
"answers": {
"successfulOperation": "✅ 成功!",
"errorOperation": "❗ 操作錯誤。",
"getInboundsFailed": "❌ 獲取入站資訊失敗。",
"getClientsFailed": "❌ 獲取客戶失敗。",
"canceled": "❌ {{ .Email }}:操作已取消。",
"clientRefreshSuccess": "✅ {{ .Email }}:客戶端重新整理成功。",
"IpRefreshSuccess": "✅ {{ .Email }}IP 重新整理成功。",
"TGIdRefreshSuccess": "✅ {{ .Email }}:客戶端的 Telegram 使用者重新整理成功。",
"resetTrafficSuccess": "✅ {{ .Email }}:流量已重置成功。",
"setTrafficLimitSuccess": "✅ {{ .Email }}: 流量限制儲存成功。",
"expireResetSuccess": "✅ {{ .Email }}:過期天數已重置成功。",
"resetIpSuccess": "✅ {{ .Email }}:成功儲存 IP 限制數量為 {{ .Count }}。",
"clearIpSuccess": "✅ {{ .Email }}IP 已成功清除。",
"getIpLog": "✅ {{ .Email }}:獲取 IP 日誌。",
"getUserInfo": "✅ {{ .Email }}:獲取 Telegram 使用者資訊。",
"removedTGUserSuccess": "✅ {{ .Email }}Telegram 使用者已成功移除。",
"enableSuccess": "✅ {{ .Email }}:已成功啟用。",
"disableSuccess": "✅ {{ .Email }}:已成功禁用。",
"askToAddUserId": "未找到您的配置!\r\n請向管理員詢問,在您的配置中使用您的 Telegram 使用者 ChatID。\r\n\r\n您的使用者 ChatID<code>{{ .TgUserID }}</code>",
"chooseClient": "為入站 {{ .Inbound }} 選擇一個客戶",
"chooseInbound": "選擇一個入站"
}
},
"email": {
"subjectOutboundDown": "出站 {{ .Tag }} 已中斷",
"subjectOutboundUp": "出站 {{ .Tag }} 已恢復",
"subjectXrayCrash": "Xray 已當機",
"subjectCPUHigh": "CPU 偏高",
"subjectLoginSuccess": "登入成功",
"subjectLoginFailed": "登入失敗",
"titleOutboundDown": "出站中斷",
"titleOutboundUp": "出站恢復",
"titleXrayCrash": "Xray 已當機",
"titleCPUHigh": "CPU 偏高",
"titleLoginSuccess": "登入成功",
"titleLoginFailed": "登入失敗",
"labelStatus": "狀態",
"labelOutbound": "出站",
"labelNode": "節點",
"labelError": "錯誤",
"labelDelay": "延遲",
"labelDetail": "詳細資訊",
"labelUsername": "使用者名稱",
"labelIP": "IP",
"labelReason": "原因",
"labelSource": "來源",
"labelTime": "時間",
"statusCrashed": "已當機",
"statusRunning": "執行中",
"statusHigh": "偏高",
"statusSuccess": "成功",
"statusFailed": "失敗",
"statusDown": "中斷",
"statusUp": "恢復"
}
}