Edit depends call in i18n

This commit is contained in:
parent 9f0ab4ae5a
commit a13636ca49
8 changed files with 52 additions and 53 deletions

View file

@ -44,7 +44,7 @@ class ContainerPositionManager:
},
}
def get_position_and_state(self, container_name: str, translations: Translations = Depends(get_translations())) -> Tuple[int, int, bool]:
def get_position_and_state(self, container_name: str, translations: Translations = None) -> Tuple[int, int, bool]:
"""Получает текущие координаты и состояние указанного контейнера.
Args:
@ -57,6 +57,7 @@ class ContainerPositionManager:
Raises:
ValueError: Если указан неверный идентификатор контейнера.
"""
translations = translations or get_translations()()
container = self.positions.get(container_name)
if not container:
raise ValueError(translations.gettext("Неверное имя контейнера: {container_name}").format(container_name=container_name))

View file

@ -18,7 +18,6 @@
"""
import os
import logging
from fastapi import Depends
import netifaces
from netaddr import IPNetwork
from utils.i18n import get_translations, _
@ -45,7 +44,7 @@ class NetworkScanner:
вывода информации о клиентах.
"""
def __init__(self, interface=None, translations: Translations = Depends(get_translations())):
def __init__(self, interface=None, translations: Translations = None):
"""Инициализация параметров сетевого сканера.
Args:
@ -55,7 +54,7 @@ class NetworkScanner:
Инициализирует интерфейс, информацию об IP-адресах и локальный MAC-адрес.
"""
self.translations = translations
self.translations = translations or get_translations()()
self.interface = None
self.ip_info = []
self.networks = []

View file

@ -1,6 +1,6 @@
from jose import JWTError, jwt
from datetime import datetime, timedelta
from fastapi import HTTPException, Depends, Request
from fastapi import HTTPException, Depends
from fastapi.security import OAuth2PasswordBearer
from models.auth import UserCreate, UserLogin, UserResponse, Token
from storage.json_storage import JsonStorage
@ -35,10 +35,10 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login")
class AuthService:
"""Сервис для регистрации, авторизации и управления сессиями"""
def __init__(self, translations: Translations = Depends(get_translations())):
def __init__(self, translations: Optional[Translations] = None):
self.storage = JsonStorage()
self.session_storage = SessionStorage()
self.translations = translations
self.translations = translations or get_translations()()
def create_access_token(self, data: dict) -> str:
"""Создаёт токен"""

View file

@ -20,7 +20,6 @@ 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__)
@ -37,13 +36,7 @@ class WifiConnectionService:
Автоматически определяет доступный Wi-Fi-интерфейс и сохраняет его имя.
"""
self.interface = self._get_wifi_interface()
if translations is None:
try:
self.translations = Translations.load("locales", ["ru"], "messages")
except Exception:
self.translations = Translations()
else:
self.translations = translations
self.translations = translations or get_translations()()
def _get_wifi_interface(self) -> str:
"""Автоматически определяет Wi-Fi-интерфейс.

View file

