diff --git a/SRV/locales/en/LC_MESSAGES/services.mo b/SRV/locales/en/LC_MESSAGES/services.mo new file mode 100644 index 0000000..7dc15af Binary files /dev/null and b/SRV/locales/en/LC_MESSAGES/services.mo differ diff --git a/SRV/locales/en/LC_MESSAGES/services.po b/SRV/locales/en/LC_MESSAGES/services.po new file mode 100644 index 0000000..b9a2ba1 --- /dev/null +++ b/SRV/locales/en/LC_MESSAGES/services.po @@ -0,0 +1,255 @@ +# English translations for PROJECT. +# Copyright (C) 2025 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2025-07-08 15:52+0500\n" +"PO-Revision-Date: 2025-07-08 15:54+0500\n" +"Last-Translator: FULL NAME \n" +"Language: en\n" +"Language-Team: en \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.17.0\n" + +#: services/arp_service.py:101 +msgid "Доступные устройства в сети:" +msgstr "Available devices on the network:" + +#: services/arp_service.py:102 +msgid "IP" +msgstr "IP" + +#: services/arp_service.py:102 +msgid "MAC" +msgstr "MAC" + +#: services/auth_service.py:72 +msgid "Ошибка регистрации" +msgstr "Registration error" + +#: services/auth_service.py:80 services/auth_service.py:84 +msgid "Неверный логин или пароль" +msgstr "Invalid username or password" + +#: services/auth_service.py:100 +msgid "Ошибка авторизации" +msgstr "Authentication error" + +#: services/auth_service.py:108 +msgid "Неверный токен" +msgstr "Invalid token" + +#: services/auth_service.py:113 services/auth_service.py:128 +msgid "Пользователь не найден" +msgstr "User not found" + +#: services/auth_service.py:122 +msgid "Сессия недействительна" +msgstr "Session is invalid" + +#: services/auth_service.py:144 +msgid "Успешный выход из системы" +msgstr "Successfully logged out" + +#: services/auth_service.py:148 +msgid "Ошибка при выходе из системы" +msgstr "Logout error" + +#: services/connect_service.py:70 services/connect_service.py:117 services/connect_service.py:154 services/wifi_service.py:335 +msgid "Wi-Fi-интерфейс не доступен" +msgstr "Wi-Fi interface is not available" + +#: services/connect_service.py:74 +#, python-brace-format +msgid "Сеть с SSID {ssid} не найдена в списке доступных сетей" +msgstr "Network with SSID {ssid} not found in the list of available networks" + +#: services/connect_service.py:81 services/connect_service.py:92 +#, python-brace-format +msgid "Ошибка подключения к {ssid}: Неверный пароль" +msgstr "Failed to connect to {ssid}: Invalid password" + +#: services/connect_service.py:83 services/connect_service.py:94 +#, python-brace-format +msgid "Ошибка подключения к {ssid}: Сеть с SSID {ssid} недоступна или неверно указана" +msgstr "Failed to connect to {ssid}: Network with SSID {ssid} is unavailable or incorrect" + +#: services/connect_service.py:85 services/connect_service.py:95 +#, python-brace-format +msgid "Ошибка подключения к {ssid}: {error}" +msgstr "Failed to connect to {ssid}: {error}" + +#: services/connect_service.py:98 +#, python-brace-format +msgid "Ошибка подключения к {ssid}: Неизвестная ошибка - {error}" +msgstr "Failed to connect to {ssid}: Unknown error - {error}" + +#: services/connect_service.py:122 +#, python-brace-format +msgid "Нет активного подключения для SSID {ssid}" +msgstr "No active connection for SSID {ssid}" + +#: services/connect_service.py:133 +#, python-brace-format +msgid "Активное подключение с SSID {ssid} не найдено" +msgstr "Active connection with SSID {ssid} not found" + +#: services/connect_service.py:136 services/connect_service.py:139 +#, python-brace-format +msgid "Ошибка отключения от {ssid}: {error}" +msgstr "Error disconnecting from {ssid}: {error}" + +#: services/connect_service.py:160 +msgid "Не подключено к Wi-Fi" +msgstr "Not connected to Wi-Fi" + +#: services/connect_service.py:163 +#, python-brace-format +msgid "Ошибка проверки статуса: {error}" +msgstr "Error checking status: {error}" + +#: services/ip_service.py:69 +#, python-brace-format +msgid "IP-адрес {ip} уже занят." +msgstr "IP address {ip} is already in use." + +#: services/ip_service.py:73 +msgid "Настройки сетевого профиля доступны для использования." +msgstr "Network profile settings are available for use." + +#: services/ip_service.py:101 +#, python-brace-format +msgid "Подключение {connection_id} не найдено" +msgstr "Connection {connection_id} not found" + +#: services/ip_service.py:129 +#, python-brace-format +msgid "Устройство для интерфейса {interface} не найдено" +msgstr "Device for interface {interface} not found" + +#: services/network_service.py:232 +#, python-brace-format +msgid "Не удалось выполнить команду hostname: {error}" +msgstr "Failed to execute hostname command: {error}" + +#: services/network_service.py:234 +#, python-brace-format +msgid "Ошибка обработки вывода hostname: {error}" +msgstr "Error processing hostname output: {error}" + +#: services/settings_service.py:37 +#, python-brace-format +msgid "Ошибка очистки узлов подсети: {error}" +msgstr "Error clearing subnet nodes: {error}" + +#: services/settings_service.py:58 +#, python-brace-format +msgid "Ошибка очистки точек доступа Wi-Fi: {error}" +msgstr "Error clearing Wi-Fi access points: {error}" + +#: services/settings_service.py:84 +#, python-brace-format +msgid "Ошибка очистки всех сетевых данных: {error}" +msgstr "Error clearing all network data: {error}" + +#: services/subnet_service.py:171 services/wifi_service.py:161 +msgid "Неизвестный" +msgstr "Unknown" + +#: services/subnet_service.py:319 +#, python-brace-format +msgid "Ошибка при сохранении устройств: {error}" +msgstr "Error saving devices: {error}" + +#: services/subnet_service.py:524 services/subnet_service.py:558 services/subnet_service.py:591 +#, python-brace-format +msgid "Устройство с MAC {mac} не найдено" +msgstr "Device with MAC {mac} not found" + +#: services/subnet_service.py:528 +#, python-brace-format +msgid "Заметка для устройства с MAC {mac} уже существует" +msgstr "Note for device with MAC {mac} already exists" + +#: services/subnet_service.py:537 services/subnet_service.py:571 services/subnet_service.py:603 services/wifi_service.py:432 services/wifi_service.py:463 services/wifi_service.py:493 +#, python-brace-format +msgid "Внутренняя ошибка сервера: {error}" +msgstr "Internal server error: {error}" + +#: services/subnet_service.py:562 services/subnet_service.py:595 +#, python-brace-format +msgid "Заметка для устройства с MAC {mac} не существует" +msgstr "Note for device with MAC {mac} does not exist" + +#: services/wifi_service.py:78 +#, python-brace-format +msgid "Ошибка при сохранении заметок: {error}" +msgstr "Error saving notes: {error}" + +#: services/wifi_service.py:112 +msgid "Не найдено сетевых интерфейсов" +msgstr "No network interfaces found" + +#: services/wifi_service.py:137 +msgid "Не найден активный Wi-Fi-интерфейс" +msgstr "No active Wi-Fi interface found" + +#: services/wifi_service.py:176 +msgid "WPA3" +msgstr "WPA3" + +#: services/wifi_service.py:178 +msgid "WPA2" +msgstr "WPA2" + +#: services/wifi_service.py:180 +msgid "WPA" +msgstr "WPA" + +#: services/wifi_service.py:182 +msgid "WEP" +msgstr "WEP" + +#: services/wifi_service.py:183 +msgid "Открытая" +msgstr "Open" + +#: services/wifi_service.py:222 +msgid "2.4 ГГц" +msgstr "2.4 GHz" + +#: services/wifi_service.py:224 +msgid "5 ГГц" +msgstr "5 GHz" + +#: services/wifi_service.py:247 +msgid "Интерфейс не определён" +msgstr "Interface not defined" + +#: services/wifi_service.py:312 +msgid "Таймаут при выполнении iw scan" +msgstr "Timeout during iw scan execution" + +#: services/wifi_service.py:425 +#, python-brace-format +msgid "Заметка для сети с SSID {ssid} уже существует" +msgstr "Note for network with SSID {ssid} already exists" + +#: services/wifi_service.py:453 services/wifi_service.py:483 +#, python-brace-format +msgid "Сеть с SSID {ssid} не найдена" +msgstr "Network with SSID {ssid} not found" + +#: services/wifi_service.py:456 services/wifi_service.py:486 +#, python-brace-format +msgid "Заметка для сети с SSID {ssid} не существует" +msgstr "Note for network with SSID {ssid} does not exist" + + diff --git a/SRV/locales/ru/LC_MESSAGES/services.mo b/SRV/locales/ru/LC_MESSAGES/services.mo new file mode 100644 index 0000000..b38d496 Binary files /dev/null and b/SRV/locales/ru/LC_MESSAGES/services.mo differ diff --git a/SRV/locales/ru/LC_MESSAGES/services.po b/SRV/locales/ru/LC_MESSAGES/services.po new file mode 100644 index 0000000..9db0747 --- /dev/null +++ b/SRV/locales/ru/LC_MESSAGES/services.po @@ -0,0 +1,256 @@ +# Russian translations for PROJECT. +# Copyright (C) 2025 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2025-07-08 15:52+0500\n" +"PO-Revision-Date: 2025-07-08 15:54+0500\n" +"Last-Translator: FULL NAME \n" +"Language: ru\n" +"Language-Team: ru \n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.17.0\n" + +#: services/arp_service.py:101 +msgid "Доступные устройства в сети:" +msgstr "Доступные устройства в сети:" + +#: services/arp_service.py:102 +msgid "IP" +msgstr "IP" + +#: services/arp_service.py:102 +msgid "MAC" +msgstr "MAC" + +#: services/auth_service.py:72 +msgid "Ошибка регистрации" +msgstr "Ошибка регистрации" + +#: services/auth_service.py:80 services/auth_service.py:84 +msgid "Неверный логин или пароль" +msgstr "Неверный логин или пароль" + +#: services/auth_service.py:100 +msgid "Ошибка авторизации" +msgstr "Ошибка авторизации" + +#: services/auth_service.py:108 +msgid "Неверный токен" +msgstr "Неверный токен" + +#: services/auth_service.py:113 services/auth_service.py:128 +msgid "Пользователь не найден" +msgstr "Пользователь не найден" + +#: services/auth_service.py:122 +msgid "Сессия недействительна" +msgstr "Сессия недействительна" + +#: services/auth_service.py:144 +msgid "Успешный выход из системы" +msgstr "Успешный выход из системы" + +#: services/auth_service.py:148 +msgid "Ошибка при выходе из системы" +msgstr "Ошибка при выходе из системы" + +#: services/connect_service.py:70 services/connect_service.py:117 services/connect_service.py:154 services/wifi_service.py:335 +msgid "Wi-Fi-интерфейс не доступен" +msgstr "Wi-Fi-интерфейс не доступен" + +#: services/connect_service.py:74 +#, python-brace-format +msgid "Сеть с SSID {ssid} не найдена в списке доступных сетей" +msgstr "Сеть с SSID {ssid} не найдена в списке доступных сетей" + +#: services/connect_service.py:81 services/connect_service.py:92 +#, python-brace-format +msgid "Ошибка подключения к {ssid}: Неверный пароль" +msgstr "Ошибка подключения к {ssid}: Неверный пароль" + +#: services/connect_service.py:83 services/connect_service.py:94 +#, python-brace-format +msgid "Ошибка подключения к {ssid}: Сеть с SSID {ssid} недоступна или неверно указана" +msgstr "Ошибка подключения к {ssid}: Сеть с SSID {ssid} недоступна или неверно указана" + +#: services/connect_service.py:85 services/connect_service.py:95 +#, python-brace-format +msgid "Ошибка подключения к {ssid}: {error}" +msgstr "Ошибка подключения к {ssid}: {error}" + +#: services/connect_service.py:98 +#, python-brace-format +msgid "Ошибка подключения к {ssid}: Неизвестная ошибка - {error}" +msgstr "Ошибка подключения к {ssid}: Неизвестная ошибка - {error}" + +#: services/connect_service.py:122 +#, python-brace-format +msgid "Нет активного подключения для SSID {ssid}" +msgstr "Нет активного подключения для SSID {ssid}" + +#: services/connect_service.py:133 +#, python-brace-format +msgid "Активное подключение с SSID {ssid} не найдено" +msgstr "Активное подключение с SSID {ssid} не найдено" + +#: services/connect_service.py:136 services/connect_service.py:139 +#, python-brace-format +msgid "Ошибка отключения от {ssid}: {error}" +msgstr "Ошибка отключения от {ssid}: {error}" + +#: services/connect_service.py:160 +msgid "Не подключено к Wi-Fi" +msgstr "Не подключено к Wi-Fi" + +#: services/connect_service.py:163 +#, python-brace-format +msgid "Ошибка проверки статуса: {error}" +msgstr "Ошибка проверки статуса: {error}" + +#: services/ip_service.py:69 +#, python-brace-format +msgid "IP-адрес {ip} уже занят." +msgstr "IP-адрес {ip} уже занят." + +#: services/ip_service.py:73 +msgid "Настройки сетевого профиля доступны для использования." +msgstr "Настройки сетевого профиля доступны для использования." + +#: services/ip_service.py:101 +#, python-brace-format +msgid "Подключение {connection_id} не найдено" +msgstr "Подключение {connection_id} не найдено" + +#: services/ip_service.py:129 +#, python-brace-format +msgid "Устройство для интерфейса {interface} не найдено" +msgstr "Устройство для интерфейса {interface} не найдено" + +#: services/network_service.py:232 +#, python-brace-format +msgid "Не удалось выполнить команду hostname: {error}" +msgstr "Не удалось выполнить команду hostname: {error}" + +#: services/network_service.py:234 +#, python-brace-format +msgid "Ошибка обработки вывода hostname: {error}" +msgstr "Ошибка обработки вывода hostname: {error}" + +#: services/settings_service.py:37 +#, python-brace-format +msgid "Ошибка очистки узлов подсети: {error}" +msgstr "Ошибка очистки узлов подсети: {error}" + +#: services/settings_service.py:58 +#, python-brace-format +msgid "Ошибка очистки точек доступа Wi-Fi: {error}" +msgstr "Ошибка очистки точек доступа Wi-Fi: {error}" + +#: services/settings_service.py:84 +#, python-brace-format +msgid "Ошибка очистки всех сетевых данных: {error}" +msgstr "Ошибка очистки всех сетевых данных: {error}" + +#: services/subnet_service.py:171 services/wifi_service.py:161 +msgid "Неизвестный" +msgstr "Неизвестный" + +#: services/subnet_service.py:319 +#, python-brace-format +msgid "Ошибка при сохранении устройств: {error}" +msgstr "Ошибка при сохранении устройств: {error}" + +#: services/subnet_service.py:524 services/subnet_service.py:558 services/subnet_service.py:591 +#, python-brace-format +msgid "Устройство с MAC {mac} не найдено" +msgstr "Устройство с MAC {mac} не найдено" + +#: services/subnet_service.py:528 +#, python-brace-format +msgid "Заметка для устройства с MAC {mac} уже существует" +msgstr "Заметка для устройства с MAC {mac} уже существует" + +#: services/subnet_service.py:537 services/subnet_service.py:571 services/subnet_service.py:603 services/wifi_service.py:432 services/wifi_service.py:463 services/wifi_service.py:493 +#, python-brace-format +msgid "Внутренняя ошибка сервера: {error}" +msgstr "Внутренняя ошибка сервера: {error}" + +#: services/subnet_service.py:562 services/subnet_service.py:595 +#, python-brace-format +msgid "Заметка для устройства с MAC {mac} не существует" +msgstr "Заметка для устройства с MAC {mac} не существует" + +#: services/wifi_service.py:78 +#, python-brace-format +msgid "Ошибка при сохранении заметок: {error}" +msgstr "Ошибка при сохранении заметок: {error}" + +#: services/wifi_service.py:112 +msgid "Не найдено сетевых интерфейсов" +msgstr "Не найдено сетевых интерфейсов" + +#: services/wifi_service.py:137 +msgid "Не найден активный Wi-Fi-интерфейс" +msgstr "Не найден активный Wi-Fi-интерфейс" + +#: services/wifi_service.py:176 +msgid "WPA3" +msgstr "WPA3" + +#: services/wifi_service.py:178 +msgid "WPA2" +msgstr "WPA2" + +#: services/wifi_service.py:180 +msgid "WPA" +msgstr "WPA" + +#: services/wifi_service.py:182 +msgid "WEP" +msgstr "WEP" + +#: services/wifi_service.py:183 +msgid "Открытая" +msgstr "Открытая" + +#: services/wifi_service.py:222 +msgid "2.4 ГГц" +msgstr "2.4 ГГц" + +#: services/wifi_service.py:224 +msgid "5 ГГц" +msgstr "5 ГГц" + +#: services/wifi_service.py:247 +msgid "Интерфейс не определён" +msgstr "Интерфейс не определён" + +#: services/wifi_service.py:312 +msgid "Таймаут при выполнении iw scan" +msgstr "Таймаут при выполнении iw scan" + +#: services/wifi_service.py:425 +#, python-brace-format +msgid "Заметка для сети с SSID {ssid} уже существует" +msgstr "Заметка для сети с SSID {ssid} уже существует" + +#: services/wifi_service.py:453 services/wifi_service.py:483 +#, python-brace-format +msgid "Сеть с SSID {ssid} не найдена" +msgstr "Сеть с SSID {ssid} не найдена" + +#: services/wifi_service.py:456 services/wifi_service.py:486 +#, python-brace-format +msgid "Заметка для сети с SSID {ssid} не существует" +msgstr "Заметка для сети с SSID {ssid} не существует" + + diff --git a/SRV/locales/services.pot b/SRV/locales/services.pot new file mode 100644 index 0000000..bc0be17 --- /dev/null +++ b/SRV/locales/services.pot @@ -0,0 +1,259 @@ +# Translations template for PROJECT. +# Copyright (C) 2025 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2025. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2025-07-08 15:52+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.17.0\n" + +#: services/arp_service.py:101 +msgid "Доступные устройства в сети:" +msgstr "" + +#: services/arp_service.py:102 +msgid "IP" +msgstr "" + +#: services/arp_service.py:102 +msgid "MAC" +msgstr "" + +#: services/auth_service.py:72 +msgid "Ошибка регистрации" +msgstr "" + +#: services/auth_service.py:80 services/auth_service.py:84 +msgid "Неверный логин или пароль" +msgstr "" + +#: services/auth_service.py:100 +msgid "Ошибка авторизации" +msgstr "" + +#: services/auth_service.py:108 +msgid "Неверный токен" +msgstr "" + +#: services/auth_service.py:113 services/auth_service.py:128 +msgid "Пользователь не найден" +msgstr "" + +#: services/auth_service.py:122 +msgid "Сессия недействительна" +msgstr "" + +#: services/auth_service.py:144 +msgid "Успешный выход из системы" +msgstr "" + +#: services/auth_service.py:148 +msgid "Ошибка при выходе из системы" +msgstr "" + +#: services/connect_service.py:70 services/connect_service.py:117 +#: services/connect_service.py:154 services/wifi_service.py:335 +msgid "Wi-Fi-интерфейс не доступен" +msgstr "" + +#: services/connect_service.py:74 +#, python-brace-format +msgid "Сеть с SSID {ssid} не найдена в списке доступных сетей" +msgstr "" + +#: services/connect_service.py:81 services/connect_service.py:92 +#, python-brace-format +msgid "Ошибка подключения к {ssid}: Неверный пароль" +msgstr "" + +#: services/connect_service.py:83 services/connect_service.py:94 +#, python-brace-format +msgid "" +"Ошибка подключения к {ssid}: Сеть с SSID {ssid} недоступна или неверно " +"указана" +msgstr "" + +#: services/connect_service.py:85 services/connect_service.py:95 +#, python-brace-format +msgid "Ошибка подключения к {ssid}: {error}" +msgstr "" + +#: services/connect_service.py:98 +#, python-brace-format +msgid "Ошибка подключения к {ssid}: Неизвестная ошибка - {error}" +msgstr "" + +#: services/connect_service.py:122 +#, python-brace-format +msgid "Нет активного подключения для SSID {ssid}" +msgstr "" + +#: services/connect_service.py:133 +#, python-brace-format +msgid "Активное подключение с SSID {ssid} не найдено" +msgstr "" + +#: services/connect_service.py:136 services/connect_service.py:139 +#, python-brace-format +msgid "Ошибка отключения от {ssid}: {error}" +msgstr "" + +#: services/connect_service.py:160 +msgid "Не подключено к Wi-Fi" +msgstr "" + +#: services/connect_service.py:163 +#, python-brace-format +msgid "Ошибка проверки статуса: {error}" +msgstr "" + +#: services/ip_service.py:69 +#, python-brace-format +msgid "IP-адрес {ip} уже занят." +msgstr "" + +#: services/ip_service.py:73 +msgid "Настройки сетевого профиля доступны для использования." +msgstr "" + +#: services/ip_service.py:101 +#, python-brace-format +msgid "Подключение {connection_id} не найдено" +msgstr "" + +#: services/ip_service.py:129 +#, python-brace-format +msgid "Устройство для интерфейса {interface} не найдено" +msgstr "" + +#: services/network_service.py:232 +#, python-brace-format +msgid "Не удалось выполнить команду hostname: {error}" +msgstr "" + +#: services/network_service.py:234 +#, python-brace-format +msgid "Ошибка обработки вывода hostname: {error}" +msgstr "" + +#: services/settings_service.py:37 +#, python-brace-format +msgid "Ошибка очистки узлов подсети: {error}" +msgstr "" + +#: services/settings_service.py:58 +#, python-brace-format +msgid "Ошибка очистки точек доступа Wi-Fi: {error}" +msgstr "" + +#: services/settings_service.py:84 +#, python-brace-format +msgid "Ошибка очистки всех сетевых данных: {error}" +msgstr "" + +#: services/subnet_service.py:171 services/wifi_service.py:161 +msgid "Неизвестный" +msgstr "" + +#: services/subnet_service.py:319 +#, python-brace-format +msgid "Ошибка при сохранении устройств: {error}" +msgstr "" + +#: services/subnet_service.py:524 services/subnet_service.py:558 +#: services/subnet_service.py:591 +#, python-brace-format +msgid "Устройство с MAC {mac} не найдено" +msgstr "" + +#: services/subnet_service.py:528 +#, python-brace-format +msgid "Заметка для устройства с MAC {mac} уже существует" +msgstr "" + +#: services/subnet_service.py:537 services/subnet_service.py:571 +#: services/subnet_service.py:603 services/wifi_service.py:432 +#: services/wifi_service.py:463 services/wifi_service.py:493 +#, python-brace-format +msgid "Внутренняя ошибка сервера: {error}" +msgstr "" + +#: services/subnet_service.py:562 services/subnet_service.py:595 +#, python-brace-format +msgid "Заметка для устройства с MAC {mac} не существует" +msgstr "" + +#: services/wifi_service.py:78 +#, python-brace-format +msgid "Ошибка при сохранении заметок: {error}" +msgstr "" + +#: services/wifi_service.py:112 +msgid "Не найдено сетевых интерфейсов" +msgstr "" + +#: services/wifi_service.py:137 +msgid "Не найден активный Wi-Fi-интерфейс" +msgstr "" + +#: services/wifi_service.py:176 +msgid "WPA3" +msgstr "" + +#: services/wifi_service.py:178 +msgid "WPA2" +msgstr "" + +#: services/wifi_service.py:180 +msgid "WPA" +msgstr "" + +#: services/wifi_service.py:182 +msgid "WEP" +msgstr "" + +#: services/wifi_service.py:183 +msgid "Открытая" +msgstr "" + +#: services/wifi_service.py:222 +msgid "2.4 ГГц" +msgstr "" + +#: services/wifi_service.py:224 +msgid "5 ГГц" +msgstr "" + +#: services/wifi_service.py:247 +msgid "Интерфейс не определён" +msgstr "" + +#: services/wifi_service.py:312 +msgid "Таймаут при выполнении iw scan" +msgstr "" + +#: services/wifi_service.py:425 +#, python-brace-format +msgid "Заметка для сети с SSID {ssid} уже существует" +msgstr "" + +#: services/wifi_service.py:453 services/wifi_service.py:483 +#, python-brace-format +msgid "Сеть с SSID {ssid} не найдена" +msgstr "" + +#: services/wifi_service.py:456 services/wifi_service.py:486 +#, python-brace-format +msgid "Заметка для сети с SSID {ssid} не существует" +msgstr "" + diff --git a/SRV/services/arp_service.py b/SRV/services/arp_service.py index d68464d..2aec8be 100644 --- a/SRV/services/arp_service.py +++ b/SRV/services/arp_service.py @@ -2,7 +2,8 @@ from scapy.layers.l2 import ARP, Ether from scapy.sendrecv import srp import netifaces from netaddr import IPNetwork - +from utils.i18n import get_translations, _ +from babel.support import Translations class NetworkScanner: """Инициализация сетевого сканера. @@ -11,12 +12,13 @@ class NetworkScanner: вывода информации о клиентах. """ - def __init__(self, interface=None): + def __init__(self, interface=None, translations: Translations = Depends(get_translations("services"))): """Инициализация параметров сетевого сканера. Args: interface (str, optional): Название сетевого интерфейса. По умолчанию используется интерфейс по умолчанию из netifaces.gateways(). + translations: Объект переводов для текущего языка. Инициализирует интерфейс, информацию об IP-адресах и локальный MAC-адрес. """ @@ -29,6 +31,7 @@ class NetworkScanner: ] self.local_mac = netifaces.ifaddresses( self.interface)[netifaces.AF_LINK][0]["addr"] + self.translations = translations def _create_arp_packet(self, target_ip): """Создаёт ARP-пакет для отправки на указанный IP-адрес. @@ -95,8 +98,8 @@ class NetworkScanner: Выводит IP-адреса и MAC-адреса в отсортированном по IP порядке. """ - print("Доступные устройства в сети:") - print("IP" + " " * 18 + "MAC") + print(self.translations.gettext("Доступные устройства в сети:")) + print(self.translations.gettext("IP") + " " * 18 + self.translations.gettext("MAC")) for client in sorted(clients, key=lambda x: x["ip"]): print(f"{client['ip']:<16} {client['mac']}") diff --git a/SRV/services/auth_service.py b/SRV/services/auth_service.py index 818fba0..c368e83 100644 --- a/SRV/services/auth_service.py +++ b/SRV/services/auth_service.py @@ -9,6 +9,8 @@ from typing import Optional import configparser import os import logging +from utils.i18n import get_translations, _ +from babel.support import Translations logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) @@ -16,7 +18,7 @@ logger = logging.getLogger(__name__) config = configparser.ConfigParser() config_path = "/etc/gonets/config.ini" if not os.path.exists(config_path): - raise RuntimeError(f"Конфигурационный файл {config_path} не найден") + raise RuntimeError(f"Configuration file {config_path} not found") config.read(config_path) SECRET_KEY = config["JWT"]["secret_key"] @@ -25,13 +27,13 @@ ACCESS_TOKEN_EXPIRE_MINUTES = 30 oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login") - class AuthService: """Сервис для регистрации, авторизации и управления сессиями""" - def __init__(self): + def __init__(self, translations: Translations = Depends(get_translations("services"))): self.storage = JsonStorage() self.session_storage = SessionStorage() + self.translations = translations def create_access_token(self, data: dict) -> str: """Создаёт токен""" @@ -60,31 +62,31 @@ class AuthService: return db_user except ValueError as e: logger.error( - f"Ошибка при регистрации пользователя {user.username}: {str(e)}" + f"Error registering user {user.username}: {str(e)}" ) - raise HTTPException(status_code=400, detail=str(e)) + raise HTTPException(status_code=400, detail=self.translations.gettext(str(e))) except Exception as e: logger.error( - f"Ошибка при регистрации пользователя {user.username}: {type(e).__name__} - {str(e)}" + f"Error registering user {user.username}: {type(e).__name__} - {str(e)}" ) - raise HTTPException(status_code=500, detail="Ошибка регистрации") + raise HTTPException(status_code=500, detail=self.translations.gettext("Ошибка регистрации")) def login(self, user: UserLogin, client_id: str) -> dict: """Авторизует пользователя, создаёт сессию и возвращает токен""" try: db_user = self.storage.get_user_by_username(user.username) if not db_user: - logger.error(f"Пользователь {user.username} не найден") - raise HTTPException(status_code=401, detail="Неверный логин или пароль") + logger.error(f"User {user.username} not found") + raise HTTPException(status_code=401, detail=self.translations.gettext("Неверный логин или пароль")) if not self.storage.verify_password(user.password, db_user["password_hash"]): logger.error( - f"Неверный пароль для пользователя {user.username}") - raise HTTPException(status_code=401, detail="Неверный логин или пароль") + f"Invalid password for user {user.username}") + raise HTTPException(status_code=401, detail=self.translations.gettext("Неверный логин или пароль")) access_token = self.create_access_token( data={"sub": user.username}) session_id = self.session_storage.create_session( user.username, access_token, client_id) - logger.info(f"Пользователь {user.username} успешно авторизован") + logger.info(f"User {user.username} successfully logged in") return { "access_token": access_token, "token_type": "bearer", @@ -93,22 +95,22 @@ class AuthService: } except Exception as e: logger.error( - f"Ошибка при авторизации пользователя {user.username}: {type(e).__name__} - {str(e)}" + f"Error logging in user {user.username}: {type(e).__name__} - {str(e)}" ) - raise HTTPException(status_code=500, detail="Ошибка авторизации") + raise HTTPException(status_code=500, detail=self.translations.gettext("Ошибка авторизации")) def get_current_user( self, token: str = Depends(oauth2_scheme)) -> UserResponse: """Получает текущего пользователя по токену""" credentials = self.verify_token(token) if not credentials: - logger.error("Неверный или истёкший токен") - raise HTTPException(status_code=401, detail="Неверный токен") + logger.error("Invalid or expired token") + raise HTTPException(status_code=401, detail=self.translations.gettext("Неверный токен")) username = credentials["username"] db_user = self.storage.get_user_by_username(username) if not db_user: - logger.error(f"Пользователь {username} не найден") - raise HTTPException(status_code=401, detail="Пользователь не найден") + logger.error(f"User {username} not found") + raise HTTPException(status_code=401, detail=self.translations.gettext("Пользователь не найден")) return UserResponse(id=db_user["id"], username=db_user["username"], is_admin=db_user["is_admin"]) def get_user_by_session(self, client_id: str) -> dict: @@ -116,14 +118,14 @@ class AuthService: session = self.session_storage.get_latest_session(client_id) if not session: logger.error( - f"Сессия для client_id {client_id} не найдена или истекла") - raise HTTPException(status_code=401, detail="Сессия недействительна") + f"Session for client_id {client_id} not found or expired") + raise HTTPException(status_code=401, detail=self.translations.gettext("Сессия недействительна")) username = session["username"] token = session["token"] db_user = self.storage.get_user_by_username(username) if not db_user: - logger.error(f"Пользователь {username} не найден") - raise HTTPException(status_code=401, detail="Пользователь не найден") + logger.error(f"User {username} not found") + raise HTTPException(status_code=401, detail=self.translations.gettext("Пользователь не найден")) return { "user": UserResponse(id=db_user["id"], username=db_user["username"], is_admin=db_user["is_admin"]), @@ -137,10 +139,10 @@ class AuthService: if session: self.session_storage.delete_session(session["session_id"]) logger.info( - f"Пользователь успешно вышел из системы для client_id {client_id}" + f"User successfully logged out for client_id {client_id}" ) - return {"message": "Успешный выход из системы"} + return {"message": self.translations.gettext("Успешный выход из системы")} except Exception as e: logger.error( - f"Ошибка при выходе из системы: {type(e).__name__} - {str(e)}") - raise HTTPException(status_code=500, detail="Ошибка при выходе из системы") + f"Error logging out: {type(e).__name__} - {str(e)}") + raise HTTPException(status_code=500, detail=self.translations.gettext("Ошибка при выходе из системы")) \ No newline at end of file diff --git a/SRV/services/connect_service.py b/SRV/services/connect_service.py index 984bfab..90b0621 100644 --- a/SRV/services/connect_service.py +++ b/SRV/services/connect_service.py @@ -1,6 +1,9 @@ import subprocess import logging from typing import Tuple, Optional +from utils.i18n import get_translations, _ +from babel.support import Translations +from fastapi import Depends logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s") logger = logging.getLogger(__name__) @@ -11,12 +14,13 @@ class WifiConnectionService: Предоставляет методы для подключения, отключения и проверки статуса Wi-Fi соединений. """ - def __init__(self): + def __init__(self, translations: Translations = Depends(get_translations("services"))): """Инициализирует сервис Wi-Fi. Автоматически определяет доступный Wi-Fi-интерфейс и сохраняет его имя. """ self.interface = self._get_wifi_interface() + self.translations = translations def _get_wifi_interface(self) -> str: """Автоматически определяет Wi-Fi-интерфейс. @@ -35,14 +39,14 @@ class WifiConnectionService: for line in interfaces.splitlines(): if "wifi" in line.lower() and "connected" in line.lower(): iface = line.split()[0] - logger.info(f"Используется Wi-Fi-интерфейс: {iface}") + logger.info(f"Using Wi-Fi interface: {iface}") return iface - logger.warning("Wi-Fi-интерфейс не найден или не подключён") + logger.warning("Wi-Fi interface not found or not connected") return "wlan0" - logger.error("Wi-Fi радио отключено") + logger.error("Wi-Fi radio is disabled") return "" except Exception as e: - logger.error(f"Ошибка при определении Wi-Fi-интерфейса: {str(e)}") + logger.error(f"Error detecting Wi-Fi interface: {str(e)}") return "" def connect(self, ssid: str, password: str) -> Tuple[bool, Optional[str]]: @@ -63,35 +67,35 @@ class WifiConnectionService: """ try: if not self.interface: - return False, "Wi-Fi-интерфейс не доступен" + return False, self.translations.gettext("Wi-Fi-интерфейс не доступен") result = subprocess.run(["nmcli", "-f", "SSID", "device", "wifi", "list"], capture_output=True, text=True) if ssid not in result.stdout: - return False, f"Сеть с SSID {ssid} не найдена в списке доступных сетей" + return False, self.translations.gettext("Сеть с SSID {ssid} не найдена в списке доступных сетей").format(ssid=ssid) cmd = ["nmcli", "device", "wifi", "connect", ssid, "password", password] process = subprocess.run(cmd, capture_output=True, text=True, check=False) if process.returncode != 0: error_msg = process.stderr.lower() if "secrets were required" in error_msg or "authentication failed" in error_msg or "802-11-wireless-security.psk: недействительное свойство" in process.stderr: - return False, f"Ошибка подключения к {ssid}: Неверный пароль" + return False, self.translations.gettext("Ошибка подключения к {ssid}: Неверный пароль").format(ssid=ssid) elif "no network with ssid" in error_msg: - return False, f"Ошибка подключения к {ssid}: Сеть с SSID {ssid} недоступна или неверно указана" + return False, self.translations.gettext("Ошибка подключения к {ssid}: Сеть с SSID {ssid} недоступна или неверно указана").format(ssid=ssid) else: - return False, f"Ошибка подключения к {ssid}: {process.stderr}" - logger.info(f"Успешное подключение к сети {ssid}") + return False, self.translations.gettext("Ошибка подключения к {ssid}: {error}").format(ssid=ssid, error=process.stderr) + logger.info(f"Successfully connected to network {ssid}") return True, None except subprocess.CalledProcessError as e: - logger.error(f"Ошибка подключения к {ssid}: {e.stderr}") + logger.error(f"Error connecting to {ssid}: {e.stderr}") error_msg = e.stderr.lower() if "secrets were required" in error_msg or "authentication failed" in error_msg or "802-11-wireless-security.psk: недействительное свойство" in e.stderr: - return False, f"Ошибка подключения к {ssid}: Неверный пароль" + return False, self.translations.gettext("Ошибка подключения к {ssid}: Неверный пароль").format(ssid=ssid) elif "no network with ssid" in error_msg: - return False, f"Ошибка подключения к {ssid}: Сеть с SSID {ssid} недоступна или неверно указана" - return False, f"Ошибка подключения к {ssid}: {e.stderr}" + return False, self.translations.gettext("Ошибка подключения к {ssid}: Сеть с SSID {ssid} недоступна или неверно указана").format(ssid=ssid) + return False, self.translations.gettext("Ошибка подключения к {ssid}: {error}").format(ssid=ssid, error=e.stderr) except Exception as e: - logger.error(f"Неизвестная ошибка при подключении к {ssid}: {str(e)}") - return False, f"Ошибка подключения к {ssid}: Неизвестная ошибка - {str(e)}" + logger.error(f"Unknown error connecting to {ssid}: {str(e)}") + return False, self.translations.gettext("Ошибка подключения к {ssid}: Неизвестная ошибка - {error}").format(ssid=ssid, error=str(e)) def disconnect(self, ssid: str) -> Tuple[bool, Optional[str]]: """Отключается от Wi-Fi сети по указанному SSID. @@ -110,12 +114,12 @@ class WifiConnectionService: """ try: if not self.interface: - return False, "Wi-Fi-интерфейс не доступен" + return False, self.translations.gettext("Wi-Fi-интерфейс не доступен") result = subprocess.run(["nmcli", "connection", "show", "--active"], capture_output=True, text=True) active_connections = result.stdout.strip().splitlines() if not active_connections: - logger.info(f"Нет активных подключений для SSID {ssid}") - return True, f"Нет активного подключения для SSID {ssid}" + logger.info(f"No active connections for SSID {ssid}") + return True, self.translations.gettext("Нет активного подключения для SSID {ssid}").format(ssid=ssid) for conn in active_connections: conn_details = conn.split() if len(conn_details) > 1: @@ -123,16 +127,16 @@ class WifiConnectionService: conn_info = subprocess.run(["nmcli", "connection", "show", conn_name], capture_output=True, text=True).stdout if "802-11-wireless.ssid:" in conn_info and ssid in conn_info: subprocess.run(["nmcli", "connection", "down", conn_name], capture_output=True, text=True, check=True) - logger.info(f"Отключено соединение с SSID {ssid}") + logger.info(f"Disconnected from SSID {ssid}") return True, None - logger.warning(f"Активное подключение с SSID {ssid} не найдено") - return True, f"Активное подключение с SSID {ssid} не найдено" + logger.warning(f"Active connection with SSID {ssid} not found") + return True, self.translations.gettext("Активное подключение с SSID {ssid} не найдено").format(ssid=ssid) except subprocess.CalledProcessError as e: - logger.error(f"Ошибка при отключении от {ssid}: {e.stderr}") - return False, f"Ошибка отключения от {ssid}: {e.stderr}" + logger.error(f"Error disconnecting from {ssid}: {e.stderr}") + return False, self.translations.gettext("Ошибка отключения от {ssid}: {error}").format(ssid=ssid, error=e.stderr) except Exception as e: - logger.error(f"Неизвестная ошибка при отключении от {ssid}: {str(e)}") - return False, f"Ошибка отключения от {ssid}: {str(e)}" + logger.error(f"Unknown error disconnecting from {ssid}: {str(e)}") + return False, self.translations.gettext("Ошибка отключения от {ssid}: {error}").format(ssid=ssid, error=str(e)) def get_status(self) -> Tuple[bool, Optional[str]]: """Проверяет статус текущего подключения к Wi-Fi. @@ -147,13 +151,13 @@ class WifiConnectionService: """ try: if not self.interface: - return False, "Wi-Fi-интерфейс не доступен" + return False, self.translations.gettext("Wi-Fi-интерфейс не доступен") result = subprocess.run(["nmcli", "connection", "show", "--active"], capture_output=True, text=True) if result.stdout.strip(): ssid = result.stdout.splitlines()[1].split()[0] - logger.info(f"Текущая сеть: {ssid}") + logger.info(f"Current network: {ssid}") return True, ssid - return False, "Не подключено к Wi-Fi" + return False, self.translations.gettext("Не подключено к Wi-Fi") except Exception as e: - logger.error(f"Ошибка при проверке статуса: {str(e)}") - return False, f"Ошибка проверки статуса: {str(e)}" \ No newline at end of file + logger.error(f"Error checking status: {str(e)}") + return False, self.translations.gettext("Ошибка проверки статуса: {error}").format(error=str(e)) \ No newline at end of file diff --git a/SRV/services/ip_service.py b/SRV/services/ip_service.py index 5115343..bff8c4f 100644 --- a/SRV/services/ip_service.py +++ b/SRV/services/ip_service.py @@ -8,7 +8,9 @@ from sdbus_async.networkmanager import ( import sdbus from sdbus_async.networkmanager.settings import ConnectionProfile from services.arp_service import NetworkScanner - +from utils.i18n import get_translations, _ +from babel.support import Translations +from fastapi import Depends class IPService: """Сервис проверки доступности IP-адреса и применения настроек сети. @@ -17,7 +19,7 @@ class IPService: ARP-сканирования и применения настроек через NetworkManager. """ - def __init__(self): + def __init__(self, translations: Translations = Depends(get_translations("services"))): """Инициализирует сервис IP. Создаёт объект ARP-сканера и устанавливает системную шину D-Bus как @@ -26,6 +28,7 @@ class IPService: self.arp_scanner = NetworkScanner() self.bus = sdbus.sd_bus_open_system() sdbus.set_default_bus(self.bus) + self.translations = translations def _reset_bus(self): """Перезапускает соединение с системной шиной D-Bus. @@ -63,11 +66,11 @@ class IPService: if any(client["ip"] == new_ip for client in clients): return { "available": False, - "message": f"IP address {new_ip} уже занят." + "message": self.translations.gettext("IP-адрес {ip} уже занят.").format(ip=new_ip) } return { "available": True, - "message": "Network profile settings are available for use.", + "message": self.translations.gettext("Настройки сетевого профиля доступны для использования.") } async def apply_ip_config(self, args: Dict[str, Any]) -> None: @@ -95,7 +98,7 @@ class IPService: args["connection_id"]) if not connection_paths: - raise ValueError(f"Подключение {args['connection_id']} не найдено") + raise ValueError(self.translations.gettext("Подключение {connection_id} не найдено").format(connection_id=args["connection_id"])) connection = NetworkConnectionSettings(connection_paths[0]) profile = await connection.get_profile() @@ -110,7 +113,7 @@ class IPService: new_profile = ConnectionProfile.from_settings_dict(settings_dict) await connection.update(new_profile.to_dbus()) - print(f"Обновлены настройки для {args['connection_id']}:") + print(f"Updated settings for {args['connection_id']}") interface_name = settings_dict["connection"]["interface-name"] devices = await nm.get_devices() @@ -118,9 +121,9 @@ class IPService: device = NetworkDeviceGeneric(device_path) if await device.interface == interface_name: await device.disconnect() - print(f"Отключён от {interface_name}") - await nm.activate_connection(connection=connection_paths[0],device=device_path) - print(f"Переподключён к {args['connection_id']}") + print(f"Disconnected from {interface_name}") + await nm.activate_connection(connection=connection_paths[0], device=device_path) + print(f"Reconnected to {args['connection_id']}") return - raise RuntimeError(f"Устройство для интерфейса {interface_name} не найдено") \ No newline at end of file + raise RuntimeError(self.translations.gettext("Устройство для интерфейса {interface} не найдено").format(interface=interface_name)) \ No newline at end of file diff --git a/SRV/services/network_service.py b/SRV/services/network_service.py index b047808..b9424ae 100644 --- a/SRV/services/network_service.py +++ b/SRV/services/network_service.py @@ -20,7 +20,9 @@ from models.network import ( WiFiDevice, ) import subprocess - +from utils.i18n import get_translations, _ +from babel.support import Translations +from fastapi import Depends class NetworkService: """Сервис для взаимодействия с NetworkManager через D-Bus. @@ -29,7 +31,7 @@ class NetworkService: их конфигурациях IP, Wi-Fi и состояниях. """ - def __init__(self): + def __init__(self, translations: Translations = Depends(get_translations("services"))): """Инициализирует сервис NetworkManager. Устанавливает системный D-Bus и создаёт объекты для взаимодействия с @@ -38,6 +40,7 @@ class NetworkService: self.system_bus = sd_bus_open_system() self.nm = NetworkManager(self.system_bus) self.nm_settings = NetworkManagerSettings(self.system_bus) + self.translations = translations async def get_ip_method(self, device: NetworkDeviceGeneric, ip_type: str) -> str: """Получает метод IP (например, "auto", "manual") для указанного устройства. @@ -226,9 +229,9 @@ class NetworkService: hostname = result.stdout.strip() return {"hostname": hostname} except subprocess.CalledProcessError as e: - raise RuntimeError(f"Failed to execute hostname: {e}") + raise RuntimeError(self.translations.gettext("Не удалось выполнить команду hostname: {error}").format(error=str(e))) except Exception as e: - raise RuntimeError(f"Error processing hostname output: {e}") + raise RuntimeError(self.translations.gettext("Ошибка обработки вывода hostname: {error}").format(error=str(e))) async def get_interfaces_by_state( self, diff --git a/SRV/services/settings_service.py b/SRV/services/settings_service.py index 5399b96..4fb7a09 100644 --- a/SRV/services/settings_service.py +++ b/SRV/services/settings_service.py @@ -1,5 +1,8 @@ import json import logging +from utils.i18n import get_translations, _ +from babel.support import Translations +from fastapi import Depends logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) @@ -7,9 +10,10 @@ logger = logging.getLogger(__name__) class SettingsService: """Сервис для управления настройками и очистки данных сети.""" - def __init__(self): + def __init__(self, translations: Translations = Depends(get_translations("services"))): self.subnet_file = "storage/devices/devices.json" self.wifi_file = "storage/wifi/wifi.json" + self.translations = translations def clear_subnet(self) -> bool: """Очищает данные узлов подсети в файле devices.json. @@ -23,14 +27,14 @@ class SettingsService: try: with open(self.subnet_file, "w") as f: json.dump([], f) - logger.info("Данные узлов подсети успешно очищены") + logger.info("Subnet nodes data successfully cleared") return True except FileNotFoundError: - logger.info("Файл устройств не найден, очистка считается успешной") + logger.info("Devices file not found, clearing considered successful") return True except Exception as e: - logger.error(f"Ошибка очистки узлов подсети: {str(e)}") - raise + logger.error(f"Error clearing subnet nodes: {str(e)}") + raise Exception(self.translations.gettext("Ошибка очистки узлов подсети: {error}").format(error=str(e))) def clear_wifi(self) -> bool: """Очищает данные точек доступа Wi-Fi в файле wifi.json. @@ -44,14 +48,14 @@ class SettingsService: try: with open(self.wifi_file, "w") as f: json.dump([], f) - logger.info("Данные точек доступа Wi-Fi успешно очищены") + logger.info("Wi-Fi access points data successfully cleared") return True except FileNotFoundError: - logger.info("Файл Wi-Fi не найден, очистка считается успешной") + logger.info("Wi-Fi file not found, clearing considered successful") return True except Exception as e: - logger.error(f"Ошибка очистки точек доступа Wi-Fi: {str(e)}") - raise + logger.error(f"Error clearing Wi-Fi access points: {str(e)}") + raise Exception(self.translations.gettext("Ошибка очистки точек доступа Wi-Fi: {error}").format(error=str(e))) def clear_all_data(self) -> bool: """Очищает данные узлов подсети и точек доступа Wi-Fi в обоих файлах. @@ -67,14 +71,14 @@ class SettingsService: with open(self.subnet_file, "w") as f: json.dump([], f) except FileNotFoundError: - logger.info("Файл устройств не найден, очистка считается успешной") + logger.info("Devices file not found, clearing considered successful") try: with open(self.wifi_file, "w") as f: json.dump([], f) except FileNotFoundError: - logger.info("Файл Wi-Fi не найден, очистка считается успешной") - logger.info("Все сетевые данные успешно очищены") + logger.info("Wi-Fi file not found, clearing considered successful") + logger.info("All network data successfully cleared") return True except Exception as e: - logger.error(f"Ошибка очистки всех сетевых данных: {str(e)}") - raise \ No newline at end of file + logger.error(f"Error clearing all network data: {str(e)}") + raise Exception(self.translations.gettext("Ошибка очистки всех сетевых данных: {error}").format(error=str(e))) \ No newline at end of file diff --git a/SRV/services/subnet_service.py b/SRV/services/subnet_service.py index 5384343..46ce179 100644 --- a/SRV/services/subnet_service.py +++ b/SRV/services/subnet_service.py @@ -12,6 +12,9 @@ import json from pathlib import Path from datetime import datetime, timedelta import subprocess +from utils.i18n import get_translations, _ +from babel.support import Translations +from fastapi import Depends from models.subnet import SubnetScanResult, Device from config.ports import port_config @@ -30,7 +33,7 @@ class NetworkScanner: Выполняет обнаружение устройств в указанной подсети через ARP-пакеты. """ - def __init__(self, interface: str): + def __init__(self, interface: str, translations: Translations = Depends(get_translations("services"))): """Инициализирует сканер сети с указанным сетевым интерфейсом. Args: @@ -38,6 +41,7 @@ class NetworkScanner: """ self.interface = interface conf.iface = interface + self.translations = translations def scan(self, subnet: str) -> List[Tuple[str, str]]: """Сканирует подсеть с использованием ARP-запросов. @@ -63,7 +67,7 @@ class NetworkScanner: return [(received.psrc, received.hwsrc) for sent, received in result] except Exception as e: - logger.error(f"Ошибка ARP-сканирования подсети {subnet}: {str(e)}") + logger.error(f"Error scanning subnet {subnet}: {str(e)}") return [] class PortScanner: @@ -72,13 +76,14 @@ class PortScanner: Выполняет сканирование портов с использованием TCP SYN-запросов. """ - def __init__(self, interface: str): + def __init__(self, interface: str, translations: Translations = Depends(get_translations("services"))): """Инициализирует сканер портов с указанным сетевым интерфейсом. Args: interface (str): Название сетевого интерфейса (например, "eth0"). """ self.interface = interface + self.translations = translations def scan(self, ip: str) -> List[str]: """Сканирует открытые порты на указанном IP-адресе. @@ -114,7 +119,7 @@ class PortScanner: return None except Exception as e: logger.debug( - f"Ошибка проверки порта {port} для IP {ip}: {str(e)}") + f"Error checking port {port} for IP {ip}: {str(e)}") return None try: @@ -122,11 +127,11 @@ class PortScanner: with ThreadPoolExecutor(max_workers=max_workers) as executor: results = executor.map(check_port, port_config.get_ports()) open_ports = [port for port in results if port is not None] - logger.debug(f"Открытые порты для IP {ip}: {open_ports}") + logger.debug(f"Open ports for IP {ip}: {open_ports}") return open_ports except Exception as e: logger.warning( - f"Ошибка при сканировании портов для IP {ip}: {str(e)}") + f"Error scanning ports for IP {ip}: {str(e)}") return [] class DeviceInfoCollector: @@ -135,7 +140,7 @@ class DeviceInfoCollector: Управляет кэшированием данных NetBIOS и DNS. """ - def __init__(self): + def __init__(self, translations: Translations = Depends(get_translations("services"))): """Инициализирует коллектор информации об устройствах. Создаёт объект MacLookup для определения вендоров и инициализирует кэши. @@ -143,6 +148,7 @@ class DeviceInfoCollector: self.mac_lookup = MacLookup() self.nbtscan_cache = {} self.nbtscan_results = {} + self.translations = translations @lru_cache(maxsize=1000) def get_vendor(self, mac: str) -> str: @@ -161,8 +167,8 @@ class DeviceInfoCollector: return self.mac_lookup.lookup(mac) except Exception as e: logger.warning( - f"Не удалось определить производителя для MAC {mac}: {str(e)}") - return "Unknown" + f"Failed to determine vendor for MAC {mac}: {str(e)}") + return self.translations.gettext("Неизвестный") def scan_nbtscan(self, subnet: str) -> None: """Выполняет сканирование NetBIOS для указанной подсети. @@ -174,28 +180,28 @@ class DeviceInfoCollector: """ if subnet not in self.nbtscan_results: try: - logger.debug(f"Запуск nbtscan для подсети {subnet}") + logger.debug(f"Starting nbtscan for subnet {subnet}") result = subprocess.run(["sudo", "nbtscan", "-r", str(subnet)], capture_output=True, text=True, check=False, timeout=10) - logger.debug(f"Полный вывод nbtscan: {result.stdout}") + logger.debug(f"Full nbtscan output: {result.stdout}") if result.returncode == 0: for line in result.stdout.splitlines(): - logger.debug(f"Обработка строки: {line}") + logger.debug(f"Processing line: {line}") if not line.startswith(("IP address", "-", "Doing NBT")): parts = [p for p in line.split() if p] if len(parts) >= 2: ip_addr, hostname = parts[0], parts[1] if hostname != "": self.nbtscan_cache[ip_addr] = hostname - logger.info(f"NetBIOS: Найден хостнейм {hostname} для IP {ip_addr}") + logger.info(f"NetBIOS: Found hostname {hostname} for IP {ip_addr}") self.nbtscan_results[subnet] = True except subprocess.TimeoutExpired: - logger.error(f"NetBIOS: Таймаут для подсети {subnet}") + logger.error(f"NetBIOS: Timeout for subnet {subnet}") except Exception as e: - logger.error(f"NetBIOS: Ошибка для подсети {subnet}: {str(e)}") + logger.error(f"NetBIOS: Error for subnet {subnet}: {str(e)}") def get_hostname(self, ip: str) -> Optional[str]: """Определяет хостнейм для указанного IP-адреса. @@ -212,7 +218,7 @@ class DeviceInfoCollector: socket.setdefaulttimeout(2) return socket.gethostbyaddr(ip)[0] except (socket.herror, socket.gaierror, socket.timeout): - logger.debug(f"DNS: Не удалось разрешить имя для IP {ip}") + logger.debug(f"DNS: Failed to resolve name for IP {ip}") subnet = ipaddress.ip_network(f"{ip}/24", strict=False) if subnet not in self.nbtscan_results: @@ -221,7 +227,7 @@ class DeviceInfoCollector: if ip in self.nbtscan_cache: return self.nbtscan_cache[ip] - logger.debug(f"Не удалось определить хостнейм для IP {ip} через DNS или NetBIOS") + logger.debug(f"Failed to determine hostname for IP {ip} via DNS or NetBIOS") return None class DeviceStorage: @@ -230,7 +236,7 @@ class DeviceStorage: Хранит устройства в JSON-файле и удаляет устаревшие записи. """ - def __init__(self, storage_path: str = "storage/devices/devices.json"): + def __init__(self, storage_path: str = "storage/devices/devices.json", translations: Translations = Depends(get_translations("services"))): """Инициализирует хранилище устройств с указанным путём. Args: @@ -242,6 +248,7 @@ class DeviceStorage: self.storage_file = Path(storage_path) self.storage_file.parent.mkdir(parents=True, exist_ok=True) self.offline_timeout = timedelta(days=7) + self.translations = translations def load_devices(self) -> Dict[str, Device]: """Загружает устройства из файла хранения. @@ -264,7 +271,7 @@ class DeviceStorage: return self._clean_old_devices(devices) return {} except Exception as e: - logger.error(f"Ошибка при загрузке устройств: {str(e)}") + logger.error(f"Error loading devices: {str(e)}") return {} def _clean_old_devices(self, devices: Dict[str, Device]) -> Dict[str, Device]: @@ -286,9 +293,9 @@ class DeviceStorage: if now - last_seen <= self.offline_timeout: filtered[mac] = device else: - logger.info(f"Удалено устройство {mac} (offline > 7 дней)") + logger.info(f"Removed device {mac} (offline > 7 days)") except ValueError: - logger.warning(f"Неверный формат last_seen для устройства {mac}") + logger.warning(f"Invalid last_seen format for device {mac}") else: filtered[mac] = device return filtered @@ -306,9 +313,10 @@ class DeviceStorage: data = SubnetScanResult(devices=devices).model_dump() with open(self.storage_file, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) - logger.info(f"Сохранено {len(devices)} устройств в {self.storage_file}") + logger.info(f"Saved {len(devices)} devices to {self.storage_file}") except Exception as e: - logger.error(f"Ошибка при сохранении устройств: {str(e)}") + logger.error(f"Error saving devices: {str(e)}") + raise Exception(self.translations.gettext("Ошибка при сохранении устройств: {error}").format(error=str(e))) class SubnetService: """Сервис для сканирования подсетей и управления устройствами. @@ -316,7 +324,7 @@ class SubnetService: Объединяет функционал сканирования сети, портов и хранения данных об устройствах. """ - def __init__(self): + def __init__(self, translations: Translations = Depends(get_translations("services"))): """Инициализирует сервис подсети с настройкой всех компонентов. Автоматически определяет интерфейс и инициализирует сканеры и хранилище. @@ -326,6 +334,7 @@ class SubnetService: self.port_scanner = PortScanner(self.interface) self.device_info = DeviceInfoCollector() self.storage = DeviceStorage() + self.translations = translations def _get_default_interface(self) -> str: """Определяет имя сетевого интерфейса по умолчанию. @@ -346,7 +355,7 @@ class SubnetService: return iface return "eth0" except Exception as e: - logger.warning(f"Не удалось определить интерфейс: {str(e)}") + logger.warning(f"Failed to determine interface: {str(e)}") return "eth0" def scan_subnet(self, subnet: str, ports: List[int] = None) -> SubnetScanResult: @@ -438,13 +447,13 @@ class SubnetService: self.storage.save_devices(list(saved_devices.values())) logger.info( - f"Сканирование подсети {subnet} завершено за {time.time() - start_time:.2f} секунд, " - f"найдено {len(devices)} устройств (активных: {len(active_macs)})" + f"Subnet scan {subnet} completed in {time.time() - start_time:.2f} seconds, " + f"found {len(devices)} devices (active: {len(active_macs)})" ) return SubnetScanResult(devices=devices) except Exception as e: - logger.error(f"Ошибка при сканировании подсети {subnet}: {str(e)}") + logger.error(f"Error scanning subnet {subnet}: {str(e)}") return SubnetScanResult(devices=devices) def _get_local_device(self, subnet: str) -> Optional[Device]: @@ -473,7 +482,7 @@ class SubnetService: hostname = self.device_info.get_hostname(ip) open_ports = self.port_scanner.scan(ip) logger.debug( - f"Локальное устройство: IP={ip}, MAC={mac}, Ports={open_ports}, Hostname={hostname}" + f"Local device: IP={ip}, MAC={mac}, Ports={open_ports}, Hostname={hostname}" ) return Device( ip=ip, @@ -486,11 +495,11 @@ class SubnetService: note=None, ) logger.warning( - f"Локальное устройство не найдено в подсети {subnet}") + f"Local device not found in subnet {subnet}") return None except Exception as e: logger.warning( - f"Не удалось получить локальное устройство: {str(e)}") + f"Failed to get local device: {str(e)}") return None def add_note(self, mac: str, note: str) -> Tuple[bool, Optional[str]]: @@ -511,21 +520,21 @@ class SubnetService: try: saved_devices = self.storage.load_devices() if mac not in saved_devices: - logger.warning(f"Устройство с MAC {mac} не найдено") - return False, f"Устройство с MAC {mac} не найдено" + logger.warning(f"Device with MAC {mac} not found") + return False, self.translations.gettext("Устройство с MAC {mac} не найдено").format(mac=mac) if saved_devices[mac].note is not None: logger.error( - f"Заметка для устройства с MAC {mac} уже существует") - return False, f"Заметка для устройства с MAC {mac} уже существует" + f"Note for device with MAC {mac} already exists") + return False, self.translations.gettext("Заметка для устройства с MAC {mac} уже существует").format(mac=mac) saved_devices[mac].note = note self.storage.save_devices(list(saved_devices.values())) logger.info( - f"Добавлена заметка '{note}' для устройства с MAC {mac}") + f"Added note '{note}' for device with MAC {mac}") return True, None except Exception as e: logger.error( - f"Ошибка при добавлении заметки для MAC {mac}: {str(e)}") - return False, f"Внутренняя ошибка сервера: {str(e)}" + f"Error adding note for MAC {mac}: {str(e)}") + return False, self.translations.gettext("Внутренняя ошибка сервера: {error}").format(error=str(e)) def update_note(self, mac: str, note: str) -> Tuple[bool, Optional[str]]: """Обновляет заметку устройства по MAC-адресу. @@ -545,21 +554,21 @@ class SubnetService: try: saved_devices = self.storage.load_devices() if mac not in saved_devices: - logger.warning(f"Устройство с MAC {mac} не найдено") - return False, f"Устройство с MAC {mac} не найдено" + logger.warning(f"Device with MAC {mac} not found") + return False, self.translations.gettext("Устройство с MAC {mac} не найдено").format(mac=mac) if saved_devices[mac].note is None: logger.error( - f"Заметка для устройства с MAC {mac} не существует") - return False, f"Заметка для устройства с MAC {mac} не существует" + f"Note for device with MAC {mac} does not exist") + return False, self.translations.gettext("Заметка для устройства с MAC {mac} не существует").format(mac=mac) saved_devices[mac].note = note self.storage.save_devices(list(saved_devices.values())) logger.info( - f"Обновлена заметка '{note}' для устройства с MAC {mac}") + f"Updated note '{note}' for device with MAC {mac}") return True, None except Exception as e: logger.error( - f"Ошибка при обновлении заметки для MAC {mac}: {str(e)}") - return False, f"Внутренняя ошибка сервера: {str(e)}" + f"Error updating note for MAC {mac}: {str(e)}") + return False, self.translations.gettext("Внутренняя ошибка сервера: {error}").format(error=str(e)) def delete_note(self, mac: str) -> Tuple[bool, Optional[str]]: """Удаляет заметку устройства по MAC-адресу. @@ -578,17 +587,17 @@ class SubnetService: try: saved_devices = self.storage.load_devices() if mac not in saved_devices: - logger.warning(f"Устройство с MAC {mac} не найдено") - return False, f"Устройство с MAC {mac} не найдено" + logger.warning(f"Device with MAC {mac} not found") + return False, self.translations.gettext("Устройство с MAC {mac} не найдено").format(mac=mac) if saved_devices[mac].note is None: logger.error( - f"Заметка для устройства с MAC {mac} не существует") - return False, f"Заметка для устройства с MAC {mac} не существует" + f"Note for device with MAC {mac} does not exist") + return False, self.translations.gettext("Заметка для устройства с MAC {mac} не существует").format(mac=mac) saved_devices[mac].note = None self.storage.save_devices(list(saved_devices.values())) - logger.info(f"Удалена заметка для устройства с MAC {mac}") + logger.info(f"Deleted note for device with MAC {mac}") return True, None except Exception as e: logger.error( - f"Ошибка при удалении заметки для MAC {mac}: {str(e)}") - return False, f"Внутренняя ошибка сервера: {str(e)}" \ No newline at end of file + f"Error deleting note for MAC {mac}: {str(e)}") + return False, self.translations.gettext("Внутренняя ошибка сервера: {error}").format(error=str(e)) \ No newline at end of file diff --git a/SRV/services/wifi_service.py b/SRV/services/wifi_service.py index d82dccb..7420cc1 100644 --- a/SRV/services/wifi_service.py +++ b/SRV/services/wifi_service.py @@ -9,6 +9,9 @@ import pywifi from models.wifi import WifiAccessPoint, WifiScanResult from pathlib import Path import json +from utils.i18n import get_translations, _ +from babel.support import Translations +from fastapi import Depends logging.basicConfig( level=logging.DEBUG, @@ -22,7 +25,7 @@ class WifiStorage: в JSON-файле на диске. """ - def __init__(self, storage_path: str = "storage/wifi/wifi.json"): + def __init__(self, storage_path: str = "storage/wifi/wifi.json", translations: Translations = Depends(get_translations("services"))): """Инициализирует объект хранилища Wi-Fi с указанным путём к файлу. Args: @@ -33,6 +36,7 @@ class WifiStorage: """ self.storage_file = Path(storage_path) self.storage_file.parent.mkdir(parents=True, exist_ok=True) + self.translations = translations def load_notes(self) -> Dict[str, Optional[str]]: """Загружает заметки по SSID из файла хранения. @@ -51,7 +55,7 @@ class WifiStorage: return {item["ssid"]: item.get("note") for item in data.get("networks", [])} return {} except Exception as e: - logger.error(f"Ошибка при загрузке заметок: {str(e)}") + logger.error(f"Error loading notes: {str(e)}") return {} def save_notes(self, notes: Dict[str, Optional[str]]) -> None: @@ -68,9 +72,10 @@ class WifiStorage: data = {"networks": [{"ssid": ssid, "note": note} for ssid, note in notes.items()]} with open(self.storage_file, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) - logger.info(f"Сохранено {len(notes)} заметок в {self.storage_file}") + logger.info(f"Saved {len(notes)} notes to {self.storage_file}") except Exception as e: - logger.error(f"Ошибка при сохранении заметок: {str(e)}") + logger.error(f"Error saving notes: {str(e)}") + raise Exception(self.translations.gettext("Ошибка при сохранении заметок: {error}").format(error=str(e))) class WifiService: """Сервис для сканирования текущих Wi-Fi точек доступа. @@ -80,7 +85,7 @@ class WifiService: а также управления заметками. """ - def __init__(self): + def __init__(self, translations: Translations = Depends(get_translations("services"))): """Инициализирует сервис Wi-Fi с настройкой интерфейса и хранилища. Инициализирует объект MacLookup для определения вендоров по MAC-адресам, @@ -90,6 +95,7 @@ class WifiService: self.wifi = pywifi.PyWiFi() self.interface = self._get_wifi_interface() self.storage = WifiStorage() + self.translations = translations def _get_wifi_interface(self) -> Optional[object]: """Автоматически определяет активный Wi-Fi-интерфейс. @@ -103,35 +109,35 @@ class WifiService: try: interfaces = self.wifi.interfaces() if not interfaces: - logger.error("Не найдено сетевых интерфейсов") + logger.error(self.translations.gettext("Не найдено сетевых интерфейсов")) return None logger.debug( - f"Доступные интерфейсы: {[iface.name() for iface in interfaces]}" + f"Available interfaces: {[iface.name() for iface in interfaces]}" ) for iface in interfaces: iface_name = iface.name() if "p2p" in iface_name.lower(): - logger.debug(f"Пропущен интерфейс {iface_name} (P2P)") + logger.debug(f"Skipped interface {iface_name} (P2P)") continue try: iface.scan() time.sleep(1) results = iface.scan_results() if results: - logger.info(f"Выбран Wi-Fi-интерфейс: {iface_name}") + logger.info(f"Selected Wi-Fi interface: {iface_name}") return iface logger.debug( - f"Интерфейс {iface_name} не вернул результатов сканирования" + f"Interface {iface_name} returned no scan results" ) except Exception as e: - logger.debug(f"Интерфейс {iface_name} неактивен: {str(e)}") + logger.debug(f"Interface {iface_name} inactive: {str(e)}") - logger.error("Не найден активный Wi-Fi-интерфейс") + logger.error(self.translations.gettext("Не найден активный Wi-Fi-интерфейс")) return None except Exception as e: - logger.error(f"Ошибка при определении Wi-Fi-интерфейса: {str(e)}") + logger.error(f"Error determining Wi-Fi interface: {str(e)}") return None @lru_cache(maxsize=1000) @@ -151,8 +157,8 @@ class WifiService: return self.mac_lookup.lookup(mac) except Exception as e: logger.warning( - f"Не удалось определить производителя для MAC {mac}: {str(e)}") - return "Unknown" + f"Failed to determine vendor for MAC {mac}: {str(e)}") + return self.translations.gettext("Неизвестный") def _get_encryption_from_iw(self, ap_info: Dict) -> str: """Определяет тип шифрования из данных, полученных через iw. @@ -165,16 +171,16 @@ class WifiService: """ security = ap_info.get("security", "") logger.debug( - f"Шифрование для BSSID {ap_info.get('bssid')}: {security}") + f"Encryption for BSSID {ap_info.get('bssid')}: {security}") if "WPA3" in security: - return "WPA3" + return self.translations.gettext("WPA3") elif "WPA2" in security or "RSN" in security: - return "WPA2" + return self.translations.gettext("WPA2") elif "WPA" in security: - return "WPA" + return self.translations.gettext("WPA") elif "WEP" in security: - return "WEP" - return "Open" + return self.translations.gettext("WEP") + return self.translations.gettext("Открытая") def _get_channel(self, frequency: Optional[int]) -> Optional[int]: """Преобразует частоту в номер канала. @@ -192,11 +198,11 @@ class WifiService: return (frequency - 2412) // 5 + 1 elif 5180 <= frequency <= 5825: return (frequency - 5180) // 5 + 36 - logger.debug(f"Частота {frequency} вне диапазона 2.4/5 GHz") + logger.debug(f"Frequency {frequency} outside 2.4/5 GHz range") return None except Exception as e: logger.debug( - f"Ошибка при определении канала для частоты {frequency}: {str(e)}" + f"Error determining channel for frequency {frequency}: {str(e)}" ) return None @@ -213,14 +219,14 @@ class WifiService: return None try: if 2412 <= frequency <= 2472: - return "2.4 GHz" + return self.translations.gettext("2.4 ГГц") elif 5180 <= frequency <= 5825: - return "5 GHz" - logger.debug(f"Частота {frequency} вне диапазона 2.4/5 GHz") + return self.translations.gettext("5 ГГц") + logger.debug(f"Frequency {frequency} outside 2.4/5 GHz range") return None except Exception as e: logger.debug( - f"Ошибка при определении диапазона для частоты {frequency}: {str(e)}" + f"Error determining band for frequency {frequency}: {str(e)}" ) return None @@ -238,20 +244,20 @@ class WifiService: """ try: if not self.interface: - logger.error("Интерфейс не определён") + logger.error(self.translations.gettext("Интерфейс не определён")) return [] cmd = ["sudo", "iw", "dev", self.interface.name(), "scan"] - logger.debug(f"Выполняем команду: {' '.join(cmd)}") + logger.debug(f"Executing command: {' '.join(cmd)}") result = subprocess.run(cmd, capture_output=True, text=True, timeout=10) if result.returncode != 0: - logger.error(f"Ошибка iw scan: {result.stderr}") + logger.error(f"iw scan error: {result.stderr}") return [] output = result.stdout logger.debug( - f"Вывод iw scan (первые 500 символов): {output[:500]}...") + f"iw scan output (first 500 chars): {output[:500]}...") aps = [] current_ap = None @@ -294,19 +300,19 @@ class WifiService: aps.append(current_ap) logger.debug( - f"Найдено {len(aps)} точек через iw: {[ap['bssid'] for ap in aps]}" + f"Found {len(aps)} access points via iw: {[ap['bssid'] for ap in aps]}" ) for ap in aps: - logger.debug(f"Данные точки {ap['bssid']}: {ap}") + logger.debug(f"Access point {ap['bssid']}: {ap}") return aps except subprocess.CalledProcessError as e: - logger.error(f"Ошибка при выполнении iw scan: {e.stderr}") + logger.error(f"Error executing iw scan: {e.stderr}") return [] except subprocess.TimeoutExpired: - logger.error("Таймаут при выполнении iw scan") + logger.error(self.translations.gettext("Таймаут при выполнении iw scan")) return [] except Exception as e: - logger.error(f"Ошибка при парсинге iw scan: {str(e)}") + logger.error(f"Error parsing iw scan: {str(e)}") return [] def scan_wifi(self, timeout: int = 30) -> WifiScanResult: @@ -326,17 +332,17 @@ class WifiService: aps = [] if not self.interface: - logger.error("Wi-Fi-интерфейс не доступен") + logger.error(self.translations.gettext("Wi-Fi-интерфейс не доступен")) return WifiScanResult(access_points=aps) try: logger.info( - f"Начало сканирования Wi-Fi на интерфейсе {self.interface.name()}" + f"Starting Wi-Fi scan on interface {self.interface.name()}" ) self.interface.scan() time.sleep(10) py_results = self.interface.scan_results() - logger.debug(f"Найдено {len(py_results)} точек через pywifi") + logger.debug(f"Found {len(py_results)} access points via pywifi") iw_results = self._get_iw_scan_data() iw_by_bssid = {ap["bssid"]: ap for ap in iw_results if ap.get("bssid")} @@ -347,7 +353,7 @@ class WifiService: for ap in py_results: bssid = ap.bssid.lower() if ap.bssid else None if not bssid: - logger.debug("Пропущена точка без BSSID") + logger.debug("Skipped access point without BSSID") continue ssid = ap.ssid if ap.ssid else "" hidden = not ssid @@ -361,7 +367,7 @@ class WifiService: vendor = self.get_vendor(bssid) logger.debug( - f"Точка {bssid}: freq={frequency}, channel={channel}, encryption={encryption}, signal={signal}" + f"Access point {bssid}: freq={frequency}, channel={channel}, encryption={encryption}, signal={signal}" ) current_ap = WifiAccessPoint( @@ -386,12 +392,13 @@ class WifiService: self.storage.save_notes(notes_to_save) logger.info( - f"Сканирование Wi-Fi завершено за {time.time() - start_time:.2f} секунд, " - f"найдено {len(aps)} уникальных сетей") + f"Wi-Fi scan completed in {time.time() - start_time:.2f} seconds, " + f"found {len(aps)} unique networks" + ) return WifiScanResult(access_points=aps) except Exception as e: - logger.error(f"Ошибка при сканировании Wi-Fi: {str(e)}") + logger.error(f"Error scanning Wi-Fi: {str(e)}") return WifiScanResult(access_points=aps) def add_note(self, ssid: str, note: str) -> Tuple[bool, Optional[str]]: @@ -412,17 +419,17 @@ class WifiService: try: saved_notes = self.storage.load_notes() if ssid not in saved_notes or saved_notes[ssid] is None: - logger.info(f"Добавлена новая заметка для сети с SSID {ssid}") + logger.info(f"Added new note for network with SSID {ssid}") elif saved_notes[ssid] is not None: - logger.error(f"Заметка для сети с SSID {ssid} уже существует") - return False, f"Заметка для сети с SSID {ssid} уже существует" + logger.error(f"Note for network with SSID {ssid} already exists") + return False, self.translations.gettext("Заметка для сети с SSID {ssid} уже существует").format(ssid=ssid) saved_notes[ssid] = note self.storage.save_notes(saved_notes) - logger.info(f"Добавлена заметка '{note}' для сети с SSID {ssid}") + logger.info(f"Added note '{note}' for network with SSID {ssid}") return True, None except Exception as e: - logger.error(f"Ошибка при добавлении заметки для SSID {ssid}: {str(e)}") - return False, f"Внутренняя ошибка сервера: {str(e)}" + logger.error(f"Error adding note for SSID {ssid}: {str(e)}") + return False, self.translations.gettext("Внутренняя ошибка сервера: {error}").format(error=str(e)) def update_note(self, ssid: str, note: str) -> Tuple[bool, Optional[str]]: """Обновляет заметку сети Wi-Fi по SSID. @@ -442,18 +449,18 @@ class WifiService: try: saved_notes = self.storage.load_notes() if ssid not in saved_notes: - logger.warning(f"Сеть с SSID {ssid} не найдена") - return False, f"Сеть с SSID {ssid} не найдена" + logger.warning(f"Network with SSID {ssid} not found") + return False, self.translations.gettext("Сеть с SSID {ssid} не найдена").format(ssid=ssid) if saved_notes[ssid] is None: - logger.error(f"Заметка для сети с SSID {ssid} не существует") - return False, f"Заметка для сети с SSID {ssid} не существует" + logger.error(f"Note for network with SSID {ssid} does not exist") + return False, self.translations.gettext("Заметка для сети с SSID {ssid} не существует").format(ssid=ssid) saved_notes[ssid] = note self.storage.save_notes(saved_notes) - logger.info(f"Обновлена заметка '{note}' для сети с SSID {ssid}") + logger.info(f"Updated note '{note}' for network with SSID {ssid}") return True, None except Exception as e: - logger.error(f"Ошибка при обновлении заметки для SSID {ssid}: {str(e)}") - return False, f"Внутренняя ошибка сервера: {str(e)}" + logger.error(f"Error updating note for SSID {ssid}: {str(e)}") + return False, self.translations.gettext("Внутренняя ошибка сервера: {error}").format(error=str(e)) def delete_note(self, ssid: str) -> Tuple[bool, Optional[str]]: """Удаляет заметку сети Wi-Fi по SSID. @@ -472,15 +479,15 @@ class WifiService: try: saved_notes = self.storage.load_notes() if ssid not in saved_notes: - logger.warning(f"Сеть с SSID {ssid} не найдена") - return False, f"Сеть с SSID {ssid} не найдена" + logger.warning(f"Network with SSID {ssid} not found") + return False, self.translations.gettext("Сеть с SSID {ssid} не найдена").format(ssid=ssid) if saved_notes[ssid] is None: - logger.error(f"Заметка для сети с SSID {ssid} не существует") - return False, f"Заметка для сети с SSID {ssid} не существует" + logger.error(f"Note for network with SSID {ssid} does not exist") + return False, self.translations.gettext("Заметка для сети с SSID {ssid} не существует").format(ssid=ssid) saved_notes[ssid] = None self.storage.save_notes(saved_notes) - logger.info(f"Удалена заметка для сети с SSID {ssid}") + logger.info(f"Deleted note for network with SSID {ssid}") return True, None except Exception as e: - logger.error(f"Ошибка при удалении заметки для SSID {ssid}: {str(e)}") - return False, f"Внутренняя ошибка сервера: {str(e)}" \ No newline at end of file + logger.error(f"Error deleting note for SSID {ssid}: {str(e)}") + return False, self.translations.gettext("Внутренняя ошибка сервера: {error}").format(error=str(e)) \ No newline at end of file