chore(i18n): delete 230 dead translation keys and guard against new ones (#6132)

* chore(i18n): delete 230 dead translation keys and guard against new ones

The 13 locale files carried 230 keys (11% of the set) that nothing in
the frontend or Go sources references — leftovers of renamed features
(the email notifier reuses tgbot.messages.* for subjects, the old
email.subject*/title* set was orphaned; likewise menu.*, the clients
bulk-copy strings, and the secAlert* family). Nothing detected this:
a missing key falls back to en-US and an unused key fails nothing.

A new test now fails the build when an en-US key has no reference in
frontend/src or internal Go sources (dynamic keys are covered by
harvesting concatenation and template-literal prefixes), and pins
that all 13 locales carry exactly the en-US key set, so parity drift
surfaces at test time instead of as a silent fallback.

Each locale shrinks by the same 230 keys; net -2,900 lines across
the translation set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(i18n): restore the 29 live remarkVars keys, match whole tokens, unmask 9 more

From review: the template-literal harvester required the prefix to end
on a dot, so pages.hosts.remarkVars.desc${token} harvested nothing
and all 29 desc* tooltip keys were wrongly deleted — and the guard
shared the flawed logic, so CI stayed green while the Hosts page
would have shown raw key names in 13 languages. Restored from the
parent commit; the harvester now requires at least one dot but not a
trailing one.

Also from review: references are matched as whole dotted tokens
instead of substrings (a dead key can no longer hide behind a longer
sibling — that unmasked 9 more genuinely dead keys, each verified by
hand before deletion), and the test excludes itself from the scan so
its own prose cannot whitelist a subtree.

Net: -210 keys per locale instead of the previous -230.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
PathGao
2026-07-29 13:59:25 +08:00
committed by GitHub
parent 17e6b5a460
commit ea35884390
14 changed files with 117 additions and 2834 deletions
+2 -218
View File
@@ -48,7 +48,6 @@
"copySuccess": "Đã sao chép thành công",
"sure": "Chắc chắn",
"encryption": "Mã hóa",
"useIPv4ForHost": "Sử dụng IPv4 cho máy chủ",
"transmission": "Truyền tải",
"host": "Host",
"path": "Đường dẫn",
@@ -74,18 +73,9 @@
"twoFactorCode": "Mã",
"remained": "Còn lại",
"security": "Bảo vệ",
"secAlertTitle": "Cảnh báo an ninh-Tiếng Việt by Ohoang7",
"secAlertSsl": "Kết nối này không an toàn; Vui lòng không nhập thông tin nhạy cảm cho đến khi TLS được kích hoạt để bảo vệ dữ liệu của Bạn",
"secAlertConf": "Một số cài đặt có thể dễ bị tấn công. Đề xuất tăng cường các giao thức bảo mật để ngăn chặn các vi phạm tiềm ẩn.",
"secAlertSSL": "Bảng điều khiển thiếu kết nối an toàn. Vui lòng cài đặt chứng chỉ TLS để bảo vệ dữ liệu.",
"secAlertPanelPort": "Cổng mặc định của bảng điều khiển có thể dễ bị tấn công. Vui lòng cấu hình một cổng ngẫu nhiên hoặc cụ thể.",
"secAlertPanelURI": "Đường dẫn URI mặc định của bảng điều khiển không an toàn. Vui lòng cấu hình một đường dẫn URI phức tạp.",
"secAlertSubURI": "Đường dẫn URI mặc định của đăng ký không an toàn. Vui lòng cấu hình một đường dẫn URI phức tạp.",
"secAlertSubJsonURI": "Đường dẫn URI JSON mặc định của đăng ký không an toàn. Vui lòng cấu hình một đường dẫn URI phức tạp.",
"emptyDnsDesc": "Không có máy chủ DNS nào được thêm.",
"emptyFakeDnsDesc": "Không có máy chủ Fake DNS nào được thêm.",
"emptyBalancersDesc": "Không có bộ cân bằng tải nào được thêm.",
"emptyReverseDesc": "Không có proxy ngược nào được thêm.",
"somethingWentWrong": "Đã xảy ra lỗi",
"subscription": {
"title": "Thông tin đăng ký",
@@ -106,8 +96,6 @@
},
"menu": {
"theme": "Chủ đề",
"dark": "Tối",
"ultraDark": "Siêu tối",
"dashboard": "Trạng thái hệ thống",
"inbounds": "Inbound",
"clients": "Khách hàng",
@@ -118,7 +106,6 @@
"routing": "Định tuyến",
"outbounds": "Outbound",
"apiDocs": "Tài liệu API",
"logout": "Đăng xuất",
"link": "Quản lý",
"donate": "Quyên góp",
"hosts": "Hosts",
@@ -139,7 +126,6 @@
}
},
"index": {
"title": "Trạng thái hệ thống",
"cpu": "CPU",
"logicalProcessors": "Bộ xử lý logic",
"frequency": "Tần số",
@@ -152,7 +138,6 @@
"restartXray": "Khởi động lại",
"xraySwitch": "Phiên bản",
"xrayUpdates": "Cập nhật Xray",
"xraySwitchClick": "Chọn phiên bản mà bạn muốn chuyển đổi sang.",
"xraySwitchClickDesk": "Hãy lựa chọn thận trọng, vì các phiên bản cũ có thể không tương thích với các cấu hình hiện tại.",
"updatePanel": "Cập nhật Panel",
"panelUpdateDesc": "Điều này sẽ cập nhật 3X-UI lên bản phát hành mới nhất và khởi động lại dịch vụ panel.",
@@ -164,12 +149,10 @@
"currentCommit": "Commit hiện tại",
"latestCommit": "Commit mới nhất",
"updateChannelChanged": "Đã đổi kênh cập nhật",
"upToDate": "Đã cập nhật",
"xrayStatusUnknown": "Không xác định",
"xrayStatusRunning": "Đang chạy",
"xrayStatusStop": "Dừng",
"xrayStatusError": "Lỗi",
"xrayErrorPopoverTitle": "Đã xảy ra lỗi khi chạy Xray",
"operationHours": "Thời gian hoạt động",
"systemHistoryTitle": "Lịch sử hệ thống",
"historyTitleCpu": "Mức sử dụng CPU",
@@ -211,9 +194,6 @@
"xrayObservatoryDead": "Ngừng",
"xrayObservatoryLastSeen": "Lần cuối thấy",
"xrayObservatoryLastTry": "Lần thử cuối",
"trendLast2Min": "2 phút gần nhất",
"systemLoad": "Tải hệ thống",
"systemLoadDesc": "trung bình tải hệ thống trong 1, 5 và 15 phút qua",
"connectionCount": "Số lượng kết nối",
"ipAddresses": "Địa chỉ IP",
"toggleIpVisibility": "Chuyển đổi hiển thị IP",
@@ -223,13 +203,11 @@
"totalData": "Tổng dữ liệu",
"sent": "Đã gửi",
"received": "Đã nhận",
"documentation": "Tài liệu",
"xraySwitchVersionDialog": "Bạn có chắc chắn muốn thay đổi phiên bản Xray không?",
"xraySwitchVersionDialogDesc": "Hành động này sẽ thay đổi phiên bản Xray thành #version#.",
"xraySwitchVersionPopover": "Xray đã được cập nhật thành công",
"panelUpdateDialog": "Bạn có chắc muốn cập nhật panel không?",
"panelUpdateDialogDesc": "Điều này sẽ cập nhật 3X-UI lên #version# và khởi động lại dịch vụ panel.",
"panelUpdateCheckPopover": "Kiểm tra cập nhật panel thất bại",
"panelUpdateStartedPopover": "Bắt đầu cập nhật panel",
"panelUpdateFailedTitle": "Cập nhật panel thất bại",
"panelUpdateFailedDesc": "Bản cập nhật không hoàn tất thành công. Hãy kiểm tra nhật ký máy chủ, hoặc chạy 'x-ui update' từ dòng lệnh.",
@@ -258,7 +236,6 @@
"accessLogs": "Nhật ký truy cập",
"autoUpdate": "Tự động cập nhật",
"config": "Cấu hình",
"backup": "Sao lưu",
"backupTitle": "Sao lưu & Khôi phục",
"exportDatabase": "Sao lưu",
"exportDatabaseDesc": "Nhấp để tải xuống tệp .db chứa bản sao lưu cơ sở dữ liệu hiện tại của bạn vào thiết bị. Tệp này cũng có thể được khôi phục vào bảng điều khiển chạy PostgreSQL.",
@@ -276,7 +253,6 @@
"migrationDownloadPgDesc": "Nhấp để tải xuống cơ sở dữ liệu SQLite .db được tạo từ dữ liệu PostgreSQL của bạn, sẵn sàng chạy bảng điều khiển này trên SQLite."
},
"inbounds": {
"title": "Inbound",
"totalDownUp": "Tổng tải lên/tải xuống",
"totalUsage": "Tổng sử dụng",
"inboundCount": "Số lượng điểm vào",
@@ -288,21 +264,11 @@
"localPanel": "Panel cục bộ",
"fallbacks": {
"title": "Fallbacks",
"help": "Khi một kết nối trên inbound này không khớp với client nào, hãy chuyển hướng nó tới nơi khác. Chọn một inbound con bên dưới để tự động điền các trường định tuyến (SNI / ALPN / Path / xver) từ transport của nó, hoặc để trống ô chọn và đặt Dest trực tiếp (ví dụ 8080 hoặc 127.0.0.1:8080) để chuyển hướng tới một máy chủ bên ngoài như Nginx. Mỗi inbound con nên lắng nghe trên 127.0.0.1 với security=none.",
"empty": "Chưa có fallback nào",
"add": "Thêm fallback",
"pickInbound": "Chọn một inbound",
"matchAny": "bất kỳ",
"destPlaceholder": "tự động (listen:port của child)",
"rederive": "Điền lại từ child",
"rederived": "Đã điền lại từ child",
"editAdvanced": "Sửa trường định tuyến",
"hideAdvanced": "Ẩn nâng cao",
"quickAddAll": "Thêm nhanh tất cả các inbound đủ điều kiện",
"quickAdded": "Đã thêm {n} fallback",
"quickAddedNone": "Không có inbound mới nào đủ điều kiện",
"routesWhen": "Định tuyến khi",
"defaultCatchAll": "Mặc định — bắt mọi thứ khác",
"needsTls": "Fallback khả dụng sau khi chọn TLS hoặc Reality trong thẻ Bảo mật (chỉ VLESS/Trojan trên RAW)."
},
"protocol": "Giao thức",
@@ -310,8 +276,6 @@
"portMap": "Ánh xạ cổng",
"traffic": "Lưu lượng",
"speed": "Tốc độ",
"details": "Chi tiết",
"transportConfig": "Truyền dẫn",
"expireDate": "Ngày hết hạn",
"createdAt": "Tạo lúc",
"updatedAt": "Cập nhật",
@@ -319,8 +283,6 @@
"addInbound": "Thêm điểm vào",
"generalActions": "Hành động chung",
"modifyInbound": "Chỉnh sửa điểm vào (Inbound)",
"deleteInbound": "Xóa điểm vào (Inbound)",
"deleteInboundContent": "Xác nhận xóa điểm vào? (Inbound)",
"deleteConfirmTitle": "Xóa inbound \"{remark}\"?",
"deleteConfirmContent": "Hành động này xóa inbound và toàn bộ khách hàng của nó. Không thể hoàn tác.",
"resetConfirmTitle": "Đặt lại lưu lượng của \"{remark}\"?",
@@ -364,8 +326,6 @@
"exportAllLinksFileName": "Tat-ca-Inbound",
"exportAllSubsFileName": "Tat-ca-Inbound-Subs",
"inboundJsonTitle": "JSON inbound",
"deleteClient": "Xóa người dùng",
"deleteClientContent": "Bạn có chắc chắn muốn xóa người dùng không?",
"resetTrafficContent": "Xác nhận đặt lại lưu lượng?",
"copyLink": "Sao chép liên kết",
"address": "Địa chỉ",
@@ -376,36 +336,19 @@
"meansNoLimit": "= Không giới hạn. (đơn vị: GB)",
"totalFlow": "Tổng lưu lượng",
"leaveBlankToNeverExpire": "Để trống để không bao giờ hết hạn",
"noRecommendKeepDefault": "Không yêu cầu đặc biệt để giữ nguyên cài đặt mặc định",
"certificatePath": "Đường dẫn tập",
"certificateContent": "Nội dung tập",
"publicKey": "Khóa công khai",
"privatekey": "Khóa cá nhân",
"clickOnQRcode": "Nhấn vào Mã QR để sao chép",
"client": "Người dùng",
"export": "Xuất liên kết",
"clone": "Sao chép",
"cloneInbound": "Sao chép điểm vào (Inbound)",
"cloneInboundContent": "Tất cả cài đặt của điểm vào này, trừ Cổng, IP nghe và máy khách, sẽ được áp dụng cho bản sao.",
"cloneInboundOk": "Sao chép",
"resetAllTraffic": "Đặt lại lưu lượng cho tất cả điểm vào",
"resetAllTrafficTitle": "Đặt lại lưu lượng cho tất cả điểm vào",
"resetAllTrafficContent": "Bạn có chắc chắn muốn đặt lại lưu lượng cho tất cả điểm vào không?",
"resetInboundClientTraffics": "Đặt lại lưu lượng toàn bộ người dùng của điểm vào",
"resetInboundClientTrafficTitle": "Đặt lại lưu lượng cho toàn bộ người dùng của điểm vào",
"resetInboundClientTrafficContent": "Bạn có chắc chắn muốn đặt lại tất cả lưu lượng cho các người dùng của điểm vào này không?",
"resetAllClientTraffics": "Đặt lại lưu lượng cho toàn bộ người dùng",
"resetAllClientTrafficTitle": "Đặt lại lưu lượng cho toàn bộ người dùng",
"resetAllClientTrafficContent": "Bạn có chắc chắn muốn đặt lại tất cả lưu lượng cho toàn bộ người dùng không?",
"delDepletedClients": "Xóa các người dùng đã cạn kiệt",
"delDepletedClientsTitle": "Xóa các người dùng đã cạn kiệt",
"delDepletedClientsContent": "Bạn có chắc chắn muốn xóa toàn bộ người dùng đã cạn kiệt không?",
"email": "Email",
"emailDesc": "Vui lòng cung cấp một địa chỉ email duy nhất.",
"IPLimit": "Giới hạn IP",
"IPLimitDesc": "Vô hiệu hóa điểm vào nếu số lượng vượt quá giá trị đã nhập (nhập 0 để vô hiệu hóa giới hạn IP).",
"IPLimitlog": "Lịch sử IP",
"IPLimitlogDesc": "Lịch sử đăng nhập IP (trước khi kích hoạt điểm vào sau khi bị vô hiệu hóa bởi giới hạn IP, bạn nên xóa lịch sử).",
"IPLimitlogclear": "Xóa Lịch sử",
"setDefaultCert": "Đặt chứng chỉ từ bảng điều khiển",
"setDefaultCertEmpty": "Không có chứng chỉ nào được cấu hình cho bảng điều khiển. Hãy đặt một chứng chỉ trong Cài đặt trước.",
@@ -438,21 +381,15 @@
"sniffing": "Sniffing",
"sniffingHelp": "Bao đóng khối sniffing của Xray:",
"stream": "Stream",
"streamHelp": "Bao đóng khối stream của Xray:",
"jsonErrorPrefix": "JSON nâng cao"
"streamHelp": "Bao đóng khối stream của Xray:"
},
"telegramDesc": "Vui lòng cung cấp ID Trò chuyện Telegram. (sử dụng lệnh '/id' trong bot) hoặc ({'@'}userinfobot)",
"subscriptionDesc": "Bạn có thể tìm liên kết gói đăng ký của mình trong Chi tiết, cũng như bạn có thể sử dụng cùng tên cho nhiều cấu hình khác nhau",
"subSortIndex": "Thứ tự sub",
"same": "Giống nhau",
"inboundInfo": "Thông tin Inbound",
"exportInbound": "Xuất nhập khẩu",
"import": "Nhập",
"importInbound": "Nhập inbound",
"periodicTrafficResetTitle": "Đặt lại lưu lượng",
"periodicTrafficResetDesc": "Tự động đặt lại bộ đếm lưu lượng theo khoảng thời gian xác định",
"periodicTrafficResetDay": "Ngày đặt lại hàng tháng",
"lastReset": "Đặt lại lần cuối",
"periodicTrafficReset": {
"never": "Không bao giờ",
"daily": "Hàng ngày",
@@ -464,7 +401,6 @@
"obtain": "Nhận",
"updateSuccess": "Cập nhật thành công",
"logCleanSuccess": "Đã xóa nhật ký",
"inboundsUpdateSuccess": "Đã cập nhật thành công các kết nối inbound",
"inboundUpdateSuccess": "Đã cập nhật thành công kết nối inbound",
"inboundCreateSuccess": "Đã tạo thành công kết nối inbound",
"bulkDeleted": "Đã xóa {count} inbound",
@@ -474,7 +410,6 @@
"inboundClientDeleteSuccess": "Đã xóa client inbound",
"inboundClientUpdateSuccess": "Đã cập nhật client inbound",
"savedNodeOfflineWillSync": "Đã lưu cục bộ. Một nút hỗ trợ đang ngoại tuyến hoặc bị tắt — thay đổi sẽ được đồng bộ khi kết nối lại.",
"delDepletedClientsSuccess": "Đã xóa tất cả client hết hạn",
"resetAllClientTrafficSuccess": "Đã đặt lại toàn bộ lưu lượng client",
"resetAllTrafficSuccess": "Đã đặt lại toàn bộ lưu lượng",
"resetInboundClientTrafficSuccess": "Đã đặt lại lưu lượng",
@@ -717,23 +652,6 @@
"peerNumber": "Peer {n}",
"peerNumberConfig": "Cấu hình Peer {n}"
},
"stream": {
"general": {
"request": "Lời yêu cầu",
"response": "Phản ứng",
"name": "Tên",
"value": "Giá trị"
},
"tcp": {
"version": "Phiên bản",
"method": "Phương pháp",
"path": "Đường dẫn",
"status": "Trạng thái",
"statusDescription": "Tình trạng Mô tả",
"requestHeader": "Header yêu cầu",
"responseHeader": "Header phản hồi"
}
},
"sniffingDestOverride": "Ghi đè đích"
},
"clients": {
@@ -747,24 +665,9 @@
"addExternalSubscription": "Thêm đăng ký ngoài",
"noExternalLinks": "Chưa có liên kết ngoài.",
"noExternalSubscriptions": "Chưa có đăng ký ngoài.",
"add": "Thêm khách hàng",
"edit": "Chỉnh sửa khách hàng",
"submitAdd": "Thêm khách hàng",
"submitEdit": "Lưu thay đổi",
"clientCount": "Số lượng khách hàng",
"bulk": "Thêm hàng loạt",
"copyFromInbound": "Sao chép khách hàng từ inbound",
"copyToInbound": "Sao chép khách hàng đến",
"copySelected": "Sao chép đã chọn",
"copySource": "Nguồn",
"copyEmailPreview": "Xem trước email kết quả",
"copySelectSourceFirst": "Hãy chọn inbound nguồn trước.",
"copyResult": "Kết quả sao chép",
"copyResultSuccess": "Đã sao chép thành công",
"copyResultNone": "Không có gì để sao chép: chưa chọn khách hàng hoặc nguồn rỗng",
"copyResultErrors": "Lỗi sao chép",
"copyFlowLabel": "Flow cho khách hàng mới (VLESS)",
"copyFlowHint": "Áp dụng cho tất cả khách hàng được sao chép. Để trống để bỏ qua.",
"selectAll": "Chọn tất cả",
"clearAll": "Xóa tất cả",
"method": "Phương thức",
@@ -775,7 +678,6 @@
"postfix": "Hậu tố",
"delayedStart": "Bắt đầu sau lần dùng đầu",
"expireDays": "Thời hạn (ngày)",
"days": "Ngày",
"renew": "Tự động gia hạn",
"renewDesc": "Tự động gia hạn sau khi hết hạn. (0 = tắt) (đơn vị: ngày)",
"renewDays": "Tự động gia hạn (ngày)",
@@ -798,7 +700,6 @@
"sortExpiringSoonest": "Sắp hết hạn",
"has": "Có",
"hasNot": "Không có",
"title": "Khách hàng",
"actions": "Hành động",
"totalGB": "Giới hạn lưu lượng (GB)",
"totalGBDesc": "Hạn mức dữ liệu cho khách hàng này. 0 = không giới hạn.",
@@ -826,8 +727,6 @@
"addClient": "Thêm khách hàng",
"qrCode": "Mã QR",
"clientInfo": "Thông tin khách hàng",
"delete": "Xóa",
"reset": "Đặt lại lưu lượng",
"editClient": "Chỉnh sửa khách hàng",
"client": "Khách hàng",
"enabled": "Đã bật",
@@ -841,13 +740,11 @@
"noLinks": "Không có liên kết chia sẻ — hãy gắn khách hàng này vào một inbound có giao thức tương thích trước.",
"link": "Liên kết",
"resetNotPossible": "Hãy gắn khách hàng này vào một inbound trước.",
"general": "Chung",
"resetAllTraffics": "Đặt lại lưu lượng của tất cả khách hàng",
"resetAllTrafficsTitle": "Đặt lại lưu lượng của tất cả khách hàng?",
"resetAllTrafficsContent": "Bộ đếm gửi/nhận của mỗi khách hàng về 0. Hạn mức và thời hạn không bị ảnh hưởng. Không thể hoàn tác.",
"deleteConfirmTitle": "Xóa khách hàng {email}?",
"deleteConfirmContent": "Hành động này gỡ khách hàng khỏi mọi inbound đã gắn và xóa bản ghi lưu lượng. Không thể hoàn tác.",
"deleteSelected": "Xóa ({count})",
"adjustSelected": "Điều chỉnh ({count})",
"subLinksSelected": "Liên kết sub ({count})",
"addToGroupTitle": "Thêm {count} client vào một nhóm",
@@ -869,12 +766,10 @@
"bulkDisableConfirmTitle": "Tắt {count} khách hàng?",
"bulkDisableConfirmContent": "Tắt từng khách hàng đã chọn trên mọi inbound được gắn. Họ mất quyền truy cập ngay lập tức nhưng hồ sơ và lưu lượng của họ vẫn được giữ lại.",
"selectedCount": "Đã chọn {count}",
"attachSelected": "Gắn ({count})",
"attachToInboundsTitle": "Gắn {count} client vào inbound",
"attachToInboundsDesc": "Gắn {count} client đã chọn (cùng UUID/mật khẩu và lưu lượng chung) vào các inbound đã chọn. Các gắn kết hiện tại được giữ nguyên.",
"attachToInboundsTargets": "Inbound đích",
"attachToInboundsNoTargets": "Không có inbound đa người dùng nào để gắn.",
"detachSelected": "Tách ({count})",
"detach": "Tách",
"detachFromInboundsTitle": "Tách {count} client khỏi inbound",
"detachFromInboundsDesc": "Xóa {count} client đã chọn khỏi các inbound đã chọn. Các cặp client chưa gắn sẽ được bỏ qua. Hồ sơ client được giữ lại (dùng Delete để xóa hoàn toàn).",
@@ -928,8 +823,6 @@
"reverseTagPlaceholder": "Reverse tag tùy chọn",
"telegramId": "ID người dùng Telegram",
"telegramIdPlaceholder": "ID người dùng Telegram dạng số (0 = không có)",
"created": "Tạo",
"updated": "Cập nhật",
"ipLimit": "Giới hạn IP",
"toasts": {
"deleted": "Đã xóa khách hàng",
@@ -952,7 +845,6 @@
}
},
"groups": {
"title": "Nhóm",
"name": "Tên",
"clientCount": "Client",
"totalGroups": "Tổng số nhóm",
@@ -994,7 +886,6 @@
"removeFromGroupResult": "Đã xóa {count} client khỏi {name}."
},
"nodes": {
"title": "Nút",
"addNode": "Thêm nút",
"editNode": "Sửa node",
"totalNodes": "Tổng số nút",
@@ -1013,8 +904,6 @@
"apiTokenPlaceholder": "Token từ trang Cài đặt của panel từ xa",
"apiTokenHint": "Panel từ xa hiển thị token API tại Bảo mật → Token API.",
"apiTokenKeepHint": "Để trống để giữ token hiện tại",
"regenerate": "Tạo lại token",
"regenerateConfirm": "Tạo lại sẽ vô hiệu hóa token hiện tại. Mọi panel trung tâm dùng nó sẽ mất quyền truy cập cho đến khi được cập nhật. Tiếp tục?",
"allowPrivateAddress": "Cho phép địa chỉ riêng",
"allowPrivateAddressHint": "Chỉ bật cho các nút trên mạng riêng hoặc VPN.",
"outboundTag": "Outbound kết nối",
@@ -1046,7 +935,6 @@
"updatePanel": "Cập nhật bảng điều khiển",
"updateSelected": "Cập nhật đã chọn ({count})",
"updateAvailable": "Có bản cập nhật",
"upToDate": "Mới nhất",
"updateConfirmTitle": "Cập nhật {count} node lên phiên bản mới nhất?",
"updateConfirmContent": "Mỗi node đã chọn sẽ tải bản phát hành mới nhất và khởi động lại. Chỉ các node đang bật và trực tuyến được cập nhật.",
"updateDevChannel": "Cập nhật lên kênh phát triển (commit mới nhất)",
@@ -1447,7 +1335,6 @@
"secretClearUndo": "Hoàn tác xóa"
},
"xray": {
"title": "Cài đặt Xray",
"importRules": "Nhập quy tắc",
"exportRules": "Xuất quy tắc",
"importOutbounds": "Nhập outbound",
@@ -1457,11 +1344,7 @@
"metricsListenDesc": "Hiển thị các chỉ số kiểu Prometheus của Xray tại địa chỉ:cổng này (ví dụ 127.0.0.1:11111). Để trống để tắt. Hãy gắn vào localhost và reverse-proxy nó — vì nó không có xác thực.",
"metricsTag": "Metrics Tag",
"save": "Lưu cài đặt",
"restart": "Khởi động lại Xray",
"restartSuccess": "Đã khởi động lại Xray thành công",
"restartOutputTitle": "Đầu ra khởi động lại Xray",
"restartConfirmTitle": "Khởi động lại xray?",
"restartConfirmContent": "Tải lại dịch vụ xray với cấu hình đã lưu.",
"stopSuccess": "Xray đã được dừng thành công",
"restartError": "Đã xảy ra lỗi khi khởi động lại Xray.",
"stopError": "Đã xảy ra lỗi khi dừng Xray.",
@@ -1471,7 +1354,6 @@
"generalConfigsDesc": "Những tùy chọn này sẽ cung cấp điều chỉnh tổng quát.",
"logConfigs": "Nhật ký",
"logConfigsDesc": "Nhật ký có thể ảnh hưởng đến hiệu suất máy chủ của bạn. Bạn chỉ nên kích hoạt nó một cách khôn ngoan trong trường hợp bạn cần",
"blockConfigsDesc": "Những tùy chọn này sẽ ngăn người dùng kết nối đến các giao thức và trang web cụ thể.",
"basicRouting": "Định tuyến Cơ bản",
"blockConnectionsConfigsDesc": "Các tùy chọn này sẽ chặn lưu lượng truy cập dựa trên quốc gia được yêu cầu cụ thể.",
"directConnectionsConfigsDesc": "Kết nối trực tiếp đảm bảo rằng lưu lượng truy cập cụ thể không được định tuyến qua máy chủ khác.",
@@ -1481,10 +1363,6 @@
"directdomains": "Tên Miền Trực Tiếp",
"ipv4Routing": "Định tuyến IPv4",
"ipv4RoutingDesc": "Những tùy chọn này sẽ chỉ định kết nối đến các tên miền mục tiêu qua IPv4.",
"warpRouting": "Định tuyến WARP",
"warpRoutingDesc": "Cảnh báo: Trước khi sử dụng những tùy chọn này, hãy cài đặt WARP ở chế độ proxy socks5 trên máy chủ của bạn bằng cách làm theo các bước trên GitHub của bảng điều khiển. WARP sẽ định tuyến lưu lượng đến các trang web qua máy chủ Cloudflare.",
"nordRouting": "Định tuyến NordVPN",
"nordRoutingDesc": "Các tùy chọn này sẽ định tuyến lưu lượng dựa trên đích cụ thể qua NordVPN.",
"Template": "Mẫu Cấu hình Xray",
"TemplateDesc": "Tạo tệp cấu hình Xray cuối cùng dựa trên mẫu này.",
"FreedomStrategy": "Cấu hình Chiến lược cho Giao thức Freedom",
@@ -1498,10 +1376,7 @@
"outboundTestUrlDesc": "URL dùng khi kiểm tra kết nối outbound",
"Torrent": "Cấu hình sử dụng BitTorrent",
"Inbounds": "Inbound",
"InboundsDesc": "Thay đổi mẫu cấu hình để chấp nhận các máy khách cụ thể.",
"Outbounds": "Outbound",
"OutboundSubscriptions": "Đăng ký Outbound",
"OutboundSubscriptionsDesc": "Nhập các outbound từ URL đăng ký từ xa (vmess/vless/trojan/ss/...). Tag được giữ ổn định để dùng trong bộ cân bằng tải và quy tắc định tuyến. Cập nhật diễn ra tự động.",
"Balancers": "Cân bằng",
"balancerTagRequired": "Tag là bắt buộc",
"balancerSelectorRequired": "Chọn ít nhất một outbound",
@@ -1520,9 +1395,7 @@
"routeTesterMatchedOutbound": "Outbound phù hợp",
"routeTesterViaBalancer": "qua bộ cân bằng tải",
"routeTesterDefaultOutbound": "Không có quy tắc định tuyến nào khớp — lưu lượng đến outbound mặc định (đầu tiên).",
"OutboundsDesc": "Thay đổi mẫu cấu hình để xác định các cách ra đi cho máy chủ này.",
"Routings": "Quy tắc định tuyến",
"RoutingsDesc": "Mức độ ưu tiên của mỗi quy tắc đều quan trọng!",
"completeTemplate": "Tất cả",
"logLevel": "Mức đăng nhập",
"logLevelDesc": "Cấp độ nhật ký cho nhật ký lỗi, cho biết thông tin cần được ghi lại.",
@@ -1536,13 +1409,9 @@
"maskAddressDesc": "Mặt nạ địa chỉ IP, khi được bật, sẽ tự động thay thế địa chỉ IP xuất hiện trong nhật ký.",
"statistics": "Thống kê",
"statsInboundUplink": "Thống kê tải lên đầu vào",
"statsInboundUplinkDesc": "Kích hoạt thu thập thống kê cho lưu lượng tải lên của tất cả các proxy đầu vào.",
"statsInboundDownlink": "Thống kê tải xuống đầu vào",
"statsInboundDownlinkDesc": "Kích hoạt thu thập thống kê cho lưu lượng tải xuống của tất cả các proxy đầu vào.",
"statsOutboundUplink": "Thống kê tải lên đầu ra",
"statsOutboundUplinkDesc": "Kích hoạt thu thập thống kê cho lưu lượng tải lên của tất cả các proxy đầu ra.",
"statsOutboundDownlink": "Thống kê tải xuống đầu ra",
"statsOutboundDownlinkDesc": "Kích hoạt thu thập thống kê cho lưu lượng tải xuống của tất cả các proxy đầu ra.",
"connectionLimits": "Giới hạn kết nối",
"connectionLimitsDesc": "Chính sách cấp kết nối cho người dùng cấp 0. Để trống một trường để sử dụng giá trị mặc định của Xray.",
"connIdle": "Thời gian chờ nhàn rỗi",
@@ -1552,18 +1421,10 @@
"bufferSizePlaceholder": "tự động",
"seconds": "giây",
"rules": {
"first": "Đầu tiên",
"last": "Cuối cùng",
"up": "Lên",
"down": "Xuống",
"source": "Nguồn",
"dest": "Đích",
"inbound": "Vào",
"outbound": "Ra",
"balancer": "Cân bằng",
"info": "Thông tin",
"add": "Thêm quy tắc",
"edit": "Chỉnh sửa quy tắc",
"useComma": "Các mục được phân tách bằng dấu phẩy"
},
"routing": {
@@ -1604,7 +1465,6 @@
"ruleN": "Quy tắc {n}",
"action": "Hành động",
"redirect": "Redirect",
"fragment": "Fragment",
"finalRules": "Quy tắc cuối",
"overrideXrayPrivateIp": "Ghi đè chặn IP riêng mặc định của Xray",
"blockDelay": "Trễ chặn (ms)",
@@ -1630,43 +1490,17 @@
"keepAliveInterval": "Khoảng keep alive",
"markFwmark": "Mark (fwmark)",
"interface": "Giao diện",
"ipv6Only": "Chỉ IPv6",
"acceptProxyProtocol": "Chấp nhận proxy protocol",
"proxyProtocol": "Proxy protocol",
"tcpUserTimeoutMs": "TCP user timeout (ms)",
"tcpKeepAliveIdleS": "TCP keep-alive idle (s)"
},
"outbound": {
"addOutbound": "Thêm thư đi",
"addReverse": "Thêm đảo ngược",
"editOutbound": "Chỉnh sửa gửi đi",
"editReverse": "Chỉnh sửa ngược lại",
"reverseTag": "Thẻ Ngược",
"reverseTagDesc": "Thẻ outbound của proxy ngược đơn giản VLESS. Để trống để vô hiệu hóa.",
"reverseTagPlaceholder": "thẻ outbound (để trống để vô hiệu hóa)",
"tag": "Tag",
"tagDesc": "thẻ duy nhất",
"address": "Địa chỉ",
"egress": "Egress",
"egressHint": "Run an HTTP test to show egress IP and country.",
"reverse": "Đảo ngược",
"domain": "Tên miền",
"type": "Loại",
"bridge": "Bridge",
"portal": "Portal",
"link": "Liên kết",
"intercon": "Kết nối",
"settings": "cài đặt",
"accountInfo": "Thông tin tài khoản",
"outboundStatus": "Trạng thái đầu ra",
"sendThrough": "Gửi qua",
"targetStrategy": "Chiến lược đích",
"test": "Kiểm tra",
"testResult": "Kết quả kiểm tra",
"testing": "Đang kiểm tra kết nối...",
"testSuccess": "Kiểm tra thành công",
"testFailed": "Kiểm tra thất bại",
"testError": "Không thể kiểm tra đầu ra",
"modeRealDelay": "Độ trễ thực",
"testModeTooltip": "TCP: probe dial nhanh. HTTP: yêu cầu đầy đủ qua xray. Độ trễ thực: tổng thời gian gồm cả thiết lập kết nối.",
"testAll": "Kiểm tra tất cả",
@@ -1674,14 +1508,10 @@
"breakdownConnect": "Kết nối proxy",
"breakdownTls": "TLS qua outbound",
"breakdownTtfb": "Byte đầu tiên",
"nordvpn": "NordVPN",
"accessToken": "Mã truy cập",
"country": "Quốc gia",
"server": "Máy chủ",
"city": "Thành phố",
"allCities": "Tất cả thành phố",
"privateKey": "Khóa riêng",
"load": "Tải",
"moveToTop": "Chuyển lên đầu"
},
"outboundSub": {
@@ -1711,16 +1541,11 @@
"active": "Đăng ký đang hoạt động",
"empty": "Chưa có đăng ký nào. Hãy thêm một mục ở trên.",
"colRemark": "Ghi chú",
"colPrefix": "Tiền tố",
"colInterval": "Khoảng",
"colLastFetch": "Lần tải gần nhất",
"colEnabled": "Đã kích hoạt",
"auto": "tự động",
"never": "không bao giờ",
"yes": "Có",
"no": "Không",
"refreshNow": "Cập nhật ngay",
"lastError": "Lỗi gần nhất",
"deleteConfirm": "Xóa đăng ký này?",
"restartHint": "Sau khi thêm hoặc cập nhật, hãy khởi động lại Xray (hoặc chờ lần tự động tải lại tiếp theo) để kích hoạt các outbound.",
"fromSubsTitle": "Từ đăng ký outbound (chỉ đọc)",
@@ -1737,8 +1562,6 @@
"tabBalancerSettings": "Cài đặt Balancer",
"tabObservatory": "Observatory",
"observatory": {
"title": "Observatory",
"burstTitle": "Burst Observatory",
"autoManaged": "Observer được quản lý tự động từ các balancer của bạn. Điều chỉnh cách chúng dò ở bên dưới; các outbound được theo dõi sẽ tuân theo selector của balancer.",
"emptyHint": "Không có observer kết nối nào đang hoạt động. Một observer sẽ được thêm tự động khi bạn tạo balancer Least Ping hoặc Least Load — hoặc balancer Random / Round-robin có fallback — để các balancer dùng observer có thể kiểm tra sức khỏe outbound trước khi chọn mục tiêu.",
"mixedLegacy": "Cấu hình này có cả Observatory và Burst Observatory. Xray chỉ dùng một observer toàn cục, nên trạng thái hỗn hợp cũ này không được hỗ trợ; khi lưu balancer, nó sẽ được chuẩn hóa về một observer.",
@@ -1772,12 +1595,8 @@
"balancerRemoved": "Balancer {tag} — đã xóa (không còn mục tiêu)"
},
"balancer": {
"addBalancer": "Thêm cân bằng",
"editBalancer": "Chỉnh sửa cân bằng",
"balancerStrategy": "Chiến lược",
"balancerSelectors": "Bộ chọn",
"tag": "Tag",
"tagDesc": "thẻ duy nhất",
"tagDuplicate": "Tag đã được dùng bởi balancer khác",
"tagPlaceholder": "tag balancer duy nhất",
"selector": "Selector",
@@ -1789,7 +1608,6 @@
"tolerance": "Dung sai",
"baselines": "Baselines",
"costs": "Costs",
"balancerDesc": "Không thể sử dụng balancerTag và outboundTag cùng một lúc. Nếu sử dụng cùng lúc thì chỉ outboundTag mới hoạt động.",
"costMatch": "Mẫu thẻ",
"costValue": "Trọng số",
"costRegexp": "Khớp biểu thức chính quy",
@@ -1804,14 +1622,10 @@
"publicKey": "Khóa công khai",
"allowedIPs": "IP được phép",
"endpoint": "Điểm cuối",
"psk": "Khóa chia sẻ",
"domainStrategy": "Chiến lược tên miền"
},
"tun": {
"nameDesc": "Tên của giao diện TUN. Giá trị mặc định là 'xray0'",
"mtuDesc": "Đơn vị Truyền Tối đa. Kích thước tối đa của các gói dữ liệu. Giá trị mặc định là 1500",
"userLevel": "Mức Người Dùng",
"userLevelDesc": "Tất cả các kết nối được thực hiện thông qua inbound này sẽ sử dụng mức người dùng này. Giá trị mặc định là 0"
"userLevel": "Mức Người Dùng"
},
"nord": {
"accessToken": "Access token",
@@ -1896,7 +1710,6 @@
},
"fakedns": {
"add": "Thêm DNS giả",
"edit": "Chỉnh sửa DNS giả",
"ipPool": "Mạng con nhóm IP",
"poolSize": "Kích thước bể bơi"
},
@@ -2032,7 +1845,6 @@
"add": "Thêm",
"month": "Tháng",
"months": "Tháng",
"day": "Ngày",
"days": "Ngày",
"hours": "Giờ",
"minutes": "Phút",
@@ -2071,7 +1883,6 @@
"userSaved": "✅ Người dùng Telegram đã được lưu.",
"loginSuccess": "✅ Đăng nhập thành công vào bảng điều khiển.\r\n",
"loginFailed": "❗️ Đăng nhập vào bảng điều khiển thất bại.\r\n",
"2faFailed": "Lỗi 2FA",
"report": "🕰 Báo cáo định kỳ: {{ .RunTime }}\r\n",
"datetime": "⏰ Ngày-Giờ: {{ .DateTime }}\r\n",
"hostname": "💻 Host: {{ .Hostname }}\r\n",
@@ -2104,7 +1915,6 @@
"download": "🔽 Tải xuống: ↓{{ .Download }}\r\n",
"total": "📊 Tổng: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
"TGUser": "👤 Người dùng Telegram: {{ .TelegramID }}\r\n",
"exhaustedMsg": "🚨 Sự cạn kiệt {{ .Type }}:\r\n",
"exhaustedCount": "🚨 Số lần cạn kiệt {{ .Type }}:\r\n",
"onlinesCount": "🌐 Khách hàng trực tuyến: {{ .Count }}\r\n",
"disabled": "🛑 Vô hiệu hóa: {{ .Disabled }}\r\n",
@@ -2113,16 +1923,10 @@
"refreshedOn": "\r\n📋🔄 Đã cập nhật lần cuối vào: {{ .Time }}\r\n\r\n",
"yes": "✅ Có",
"no": "❌ Không",
"received_id": "🔑📥 ID đã được cập nhật.",
"received_password": "🔑📥 Mật khẩu đã được cập nhật.",
"received_email": "📧📥 Email đã được cập nhật.",
"received_comment": "💬📥 Bình luận đã được cập nhật.",
"id_prompt": "🔑 ID mặc định: {{ .ClientId }}\n\nVui lòng nhập ID của bạn.",
"pass_prompt": "🔑 Mật khẩu mặc định: {{ .ClientPassword }}\n\nVui lòng nhập mật khẩu của bạn.",
"email_prompt": "📧 Email mặc định: {{ .ClientEmail }}\n\nVui lòng nhập email của bạn.",
"comment_prompt": "💬 Bình luận mặc định: {{ .ClientComment }}\n\nVui lòng nhập bình luận của bạn.",
"inbound_client_data_id": "🔄 Kết nối vào: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Dung lượng: {{ .ClientTraffic }}\n📅 Ngày hết hạn: {{ .ClientExp }}\n🌐 Giới hạn IP: {{ .IpLimit }}\n💬 Ghi chú: {{ .ClientComment }}\n\nBây giờ bạn có thể thêm khách hàng vào inbound!",
"inbound_client_data_pass": "🔄 Kết nối vào: {{ .InboundRemark }}\n\n🔑 Mật khẩu: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Dung lượng: {{ .ClientTraffic }}\n📅 Ngày hết hạn: {{ .ClientExp }}\n🌐 Giới hạn IP: {{ .IpLimit }}\n💬 Ghi chú: {{ .ClientComment }}\n\nBây giờ bạn có thể thêm khách hàng vào inbound!",
"cancel": "❌ Quá trình đã bị hủy! \n\nBạn có thể bắt đầu lại bất cứ lúc nào bằng cách nhập /start. 🔄",
"error_add_client": "⚠️ Lỗi:\n\n {{ .error }}",
"using_default_value": "Được rồi, tôi sẽ sử dụng giá trị mặc định. 😊",
@@ -2139,8 +1943,6 @@
"eventXrayCrashError": "Lỗi: {{ .Error }}",
"eventNodeDown": "Node {{ .Name }} đã NGỪNG HOẠT ĐỘNG",
"eventNodeUp": "Node {{ .Name }} đã HOẠT ĐỘNG",
"eventCPUHigh": "CPU cao",
"eventCPUHighDetail": "CPU: {{ .Detail }}",
"eventLoginFallback": "Đăng nhập thất bại từ {{ .Source }}",
"memoryThreshold": "Sử dụng bộ nhớ {{ .Percent }}% vượt quá ngưỡng {{ .Threshold }}%"
},
@@ -2181,11 +1983,8 @@
"submitDisable": "Gửi Dưới Dạng Vô Hiệu ☑️",
"submitEnable": "Gửi Dưới Dạng Kích Hoạt ✅",
"use_default": "🏷️ Sử Dụng Mặc Định",
"change_id": "⚙️🔑 ID",
"change_password": "⚙️🔑 Mật Khẩu",
"change_email": "⚙️📧 Email",
"change_comment": "⚙️💬 Bình Luận",
"change_flow": "⚙️🚦 Flow",
"ResetAllTraffics": "Đặt lại tất cả lưu lượng",
"SortedTrafficUsageReport": "Báo cáo sử dụng lưu lượng đã sắp xếp"
},
@@ -2214,31 +2013,16 @@
}
},
"email": {
"subjectOutboundDown": "Outbound {{ .Tag }} đã NGỪNG HOẠT ĐỘNG",
"subjectOutboundUp": "Outbound {{ .Tag }} đã HOẠT ĐỘNG",
"subjectXrayCrash": "Xray GẶP SỰ CỐ",
"subjectCPUHigh": "CPU cao",
"subjectLoginSuccess": "Đăng nhập thành công",
"subjectLoginFailed": "Đăng nhập thất bại",
"titleOutboundDown": "Outbound NGỪNG HOẠT ĐỘNG",
"titleOutboundUp": "Outbound HOẠT ĐỘNG",
"titleXrayCrash": "Xray GẶP SỰ CỐ",
"titleCPUHigh": "CPU cao",
"titleLoginSuccess": "Đăng nhập thành công",
"titleLoginFailed": "Đăng nhập thất bại",
"labelStatus": "Trạng thái",
"labelOutbound": "Outbound",
"labelNode": "Node",
"labelError": "Lỗi",
"labelDelay": "Độ trễ",
"labelDetail": "Chi tiết",
"labelUsername": "Tên đăng nhập",
"labelIP": "IP",
"labelReason": "Lý do",
"labelSource": "Nguồn",
"labelTime": "Thời gian",
"statusCrashed": "GẶP SỰ CỐ",
"statusRunning": "Đang chạy",
"statusHigh": "CAO",
"statusSuccess": "THÀNH CÔNG",
"statusFailed": "THẤT BẠI",