From d11be24c5f185826d2bb33ce56eb6b60e37b19f0 Mon Sep 17 00:00:00 2001 From: Marker689 Date: Sun, 10 May 2026 07:52:58 +0300 Subject: [PATCH] =?UTF-8?q?fix(i18n):=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D1=80=D1=83=D1=81=D1=81=D0=BA?= =?UTF-8?q?=D0=B8=D0=B9=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=BE=D0=B4=20+?= =?UTF-8?q?=20t()=20=D0=B2=D0=BE=20=D0=B2=D1=81=D0=B5=D1=85=20=D1=88=D0=B0?= =?UTF-8?q?=D0=B1=D0=BB=D0=BE=D0=BD=D0=B0=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - i18n.py: формальный русский (сканирования, панель управления, и т.д.) - Все шаблоны: замена хардкод-строк на t(key, request.state.lang) - dashboard_stats_fragment: добавлен request в контекст --- guarddog_nexus/i18n.py | 83 ++++++++++--------- guarddog_nexus/routes/web.py | 4 +- .../web/templates/_packages_table.html | 24 +++--- .../web/templates/_scans_table.html | 24 +++--- guarddog_nexus/web/templates/dashboard.html | 8 +- .../web/templates/dashboard_stats.html | 12 +-- .../web/templates/package_detail.html | 20 ++--- .../web/templates/packages_list.html | 14 ++-- guarddog_nexus/web/templates/scan_detail.html | 42 +++++----- guarddog_nexus/web/templates/scans_list.html | 24 +++--- 10 files changed, 129 insertions(+), 126 deletions(-) diff --git a/guarddog_nexus/i18n.py b/guarddog_nexus/i18n.py index c4c22d1..ad8533e 100644 --- a/guarddog_nexus/i18n.py +++ b/guarddog_nexus/i18n.py @@ -1,22 +1,25 @@ """Internationalisation — RU / EN dictionaries and helpers.""" _STRINGS = { - "nav_dashboard": {"en": "Dashboard", "ru": "Дашборд"}, - "nav_scans": {"en": "Scans", "ru": "Сканы"}, + "nav_dashboard": {"en": "Dashboard", "ru": "Панель"}, + "nav_scans": {"en": "Scans", "ru": "Сканирования"}, "nav_packages": {"en": "Packages", "ru": "Пакеты"}, - "title_dashboard": {"en": "GuardDog Nexus", "ru": "GuardDog Nexus"}, - "title_scans": {"en": "Scans — GuardDog Nexus", "ru": "Сканы — GuardDog Nexus"}, + "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_scan_detail": { + "en": "Scan #{} — GuardDog Nexus", + "ru": "Сканирование #{} — GuardDog Nexus", + }, "title_package_detail": {"en": "{} v{} — GuardDog Nexus", "ru": "{} v{} — GuardDog Nexus"}, - "heading_scans": {"en": "Scans", "ru": "Сканы"}, + "heading_dashboard": {"en": "Dashboard", "ru": "Панель управления"}, + "heading_scans": {"en": "Scans", "ru": "Сканирования"}, "heading_packages": {"en": "Packages", "ru": "Пакеты"}, - "heading_dashboard": {"en": "Dashboard", "ru": "Дашборд"}, - "heading_latest_flagged": {"en": "Latest Flagged", "ru": "Последние флаги"}, - "heading_latest_scans": {"en": "Latest Scans", "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": "Сканы ({})"}, + "heading_scans_count": {"en": "Scans ({})", "ru": "Сканирований ({})"}, "col_id": {"en": "ID", "ru": "ID"}, "col_package": {"en": "Package", "ru": "Пакет"}, "col_version": {"en": "Version", "ru": "Версия"}, @@ -25,53 +28,53 @@ _STRINGS = { "col_status": {"en": "Status", "ru": "Статус"}, "col_findings": {"en": "Findings", "ru": "Находки"}, "col_time": {"en": "Time", "ru": "Время"}, - "col_name": {"en": "Name", "ru": "Имя"}, + "col_name": {"en": "Name", "ru": "Название"}, "col_ecosystem": {"en": "Ecosystem", "ru": "Экосистема"}, - "col_flagged": {"en": "Flagged", "ru": "Флаг"}, - "col_last_scan": {"en": "Last Scan", "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_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_flagged_only": {"en": "Flagged only", "ru": "Только помеченные"}, "btn_export_csv": {"en": "Export CSV", "ru": "Экспорт CSV"}, - "btn_analyze_llm": {"en": "Analyze with LLM", "ru": "Анализ через LLM"}, + "btn_analyze_llm": {"en": "Analyze with LLM", "ru": "Анализировать через LLM"}, "btn_copy": {"en": "Copy", "ru": "Копировать"}, - "btn_prev": {"en": "Prev", "ru": "Назад"}, - "btn_next": {"en": "Next", "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_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": "Сканов пока нет — появятся после обработки пакетов.", + "ru": "Сканирования отсутствуют — появятся после обработки пакетов.", }, "empty_no_packages": { "en": "No packages yet — packages will appear here once scans are processed.", - "ru": "Пакетов пока нет — появятся после сканирования.", + "ru": "Пакеты отсутствуют — появятся после сканирования.", }, "empty_no_findings": { "en": "No findings — package looks clean.", - "ru": "Находок нет — пакет чистый.", + "ru": "Находки отсутствуют — пакет не содержит угроз.", }, - "view_all_scans": {"en": "View all scans →", "ru": "Все сканы →"}, + "view_all_scans": {"en": "View all scans →", "ru": "Все сканирования →"}, "refresh_hint": { "en": "Last refresh: {} (auto every 30s)", - "ru": "Обновлено: {} (авто каждые 30с)", + "ru": "Последнее обновление: {} (автоматически каждые 30 с)", }, "llm_disabled": {"en": "LLM analysis is disabled", "ru": "LLM-анализ отключён"}, - "llm_failed": {"en": "LLM analysis failed", "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. " @@ -80,27 +83,27 @@ _STRINGS = { "Всегда проверяйте находки перед принятием мер.", }, "breadcrumb_home": {"en": "Home", "ru": "Главная"}, - "breadcrumb_scans": {"en": "Scans", "ru": "Сканы"}, + "breadcrumb_dashboard": {"en": "Dashboard", "ru": "Панель"}, + "breadcrumb_scans": {"en": "Scans", "ru": "Сканирования"}, "breadcrumb_packages": {"en": "Packages", "ru": "Пакеты"}, - "breadcrumb_dashboard": {"en": "Dashboard", "ru": "Дашборд"}, "page_of": {"en": "of", "ru": "из"}, - "total_scans": {"en": "{} total scans", "ru": "{} всего сканов"}, - "total_packages": {"en": "{} total packages", "ru": "{} всего пакетов"}, - "scan_detail_title": {"en": "Scan #{}", "ru": "Скан #{}"}, - "status_pending": {"en": "pending", "ru": "ожидает"}, - "status_scanning": {"en": "scanning", "ru": "сканируется"}, - "status_completed": {"en": "completed", "ru": "завершён"}, - "status_failed": {"en": "failed", "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, **kwargs) -> str: +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 kwargs: - return text.format(**kwargs) + if args or kwargs: + try: + return text.format(*args, **kwargs) + except (KeyError, IndexError): + return text return text diff --git a/guarddog_nexus/routes/web.py b/guarddog_nexus/routes/web.py index 708fb87..706c989 100644 --- a/guarddog_nexus/routes/web.py +++ b/guarddog_nexus/routes/web.py @@ -45,9 +45,9 @@ async def dashboard(request: Request, session: AsyncSession = Depends(get_sessio @router.get("/dashboard/stats", response_class=HTMLResponse) -async def dashboard_stats_fragment(session: AsyncSession = Depends(get_session)): +async def dashboard_stats_fragment(request: Request, session: AsyncSession = Depends(get_session)): ctx = await get_dashboard_stats(session) - return _render("dashboard_stats.html", **ctx) + return _render("dashboard_stats.html", request=request, **ctx) @router.get("/scans", response_class=HTMLResponse) diff --git a/guarddog_nexus/web/templates/_packages_table.html b/guarddog_nexus/web/templates/_packages_table.html index fb79580..e466b40 100644 --- a/guarddog_nexus/web/templates/_packages_table.html +++ b/guarddog_nexus/web/templates/_packages_table.html @@ -2,19 +2,19 @@ - Name {% if sort_by == 'name' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} + {{ t('col_name', request.state.lang) }} {% if sort_by == 'name' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} - Version - Ecosystem - Repo + {{ t('col_version', request.state.lang) }} + {{ t('col_ecosystem', request.state.lang) }} + {{ t('col_repo', request.state.lang) }} - Flagged {% if sort_by == 'flagged' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} + {{ t('col_flagged', request.state.lang) }} {% if sort_by == 'flagged' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} - Findings {% if sort_by == 'total_findings' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} + {{ t('col_findings', request.state.lang) }} {% if sort_by == 'total_findings' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} - Last Scan {% if sort_by == 'last_scanned_at' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} + {{ t('col_last_scan', request.state.lang) }} {% if sort_by == 'last_scanned_at' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} @@ -32,7 +32,7 @@ {% endfor %} {% if not packages %} - No packages yet — packages will appear here once scans are processed. + {{ t('empty_no_packages', request.state.lang) }} {% endif %} @@ -42,10 +42,10 @@ {% if total_pages > 1 %} {% endif %} -{{ total }} total packages +{{ t('total_packages', request.state.lang, total) }} diff --git a/guarddog_nexus/web/templates/_scans_table.html b/guarddog_nexus/web/templates/_scans_table.html index b527097..25f4177 100644 --- a/guarddog_nexus/web/templates/_scans_table.html +++ b/guarddog_nexus/web/templates/_scans_table.html @@ -2,21 +2,21 @@ - ID {% if sort_by == 'id' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} + {{ t('col_id', request.state.lang) }} {% if sort_by == 'id' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} - Package {% if sort_by == 'package_name' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} + {{ t('col_package', request.state.lang) }} {% if sort_by == 'package_name' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} - Version - Repo + {{ t('col_version', request.state.lang) }} + {{ t('col_repo', request.state.lang) }} - Status {% if sort_by == 'status' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} + {{ t('col_status', request.state.lang) }} {% if sort_by == 'status' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} - Findings {% if sort_by == 'total_findings' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} + {{ t('col_findings', request.state.lang) }} {% if sort_by == 'total_findings' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} - Time {% if sort_by == 'started_at' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} + {{ t('col_time', request.state.lang) }} {% if sort_by == 'started_at' %}{{ '▲' if sort_dir == 'asc' else '▼' }}{% else %}↕{% endif %} @@ -36,7 +36,7 @@ {% endfor %} {% if not scans %} - No scans yet — scans will appear here once packages are processed. + {{ t('empty_no_scans', request.state.lang) }} {% endif %} @@ -46,10 +46,10 @@ {% if total_pages > 1 %} {% endif %} -{{ total }} total scans +{{ t('total_scans', request.state.lang, total) }} diff --git a/guarddog_nexus/web/templates/dashboard.html b/guarddog_nexus/web/templates/dashboard.html index cb23fad..8e6eec3 100644 --- a/guarddog_nexus/web/templates/dashboard.html +++ b/guarddog_nexus/web/templates/dashboard.html @@ -1,14 +1,14 @@ {% extends "base.html" %} -{% block title %}Dashboard — GuardDog Nexus{% endblock %} +{% block title %}{{ t('title_dashboard', request.state.lang) }}{% endblock %} {% block breadcrumbs %} {% endblock %} {% block content %} -

Dashboard

+

{{ t('heading_dashboard', request.state.lang) }}

{% include "dashboard_stats.html" %} diff --git a/guarddog_nexus/web/templates/dashboard_stats.html b/guarddog_nexus/web/templates/dashboard_stats.html index dcd89be..62bf27a 100644 --- a/guarddog_nexus/web/templates/dashboard_stats.html +++ b/guarddog_nexus/web/templates/dashboard_stats.html @@ -1,8 +1,8 @@ {% if latest_flagged %}
-

Latest Flagged

+

{{ t('heading_latest_flagged', request.state.lang) }}

- + {% for s in latest_flagged %} @@ -18,10 +18,10 @@ {% endif %}
-

Latest Scans

+

{{ t('heading_latest_scans', request.state.lang) }}

PackageVersionFindingsTime
{{ t('col_package', request.state.lang) }}{{ t('col_version', request.state.lang) }}{{ t('col_findings', request.state.lang) }}{{ t('col_time', request.state.lang) }}
- + {% for s in latest_scans %} @@ -38,7 +38,7 @@ {% endfor %}
PackageVersionRepoStatusTime
{{ t('col_package', request.state.lang) }}{{ t('col_version', request.state.lang) }}{{ t('col_repo', request.state.lang) }}{{ t('col_status', request.state.lang) }}{{ t('col_time', request.state.lang) }}
- View all scans → + {{ t('view_all_scans', request.state.lang) }}
-Last refresh: {{ now.strftime('%H:%M:%S') }} (auto every 30s) +{{ t('refresh_hint', request.state.lang, now.strftime('%H:%M:%S')) }} diff --git a/guarddog_nexus/web/templates/package_detail.html b/guarddog_nexus/web/templates/package_detail.html index 27260eb..fd744c5 100644 --- a/guarddog_nexus/web/templates/package_detail.html +++ b/guarddog_nexus/web/templates/package_detail.html @@ -1,10 +1,10 @@ {% extends "base.html" %} -{% block title %}{{ pkg_name }} v{{ pkg_version }} — GuardDog Nexus{% endblock %} +{% block title %}{{ t('title_package_detail', request.state.lang, pkg_name, pkg_version) }}{% endblock %} {% block breadcrumbs %} @@ -13,10 +13,10 @@

{{ pkg_name }} v{{ pkg_version }}

-

Scans ({{ scans|length }})

+

{{ t('heading_scans_count', request.state.lang, scans|length) }}

- + {% for s in scans %} @@ -34,7 +34,7 @@
IDRepoStatusFindingsTime
{{ t('col_id', request.state.lang) }}{{ t('col_repo', request.state.lang) }}{{ t('col_status', request.state.lang) }}{{ t('col_findings', request.state.lang) }}{{ t('col_time', request.state.lang) }}
-

Findings ({{ findings|length }})

+

{{ t('heading_findings_count', request.state.lang, findings|length) }}

{% if findings %}
@@ -49,7 +49,7 @@

{{ f.data.message }}

{% if f.data.code %}
- +
{{ f.data.code }}
{% endif %} @@ -64,7 +64,7 @@

{{ f.report.summary }}

{{ f.report.analysis }}

-

⚠ AI-generated analysis — may contain inaccuracies.

+

{{ t('llm_disclaimer', request.state.lang) }}

{% else %}
@@ -76,7 +76,7 @@ - Analyze with LLM + {{ t('btn_analyze_llm', request.state.lang) }}
{% endif %} @@ -85,6 +85,6 @@ {% endfor %} {% else %} -

No findings — package looks clean.

+

{{ t('empty_no_findings', request.state.lang) }}

{% endif %} {% endblock %} diff --git a/guarddog_nexus/web/templates/packages_list.html b/guarddog_nexus/web/templates/packages_list.html index 259eebc..e01cf34 100644 --- a/guarddog_nexus/web/templates/packages_list.html +++ b/guarddog_nexus/web/templates/packages_list.html @@ -1,21 +1,21 @@ {% extends "base.html" %} -{% block title %}Packages — GuardDog Nexus{% endblock %} +{% block title %}{{ t('title_packages', request.state.lang) }}{% endblock %} {% block breadcrumbs %} {% endblock %} {% block content %} -

Packages

+

{{ t('heading_packages', request.state.lang) }}

- + - {% if flagged_filter == '1' %}Show all{% else %}Flagged only{% endif %} + {% if flagged_filter == '1' %}{{ t('btn_show_all', request.state.lang) }}{% else %}{{ t('btn_flagged_only', request.state.lang) }}{% endif %} - Export CSV + {{ t('btn_export_csv', request.state.lang) }}
diff --git a/guarddog_nexus/web/templates/scan_detail.html b/guarddog_nexus/web/templates/scan_detail.html index 8e7b42c..cb97c7c 100644 --- a/guarddog_nexus/web/templates/scan_detail.html +++ b/guarddog_nexus/web/templates/scan_detail.html @@ -1,36 +1,36 @@ {% extends "base.html" %} -{% block title %}Scan #{{ scan.id }} — GuardDog Nexus{% endblock %} +{% block title %}{{ t('title_scan_detail', request.state.lang, scan.id) }}{% endblock %} {% block breadcrumbs %} {% endblock %} {% block content %} -

Scan #{{ scan.id }}

+

{{ t('scan_detail_title', request.state.lang, scan.id) }}

-
Package
{{ scan.package_name }}
-
Version
{{ scan.package_version }}
-
Ecosystem
{{ scan.ecosystem }}
-
Repository
{{ scan.repository }}
-
Status
+
{{ t('scan_info_package', request.state.lang) }}
{{ scan.package_name }}
+
{{ t('scan_info_version', request.state.lang) }}
{{ scan.package_version }}
+
{{ t('scan_info_ecosystem', request.state.lang) }}
{{ scan.ecosystem }}
+
{{ t('scan_info_repository', request.state.lang) }}
{{ scan.repository }}
+
{{ t('scan_info_status', request.state.lang) }}
{% if scan.status == 'scanning' %}scanning{% else %}{{ scan.status }}{% endif %}
-
SHA256
{{ scan.sha256 or '-' }}
-
Started
{{ scan.started_at.strftime('%Y-%m-%d %H:%M') if scan.started_at }}
-
Finished
{{ scan.finished_at.strftime('%Y-%m-%d %H:%M') if scan.finished_at }}
- {% if scan.initiator %}
Initiated by
{{ scan.initiator }}
{% endif %} - {% if scan.source_ip %}
Source IP
{{ scan.source_ip }}
{% endif %} +
{{ t('scan_info_sha256', request.state.lang) }}
{{ scan.sha256 or '-' }}
+
{{ t('scan_info_started', request.state.lang) }}
{{ scan.started_at.strftime('%Y-%m-%d %H:%M') if scan.started_at }}
+
{{ t('scan_info_finished', request.state.lang) }}
{{ scan.finished_at.strftime('%Y-%m-%d %H:%M') if scan.finished_at }}
+ {% if scan.initiator %}
{{ t('scan_info_initiated', request.state.lang) }}
{{ scan.initiator }}
{% endif %} + {% if scan.source_ip %}
{{ t('scan_info_source_ip', request.state.lang) }}
{{ scan.source_ip }}
{% endif %}
- {% if scan.error_message %}
Error: {{ scan.error_message }}
{% endif %} + {% if scan.error_message %}
{{ t('scan_info_error', request.state.lang) }}: {{ scan.error_message }}
{% endif %}
-

Findings ({{ scan.findings|length }})

+

{{ t('heading_findings_count', request.state.lang, scan.findings|length) }}

{% if scan.findings %}
@@ -45,7 +45,7 @@

{{ f.data.message }}

{% if f.data.code %}
- +
{{ f.data.code }}
{% endif %} @@ -60,7 +60,7 @@

{{ f.report.summary }}

{{ f.report.analysis }}

-

⚠ AI-generated analysis — may contain inaccuracies.

+

{{ t('llm_disclaimer', request.state.lang) }}

{% else %}
@@ -72,7 +72,7 @@ - Analyze with LLM + {{ t('btn_analyze_llm', request.state.lang) }}
{% endif %} @@ -81,6 +81,6 @@ {% endfor %} {% else %} -

No findings — package looks clean.

+

{{ t('empty_no_findings', request.state.lang) }}

{% endif %} {% endblock %} diff --git a/guarddog_nexus/web/templates/scans_list.html b/guarddog_nexus/web/templates/scans_list.html index 30ddb8d..f1bb38d 100644 --- a/guarddog_nexus/web/templates/scans_list.html +++ b/guarddog_nexus/web/templates/scans_list.html @@ -1,28 +1,28 @@ {% extends "base.html" %} -{% block title %}Scans — GuardDog Nexus{% endblock %} +{% block title %}{{ t('title_scans', request.state.lang) }}{% endblock %} {% block breadcrumbs %} {% endblock %} {% block content %} -

Scans

+

{{ t('heading_scans', request.state.lang) }}

- + - {% if flagged_filter == '1' %}Show all{% else %}Flagged only{% endif %} + {% if flagged_filter == '1' %}{{ t('btn_show_all', request.state.lang) }}{% else %}{{ t('btn_flagged_only', request.state.lang) }}{% endif %} - Export CSV + {{ t('btn_export_csv', request.state.lang) }}