Files
guarddog-nexus/guarddog_nexus/i18n.py
Marker689 d11be24c5f fix(i18n): формальный русский перевод + t() во всех шаблонах
- i18n.py: формальный русский (сканирования, панель управления, и т.д.)
- Все шаблоны: замена хардкод-строк на t(key, request.state.lang)
- dashboard_stats_fragment: добавлен request в контекст
2026-05-10 07:52:58 +03:00

110 lines
6.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Internationalisation — RU / EN dictionaries and helpers."""
_STRINGS = {
"nav_dashboard": {"en": "Dashboard", "ru": "Панель"},
"nav_scans": {"en": "Scans", "ru": "Сканирования"},
"nav_packages": {"en": "Packages", "ru": "Пакеты"},
"title_dashboard": {"en": "Dashboard — GuardDog Nexus", "ru": "Панель — GuardDog Nexus"},
"title_scans": {"en": "Scans — GuardDog Nexus", "ru": "Сканирования — GuardDog Nexus"},
"title_packages": {"en": "Packages — GuardDog Nexus", "ru": "Пакеты — GuardDog Nexus"},
"title_scan_detail": {
"en": "Scan #{} — GuardDog Nexus",
"ru": "Сканирование #{} — GuardDog Nexus",
},
"title_package_detail": {"en": "{} v{} — GuardDog Nexus", "ru": "{} v{} — GuardDog Nexus"},
"heading_dashboard": {"en": "Dashboard", "ru": "Панель управления"},
"heading_scans": {"en": "Scans", "ru": "Сканирования"},
"heading_packages": {"en": "Packages", "ru": "Пакеты"},
"heading_latest_flagged": {"en": "Latest Flagged", "ru": "Последние обнаружения"},
"heading_latest_scans": {"en": "Latest Scans", "ru": "Последние сканирования"},
"heading_findings": {"en": "Findings", "ru": "Находки"},
"heading_findings_count": {"en": "Findings ({})", "ru": "Находки ({})"},
"heading_scans_count": {"en": "Scans ({})", "ru": "Сканирований ({})"},
"col_id": {"en": "ID", "ru": "ID"},
"col_package": {"en": "Package", "ru": "Пакет"},
"col_version": {"en": "Version", "ru": "Версия"},
"col_repo": {"en": "Repo", "ru": "Репозиторий"},
"col_repository": {"en": "Repository", "ru": "Репозиторий"},
"col_status": {"en": "Status", "ru": "Статус"},
"col_findings": {"en": "Findings", "ru": "Находки"},
"col_time": {"en": "Time", "ru": "Время"},
"col_name": {"en": "Name", "ru": "Название"},
"col_ecosystem": {"en": "Ecosystem", "ru": "Экосистема"},
"col_flagged": {"en": "Flagged", "ru": "Помечен"},
"col_last_scan": {"en": "Last Scan", "ru": "Последнее сканирование"},
"filter_search": {"en": "Search packages...", "ru": "Поиск пакетов..."},
"filter_all_statuses": {"en": "All Statuses", "ru": "Все статусы"},
"filter_pending": {"en": "Pending", "ru": "Ожидание"},
"filter_scanning": {"en": "Scanning", "ru": "Сканирование"},
"filter_completed": {"en": "Completed", "ru": "Завершено"},
"filter_failed": {"en": "Failed", "ru": "Ошибка"},
"btn_show_all": {"en": "Show all", "ru": "Показать все"},
"btn_flagged_only": {"en": "Flagged only", "ru": "Только помеченные"},
"btn_export_csv": {"en": "Export CSV", "ru": "Экспорт CSV"},
"btn_analyze_llm": {"en": "Analyze with LLM", "ru": "Анализировать через LLM"},
"btn_copy": {"en": "Copy", "ru": "Копировать"},
"btn_prev": {"en": "Prev", "ru": "Пред."},
"btn_next": {"en": "Next", "ru": "След."},
"scan_info_package": {"en": "Package", "ru": "Пакет"},
"scan_info_version": {"en": "Version", "ru": "Версия"},
"scan_info_ecosystem": {"en": "Ecosystem", "ru": "Экосистема"},
"scan_info_repository": {"en": "Repository", "ru": "Репозиторий"},
"scan_info_status": {"en": "Status", "ru": "Статус"},
"scan_info_sha256": {"en": "SHA256", "ru": "SHA256"},
"scan_info_started": {"en": "Started", "ru": "Запущено"},
"scan_info_finished": {"en": "Finished", "ru": "Завершено"},
"scan_info_initiated": {"en": "Initiated by", "ru": "Инициатор"},
"scan_info_source_ip": {"en": "Source IP", "ru": "IP-адрес"},
"scan_info_error": {"en": "Error", "ru": "Ошибка"},
"empty_no_scans": {
"en": "No scans yet — scans will appear here once packages are processed.",
"ru": "Сканирования отсутствуют — появятся после обработки пакетов.",
},
"empty_no_packages": {
"en": "No packages yet — packages will appear here once scans are processed.",
"ru": "Пакеты отсутствуют — появятся после сканирования.",
},
"empty_no_findings": {
"en": "No findings — package looks clean.",
"ru": "Находки отсутствуют — пакет не содержит угроз.",
},
"view_all_scans": {"en": "View all scans →", "ru": "Все сканирования →"},
"refresh_hint": {
"en": "Last refresh: {} (auto every 30s)",
"ru": "Последнее обновление: {} (автоматически каждые 30 с)",
},
"llm_disabled": {"en": "LLM analysis is disabled", "ru": "LLM-анализ отключён"},
"llm_failed": {"en": "LLM analysis failed", "ru": "Ошибка LLM-анализа"},
"llm_not_found": {"en": "Finding not found", "ru": "Находка не найдена"},
"llm_disclaimer": {
"en": "⚠ AI-generated analysis — may contain inaccuracies. "
"Always verify findings before taking action.",
"ru": "⚠ Анализ сгенерирован AI — может содержать неточности. "
"Всегда проверяйте находки перед принятием мер.",
},
"breadcrumb_home": {"en": "Home", "ru": "Главная"},
"breadcrumb_dashboard": {"en": "Dashboard", "ru": "Панель"},
"breadcrumb_scans": {"en": "Scans", "ru": "Сканирования"},
"breadcrumb_packages": {"en": "Packages", "ru": "Пакеты"},
"page_of": {"en": "of", "ru": "из"},
"page_label": {"en": "Page", "ru": "Стр."},
"total_scans": {"en": "{} total scans", "ru": "{} сканирований всего"},
"total_packages": {"en": "{} total packages", "ru": "{} пакетов всего"},
"scan_detail_title": {"en": "Scan #{}", "ru": "Сканирование #{}"},
}
LANGUAGES = {"en": "English", "ru": "Русский"}
DEFAULT_LANG = "en"
def t(key: str, lang: str = DEFAULT_LANG, *args, **kwargs) -> str:
"""Look up a string in the given language, with optional formatting."""
entry = _STRINGS.get(key, {})
text = entry.get(lang) or entry.get(DEFAULT_LANG, key)
if args or kwargs:
try:
return text.format(*args, **kwargs)
except (KeyError, IndexError):
return text
return text