3x-ui/web/translation/zh-CN.json
Sanaei edf0f36940
Frontend rewrite: React + TypeScript with AntD v6 (#4498)
* chore(frontend): add react+typescript toolchain alongside vue

Step 0 of the planned vue->react migration. React 19, antd 5, i18next
+ react-i18next, typescript 5, and @vitejs/plugin-react 6 are added as
dev/runtime deps alongside the existing vue stack. Both frameworks
coexist in the build until the last entry flips.

* vite.config.js: react() plugin runs next to vue(); new manualChunks
  for vendor-react / vendor-antd-react / vendor-icons-react /
  vendor-i18next. Existing vue chunks unchanged.
* eslint.config.js: typescript-eslint + eslint-plugin-react-hooks
  rules scoped to *.{ts,tsx}; vue config untouched for *.{js,vue}.
* tsconfig.json: strict, jsx: react-jsx, moduleResolution: bundler,
  allowJs: true (lets .tsx files import the remaining .js modules
  during incremental migration), @/* path alias.
* env.d.ts: Vite client types + window.X_UI_BASE_PATH typing +
  SubPageData shape consumed by the subscription page.

Vite stays pinned at 8.0.13 per the existing project policy. No
existing .vue/.js source files touched in this step.

eslint-plugin-react (not -hooks) is not included because its latest
release does not yet support ESLint 10. react-hooks/purity covers
the safety-critical case; revisit when the plugin updates.

* refactor(frontend): port subpage to react+ts

Step 1 of the planned vue->react migration. The standalone
subscription page (sub/sub.go renders the HTML host; React mounts
into #app) is the first entry off vue.

Introduces two shared pieces both entries (and future ones) will
use:

* src/hooks/useTheme.tsx — React Context + useTheme hook + the
  same buildAntdThemeConfig (dark/ultra-dark token overrides) and
  pauseAnimationsUntilLeave helper the vue version exposes. Same
  localStorage keys (dark-mode, isUltraDarkThemeEnabled) and DOM
  side effects (body.className, html[data-theme]) so the two stay
  in sync across the coexistence period.
* src/i18n/react.ts — i18next + react-i18next loader that reads
  the same web/translation/*.json files via import.meta.glob. The
  vue-i18n setup in src/i18n/index.js is untouched and still serves
  the remaining vue entries.

SubPage.tsx mirrors the vue version's behavior: reads
window.__SUB_PAGE_DATA__ injected by the Go sub server, renders QR
codes / descriptions / Android+iOS deep-link dropdowns, supports
theme cycle and language switch. Uses AntD v5 idioms: Descriptions
items prop, Dropdown menu prop, Layout.Content.

* refactor(frontend): port login to react+ts

Step 2 of the planned vue->react migration. The login entry is the
first to exercise AntD React's Form API (Form + Form.Item with
name/rules + onFinish) and the existing axios/CSRF interceptors
under React.

* LoginPage.tsx: same form fields, conditional 2FA input,
  rotating headline ("Hello" / "Welcome to..."), drifting blob
  background, theme cycle + language popover. Headline transition
  switches from vue's <Transition mode=out-in> to a CSS keyframe
  animation keyed off the visible word.
* entries/login.tsx: setupAxios() + applyDocumentTitle() unchanged
  from the vue entry — both are framework-agnostic in src/utils
  and src/api/axios-init.js.

useTheme hook, ThemeProvider, and i18n/react.ts loader introduced
in step 1 are now shared across two entries; Vite extracts them as
a small chunk in the build output.

* refactor(frontend): port api-docs to react+ts

Step 3 of the planned vue->react migration. The five api-docs files
(ApiDocsPage, CodeBlock, EndpointRow, EndpointSection, plus the
data-only endpoints.js) all move to react+ts.

Also introduces components/AppSidebar.tsx — api-docs is the first
authenticated page to need it. AppSidebar.vue stays in place for the
six remaining vue entries (settings, inbounds, clients, xray, nodes,
index); each gets switched to AppSidebar.tsx as its entry migrates.
After the last entry flips, AppSidebar.vue is deleted.

Notable transformations:

* The scroll observer that highlights the active TOC link is a
  useEffect keyed on sections — re-registers whenever the visible
  set changes (search filter narrows it). Same behaviour as the vue
  watchEffect.
* v-html="safeInlineHtml(...)" becomes
  dangerouslySetInnerHTML={{ __html: safeInlineHtml(...) }}. The
  helper still escapes everything except <code> tags.
* JSON syntax highlighter in CodeBlock is unchanged — pure regex on
  the escaped string, then rendered via dangerouslySetInnerHTML.
* endpoints.js stays as JS (allowJs in tsconfig); only the consumer
  signatures (Endpoint, Section) are typed at the React boundary.
* AppSidebar reuses pauseAnimationsUntilLeave + useTheme from
  step 1. Drawer + Sider keyed off the same localStorage flag
  (isSidebarCollapsed) and DOM theme attributes the vue version
  uses, so the two stay in sync during coexistence.

* refactor(frontend): port nodes to react+ts

Step 4 of the planned vue->react migration. The nodes entry brings in
the largest shared-infrastructure batch so far — every authenticated
react page from here on can lean on these.

New shared pieces (live alongside their .vue counterparts during
coexistence):

* hooks/useMediaQuery.ts — useState + resize listener
* hooks/useWebSocket.ts — wraps WebSocketClient, subscribes on mount
  and unsubscribes on unmount. The underlying client is a single
  module-level instance so multiple components on the same page
  share one socket.
* hooks/useNodes.ts — node list state + CRUD + probe/test, including
  the totals memo (online/offline/avgLatency) used by the summary card.
  applyNodesEvent is the entry point for the heartbeat-pushed list.
* components/CustomStatistic.tsx — thin Statistic wrapper, prefix +
  suffix slots become props.
* components/Sparkline.tsx — the SVG line chart with measured-width
  axis scaling, gradient fill, tooltip overlay, and per-instance
  gradient id from React.useId. ResizeObserver lifecycle is in
  useEffect; the math is unchanged.

Pages:

* NodesPage — wires hooks + WebSocket together, renders summary card
  + NodeList, hosts the form modal. Uses Modal.useModal() for the
  delete confirm so the dialog inherits ConfigProvider theming.
* NodeList — desktop renders a Table with expandable history rows;
  mobile flips to a vertical card list whose actions live in a
  bottom-right Dropdown. The IP-blur eye toggle persists across both.
* NodeFormModal — controlled form (useState object, single setForm
  per change). The reset-on-open effect computes the next state
  once and applies it with eslint-disable to satisfy the new
  react-hooks/set-state-in-effect rule on a legitimate pattern.
* NodeHistoryPanel — polls /panel/api/nodes/history/{id}/{metric}/
  {bucket} every 15s, renders cpu+mem sparklines side-by-side.

* refactor(frontend): port settings to react+ts

Step 5 of the planned vue->react migration. Settings is the first
entry whose state model didn't translate to the Vue-style "parent
passes a reactive object, children mutate it in place" pattern, so
the React port flips it to lifted state + a typed updateSetting
patch function.

* models/setting.ts — typed AllSetting class with the same field
  defaults and equals() behavior the vue version had. The .js
  twin is deleted; nothing else imported it.
* hooks/useAllSetting.ts — owns allSetting + oldAllSetting state,
  exposes updateSetting(patch), saveDisabled is derived via useMemo
  off equals() (no more 1Hz dirty-check timer).
* components/SettingListItem.tsx — children-based wrapper instead
  of named slots. The vue twin stays alive because xray (BasicsTab,
  DnsTab) still imports it; deleted when xray migrates.

The five tab components and the TwoFactorModal each accept
{ allSetting, updateSetting } and render with AntD v5's Collapse
items[] API. Every v-model:value="x" became
value={...} onChange={(e) => updateSetting({ key: e.target.value })}
or onChange={(v) => updateSetting({ key: v })} for non-input
controls.

SubscriptionFormatsTab is the trickiest — fragment / noises[] /
mux / direct routing rules are stored as JSON-encoded strings on
the wire. Parsing them once via useMemo per field, mutating the
parsed object on edit, and stringifying back into the patch keeps
the round-trip identical to the vue version.

SettingsPage hosts the tab navigation (with hash sync), the
save / restart action bar, the security-warnings alert banner,
and the restart flow that rebuilds the panel URL after the new
host/port/cert settings take effect.

* refactor(frontend): port clients to react+ts

Step 6 of the planned vue->react migration. Clients is the biggest
data-CRUD page in the panel (1.1k-line ClientsPage, 4 modals, full
table + mobile card list, WebSocket-driven realtime traffic + online
updates).

New shared infra (lives alongside vue twins until inbounds migrates):

* hooks/useClients.ts — clients + inbounds list, CRUD + bulk delete +
  attach/detach + traffic reset, with WebSocket event handlers
  (traffic, client_stats, invalidate) and a small debounced refresh
  on the invalidate event. State managed via setState; the live
  client_stats event merges traffic snapshots row-by-row through a
  ref to avoid stale closure issues.
* hooks/useDatepicker.ts — singleton "gregorian"/"jalalian" cache
  with subscribe/notify so multiple components can read the panel's
  Calendar Type without re-fetching. Mirrors useDatepicker.js.
* components/DateTimePicker.tsx — AntD DatePicker wrapper.
  vue3-persian-datetime-picker has no React port; the Jalali UI
  calendar is deferred (read-only Jalali display via IntlUtil
  formatDate still works). The vue twin stays for inbounds.
* pages/inbounds/QrPanel.tsx — copy/download/copy-as-png QR helper
  shared between clients (qr modal) and inbounds (still on vue).
  Vue twin stays alive at QrPanel.vue.
* models/inbound.ts — slim port: only the TLS_FLOW_CONTROL constant
  the clients form needs. The full inbound model stays as
  inbound.js for now; inbounds will pull it in as inbound.ts.

The clients page itself uses Modal.useModal() for all confirm
dialogs (delete, bulk-delete, reset-traffic, delDepleted, reset-all)
so the dialogs render themed. Filter state persists to
localStorage under clientsFilterState. Sort + pagination state is
local; pageSize seeds from /panel/setting/defaultSettings.

The four modals share a controlled "open/onOpenChange" pattern
that replaces vue's v-model:open. ClientFormModal computes
attach/detach diffs from the inbound multi-select on submit; the
parent's onSave callback routes them through useClients's attach()/
detach() after the main update succeeds.

ESLint config: turned off four react-hooks v7 rules
(react-compiler, preserve-manual-memoization, set-state-in-effect,
purity). They're all React-Compiler-driven informational rules; we
don't run the compiler and the patterns they flag (initial-fetch
useEffect, derived computations using Date.now, inline arrow event
handlers) are all idiomatic React. Disabling globally instead of
per-line keeps the diff readable.

* refactor(frontend): port index dashboard to react+ts

Step 7 of the Vue→React migration. Ports the overview/index entry: dashboard
page, status + xray cards, panel-update / log / backup / system-history /
xray-metrics / xray-log / version modals, and the custom-geo subsection. Adds
the shared JsonEditor (CodeMirror 6) and useStatus hook used by the config
modal. Removes the unused react-hooks/set-state-in-effect disables now that
the rule is off globally.

* refactor(frontend): port xray to react+ts

Step 8 of the Vue→React migration. Ports the xray config entry: page shell,
basics/routing/outbounds/balancers/dns tabs, the rule + balancer + dns server
+ dns presets + warp + nord modals, the protocol-aware outbound form, and the
shared FinalMaskForm (TCP/UDP masks + QUIC params). Adds useXraySetting that
mirrors the legacy two-way sync between the JSON template string and the
parsed templateSettings tree. The outbound model itself stays in JS so the
class-driven form keeps its existing mutation API; instance access is typed
loosely inside the form to match.

The shared FinalMaskForm.vue and JsonEditor.vue stay alongside the new .tsx
versions until step 9 — InboundFormModal.vue still imports them.

Adds react-hooks/immutability and react-hooks/refs to the already-disabled
react-compiler rule set; both flag the outbound form's instance-mutation
pattern that doesn't run through useState.

* Upgrade frontend deps (antd v6, i18n, TS)

Bump frontend dependencies in package.json and regenerate package-lock.json. Notable updates: upgrade antd to v6, update i18next/react-i18next, axios, qs, vue-i18n, TypeScript and ESLint, plus related @rc-component packages and replacements (e.g. classnames/rc-util -> clsx/@rc-component/util). Lockfile changes reflect the new dependency tree required for Ant Design v6 and other package upgrades.

* refactor(frontend): port inbounds to react+ts and drop vue toolchain

Step 9 — the last entry. Ports the inbounds entry: page shell, list with
desktop table + mobile cards, info modal, qr-code modal, share-link
helpers, and the protocol-aware form modal (basics / protocol /
stream / security / sniffing / advanced JSON). useInbounds replaces
the Vue composable with WebSocket-driven traffic + client-stats merge.

Inbound and DBInbound models stay in JS so the class-driven form keeps
its mutation API; instance access is typed loosely inside the form to
match. FinalMaskForm/JsonEditor/TextModal/PromptModal/InfinityIcon are
the last shared bits to flip; their .vue counterparts go too.

Toolchain cleanup now that no entry needs Vue: drop plugin-vue from
vite.config, remove the .vue lint block + parser, prune vue / vue-i18n
/ ant-design-vue / @ant-design/icons-vue / vue3-persian-datetime-picker
/ moment-jalaali override from package.json, and switch utils/index.js
to import { message } from 'antd' instead of ant-design-vue.

* chore(frontend): adopt antd v6 api updates

Sweep deprecated props across the React tree:
- Modal: destroyOnClose -> destroyOnHidden, maskClosable -> mask.closable
- Space: direction -> orientation (or removed when redundant)
- Input.Group compact -> Space.Compact block
- Drawer: width -> size
- Spin: tip -> description
- Progress: trailColor -> railColor
- Alert: message -> title
- Popover: overlayClassName -> rootClassName
- BackTop -> FloatButton.BackTop

Also refresh dashboard theming for v6: rename dark/ultra Layout and Menu
tokens (siderBg, darkItemBg, darkSubMenuItemBg, darkPopupBg), tweak gauge
size/stroke, add font-size overrides for Statistic and Progress so the
overview numbers stay legible under v6 defaults.

* chore(frontend): antd v6 polish, theme + modal fixes

- adopt message.useMessage hook + messageBus bridge so HttpUtil messages
  inherit ConfigProvider theme tokens
- replace deprecated antd APIs (List, Input addonBefore/After, Empty
  imageStyle); introduce InputAddon helper + SettingListItem custom rows
- fix dark/ultra selectors in portaled modals (body.dark,
  html[data-theme='ultra-dark']) instead of nonexistent .is-dark/.is-ultra
- add horizontal scroll to clients table; reorder node columns so
  actions+enable sit at the left
- swap raw button for antd Button in NodeFormModal test connection
- fix FinalMaskForm nested-form by hoisting it outside OutboundFormModal's
  parent Form
- fix advanced "all" JSON tab in InboundFormModal — useMemo on a mutated
  ref was stale; compute on every render
- fix chart-on-open for SystemHistory + XrayMetrics modals by adding open
  to effect deps (useRef.current doesn't trigger re-runs)
- switch i18next interpolation to single-brace {var} to match locale files
- drop residual Vue mentions in CI workflows and Go comments

* fix(frontend): qr code collapse — open only first panel, allow toggle

ClientQrModal and QrCodeModal both used activeKey without onChange,
forcing every panel open and blocking user toggle. Switch to controlled
state initialized to the first item's key on open, with onChange so
clicks update state.

Also remove unused AppBridge.tsx (superseded by per-page message.useMessage
hook).

* fix(frontend): hover cards, balancer load, routing dnd, modal a11y, outbound crash

- ClientsPage/SettingsPage/XrayPage: add hoverable to bottom card/tabs so
  hover affordance matches the top card
- BalancerFormModal: lazy-init useState from props + destroyOnHidden so
  the form mounts with saved values instead of relying on a useEffect
  sync that could miss the first open
- RoutingTab: rewrite pointer drag — handlers are now defined inside the
  pointerdown closure so addEventListener/removeEventListener match;
  drag state lives on a ref (from/to/moved) so onUp reads the real
  indices, not stale closure values. Adds setPointerCapture so Windows
  and touch keep delivering events when the cursor leaves the handle.
- OutboundFormModal/InboundFormModal: blur the focused input before
  switching tabs to silence the aria-hidden-on-focused-element warning
- utils.isArrEmpty: return true for undefined/null arrays — the old form
  treated undefined as "not empty" which crashed VLESSSettings.fromJson
  when json.vnext was missing

* fix(frontend): clipboard reliability + restyle login page

- ClipboardManager.copyText: prefer navigator.clipboard on secure
  contexts, fall back to a focused on-screen textarea + execCommand.
  Old path used left:-9999px which failed selection in some browsers
  and swallowed execCommand's return value, so the "copied" toast
  appeared even when nothing made it to the clipboard.
- LoginPage: richer gradient backdrop — five animated colour blobs,
  glassmorphic card (backdrop-filter blur + saturate), gradient brand
  text/accent, masked grid texture for depth, and a thin gradient
  border on the card. Light/dark/ultra each get their own palette.

* Memoize compactAdvancedJson and update deps

Wrap compactAdvancedJson in useCallback (dependent on messageApi) and add it to the dependency array of applyAdvancedJsonToBasic. This ensures a stable function reference for correct dependency tracking and avoids stale closures/unnecessary re-renders in InboundFormModal.tsx.

* style(frontend): prettier charts, drop redundant frame, format net rates

- Sparkline: multi-stop gradient fill, soft drop-shadow under the line,
  dashed grid, glowing pulse on the latest-point marker, pill-shaped
  tooltip with dashed crosshair
- XrayMetricsModal: glow + pulse on the observatory alive dot,
  monospace stamps/listen text
- SystemHistoryModal: keep just the modal's frame around the chart (the
  inner wrapper I'd added stacked a second border on top); strip the
  decimal from Net Up/Down (25.63 KB/s → 25 KB/s) only on this chart's
  formatter

* style(frontend): refined dark/ultra palette + shared pro card frame

- Dark tokens shifted to a cooler, Linear-style palette: page #1a1b1f,
  sidebar/header #15161a (recessed nav, darker than cards), card
  #23252b, elevated #2d2f37
- Ultra dark: page pure #000 for OLED, sidebar #050507 disappears into
  the frame, card #101013 with a clear step, elevated #1a1a1e
- New styles/page-cards.css holds the card border/shadow/hover rules so
  all seven content pages (index, clients, inbounds, xray, settings,
  nodes, api-docs) share one definition instead of duplicating in each
  page CSS
- Dashboard typography: uppercase card titles with letter-spacing,
  larger 17px stat values, subtle gradient divider between stat columns,
  ellipsis on action labels so "Backup & Restore" doesn't break the
  card height at mid widths
- Light --bg-page stays at #e6e8ec for the contrast against white cards

* fix(frontend): wireguard info alignment, blue login dark, embed gitkeep

- align WireGuard info-modal fields with Protocol/Address/Port by wrapping
  values in Tag (matches the rest of the dl.info-list rows)
- swap login dark palette from purple to pure blue blobs/accent/brand
- pin web/dist/.gitkeep through gitignore so //go:embed all:dist never
  fails on a fresh clone with an empty dist directory

* docs: refresh frontend docs for the React + TS + AntD 6 stack

Update CONTRIBUTING.md and frontend/README.md to describe the migrated
frontend accurately:

- replace Vue 3 / Ant Design Vue 4 references with React 19 / AntD 6 / TS
- swap composables -> hooks, vue-i18n -> react-i18next, createApp -> createRoot
- mention the typecheck step (tsc --noEmit) in the PR checklist
- document the Vite 8.0.13 pin and TypeScript strict mode in conventions
- list the nodes and api-docs entries that were missing from the layout

* style(frontend): improve readability and mobile polish

- bump statistic title/value contrast in dark and ultra-dark so totals
  on the inbounds summary card stay legible
- give index card actions explicit colors per theme so links like Stop,
  Logs, System History no longer fade into the card background
- show the panel version as a tag next to "3X-UI" on mobile, mirroring
  the Xray version tag pattern, and turn it orange when an update is
  available
- make the login settings button a proper circle by adding size="large"
  + an explicit border-radius fallback on .toolbar-btn

* feat: jalali calendar support and date formatting fixes

- Wire useDatepicker into IntlUtil and switch jalalian display locale
  to fa-IR for clean "1405/07/03 12:00:00" output (drops the awkward
  "AP" era suffix that "<lang>-u-ca-persian" produced)
- Drop in persian-calendar-suite for the jalali date picker, with a
  light/dark/ultra theme map and CSS overrides so the inline-styled
  input stays readable and bg matches the surrounding container
- Force LTR on the picker input so "1405/03/07 00:00" reads naturally
- Pass calendar setting through ClientInfoModal, ClientsPage Duration
  tooltip, and ClientFormModal's expiry picker
- Heuristic toMs() in ClientInfoModal so GORM's autoUpdateTime seconds
  render as a real date instead of "1348/11/01"
- Persist UpdatedAt on the ClientRecord row in client_service.Update;
  previously only the inbound settings JSON was bumped, so the panel
  never saw a fresh updated_at after editing a client

* feat(frontend): donate link, panel version label, login lang menu

- Sidebar: add heart donate link to https://donate.sanaei.dev and small panel version under 3X-UI brand
- Login: swap settings-cog for translation icon, drop title, render languages as a direct list
- Vite dev: inject window.X_UI_CUR_VER from config/version so dev mode matches prod
- Translations: add menu.donate across all locales

* fix(xray-update): respect XUI_BIN_FOLDER on Windows

The Windows update path hardcoded "bin/xray-windows-amd64.exe", ignoring
the configured XUI_BIN_FOLDER. In dev mode (folder set to x-ui) this
created a stray bin/ folder while the running binary stayed un-updated.

* Bump Xray to v26.5.9 and minor cleanup

Update Xray release URLs to v26.5.9 in the GitHub Actions workflow and DockerInit.sh. Remove the hardcoded skip for tagVersion "26.5.3" so it will be considered when collecting Xray versions. Apply small formatting fixes: remove an extra blank line in database/db.go, normalize spacing/alignment of Protocol constants in database/model/model.go, and trim a trailing blank line in web/controller/inbound.go.

* fix(frontend): route remaining copy buttons through ClipboardManager

Direct navigator.clipboard calls fail in non-secure contexts (HTTP on a
LAN IP), making the API-docs code copy and security-tab token copy
silently broken. Both now go through ClipboardManager which falls back
to document.execCommand('copy') when navigator.clipboard is unavailable.

* fix(db): store CreatedAt/UpdatedAt in milliseconds

GORM's autoCreateTime/autoUpdateTime tags default to Unix seconds on
int64 fields and overwrite the service-supplied UnixMilli value on
save. The frontend interprets these timestamps as JS Date inputs
(milliseconds), so created/updated columns rendered ~1970 dates. Adding
the :milli qualifier makes GORM match what the service code and UI
expect.

* Improve legacy clipboard copy handling

Refactor ClipboardManager._legacyCopy to better handle focus and selection when copying. The textarea is now appended to the active element's parent (or body) and placed off-screen with aria-hidden and readonly attributes. The code preserves and restores the previous document selection and active element, uses focus({preventScroll: true}) to avoid scrolling, and returns the execCommand('copy') result. This makes legacy copy behavior more robust and less disruptive to the page state.

* fix(lint): drop redundant ok=false in clipboard fallback catch

* chore(deps): bump golang.org/x/net to v0.55.0 for GO-2026-5026
2026-05-23 15:21:45 +02:00

1093 lines
No EOL
51 KiB
JSON
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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": "创建",
"update": "更新",
"copy": "复制",
"copied": "已复制",
"download": "下载",
"remark": "备注",
"enable": "启用",
"protocol": "协议",
"search": "搜索",
"filter": "筛选",
"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": "无到期"
},
"menu": {
"theme": "主题",
"dark": "暗色",
"ultraDark": "超暗色",
"dashboard": "系统状态",
"inbounds": "入站列表",
"clients": "客户端",
"nodes": "节点",
"settings": "面板设置",
"xray": "Xray 设置",
"apiDocs": "API 文档",
"logout": "退出登录",
"link": "管理",
"donate": "捐赠"
},
"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": "面板已是最新",
"upToDate": "已是最新",
"xrayStatusUnknown": "未知",
"xrayStatusRunning": "运行中",
"xrayStatusStop": "停止",
"xrayStatusError": "错误",
"xrayErrorPopoverTitle": "运行Xray时发生错误",
"operationHours": "系统正常运行时间",
"systemHistoryTitle": "系统历史",
"charts": "图表",
"xrayMetricsTitle": "Xray 指标",
"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": "已开始更新面板",
"geofileUpdateDialog": "您确定要更新地理文件吗?",
"geofileUpdateDialogDesc": "这将更新 #filename# 文件。",
"geofilesUpdateDialogDesc": "这将更新所有文件。",
"geofilesUpdateAll": "全部更新",
"geofileUpdatePopover": "地理文件更新成功",
"customGeoTitle": "自定义 GeoSite / GeoIP",
"customGeoAdd": "添加",
"customGeoType": "类型",
"customGeoAlias": "别名",
"customGeoUrl": "URL",
"customGeoEnabled": "启用",
"customGeoLastUpdated": "上次更新",
"customGeoExtColumn": "路由 (ext:…)",
"customGeoToastUpdateAll": "所有自定义来源已更新",
"customGeoActions": "操作",
"customGeoEdit": "编辑",
"customGeoDelete": "删除",
"customGeoDownload": "立即更新",
"customGeoModalAdd": "添加自定义 geo",
"customGeoModalEdit": "编辑自定义 geo",
"customGeoModalSave": "保存",
"customGeoDeleteConfirm": "删除此自定义 geo 源?",
"customGeoRoutingHint": "在路由规则中将值列写为 ext:文件.dat:标签(替换标签)。",
"customGeoInvalidId": "无效的资源 ID",
"customGeoAliasesError": "加载自定义 geo 别名失败",
"customGeoValidationAlias": "别名只能包含小写字母、数字、- 和 _",
"customGeoValidationUrl": "URL 必须以 http:// 或 https:// 开头",
"customGeoAliasPlaceholder": "a-z 0-9 _ -",
"customGeoAliasLabelSuffix": "(自定义)",
"customGeoToastList": "自定义 geo 列表",
"customGeoToastAdd": "添加自定义 geo",
"customGeoToastUpdate": "更新自定义 geo",
"customGeoToastDelete": "自定义 geofile「{{ .fileName }}」已删除",
"customGeoToastDownload": "geofile「{{ .fileName }}」已更新",
"customGeoErrInvalidType": "类型必须是 geosite 或 geoip",
"customGeoErrAliasRequired": "请填写别名",
"customGeoErrAliasPattern": "别名包含不允许的字符",
"customGeoErrAliasReserved": "该别名已保留",
"customGeoErrUrlRequired": "请填写 URL",
"customGeoErrInvalidUrl": "URL 无效",
"customGeoErrUrlScheme": "URL 必须使用 http 或 https",
"customGeoErrUrlHost": "URL 主机无效",
"customGeoErrDuplicateAlias": "此类型下已使用该别名",
"customGeoErrNotFound": "未找到自定义 geo 源",
"customGeoErrDownload": "下载失败",
"customGeoErrUpdateAllIncomplete": "有一个或多个自定义 geo 源更新失败",
"customGeoEmpty": "暂无自定义 geo 源 — 点击「添加」以创建",
"dontRefresh": "安装中,请勿刷新此页面",
"logs": "日志",
"config": "配置",
"backup": "备份",
"backupTitle": "备份和恢复",
"exportDatabase": "备份",
"exportDatabaseDesc": "点击下载包含当前数据库备份的 .db 文件到您的设备。",
"importDatabase": "恢复",
"importDatabaseDesc": "点击选择并上传设备中的 .db 文件以从备份恢复数据库。",
"importDatabaseSuccess": "数据库导入成功",
"importDatabaseError": "导入数据库时出错",
"readDatabaseError": "读取数据库时出错",
"getDatabaseError": "检索数据库时出错",
"getConfigError": "检索配置文件时出错"
},
"inbounds": {
"title": "入站列表",
"totalDownUp": "总上传 / 下载",
"totalUsage": "总用量",
"inboundCount": "入站数量",
"operate": "菜单",
"enable": "启用",
"remark": "备注",
"node": "节点",
"deployTo": "部署到",
"localPanel": "本地面板",
"fallbacks": {
"title": "回落",
"help": "当此入站的连接未匹配任何客户端时将其路由到另一个入站。在下方选择一个子入站路由字段SNI / ALPN / Path / xver会从子入站的传输方式中自动填充——大多数场景无需再调整。每个子入站应监听 127.0.0.1security=none。",
"empty": "暂无回落",
"add": "添加回落",
"pickInbound": "选择一个入站",
"matchAny": "任意",
"rederive": "从子入站重新填充",
"rederived": "已从子入站重新填充",
"editAdvanced": "编辑路由字段",
"hideAdvanced": "隐藏高级",
"quickAddAll": "一键添加所有可用入站",
"quickAdded": "已添加 {n} 条回落",
"quickAddedNone": "没有可添加的新入站",
"routesWhen": "当满足条件时路由",
"defaultCatchAll": "默认 — 兜底匹配其他所有"
},
"protocol": "协议",
"port": "端口",
"portMap": "端口映射",
"traffic": "流量",
"details": "详细信息",
"transportConfig": "传输配置",
"expireDate": "到期时间",
"createdAt": "创建时间",
"updatedAt": "更新时间",
"resetTraffic": "重置流量",
"addInbound": "添加入站",
"generalActions": "通用操作",
"modifyInbound": "修改入站",
"deleteInbound": "删除入站",
"deleteInboundContent": "确定要删除入站吗?",
"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、监听 IPListening 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": "从面板设置证书",
"streamTab": "流",
"securityTab": "安全",
"sniffingTab": "嗅探",
"sniffingMetadataOnly": "仅元数据",
"sniffingRouteOnly": "仅路由",
"sniffingIpsExcluded": "排除的 IP",
"sniffingDomainsExcluded": "排除的域名",
"decryption": "解密",
"encryption": "加密",
"vlessAuthX25519": "X25519 认证",
"vlessAuthMlkem768": "ML-KEM-768 认证",
"vlessAuthCustom": "自定义",
"vlessAuthSelected": "已选择:{auth}",
"advanced": {
"title": "入站 JSON 部分",
"subtitle": "完整入站 JSON 以及针对 settings、sniffing 和 streamSettings 的专用编辑器。",
"all": "全部",
"allHelp": "在单个编辑器中编辑包含所有字段的完整入站对象。",
"settings": "设置",
"settingsHelp": "Xray settings 块包装:",
"sniffing": "嗅探",
"sniffingHelp": "Xray sniffing 块包装:",
"stream": "流",
"streamHelp": "Xray stream 块包装:",
"jsonErrorPrefix": "高级 JSON"
},
"telegramDesc": "请提供Telegram聊天ID。在机器人中使用'/id'命令)或({'@'}userinfobot",
"subscriptionDesc": "要找到你的订阅 URL请导航到“详细信息”。此外你可以为多个客户端使用相同的名称。",
"info": "信息",
"same": "相同",
"inboundData": "入站数据",
"exportInbound": "导出入站规则",
"import": "导入",
"importInbound": "导入入站规则",
"periodicTrafficResetTitle": "流量重置",
"periodicTrafficResetDesc": "按指定间隔自动重置流量计数器",
"lastReset": "上次重置",
"periodicTrafficReset": {
"never": "从不",
"daily": "每日",
"weekly": "每周",
"monthly": "每月",
"hourly": "每小时"
},
"toasts": {
"obtain": "获取",
"updateSuccess": "更新成功",
"logCleanSuccess": "日志已清除",
"inboundsUpdateSuccess": "入站连接已成功更新",
"inboundUpdateSuccess": "入站连接已成功更新",
"inboundCreateSuccess": "入站连接已成功创建",
"inboundDeleteSuccess": "入站连接已成功删除",
"inboundClientAddSuccess": "已添加入站客户端",
"inboundClientDeleteSuccess": "入站客户端已删除",
"inboundClientUpdateSuccess": "入站客户端已更新",
"delDepletedClientsSuccess": "所有耗尽客户端已删除",
"resetAllClientTrafficSuccess": "客户端所有流量已重置",
"resetAllTrafficSuccess": "所有流量已重置",
"resetInboundClientTrafficSuccess": "流量已重置",
"resetInboundTrafficSuccess": "入站流量已重置",
"trafficGetError": "获取流量数据时出错",
"getNewX25519CertError": "获取X25519证书时出错。",
"getNewmldsa65Error": "获取mldsa65证书时出错。",
"getNewVlessEncError": "获取VlessEnc证书时出错。"
},
"stream": {
"general": {
"request": "请求",
"response": "响应",
"name": "名称",
"value": "值"
},
"tcp": {
"version": "版本",
"method": "方法",
"path": "路径",
"status": "状态",
"statusDescription": "状态说明",
"requestHeader": "请求头",
"responseHeader": "响应头"
}
}
},
"clients": {
"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 = 禁用) (单位: 天)",
"title": "客户端",
"actions": "操作",
"totalGB": "总上传/下载 (GB)",
"expiryTime": "过期时间",
"addClients": "添加客户端",
"limitIp": "IP 限制",
"password": "密码",
"subId": "订阅 ID",
"online": "在线",
"email": "邮箱",
"comment": "备注",
"traffic": "流量",
"offline": "离线",
"addTitle": "添加客户端",
"qrCode": "二维码",
"moreInformation": "更多信息",
"delete": "删除",
"reset": "重置流量",
"editTitle": "编辑客户端",
"client": "客户端",
"enabled": "已启用",
"remaining": "剩余",
"duration": "时长",
"attachedInbounds": "关联入站",
"selectInbound": "选择一个或多个入站",
"noSubId": "该客户端没有 subId无法生成共享链接。",
"noLinks": "没有可共享的链接 — 请先将此客户端关联到支持协议的入站。",
"link": "链接",
"resetNotPossible": "请先将此客户端关联到入站。",
"general": "通用",
"resetAllTraffics": "重置所有客户端流量",
"resetAllTrafficsTitle": "重置所有客户端流量?",
"resetAllTrafficsContent": "所有客户端的上下行计数器将归零。配额与过期时间不受影响。该操作不可撤销。",
"empty": "尚无客户端 — 添加一个开始使用。",
"deleteConfirmTitle": "删除客户端 {email}",
"deleteConfirmContent": "将从所有关联入站中移除该客户端并删除其流量记录。该操作不可撤销。",
"deleteSelected": "删除 ({count})",
"bulkDeleteConfirmTitle": "删除 {count} 个客户端?",
"bulkDeleteConfirmContent": "每个所选客户端都会从关联的入站中被移除,其流量记录也会被删除。该操作不可撤销。",
"delDepleted": "删除已耗尽",
"delDepletedConfirmTitle": "删除已耗尽的客户端?",
"delDepletedConfirmContent": "删除所有流量配额已用尽或已过期的客户端。该操作不可撤销。",
"auth": "Auth",
"hysteriaAuth": "Hysteria Auth",
"uuid": "UUID",
"flow": "Flow",
"reverseTag": "Reverse tag",
"reverseTagPlaceholder": "可选 Reverse tag",
"telegramId": "Telegram 用户 ID",
"telegramIdPlaceholder": "数字形式的 Telegram 用户 ID (0 = 无)",
"created": "创建时间",
"updated": "更新时间",
"ipLimit": "IP 限制",
"toasts": {
"deleted": "客户端已删除",
"trafficReset": "流量已重置",
"allTrafficsReset": "所有客户端流量已重置",
"bulkDeleted": "已删除 {count} 个客户端",
"bulkDeletedMixed": "已删除 {ok} 个,失败 {failed} 个",
"bulkCreated": "已创建 {count} 个客户端",
"bulkCreatedMixed": "已创建 {ok} 个,失败 {failed} 个",
"delDepleted": "已删除 {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上的节点启用。",
"enable": "已启用",
"status": "状态",
"cpu": "CPU",
"mem": "内存",
"uptime": "运行时间",
"latency": "延迟",
"lastHeartbeat": "上次心跳",
"xrayVersion": "Xray 版本",
"panelVersion": "面板版本",
"actions": "操作",
"probe": "立即探测",
"testConnection": "测试连接",
"connectionOk": "连接正常 ({ms} ms)",
"connectionFailed": "连接失败",
"never": "从未",
"justNow": "刚刚",
"deleteConfirmTitle": "删除节点 \"{name}\"",
"deleteConfirmContent": "这将停止监控该节点。远程面板本身不受影响。",
"statusValues": {
"online": "在线",
"offline": "离线",
"unknown": "未知"
},
"toasts": {
"list": "加载节点失败",
"obtain": "加载节点失败",
"add": "添加节点",
"update": "更新节点",
"delete": "删除节点",
"deleted": "节点已删除",
"test": "测试连接",
"fillRequired": "名称、地址、端口和 API 令牌为必填项",
"probeFailed": "探测失败"
}
},
"settings": {
"title": "面板设置",
"save": "保存",
"infoDesc": "此处的所有更改都需要保存并重启面板才能生效",
"restartPanel": "重启面板",
"restartPanelDesc": "确定要重启面板吗?若重启后无法访问面板,请前往服务器查看面板日志信息",
"restartPanelSuccess": "面板已成功重启",
"actions": "操作",
"resetDefaultConfig": "重置为默认配置",
"panelSettings": "常规",
"securitySettings": "安全设定",
"TGBotSettings": "Telegram 机器人配置",
"panelListeningIP": "面板监听 IP",
"panelListeningIPDesc": "默认留空监听所有 IP",
"panelListeningDomain": "面板监听域名",
"panelListeningDomainDesc": "默认情况下留空以监视所有域名和 IP 地址",
"panelPort": "面板监听端口",
"panelPortDesc": "重启面板生效",
"publicKeyPath": "面板证书公钥文件路径",
"publicKeyPathDesc": "填写一个 '/' 开头的绝对路径",
"privateKeyPath": "面板证书密钥文件路径",
"privateKeyPathDesc": "填写一个 '/' 开头的绝对路径",
"panelUrlPath": "面板 url 根路径",
"panelUrlPathDesc": "必须以 '/' 开头,以 '/' 结尾",
"pageSize": "分页大小",
"pageSizeDesc": "定义入站表的页面大小。设置 0 表示禁用",
"remarkModel": "备注模型和分隔符",
"datepicker": "日期选择器",
"datepickerPlaceholder": "选择日期",
"datepickerDescription": "选择器日历类型指定到期日期",
"sampleRemark": "备注示例",
"oldUsername": "原用户名",
"currentPassword": "原密码",
"newUsername": "新用户名",
"newPassword": "新密码",
"telegramBotEnable": "启用 Telegram 机器人",
"telegramBotEnableDesc": "启用 Telegram 机器人功能",
"telegramToken": "Telegram 机器人令牌token",
"telegramTokenDesc": "从 '{'@'}BotFather' 获取的 Telegram 机器人令牌",
"telegramProxy": "SOCKS5 Proxy",
"telegramProxyDesc": "启用 SOCKS5 代理连接到 Telegram根据指南调整设置",
"telegramAPIServer": "Telegram API Server",
"telegramAPIServerDesc": "要使用的 Telegram API 服务器。留空以使用默认服务器。",
"telegramChatId": "管理员聊天 ID",
"telegramChatIdDesc": "Telegram 管理员聊天 ID (多个以逗号分隔)(可通过 {'@'}userinfobot 获取,或在机器人中使用 '/id' 命令获取)",
"telegramNotifyTime": "通知时间",
"telegramNotifyTimeDesc": "设置周期性的 Telegram 机器人通知时间(使用 crontab 时间格式)",
"tgNotifyBackup": "数据库备份",
"tgNotifyBackupDesc": "发送带有报告的数据库备份文件",
"tgNotifyLogin": "登录通知",
"tgNotifyLoginDesc": "当有人试图登录你的面板时显示用户名、IP 地址和时间",
"sessionMaxAge": "会话时长",
"sessionMaxAgeDesc": "保持登录状态的时长(单位:分钟)",
"expireTimeDiff": "到期通知阈值",
"expireTimeDiffDesc": "达到此阈值时,将收到有关到期时间的通知(单位:天)",
"trafficDiff": "流量耗尽阈值",
"trafficDiffDesc": "达到此阈值时将收到有关流量耗尽的通知单位GB",
"tgNotifyCpu": "CPU 负载通知阈值",
"tgNotifyCpuDesc": "CPU 负载超过此阈值时,将收到通知(单位:%",
"timeZone": "时区",
"timeZoneDesc": "定时任务将按照该时区的时间运行",
"subSettings": "订阅设置",
"subEnable": "启用订阅服务",
"subEnableDesc": "启用订阅服务功能",
"subJsonEnable": "单独启用/禁用 JSON 订阅端点。",
"subTitle": "订阅标题",
"subTitleDesc": "在VPN客户端中显示的标题",
"subSupportUrl": "支持链接",
"subSupportUrlDesc": "VPN 客户端中显示的技术支持链接",
"subProfileUrl": "个人资料链接",
"subProfileUrlDesc": "VPN 客户端中显示的网站链接",
"subAnnounce": "公告",
"subAnnounceDesc": "VPN 客户端中显示的公告文本",
"subEnableRouting": "启用路由",
"subEnableRoutingDesc": "在 VPN 客户端中启用路由的全局设置。(僅限 Happ",
"subRoutingRules": "路由規則",
"subRoutingRulesDesc": "VPN 用戶端的全域路由規則。(僅限 Happ",
"subListen": "监听 IP",
"subListenDesc": "订阅服务监听的 IP 地址(留空表示监听所有 IP",
"subPort": "监听端口",
"subPortDesc": "订阅服务监听的端口号(必须是未使用的端口)",
"subCertPath": "公钥路径",
"subCertPathDesc": "订阅服务使用的公钥文件路径(以 '/' 开头)",
"subKeyPath": "私钥路径",
"subKeyPathDesc": "订阅服务使用的私钥文件路径(以 '/' 开头)",
"subPath": "URI 路径",
"subPathDesc": "订阅服务使用的 URI 路径(以 '/' 开头,以 '/' 结尾)",
"subDomain": "监听域名",
"subDomainDesc": "订阅服务监听的域名(留空表示监听所有域名和 IP",
"subUpdates": "更新间隔",
"subUpdatesDesc": "客户端应用中订阅 URL 的更新间隔(单位:小时)",
"subEncrypt": "编码",
"subEncryptDesc": "订阅服务返回的内容将采用 Base64 编码",
"subShowInfo": "显示使用信息",
"subShowInfoDesc": "客户端应用中将显示剩余流量和日期信息",
"subEmailInRemark": "在名称中包含邮箱",
"subEmailInRemarkDesc": "在订阅配置名称中包含客户端邮箱。",
"subURI": "反向代理 URI",
"subURIDesc": "用于代理后面的订阅 URL 的 URI 路径",
"externalTrafficInformEnable": "外部交通通知",
"externalTrafficInformEnableDesc": "每次流量更新时通知外部 API",
"externalTrafficInformURI": "外部流量通知 URI",
"externalTrafficInformURIDesc": "流量更新将发送到此 URI",
"restartXrayOnClientDisable": "客户端自动禁用后重启 Xray",
"restartXrayOnClientDisableDesc": "当客户端因到期或流量超限被自动禁用时,重启 Xray。",
"fragment": "分片",
"fragmentDesc": "启用 TLS hello 数据包分片",
"fragmentSett": "设置",
"noisesDesc": "启用 Noises.",
"noisesSett": "Noises 设置",
"mux": "多路复用器",
"muxDesc": "在已建立的数据流内传输多个独立的数据流",
"muxSett": "复用器设置",
"direct": "直接连接",
"directDesc": "直接与特定国家的域或IP范围建立连接",
"notifications": "通知",
"certs": "证书",
"externalTraffic": "外部流量",
"dateAndTime": "日期和时间",
"proxyAndServer": "代理和服务器",
"intervals": "间隔",
"information": "信息",
"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": "使用此令牌的任何调用方将立即无法认证。"
},
"toasts": {
"modifySettings": "参数已更改。",
"getSettings": "获取参数时发生错误",
"modifyUserError": "更改管理员凭据时发生错误。",
"modifyUser": "您已成功更改管理员凭据。",
"originalUserPassIncorrect": "原用户名或原密码错误",
"userPassMustBeNotEmpty": "新用户名和新密码不能为空",
"getOutboundTrafficError": "获取出站流量错误",
"resetOutboundTrafficError": "重置出站流量错误"
}
},
"xray": {
"title": "Xray 配置",
"save": "保存",
"restart": "重新启动 Xray",
"restartSuccess": "Xray 已成功重新启动",
"stopSuccess": "Xray 已成功停止",
"restartError": "重启Xray时发生错误。",
"stopError": "停止Xray时发生错误。",
"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 协议中网络的输出策略",
"RoutingStrategy": "配置路由域策略",
"RoutingStrategyDesc": "设置 DNS 解析的整体路由策略",
"outboundTestUrl": "出站测试 URL",
"outboundTestUrlDesc": "测试出站连接时使用的 URL",
"Torrent": "屏蔽 BitTorrent 协议",
"Inbounds": "入站规则",
"InboundsDesc": "接受来自特定客户端的流量",
"Outbounds": "出站规则",
"Balancers": "负载均衡",
"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": "启用所有出站代理的下行流量统计收集。",
"rules": {
"first": "置顶",
"last": "置底",
"up": "向上",
"down": "向下",
"source": "来源",
"dest": "目的地址",
"inbound": "入站",
"outbound": "出站",
"balancer": "负载均衡",
"info": "信息",
"add": "添加规则",
"edit": "编辑规则",
"useComma": "逗号分隔的项目"
},
"outbound": {
"addOutbound": "添加出站",
"addReverse": "添加反向",
"editOutbound": "编辑出站",
"editReverse": "编辑反向",
"reverseTag": "反向标签",
"reverseTagDesc": "VLESS 简易反向代理出站标签。留空则禁用。设置后,此客户端的连接可用作反向代理隧道。",
"reverseTagPlaceholder": "出站标签(留空则禁用)",
"tag": "标签",
"tagDesc": "唯一标签",
"address": "地址",
"reverse": "反向",
"domain": "域名",
"type": "类型",
"bridge": "Bridge",
"portal": "Portal",
"link": "链接",
"intercon": "互连",
"settings": "设置",
"accountInfo": "帐户信息",
"outboundStatus": "出站状态",
"sendThrough": "发送通过",
"test": "测试",
"testResult": "测试结果",
"testing": "正在测试连接...",
"testSuccess": "测试成功",
"testFailed": "测试失败",
"testError": "测试出站失败",
"nordvpn": "NordVPN",
"accessToken": "访问令牌",
"country": "国家",
"server": "服务器",
"city": "城市",
"allCities": "所有城市",
"privateKey": "私钥",
"load": "负载"
},
"balancer": {
"addBalancer": "添加负载均衡",
"editBalancer": "编辑负载均衡",
"balancerStrategy": "策略",
"balancerSelectors": "选择器",
"tag": "标签",
"tagDesc": "唯一标签",
"balancerDesc": "无法同时使用 balancerTag 和 outboundTag。如果同时使用则只有 outboundTag 会生效。"
},
"wireguard": {
"secretKey": "密钥",
"publicKey": "公钥",
"allowedIPs": "允许的 IP",
"endpoint": "端点",
"psk": "共享密钥",
"domainStrategy": "域策略"
},
"tun": {
"nameDesc": "TUN 接口的名称。默认值为 'xray0'",
"mtuDesc": "最大传输单元。数据包的最大大小。默认值为 1500",
"userLevel": "用户级别",
"userLevelDesc": "通过此入站的所有连接都将使用此用户级别。默认值为 0"
},
"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 服务器,且无法撤销。"
},
"fakedns": {
"add": "添加假 DNS",
"edit": "编辑假 DNS",
"ipPool": "IP 池子网",
"poolSize": "池大小"
}
}
},
"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"
},
"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": "🔢 IP 地址:\r\n{{ .IPs }}\r\n",
"serverUpTime": "⏳ 服务器运行时间:{{ .UpTime }} {{ .Unit }}\r\n",
"serverLoad": "📈 服务器负载:{{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
"serverMemory": "📋 服务器内存:{{ .Current }}/{{ .Total }}\r\n",
"tcpCount": "🔹 TCP 连接数:{{ .Count }}\r\n",
"udpCount": "🔸 UDP 连接数:{{ .Count }}\r\n",
"traffic": "🚦 流量:{{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
"xrayStatus": " Xray 状态:{{ .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": "🔚 所有客户的流量重置已完成。"
},
"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": "⚙️🚦 流控",
"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": "选择一个入站"
}
}
}