精简版第四轮补裁(P4): 页面层摘除 + Xray更新端点下线 + 本机核心监管下线

页面层(用户真机截图发现前两轮漏裁):
- 设置: 摘除 Telegram机器人/邮件菜单与页面, 及页内残留入口(通知页/外部流量/LDAP/2FA设置页)
- Xray配置: 摘除负载均衡/DNS/高级配置菜单与页面; 基础配置(出站+路由)完好
- 总览: 摘除 Xray更新弹窗(VersionModal+GeodataSection)全部入口, 版本号改为静态展示
- 13个locale同步摘除461个已删功能专属翻译键(逐键核查前后端引用为零; i18n-dead-keys测试全绿)

Xray更新后端(经调查确认仅服务本机bin/xray, 与agent下发/订阅无关):
- 删除 getXrayVersion/installXray/updateGeofile 路由与handler(访问返回404)
- 删除 ServerService 对应实现与校验和函数; 同步api-docs/monitor白名单/openapi

本机核心监管下线(设计: 主控永不运行本机xray, 入站全在agent):
- XrayService.RestartXray 降级为no-op(一次性Warning说明日志); StopXray无进程时幂等返回
- web.go 摘除启动拉起本机核心/CheckXrayRunning看门狗(1s)/ApplyPendingRestart cron(30s)/XrayTrafficJob/CheckClientIpJob 注册
- ApplyPendingRestart 降级为消费即清, 其测试更新为新语义
- XrayMetricsService.Sample 短路: 不再每2s探本机/debug/vars, 状态优雅置为不可用
- 配置生成(纯JSON)/agent链路/订阅/入站CRUD未动; 状态读数优雅归零(stop/Unknown)

