diff --git a/AppImage/components/health-status-modal.tsx b/AppImage/components/health-status-modal.tsx index f986e903..3b27172c 100644 --- a/AppImage/components/health-status-modal.tsx +++ b/AppImage/components/health-status-modal.tsx @@ -340,6 +340,10 @@ export function HealthStatusModal({ open, onOpenChange, getApiUrl }: HealthStatu const translateHealthText = (value?: string): string => { if (!value) return "" + // Health summaries include the category before the same detail text. + if (value.startsWith("Updates: ")) { + return `${t("healthStatus.categories.updates")}: ${translateHealthText(value.slice(9))}` + } const exact: Record = { "No temperature sensor detected - install lm-sensors if hardware supports it": t("healthStatus.details.noTemperatureSensor"), "Sustained high CPU usage": t("healthStatus.details.cpuHighSustained"), @@ -903,9 +907,13 @@ export function HealthStatusModal({ open, onOpenChange, getApiUrl }: HealthStatu pending prevents the operator from spawning a terminal that would only report "System is already up to date". */} - {key === "updates" && } {key === "updates" && Number(categoryData?.count ?? 0) > 0 && ( -
+

+ {t("healthStatus.packagePlanNote")} +

+ )} + {key === "updates" && Number(categoryData?.count ?? 0) > 0 && ( +
)} + {key === "updates" && }
)} diff --git a/AppImage/messages/en/common.json b/AppImage/messages/en/common.json index d2507a10..f35857dc 100644 --- a/AppImage/messages/en/common.json +++ b/AppImage/messages/en/common.json @@ -5470,7 +5470,7 @@ "failedLogins": "{count} failed login attempts in 24h", "fail2banBannedIps": "Fail2Ban is currently blocking {count} IP addresses (jails: {jails})", "uptimeDays": "Uptime: {count} days", - "pendingPackages": "{count} packages pending", + "pendingPackages": "Planned packages: {count} (including new packages)", "updatedDaysAgo": "Last updated {count} days ago", "startupStoragesChecking": "Checking Proxmox storage after startup: {storages}", "startupStorageChecking": "Checking Proxmox storage after startup: {storage}", @@ -5498,6 +5498,8 @@ }, "noIssues": "No issues detected", "updateNow": "Update now", + "updateSystem": "Update system", + "packagePlanNote": "The plan also includes new packages, such as a new kernel. The overview counts updates to existing packages only.", "dismissedItems": "Dismissed items ({count})", "permanent": "Permanent", "dismissed": "Dismissed", diff --git a/AppImage/messages/sk/common.json b/AppImage/messages/sk/common.json index 3e522ea1..84bfb9bc 100644 --- a/AppImage/messages/sk/common.json +++ b/AppImage/messages/sk/common.json @@ -5303,7 +5303,7 @@ "failedLogins": "Neúspešné prihlásenia za 24 h: {count}", "fail2banBannedIps": "Fail2Ban momentálne blokuje IP adresy: {count} (pravidlá: {jails})", "uptimeDays": "Beží {count} dní", - "pendingPackages": "Čakajúce balíky: {count}", + "pendingPackages": "Plánované balíky: {count} (vrátane nových)", "updatedDaysAgo": "Naposledy aktualizované pred {count} dňami", "startupStoragesChecking": "Po štarte sa ešte overuje stav Proxmox úložísk: {storages}", "startupStorageChecking": "Po štarte sa ešte overuje stav Proxmox úložiska: {storage}", @@ -5334,7 +5334,7 @@ "pendingSecurityUpdatesDays": "Čakajúce aktualizácie zabezpečenia: {count} (dni čakania: {days})", "systemNotUpdatedMonths": "Systém nebol aktualizovaný za {days} dní (>18 mesiacov)", "systemNotUpdatedYear": "Systém nebol aktualizovaný za {days} dní (>1 rok)", - "runningKernelUpdate": "K dispozícii je aktualizácia jadra pre spustenie {kernel}", + "runningKernelUpdate": "K dispozícii je aktualizácia pre bežiace jadro {kernel}", "kernelPveUpdates": "Dostupné aktualizácie jadra: {kernelCount}; dostupné aktualizácie Proxmox: {pveCount}", "pendingPackageUpdates": "Čakajúce aktualizácie balíka: {count}", "noPendingUpdates": "Žiadne čakajúce aktualizácie", @@ -5370,6 +5370,8 @@ }, "noIssues": "Neboli zistené žiadne problémy", "updateNow": "Aktualizovať teraz", + "updateSystem": "Aktualizovať systém", + "packagePlanNote": "Plán zahŕňa aj nové balíky, napríklad nové jadro. Prehľad počíta iba aktualizácie existujúcich balíkov.", "dismissedItems": "Skryté upozornenia ({count})", "permanent": "Natrvalo", "dismissed": "Skryté", diff --git a/tests/test_health_text.cjs b/tests/test_health_text.cjs index 2ffee6ff..34bf9d81 100644 --- a/tests/test_health_text.cjs +++ b/tests/test_health_text.cjs @@ -261,5 +261,16 @@ for (const input of passthrough) { check(`passthrough ${JSON.stringify(input)}`, () => assert.equal(select(input), input)); for (const locale of Object.keys(catalogs)) check(`passthrough ${locale} ${JSON.stringify(input)}`, () => assert.equal(render(input, locale), input)); } +// Real summary contract from health_monitor: category prefix + reason. +for (const [locale, expectedText] of [ + ['sk', 'Aktualizácie systému: K dispozícii je aktualizácia pre bežiace jadro 7.0.14-25-pve'], + ['en', 'System updates: Kernel update available for running 7.0.14-25-pve'], +]) { + check(`prefixed update summary ${locale}`, () => assert.equal( + render('Updates: Kernel update available for running 7.0.14-25-pve', locale), expectedText)); + const opaque = 'Repository unavailable; diagnostic: /srv/path {count}\nline 2'; + check(`prefixed diagnostic preserved ${locale}`, () => assert.equal( + render('Updates: ' + opaque, locale), translator(locale)('healthStatus.categories.updates') + ': ' + opaque)); +} if (failures) throw new Error(`${failures} health-text assertions failed`); console.log(`PASS: actual health mapper/provider; ${new Set(cases.map(row => row[1])).size} new keys, ${cases.length} message variants, ${Object.keys(catalogs).length} shipped locales and unconditional missing-key fallback`);