fix(guest_mode,telegram): fix guest mode view, translations and bot language switcher

This commit is contained in:
Dushnilin
2026-09-08 09:58:43 +03:00
parent 4ed85f5b30
commit 625fa1e9b3
11 changed files with 5100 additions and 4415 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+92 -2
View File
@@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: TACHYON\n" "Project-Id-Version: TACHYON\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-09-07 11:45+0300\n" "POT-Creation-Date: 2026-09-08 09:57+0300\n"
"PO-Revision-Date: 2026-09-07 11:45+0300\n" "PO-Revision-Date: 2026-09-08 09:57+0300\n"
"Last-Translator: Dushnilin\n" "Last-Translator: Dushnilin\n"
"Language-Team: none\n" "Language-Team: none\n"
"Language: ru\n" "Language: ru\n"
@@ -353,6 +353,9 @@ msgstr "Все компоненты"
msgid "All devices" msgid "All devices"
msgstr "Все устройства" msgstr "Все устройства"
msgid "All Devices are Guests EXCEPT Trusted (Zero-Trust)"
msgstr "Все устройства — гости, кроме доверенных (Zero-Trust)"
msgid "All Engines (Full Matrix)" msgid "All Engines (Full Matrix)"
msgstr "Все движки (Полная матрица)" msgstr "Все движки (Полная матрица)"
@@ -404,9 +407,18 @@ msgstr "Разрешать только перечисленные сайты (
msgid "Allow only:" msgid "Allow only:"
msgstr "Только разрешённые:" msgstr "Только разрешённые:"
msgid "Allowed Days of Week"
msgstr "Разрешенные дни недели"
msgid "Allowed domain prefixes are full:, keyword:, and regex:" msgid "Allowed domain prefixes are full:, keyword:, and regex:"
msgstr "Допустимые префиксы доменов: full:, keyword:, и regex:" msgstr "Допустимые префиксы доменов: full:, keyword:, и regex:"
msgid "Allowed End Time"
msgstr "Время окончания доступа"
msgid "Allowed Start Time"
msgstr "Время начала доступа"
msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall." msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."
msgstr "Позволяет доступ к YACD из WAN. Убедитесь, что соответствующий порт открыт в файрволе." msgstr "Позволяет доступ к YACD из WAN. Убедитесь, что соответствующий порт открыт в файрволе."
@@ -680,6 +692,9 @@ msgstr "Блокировка доступа в интернет или опре
msgid "Block listed sites (Standard)" msgid "Block listed sites (Standard)"
msgstr "Блокировать перечисленные сайты (стандартно)" msgstr "Блокировать перечисленные сайты (стандартно)"
msgid "Block Router Administration"
msgstr "Блокировать доступ к управлению роутером"
msgid "Block:" msgid "Block:"
msgstr "Блокировать:" msgstr "Блокировать:"
@@ -1148,9 +1163,15 @@ msgstr "Дневная квота"
msgid "Daily Screen Time Quota (minutes)" msgid "Daily Screen Time Quota (minutes)"
msgstr "Дневная квота экранного времени (минуты)" msgstr "Дневная квота экранного времени (минуты)"
msgid "Daily Time Limit (minutes)"
msgstr "Дневной лимит времени (минуты)"
msgid "Daily time quota (minutes)" msgid "Daily time quota (minutes)"
msgstr "Дневной лимит времени (минуты)" msgstr "Дневной лимит времени (минуты)"
msgid "Daily Traffic Limit (MB)"
msgstr "Дневной лимит трафика (МБ)"
msgid "Dashboard" msgid "Dashboard"
msgstr "Панель управления" msgstr "Панель управления"
@@ -1220,6 +1241,9 @@ msgstr "Режим устройства обновлен"
msgid "Devices (MAC / IP)" msgid "Devices (MAC / IP)"
msgstr "Устройства (MAC / IP)" msgstr "Устройства (MAC / IP)"
msgid "Devices that are isolated as guests. Enter IP or MAC addresses, or pick from active LAN devices."
msgstr "Устройства, изолированные в качестве гостевых. Введите IP- или MAC-адреса, либо выберите из активных устройств сети."
msgid "DHCP has DNS server" msgid "DHCP has DNS server"
msgstr "DHCP содержит DNS сервер" msgstr "DHCP содержит DNS сервер"
@@ -1547,6 +1571,9 @@ msgstr "Включить дедупликацию перезагрузки фа
msgid "Enable Graceful Degradation" msgid "Enable Graceful Degradation"
msgstr "Включить мягкое деградирование" msgstr "Включить мягкое деградирование"
msgid "Enable Guest Mode"
msgstr "Включить гостевой режим"
msgid "Enable Health Metrics" msgid "Enable Health Metrics"
msgstr "Включить метрики здоровья" msgstr "Включить метрики здоровья"
@@ -1601,6 +1628,9 @@ msgstr "Включает фоновый демон, который опраши
msgid "Enables the background watchdog process to monitor services and auto-recover on failures." msgid "Enables the background watchdog process to monitor services and auto-recover on failures."
msgstr "Включает фоновый процесс watchdog для мониторинга сервисов и автоматического восстановления при сбоях." msgstr "Включает фоновый процесс watchdog для мониторинга сервисов и автоматического восстановления при сбоях."
msgid "End of allowed daily access window in HH:MM format (24-hour clock)."
msgstr "Конец разрешенного ежедневного интервала доступа в формате ЧЧ:ММ (24-часовой формат)."
msgid "End of the schedule interval (e.g. 08:00). Supports spans crossing midnight." msgid "End of the schedule interval (e.g. 08:00). Supports spans crossing midnight."
msgstr "Конец интервала расписания (например, 08:00). Поддерживает переход через полночь." msgstr "Конец интервала расписания (например, 08:00). Поддерживает переход через полночь."
@@ -1631,6 +1661,9 @@ msgstr "Введите имя уровня"
msgid "Enter a number or range, e.g. 25 or 25-35" msgid "Enter a number or range, e.g. 25 or 25-35"
msgstr "Введите число или диапазон, например 25 или 25-35" msgstr "Введите число или диапазон, например 25 или 25-35"
msgid "Enter a positive whole number in megabytes"
msgstr "Введите положительное целое число в мегабайтах"
msgid "Enter a valid time in HH:MM format (00:00 to 23:59)" msgid "Enter a valid time in HH:MM format (00:00 to 23:59)"
msgstr "Введите корректное время в формате ЧЧ:ММ (от 00:00 до 23:59)" msgstr "Введите корректное время в формате ЧЧ:ММ (от 00:00 до 23:59)"
@@ -2093,6 +2126,18 @@ msgstr "Группируйте устройства в семейные проф
msgid "gRPC service" msgid "gRPC service"
msgstr "Сервис gRPC" msgstr "Сервис gRPC"
msgid "Guest Devices (MAC / IP)"
msgstr "Гостевые устройства (MAC / IP)"
msgid "Guest Mode"
msgstr "Гостевой режим"
msgid "Guest mode isolates guest devices from local LAN and router administration, while allowing internet access with daily quotas and schedules."
msgstr "Гостевой режим изолирует гостевые устройства от локальной сети и панели управления роутером, сохраняя доступ в интернет с дневными квотами и расписанием."
msgid "Guest network isolation and device quotas"
msgstr "Изоляция гостевой сети и квоты устройств"
msgid "Handshake timeout" msgid "Handshake timeout"
msgstr "Таймаут рукопожатия" msgstr "Таймаут рукопожатия"
@@ -2438,6 +2483,9 @@ msgstr "Неверный URL Hysteria2: неподдерживаемый тип
msgid "Invalid IP address" msgid "Invalid IP address"
msgstr "Неверный IP-адрес" msgstr "Неверный IP-адрес"
msgid "Invalid IP or MAC address format"
msgstr "Неверный формат IP или MAC-адреса"
msgid "Invalid IP or MAC address. Expected e.g. 192.168.1.150 or AA:BB:CC:DD:EE:FF" msgid "Invalid IP or MAC address. Expected e.g. 192.168.1.150 or AA:BB:CC:DD:EE:FF"
msgstr "Неверный IP или MAC-адрес. Ожидается, например, 192.168.1.150 или AA:BB:CC:DD:EE:FF" msgstr "Неверный IP или MAC-адрес. Ожидается, например, 192.168.1.150 или AA:BB:CC:DD:EE:FF"
@@ -2519,6 +2567,9 @@ msgstr "Неверный URL SOCKS: парсинг не удался"
msgid "Invalid time format. Expected HH:MM (e.g. 22:00)" msgid "Invalid time format. Expected HH:MM (e.g. 22:00)"
msgstr "Неверный формат времени. Ожидается ЧЧ:ММ (например, 22:00)" msgstr "Неверный формат времени. Ожидается ЧЧ:ММ (например, 22:00)"
msgid "Invalid time format. Use HH:MM (e.g. 08:00 or 22:30)"
msgstr "Неверный формат времени. Используйте ЧЧ:ММ (например, 08:00 или 22:30)"
msgid "Invalid Trojan URL: must not contain spaces" msgid "Invalid Trojan URL: must not contain spaces"
msgstr "Неверный URL Trojan: не должен содержать пробелов" msgstr "Неверный URL Trojan: не должен содержать пробелов"
@@ -2606,6 +2657,9 @@ msgstr "недоступно"
msgid "Isolate BitTorrent traffic and force it direct to prevent VPN bans" msgid "Isolate BitTorrent traffic and force it direct to prevent VPN bans"
msgstr "Изолировать трафик BitTorrent и направить его напрямую для предотвращения блокировок VPN" msgstr "Изолировать трафик BitTorrent и направить его напрямую для предотвращения блокировок VPN"
msgid "Isolate Local LAN"
msgstr "Изолировать локальную сеть"
msgid "Issues" msgid "Issues"
msgstr "Проблемы" msgstr "Проблемы"
@@ -2843,6 +2897,9 @@ msgstr "Приватный ключ MASQUE"
msgid "Masquerade LAN traffic into tailnet" msgid "Masquerade LAN traffic into tailnet"
msgstr "Маскарадинг LAN-трафика в тейлнет" msgstr "Маскарадинг LAN-трафика в тейлнет"
msgid "Master and family devices with full LAN and router access. Any device NOT in this list will be treated as a guest."
msgstr "Основные и семейные устройства с полным доступом к локальной сети и роутеру. Любое устройство не из этого списка будет считаться гостевым."
msgid "Match destination IPs or subnets" msgid "Match destination IPs or subnets"
msgstr "Сопоставлять IP-адреса или подсети назначения" msgstr "Сопоставлять IP-адреса или подсети назначения"
@@ -2861,6 +2918,12 @@ msgstr "Максимум попыток рукопожатия"
msgid "Max reconnects per hour before alert (default 10)." msgid "Max reconnects per hour before alert (default 10)."
msgstr "Макс. переподключений в час до оповещения (по умолчанию 10)." msgstr "Макс. переподключений в час до оповещения (по умолчанию 10)."
msgid "Maximum allowed download and upload traffic per guest device per day in megabytes. Enter 0 for unlimited."
msgstr "Максимально допустимый суммарный трафик на гостевое устройство в день в мегабайтах. Введите 0 для отсутствия ограничений."
msgid "Maximum allowed online time per guest device per day. When reached, access is blocked until midnight. Enter 0 for unlimited."
msgstr "Максимально допустимое время доступа в интернет на одно гостевое устройство в день. При исчерпании доступ блокируется до полуночи. Введите 0 для отсутствия ограничений."
msgid "Maximum size of junk packets" msgid "Maximum size of junk packets"
msgstr "Максимальный размер мусорных пакетов" msgstr "Максимальный размер мусорных пакетов"
@@ -3407,6 +3470,9 @@ msgstr "Обычные UDP DNS-серверы, используемые как
msgid "Please specify strategy name and arguments" msgid "Please specify strategy name and arguments"
msgstr "Пожалуйста, укажите имя стратегии и аргументы" msgstr "Пожалуйста, укажите имя стратегии и аргументы"
msgid "Policy Mode"
msgstr "Режим политики"
msgid "Polling Interval (seconds)" msgid "Polling Interval (seconds)"
msgstr "Интервал опроса (секунды)" msgstr "Интервал опроса (секунды)"
@@ -3470,6 +3536,12 @@ msgstr "Подготовка стратегий и изолированной о
msgid "Preshared Key" msgid "Preshared Key"
msgstr "Предварительный общий ключ" msgstr "Предварительный общий ключ"
msgid "Prevent guest devices from accessing other local network devices (RFC1918 and IPv6 local subnets)."
msgstr "Запретить гостевым устройствам доступ к другим устройствам локальной сети (RFC1918 и локальные подсети IPv6)."
msgid "Prevent guest devices from accessing router management services (LuCI Web UI, SSH, Clash API). DHCP and DNS remain accessible."
msgstr "Запретить гостевым устройствам доступ к службам управления роутером (LuCI Web UI, SSH, Clash API). DHCP и DNS остаются доступными."
msgid "Prevents multiple reload_firewall calls within 120 seconds to avoid connection drops." msgid "Prevents multiple reload_firewall calls within 120 seconds to avoid connection drops."
msgstr "Предотвращает множественные вызовы reload_firewall в течение 120 секунд для избежания разрыва соединений." msgstr "Предотвращает множественные вызовы reload_firewall в течение 120 секунд для избежания разрыва соединений."
@@ -4013,6 +4085,9 @@ msgstr "Выберите промежуточную секцию"
msgid "Select and order the sections through which blocked domains are tested. Checked sections are tried top-to-bottom." msgid "Select and order the sections through which blocked domains are tested. Checked sections are tried top-to-bottom."
msgstr "Выберите и упорядочите секции, через которые тестируются заблокированные домены. Отмеченные секции проверяются сверху вниз." msgstr "Выберите и упорядочите секции, через которые тестируются заблокированные домены. Отмеченные секции проверяются сверху вниз."
msgid "Select days when guest access is permitted. Leave empty for all days."
msgstr "Выберите дни, когда гостевой доступ разрешен. Оставьте пустым для доступа во все дни."
msgid "Select DNS protocol to use" msgid "Select DNS protocol to use"
msgstr "Выберите протокол DNS" msgstr "Выберите протокол DNS"
@@ -4067,9 +4142,15 @@ msgstr "Выберите, какая вкладка открывается ав
msgid "Selected" msgid "Selected"
msgstr "Выбран" msgstr "Выбран"
msgid "Selected Devices are Guests (Explicit list)"
msgstr "Выбранные устройства — гости (явный список)"
msgid "Selected section" msgid "Selected section"
msgstr "Выбранная секция" msgstr "Выбранная секция"
msgid "Selected: specified devices become guests. Inverted: all devices on the network become guests EXCEPT the trusted ones (Zero-Trust)."
msgstr "Выборочный: указанные устройства становятся гостевыми. Инвертированный: все устройства в сети считаются гостевыми, КРОМЕ доверенных (Zero-Trust)."
msgid "Selector and URLTest outbounds must contain a non-empty outbounds array" msgid "Selector and URLTest outbounds must contain a non-empty outbounds array"
msgstr "Selector и URLTest outbound должны содержать непустой массив outbounds" msgstr "Selector и URLTest outbound должны содержать непустой массив outbounds"
@@ -4100,6 +4181,9 @@ msgstr "Отправлять уведомление в Telegram при успе
msgid "Send Telegram alerts to parents when daily screen time is exhausted or blocked sites are accessed." msgid "Send Telegram alerts to parents when daily screen time is exhausted or blocked sites are accessed."
msgstr "Отправлять уведомления родителям в Telegram при исчерпании экранного времени или попытке открыть заблокированные сайты." msgstr "Отправлять уведомления родителям в Telegram при исчерпании экранного времени или попытке открыть заблокированные сайты."
msgid "Send Telegram notification when a guest device hits its daily time or traffic quota."
msgstr "Отправлять уведомление в Telegram при исчерпании гостевым устройством лимита времени или трафика."
msgid "Sequence Overlaps (seqovl)" msgid "Sequence Overlaps (seqovl)"
msgstr "Перекрытия последовательностей (seqovl)" msgstr "Перекрытия последовательностей (seqovl)"
@@ -4391,6 +4475,9 @@ msgstr "Начать тест"
msgid "Start bot" msgid "Start bot"
msgstr "Запустить бота" msgstr "Запустить бота"
msgid "Start of allowed daily access window in HH:MM format (24-hour clock)."
msgstr "Начало разрешенного ежедневного интервала доступа в формате ЧЧ:ММ (24-часовой формат)."
msgid "Start sing-box" msgid "Start sing-box"
msgstr "Запустить sing-box" msgstr "Запустить sing-box"
@@ -4877,6 +4964,9 @@ msgstr "Путь транспорта должен начинаться с /"
msgid "Troubleshooting" msgid "Troubleshooting"
msgstr "Устранение неполадок" msgstr "Устранение неполадок"
msgid "Trusted Master Devices (MAC / IP)"
msgstr "Доверенные основные устройства (MAC / IP)"
msgid "Try compatible User-Agent profiles automatically when downloading this subscription" msgid "Try compatible User-Agent profiles automatically when downloading this subscription"
msgstr "Пробовать совместимые профили User-Agent автоматически при загрузке этой подписки" msgstr "Пробовать совместимые профили User-Agent автоматически при загрузке этой подписки"
@@ -1299,6 +1299,23 @@ function createParentalContent(section) {
// ─── Guest Mode Section ─────────────────────────────────────────────────────── // ─── Guest Mode Section ───────────────────────────────────────────────────────
function validateGuestDevice(_sectionId, value) {
if (value === "" || value === null || value === undefined) return true;
const v = String(value).trim();
const isMac = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.test(v);
const isIpv4 = /^(\d{1,3}\.){3}\d{1,3}(\/\d{1,2})?$/.test(v);
const isIpv6 = /^[0-9a-fA-F:]+(\/\d{1,3})?$/.test(v);
if (isMac || isIpv4 || isIpv6) return true;
return _("Invalid IP or MAC address format");
}
function validateGuestTime(_sectionId, value) {
if (value === "" || value === null || value === undefined) return true;
const v = String(value).trim();
if (/^([01]\d|2[0-3]):[0-5]\d$/.test(v)) return true;
return _("Invalid time format. Use HH:MM (e.g. 08:00 or 22:30)");
}
function createGuestModeContent(section) { function createGuestModeContent(section) {
// Enabled switch // Enabled switch
let o = section.option(form.Flag, "enabled", _("Enable Guest Mode")); let o = section.option(form.Flag, "enabled", _("Enable Guest Mode"));
@@ -1329,7 +1346,7 @@ function createGuestModeContent(section) {
); );
o.rmempty = true; o.rmempty = true;
o.placeholder = "192.168.1.150 or AA:BB:CC:DD:EE:FF"; o.placeholder = "192.168.1.150 or AA:BB:CC:DD:EE:FF";
o.validate = validateDevice; o.validate = validateGuestDevice;
o.depends("mode", "selected"); o.depends("mode", "selected");
o.renderWidget = function (sectionId, optionIndex, cfgvalue) { o.renderWidget = function (sectionId, optionIndex, cfgvalue) {
return local_devices.createLocalDeviceDynamicListWidget( return local_devices.createLocalDeviceDynamicListWidget(
@@ -1350,7 +1367,7 @@ function createGuestModeContent(section) {
); );
o.rmempty = true; o.rmempty = true;
o.placeholder = "192.168.1.100 or AA:BB:CC:DD:EE:FF"; o.placeholder = "192.168.1.100 or AA:BB:CC:DD:EE:FF";
o.validate = validateDevice; o.validate = validateGuestDevice;
o.depends("mode", "inverted"); o.depends("mode", "inverted");
o.renderWidget = function (sectionId, optionIndex, cfgvalue) { o.renderWidget = function (sectionId, optionIndex, cfgvalue) {
return local_devices.createLocalDeviceDynamicListWidget( return local_devices.createLocalDeviceDynamicListWidget(
@@ -1433,7 +1450,7 @@ function createGuestModeContent(section) {
); );
o.placeholder = "08:00"; o.placeholder = "08:00";
o.rmempty = true; o.rmempty = true;
o.validate = validateTime; o.validate = validateGuestTime;
o = section.option( o = section.option(
form.Value, form.Value,
@@ -1443,7 +1460,7 @@ function createGuestModeContent(section) {
); );
o.placeholder = "22:00"; o.placeholder = "22:00";
o.rmempty = true; o.rmempty = true;
o.validate = validateTime; o.validate = validateGuestTime;
// Days of week // Days of week
o = section.option( o = section.option(
@@ -386,6 +386,9 @@ const EntryPoint = {
if (!uci.get(self.config, "telegram")) { if (!uci.get(self.config, "telegram")) {
uci.add(self.config, "telegram", "telegram"); uci.add(self.config, "telegram", "telegram");
} }
if (!uci.get(self.config, "guest_mode")) {
uci.add(self.config, "guest_mode", "guest_mode");
}
return form.Map.prototype.load.call(self); return form.Map.prototype.load.call(self);
}); });
}; };
@@ -578,16 +581,18 @@ const EntryPoint = {
}, },
guest_mode: () => { guest_mode: () => {
const s = tachyonMap.section( const s = tachyonMap.section(
form.NamedSection, form.TypedSection,
"guest_mode",
"guest_mode", "guest_mode",
_("Guest Mode"), _("Guest Mode"),
_( _(
"Guest mode isolates guest devices from local LAN and router administration, while allowing internet access with daily quotas and schedules.", "Guest mode isolates guest devices from local LAN and router administration, while allowing internet access with daily quotas and schedules.",
), ),
); );
s.anonymous = false; s.anonymous = true;
s.addremove = false; s.addremove = false;
s.cfgsections = function () {
return ["guest_mode"];
};
parental.createGuestModeContent(s); parental.createGuestModeContent(s);
return s; return s;
}, },
+92 -2
View File
@@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: TACHYON\n" "Project-Id-Version: TACHYON\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-09-07 11:45+0300\n" "POT-Creation-Date: 2026-09-08 09:57+0300\n"
"PO-Revision-Date: 2026-09-07 11:45+0300\n" "PO-Revision-Date: 2026-09-08 09:57+0300\n"
"Last-Translator: Dushnilin\n" "Last-Translator: Dushnilin\n"
"Language-Team: none\n" "Language-Team: none\n"
"Language: ru\n" "Language: ru\n"
@@ -353,6 +353,9 @@ msgstr "Все компоненты"
msgid "All devices" msgid "All devices"
msgstr "Все устройства" msgstr "Все устройства"
msgid "All Devices are Guests EXCEPT Trusted (Zero-Trust)"
msgstr "Все устройства — гости, кроме доверенных (Zero-Trust)"
msgid "All Engines (Full Matrix)" msgid "All Engines (Full Matrix)"
msgstr "Все движки (Полная матрица)" msgstr "Все движки (Полная матрица)"
@@ -404,9 +407,18 @@ msgstr "Разрешать только перечисленные сайты (
msgid "Allow only:" msgid "Allow only:"
msgstr "Только разрешённые:" msgstr "Только разрешённые:"
msgid "Allowed Days of Week"
msgstr "Разрешенные дни недели"
msgid "Allowed domain prefixes are full:, keyword:, and regex:" msgid "Allowed domain prefixes are full:, keyword:, and regex:"
msgstr "Допустимые префиксы доменов: full:, keyword:, и regex:" msgstr "Допустимые префиксы доменов: full:, keyword:, и regex:"
msgid "Allowed End Time"
msgstr "Время окончания доступа"
msgid "Allowed Start Time"
msgstr "Время начала доступа"
msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall." msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."
msgstr "Позволяет доступ к YACD из WAN. Убедитесь, что соответствующий порт открыт в файрволе." msgstr "Позволяет доступ к YACD из WAN. Убедитесь, что соответствующий порт открыт в файрволе."
@@ -680,6 +692,9 @@ msgstr "Блокировка доступа в интернет или опре
msgid "Block listed sites (Standard)" msgid "Block listed sites (Standard)"
msgstr "Блокировать перечисленные сайты (стандартно)" msgstr "Блокировать перечисленные сайты (стандартно)"
msgid "Block Router Administration"
msgstr "Блокировать доступ к управлению роутером"
msgid "Block:" msgid "Block:"
msgstr "Блокировать:" msgstr "Блокировать:"
@@ -1148,9 +1163,15 @@ msgstr "Дневная квота"
msgid "Daily Screen Time Quota (minutes)" msgid "Daily Screen Time Quota (minutes)"
msgstr "Дневная квота экранного времени (минуты)" msgstr "Дневная квота экранного времени (минуты)"
msgid "Daily Time Limit (minutes)"
msgstr "Дневной лимит времени (минуты)"
msgid "Daily time quota (minutes)" msgid "Daily time quota (minutes)"
msgstr "Дневной лимит времени (минуты)" msgstr "Дневной лимит времени (минуты)"
msgid "Daily Traffic Limit (MB)"
msgstr "Дневной лимит трафика (МБ)"
msgid "Dashboard" msgid "Dashboard"
msgstr "Панель управления" msgstr "Панель управления"
@@ -1220,6 +1241,9 @@ msgstr "Режим устройства обновлен"
msgid "Devices (MAC / IP)" msgid "Devices (MAC / IP)"
msgstr "Устройства (MAC / IP)" msgstr "Устройства (MAC / IP)"
msgid "Devices that are isolated as guests. Enter IP or MAC addresses, or pick from active LAN devices."
msgstr "Устройства, изолированные в качестве гостевых. Введите IP- или MAC-адреса, либо выберите из активных устройств сети."
msgid "DHCP has DNS server" msgid "DHCP has DNS server"
msgstr "DHCP содержит DNS сервер" msgstr "DHCP содержит DNS сервер"
@@ -1547,6 +1571,9 @@ msgstr "Включить дедупликацию перезагрузки фа
msgid "Enable Graceful Degradation" msgid "Enable Graceful Degradation"
msgstr "Включить мягкое деградирование" msgstr "Включить мягкое деградирование"
msgid "Enable Guest Mode"
msgstr "Включить гостевой режим"
msgid "Enable Health Metrics" msgid "Enable Health Metrics"
msgstr "Включить метрики здоровья" msgstr "Включить метрики здоровья"
@@ -1601,6 +1628,9 @@ msgstr "Включает фоновый демон, который опраши
msgid "Enables the background watchdog process to monitor services and auto-recover on failures." msgid "Enables the background watchdog process to monitor services and auto-recover on failures."
msgstr "Включает фоновый процесс watchdog для мониторинга сервисов и автоматического восстановления при сбоях." msgstr "Включает фоновый процесс watchdog для мониторинга сервисов и автоматического восстановления при сбоях."
msgid "End of allowed daily access window in HH:MM format (24-hour clock)."
msgstr "Конец разрешенного ежедневного интервала доступа в формате ЧЧ:ММ (24-часовой формат)."
msgid "End of the schedule interval (e.g. 08:00). Supports spans crossing midnight." msgid "End of the schedule interval (e.g. 08:00). Supports spans crossing midnight."
msgstr "Конец интервала расписания (например, 08:00). Поддерживает переход через полночь." msgstr "Конец интервала расписания (например, 08:00). Поддерживает переход через полночь."
@@ -1631,6 +1661,9 @@ msgstr "Введите имя уровня"
msgid "Enter a number or range, e.g. 25 or 25-35" msgid "Enter a number or range, e.g. 25 or 25-35"
msgstr "Введите число или диапазон, например 25 или 25-35" msgstr "Введите число или диапазон, например 25 или 25-35"
msgid "Enter a positive whole number in megabytes"
msgstr "Введите положительное целое число в мегабайтах"
msgid "Enter a valid time in HH:MM format (00:00 to 23:59)" msgid "Enter a valid time in HH:MM format (00:00 to 23:59)"
msgstr "Введите корректное время в формате ЧЧ:ММ (от 00:00 до 23:59)" msgstr "Введите корректное время в формате ЧЧ:ММ (от 00:00 до 23:59)"
@@ -2093,6 +2126,18 @@ msgstr "Группируйте устройства в семейные проф
msgid "gRPC service" msgid "gRPC service"
msgstr "Сервис gRPC" msgstr "Сервис gRPC"
msgid "Guest Devices (MAC / IP)"
msgstr "Гостевые устройства (MAC / IP)"
msgid "Guest Mode"
msgstr "Гостевой режим"
msgid "Guest mode isolates guest devices from local LAN and router administration, while allowing internet access with daily quotas and schedules."
msgstr "Гостевой режим изолирует гостевые устройства от локальной сети и панели управления роутером, сохраняя доступ в интернет с дневными квотами и расписанием."
msgid "Guest network isolation and device quotas"
msgstr "Изоляция гостевой сети и квоты устройств"
msgid "Handshake timeout" msgid "Handshake timeout"
msgstr "Таймаут рукопожатия" msgstr "Таймаут рукопожатия"
@@ -2438,6 +2483,9 @@ msgstr "Неверный URL Hysteria2: неподдерживаемый тип
msgid "Invalid IP address" msgid "Invalid IP address"
msgstr "Неверный IP-адрес" msgstr "Неверный IP-адрес"
msgid "Invalid IP or MAC address format"
msgstr "Неверный формат IP или MAC-адреса"
msgid "Invalid IP or MAC address. Expected e.g. 192.168.1.150 or AA:BB:CC:DD:EE:FF" msgid "Invalid IP or MAC address. Expected e.g. 192.168.1.150 or AA:BB:CC:DD:EE:FF"
msgstr "Неверный IP или MAC-адрес. Ожидается, например, 192.168.1.150 или AA:BB:CC:DD:EE:FF" msgstr "Неверный IP или MAC-адрес. Ожидается, например, 192.168.1.150 или AA:BB:CC:DD:EE:FF"
@@ -2519,6 +2567,9 @@ msgstr "Неверный URL SOCKS: парсинг не удался"
msgid "Invalid time format. Expected HH:MM (e.g. 22:00)" msgid "Invalid time format. Expected HH:MM (e.g. 22:00)"
msgstr "Неверный формат времени. Ожидается ЧЧ:ММ (например, 22:00)" msgstr "Неверный формат времени. Ожидается ЧЧ:ММ (например, 22:00)"
msgid "Invalid time format. Use HH:MM (e.g. 08:00 or 22:30)"
msgstr "Неверный формат времени. Используйте ЧЧ:ММ (например, 08:00 или 22:30)"
msgid "Invalid Trojan URL: must not contain spaces" msgid "Invalid Trojan URL: must not contain spaces"
msgstr "Неверный URL Trojan: не должен содержать пробелов" msgstr "Неверный URL Trojan: не должен содержать пробелов"
@@ -2606,6 +2657,9 @@ msgstr "недоступно"
msgid "Isolate BitTorrent traffic and force it direct to prevent VPN bans" msgid "Isolate BitTorrent traffic and force it direct to prevent VPN bans"
msgstr "Изолировать трафик BitTorrent и направить его напрямую для предотвращения блокировок VPN" msgstr "Изолировать трафик BitTorrent и направить его напрямую для предотвращения блокировок VPN"
msgid "Isolate Local LAN"
msgstr "Изолировать локальную сеть"
msgid "Issues" msgid "Issues"
msgstr "Проблемы" msgstr "Проблемы"
@@ -2843,6 +2897,9 @@ msgstr "Приватный ключ MASQUE"
msgid "Masquerade LAN traffic into tailnet" msgid "Masquerade LAN traffic into tailnet"
msgstr "Маскарадинг LAN-трафика в тейлнет" msgstr "Маскарадинг LAN-трафика в тейлнет"
msgid "Master and family devices with full LAN and router access. Any device NOT in this list will be treated as a guest."
msgstr "Основные и семейные устройства с полным доступом к локальной сети и роутеру. Любое устройство не из этого списка будет считаться гостевым."
msgid "Match destination IPs or subnets" msgid "Match destination IPs or subnets"
msgstr "Сопоставлять IP-адреса или подсети назначения" msgstr "Сопоставлять IP-адреса или подсети назначения"
@@ -2861,6 +2918,12 @@ msgstr "Максимум попыток рукопожатия"
msgid "Max reconnects per hour before alert (default 10)." msgid "Max reconnects per hour before alert (default 10)."
msgstr "Макс. переподключений в час до оповещения (по умолчанию 10)." msgstr "Макс. переподключений в час до оповещения (по умолчанию 10)."
msgid "Maximum allowed download and upload traffic per guest device per day in megabytes. Enter 0 for unlimited."
msgstr "Максимально допустимый суммарный трафик на гостевое устройство в день в мегабайтах. Введите 0 для отсутствия ограничений."
msgid "Maximum allowed online time per guest device per day. When reached, access is blocked until midnight. Enter 0 for unlimited."
msgstr "Максимально допустимое время доступа в интернет на одно гостевое устройство в день. При исчерпании доступ блокируется до полуночи. Введите 0 для отсутствия ограничений."
msgid "Maximum size of junk packets" msgid "Maximum size of junk packets"
msgstr "Максимальный размер мусорных пакетов" msgstr "Максимальный размер мусорных пакетов"
@@ -3407,6 +3470,9 @@ msgstr "Обычные UDP DNS-серверы, используемые как
msgid "Please specify strategy name and arguments" msgid "Please specify strategy name and arguments"
msgstr "Пожалуйста, укажите имя стратегии и аргументы" msgstr "Пожалуйста, укажите имя стратегии и аргументы"
msgid "Policy Mode"
msgstr "Режим политики"
msgid "Polling Interval (seconds)" msgid "Polling Interval (seconds)"
msgstr "Интервал опроса (секунды)" msgstr "Интервал опроса (секунды)"
@@ -3470,6 +3536,12 @@ msgstr "Подготовка стратегий и изолированной о
msgid "Preshared Key" msgid "Preshared Key"
msgstr "Предварительный общий ключ" msgstr "Предварительный общий ключ"
msgid "Prevent guest devices from accessing other local network devices (RFC1918 and IPv6 local subnets)."
msgstr "Запретить гостевым устройствам доступ к другим устройствам локальной сети (RFC1918 и локальные подсети IPv6)."
msgid "Prevent guest devices from accessing router management services (LuCI Web UI, SSH, Clash API). DHCP and DNS remain accessible."
msgstr "Запретить гостевым устройствам доступ к службам управления роутером (LuCI Web UI, SSH, Clash API). DHCP и DNS остаются доступными."
msgid "Prevents multiple reload_firewall calls within 120 seconds to avoid connection drops." msgid "Prevents multiple reload_firewall calls within 120 seconds to avoid connection drops."
msgstr "Предотвращает множественные вызовы reload_firewall в течение 120 секунд для избежания разрыва соединений." msgstr "Предотвращает множественные вызовы reload_firewall в течение 120 секунд для избежания разрыва соединений."
@@ -4013,6 +4085,9 @@ msgstr "Выберите промежуточную секцию"
msgid "Select and order the sections through which blocked domains are tested. Checked sections are tried top-to-bottom." msgid "Select and order the sections through which blocked domains are tested. Checked sections are tried top-to-bottom."
msgstr "Выберите и упорядочите секции, через которые тестируются заблокированные домены. Отмеченные секции проверяются сверху вниз." msgstr "Выберите и упорядочите секции, через которые тестируются заблокированные домены. Отмеченные секции проверяются сверху вниз."
msgid "Select days when guest access is permitted. Leave empty for all days."
msgstr "Выберите дни, когда гостевой доступ разрешен. Оставьте пустым для доступа во все дни."
msgid "Select DNS protocol to use" msgid "Select DNS protocol to use"
msgstr "Выберите протокол DNS" msgstr "Выберите протокол DNS"
@@ -4067,9 +4142,15 @@ msgstr "Выберите, какая вкладка открывается ав
msgid "Selected" msgid "Selected"
msgstr "Выбран" msgstr "Выбран"
msgid "Selected Devices are Guests (Explicit list)"
msgstr "Выбранные устройства — гости (явный список)"
msgid "Selected section" msgid "Selected section"
msgstr "Выбранная секция" msgstr "Выбранная секция"
msgid "Selected: specified devices become guests. Inverted: all devices on the network become guests EXCEPT the trusted ones (Zero-Trust)."
msgstr "Выборочный: указанные устройства становятся гостевыми. Инвертированный: все устройства в сети считаются гостевыми, КРОМЕ доверенных (Zero-Trust)."
msgid "Selector and URLTest outbounds must contain a non-empty outbounds array" msgid "Selector and URLTest outbounds must contain a non-empty outbounds array"
msgstr "Selector и URLTest outbound должны содержать непустой массив outbounds" msgstr "Selector и URLTest outbound должны содержать непустой массив outbounds"
@@ -4100,6 +4181,9 @@ msgstr "Отправлять уведомление в Telegram при успе
msgid "Send Telegram alerts to parents when daily screen time is exhausted or blocked sites are accessed." msgid "Send Telegram alerts to parents when daily screen time is exhausted or blocked sites are accessed."
msgstr "Отправлять уведомления родителям в Telegram при исчерпании экранного времени или попытке открыть заблокированные сайты." msgstr "Отправлять уведомления родителям в Telegram при исчерпании экранного времени или попытке открыть заблокированные сайты."
msgid "Send Telegram notification when a guest device hits its daily time or traffic quota."
msgstr "Отправлять уведомление в Telegram при исчерпании гостевым устройством лимита времени или трафика."
msgid "Sequence Overlaps (seqovl)" msgid "Sequence Overlaps (seqovl)"
msgstr "Перекрытия последовательностей (seqovl)" msgstr "Перекрытия последовательностей (seqovl)"
@@ -4391,6 +4475,9 @@ msgstr "Начать тест"
msgid "Start bot" msgid "Start bot"
msgstr "Запустить бота" msgstr "Запустить бота"
msgid "Start of allowed daily access window in HH:MM format (24-hour clock)."
msgstr "Начало разрешенного ежедневного интервала доступа в формате ЧЧ:ММ (24-часовой формат)."
msgid "Start sing-box" msgid "Start sing-box"
msgstr "Запустить sing-box" msgstr "Запустить sing-box"
@@ -4877,6 +4964,9 @@ msgstr "Путь транспорта должен начинаться с /"
msgid "Troubleshooting" msgid "Troubleshooting"
msgstr "Устранение неполадок" msgstr "Устранение неполадок"
msgid "Trusted Master Devices (MAC / IP)"
msgstr "Доверенные основные устройства (MAC / IP)"
msgid "Try compatible User-Agent profiles automatically when downloading this subscription" msgid "Try compatible User-Agent profiles automatically when downloading this subscription"
msgstr "Пробовать совместимые профили User-Agent автоматически при загрузке этой подписки" msgstr "Пробовать совместимые профили User-Agent автоматически при загрузке этой подписки"
File diff suppressed because it is too large Load Diff
+2 -5
View File
@@ -1118,16 +1118,13 @@ function resolve_lang(cfg_lang) {
// Strings with %s placeholders use sprintf for substitution. // Strings with %s placeholders use sprintf for substitution.
function bind(lang) { function bind(lang) {
lang = resolve_lang(lang); lang = resolve_lang(lang);
return function(key) { return function(key, ...args) {
let table = strings[lang]; let table = strings[lang];
let val = table ? table[key] : null; let val = table ? table[key] : null;
if (val == null) val = strings.en[key]; if (val == null) val = strings.en[key];
if (val == null) return key; if (val == null) return key;
// sprintf-style substitution: pass extra args to t("key", arg1, arg2) // sprintf-style substitution: pass extra args to t("key", arg1, arg2)
if (length(arguments) > 1) { if (length(args) > 0) {
let args = [];
for (let i = 1; i < length(arguments); i++)
push(args, arguments[i]);
try { return sprintf(val, ...args); } catch(e) { return val; } try { return sprintf(val, ...args); } catch(e) { return val; }
} }
return val; return val;
+9
View File
@@ -303,10 +303,19 @@ function remove_component_update_cache() {
unlink_if_exists(path); unlink_if_exists(path);
} }
function ensure_guest_mode_section() {
if (path_exists("/etc/config/" + CONFIG_NAME) && !uci_core.exists(CONFIG_NAME + ".guest_mode")) {
uci_core.set_section(CONFIG_NAME + ".guest_mode", "guest_mode");
uci_core.set(CONFIG_NAME + ".guest_mode.enabled", "0");
uci_core.commit(CONFIG_NAME);
}
}
function luci_postinst() { function luci_postinst() {
remove_luci_index_cache(); remove_luci_index_cache();
remove_component_update_cache(); remove_component_update_cache();
if (!PACKAGE_TEST_MODE) { if (!PACKAGE_TEST_MODE) {
ensure_guest_mode_section();
if (path_exists("/etc/init.d/rpcd")) if (path_exists("/etc/init.d/rpcd"))
command_success_from_args([ "/etc/init.d/rpcd", "reload" ]); command_success_from_args([ "/etc/init.d/rpcd", "reload" ]);
command_success_from_args([ "logger", "-t", "tachyon", "[info] Package defaults applied" ]); command_success_from_args([ "logger", "-t", "tachyon", "[info] Package defaults applied" ]);
+2 -2
View File
@@ -2491,9 +2491,9 @@ function dispatch_command(token, chat_id, text, msg_id) {
if (cmd == "/info") return view_system_info(token, chat_id, msg_id); if (cmd == "/info") return view_system_info(token, chat_id, msg_id);
if (cmd == "/help") return view_help(token, chat_id, msg_id); if (cmd == "/help") return view_help(token, chat_id, msg_id);
if (cmd == "/lang" || cmd == "/language") return view_language(token, chat_id, msg_id); if (cmd == "/lang" || cmd == "/language") return view_language(token, chat_id, msg_id);
let lang_match = match(cmd, /^\/(?:lang_set|lang|language)[ \t]+([a-zA-Z0-9_-]+)/); let lang_match = match(cmd, /^\/(lang_set|lang|language)[ \t]+([a-zA-Z0-9_-]+)/);
if (lang_match) { if (lang_match) {
let lang = lc(trim(lang_match[1])); let lang = lc(trim(lang_match[2]));
return handle_lang_set(token, chat_id, msg_id, lang); return handle_lang_set(token, chat_id, msg_id, lang);
} }
if (cmd == "/guest") return view_guest_mode(token, chat_id, msg_id); if (cmd == "/guest") return view_guest_mode(token, chat_id, msg_id);
+11 -5
View File
@@ -24,7 +24,7 @@ if grep -E 'lang.*substr\(cmd, 11\)' "$TG"; then
fi fi
# 3. /lang_set matching must capture the full language code # 3. /lang_set matching must capture the full language code
grep -Fq 'lang_match = match(cmd, /^\/(?:lang_set|lang|language)' "$TG" || grep -Fq 'lang_match = match(cmd, /^\/(lang_set|lang|language)' "$TG" ||
fail "telegram.uc must robustly match /lang_set and /lang commands with arguments" fail "telegram.uc must robustly match /lang_set and /lang commands with arguments"
# 4. handle_lang_set must rebind t immediately # 4. handle_lang_set must rebind t immediately
@@ -45,7 +45,7 @@ grep -Fq 'if (cmd == "/guest")' "$TG" ||
grep -Fq 'if (cmd == "/guest_toggle")' "$TG" || grep -Fq 'if (cmd == "/guest_toggle")' "$TG" ||
fail "dispatch_command must route /guest_toggle" fail "dispatch_command must route /guest_toggle"
# 7. Run ucode evaluation test of i18n language resolution and strings # 7. Run ucode evaluation test of i18n language resolution, sprintf args, and regex
ucode -e ' ucode -e '
let i18n = loadfile("'"$I18N"'")(); let i18n = loadfile("'"$I18N"'")();
if (i18n.resolve_lang("ru") != "ru") exit(1); if (i18n.resolve_lang("ru") != "ru") exit(1);
@@ -54,11 +54,17 @@ if (i18n.resolve_lang("invalid") != "en") exit(3);
let t_ru = i18n.bind("ru"); let t_ru = i18n.bind("ru");
if (t_ru("lang_saved") != "Язык сохранён!") exit(4); if (t_ru("lang_saved") != "Язык сохранён!") exit(4);
if (t_ru("cmd_guest") != "Гостевой режим") exit(5); if (t_ru("cmd_guest") != "Гостевой режим") exit(5);
if (t_ru("lang_current", "Русский") != "Текущий язык: Русский") exit(6);
let t_en = i18n.bind("en"); let t_en = i18n.bind("en");
if (t_en("lang_saved") != "Language saved!") exit(6); if (t_en("lang_saved") != "Language saved!") exit(7);
if (t_en("cmd_guest") != "Guest mode") exit(7); if (t_en("cmd_guest") != "Guest mode") exit(8);
if (t_en("lang_current", "English") != "Current language: English") exit(9);
let langs = i18n.available_languages("en"); let langs = i18n.available_languages("en");
if (length(langs) != 2 || !langs[0].available || !langs[1].available) exit(8); if (length(langs) != 2 || !langs[0].available || !langs[1].available) exit(10);
let m1 = match("/lang_set ru", /^\/(lang_set|lang|language)[ \t]+([a-zA-Z0-9_-]+)/);
if (!m1 || m1[2] != "ru") exit(11);
let m2 = match("/lang en", /^\/(lang_set|lang|language)[ \t]+([a-zA-Z0-9_-]+)/);
if (!m2 || m2[2] != "en") exit(12);
' || fail "ucode i18n evaluation failed" ' || fail "ucode i18n evaluation failed"
printf 'telegram language and guest route checks passed\n' printf 'telegram language and guest route checks passed\n'