From 4fb11d9dba51f4acadbfa6b1ca971e7f6051492c Mon Sep 17 00:00:00 2001 From: gsd Date: Thu, 23 Oct 2025 21:02:50 +0300 Subject: [PATCH] ruLang --- Dockerfile.web | 26 + .../public/i18n/locales/ru-RU/channels.json | 71 +++ .../i18n/locales/ru-RU/commandPalette.json | 51 ++ .../web/public/i18n/locales/ru-RU/common.json | 123 +++++ .../public/i18n/locales/ru-RU/dashboard.json | 12 + .../i18n/locales/ru-RU/deviceConfig.json | 428 +++++++++++++++++ .../web/public/i18n/locales/ru-RU/dialog.json | 221 +++++++++ .../web/public/i18n/locales/ru-RU/map.json | 38 ++ .../public/i18n/locales/ru-RU/messages.json | 39 ++ .../i18n/locales/ru-RU/moduleConfig.json | 448 ++++++++++++++++++ .../web/public/i18n/locales/ru-RU/nodes.json | 59 +++ .../web/public/i18n/locales/ru-RU/ui.json | 221 +++++++++ packages/web/src/i18n-config.ts | 2 + 13 files changed, 1739 insertions(+) create mode 100644 Dockerfile.web create mode 100644 packages/web/public/i18n/locales/ru-RU/channels.json create mode 100644 packages/web/public/i18n/locales/ru-RU/commandPalette.json create mode 100644 packages/web/public/i18n/locales/ru-RU/common.json create mode 100644 packages/web/public/i18n/locales/ru-RU/dashboard.json create mode 100644 packages/web/public/i18n/locales/ru-RU/deviceConfig.json create mode 100644 packages/web/public/i18n/locales/ru-RU/dialog.json create mode 100644 packages/web/public/i18n/locales/ru-RU/map.json create mode 100644 packages/web/public/i18n/locales/ru-RU/messages.json create mode 100644 packages/web/public/i18n/locales/ru-RU/moduleConfig.json create mode 100644 packages/web/public/i18n/locales/ru-RU/nodes.json create mode 100644 packages/web/public/i18n/locales/ru-RU/ui.json diff --git a/Dockerfile.web b/Dockerfile.web new file mode 100644 index 00000000..3f85d9e7 --- /dev/null +++ b/Dockerfile.web @@ -0,0 +1,26 @@ +FROM node:20-slim AS base +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable + +FROM base AS prod + +WORKDIR /app +COPY pnpm-lock.yaml /app +RUN pnpm fetch --prod + +WORKDIR /app/packages/web +COPY . /app +RUN pnpm build +#################################### +FROM nginx:1.29.1-alpine-slim as web +RUN rm -r /usr/share/nginx/html \ + && mkdir -p /usr/share/nginx/html \ + && mkdir -p /etc/nginx/conf.d + +WORKDIR /usr/share/nginx/html +COPY --from=prod /app/packages/web/dist ./ +#ADD ./packages/web/dist . +COPY --from=prod /app/packages/web/infra/default.conf /etc/nginx/conf.d/default.conf +EXPOSE 8080 +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/packages/web/public/i18n/locales/ru-RU/channels.json b/packages/web/public/i18n/locales/ru-RU/channels.json new file mode 100644 index 00000000..2a82f6ef --- /dev/null +++ b/packages/web/public/i18n/locales/ru-RU/channels.json @@ -0,0 +1,71 @@ +{ + "page": { + "sectionLabel": "Каналы", + "channelName": "Канал: {{channelName}}", + "broadcastLabel": "Основной", + "channelIndex": "Кан {{index}}", + "import": "Импорт", + "export": "Экспорт" + }, + "validation": { + "pskInvalid": "Пожалуйста, введите корректный {{bits}}-битный PSK." + }, + "settings": { + "label": "Настройки канала", + "description": "Шифрование, MQTT и прочие настройки" + }, + "role": { + "label": "Роль", + "description": "Телеметрия устройства отправляется через ОСНОВНОЙ канал. Разрешён только один ОСНОВНОЙ канал", + "options": { + "primary": "ОСНОВНОЙ", + "disabled": "ОТКЛЮЧЁН", + "secondary": "ВТОРИЧНЫЙ" + } + }, + "psk": { + "label": "Предварительный общий ключ (PSK)", + "description": "Поддерживаемые длины PSK: 256-бит, 128-бит, 8-бит, Пустой (0-бит)", + "generate": "Сгенерировать" + }, + "name": { + "label": "Название", + "description": "Уникальное имя канала <12 байт, оставьте пустым для значения по умолчанию" + }, + "uplinkEnabled": { + "label": "Восходящая связь включена", + "description": "Отправлять сообщения из локальной сети в MQTT" + }, + "downlinkEnabled": { + "label": "Нисходящая связь включена", + "description": "Отправлять сообщения из MQTT в локальную сеть" + }, + "positionPrecision": { + "label": "Локация", + "description": "Точность передаваемой локации в канале. Можно отключить.", + "options": { + "none": "Не передавать локацию", + "precise": "Точная локация", + "metric_km23": "В радиусе 23 километров", + "metric_km12": "В радиусе 12 километров", + "metric_km5_8": "В радиусе 5,8 километров", + "metric_km2_9": "В радиусе 2,9 километров", + "metric_km1_5": "В радиусе 1,5 километров", + "metric_m700": "В радиусе 700 метров", + "metric_m350": "В радиусе 350 метров", + "metric_m200": "В радиусе 200 метров", + "metric_m90": "В радиусе 90 метров", + "metric_m50": "В радиусе 50 метров", + "imperial_mi15": "В радиусе 15 миль", + "imperial_mi7_3": "В радиусе 7,3 миль", + "imperial_mi3_6": "В радиусе 3,6 миль", + "imperial_mi1_8": "В радиусе 1,8 миль", + "imperial_mi0_9": "В радиусе 0,9 миль", + "imperial_mi0_5": "В радиусе 0,5 миль", + "imperial_mi0_2": "В радиусе 0,2 миль", + "imperial_ft600": "В радиусе 600 футов", + "imperial_ft300": "В радиусе 300 футов", + "imperial_ft150": "В радиусе 150 футов" + } + } +} \ No newline at end of file diff --git a/packages/web/public/i18n/locales/ru-RU/commandPalette.json b/packages/web/public/i18n/locales/ru-RU/commandPalette.json new file mode 100644 index 00000000..fc29806c --- /dev/null +++ b/packages/web/public/i18n/locales/ru-RU/commandPalette.json @@ -0,0 +1,51 @@ +{ + "emptyState": "Ничего не найдено.", + "page": { + "title": "Меню команд" + }, + "pinGroup": { + "label": "Закрепить группу команд" + }, + "unpinGroup": { + "label": "Открепить группу команд" + }, + "goto": { + "label": "Перейти", + "command": { + "messages": "Сообщения", + "map": "Карта", + "config": "Настройки", + "nodes": "Узлы" + } + }, + "manage": { + "label": "Управление", + "command": { + "switchNode": "Сменить узел", + "connectNewNode": "Подключить новый узел" + } + }, + "contextual": { + "label": "Контекстные", + "command": { + "qrCode": "QR-код", + "qrGenerator": "Генератор", + "qrImport": "Импорт", + "scheduleShutdown": "Запланировать выключение", + "scheduleReboot": "Перезагрузить устройство", + "resetNodeDb": "Сбросить базу узлов", + "dfuMode": "Режим DFU", + "factoryResetDevice": "Сброс устройства к заводским", + "factoryResetConfig": "Сброс конфигурации к заводским", + "disconnect": "Отключиться" + } + }, + "debug": { + "label": "Отладка", + "command": { + "reconfigure": "Переконфигурировать", + "clearAllStoredMessages": "Очистить все сохранённые сообщения", + "clearAllStores": "Очистить всё локальное хранилище" + } + } +} \ No newline at end of file diff --git a/packages/web/public/i18n/locales/ru-RU/common.json b/packages/web/public/i18n/locales/ru-RU/common.json new file mode 100644 index 00000000..7a9f4436 --- /dev/null +++ b/packages/web/public/i18n/locales/ru-RU/common.json @@ -0,0 +1,123 @@ +{ + "button": { + "apply": "Применить", + "backupKey": "Сохранить ключ", + "cancel": "Отмена", + "clearMessages": "Очистить сообщения", + "close": "Закрыть", + "confirm": "Подтвердить", + "delete": "Удалить", + "dismiss": "Отклонить", + "download": "Скачать", + "export": "Экспортировать", + "generate": "Сгенерировать", + "regenerate": "Перегенерировать", + "import": "Импортировать", + "message": "Сообщение", + "now": "Сейчас", + "ok": "ОК", + "print": "Печать", + "remove": "Удалить", + "requestNewKeys": "Запросить новые ключи", + "requestPosition": "Запросить позицию", + "reset": "Сбросить", + "save": "Сохранить", + "scanQr": "Сканировать QR-код", + "traceRoute": "Трассировка маршрута", + "submit": "Отправить" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Веб-клиент" + }, + "loading": "Загрузка...", + "unit": { + "cps": "симв/с", + "dbm": "дБм", + "hertz": "Гц", + "hop": { + "one": "Передача", + "plural": "Передачи" + }, + "hopsAway": { + "one": "{{count}} передача", + "plural": "{{count}} передач", + "unknown": "Неизвестное количество передач" + }, + "megahertz": "МГц", + "raw": "исх.", + "meter": { "one": "Метр", "plural": "Метра", "suffix": "м" }, + "kilometer": { "one": "Километр", "plural": "Километров", "suffix": "км" }, + "minute": { "one": "Минута", "plural": "Минут" }, + "hour": { "one": "Час", "plural": "Часов" }, + "millisecond": { + "one": "Миллисекунда", + "plural": "Миллисекунд", + "suffix": "мс" + }, + "second": { "one": "Секунда", "plural": "Секунд" }, + "day": { + "one": "День", + "plural": "Дней", + "today": "Сегодня", + "yesterday": "Вчера" + }, + "month": { "one": "Месяц", "plural": "Месяцев" }, + "year": { "one": "Год", "plural": "Лет" }, + "snr": "ОСШ", + "volt": { "one": "Вольт", "plural": "Вольт", "suffix": "В" }, + "record": { "one": "Запись", "plural": "Записи" }, + "degree": { "one": "Градус", "plural": "Градусов", "suffix": "°" } + }, + "security": { + "0bit": "Пусто", + "8bit": "8 бит", + "128bit": "128 бит", + "256bit": "256 бит" + }, + "unknown": { + "longName": "Неизвестно", + "shortName": "НЕИЗВ", + "notAvailable": "Н/Д", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "НЕ ЗАДАНО", + "fallbackName": "Meshtastic {{last4}}", + "node": "Узел", + "formValidation": { + "unsavedChanges": "Несохранённые изменения", + "tooBig": { + "string": "Слишком длинное, ожидалось не более {{maximum}} символов.", + "number": "Слишком большое, ожидалось число не более {{maximum}}.", + "bytes": "Слишком большой размер, ожидалось не более {{params.maximum}} байт." + }, + "tooSmall": { + "string": "Слишком короткое, ожидалось не менее {{minimum}} символов.", + "number": "Слишком маленькое, ожидалось число не менее {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Неверный формат, ожидался IPv4-адрес.", + "key": "Неверный формат, ожидался ключ в формате Base64 (PSK)." + }, + "invalidType": { + "number": "Неверный тип, ожидалось число." + }, + "pskLength": { + "0bit": "Ключ должен быть пустым.", + "8bit": "Ключ должен быть 8-битным предварительно разделённым ключом (PSK).", + "128bit": "Ключ должен быть 128-битным предварительно разделённым ключом (PSK).", + "256bit": "Ключ должен быть 256-битным предварительно разделённым ключом (PSK)." + }, + "required": { + "generic": "Это поле обязательно для заполнения.", + "managed": "Требуется хотя бы один административный ключ, если узел управляемый.", + "key": "Ключ обязателен." + }, + "invalidOverrideFreq": { + "number": "Неверный формат, ожидалось значение в диапазоне 410–930 МГц или 0 (по умолчанию)." + } + }, + "yes": "Да", + "no": "Нет" +} \ No newline at end of file diff --git a/packages/web/public/i18n/locales/ru-RU/dashboard.json b/packages/web/public/i18n/locales/ru-RU/dashboard.json new file mode 100644 index 00000000..484f9c19 --- /dev/null +++ b/packages/web/public/i18n/locales/ru-RU/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Подключённые устройства", + "description": "Управление вашими подключёнными устройствами Meshtastic.", + "connectionType_ble": "BLE", + "connectionType_serial": "Последовательный порт", + "connectionType_network": "Сеть", + "noDevicesTitle": "Нет подключённых устройств", + "noDevicesDescription": "Подключите новое устройство, чтобы начать.", + "button_newConnection": "Новое подключение" + } +} \ No newline at end of file diff --git a/packages/web/public/i18n/locales/ru-RU/deviceConfig.json b/packages/web/public/i18n/locales/ru-RU/deviceConfig.json new file mode 100644 index 00000000..38282e7c --- /dev/null +++ b/packages/web/public/i18n/locales/ru-RU/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Конфигурация", + "tabBluetooth": "Bluetooth", + "tabDevice": "Устройство", + "tabDisplay": "Дисплей", + "tabLora": "LoRa", + "tabNetwork": "Сеть", + "tabPosition": "Позиция", + "tabPower": "Питание", + "tabSecurity": "Безопасность" + }, + "sidebar": { + "label": "Модули" + }, + "device": { + "title": "Настройки устройства", + "description": "Параметры устройства", + "buttonPin": { + "description": "Переопределение контакта кнопки", + "label": "Контакт кнопки" + }, + "buzzerPin": { + "description": "Переопределение контакта зуммера", + "label": "Контакт зуммера" + }, + "disableTripleClick": { + "description": "Отключить тройное нажатие", + "label": "Отключить тройное нажатие" + }, + "doubleTapAsButtonPress": { + "description": "Рассматривать двойное касание как нажатие кнопки", + "label": "Двойное касание как нажатие" + }, + "ledHeartbeatDisabled": { + "description": "Отключить мигание светодиода по умолчанию", + "label": "Отключить мигание светодиода" + }, + "nodeInfoBroadcastInterval": { + "description": "Как часто транслировать информацию об узле", + "label": "Интервал трансляции информации об узле" + }, + "posixTimezone": { + "description": "Строка временной зоны POSIX для устройства", + "label": "Временная зона POSIX" + }, + "rebroadcastMode": { + "description": "Как обрабатывать ретрансляцию", + "label": "Режим ретрансляции" + }, + "role": { + "description": "Роль устройства в сети", + "label": "Роль" + } + }, + "bluetooth": { + "title": "Настройки Bluetooth", + "description": "Параметры модуля Bluetooth", + "note": "Примечание: Некоторые устройства (ESP32) не могут использовать Bluetooth и Wi-Fi одновременно.", + "enabled": { + "description": "Включить или отключить Bluetooth", + "label": "Включено" + }, + "pairingMode": { + "description": "Поведение при выборе PIN-кода.", + "label": "Режим сопряжения" + }, + "pin": { + "description": "PIN-код для сопряжения", + "label": "PIN-код" + } + }, + "display": { + "description": "Параметры дисплея устройства", + "title": "Настройки дисплея", + "headingBold": { + "description": "Выделение текста заголовка жирным", + "label": "Жирный заголовок" + }, + "carouselDelay": { + "description": "Скорость переключения между окнами", + "label": "Задержка карусели" + }, + "compassNorthTop": { + "description": "Фиксировать север вверху компаса", + "label": "Север вверху компаса" + }, + "displayMode": { + "description": "Вариант компоновки экрана", + "label": "Режим отображения" + }, + "displayUnits": { + "description": "Отображение метрических или имперских единиц", + "label": "Единицы измерения" + }, + "flipScreen": { + "description": "Повернуть экран на 180 градусов", + "label": "Перевернуть экран" + }, + "gpsDisplayUnits": { + "description": "Формат отображения координат", + "label": "Единицы отображения GPS" + }, + "oledType": { + "description": "Тип OLED-экрана, подключённого к устройству", + "label": "Тип OLED" + }, + "screenTimeout": { + "description": "Выключать дисплей через указанное время", + "label": "Таймаут экрана" + }, + "twelveHourClock": { + "description": "Использовать 12-часовой формат времени", + "label": "12-часовой формат" + }, + "wakeOnTapOrMotion": { + "description": "Пробуждать устройство по касанию или движению", + "label": "Пробуждение по касанию или движению" + } + }, + "lora": { + "title": "Настройки сети LoRa", + "description": "Параметры сети LoRa", + "bandwidth": { + "description": "Полоса пропускания канала в МГц", + "label": "Полоса пропускания" + }, + "boostedRxGain": { + "description": "Усиленное усиление приёма", + "label": "Усиленное усиление RX" + }, + "codingRate": { + "description": "Знаменатель кодовой скорости", + "label": "Кодовая скорость" + }, + "frequencyOffset": { + "description": "Смещение частоты для коррекции ошибок калибровки кварца", + "label": "Смещение частоты" + }, + "frequencySlot": { + "description": "Номер частотного канала LoRa", + "label": "Частотный слот" + }, + "hopLimit": { + "description": "Максимальное количество переприёмов", + "label": "Лимит переприёмов" + }, + "ignoreMqtt": { + "description": "Не передавать MQTT-сообщения по сети", + "label": "Игнорировать MQTT" + }, + "modemPreset": { + "description": "Используемый пресет модема", + "label": "Пресет модема" + }, + "okToMqtt": { + "description": "Если установлено \"true\", это означает, что пользователь разрешает загрузку пакетов в MQTT. Если \"false\", удалённые узлы не должны передавать пакеты в MQTT", + "label": "Разрешить MQTT" + }, + "overrideDutyCycle": { + "description": "Переопределение рабочего цикла", + "label": "Переопределить рабочий цикл" + }, + "overrideFrequency": { + "description": "Переопределение частоты", + "label": "Переопределить частоту" + }, + "region": { + "description": "Регион для вашего узла", + "label": "Регион" + }, + "spreadingFactor": { + "description": "Количество чирпов на символ", + "label": "Коэффициент расширения" + }, + "transmitEnabled": { + "description": "Включить/отключить передачу (TX) по радио LoRa", + "label": "Передача включена" + }, + "transmitPower": { + "description": "Максимальная мощность передачи", + "label": "Мощность передачи" + }, + "usePreset": { + "description": "Использовать один из заранее определённых пресетов модема", + "label": "Использовать пресет" + }, + "meshSettings": { + "description": "Параметры сети LoRa", + "label": "Настройки сети" + }, + "waveformSettings": { + "description": "Параметры формы сигнала LoRa", + "label": "Настройки формы сигнала" + }, + "radioSettings": { + "label": "Настройки радио", + "description": "Параметры радио LoRa" + } + }, + "network": { + "title": "Конфигурация Wi-Fi", + "description": "Настройки радиомодуля Wi-Fi", + "note": "Примечание: Некоторые устройства (ESP32) не могут использовать Bluetooth и Wi-Fi одновременно.", + "addressMode": { + "description": "Выбор способа назначения адреса", + "label": "Режим адресации" + }, + "dns": { + "description": "DNS-сервер", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Включить или отключить Ethernet-порт", + "label": "Включено" + }, + "gateway": { + "description": "Основной шлюз", + "label": "Шлюз" + }, + "ip": { + "description": "IP-адрес", + "label": "IP" + }, + "psk": { + "description": "Пароль сети", + "label": "Пароль" + }, + "ssid": { + "description": "Имя сети", + "label": "SSID" + }, + "subnet": { + "description": "Маска подсети", + "label": "Подсеть" + }, + "wifiEnabled": { + "description": "Включить или отключить радиомодуль Wi-Fi", + "label": "Включено" + }, + "meshViaUdp": { + "label": "Сеть через UDP" + }, + "ntpServer": { + "label": "NTP-сервер" + }, + "rsyslogServer": { + "label": "Rsyslog-сервер" + }, + "ethernetConfigSettings": { + "description": "Настройки Ethernet-порта", + "label": "Конфигурация Ethernet" + }, + "ipConfigSettings": { + "description": "Конфигурация IP", + "label": "Конфигурация IP" + }, + "ntpConfigSettings": { + "description": "Конфигурация NTP", + "label": "Конфигурация NTP" + }, + "rsyslogConfigSettings": { + "description": "Конфигурация Rsyslog", + "label": "Конфигурация Rsyslog" + }, + "udpConfigSettings": { + "description": "Конфигурация UDP через сеть", + "label": "Конфигурация UDP" + } + }, + "position": { + "title": "Настройки позиции", + "description": "Параметры модуля позиции", + "broadcastInterval": { + "description": "Как часто ваша позиция отправляется по сети", + "label": "Интервал трансляции" + }, + "enablePin": { + "description": "Переопределение контакта включения GPS-модуля", + "label": "Контакт включения" + }, + "fixedPosition": { + "description": "Не передавать данные GPS, а использовать заданную вручную позицию", + "label": "Фиксированная позиция" + }, + "gpsMode": { + "description": "Настройка режима GPS: включён, отключён или отсутствует", + "label": "Режим GPS" + }, + "gpsUpdateInterval": { + "description": "Как часто обновлять данные GPS", + "label": "Интервал обновления GPS" + }, + "positionFlags": { + "description": "Дополнительные поля для включения в сообщения о позиции. Чем больше полей выбрано, тем больше размер сообщения, что увеличивает время передачи и риск потери пакетов.", + "label": "Флаги позиции" + }, + "receivePin": { + "description": "Переопределение контакта RX GPS-модуля", + "label": "Контакт приёма" + }, + "smartPositionEnabled": { + "description": "Отправлять позицию только при значительном изменении местоположения", + "label": "Умная позиция" + }, + "smartPositionMinDistance": { + "description": "Минимальное расстояние (в метрах), которое должно быть пройдено перед отправкой обновления позиции", + "label": "Минимальное расстояние" + }, + "smartPositionMinInterval": { + "description": "Минимальный интервал (в секундах), который должен пройти перед отправкой обновления позиции", + "label": "Минимальный интервал" + }, + "transmitPin": { + "description": "Переопределение контакта TX GPS-модуля", + "label": "Контакт передачи" + }, + "intervalsSettings": { + "description": "Как часто отправлять обновления позиции", + "label": "Интервалы" + }, + "flags": { + "placeholder": "Выберите флаги позиции...", + "altitude": "Высота", + "altitudeGeoidalSeparation": "Разделение высоты по геоиду", + "altitudeMsl": "Высота над уровнем моря", + "dop": "Показатель точности (DOP), по умолчанию PDOP", + "hdopVdop": "Если выбран DOP, использовать значения HDOP/VDOP вместо PDOP", + "numSatellites": "Количество спутников", + "sequenceNumber": "Порядковый номер", + "timestamp": "Временная метка", + "unset": "Сбросить", + "vehicleHeading": "Направление движения", + "vehicleSpeed": "Скорость движения" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Используется для корректировки показаний напряжения батареи", + "label": "Коэффициент пересчёта АЦП" + }, + "ina219Address": { + "description": "Адрес монитора батареи INA219", + "label": "Адрес INA219" + }, + "lightSleepDuration": { + "description": "Продолжительность лёгкого сна устройства", + "label": "Длительность лёгкого сна" + }, + "minimumWakeTime": { + "description": "Минимальное время бодрствования устройства после получения пакета", + "label": "Минимальное время бодрствования" + }, + "noConnectionBluetoothDisabled": { + "description": "Если устройство не получает подключение по Bluetooth, модуль BLE будет отключён через указанное время", + "label": "Отключить Bluetooth при отсутствии подключения" + }, + "powerSavingEnabled": { + "description": "Выберите, если устройство питается от источника с низким током (например, солнечная батарея), чтобы минимизировать потребление энергии.", + "label": "Включить режим энергосбережения" + }, + "shutdownOnBatteryDelay": { + "description": "Автоматическое выключение узла через указанное время при питании от батареи, 0 — без ограничения", + "label": "Задержка выключения на батарее" + }, + "superDeepSleepDuration": { + "description": "Продолжительность сверхглубокого сна устройства", + "label": "Длительность сверхглубокого сна" + }, + "powerConfigSettings": { + "description": "Параметры модуля питания", + "label": "Конфигурация питания" + }, + "sleepSettings": { + "description": "Настройки сна для модуля питания", + "label": "Настройки сна" + } + }, + "security": { + "description": "Параметры конфигурации безопасности", + "title": "Настройки безопасности", + "button_backupKey": "Резервное копирование ключа", + "adminChannelEnabled": { + "description": "Разрешить входящее управление устройством через небезопасный устаревший административный канал", + "label": "Разрешить устаревший административный канал" + }, + "enableDebugLogApi": { + "description": "Выводить живой отладочный лог через последовательный порт, просматривать и экспортировать логи устройства (без данных о позиции) через Bluetooth", + "label": "Включить API отладочного лога" + }, + "managed": { + "description": "Если включено, параметры конфигурации устройства могут изменяться только удалённо узлом Remote Admin через административные сообщения. Не включайте эту опцию, если не настроен хотя бы один подходящий узел Remote Admin и его публичный ключ не сохранён в одном из полей выше.", + "label": "Управляемый режим" + }, + "privateKey": { + "description": "Используется для создания общего ключа с удалённым устройством", + "label": "Закрытый ключ" + }, + "publicKey": { + "description": "Отправляется другим узлам сети для вычисления общего секретного ключа", + "label": "Открытый ключ" + }, + "primaryAdminKey": { + "description": "Основной публичный ключ, авторизованный для отправки административных сообщений на этот узел", + "label": "Основной административный ключ" + }, + "secondaryAdminKey": { + "description": "Вторичный публичный ключ, авторизованный для отправки административных сообщений на этот узел", + "label": "Вторичный административный ключ" + }, + "serialOutputEnabled": { + "description": "Серийная консоль через Stream API", + "label": "Вывод через последовательный порт" + }, + "tertiaryAdminKey": { + "description": "Третичный публичный ключ, авторизованный для отправки административных сообщений на этот узел", + "label": "Третичный административный ключ" + }, + "adminSettings": { + "description": "Параметры администратора", + "label": "Настройки администратора" + }, + "loggingSettings": { + "description": "Параметры ведения лога", + "label": "Настройки лога" + } + } +} \ No newline at end of file diff --git a/packages/web/public/i18n/locales/ru-RU/dialog.json b/packages/web/public/i18n/locales/ru-RU/dialog.json new file mode 100644 index 00000000..54db3500 --- /dev/null +++ b/packages/web/public/i18n/locales/ru-RU/dialog.json @@ -0,0 +1,221 @@ +{ + "deleteMessages": { + "description": "Это действие удалит всю историю сообщений. Отменить это будет невозможно. Вы уверены, что хотите продолжить?", + "title": "Очистить все сообщения" + }, + "deviceName": { + "description": "Устройство перезагрузится после сохранения настроек.", + "longName": "Длинное имя", + "shortName": "Короткое имя", + "title": "Изменить имя устройства", + "validation": { + "longNameMax": "Длинное имя не должно превышать 40 символов", + "shortNameMax": "Короткое имя не должно превышать 4 символов", + "longNameMin": "Длинное имя должно содержать хотя бы 1 символ", + "shortNameMin": "Короткое имя должно содержать хотя бы 1 символ" + } + }, + "import": { + "description": "Импортировать набор каналов из Meshtastic URL.
Допустимые URL Meshtastic начинаются с \"https://meshtastic.org/e/...\"", + "error": { + "invalidUrl": "Некорректный Meshtastic URL" + }, + "channelPrefix": "Канал ", + "primary": "Основной ", + "doNotImport": "Не импортировать", + "channelName": "Имя", + "channelSlot": "Слот", + "channelSetUrl": "URL набора каналов/QR-кода", + "useLoraConfig": "Импортировать конфигурацию LoRa", + "presetDescription": "Текущая конфигурация LoRa будет заменена.", + "title": "Импорт каналов" + }, + "locationResponse": { + "title": "Местоположение: {{identifier}}", + "altitude": "Высота: ", + "coordinates": "Координаты: ", + "noCoordinates": "Координаты отсутствуют" + }, + "pkiRegenerateDialog": { + "title": "Перегенерировать предварительно разделённый ключ?", + "description": "Вы уверены, что хотите перегенерировать предварительно разделённый ключ?", + "regenerate": "Перегенерировать" + }, + "newDeviceDialog": { + "title": "Подключить новое устройство", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Последовательный порт", + "useHttps": "Использовать HTTPS", + "connecting": "Подключение...", + "connect": "Подключиться", + "connectionFailedAlert": { + "title": "Ошибка подключения", + "descriptionPrefix": "Не удалось подключиться к устройству. ", + "httpsHint": "При использовании HTTPS может потребоваться принять самоподписанный сертификат. ", + "openLinkPrefix": "Пожалуйста, откройте ", + "openLinkSuffix": " в новой вкладке", + "acceptTlsWarningSuffix": ", примите все предупреждения TLS, если они появятся, затем повторите попытку", + "learnMoreLink": "Узнать больше" + }, + "httpConnection": { + "label": "IP-адрес/Имя хоста", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "Ещё нет сопряжённых устройств.", + "newDeviceButton": "Новое устройство", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "Ещё нет сопряжённых устройств.", + "newDeviceButton": "Новое устройство", + "connectionFailed": "Ошибка подключения", + "deviceDisconnected": "Устройство отключено", + "unknownDevice": "Неизвестное устройство", + "errorLoadingDevices": "Ошибка загрузки устройств", + "unknownErrorLoadingDevices": "Неизвестная ошибка загрузки устройств" + }, + "validation": { + "requiresWebBluetooth": "Этот тип подключения требует <0>Web Bluetooth. Пожалуйста, используйте поддерживаемый браузер, например Chrome или Edge.", + "requiresWebSerial": "Этот тип подключения требует <0>Web Serial. Пожалуйста, используйте поддерживаемый браузер, например Chrome или Edge.", + "requiresSecureContext": "Это приложение требует <0>защищённого контекста. Пожалуйста, подключайтесь по HTTPS или через localhost.", + "additionallyRequiresSecureContext": "Кроме того, требуется <0>защищённый контекст. Пожалуйста, подключайтесь по HTTPS или через localhost." + } + }, + "nodeDetails": { + "message": "Сообщение", + "requestPosition": "Запросить местоположение", + "traceRoute": "Трассировка маршрута", + "airTxUtilization": "Использование эфира (TX)", + "allRawMetrics": "Все исходные метрики:", + "batteryLevel": "Уровень заряда батареи", + "channelUtilization": "Использование канала", + "details": "Детали:", + "deviceMetrics": "Метрики устройства:", + "hardware": "Оборудование: ", + "lastHeard": "Последний сигнал: ", + "nodeHexPrefix": "Hex-адрес узла: ", + "nodeNumber": "Номер узла: ", + "position": "Позиция:", + "role": "Роль: ", + "uptime": "Время работы: ", + "voltage": "Напряжение", + "title": "Детали узла для {{identifier}}", + "ignoreNode": "Игнорировать узел", + "removeNode": "Удалить узел", + "unignoreNode": "Перестать игнорировать узел", + "security": "Безопасность:", + "publicKey": "Публичный ключ: ", + "messageable": "Доступен для сообщений: ", + "KeyManuallyVerifiedTrue": "Публичный ключ подтверждён вручную", + "KeyManuallyVerifiedFalse": "Публичный ключ не подтверждён вручную" + }, + "pkiBackup": { + "loseKeysWarning": "Если вы потеряете ключи, вам потребуется сбросить устройство.", + "secureBackup": "Важно сделать резервную копию ваших публичных и приватных ключей и хранить её в безопасности!", + "footer": "=== КОНЕЦ КЛЮЧЕЙ ===", + "header": "=== КЛЮЧИ MESHTASTIC ДЛЯ {{longName}} ({{shortName}}) ===", + "privateKey": "Приватный ключ:", + "publicKey": "Публичный ключ:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Резервное копирование ключей" + }, + "pkiBackupReminder": { + "description": "Рекомендуем регулярно делать резервную копию ключей. Хотите сделать резервную копию сейчас?", + "title": "Напоминание о резервном копировании", + "remindLaterPrefix": "Напомнить через", + "remindNever": "Больше не напоминать", + "backupNow": "Сделать резервную копию сейчас" + }, + "pkiRegenerate": { + "description": "Вы уверены, что хотите перегенерировать пару ключей?", + "title": "Перегенерировать пару ключей" + }, + "qr": { + "addChannels": "Добавить каналы", + "replaceChannels": "Заменить каналы", + "description": "Текущая конфигурация LoRa также будет включена.", + "sharableUrl": "Ссылка для совместного доступа", + "title": "Сгенерировать QR-код" + }, + "reboot": { + "title": "Перезагрузка устройства", + "description": "Перезагрузить устройство сейчас или запланировать перезагрузку подключённого узла. При желании можно перезагрузиться в режим OTA (по воздуху).", + "ota": "Перезагрузиться в режим OTA", + "enterDelay": "Введите задержку", + "scheduled": "Перезагрузка запланирована", + "schedule": "Запланировать перезагрузку", + "now": "Перезагрузить сейчас", + "cancel": "Отменить запланированную перезагрузку" + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "Это удалит узел с устройства и запросит новые ключи.", + "keyMismatchReasonSuffix": ". Это связано с тем, что текущий публичный ключ удалённого узла не совпадает с ранее сохранённым ключом для этого узла.", + "unableToSendDmPrefix": "Ваш узел не может отправить прямое сообщение узлу: " + }, + "acceptNewKeys": "Принять новые ключи", + "title": "Несовпадение ключей — {{identifier}}" + }, + "removeNode": { + "description": "Вы уверены, что хотите удалить этот узел?", + "title": "Удалить узел?" + }, + "shutdown": { + "title": "Запланировать выключение", + "description": "Выключить подключённый узел через X минут." + }, + "traceRoute": { + "routeToDestination": "Маршрут до места назначения:", + "routeBack": "Обратный маршрут:" + }, + "tracerouteResponse": { + "title": "Трассировка: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Да, я знаю, что делаю", + "conjunction": " и статью в блоге о ", + "postamble": " и понимаю последствия изменения роли.", + "preamble": "Я прочитал ", + "choosingRightDeviceRole": "Выбор правильной роли устройства", + "deviceRoleDocumentation": "Документация по ролям устройств", + "title": "Вы уверены?" + }, + "managedMode": { + "confirmUnderstanding": "Да, я знаю, что делаю", + "title": "Вы уверены?", + "description": "Включение управляемого режима блокирует клиентским приложениям (включая веб-клиент) возможность записывать конфигурации в радио. После включения конфигурации радио можно изменять только через сообщения удалённого администратора. Эта настройка не обязательна для удалённого администрирования узлов." + }, + "clientNotification": { + "title": "Уведомление клиента", + "TraceRoute can only be sent once every 30 seconds": "TraceRoute можно отправлять не чаще одного раза в 30 секунд", + "Compromised keys were detected and regenerated.": "Обнаружены скомпрометированные ключи и они были перегенерарованы." + }, + "resetNodeDb": { + "title": "Сбросить базу данных узлов", + "description": "Это удалит все узлы из базы данных подключённого устройства и очистит всю историю сообщений в клиенте. Это действие нельзя отменить. Вы уверены, что хотите продолжить?", + "confirm": "Сбросить базу данных узлов", + "failedTitle": "Произошла ошибка при сбросе базы данных узлов. Пожалуйста, попробуйте ещё раз." + }, + "clearAllStores": { + "title": "Очистить всё локальное хранилище", + "description": "Это удалит все локально сохранённые данные, включая историю сообщений и базы данных узлов для всех ранее подключённых устройств. После этого вам потребуется заново подключиться к узлу. Это действие нельзя отменить. Вы уверены, что хотите продолжить?", + "confirm": "Очистить всё локальное хранилище", + "failedTitle": "Произошла ошибка при очистке локального хранилища. Пожалуйста, попробуйте ещё раз." + }, + "factoryResetDevice": { + "title": "Сброс устройства к заводским настройкам", + "description": "Это выполнит сброс подключённого устройства к заводским настройкам, удалив все конфигурации и данные на устройстве, а также все узлы и сообщения, сохранённые в клиенте. Это действие нельзя отменить. Вы уверены, что хотите продолжить?", + "confirm": "Сбросить устройство к заводским настройкам", + "failedTitle": "Произошла ошибка при сбросе устройства. Пожалуйста, попробуйте ещё раз." + }, + "factoryResetConfig": { + "title": "Сброс конфигурации к заводским настройкам", + "description": "Это выполнит сброс конфигурации подключённого устройства к заводским настройкам, удалив все конфигурации на устройстве. Это действие нельзя отменить. Вы уверены, что хотите продолжить?", + "confirm": "Сбросить конфигурацию к заводским настройкам", + "failedTitle": "Произошла ошибка при сбросе конфигурации. Пожалуйста, попробуйте ещё раз." + } +} diff --git a/packages/web/public/i18n/locales/ru-RU/map.json b/packages/web/public/i18n/locales/ru-RU/map.json new file mode 100644 index 00000000..3d699819 --- /dev/null +++ b/packages/web/public/i18n/locales/ru-RU/map.json @@ -0,0 +1,38 @@ +{ + "maplibre": { + "GeolocateControl.FindMyLocation": "Найти моё местоположение", + "NavigationControl.ZoomIn": "Увеличить", + "NavigationControl.ZoomOut": "Уменьшить", + "CooperativeGesturesHandler.WindowsHelpText": "Используйте Ctrl + прокрутку для масштабирования карты", + "CooperativeGesturesHandler.MacHelpText": "Используйте ⌘ + прокрутку для масштабирования карты", + "CooperativeGesturesHandler.MobileHelpText": "Используйте два пальца для перемещения по карте" + }, + "layerTool": { + "nodeMarkers": "Показать узлы", + "directNeighbors": "Показать прямые соединения", + "remoteNeighbors": "Показать удалённые соединения", + "positionPrecision": "Показать точность позиции", + "traceroutes": "Показать маршруты", + "waypoints": "Показать точки маршрута" + }, + "mapMenu": { + "locateAria": "Найти мой узел", + "layersAria": "Изменить стиль карты" + }, + "waypointDetail": { + "edit": "Редактировать", + "description": "Описание:", + "createdBy": "Отредактировано:", + "createdDate": "Создано:", + "updated": "Обновлено:", + "expires": "Истекает:", + "distance": "Расстояние:", + "bearing": "Абсолютный азимут:", + "lockedTo": "Заблокировано:", + "latitude": "Широта:", + "longitude": "Долгота:" + }, + "myNode": { + "tooltip": "Это устройство" + } +} diff --git a/packages/web/public/i18n/locales/ru-RU/messages.json b/packages/web/public/i18n/locales/ru-RU/messages.json new file mode 100644 index 00000000..b053dd3b --- /dev/null +++ b/packages/web/public/i18n/locales/ru-RU/messages.json @@ -0,0 +1,39 @@ +{ + "page": { + "title": "Сообщения: {{chatName}}", + "placeholder": "Введите сообщение" + }, + "emptyState": { + "title": "Выберите чат", + "text": "Сообщений пока нет." + }, + "selectChatPrompt": { + "text": "Выберите канал или узел, чтобы начать обмен сообщениями." + }, + "sendMessage": { + "placeholder": "Введите ваше сообщение здесь...", + "sendButton": "Отправить" + }, + "actionsMenu": { + "addReactionLabel": "Добавить реакцию", + "replyLabel": "Ответить" + }, + "deliveryStatus": { + "delivered": { + "label": "Сообщение доставлено", + "displayText": "Доставлено" + }, + "failed": { + "label": "Не удалось доставить сообщение", + "displayText": "Доставка не удалась" + }, + "unknown": { + "label": "Статус сообщения неизвестен", + "displayText": "Неизвестный статус" + }, + "waiting": { + "label": "Отправка сообщения", + "displayText": "Ожидание доставки" + } + } +} diff --git a/packages/web/public/i18n/locales/ru-RU/moduleConfig.json b/packages/web/public/i18n/locales/ru-RU/moduleConfig.json new file mode 100644 index 00000000..9ad42b52 --- /dev/null +++ b/packages/web/public/i18n/locales/ru-RU/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Подсветка", + "tabAudio": "Аудио", + "tabCannedMessage": "Шаблоны", + "tabDetectionSensor": "Датчик обнаружения", + "tabExternalNotification": "Внешние уведомления", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Информация о соседах", + "tabPaxcounter": "Счётчик людей", + "tabRangeTest": "Тест дальности", + "tabSerial": "Последовательный порт", + "tabStoreAndForward": "Хранение и пересылка", + "tabTelemetry": "Телеметрия" + }, + "ambientLighting": { + "title": "Настройки подсветки", + "description": "Настройки модуля подсветки", + "ledState": { + "label": "Состояние LED", + "description": "Включить или выключить LED" + }, + "current": { + "label": "Ток", + "description": "Устанавливает ток для выхода LED. По умолчанию 10" + }, + "red": { + "label": "Красный", + "description": "Уровень красного LED. Значения от 0 до 255" + }, + "green": { + "label": "Зелёный", + "description": "Уровень зелёного LED. Значения от 0 до 255" + }, + "blue": { + "label": "Синий", + "description": "Уровень синего LED. Значения от 0 до 255" + } + }, + "audio": { + "title": "Настройки аудио", + "description": "Настройки модуля аудио", + "codec2Enabled": { + "label": "Codec 2 включён", + "description": "Включить кодирование аудио Codec 2" + }, + "pttPin": { + "label": "PTT контакт", + "description": "Контакт GPIO для PTT" + }, + "bitrate": { + "label": "Битрейт", + "description": "Битрейт для кодирования аудио" + }, + "i2sWs": { + "label": "i2S WS", + "description": "Контакт GPIO для i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "Контакт GPIO для i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "Контакт GPIO для i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "Контакт GPIO для i2S SCK" + } + }, + "cannedMessage": { + "title": "Настройки шаблонов сообщений", + "description": "Настройки модуля шаблонов сообщений", + "moduleEnabled": { + "label": "Модуль включён", + "description": "Включить шаблоны сообщений" + }, + "rotary1Enabled": { + "label": "Энкодер #1 включён", + "description": "Включить поворотный энкодер" + }, + "inputbrokerPinA": { + "label": "Контакт энкодера A", + "description": "Значение контакта GPIO (1-39) для порта A энкодера" + }, + "inputbrokerPinB": { + "label": "Контакт энкодера B", + "description": "Значение контакта GPIO (1-39) для порта B энкодера" + }, + "inputbrokerPinPress": { + "label": "Контакт нажатия энкодера", + "description": "Значение контакта GPIO (1-39) для нажатия энкодера" + }, + "inputbrokerEventCw": { + "label": "Событие по часовой", + "description": "Выберите событие." + }, + "inputbrokerEventCcw": { + "label": "Событие против часовой", + "description": "Выберите событие." + }, + "inputbrokerEventPress": { + "label": "Событие нажатия", + "description": "Выберите событие" + }, + "updown1Enabled": { + "label": "Вверх/вниз включено", + "description": "Включить энкодер вверх/вниз" + }, + "allowInputSource": { + "label": "Разрешить источник ввода", + "description": "Выберите из: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Отправлять звонок", + "description": "Отправлять символ звонка с каждым сообщением" + } + }, + "detectionSensor": { + "title": "Настройки датчика обнаружения", + "description": "Настройки модуля датчика обнаружения", + "enabled": { + "label": "Включено", + "description": "Включить или отключить модуль датчика обнаружения" + }, + "minimumBroadcastSecs": { + "label": "Минимальный интервал передачи (сек)", + "description": "Интервал в секундах, как часто отправлять сообщение в сеть при обнаружении изменения состояния" + }, + "stateBroadcastSecs": { + "label": "Интервал передачи состояния (сек)", + "description": "Интервал в секундах, как часто отправлять сообщение в сеть с текущим состоянием, независимо от изменений" + }, + "sendBell": { + "label": "Отправлять звонок", + "description": "Отправлять ASCII-звонок с сообщением об оповещении" + }, + "name": { + "label": "Дружественное имя", + "description": "Используется для форматирования сообщения, отправляемого в сеть, максимум 20 символов" + }, + "monitorPin": { + "label": "Контакт мониторинга", + "description": "Контакт GPIO для мониторинга изменений состояния" + }, + "detectionTriggerType": { + "label": "Тип триггера обнаружения", + "description": "Тип события триггера, который будет использоваться" + }, + "usePullup": { + "label": "Использовать подтяжку", + "description": "Использовать режим INPUT_PULLUP для контакта GPIO" + } + }, + "externalNotification": { + "title": "Настройки внешних уведомлений", + "description": "Настройка модуля внешних уведомлений", + "enabled": { + "label": "Модуль включён", + "description": "Включить внешние уведомления" + }, + "outputMs": { + "label": "Длительность выхода (мс)", + "description": "Длительность выхода в миллисекундах" + }, + "output": { + "label": "Выход", + "description": "Выход" + }, + "outputVibra": { + "label": "Вибрационный выход", + "description": "Вибрационный выход" + }, + "outputBuzzer": { + "label": "Звуковой выход", + "description": "Звуковой выход" + }, + "active": { + "label": "Активен", + "description": "Активен" + }, + "alertMessage": { + "label": "Сообщение оповещения", + "description": "Сообщение оповещения" + }, + "alertMessageVibra": { + "label": "Вибрационное оповещение", + "description": "Вибрационное оповещение" + }, + "alertMessageBuzzer": { + "label": "Звуковое оповещение", + "description": "Звуковое оповещение" + }, + "alertBell": { + "label": "Оповещение звонком", + "description": "Следует ли срабатывать оповещение при получении входящего звонка?" + }, + "alertBellVibra": { + "label": "Вибрация при звонке", + "description": "Вибрация при звонке" + }, + "alertBellBuzzer": { + "label": "Звук при звонке", + "description": "Звук при звонке" + }, + "usePwm": { + "label": "Использовать ШИМ", + "description": "Использовать ШИМ" + }, + "nagTimeout": { + "label": "Таймаут напоминания", + "description": "Таймаут напоминания" + }, + "useI2sAsBuzzer": { + "label": "Использовать I²S как зуммер", + "description": "Назначить контакт I²S как выход зуммера" + } + }, + "mqtt": { + "title": "Настройки MQTT", + "description": "Настройки модуля MQTT", + "enabled": { + "label": "Включено", + "description": "Включить или отключить MQTT" + }, + "address": { + "label": "Адрес сервера MQTT", + "description": "Адрес сервера MQTT для стандартных/пользовательских серверов" + }, + "username": { + "label": "Имя пользователя MQTT", + "description": "Имя пользователя MQTT для стандартных/пользовательских серверов" + }, + "password": { + "label": "Пароль MQTT", + "description": "Пароль MQTT для стандартных/пользовательских серверов" + }, + "encryptionEnabled": { + "label": "Шифрование включено", + "description": "Включить или отключить шифрование MQTT. Примечание: все сообщения отправляются на брокер MQTT незашифрованными, если эта опция не включена, даже если ваши каналы связи зашифрованы. Это включает данные о местоположении." + }, + "jsonEnabled": { + "label": "JSON включён", + "description": "Отправлять/принимать JSON-пакеты по MQTT" + }, + "tlsEnabled": { + "label": "TLS включён", + "description": "Включить или отключить TLS" + }, + "root": { + "label": "Корневой топик", + "description": "Корневой топик MQTT для стандартных/пользовательских серверов" + }, + "proxyToClientEnabled": { + "label": "Прокси MQTT для клиента включено", + "description": "Использует сетевое подключение для проксирования сообщений MQTT клиенту." + }, + "mapReportingEnabled": { + "label": "Отправка данных на карту включена", + "description": "Ваш узел будет периодически отправлять незашифрованный пакет отчёта на карту на настроенный сервер MQTT, это включает ID, короткое и длинное имя, приблизительное местоположение, модель оборудования, роль, версию прошивки, регион LoRa, пресет модема и имя основного канала." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Интервал публикации отчёта (сек)", + "description": "Интервал в секундах для публикации отчётов на карте" + }, + "positionPrecision": { + "label": "Приблизительное местоположение", + "description": "Разделяемая позиция будет точной в пределах этого расстояния", + "options": { + "metric_km23": "В пределах 23 км", + "metric_km12": "В пределах 12 км", + "metric_km5_8": "В пределах 5,8 км", + "metric_km2_9": "В пределах 2,9 км", + "metric_km1_5": "В пределах 1,5 км", + "metric_m700": "В пределах 700 м", + "metric_m350": "В пределах 350 м", + "metric_m200": "В пределах 200 м", + "metric_m90": "В пределах 90 м", + "metric_m50": "В пределах 50 м", + "imperial_mi15": "В пределах 15 миль", + "imperial_mi7_3": "В пределах 7,3 миль", + "imperial_mi3_6": "В пределах 3,6 миль", + "imperial_mi1_8": "В пределах 1,8 миль", + "imperial_mi0_9": "В пределах 0,9 миль", + "imperial_mi0_5": "В пределах 0,5 миль", + "imperial_mi0_2": "В пределах 0,2 миль", + "imperial_ft600": "В пределах 600 футов", + "imperial_ft300": "В пределах 300 футов", + "imperial_ft150": "В пределах 150 футов" + } + } + } + }, + "neighborInfo": { + "title": "Настройки информации о соседах", + "description": "Настройки модуля информации о соседах", + "enabled": { + "label": "Включено", + "description": "Включить или отключить модуль информации о соседах" + }, + "updateInterval": { + "label": "Интервал обновления", + "description": "Интервал в секундах, как часто пытаться отправлять информацию о соседах в сеть" + } + }, + "paxcounter": { + "title": "Настройки счётчика людей", + "description": "Настройки модуля счётчика людей", + "enabled": { + "label": "Модуль включён", + "description": "Включить счётчик людей" + }, + "paxcounterUpdateInterval": { + "label": "Интервал обновления (сек)", + "description": "Как долго ждать между отправкой пакетов счётчика" + }, + "wifiThreshold": { + "label": "Порог RSSI Wi-Fi", + "description": "При каком уровне RSSI Wi-Fi счётчик должен увеличиваться. По умолчанию -80." + }, + "bleThreshold": { + "label": "Порог RSSI BLE", + "description": "При каком уровне RSSI BLE счётчик должен увеличиваться. По умолчанию -80." + } + }, + "rangeTest": { + "title": "Настройки теста дальности", + "description": "Настройки модуля теста дальности", + "enabled": { + "label": "Модуль включён", + "description": "Включить тест дальности" + }, + "sender": { + "label": "Интервал сообщений", + "description": "Как долго ждать между отправкой тестовых пакетов" + }, + "save": { + "label": "Сохранить CSV в память", + "description": "Только для ESP32" + } + }, + "serial": { + "title": "Настройки последовательного порта", + "description": "Настройки модуля последовательного порта", + "enabled": { + "label": "Модуль включён", + "description": "Включить вывод через последовательный порт" + }, + "echo": { + "label": "Эхо", + "description": "Все отправленные пакеты будут возвращаться обратно на ваше устройство" + }, + "rxd": { + "label": "Контакт приёма", + "description": "Установите контакт GPIO как RXD." + }, + "txd": { + "label": "Контакт передачи", + "description": "Установите контакт GPIO как TXD." + }, + "baud": { + "label": "Скорость (бод)", + "description": "Скорость передачи данных" + }, + "timeout": { + "label": "Таймаут", + "description": "Время ожидания в секундах, после которого пакет считается завершённым" + }, + "mode": { + "label": "Режим", + "description": "Выберите режим" + }, + "overrideConsoleSerialPort": { + "label": "Переопределить консольный порт", + "description": "Если у вас подключён последовательный порт к консоли, это переопределит его." + } + }, + "storeForward": { + "title": "Настройки хранения и пересылки", + "description": "Настройки модуля хранения и пересылки", + "enabled": { + "label": "Модуль включён", + "description": "Включить хранение и пересылку" + }, + "heartbeat": { + "label": "Heartbeat включён", + "description": "Включить heartbeat для хранения и пересылки" + }, + "records": { + "label": "Количество записей", + "description": "Количество записей для хранения" + }, + "historyReturnMax": { + "label": "Максимум возвращаемых записей", + "description": "Максимальное количество возвращаемых записей" + }, + "historyReturnWindow": { + "label": "Окно возвращаемых записей", + "description": "Максимальное количество возвращаемых записей" + } + }, + "telemetry": { + "title": "Настройки телеметрии", + "description": "Настройки модуля телеметрии", + "deviceUpdateInterval": { + "label": "Интервал обновления устройства", + "description": "Интервал обновления метрик устройства (сек)" + }, + "environmentUpdateInterval": { + "label": "Интервал обновления окружающей среды (сек)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Модуль включён", + "description": "Включить телеметрию окружающей среды" + }, + "environmentScreenEnabled": { + "label": "Отображать на экране", + "description": "Показывать модуль телеметрии на OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Отображать в Фаренгейтах", + "description": "Отображать температуру в Фаренгейтах" + }, + "airQualityEnabled": { + "label": "Качество воздуха включено", + "description": "Включить телеметрию качества воздуха" + }, + "airQualityInterval": { + "label": "Интервал обновления качества воздуха", + "description": "Как часто отправлять данные о качестве воздуха в сеть" + }, + "powerMeasurementEnabled": { + "label": "Измерение мощности включено", + "description": "Включить телеметрию измерения мощности" + }, + "powerUpdateInterval": { + "label": "Интервал обновления мощности", + "description": "Как часто отправлять данные о мощности в сеть" + }, + "powerScreenEnabled": { + "label": "Экран мощности включён", + "description": "Включить экран телеметрии мощности" + } + } +} diff --git a/packages/web/public/i18n/locales/ru-RU/nodes.json b/packages/web/public/i18n/locales/ru-RU/nodes.json new file mode 100644 index 00000000..3500fae2 --- /dev/null +++ b/packages/web/public/i18n/locales/ru-RU/nodes.json @@ -0,0 +1,59 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Публичный ключ включён" + }, + "noPublicKey": { + "label": "Нет публичного ключа" + }, + "directMessage": { + "label": "Прямое сообщение {{shortName}}" + }, + "favorite": { + "label": "Избранное", + "tooltip": "Добавить или убрать этот узел из избранного" + }, + "notFavorite": { + "label": "Не в избранном" + }, + "error": { + "label": "Ошибка", + "text": "Произошла ошибка при получении данных об узле. Пожалуйста, попробуйте позже." + }, + "status": { + "heard": "Услышан", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Высота" + }, + "channelUtil": { + "label": "Использование канала" + }, + "airtimeUtil": { + "label": "Использование эфирного времени" + } + }, + "nodesTable": { + "headings": { + "longName": "Полное имя", + "connection": "Подключение", + "lastHeard": "Последний контакт", + "encryption": "Шифрование", + "model": "Модель", + "macAddress": "MAC-адрес" + }, + "connectionStatus": { + "direct": "Прямое", + "away": "недоступен", + "viaMqtt": ", через MQTT" + } + }, + "actions": { + "added": "Добавлено", + "removed": "Удалено", + "ignoreNode": "Игнорировать узел", + "unignoreNode": "Перестать игнорировать узел", + "requestPosition": "Запросить позицию" + } +} \ No newline at end of file diff --git a/packages/web/public/i18n/locales/ru-RU/ui.json b/packages/web/public/i18n/locales/ru-RU/ui.json new file mode 100644 index 00000000..8ea02d95 --- /dev/null +++ b/packages/web/public/i18n/locales/ru-RU/ui.json @@ -0,0 +1,221 @@ +{ + "navigation": { + "title": "Навигация", + "messages": "Сообщения", + "map": "Карта", + "config": "Настройки", + "channels": "Каналы", + "radioConfig": "Настройки радио", + "moduleConfig": "Настройки модуля", + "channelConfig": "Настройки канала", + "nodes": "Узлы" + }, + "app": { + "title": "Meshtastic", + "logo": "Логотип Meshtastic" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Открыть боковую панель", + "close": "Закрыть боковую панель" + } + }, + "deviceInfo": { + "volts": "{{voltage}} вольт", + "firmware": { + "title": "Прошивка", + "version": "в{{version}}", + "buildDate": "Дата сборки: {{date}}" + }, + "deviceName": { + "title": "Имя устройства", + "changeName": "Изменить имя устройства", + "placeholder": "Введите имя устройства" + }, + "editDeviceName": "Редактировать имя устройства" + } + }, + "batteryStatus": { + "charging": "{{level}}% зарядки", + "pluggedIn": "Подключено к сети", + "title": "Аккумулятор" + }, + "search": { + "nodes": "Поиск узлов...", + "channels": "Поиск каналов...", + "commandPalette": "Поиск команд..." + }, + "toast": { + "positionRequestSent": { "title": "Запрос позиции отправлен." }, + "requestingPosition": { "title": "Запрос позиции, пожалуйста, подождите..." }, + "sendingTraceroute": { "title": "Отправка трассировки, пожалуйста, подождите..." }, + "tracerouteSent": { "title": "Трассировка отправлена." }, + "savedChannel": { "title": "Сохранённый канал: {{channelName}}" }, + "messages": { + "pkiEncryption": { "title": "Чат использует PKI-шифрование." }, + "pskEncryption": { "title": "Чат использует PSK-шифрование." } + }, + "configSaveError": { + "title": "Ошибка сохранения настроек", + "description": "Произошла ошибка при сохранении конфигурации." + }, + "validationError": { + "title": "Ошибки в конфигурации", + "description": "Пожалуйста, исправьте ошибки в конфигурации перед сохранением." + }, + "saveSuccess": { + "title": "Сохранение настроек", + "description": "Изменение конфигурации {{case}} сохранено." + }, + "saveAllSuccess": { + "title": "Сохранено", + "description": "Все изменения конфигурации сохранены." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} избранное.", + "action": { + "added": "Добавлено", + "removed": "Удалено", + "to": "в", + "from": "из" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} список игнорирования", + "action": { + "added": "Добавлено", + "removed": "Удалено", + "to": "в", + "from": "из" + } + } + }, + "notifications": { + "copied": { + "label": "Скопировано!" + }, + "copyToClipboard": { + "label": "Скопировать в буфер обмена" + }, + "hidePassword": { + "label": "Скрыть пароль" + }, + "showPassword": { + "label": "Показать пароль" + }, + "deliveryStatus": { + "delivered": "Доставлено", + "failed": "Доставка не удалась", + "waiting": "Ожидание", + "unknown": "Неизвестно" + } + }, + "general": { + "label": "Общие" + }, + "hardware": { + "label": "Аппаратное обеспечение" + }, + "metrics": { + "label": "Метрики" + }, + "role": { + "label": "Роль" + }, + "filter": { + "label": "Фильтр" + }, + "advanced": { + "label": "Дополнительно" + }, + "clearInput": { + "label": "Очистить ввод" + }, + "resetFilters": { + "label": "Сбросить фильтры" + }, + "nodeName": { + "label": "Имя/номер узла", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Использование эфирного времени (%)", + "short": "Исп. эфира (%)" + }, + "batteryLevel": { + "label": "Уровень заряда (%)", + "labelText": "Уровень заряда (%): {{value}}" + }, + "batteryVoltage": { + "label": "Напряжение аккумулятора (В)", + "title": "Напряжение" + }, + "channelUtilization": { + "label": "Использование канала (%)", + "short": "Исп. канала (%)" + }, + "hops": { + "direct": "Прямое", + "label": "Количество переходов", + "text": "Количество переходов: {{value}}" + }, + "lastHeard": { + "label": "Последний контакт", + "labelText": "Последний контакт: {{value}}", + "nowLabel": "Сейчас" + }, + "snr": { + "label": "Отношение сигнал/шум (дБ)" + }, + "favorites": { + "label": "Избранное" + }, + "hide": { + "label": "Скрыть" + }, + "showOnly": { + "label": "Показать только" + }, + "viaMqtt": { + "label": "Подключено через MQTT" + }, + "hopsUnknown": { + "label": "Неизвестное количество переходов" + }, + "showUnheard": { + "label": "Неизвестно время последнего контакта" + }, + "language": { + "label": "Язык", + "changeLanguage": "Изменить язык" + }, + "theme": { + "dark": "Тёмная", + "light": "Светлая", + "system": "Автоматическая", + "changeTheme": "Изменить цветовую схему" + }, + "errorPage": { + "title": "Это немного неловко...", + "description1": "Нам очень жаль, но в веб-клиенте произошла ошибка, из-за которой он завершил работу.
Такого не должно было произойти, и мы усердно работаем над исправлением.", + "description2": "Лучший способ предотвратить повторение этой ошибки — сообщить нам о проблеме.", + "reportInstructions": "Пожалуйста, укажите в отчёте следующую информацию:", + "reportSteps": { + "step1": "Что вы делали, когда произошла ошибка", + "step2": "Что вы ожидали увидеть", + "step3": "Что произошло на самом деле", + "step4": "Любая другая актуальная информация" + }, + "reportLink": "Вы можете сообщить о проблеме на нашем <0>GitHub", + "dashboardLink": "Вернуться на <0>главную панель", + "detailsSummary": "Детали ошибки", + "errorMessageLabel": "Сообщение об ошибке:", + "stackTraceLabel": "Трассировка стека:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Работает на <0>▲ Vercel | Meshtastic® — зарегистрированный товарный знак Meshtastic LLC. | <1>Юридическая информация", + "commitSha": "Коммит SHA: {{sha}}" + } +} diff --git a/packages/web/src/i18n-config.ts b/packages/web/src/i18n-config.ts index 8b8de390..c05113d9 100644 --- a/packages/web/src/i18n-config.ts +++ b/packages/web/src/i18n-config.ts @@ -18,6 +18,7 @@ export const supportedLanguages: Lang[] = [ { code: "en", name: "English", flag: "🇺🇸" }, { code: "fr", name: "Français", flag: "🇫🇷" }, { code: "sv", name: "Svenska", flag: "🇸🇪" }, + { code: "ru", name: "Русский", flag: "🇷🇺​​" }, ]; export const FALLBACK_LANGUAGE_CODE: LangCode = "en"; @@ -45,6 +46,7 @@ i18next fr: ["fr-FR", FALLBACK_LANGUAGE_CODE], sv: ["sv-SE", FALLBACK_LANGUAGE_CODE], de: ["de-DE", FALLBACK_LANGUAGE_CODE], + ru: ["ru-RU", FALLBACK_LANGUAGE_CODE], }, fallbackNS: ["common", "ui", "dialog"], debug: import.meta.env.MODE === "development",