@ -34,7 +34,6 @@ from models.network import (
import subprocess
from utils.i18n import get_translations, _
from babel.support import Translations
from fastapi import Depends
class NetworkService:
"""Сервис для взаимодействия с NetworkManager через D-Bus.
@ -43,7 +42,7 @@ class NetworkService:
их конфигурациях IP, Wi-Fi и состояниях.
"""
def __init__(self, translations: Translations = Depends(get_translations())):
def __init__(self, translations: Translations = None):
"""Инициализирует сервис NetworkManager.
Устанавливает системный D-Bus и создаёт объекты для взаимодействия с
@ -52,7 +51,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
self.translations = translations or get_translations()()
async def get_ip_method(self, device: NetworkDeviceGeneric, ip_type: str) -> str:
"""Получает метод IP (например, "auto", "manual") для указанного устройства.

View file

@ -4,7 +4,6 @@ from typing import Optional
from utils.i18n import get_translations
from babel.support import Translations
from fastapi import Depends
from pathlib import Path
logging.basicConfig(level=logging.INFO)
@ -13,10 +12,10 @@ logger = logging.getLogger(__name__)
class SettingsService:
"""Сервис для управления настройками и очистки данных сети."""
def __init__(self, translations: Translations = Depends(get_translations())):
def __init__(self, translations: Translations = None):
self.subnet_base_path = "storage/subnets"
self.wifi_file = "storage/wifi/wifi.json"
self.translations = translations
self.translations = translations or get_translations()()
def clear_subnet(self, subnet: Optional[str] = None) -> bool:
"""Очищает данные узлов подсети в указанном файле или во всех файлах.

View file

@ -11,7 +11,6 @@ from pathlib import Path
import json
from utils.i18n import get_translations
from babel.support import Translations
from fastapi import Depends
# Настройка логирования
logging.basicConfig(
@ -34,10 +33,10 @@ class WifiStorage:
- Создаёт директорию хранения при инициализации, ведёт логирование путей.
- Валидирует структуру при чтении и безопасно записывает JSON с Unicode и отступами.
"""
def __init__(self, storage_path: str = "storage/wifi/wifi.json", translations: Translations = Depends(get_translations())):
def __init__(self, storage_path: str = "storage/wifi/wifi.json", translations: Translations = None):
self.storage_file = Path(storage_path)
self.storage_file.parent.mkdir(parents=True, exist_ok=True)
self.translations = translations
self.translations = translations or get_translations()()
logger.info(f"Wi-Fi storage initialized at: {self.storage_file.absolute()}")
def load_notes(self) -> Dict[str, Optional[str]]:
@ -85,15 +84,15 @@ class WifiService:
- Кэширование определения вендора.
- Сохранение SSID даже без заметок для будущих операций.
"""
def __init__(self, translations: Translations = Depends(get_translations())):
def __init__(self, translations: Translations = None):
self.mac_lookup = MacLookup()
self.wifi = pywifi.PyWiFi()
self.interface = self._get_wifi_interface()
if not hasattr(translations, 'gettext'):
validated_translations = translations or get_translations()()
if not hasattr(validated_translations, "gettext"):
logger.warning("Translations object does not support gettext, using fallback")
self.translations = Translations.load("utils/locales/en/LC_MESSAGES/services.mo")
else:
self.translations = translations
validated_translations = get_translations()()
self.translations = validated_translations
self.storage = WifiStorage()
def _get_wifi_interface(self) -> Optional[object]:

View file

@ -16,40 +16,49 @@
региональных суффиксов) для упрощения.
- Модуль ведёт отладочное логирование выбора и загрузки локали.
"""
from fastapi import Request, Depends
from fastapi import Request, WebSocket
from babel.support import Translations
import logging
from typing import Optional, Union
from pathlib import Path
logger = logging.getLogger(__name__)
LOCALES_DIR = Path(__file__).resolve().parent.parent / "locales"
def _load_translations(locale: str) -> Translations:
"""Подгружает словарь переводов с fallback на ru."""
try:
translations = Translations.load(str(LOCALES_DIR), [locale], "messages")
if not translations._catalog:
logger.warning(f"Translations for locale {locale} not found, falling back to ru")
translations = Translations.load(str(LOCALES_DIR), ["ru"], "messages")
return translations
except Exception as e: # pragma: no cover - логируем и возвращаем ru
logger.error(f"Failed to load translations for locale {locale}: {str(e)}")
return Translations.load(str(LOCALES_DIR), ["ru"], "messages")
def get_translations() -> callable:
"""
Создаёт зависимость для загрузки переводов на основе заголовка Accept-Language
или параметра запроса 'locale'. По умолчанию используется русский язык.
"""
def translations_dependency(request: Request) -> Translations:
def translations_dependency(request: Optional[Union[Request, WebSocket]] = None) -> Translations:
if request is None:
logger.warning("Translations dependency called without request/websocket; fallback to ru")
return _load_translations("ru")
# Проверяем параметр запроса 'locale', если он есть
locale = None
if hasattr(request, "query_params"):
locale = request.query_params.get("locale")
if not locale:
# Если параметр отсутствует, проверяем куку 'locale'
if not locale and hasattr(request, "cookies"):
locale = request.cookies.get("locale")
if not locale:
# Если куки нет, используем заголовок Accept-Language
if not locale and hasattr(request, "headers"):
locale = request.headers.get("Accept-Language", "ru").split(",")[0].split("-")[0]
locale = locale or "ru"
logger.debug(f"Determined locale: {locale}")
try:
translations = Translations.load("locales", [locale], "messages")
if not translations._catalog:
logger.warning(f"Translations for locale {locale} not found, falling back to ru")
translations = Translations.load("locales", ["ru"], "messages")
logger.debug(f"Loaded translations for locale {locale}, catalog size: {len(translations._catalog)}")
return translations
except Exception as e:
logger.error(f"Failed to load translations for locale {locale}: {str(e)}")
# Fallback на русский
logger.debug("Falling back to ru translations")
return Translations.load("locales", ["ru"], "messages")
return _load_translations(locale)
return translations_dependency
@ -66,7 +75,7 @@ def _(msgid: str, request: Request = None) -> str:
"""
if request is None:
# Язык, который будет отображаться по умолчанию
translations = Translations.load("locales", ["ru"], "messages")
translations = _load_translations("ru")
logger.debug(f"Using default ru translations for msgid: {msgid}")
else:
translations = get_translations()(request)