注: TestGetXrayConfig_EnabledClientsStillEmitted 在基线945b3a5同样失败(既有问题, 非本轮引入)
This commit is contained in:
Muse
2026-10-20 14:58:05 +00:00
parent 945b3a56a2
commit 4828f946b1
56 changed files with 149 additions and 11458 deletions
+4 -466
View File
@@ -67,16 +67,12 @@
"success": "Успешно",
"lastOnline": "Был(а) в сети",
"lastSubFetch": "Последнее получение подписки",
"getVersion": "Узнать версию",
"install": "Установка",
"clients": "Клиенты",
"usage": "Использование",
"twoFactorCode": "Код 2FA",
"remained": "Остаток",
"security": "Безопасность",
"emptyDnsDesc": "Нет добавленных DNS-серверов.",
"emptyFakeDnsDesc": "Нет добавленных Fake DNS-серверов.",
"emptyBalancersDesc": "Нет добавленных балансировщиков.",
"somethingWentWrong": "Что-то пошло не так",
"subscription": {
"title": "Информация о подписке",
@@ -86,7 +82,6 @@
"uploaded": "Отправлено",
"expiry": "Срок действия",
"totalQuota": "Общий лимит",
"individualLinks": "Индивидуальные ссылки",
"active": "Активна",
"inactive": "Неактивна",
"unlimited": "Неограниченно",
@@ -136,9 +131,6 @@
"xrayStatus": "Xray",
"stopXray": "Стоп",
"restartXray": "Перезапуск",
"xraySwitch": "Выбор версии",
"xrayUpdates": "Обновления Xray",
"xraySwitchClickDesk": "Важно: старые версии могут не поддерживать текущие настройки",
"updatePanel": "Обновить панель",
"panelUpdateDesc": "Это обновит 3X-UI до последнего релиза и перезапустит сервис панели.",
"currentPanelVersion": "Текущая версия панели",
@@ -200,9 +192,6 @@
"download": "Скачать",
"sent": "Отправлено",
"received": "Получено",
"xraySwitchVersionDialog": "Переключить версию Xray",
"xraySwitchVersionDialogDesc": "Вы точно хотите сменить версию Xray?",
"xraySwitchVersionPopover": "Xray успешно обновлён",
"panelUpdateDialog": "Вы действительно хотите обновить панель?",
"panelUpdateDialogDesc": "Это обновит 3X-UI до версии #version# и перезапустит сервис панели.",
"panelUpdateStartedPopover": "Обновление панели началось",
@@ -210,24 +199,6 @@
"panelUpdateFailedDesc": "Обновление не завершилось успешно. Проверьте журналы сервера или выполните 'x-ui update' в командной строке.",
"panelUpdateUnknownTitle": "Не удалось подтвердить завершение обновления",
"panelUpdateUnknownDesc": "Панель не сообщила результат вовремя. Перезагрузите страницу, чтобы проверить текущую версию, или проверьте журналы сервера.",
"geofileUpdateDialog": "Вы действительно хотите обновить геофайл?",
"geofileUpdateDialogDesc": "Это обновит файл #filename#.",
"geofilesUpdateDialogDesc": "Это обновит все геофайлы.",
"geofilesUpdateAll": "Обновить все",
"geofileUpdatePopover": "Геофайлы успешно обновлены",
"geodataTitle": "Автообновление Geodata",
"geodataHint": "Xray скачивает эти файлы по расписанию и перезагружает их без перезапуска. URL должны быть HTTPS. Файл должен уже существовать в папке bin, прежде чем Xray сможет его обновлять.",
"geodataCron": "Расписание (cron)",
"geodataOutbound": "Скачивать через outbound (необязательно)",
"geodataFile": "Имя файла",
"geodataAddFile": "Добавить файл",
"geodataSaveRestart": "Сохранить и перезапустить Xray",
"geodataConfirmTitle": "Сохранить настройки geodata?",
"geodataConfirmContent": "Шаблон конфигурации Xray будет обновлён, а Xray перезапущен.",
"geodataInvalidUrl": "Для каждого файла нужен HTTPS URL.",
"geodataInvalidFile": "Имя файла должно быть простым, например geosite_custom.dat (без путей).",
"geodataInvalidCron": "Cron должен содержать 5 полей, напр. 0 4 * * *",
"geodataEmpty": "Файлы не настроены. В правилах маршрутизации файлы указываются как ext:geosite_custom.dat:category.",
"dontRefresh": "Установка в процессе. Не обновляйте страницу",
"logs": "Логи",
"accessLogs": "Логи доступа",
@@ -1082,7 +1053,6 @@
"warnDefaultBasePath": "Базовый путь по умолчанию \"/\" широко известен — измените его на случайный.",
"warnDefaultSubPath": "Путь подписки по умолчанию \"/sub/\" широко известен — измените его.",
"warnDefaultJsonPath": "JSON-путь подписки по умолчанию \"/json/\" широко известен — измените его.",
"TGBotSettings": "Telegram-бот",
"panelListeningIP": "IP-адрес для управления панелью",
"panelListeningIPDesc": "Оставьте пустым для подключения с любого IP",
"panelListeningDomain": "Домен панели",
@@ -1107,43 +1077,12 @@
"currentPassword": "Текущий пароль",
"newUsername": "Новый логин",
"newPassword": "Новый пароль",
"telegramBotEnable": "Включить Telegram бота",
"telegramBotEnableDesc": "Доступ к функциям панели через Telegram-бота",
"telegramToken": "Telegram-токен",
"telegramTokenDesc": "Необходимо получить токен у менеджера ботов Telegram {'@'}botfather",
"telegramProxy": "SOCKS-прокси",
"telegramProxyDesc": "Если для подключения к Telegram вам нужен прокси Socks5, настройте его параметры согласно руководству.",
"telegramAPIServer": "Telegram API Server",
"telegramAPIServerDesc": "Используемый API-сервер Telegram. Оставьте пустым, чтобы использовать сервер по умолчанию.",
"telegramChatId": "User ID администратора бота",
"telegramChatIdDesc": "Один или несколько User ID администратора(-ов) Telegram-бота. Для получения User ID используйте {'@'}userinfobot или команду '/id' в боте.",
"telegramNotifyTime": "Частота уведомлений для администраторов от бота",
"telegramNotifyTimeDesc": "Как часто бот Telegram отправляет периодические отчёты. Выберите готовый интервал или «Произвольный», чтобы ввести выражение crontab.",
"notifyTime": {
"every": "@every — повторять с интервалом",
"hourly": "@hourly — каждый час",
"daily": "@daily — каждый день в 00:00",
"weekly": "@weekly — каждую неделю",
"monthly": "@monthly — каждый месяц",
"custom": "Произвольный (crontab)",
"seconds": "Секунды",
"minutes": "Минуты",
"hours": "Часы",
"interval": "Интервал",
"unit": "Единица"
},
"tgNotifyBackup": "Резервное копирование базы данных",
"tgNotifyBackupDesc": "Отправлять уведомление с файлом резервной копии базы данных",
"tgNotifyLogin": "Уведомление о входе",
"tgNotifyLoginDesc": "Отображает имя пользователя, IP-адрес и время, когда кто-то пытается войти в вашу панель.",
"sessionMaxAge": "Продолжительность сессии",
"sessionMaxAgeDesc": "Продолжительность сессии в системе (значение: минута)",
"expireTimeDiff": "Задержка уведомления об истечении сессии",
"expireTimeDiffDesc": "Получение уведомления об истечении срока действия сессии до достижения порогового значения (значение: день)",
"trafficDiff": "Порог трафика для уведомления",
"trafficDiffDesc": "Получение уведомления об исчерпании трафика до достижения порога (значение: ГБ)",
"tgNotifyCpu": "Порог нагрузки на ЦП для уведомления",
"tgNotifyCpuDesc": "Уведомление администраторов в Telegram, если нагрузка на ЦП превышает этот порог (значение: %)",
"timeZone": "Часовой пояс",
"timeZoneDesc": "Запланированные задачи выполняются в соответствии со временем в этом часовом поясе",
"subSettings": "Подписка",
@@ -1208,10 +1147,6 @@
"subEncryptDesc": "Шифровать возвращенные конфиги в подписке",
"subURI": "URI обратного прокси",
"subURIDesc": "Полный базовый URL (schema://домен[:порт]/путь/) для ссылки подписки и QR-кода вместо «Домена прослушивания»/«Порта подписки». Заполните, если подписка доступна через reverse-proxy или на другом домене/порту.",
"externalTrafficInformEnable": "Информация о внешнем трафике",
"externalTrafficInformEnableDesc": "Уведомлять внешний API при каждом обновлении трафика.",
"externalTrafficInformURI": "URI информации о внешнем трафике",
"externalTrafficInformURIDesc": "Обновления трафика отправляются на этот URI",
"restartXrayOnClientDisable": "Перезапускать Xray после автоотключения",
"restartXrayOnClientDisableDesc": "Когда клиент автоматически отключается из-за окончания срока действия или лимита трафика, перезапускать Xray.",
"fragment": "Фрагментация",
@@ -1221,38 +1156,6 @@
"noisesSett": "Настройки Noises",
"trustedProxyCidrs": "Доверенные CIDR прокси",
"trustedProxyCidrsDesc": "IP/CIDR через запятую, которым разрешено устанавливать заголовки forwarded host, proto и client IP.",
"ldap": {
"enable": "Включить LDAP-синхронизацию",
"host": "LDAP-хост",
"port": "Порт LDAP",
"useTls": "Использовать TLS (LDAPS)",
"skipTlsVerify": "Пропустить проверку сертификата TLS",
"skipTlsVerifyDesc": "Небезопасно — отключает проверку сертификата сервера. Используйте только с внутренними/недоверенными CA.",
"bindDn": "Bind DN",
"passwordConfigured": "Настроено; оставьте пустым, чтобы сохранить текущий пароль.",
"passwordUnconfigured": "Не настроено.",
"passwordPlaceholder": "Настроено — введите новое значение для замены",
"baseDn": "Base DN",
"userFilter": "Фильтр пользователя",
"userAttr": "Атрибут пользователя (username/email)",
"vlessField": "Атрибут VLESS-флага",
"flagField": "Общий атрибут флага (опц.)",
"flagFieldDesc": "Если задано, переопределяет флаг VLESS — напр. shadowInactive.",
"truthyValues": "Truthy-значения",
"truthyValuesDesc": "Через запятую; по умолчанию: true,1,yes,on",
"invertFlag": "Инвертировать флаг",
"invertFlagDesc": "Включите, когда атрибут означает «отключено» (напр. shadowInactive).",
"syncSchedule": "Расписание синхронизации",
"syncScheduleDesc": "Строка типа cron, напр. @every 1m",
"inboundTags": "Теги входящих",
"inboundTagsDesc": "Входящие, на которых LDAP-синхронизация может авто-создавать или авто-удалять клиентов.",
"noInbounds": "Входящие не найдены. Сначала создайте входящий.",
"autoCreate": "Авто-создание клиентов",
"autoDelete": "Авто-удаление клиентов",
"defaultTotalGb": "Объём по умолчанию (ГБ)",
"defaultExpiryDays": "Срок по умолчанию (дни)",
"defaultIpLimit": "Лимит IP по умолчанию"
},
"subFormats": {
"finalMask": "Final Mask",
"finalMaskDesc": "Добавляет TCP/UDP-маски finalmask Xray и параметры QUIC в каждый созданный профиль Xray JSON. Требуется приложение с поддержкой подписок Xray JSON и свежая версия ядра Xray.",
@@ -1276,31 +1179,15 @@
"muxSett": "Настройки Mux",
"direct": "Прямое подключение",
"directDesc": "Устанавливает прямые соединения с доменами или IP-адресами определённой страны.",
"notifications": "Уведомления",
"certs": "Сертификаты",
"externalTraffic": "Внешний трафик",
"dateAndTime": "Дата и время",
"proxyAndServer": "Прокси и сервер",
"intervals": "Интервалы",
"information": "Информация",
"profile": "Профиль",
"language": "Язык интерфейса",
"telegramBotLanguage": "Язык Telegram-бота",
"security": {
"admin": "Учетные данные администратора",
"twoFactor": "Двухфакторная аутентификация",
"twoFactorEnable": "Включить 2FA",
"twoFactorEnableDesc": "Добавляет дополнительный уровень аутентификации для повышения безопасности.",
"twoFactorModalSetTitle": "Включить двухфакторную аутентификацию",
"twoFactorModalDeleteTitle": "Отключить двухфакторную аутентификацию",
"twoFactorModalSteps": "Для настройки двухфакторной аутентификации выполните несколько шагов:",
"twoFactorModalFirstStep": "1. Отсканируйте этот QR-код в приложении для аутентификации или скопируйте токен рядом с QR-кодом и вставьте его в приложение",
"twoFactorModalSecondStep": "2. Введите код из приложения",
"twoFactorModalRemoveStep": "Введите код из приложения, чтобы отключить двухфакторную аутентификацию.",
"twoFactorModalChangeCredentialsTitle": "Изменить учетные данные",
"twoFactorModalChangeCredentialsStep": "Введите код из приложения, чтобы изменить учетные данные администратора.",
"twoFactorModalSetSuccess": "Двухфакторная аутентификация была успешно установлена",
"twoFactorModalDeleteSuccess": "Двухфакторная аутентификация была успешно удалена",
"twoFactorModalError": "Неверный код",
"show": "Показать",
"hide": "Скрыть",
@@ -1323,36 +1210,6 @@
"getOutboundTrafficError": "Ошибка получения трафика исходящего подключения",
"resetOutboundTrafficError": "Ошибка сброса трафика исходящего подключения"
},
"smtpSettings": "Настройки SMTP",
"smtpEnable": "Включить уведомления по Email",
"smtpEnableDesc": "Включить уведомления по email через SMTP",
"smtpHost": "SMTP хост",
"smtpHostDesc": "Имя хоста SMTP сервера (например smtp.gmail.com)",
"smtpPort": "SMTP порт",
"smtpPortDesc": "Порт SMTP сервера (по умолчанию: 587)",
"smtpUsername": "SMTP логин",
"smtpUsernameDesc": "Логин для аутентификации SMTP",
"smtpFrom": "Адрес отправителя (From)",
"smtpFromDesc": "Адрес в заголовке From письма. Оставьте пустым, чтобы использовать имя пользователя.",
"smtpFromName": "Имя отправителя (From)",
"smtpFromNameDesc": "Необязательное отображаемое имя перед адресом в заголовке From.",
"smtpPassword": "SMTP пароль",
"smtpPasswordDesc": "Пароль для аутентификации SMTP",
"smtpTo": "Получатели",
"smtpToDesc": "Адреса получателей через запятую",
"emailSettings": "Email",
"emailNotifications": "Уведомления",
"smtpEventBusNotify": "Email уведомления о событиях",
"smtpEventBusNotifyDesc": "Выберите события для email уведомлений",
"tgEventBusNotify": "Telegram уведомления о событиях",
"tgEventBusNotifyDesc": "Выберите события для Telegram уведомлений",
"testSmtp": "Отправить тестовое письмо",
"testTgBot": "Отправить тестовое сообщение",
"eventGroupOutbound": "Исходящие",
"eventGroupXray": "Ядро Xray",
"eventGroupSystem": "Система",
"eventGroupSecurity": "Безопасность",
"eventGroupNode": "Узлы",
"eventOutboundDown": "Недоступен",
"eventOutboundUp": "Работает",
"eventXrayCrash": "Сбой",
@@ -1360,36 +1217,7 @@
"eventNodeUp": "В сети",
"eventCPUHigh": "Превышение порога CPU (%)",
"requestFailed": "Запрос не удался",
"smtpEncryption": "Шифрование",
"smtpEncryptionDesc": "Метод шифрования SMTP соединения",
"smtpEncryptionNone": "Нет (открытый текст)",
"smtpEncryptionStartTLS": "STARTTLS",
"smtpEncryptionTLS": "TLS (неявное)",
"smtpStageConnect": "Подключение",
"smtpStageAuth": "Аутентификация",
"smtpStageSend": "Отправка",
"smtpTestSuccess": "Тестовое письмо отправлено успешно",
"smtpHostNotConfigured": "SMTP хост не настроен",
"smtpNoRecipients": "Получатели не настроены",
"smtpFromNotConfigured": "Адрес отправителя SMTP не настроен",
"eventLoginAttempt": "Попытка входа",
"telegramTokenConfigured": "Настроен; оставьте пустым для сохранения текущего токена.",
"telegramTokenPlaceholder": "Настроен - введите новый токен для замены",
"smtpPasswordConfigured": "Настроен; оставьте пустым для сохранения текущего пароля.",
"smtpPasswordPlaceholder": "Настроен - введите новый пароль для замены",
"smtpNotInitialized": "SMTP не инициализирован",
"tgBotNotEnabled": "Telegram бот не включен",
"tgTestFailed": "Тест Telegram не удался",
"tgTestSuccess": "Тестовое сообщение отправлено в Telegram",
"tgBotNotRunning": "Telegram бот не запущен",
"smtpErrorAuth": "Ошибка аутентификации — проверьте логин и пароль",
"smtpErrorStarttls": "Сервер требует STARTTLS — измените тип шифрования",
"smtpErrorTls": "Сервер требует TLS — измените тип шифрования",
"smtpErrorRefused": "Соединение отклонено — проверьте хост и порт",
"smtpErrorTimeout": "Таймаут соединения — хост недоступен",
"smtpErrorRelay": "Сервер отклоняет отправку с этого адреса",
"smtpErrorEof": "Соединение закрыто сервером",
"smtpErrorUnknown": "Ошибка SMTP: {{ .Error }}",
"eventMemoryHigh": "Превышение порога памяти (%)",
"remarkTemplate": "Шаблон примечания",
"remarkTemplateDesc": "Если задан, заменяет модель примечания для каждой ссылки подписки — задайте собственный формат с помощью токенов переменных (используйте кнопку для их вставки). Оставьте пустым, чтобы использовать модель выше.",
@@ -1483,8 +1311,6 @@
"directdomains": "Прямые домены",
"ipv4Routing": "Правила IPv4",
"ipv4RoutingDesc": "Эти параметры позволят клиентам маршрутизироваться к целевым доменам только через IPv4",
"Template": "Шаблон конфигурации Xray",
"TemplateDesc": "На основе шаблона создаётся конфигурационный файл Xray.",
"FreedomStrategy": "Настройка стратегии протокола Freedom",
"FreedomStrategyDesc": "Установка стратегии вывода сети в протоколе Freedom",
"FreedomHappyEyeballs": "Freedom Happy Eyeballs (IPv4/IPv6)",
@@ -1500,11 +1326,6 @@
"Balancers": "Балансировщик",
"balancerTagRequired": "Тег обязателен",
"balancerSelectorRequired": "Выберите хотя бы одно исходящее",
"balancerLive": "Текущая цель",
"balancerOverride": "Переопределить",
"balancerOverridePh": "Авто (стратегия)",
"balancerLiveRefresh": "Обновить состояние балансировщика",
"balancerNotRunning": "Этот балансировщик неактивен в запущенном Xray — сохраните изменения или запустите Xray",
"routeTester": "Тест маршрута",
"routeTesterDesc": "Спросите запущенный Xray, через какой исходящий будет обработано соединение. Трафик не отправляется — решение поступает напрямую от живого движка маршрутизации.",
"routeTesterDest": "Домен или IP",
@@ -1516,7 +1337,6 @@
"routeTesterViaBalancer": "через балансировщик",
"routeTesterDefaultOutbound": "Ни одно правило маршрутизации не совпало — трафик направляется в исходящий по умолчанию (первый).",
"Routings": "Маршрутизация",
"completeTemplate": "Все",
"logLevel": "Уровень логов",
"logLevelDesc": "Уровень журнала для журналов ошибок, указывающий информацию, которую необходимо записать.",
"accessLog": "Логи доступа",
@@ -1544,7 +1364,6 @@
"source": "Источник",
"dest": "Пункт назначения",
"inbound": "Входящее подключение",
"balancer": "Балансировщик",
"useComma": "Элементы, разделённые запятыми"
},
"routing": {
@@ -1725,32 +1544,7 @@
"alreadyAdded": "Этот сервер уже в списке исходящих. Чтобы обновить ключ, нажмите {reset}.",
"provisionFailed": "Не удалось создать исходящее PIA. Попробуйте ещё раз."
},
"tabBalancerSettings": "Настройки балансировщика",
"tabObservatory": "Обсерватория",
"observatory": {
"autoManaged": "Наблюдатели управляются автоматически на основе ваших балансировщиков. Ниже можно настроить, как они опрашивают; отслеживаемые исходящие следуют за селекторами балансировщика.",
"emptyHint": "Нет активного наблюдателя соединений. Он добавляется автоматически при создании балансировщика Least Ping или Least Load — либо Random / Round-robin с fallback — чтобы балансировщики с наблюдателем могли проверять состояние исходящих перед выбором цели.",
"mixedLegacy": "В этой конфигурации одновременно есть Observatory и Burst Observatory. Xray использует один глобальный наблюдатель, поэтому такое устаревшее смешанное состояние не поддерживается; сохранение балансировщиков нормализует его до одного наблюдателя.",
"subjectSelector": "Отслеживаемые исходящие",
"subjectSelectorDesc": "Теги исходящих, которые опрашивает этот наблюдатель. Управляется автоматически на основе ваших балансировщиков.",
"probeURL": "URL пробы",
"probeURLDesc": "URL, запрашиваемый для измерения каждого исходящего. Должен возвращать HTTP 204.",
"probeInterval": "Интервал пробы",
"probeIntervalDesc": "Как часто опрашивать каждый исходящий, например 30s, 1m, 2h45m.",
"enableConcurrency": "Параллельные пробы",
"enableConcurrencyDesc": "Опрашивать все отслеживаемые исходящие сразу, а не по одному. Быстрее, но заметнее в сети.",
"destination": "Назначение пробы",
"destinationDesc": "URL, запрашиваемый для измерения каждого исходящего. Должен возвращать HTTP 204.",
"connectivity": "Проверка связи",
"connectivityDesc": "Необязательный URL проверки локальной сети, используется только после сбоя назначения. Оставьте пустым, чтобы пропустить.",
"interval": "Интервал пробы",
"intervalDesc": "Среднее время между пробами для каждого исходящего, например 1m. Минимум 10s.",
"timeout": "Тайм-аут пробы",
"timeoutDesc": "Сколько ждать ответа на пробу, прежде чем считать её неуспешной, например 5s.",
"sampling": "Размер выборки",
"samplingDesc": "Сколько последних результатов проб хранится для оценки каждого исходящего.",
"httpMethod": "Метод HTTP",
"httpMethodDesc": "Метод HTTP, используемый для проб.",
"deleteAlsoObservatory": "Это последний балансировщик, использующий Observatory, поэтому он тоже будет удалён.",
"deleteAlsoBurst": "Это последний балансировщик, использующий Burst Observatory, поэтому он тоже будет удалён."
},
@@ -1762,25 +1556,7 @@
},
"balancer": {
"balancerStrategy": "Стратегия",
"tag": "Тег",
"tagDuplicate": "Тег уже используется другим балансировщиком",
"tagPlaceholder": "уникальный тег балансировщика",
"selector": "Селектор",
"fallback": "Fallback",
"cycleTooltip": "Цикл: {path} → (обратно к {start})",
"expected": "Ожидаемое",
"expectedPlaceholder": "оптимальное число узлов",
"maxRtt": "Макс. RTT",
"tolerance": "Допуск",
"baselines": "Baselines",
"costs": "Costs",
"costMatch": "Шаблон тега",
"costValue": "Вес",
"costRegexp": "Совпадение по регулярному выражению",
"balancerDeleteInUse": "Невозможно удалить этот балансировщик — он используется как запасной для: {names}",
"balancerFallbackCycle": "Невозможно назначить этот балансировщик запасным — это создаст циклическую зависимость.",
"balancerFallbackInfo": "Трафик будет маршрутизирован через: Балансировщик → Loopback → Сервер → Целевой балансировщик → Исходящее соединение. Это добавляет дополнительный хоп через сервер, что может вызвать небольшие задержки.",
"fallbackBalancerHint": "Выберите другой балансировщик в качестве запасного",
"reservedPrefix": "Префикс _bl_ зарезервирован для внутренних loopback-объектов балансеров"
},
"wireguard": {
@@ -1883,55 +1659,8 @@
"usage": "Использование",
"addOutbound": "Добавить исходящий"
},
"dns": {
"enable": "Включить DNS",
"enableDesc": "Включить встроенный DNS-сервер",
"tag": "Название тега DNS",
"tagDesc": "Этот тег будет доступен как входящий тег в правилах маршрутизации.",
"clientIp": "IP клиента",
"clientIpDesc": "Используется для уведомления сервера о указанном местоположении IP во время DNS-запросов",
"disableCache": "Отключить кэш",
"disableCacheDesc": "Отключает кэширование DNS",
"disableFallback": "Отключить резервный DNS",
"disableFallbackDesc": "Отключает резервные DNS-запросы",
"disableFallbackIfMatch": "Отключить резервный DNS при совпадении",
"disableFallbackIfMatchDesc": "Отключает резервные DNS-запросы при совпадении списка доменов DNS-сервера",
"enableParallelQuery": "Включить параллельные запросы",
"enableParallelQueryDesc": "Включить параллельные DNS-запросы к нескольким серверам для более быстрого разрешения",
"strategy": "Стратегия запроса",
"strategyDesc": "Общая стратегия разрешения доменных имен",
"add": "Создать DNS",
"edit": "Редактировать DNS",
"domains": "Домены",
"expectIPs": "Ожидаемые IP",
"unexpectIPs": "Неожидаемые IP",
"useSystemHosts": "Использовать системные Hosts",
"useSystemHostsDesc": "Использовать файл hosts из установленной системы",
"serveStale": "Использовать устаревшие",
"serveStaleDesc": "Возвращать устаревшие результаты из кэша во время обновления в фоне",
"serveExpiredTTL": "TTL устаревших",
"serveExpiredTTLDesc": "Срок действия (секунды) устаревших записей кэша; 0 = бессрочно",
"timeoutMs": "Тайм-аут (мс)",
"skipFallback": "Пропустить Fallback",
"finalQuery": "Финальный запрос",
"hosts": "Hosts",
"hostsAdd": "Добавить Host",
"hostsEmpty": "Host не определены",
"hostsDomain": "Домен (напр. domain:example.com)",
"hostsValues": "IP или домен — введите и нажмите Enter",
"usePreset": "Использовать шаблон",
"dnsPresetTitle": "Шаблоны DNS",
"dnsPresetFamily": "Семейный",
"clearAll": "Удалить все",
"clearAllTitle": "Удалить все DNS-серверы?",
"clearAllConfirm": "Все DNS-серверы будут удалены из списка. Это действие нельзя отменить.",
"dnsLeakWarning": "DNS может утекать через localhost, обычный UDP/TCP, локальный режим DoH/DoQ, fallback-запросы или EDNS client IP. Для приватности используйте маршрутизируемый DoH, закрепляйте резолверы в hosts и отключайте fallback."
},
"fakedns": {
"add": "Создать Fake DNS",
"ipPool": "Подсеть пула IP",
"poolSize": "Размер пула"
},
"dns": {},
"fakedns": {},
"defaultOutbound": "Исходящий по умолчанию",
"defaultOutboundDesc": "Трафик без совпадения с правилами маршрутизации идёт через этот исходящий (первый в списке)."
},
@@ -2055,198 +1784,7 @@
}
},
"tgbot": {
"keyboardClosed": "❌ Клавиатура закрыта.",
"noResult": "❗ Нет результатов.",
"noQuery": "❌ Запрос не найден. Пожалуйста, повторите команду.",
"wentWrong": "❌ Что-то пошло не так...",
"noIpRecord": "❗ Нет записей об IP-адресе.",
"noInbounds": "❗ У вас не настроено ни одного входящего подключения.",
"unlimited": "♾ Безлимит",
"add": "Добавить",
"month": "Месяц",
"months": "Месяцев",
"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": "❗ Пожалуйста, укажите email для поиска.",
"getID": "🆔 Ваш User ID: <code>{{ .ID }}</code>",
"helpAdminCommands": "🔃 Для перезапуска Xray Core:\r\n<code>/restart</code>\r\n\r\n🔎 Для поиска клиента по email:\r\n<code>/usage [Email]</code>\r\n\r\n📊 Для поиска входящих подключений (со статистикой клиентов):\r\n<code>/inbound [имя подключения]</code>\r\n\r\n🆔 Ваш Telegram User ID:\r\n<code>/id</code>",
"helpClientCommands": "💲 Для просмотра информации о вашей подписке используйте команду:\r\n<code>/usage [Email]</code>\r\n\r\n🆔 Ваш Telegram User ID:\r\n<code>/id</code>",
"restartUsage": "\r\n\r\n<code>/restart</code>",
"restartSuccess": "✅ Ядро Xray успешно перезапущено.",
"restartFailed": "❗ Ошибка при перезапуске Xray-core.\r\n\r\n<code>Ошибка: {{ .Error }}</code>.",
"xrayNotRunning": "❗ Xray Core не запущен.",
"startDesc": "Показать главное меню",
"helpDesc": "Справка по боту",
"statusDesc": "Проверить статус бота",
"idDesc": "Показать ваш Telegram ID",
"usageDesc": "Показать трафик клиента: /usage email",
"inboundDesc": "Поиск входящих: /inbound имя (админ)",
"restartDesc": "Перезапустить ядро Xray (админ)",
"clearallDesc": "Сбросить трафик всех клиентов (админ)"
},
"messages": {
"cpuThreshold": "Загрузка процессора составляет {{ .Percent }}%, что превышает пороговое значение {{ .Threshold }}%",
"selectUserFailed": "❌ Ошибка при выборе пользователя.",
"userSaved": "✅ Пользователь Telegram сохранен.",
"loginSuccess": "✅ Успешный вход в панель.\r\n",
"loginFailed": "❗️ Ошибка входа в панель.\r\n",
"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": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
"tcpCount": "🔹 TCP: {{ .Count }}\r\n",
"udpCount": "🔸 UDP: {{ .Count }}\r\n",
"traffic": "🚦 Трафик: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
"xrayStatus": "ℹ️ Статус: {{ .State }}\r\n",
"username": "👤 Имя пользователя: {{ .Username }}\r\n",
"reason": "❗️ Причина: {{ .Reason }}\r\n",
"time": "⏰ Время: {{ .Time }}\r\n",
"inbound": "📍 Входящий: {{ .Remark }}\r\n",
"port": "🔌 Порт: {{ .Port }}\r\n",
"expire": "📅 Дата окончания: {{ .Time }}\r\n",
"expireIn": "📅 Окончание через: {{ .Time }}\r\n",
"active": "💡 Активен: {{ .Enable }}\r\n",
"enabled": "🚨 Активен: {{ .Enable }}\r\n",
"online": "🌐 Статус соединения: {{ .Status }}\r\n",
"lastOnline": "🔙 Был(а) в сети: {{ .Time }}\r\n",
"email": "📧 Email: {{ .Email }}\r\n",
"upload": "🔼 Загрузка: ↑{{ .Upload }}\r\n",
"download": "🔽 Загрузка: ↓{{ .Download }}\r\n",
"total": "📊 Всего: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
"TGUser": "👤 Telegram User ID: {{ .TelegramID }}\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_email": "📧📥 Email обновлен.",
"received_comment": "💬📥 Комментарий обновлён.",
"email_prompt": "📧 Стандартный email: {{ .ClientEmail }}\n\nВведите ваш email.",
"comment_prompt": "💬 Стандартный комментарий: {{ .ClientComment }}\n\nВведите ваш комментарий.",
"cancel": "❌ Процесс отменён! \n\nВы можете снова начать с /start в любое время. 🔄",
"error_add_client": "⚠️ Ошибка:\n\n {{ .error }}",
"using_default_value": "Используется значение по умолчанию👌",
"incorrect_input": "Ваш ввод недействителен.\nФразы должны быть непрерывными без пробелов.\nПравильный пример: aaaaaa\nНеправильный пример: aaa aaa 🚫",
"AreYouSure": "Вы уверены? 🤔",
"SuccessResetTraffic": "📧 Почта: {{ .ClientEmail }}\n🏁 Результат: ✅ Успешно",
"FailedResetTraffic": "📧 Почта: {{ .ClientEmail }}\n🏁 Результат: ❌ Неудача \n\n🛠️ Ошибка: [ {{ .ErrorMessage }} ]",
"FinishProcess": "🔚 Сброс трафика завершён для всех клиентов.",
"eventOutboundDown": "Исходящее подключение {{ .Tag }} НЕДОСТУПНО",
"eventOutboundUp": "Исходящее подключение {{ .Tag }} РАБОТАЕТ",
"eventErrorDetail": "Ошибка: {{ .Error }}",
"eventDelayDetail": "Задержка: {{ .Delay }} мс",
"eventXrayCrash": "Сбой Xray",
"eventXrayCrashError": "Ошибка: {{ .Error }}",
"eventNodeDown": "Узел {{ .Name }} НЕДОСТУПЕН",
"eventNodeUp": "Узел {{ .Name }} В СЕТИ",
"eventLoginFallback": "Неудачный вход с {{ .Source }}",
"memoryThreshold": "🔴 Использование памяти {{ .Percent }}% превышает пороговое значение {{ .Threshold }}%"
},
"buttons": {
"closeKeyboard": "❌ Закрыть клавиатуру",
"cancel": "❌ Отмена",
"cancelReset": "❌ Отменить сброс",
"cancelIpLimit": "❌ Отменить лимит IP",
"confirmResetTraffic": "✅ Подтвердить сброс трафика?",
"confirmClearIps": "✅ Подтвердить очистку IP?",
"confirmRemoveTGUser": "✅ Подтвердить удаление пользователя Telegram?",
"confirmToggle": "✅ Подтвердить вкл/выкл пользователя?",
"dbBackup": "📂 Бэкап БД",
"serverUsage": "💻 Состояние сервера",
"getInbounds": "🔌 Входящие подключения",
"depleteSoon": "⚠️ Скоро конец",
"clientUsage": "Статистика клиента",
"onlines": "🟢 Онлайн",
"commands": "🖱️ Команды",
"refresh": "🔄 Обновить",
"clearIPs": "❌ Очистить IP",
"removeTGUser": "❌ Удалить пользователя Telegram",
"selectTGUser": "👤 Выбрать пользователя Telegram",
"selectOneTGUser": "👤 Выберите пользователя Telegram:",
"resetTraffic": "📈 Сбросить трафик",
"resetExpire": "📅 Изменить дату окончания",
"ipLog": "🔢 Лог IP",
"ipLimit": "🔢 Лимит IP",
"setTGUser": "👤 Установить пользователя Telegram",
"toggle": "🔘 Вкл./Выкл.",
"custom": "🔢 Своё",
"confirmNumber": "✅ Подтвердить: {{ .Num }}",
"confirmNumberAdd": "✅ Подтвердить добавление: {{ .Num }}",
"limitTraffic": "🚧 Лимит трафика",
"getBanLogs": "📄 Лог банов",
"allClients": "👥 Все клиенты",
"addClient": "➕ Новый клиент",
"submitDisable": "Добавить отключенным ☑️",
"submitEnable": "Добавить включенным ✅",
"use_default": "🏷️ Использовать по умолчанию",
"change_email": "⚙️📧 Email",
"change_comment": "⚙️💬 Комментарий",
"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 User ID в конфигурации.\r\n\r\n🆔 Ваш User ID: <code>{{ .TgUserID }}</code>",
"chooseClient": "Выберите клиента для входящего подключения {{ .Inbound }}",
"chooseInbound": "Выберите входящее подключение"
}
"noIpRecord": "❗ Нет записей об IP-адресе."
},
"email": {
"labelStatus": "Статус",
"labelOutbound": "Исходящее подключение",
"labelNode": "Узел",
"labelError": "Ошибка",
"labelDelay": "Задержка",
"labelUsername": "Имя пользователя",
"labelIP": "IP",
"labelReason": "Причина",
"labelSource": "Источник",
"statusCrashed": "СБОЙ",
"statusHigh": "ВЫСОКАЯ",
"statusSuccess": "УСПЕШНО",
"statusFailed": "НЕУДАЧНО",
"statusDown": "НЕДОСТУПЕН",
"statusUp": "РАБОТАЕТ"
}
"email": {}
}