From a00617194c2a55edbc740c6443f161d34737e957 Mon Sep 17 00:00:00 2001 From: Marcel Date: Sat, 18 Apr 2026 08:59:49 +0200 Subject: [PATCH] fix(admin): i18n all hardcoded OCR strings, fix personName lookup, add empty state - Replace hardcoded EN strings in OcrHealthBar/OcrStatCards/OcrModelsTable with Paraglide message keys (de/en/es translations added) - Add role=img + aria-label to OcrHealthBar status dot - Add {:else} empty-state row in OcrModelsTable - Fix personName derivation in [personId]/+page.svelte to use params.personId key instead of Object.values()[0] (fragile when multiple persons present) - Update OcrModelsTable spec to assert empty-state row structure (locale-agnostic) - Add missing availableSegBlocks test to OcrStatCards spec Co-Authored-By: Claude Sonnet 4.6 --- frontend/messages/de.json | 16 ++++++++++++++++ frontend/messages/en.json | 16 ++++++++++++++++ frontend/messages/es.json | 16 ++++++++++++++++ frontend/src/routes/admin/ocr/+page.svelte | 11 ++++++++--- .../src/routes/admin/ocr/OcrHealthBar.svelte | 5 ++++- .../routes/admin/ocr/OcrModelsTable.svelte | 19 +++++++++++++------ .../admin/ocr/OcrModelsTable.svelte.spec.ts | 5 +++-- .../src/routes/admin/ocr/OcrStatCards.svelte | 16 ++++++++++++---- .../admin/ocr/OcrStatCards.svelte.spec.ts | 5 +++++ .../routes/admin/ocr/[personId]/+page.svelte | 7 ++++--- .../src/routes/admin/ocr/global/+page.svelte | 5 +++-- 11 files changed, 100 insertions(+), 21 deletions(-) diff --git a/frontend/messages/de.json b/frontend/messages/de.json index ed968638..ddceced2 100644 --- a/frontend/messages/de.json +++ b/frontend/messages/de.json @@ -300,6 +300,22 @@ "history_field_tags": "Schlagworte", "admin_tab_system": "System", "admin_tab_ocr": "OCR", + "ocr_status_online": "Online", + "ocr_status_offline": "Offline", + "ocr_stat_training_blocks": "Trainingsblöcke", + "ocr_stat_total_blocks": "Gesamt Blöcke", + "ocr_stat_documents": "Dokumente", + "ocr_stat_seg_blocks": "Seg.-Blöcke", + "ocr_table_person": "Person", + "ocr_table_cer": "ZFR", + "ocr_table_accuracy": "Genauigkeit", + "ocr_table_lines": "Zeilen", + "ocr_table_actions": "Aktionen", + "ocr_table_details": "Details", + "ocr_no_models": "Noch keine Sender-Modelle trainiert.", + "ocr_sender_models_heading": "Sender-Modelle", + "ocr_global_history_link": "Globaler Verlauf →", + "ocr_global_history_heading": "Globaler Verlauf", "admin_system_backfill_heading": "Verlaufsdaten auffüllen", "admin_system_backfill_description": "Erstellt einen initialen Verlaufseintrag für alle Dokumente, die noch keinen Verlauf haben (z.B. importierte Dokumente). Dadurch werden beim nächsten Bearbeiten nur die tatsächlich geänderten Felder hervorgehoben.", "admin_system_backfill_btn": "Jetzt auffüllen", diff --git a/frontend/messages/en.json b/frontend/messages/en.json index 16c10e93..005cad89 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -300,6 +300,22 @@ "history_field_tags": "Tags", "admin_tab_system": "System", "admin_tab_ocr": "OCR", + "ocr_status_online": "Online", + "ocr_status_offline": "Offline", + "ocr_stat_training_blocks": "Training blocks", + "ocr_stat_total_blocks": "Total blocks", + "ocr_stat_documents": "Documents", + "ocr_stat_seg_blocks": "Seg. blocks", + "ocr_table_person": "Person", + "ocr_table_cer": "CER", + "ocr_table_accuracy": "Accuracy", + "ocr_table_lines": "Lines", + "ocr_table_actions": "Actions", + "ocr_table_details": "Details", + "ocr_no_models": "No sender models trained yet.", + "ocr_sender_models_heading": "Sender Models", + "ocr_global_history_link": "Global history →", + "ocr_global_history_heading": "Global History", "admin_system_backfill_heading": "Backfill history data", "admin_system_backfill_description": "Creates an initial history entry for all documents that do not have one yet (e.g. imported documents). This ensures that future edits only highlight actually changed fields.", "admin_system_backfill_btn": "Backfill now", diff --git a/frontend/messages/es.json b/frontend/messages/es.json index b9fa125a..9675673e 100644 --- a/frontend/messages/es.json +++ b/frontend/messages/es.json @@ -300,6 +300,22 @@ "history_field_tags": "Etiquetas", "admin_tab_system": "Sistema", "admin_tab_ocr": "OCR", + "ocr_status_online": "En línea", + "ocr_status_offline": "Sin conexión", + "ocr_stat_training_blocks": "Bloques de entrenamiento", + "ocr_stat_total_blocks": "Total de bloques", + "ocr_stat_documents": "Documentos", + "ocr_stat_seg_blocks": "Bloques de seg.", + "ocr_table_person": "Persona", + "ocr_table_cer": "TCE", + "ocr_table_accuracy": "Precisión", + "ocr_table_lines": "Líneas", + "ocr_table_actions": "Acciones", + "ocr_table_details": "Detalles", + "ocr_no_models": "Aún no hay modelos de remitente entrenados.", + "ocr_sender_models_heading": "Modelos de remitente", + "ocr_global_history_link": "Historial global →", + "ocr_global_history_heading": "Historial global", "admin_system_backfill_heading": "Completar datos de historial", "admin_system_backfill_description": "Crea una entrada de historial inicial para todos los documentos que aún no tienen ninguna (p.ej. documentos importados). Así, en la próxima edición solo se resaltarán los campos realmente modificados.", "admin_system_backfill_btn": "Completar ahora", diff --git a/frontend/src/routes/admin/ocr/+page.svelte b/frontend/src/routes/admin/ocr/+page.svelte index cc063db2..a068f01f 100644 --- a/frontend/src/routes/admin/ocr/+page.svelte +++ b/frontend/src/routes/admin/ocr/+page.svelte @@ -3,6 +3,7 @@ import type { PageData } from './$types'; import OcrHealthBar from './OcrHealthBar.svelte'; import OcrStatCards from './OcrStatCards.svelte'; import OcrModelsTable from './OcrModelsTable.svelte'; +import * as m from '$lib/paraglide/messages.js'; let { data }: { data: PageData } = $props(); const { trainingInfo } = $derived(data); @@ -11,7 +12,9 @@ const { trainingInfo } = $derived(data);
-

