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": "Скопировано",
"sure": "Да",
"encryption": "Шифрование",
"useIPv4ForHost": "Использовать IPv4 для подключения к хосту",
"transmission": "Транспорт",
"host": "Хост",
"path": "Путь",
@@ -74,18 +73,9 @@
"twoFactorCode": "Код 2FA",
"remained": "Остаток",
"security": "Безопасность",
"secAlertTitle": "Предупреждение системы безопасности",
"secAlertSsl": "Соединение не защищено. Не вводите конфиденциальные данные до установки SSL-сертификата.",
"secAlertConf": "Некоторые настройки уязвимы. Рекомендуется усилить защиту для предотвращения атак.",
"secAlertSSL": "Подключение к панели не защищено. Установите SSL-сертификат для защиты данных.",
"secAlertPanelPort": "Порт панели по умолчанию небезопасен. Установите нестандартный или случайный порт.",
"secAlertPanelURI": "Адрес панели по умолчанию небезопасен. Настройте уникальный и сложный URI.",
"secAlertSubURI": "URI подписки по умолчанию небезопасен. Настройте уникальный и сложный адрес.",
"secAlertSubJsonURI": "URI JSON-подписки по умолчанию небезопасен. Настройте уникальный и сложный адрес.",
"emptyDnsDesc": "Нет добавленных DNS-серверов.",
"emptyFakeDnsDesc": "Нет добавленных Fake DNS-серверов.",
"emptyBalancersDesc": "Нет добавленных балансировщиков.",
"emptyReverseDesc": "Нет добавленных реверс-прокси.",
"somethingWentWrong": "Что-то пошло не так",
"subscription": {
"title": "Информация о подписке",
@@ -106,8 +96,6 @@
},
"menu": {
"theme": "Тема",
"dark": "Темная",
"ultraDark": "Очень темная",
"dashboard": "Дашборд",
"inbounds": "Входящие",
"clients": "Клиенты",
@@ -118,7 +106,6 @@
"routing": "Маршрутизация",
"outbounds": "Исходящие",
"apiDocs": "Документация API",
"logout": "Выход",
"link": "Управление",
"donate": "Поддержать",
"hosts": "Хосты",
@@ -139,7 +126,6 @@
}
},
"index": {
"title": "Дашборд",
"cpu": "ЦП",
"logicalProcessors": "Логические процессоры",
"frequency": "Частота",
@@ -152,7 +138,6 @@
"restartXray": "Перезапуск",
"xraySwitch": "Выбор версии",
"xrayUpdates": "Обновления Xray",
"xraySwitchClick": "Выберите нужную версию",
"xraySwitchClickDesk": "Важно: старые версии могут не поддерживать текущие настройки",
"updatePanel": "Обновить панель",
"panelUpdateDesc": "Это обновит 3X-UI до последнего релиза и перезапустит сервис панели.",
@@ -164,12 +149,10 @@
"currentCommit": "Текущий коммит",
"latestCommit": "Последний коммит",
"updateChannelChanged": "Канал обновления изменён",
"upToDate": "Обновлено",
"xrayStatusUnknown": "Неизвестно",
"xrayStatusRunning": "Запущен",
"xrayStatusStop": "Остановлен",
"xrayStatusError": "Ошибка",
"xrayErrorPopoverTitle": "Ошибка при запуске Xray",
"operationHours": "Время работы системы",
"systemHistoryTitle": "История системы",
"historyTitleCpu": "Загрузка ЦП",
@@ -211,9 +194,6 @@
"xrayObservatoryDead": "Недоступен",
"xrayObservatoryLastSeen": "Последняя активность",
"xrayObservatoryLastTry": "Последняя попытка",
"trendLast2Min": "Последние 2 минуты",
"systemLoad": "Нагрузка на систему",
"systemLoadDesc": "Средняя загрузка системы за последние 1, 5 и 15 минут",
"connectionCount": "Количество соединений",
"ipAddresses": "IP-адреса сервера",
"toggleIpVisibility": "Скрыть или показать IP-адреса сервера",
@@ -223,13 +203,11 @@
"totalData": "Общий объем трафика",
"sent": "Отправлено",
"received": "Получено",
"documentation": "Документация",
"xraySwitchVersionDialog": "Переключить версию Xray",
"xraySwitchVersionDialogDesc": "Вы точно хотите сменить версию Xray?",
"xraySwitchVersionPopover": "Xray успешно обновлён",
"panelUpdateDialog": "Вы действительно хотите обновить панель?",
"panelUpdateDialogDesc": "Это обновит 3X-UI до версии #version# и перезапустит сервис панели.",
"panelUpdateCheckPopover": "Проверка обновления панели не удалась",
"panelUpdateStartedPopover": "Обновление панели началось",
"panelUpdateFailedTitle": "Не удалось обновить панель",
"panelUpdateFailedDesc": "Обновление не завершилось успешно. Проверьте журналы сервера или выполните 'x-ui update' в командной строке.",
@@ -258,7 +236,6 @@
"accessLogs": "Логи доступа",
"autoUpdate": "Автообновление",
"config": "Конфигурация",
"backup": "Резервная копия",
"backupTitle": "Бэкап и восстановление",
"exportDatabase": "Экспорт базы данных",
"exportDatabaseDesc": "Нажмите, чтобы скачать файл .db, содержащий резервную копию вашей текущей базы данных на ваше устройство. Этот же файл можно восстановить на панели, работающей на PostgreSQL.",
@@ -276,7 +253,6 @@
"migrationDownloadPgDesc": "Нажмите, чтобы скачать базу данных SQLite (.db), собранную из ваших данных PostgreSQL и готовую для запуска панели на SQLite."
},
"inbounds": {
"title": "Входящие",
"totalDownUp": "Отправлено/получено",
"totalUsage": "Всего трафика",
"inboundCount": "Всего подключений",
@@ -288,21 +264,11 @@
"localPanel": "Локальная панель",
"fallbacks": {
"title": "Fallback'и",
"help": "Когда соединение на этом инбаунде не совпадает ни с одним клиентом, оно перенаправляется в другое место. Выберите дочерний инбаунд ниже, чтобы поля маршрутизации (SNI / ALPN / Path / xver) заполнились автоматически из его транспорта, либо оставьте выбор пустым и задайте Dest напрямую (например, 8080 или 127.0.0.1:8080), чтобы перенаправить на внешний сервер, такой как Nginx. Каждый дочерний инбаунд должен слушать на 127.0.0.1 с security=none.",
"empty": "Фолбэков пока нет",
"add": "Добавить фолбэк",
"pickInbound": "Выберите инбаунд",
"matchAny": "любой",
"destPlaceholder": "авто (listen:порт дочернего)",
"rederive": "Заполнить из дочернего",
"rederived": "Заполнено из дочернего",
"editAdvanced": "Изменить поля маршрутизации",
"hideAdvanced": "Скрыть расширенные",
"quickAddAll": "Быстро добавить все подходящие",
"quickAdded": "Добавлено {n} фолбэк(ов)",
"quickAddedNone": "Нет новых подходящих инбаундов",
"routesWhen": "Маршрутизирует, когда",
"defaultCatchAll": "По умолчанию — ловит всё остальное",
"needsTls": "Fallbacks станут доступны после выбора TLS или Reality на вкладке «Безопасность» (только VLESS/Trojan поверх RAW)."
},
"protocol": "Протокол",
@@ -310,8 +276,6 @@
"portMap": "Сопоставление портов",
"traffic": "Трафик",
"speed": "Скорость",
"details": "Подробнее",
"transportConfig": "Транспорт",
"expireDate": "Дата окончания",
"createdAt": "Создано",
"updatedAt": "Обновлено",
@@ -319,8 +283,6 @@
"addInbound": "Создать подключение",
"generalActions": "Общие действия",
"modifyInbound": "Изменить подключение",
"deleteInbound": "Удалить подключение",
"deleteInboundContent": "Вы уверены, что хотите удалить подключение?",
"deleteConfirmTitle": "Удалить подключение \"{remark}\"?",
"deleteConfirmContent": "Подключение и все его клиенты будут удалены. Это действие нельзя отменить.",
"resetConfirmTitle": "Сбросить трафик \"{remark}\"?",
@@ -364,8 +326,6 @@
"exportAllLinksFileName": "Все-входящие",
"exportAllSubsFileName": "Все-входящие-Subs",
"inboundJsonTitle": "JSON входящего",
"deleteClient": "Удалить клиента",
"deleteClientContent": "Вы уверены, что хотите удалить клиента?",
"resetTrafficContent": "Вы уверены, что хотите сбросить трафик?",
"copyLink": "Копировать ссылку",
"address": "Адрес",
@@ -376,36 +336,19 @@
"meansNoLimit": "= Безлимит. (единица: ГБ)",
"totalFlow": "Общий расход",
"leaveBlankToNeverExpire": "Оставьте пустым, чтобы было бесконечным",
"noRecommendKeepDefault": "Рекомендуется оставить настройки по умолчанию",
"certificatePath": "Путь к сертификату",
"certificateContent": "Содержимое сертификата",
"publicKey": "Публичный ключ",
"privatekey": "Приватный ключ",
"clickOnQRcode": "Нажмите на QR-код, чтобы скопировать",
"client": "Клиент",
"export": "Экспорт ссылок",
"clone": "Клонировать",
"cloneInbound": "Клонировать",
"cloneInboundContent": "Будут клонированы все настройки подключений, кроме списка клиентов, порта и IP-адреса прослушивания",
"cloneInboundOk": "Клонировано",
"resetAllTraffic": "Сброс трафика всех подключений",
"resetAllTrafficTitle": "Сброс трафика всех подключений",
"resetAllTrafficContent": "Вы уверены, что хотите сбросить трафик всех подключений?",
"resetInboundClientTraffics": "Сброс трафика клиента",
"resetInboundClientTrafficTitle": "Сброс трафика клиентов",
"resetInboundClientTrafficContent": "Вы уверены, что хотите сбросить трафик для этих клиентов?",
"resetAllClientTraffics": "Сброс трафика всех клиентов",
"resetAllClientTrafficTitle": "Сброс трафика всех клиентов",
"resetAllClientTrafficContent": "Вы уверены, что хотите сбросить трафик всех клиентов?",
"delDepletedClients": "Удалить отключенных клиентов",
"delDepletedClientsTitle": "Удаление отключенных клиентов",
"delDepletedClientsContent": "Вы уверены, что хотите удалить всех отключенных клиентов?",
"email": "Email",
"emailDesc": "Пожалуйста, укажите уникальный Email",
"IPLimit": "Лимит по количеству IP",
"IPLimitDesc": "Ограничение числа одновременных подключений с разных IP (0 – отключить)",
"IPLimitlog": "Лог IP-адресов",
"IPLimitlogDesc": "Лог IP-адресов (перед включением лога IP-адресов, вы должны очистить лог)",
"IPLimitlogclear": "Очистить лог",
"setDefaultCert": "Установить сертификат панели",
"setDefaultCertEmpty": "Для панели не настроен сертификат. Сначала установите его в Настройках.",
@@ -438,21 +381,15 @@
"sniffing": "Sniffing",
"sniffingHelp": "Обёртка блока sniffing Xray:",
"stream": "Stream",
"streamHelp": "Обёртка блока stream Xray:",
"jsonErrorPrefix": "Расширенный JSON"
"streamHelp": "Обёртка блока stream Xray:"
},
"telegramDesc": "Пожалуйста, укажите Chat ID Telegram. (используйте команду '/id' в боте) или ({'@'}userinfobot)",
"subscriptionDesc": "Вы можете найти свою ссылку подписки в разделе 'Подробнее'",
"subSortIndex": "Порядок",
"same": "Тот же",
"inboundInfo": "Информация о подключении",
"exportInbound": "Экспорт подключений",
"import": "Импортировать",
"importInbound": "Импорт подключений",
"periodicTrafficResetTitle": "Сброс трафика",
"periodicTrafficResetDesc": "Автоматический сброс счетчика трафика через указанные интервалы",
"periodicTrafficResetDay": "День ежемесячного сброса",
"lastReset": "Последний сброс",
"periodicTrafficReset": {
"never": "Никогда",
"daily": "Ежедневно",
@@ -464,7 +401,6 @@
"obtain": "Получить",
"updateSuccess": "Обновление прошло успешно",
"logCleanSuccess": "Лог был очищен",
"inboundsUpdateSuccess": "Подключения успешно обновлены",
"inboundUpdateSuccess": "Подключение успешно обновлено",
"inboundCreateSuccess": "Подключение успешно создано",
"bulkDeleted": "Удалено подключений: {count}",
@@ -474,7 +410,6 @@
"inboundClientDeleteSuccess": "Клиент подключения удалён",
"inboundClientUpdateSuccess": "Клиент подключения обновлён",
"savedNodeOfflineWillSync": "Сохранено локально. Опорный узел отключён или недоступен — изменение синхронизируется после повторного подключения.",
"delDepletedClientsSuccess": "Все исчерпанные клиенты удалены",
"resetAllClientTrafficSuccess": "Весь трафик клиента сброшен",
"resetAllTrafficSuccess": "Весь трафик сброшен",
"resetInboundClientTrafficSuccess": "Трафик сброшен",
@@ -717,23 +652,6 @@
"peerNumber": "Peer {n}",
"peerNumberConfig": "Конфиг Peer {n}"
},
"stream": {
"general": {
"request": "Запрос",
"response": "Ответ",
"name": "Имя",
"value": "Значение"
},
"tcp": {
"version": "Версия",
"method": "Метод",
"path": "Путь",
"status": "Статус",
"statusDescription": "Описание статуса",
"requestHeader": "Заголовок запроса",
"responseHeader": "Заголовок ответа"
}
},
"sniffingDestOverride": "Переопределение назначения"
},
"clients": {
@@ -747,24 +665,9 @@
"addExternalSubscription": "Добавить внешнюю подписку",
"noExternalLinks": "Пока нет внешних ссылок.",
"noExternalSubscriptions": "Пока нет внешних подписок.",
"add": "Добавить клиента",
"edit": "Изменить клиента",
"submitAdd": "Добавить клиента",
"submitEdit": "Сохранить изменения",
"clientCount": "Количество клиентов",
"bulk": "Массовое добавление",
"copyFromInbound": "Скопировать клиентов из входящего",
"copyToInbound": "Скопировать клиентов в",
"copySelected": "Скопировать выбранное",
"copySource": "Источник",
"copyEmailPreview": "Предпросмотр результирующего email",
"copySelectSourceFirst": "Сначала выберите исходный входящий.",
"copyResult": "Результат копирования",
"copyResultSuccess": "Скопировано успешно",
"copyResultNone": "Нечего копировать: клиенты не выбраны или источник пуст",
"copyResultErrors": "Ошибки копирования",
"copyFlowLabel": "Flow для новых клиентов (VLESS)",
"copyFlowHint": "Применяется ко всем скопированным клиентам. Оставьте пустым, чтобы пропустить.",
"selectAll": "Выбрать всё",
"clearAll": "Очистить всё",
"method": "Метод",
@@ -775,7 +678,6 @@
"postfix": "Постфикс",
"delayedStart": "Старт после первого использования",
"expireDays": "Длительность (дней)",
"days": "Дни",
"renew": "Автопродление",
"renewDesc": "Автоматическое продление после окончания. (0 = отключено) (единица: день)",
"renewDays": "Автопродление (дней)",
@@ -798,7 +700,6 @@
"sortExpiringSoonest": "Скорее истекают",
"has": "Есть",
"hasNot": "Нет",
"title": "Клиенты",
"actions": "Действия",
"totalGB": "Лимит трафика (ГБ)",
"totalGBDesc": "Квота трафика для этого клиента. 0 = без ограничений.",
@@ -826,8 +727,6 @@
"addClient": "Добавить клиента",
"qrCode": "QR-код",
"clientInfo": "Информация о клиенте",
"delete": "Удалить",
"reset": "Сбросить трафик",
"editClient": "Изменить клиента",
"client": "Клиент",
"enabled": "Включён",
@@ -841,13 +740,11 @@
"noLinks": "Нет ссылок для общего доступа — сначала привяжите клиента к входящему с поддерживаемым протоколом.",
"link": "Ссылка",
"resetNotPossible": "Сначала привяжите этого клиента к входящему.",
"general": "Общие",
"resetAllTraffics": "Сбросить трафик всех клиентов",
"resetAllTrafficsTitle": "Сбросить трафик всех клиентов?",
"resetAllTrafficsContent": "Счётчики отправки/приёма всех клиентов сбрасываются в ноль. Квоты и срок действия не затрагиваются. Это действие нельзя отменить.",
"deleteConfirmTitle": "Удалить клиента {email}?",
"deleteConfirmContent": "Клиент будет удалён из всех привязанных входящих, а его запись трафика будет уничтожена. Это действие нельзя отменить.",
"deleteSelected": "Удалить ({count})",
"adjustSelected": "Изменить ({count})",
"subLinksSelected": "Sub-ссылки ({count})",
"addToGroupTitle": "Добавить {count} клиент(ов) в группу",
@@ -869,12 +766,10 @@
"bulkDisableConfirmTitle": "Отключить {count} клиентов?",
"bulkDisableConfirmContent": "Отключает каждого выбранного клиента на всех привязанных подключениях. Они сразу теряют доступ, но их записи и трафик сохраняются.",
"selectedCount": "{count} выбрано",
"attachSelected": "Привязать ({count})",
"attachToInboundsTitle": "Привязать {count} клиент(ов) к входящим",
"attachToInboundsDesc": "Привязывает выбранных {count} клиент(ов) (тот же UUID/пароль и общий трафик) к выбранным входящим. Существующие привязки сохраняются.",
"attachToInboundsTargets": "Целевые входящие",
"attachToInboundsNoTargets": "Нет доступных многопользовательских входящих для привязки.",
"detachSelected": "Отвязать ({count})",
"detach": "Отвязать",
"detachFromInboundsTitle": "Отвязать {count} клиент(ов) от входящих",
"detachFromInboundsDesc": "Удаляет выбранных {count} клиент(ов) из выбранных входящих. Пары, где клиент не был привязан, тихо пропускаются. Записи клиентов сохраняются (используйте Delete для полного удаления).",
@@ -928,8 +823,6 @@
"reverseTagPlaceholder": "Необязательный Reverse tag",
"telegramId": "ID пользователя Telegram",
"telegramIdPlaceholder": "Числовой ID пользователя Telegram (0 = нет)",
"created": "Создан",
"updated": "Обновлён",
"ipLimit": "Лимит IP",
"toasts": {
"deleted": "Клиент удалён",
@@ -952,7 +845,6 @@
}
},
"groups": {
"title": "Группы",
"name": "Имя",
"clientCount": "Клиенты",
"totalGroups": "Всего групп",
@@ -994,7 +886,6 @@
"removeFromGroupResult": "Удалено {count} клиент(ов) из {name}."
},
"nodes": {
"title": "Узлы",
"addNode": "Добавить узел",
"editNode": "Изменить узел",
"totalNodes": "Всего узлов",
@@ -1013,8 +904,6 @@
"apiTokenPlaceholder": "Токен со страницы Настроек удалённой панели",
"apiTokenHint": "Удалённая панель показывает свой токен API в разделе Учетная запись → Токен API.",
"apiTokenKeepHint": "Оставьте пустым, чтобы сохранить текущий токен",
"regenerate": "Сгенерировать токен заново",
"regenerateConfirm": "Повторная генерация аннулирует текущий токен. Любая центральная панель, использующая его, потеряет доступ до обновления. Продолжить?",
"allowPrivateAddress": "Разрешить частный адрес",
"allowPrivateAddressHint": "Включить только для узлов в частной сети или VPN.",
"outboundTag": "Исходящее подключение",
@@ -1046,7 +935,6 @@
"updatePanel": "Обновить панель",
"updateSelected": "Обновить выбранные ({count})",
"updateAvailable": "Доступно обновление",
"upToDate": "Актуально",
"updateConfirmTitle": "Обновить {count} узлов до последней версии?",
"updateConfirmContent": "Каждый выбранный узел загрузит последний релиз и перезапустится. Обновляются только включённые узлы в сети.",
"updateDevChannel": "Обновить до канала разработки (последний коммит)",
@@ -1455,13 +1343,8 @@
"metricsListen": "Эндпоинт метрик",
"metricsListenDesc": "Публикует метрики Xray в стиле Prometheus по этому адресу:порту (например, 127.0.0.1:11111). Оставьте пустым, чтобы отключить. Привяжите к localhost и проксируйте через reverse-proxy — он без аутентификации.",
"metricsTag": "Тег метрик",
"title": "Настройки Xray",
"save": "Сохранить",
"restart": "Перезапуск Xray",
"restartSuccess": "Xray успешно перезапущен",
"restartOutputTitle": "Вывод перезапуска Xray",
"restartConfirmTitle": "Перезапустить xray?",
"restartConfirmContent": "Перезагружает сервис xray с сохранённой конфигурацией.",
"stopSuccess": "Xray успешно остановлен",
"restartError": "Произошла ошибка при перезапуске Xray.",
"stopError": "Произошла ошибка при остановке Xray.",
@@ -1471,7 +1354,6 @@
"generalConfigsDesc": "Эти параметры описывают общие настройки",
"logConfigs": "Лог",
"logConfigsDesc": "Логи могут замедлять работу сервера. Включайте только нужные вам виды логов при необходимости!",
"blockConfigsDesc": "Настройте, чтобы клиенты не имели доступа к определенным протоколам",
"basicRouting": "Базовые соединения",
"blockConnectionsConfigsDesc": "Эти параметры будут блокировать трафик в зависимости от страны назначения.",
"directConnectionsConfigsDesc": "Прямое соединение означает, что определенный трафик не будет перенаправлен через другой сервер.",
@@ -1481,10 +1363,6 @@
"directdomains": "Прямые домены",
"ipv4Routing": "Правила IPv4",
"ipv4RoutingDesc": "Эти параметры позволят клиентам маршрутизироваться к целевым доменам только через IPv4",
"warpRouting": "Правила WARP",
"warpRoutingDesc": " Эти опции будут направлять трафик в зависимости от конкретного пункта назначения через WARP.",
"nordRouting": "Маршрутизация NordVPN",
"nordRoutingDesc": "Эти опции будут направлять трафик в зависимости от конкретного пункта назначения через NordVPN.",
"Template": "Шаблон конфигурации Xray",
"TemplateDesc": "На основе шаблона создаётся конфигурационный файл Xray.",
"FreedomStrategy": "Настройка стратегии протокола Freedom",
@@ -1498,10 +1376,7 @@
"outboundTestUrlDesc": "URL для проверки подключения исходящего",
"Torrent": "Заблокировать BitTorrent",
"Inbounds": "Входящие",
"InboundsDesc": "Изменение шаблона конфигурации для подключения определенных клиентов",
"Outbounds": "Исходящие",
"OutboundSubscriptions": "Подписки исходящих",
"OutboundSubscriptionsDesc": "Импорт исходящих из удалённых URL подписок (vmess/vless/trojan/ss/...). Теги остаются неизменными для использования в балансировщиках и правилах маршрутизации. Обновление выполняется автоматически.",
"Balancers": "Балансировщик",
"balancerTagRequired": "Тег обязателен",
"balancerSelectorRequired": "Выберите хотя бы одно исходящее",
@@ -1520,9 +1395,7 @@
"routeTesterMatchedOutbound": "Совпавший исходящий",
"routeTesterViaBalancer": "через балансировщик",
"routeTesterDefaultOutbound": "Ни одно правило маршрутизации не совпало — трафик направляется в исходящий по умолчанию (первый).",
"OutboundsDesc": "Изменение шаблона конфигурации, чтобы определить исходящие подключения для этого сервера",
"Routings": "Маршрутизация",
"RoutingsDesc": "Важен приоритет каждого правила!",
"completeTemplate": "Все",
"logLevel": "Уровень логов",
"logLevelDesc": "Уровень журнала для журналов ошибок, указывающий информацию, которую необходимо записать.",
@@ -1536,13 +1409,9 @@
"maskAddressDesc": "При активации реальный IP-адрес заменяется на маскировочный в логах.",
"statistics": "Статистика",
"statsInboundUplink": "Статистика входящего аплинка",
"statsInboundUplinkDesc": "Включает сбор статистики для исходящего трафика всех входящих прокси.",
"statsInboundDownlink": "Статистика входящего даунлинка",
"statsInboundDownlinkDesc": "Включает сбор статистики для входящего трафика всех входящих прокси.",
"statsOutboundUplink": "Статистика исходящего аплинка",
"statsOutboundUplinkDesc": "Включает сбор статистики для исходящего трафика всех исходящих прокси.",
"statsOutboundDownlink": "Статистика исходящего даунлинка",
"statsOutboundDownlinkDesc": "Включает сбор статистики для входящего трафика всех исходящих прокси.",
"connectionLimits": "Ограничения соединения",
"connectionLimitsDesc": "Политики уровня соединения для пользователей уровня 0. Оставьте поле пустым, чтобы использовать значение Xray по умолчанию.",
"connIdle": "Тайм-аут простоя",
@@ -1552,18 +1421,10 @@
"bufferSizePlaceholder": "авто",
"seconds": "секунд",
"rules": {
"first": "Первый",
"last": "Последний",
"up": "Поднять вверх",
"down": "Опустить вниз",
"source": "Источник",
"dest": "Пункт назначения",
"inbound": "Входящее подключение",
"outbound": "Исходящее подключение",
"balancer": "Балансировщик",
"info": "Инфо",
"add": "Создать правило",
"edit": "Редактировать правило",
"useComma": "Элементы, разделённые запятыми"
},
"routing": {
@@ -1604,7 +1465,6 @@
"ruleN": "Правило {n}",
"action": "Действие",
"redirect": "Redirect",
"fragment": "Fragment",
"finalRules": "Финальные правила",
"overrideXrayPrivateIp": "Переопределить дефолтный блок частных IP в Xray",
"blockDelay": "Задержка блока (мс)",
@@ -1630,43 +1490,17 @@
"keepAliveInterval": "Интервал keep alive",
"markFwmark": "Mark (fwmark)",
"interface": "Интерфейс",
"ipv6Only": "Только IPv6",
"acceptProxyProtocol": "Принимать proxy protocol",
"proxyProtocol": "Proxy protocol",
"tcpUserTimeoutMs": "TCP user timeout (мс)",
"tcpKeepAliveIdleS": "TCP keep-alive idle (с)"
},
"outbound": {
"addOutbound": "Создать исходящее подключение",
"addReverse": "Создать реверс-прокси",
"editOutbound": "Изменить исходящее подключение",
"editReverse": "Редактировать реверс-прокси",
"reverseTag": "Тег реверс-прокси",
"reverseTagDesc": "Тег исходящего подключения для простого реверс-прокси VLESS. Оставьте пустым для отключения.",
"reverseTagPlaceholder": "тег исходящего (пусто = отключено)",
"tag": "Тег",
"tagDesc": "Уникальный тег",
"address": "Адрес",
"egress": "Выход",
"egressHint": "Запустите HTTP-тест, чтобы показать выходной IP и страну.",
"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 probe. HTTP: полный запрос через xray. Реальная задержка: полное время с установлением соединения.",
"testAll": "Тестировать все",
@@ -1674,14 +1508,10 @@
"breakdownConnect": "Подключение к прокси",
"breakdownTls": "TLS через исходящий",
"breakdownTtfb": "Первый байт",
"nordvpn": "NordVPN",
"accessToken": "Токен доступа",
"country": "Страна",
"server": "Сервер",
"city": "Город",
"allCities": "Все города",
"privateKey": "Приватный ключ",
"load": "Нагрузка",
"moveToTop": "Переместить наверх"
},
"outboundSub": {
@@ -1711,16 +1541,11 @@
"active": "Активные подписки",
"empty": "Подписок пока нет. Добавьте одну выше.",
"colRemark": "Примечание",
"colPrefix": "Префикс",
"colInterval": "Интервал",
"colLastFetch": "Последнее обновление",
"colEnabled": "Включено",
"auto": "авто",
"never": "никогда",
"yes": "Да",
"no": "Нет",
"refreshNow": "Обновить сейчас",
"lastError": "Последняя ошибка",
"deleteConfirm": "Удалить эту подписку?",
"restartHint": "После добавления или обновления перезапустите Xray (или дождитесь следующей автоперезагрузки), чтобы исходящие стали активными.",
"fromSubsTitle": "Из подписок исходящих (только для чтения)",
@@ -1737,8 +1562,6 @@
"tabBalancerSettings": "Настройки балансировщика",
"tabObservatory": "Обсерватория",
"observatory": {
"title": "Обсерватория",
"burstTitle": "Burst-обсерватория",
"autoManaged": "Наблюдатели управляются автоматически на основе ваших балансировщиков. Ниже можно настроить, как они опрашивают; отслеживаемые исходящие следуют за селекторами балансировщика.",
"emptyHint": "Нет активного наблюдателя соединений. Он добавляется автоматически при создании балансировщика Least Ping или Least Load — либо Random / Round-robin с fallback — чтобы балансировщики с наблюдателем могли проверять состояние исходящих перед выбором цели.",
"mixedLegacy": "В этой конфигурации одновременно есть Observatory и Burst Observatory. Xray использует один глобальный наблюдатель, поэтому такое устаревшее смешанное состояние не поддерживается; сохранение балансировщиков нормализует его до одного наблюдателя.",
@@ -1772,12 +1595,8 @@
"balancerRemoved": "Балансировщик {tag} — удалён (не осталось целей)"
},
"balancer": {
"addBalancer": "Создать балансировщик",
"editBalancer": "Редактировать балансировщик",
"balancerStrategy": "Стратегия",
"balancerSelectors": "Селекторы",
"tag": "Тег",
"tagDesc": "Уникальный тег",
"tagDuplicate": "Тег уже используется другим балансировщиком",
"tagPlaceholder": "уникальный тег балансировщика",
"selector": "Селектор",
@@ -1789,7 +1608,6 @@
"tolerance": "Допуск",
"baselines": "Baselines",
"costs": "Costs",
"balancerDesc": "Невозможно одновременно использовать balancerTag и outboundTag. При одновременном использовании будет работать только outboundTag.",
"costMatch": "Шаблон тега",
"costValue": "Вес",
"costRegexp": "Совпадение по регулярному выражению",
@@ -1804,14 +1622,10 @@
"publicKey": "Публичный ключ",
"allowedIPs": "Разрешенные IP-адреса",
"endpoint": "Конечная точка",
"psk": "Общий ключ",
"domainStrategy": "Стратегия домена"
},
"tun": {
"nameDesc": "Имя интерфейса TUN. Значение по умолчанию - 'xray0'",
"mtuDesc": "Максимальная единица передачи. Максимальный размер пакетов данных. Значение по умолчанию - 1500",
"userLevel": "Уровень пользователя",
"userLevelDesc": "Все соединения, установленные через этот входящий поток, будут использовать этот уровень пользователя. Значение по умолчанию - 0"
"userLevel": "Уровень пользователя"
},
"nord": {
"accessToken": "Access token",
@@ -1896,7 +1710,6 @@
},
"fakedns": {
"add": "Создать Fake DNS",
"edit": "Редактировать Fake DNS",
"ipPool": "Подсеть пула IP",
"poolSize": "Размер пула"
},
@@ -2032,7 +1845,6 @@
"add": "Добавить",
"month": "Месяц",
"months": "Месяцев",
"day": "День",
"days": "Дней",
"hours": "Часов",
"minutes": "Минуты",
@@ -2071,7 +1883,6 @@
"userSaved": "✅ Пользователь Telegram сохранен.",
"loginSuccess": "✅ Успешный вход в панель.\r\n",
"loginFailed": "❗️ Ошибка входа в панель.\r\n",
"2faFailed": "Ошибка 2FA",
"report": "🕰 Запланированные отчеты: {{ .RunTime }}\r\n",
"datetime": "⏰ Дата и время: {{ .DateTime }}\r\n",
"hostname": "💻 Хост: {{ .Hostname }}\r\n",
@@ -2104,7 +1915,6 @@
"download": "🔽 Загрузка: ↓{{ .Download }}\r\n",
"total": "📊 Всего: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
"TGUser": "👤 Telegram User ID: {{ .TelegramID }}\r\n",
"exhaustedMsg": "🚨 Исчерпаны {{ .Type }}:\r\n",
"exhaustedCount": "🚨 Количество исчерпанных {{ .Type }}:\r\n",
"onlinesCount": "🌐 Клиентов онлайн: {{ .Count }}\r\n",
"disabled": "🛑 Отключено: {{ .Disabled }}\r\n",
@@ -2113,16 +1923,10 @@
"refreshedOn": "\r\n📋🔄 Обновлено: {{ .Time }}\r\n\r\n",
"yes": "✅ Да",
"no": "❌ Нет",
"received_id": "🔑📥 ID обновлён.",
"received_password": "🔑📥 Пароль обновлён.",
"received_email": "📧📥 Email обновлен.",
"received_comment": "💬📥 Комментарий обновлён.",
"id_prompt": "🔑 Стандартный ID: {{ .ClientId }}\n\nВведите ваш ID.",
"pass_prompt": "🔑 Стандартный пароль: {{ .ClientPassword }}\n\nВведите ваш пароль.",
"email_prompt": "📧 Стандартный email: {{ .ClientEmail }}\n\nВведите ваш email.",
"comment_prompt": "💬 Стандартный комментарий: {{ .ClientComment }}\n\nВведите ваш комментарий.",
"inbound_client_data_id": "🔄 Входящие подключения: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Срок действия: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в входящее подключение!",
"inbound_client_data_pass": "🔄 Входящие подключения: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Срок действия: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в входящее подключение!",
"cancel": "❌ Процесс отменён! \n\nВы можете снова начать с /start в любое время. 🔄",
"error_add_client": "⚠️ Ошибка:\n\n {{ .error }}",
"using_default_value": "Используется значение по умолчанию👌",
@@ -2139,8 +1943,6 @@
"eventXrayCrashError": "Ошибка: {{ .Error }}",
"eventNodeDown": "Узел {{ .Name }} НЕДОСТУПЕН",
"eventNodeUp": "Узел {{ .Name }} В СЕТИ",
"eventCPUHigh": "Высокая загрузка CPU",
"eventCPUHighDetail": "CPU: {{ .Detail }}",
"eventLoginFallback": "Неудачный вход с {{ .Source }}",
"memoryThreshold": "🔴 Использование памяти {{ .Percent }}% превышает пороговое значение {{ .Threshold }}%"
},
@@ -2181,11 +1983,8 @@
"submitDisable": "Добавить отключенным ☑️",
"submitEnable": "Добавить включенным ✅",
"use_default": "🏷️ Использовать по умолчанию",
"change_id": "⚙️🔑 ID",
"change_password": "⚙️🔑 Пароль",
"change_email": "⚙️📧 Email",
"change_comment": "⚙️💬 Комментарий",
"change_flow": "⚙️🚦 Flow",
"ResetAllTraffics": "Сбросить весь трафик",
"SortedTrafficUsageReport": "Отсортированный отчет об использовании трафика"
},
@@ -2214,31 +2013,16 @@
}
},
"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": "НЕУДАЧНО",