diff --git a/docs/i18n/ADMIN_METRIC_FORMATTING.md b/docs/i18n/ADMIN_METRIC_FORMATTING.md new file mode 100644 index 00000000..aaf69f69 --- /dev/null +++ b/docs/i18n/ADMIN_METRIC_FORMATTING.md @@ -0,0 +1,7 @@ +# Admin System metric formatting + +Bounded I18N-02 display fix on `codex/i18n-admin-metrics`, based on the isolated salary checkpoint `af33e45542aea1e18088c44308161284fdca47a7`. The same unlocalised storage-size and benchmark-percentage formatting was present at A3 `49e79875`. + +Database storage sizes and CV benchmark summary and entry percentages now format using the current English or Bokmål UI locale. Storage retains the existing B/KB/MB boundaries and one fractional digit for KB and MB. Percentages use locale-specific spacing and whole-number precision. Input metrics, missing-value fallbacks, threshold colours and diagnostic operation paths remain intact. + +The existing mounted Bokmål diagnostic test reproduced the missing `2,0 KB` display before the fix and now checks that display and the localised `72 %` benchmark result. `npm test -- --runInBand --runTestsByPath src/admin-system-page.test.tsx src/translation-catalogue.test.ts` passed 23 tests across two suites. Full frontend typecheck, scoped ESLint with zero warnings and the Next static export passed. No browser/device or native-language review and no actual diagnostic or benchmark execution. diff --git a/docs/i18n/CURRENT_STATUS.md b/docs/i18n/CURRENT_STATUS.md index b8130368..cc13e9ae 100644 --- a/docs/i18n/CURRENT_STATUS.md +++ b/docs/i18n/CURRENT_STATUS.md @@ -1,5 +1,7 @@ # Current localisation continuation +Admin System database sizes and CV benchmark percentages now follow the EN/NB UI locale on the isolated admin-metrics branch. See [implementation and validation](ADMIN_METRIC_FORMATTING.md). + Mobile application cards now use the selected EN/NB locale and existing salary-period labels on the isolated mobile-salary branch. See [the bounded implementation and validation](MOBILE_SALARY_FORMATTING.md). Full I18N-02 surface coverage and European locale acceptance remain open. 3 November 2026 — independent document-date fix: invalid uploaded wall-clock dates/times/trailing junk now show the existing EN/NB unknown-date message instead of JavaScript rollover.40 tests/3 suites, typecheck, scoped lint and build pass; see DOCUMENT_DATE_VALIDATION.md. All four historical direct-catalogue accesses have contextual dispositions in DIRECT_CATALOGUE_REVIEW.md; current full extraction/backend literals/every-string triage remain open. No new locales or release approval. This branch is not yet integrated into A3 dashboard/application work. diff --git a/job-tracker-ui/src/admin-system-page.test.tsx b/job-tracker-ui/src/admin-system-page.test.tsx index 77eab3d3..fec9439f 100644 --- a/job-tracker-ui/src/admin-system-page.test.tsx +++ b/job-tracker-ui/src/admin-system-page.test.tsx @@ -472,6 +472,8 @@ describe('AdminSystemPage', () => { expect(await screen.findByText(/Mistenkelig kontaktsted: san francisco, hobbies/i)).toBeTruthy(); expect(screen.getByText('Production')).toBeTruthy(); expect(screen.getByText(/Modell · qwen2.5:7b/i)).toBeTruthy(); + expect(screen.getByText(/2,0 KB/)).toBeVisible(); + expect(screen.getByText('72 %')).toBeVisible(); fireEvent.click(screen.getByRole('tab', { name: /innstillinger/i })); expect(await screen.findByDisplayValue('Dette er en test-e-post fra systempanelet i Jobbjakt.')).toBeTruthy(); }); diff --git a/job-tracker-ui/src/views/AdminSystemPage.tsx b/job-tracker-ui/src/views/AdminSystemPage.tsx index c4b6c8c7..fe646641 100644 --- a/job-tracker-ui/src/views/AdminSystemPage.tsx +++ b/job-tracker-ui/src/views/AdminSystemPage.tsx @@ -167,11 +167,12 @@ type SystemStatus = { ai: AiServiceMetrics; }; -function formatBytes(bytes?: number | null) { +function formatBytes(bytes: number | null | undefined, locale: string) { if (bytes == null) return "-"; - if (bytes < 1024) return `${bytes} B`; - if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; - return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; + if (bytes < 1024) return `${bytes.toLocaleString(locale)} B`; + const options = { minimumFractionDigits: 1, maximumFractionDigits: 1 }; + if (bytes < 1024 * 1024) return `${(bytes / 1024).toLocaleString(locale, options)} KB`; + return `${(bytes / (1024 * 1024)).toLocaleString(locale, options)} MB`; } function displayMetadata(value?: string | null) { @@ -182,8 +183,8 @@ function formatDate(value?: string | null, locale?: string) { return value ? new Date(value).toLocaleString(locale) : "-"; } -function formatPercent(value?: number | null) { - return typeof value === "number" ? `${Math.round(value * 100)}%` : "-"; +function formatPercent(value: number | null | undefined, locale: string) { + return typeof value === "number" ? value.toLocaleString(locale, { style: "percent", maximumFractionDigits: 0 }) : "-"; } function parseBenchmarkIndex(indexJson?: string | null): CvBenchmarkIndex | null { @@ -225,6 +226,7 @@ const actionErrorKeys: Record = { save: "adminSystem export default function AdminSystemPage() { const { language, t } = useI18n(); + const locale = language === "nb" ? "nb-NO" : "en"; const [tab, setTab] = useState(0); const [status, setStatus] = useState(null); const [emailSettings, setEmailSettings] = useState(null); @@ -495,7 +497,7 @@ export default function AdminSystemPage() { - + @@ -612,9 +614,9 @@ export default function AdminSystemPage() { <> - - - + + + 0 ? "warning" : "success"} /> @@ -638,9 +640,9 @@ export default function AdminSystemPage() { {entry.FileName} - - - + + + {entry.DiffSummary || "-"}