diff --git a/frontend/messages/de.json b/frontend/messages/de.json index f4e6da8c..8522580c 100644 --- a/frontend/messages/de.json +++ b/frontend/messages/de.json @@ -540,6 +540,8 @@ "person_alias_btn_delete": "Entfernen", "error_alias_not_found": "Der Namensalias wurde nicht gefunden.", "error_invalid_person_type": "Der angegebene Personentyp ist ungültig.", + "validation_last_name_required": "Nachname ist Pflichtfeld.", + "validation_first_name_required": "Vorname ist Pflichtfeld.", "error_ocr_service_unavailable": "Der OCR-Dienst ist nicht verfügbar.", "error_ocr_job_not_found": "Der OCR-Auftrag wurde nicht gefunden.", "error_ocr_document_not_uploaded": "Das Dokument hat keine Datei — OCR ist nicht möglich.", diff --git a/frontend/messages/en.json b/frontend/messages/en.json index c3202419..cddafac1 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -540,6 +540,8 @@ "person_alias_btn_delete": "Remove", "error_alias_not_found": "The name alias was not found.", "error_invalid_person_type": "The specified person type is not valid.", + "validation_last_name_required": "Last name is required.", + "validation_first_name_required": "First name is required.", "error_ocr_service_unavailable": "The OCR service is not available.", "error_ocr_job_not_found": "The OCR job was not found.", "error_ocr_document_not_uploaded": "The document has no file — OCR is not possible.", diff --git a/frontend/messages/es.json b/frontend/messages/es.json index 644debef..f5125884 100644 --- a/frontend/messages/es.json +++ b/frontend/messages/es.json @@ -540,6 +540,8 @@ "person_alias_btn_delete": "Eliminar", "error_alias_not_found": "No se encontro el alias de nombre.", "error_invalid_person_type": "El tipo de persona especificado no es válido.", + "validation_last_name_required": "El apellido es obligatorio.", + "validation_first_name_required": "El nombre es obligatorio.", "error_ocr_service_unavailable": "El servicio OCR no está disponible.", "error_ocr_job_not_found": "No se encontró el trabajo OCR.", "error_ocr_document_not_uploaded": "El documento no tiene archivo — OCR no es posible.", diff --git a/frontend/src/lib/person-validation.test.ts b/frontend/src/lib/person-validation.test.ts index a3dc5343..d9f6ed58 100644 --- a/frontend/src/lib/person-validation.test.ts +++ b/frontend/src/lib/person-validation.test.ts @@ -6,22 +6,24 @@ describe('validatePersonFields', () => { expect(validatePersonFields('PERSON', 'Hans', 'Müller')).toBeNull(); }); - it('returns lastName error when lastName is missing', () => { - expect(validatePersonFields('PERSON', 'Hans', '')).toBe('Nachname ist Pflichtfeld.'); + it('returns lastName error key when lastName is missing', () => { + expect(validatePersonFields('PERSON', 'Hans', '')).toBe('validation_last_name_required'); }); - it('returns lastName error when lastName is undefined', () => { + it('returns lastName error key when lastName is undefined', () => { expect(validatePersonFields('INSTITUTION', undefined, undefined)).toBe( - 'Nachname ist Pflichtfeld.' + 'validation_last_name_required' ); }); - it('returns firstName error when type is PERSON and firstName is missing', () => { - expect(validatePersonFields('PERSON', '', 'Müller')).toBe('Vorname ist Pflichtfeld.'); + it('returns firstName error key when type is PERSON and firstName is missing', () => { + expect(validatePersonFields('PERSON', '', 'Müller')).toBe('validation_first_name_required'); }); - it('returns firstName error when type is PERSON and firstName is undefined', () => { - expect(validatePersonFields('PERSON', undefined, 'Müller')).toBe('Vorname ist Pflichtfeld.'); + it('returns firstName error key when type is PERSON and firstName is undefined', () => { + expect(validatePersonFields('PERSON', undefined, 'Müller')).toBe( + 'validation_first_name_required' + ); }); it('returns null for INSTITUTION without firstName', () => { diff --git a/frontend/src/lib/person-validation.ts b/frontend/src/lib/person-validation.ts index 72916502..1e2b3ccf 100644 --- a/frontend/src/lib/person-validation.ts +++ b/frontend/src/lib/person-validation.ts @@ -1,3 +1,5 @@ +import { m } from '$lib/paraglide/messages.js'; + export const PERSON_TYPES = ['PERSON', 'INSTITUTION', 'GROUP', 'UNKNOWN'] as const; export type PersonType = (typeof PERSON_TYPES)[number]; @@ -5,12 +7,22 @@ export function normalizePersonType(raw: string | undefined | null): PersonType return raw === 'SKIP' ? 'UNKNOWN' : ((raw ?? 'PERSON') as PersonType); } +export type PersonValidationKey = + | 'validation_last_name_required' + | 'validation_first_name_required'; + +export function resolveValidationMessage(key: PersonValidationKey): string { + return key === 'validation_last_name_required' + ? m.validation_last_name_required() + : m.validation_first_name_required(); +} + export function validatePersonFields( personType: string, firstName: string | undefined | null, lastName: string | undefined | null -): string | null { - if (!lastName) return 'Nachname ist Pflichtfeld.'; - if (personType === 'PERSON' && !firstName) return 'Vorname ist Pflichtfeld.'; +): PersonValidationKey | null { + if (!lastName) return 'validation_last_name_required'; + if (personType === 'PERSON' && !firstName) return 'validation_first_name_required'; return null; } diff --git a/frontend/src/routes/persons/[id]/edit/+page.server.ts b/frontend/src/routes/persons/[id]/edit/+page.server.ts index 0d4d988c..c3901f8f 100644 --- a/frontend/src/routes/persons/[id]/edit/+page.server.ts +++ b/frontend/src/routes/persons/[id]/edit/+page.server.ts @@ -1,7 +1,11 @@ import { error, fail, redirect } from '@sveltejs/kit'; import { createApiClient } from '$lib/api.server'; import { getErrorMessage } from '$lib/errors'; -import { normalizePersonType, validatePersonFields } from '$lib/person-validation'; +import { + normalizePersonType, + validatePersonFields, + resolveValidationMessage +} from '$lib/person-validation'; export async function load({ params, fetch, locals }) { const canWrite = @@ -42,9 +46,9 @@ export const actions = { const birthYear = birthYearStr ? parseInt(birthYearStr, 10) : undefined; const deathYear = deathYearStr ? parseInt(deathYearStr, 10) : undefined; - const validationError = validatePersonFields(personType, firstName, lastName); - if (validationError) { - return fail(400, { updateError: validationError }); + const validationKey = validatePersonFields(personType, firstName, lastName); + if (validationKey) { + return fail(400, { updateError: resolveValidationMessage(validationKey) }); } const api = createApiClient(fetch); diff --git a/frontend/src/routes/persons/new/+page.server.ts b/frontend/src/routes/persons/new/+page.server.ts index 4cde5cb8..73d6cc8e 100644 --- a/frontend/src/routes/persons/new/+page.server.ts +++ b/frontend/src/routes/persons/new/+page.server.ts @@ -1,7 +1,11 @@ import { error, fail, redirect } from '@sveltejs/kit'; import { createApiClient } from '$lib/api.server'; import { getErrorMessage } from '$lib/errors'; -import { normalizePersonType, validatePersonFields } from '$lib/person-validation'; +import { + normalizePersonType, + validatePersonFields, + resolveValidationMessage +} from '$lib/person-validation'; export async function load({ locals }: { locals: App.Locals }) { const canWrite = @@ -23,10 +27,10 @@ export const actions = { const deathYearStr = formData.get('deathYear')?.toString().trim(); const notes = formData.get('notes')?.toString().trim() || undefined; - const validationError = validatePersonFields(personType, firstName, lastName); - if (validationError) { + const validationKey = validatePersonFields(personType, firstName, lastName); + if (validationKey) { return fail(400, { - error: validationError, + error: resolveValidationMessage(validationKey), personType, title, firstName: firstName ?? '',