From c1bc76111f35ea96a6af357845919b7fe0a8d2b9 Mon Sep 17 00:00:00 2001 From: Marcel Date: Sat, 13 Jun 2026 11:14:02 +0200 Subject: [PATCH] feat(timeline): map new ErrorCodes to localized messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit errors.ts ErrorCode union + getErrorMessage() cases for the four new codes, with de/en/es i18n keys. Conflict messages are calm/recoverable ('...wurde zwischenzeitlich geändert. Bitte neu laden.'). Per #775. Co-Authored-By: Claude Fable 5 --- frontend/messages/de.json | 4 ++++ frontend/messages/en.json | 4 ++++ frontend/messages/es.json | 4 ++++ frontend/src/lib/shared/errors.ts | 12 ++++++++++++ 4 files changed, 24 insertions(+) diff --git a/frontend/messages/de.json b/frontend/messages/de.json index 6fae284d..c306a1a3 100644 --- a/frontend/messages/de.json +++ b/frontend/messages/de.json @@ -1237,6 +1237,10 @@ "error_journey_note_too_long": "Die Notiz ist zu lang (maximal 2000 Zeichen).", "error_geschichte_title_too_long": "Der Titel ist zu lang (maximal 255 Zeichen).", "error_geschichte_intro_too_long": "Die Einleitung ist zu lang (maximal 4000 Zeichen).", + "error_timeline_event_not_found": "Zeitleistenereignis nicht gefunden.", + "error_timeline_event_conflict": "Dieses Ereignis wurde zwischenzeitlich geändert. Bitte neu laden.", + "error_timeline_title_too_long": "Der Titel ist zu lang (maximal 255 Zeichen).", + "error_conflict": "Der Datensatz wurde zwischenzeitlich geändert. Bitte neu laden.", "person_unknown": "[Unbekannt]", "error_journey_document_already_added": "Dieser Brief ist bereits in der Lesereise enthalten.", "error_geschichte_type_immutable": "Der Typ einer Geschichte kann nach der Erstellung nicht mehr geändert werden." diff --git a/frontend/messages/en.json b/frontend/messages/en.json index 0c51cafe..9f3bb8e0 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -1237,6 +1237,10 @@ "error_journey_note_too_long": "The note is too long (maximum 2000 characters).", "error_geschichte_title_too_long": "The title is too long (maximum 255 characters).", "error_geschichte_intro_too_long": "The introduction is too long (maximum 4000 characters).", + "error_timeline_event_not_found": "Timeline event not found.", + "error_timeline_event_conflict": "This event was changed in the meantime. Please reload.", + "error_timeline_title_too_long": "The title is too long (maximum 255 characters).", + "error_conflict": "The record was changed in the meantime. Please reload.", "person_unknown": "[Unknown]", "error_journey_document_already_added": "This letter is already included in the reading journey.", "error_geschichte_type_immutable": "The type of a story cannot be changed after creation." diff --git a/frontend/messages/es.json b/frontend/messages/es.json index d1695d15..d4d8544d 100644 --- a/frontend/messages/es.json +++ b/frontend/messages/es.json @@ -1237,6 +1237,10 @@ "error_journey_note_too_long": "La nota es demasiado larga (máximo 2000 caracteres).", "error_geschichte_title_too_long": "El título es demasiado largo (máximo 255 caracteres).", "error_geschichte_intro_too_long": "La introducción es demasiado larga (máximo 4000 caracteres).", + "error_timeline_event_not_found": "Evento de la línea de tiempo no encontrado.", + "error_timeline_event_conflict": "Este evento se modificó mientras tanto. Vuelve a cargar.", + "error_timeline_title_too_long": "El título es demasiado largo (máximo 255 caracteres).", + "error_conflict": "El registro se modificó mientras tanto. Vuelve a cargar.", "person_unknown": "[Desconocido]", "error_journey_document_already_added": "Esta carta ya está incluida en el viaje de lectura.", "error_geschichte_type_immutable": "El tipo de una historia no se puede cambiar después de su creación." diff --git a/frontend/src/lib/shared/errors.ts b/frontend/src/lib/shared/errors.ts index 344fc08c..9bd6fd66 100644 --- a/frontend/src/lib/shared/errors.ts +++ b/frontend/src/lib/shared/errors.ts @@ -56,6 +56,9 @@ export type ErrorCode = | 'GESCHICHTE_TYPE_IMMUTABLE' | 'GESCHICHTE_TITLE_TOO_LONG' | 'GESCHICHTE_INTRO_TOO_LONG' + | 'TIMELINE_EVENT_NOT_FOUND' + | 'TIMELINE_EVENT_CONFLICT' + | 'TIMELINE_TITLE_TOO_LONG' | 'INVALID_CREDENTIALS' | 'SESSION_EXPIRED' | 'MISSING_CREDENTIALS' @@ -66,6 +69,7 @@ export type ErrorCode = | 'VALIDATION_ERROR' | 'BATCH_TOO_LARGE' | 'BULK_EDIT_TOO_MANY_IDS' + | 'CONFLICT' | 'INTERNAL_ERROR'; export interface BackendError { @@ -194,6 +198,12 @@ export function getErrorMessage(code: ErrorCode | string | undefined): string { return m.error_geschichte_title_too_long(); case 'GESCHICHTE_INTRO_TOO_LONG': return m.error_geschichte_intro_too_long(); + case 'TIMELINE_EVENT_NOT_FOUND': + return m.error_timeline_event_not_found(); + case 'TIMELINE_EVENT_CONFLICT': + return m.error_timeline_event_conflict(); + case 'TIMELINE_TITLE_TOO_LONG': + return m.error_timeline_title_too_long(); case 'INVALID_CREDENTIALS': return m.error_invalid_credentials(); case 'SESSION_EXPIRED': @@ -214,6 +224,8 @@ export function getErrorMessage(code: ErrorCode | string | undefined): string { return m.error_batch_too_large(); case 'BULK_EDIT_TOO_MANY_IDS': return m.error_bulk_edit_too_many_ids(); + case 'CONFLICT': + return m.error_conflict(); default: return m.error_internal_error(); }