OCR

+

+ {m.admin_tab_ocr()} +

@@ -26,12 +29,14 @@ const { trainingInfo } = $derived(data);
-

Sender Models

+

+ {m.ocr_sender_models_heading()} +

- Global history → + {m.ocr_global_history_link()}
+import * as m from '$lib/paraglide/messages.js'; let { ocrServiceAvailable }: { ocrServiceAvailable: boolean } = $props();
- {ocrServiceAvailable ? 'Online' : 'Offline'} + {ocrServiceAvailable ? m.ocr_status_online() : m.ocr_status_offline()}
diff --git a/frontend/src/routes/admin/ocr/OcrModelsTable.svelte b/frontend/src/routes/admin/ocr/OcrModelsTable.svelte index 785c96b0..da14705f 100644 --- a/frontend/src/routes/admin/ocr/OcrModelsTable.svelte +++ b/frontend/src/routes/admin/ocr/OcrModelsTable.svelte @@ -1,5 +1,6 @@
@@ -20,7 +21,7 @@ const personName = $derived(Object.values(data.history.personNames ?? {})[0] ?? stroke-width="2" > - OCR + {m.admin_tab_ocr()}

{personName} diff --git a/frontend/src/routes/admin/ocr/global/+page.svelte b/frontend/src/routes/admin/ocr/global/+page.svelte index 1f2c9b22..fa22fe53 100644 --- a/frontend/src/routes/admin/ocr/global/+page.svelte +++ b/frontend/src/routes/admin/ocr/global/+page.svelte @@ -1,6 +1,7 @@ @@ -19,10 +20,10 @@ let { data }: { data: PageData } = $props(); stroke-width="2" > - OCR + {m.admin_tab_ocr()}

- Global History + {m.ocr_global_history_heading()}