Files
MobilityOps/frontend/src/i18n/locales/fr-BE/errors.json
T
NuklearRabbit d17af1c52a feat: centralize API error localization
Replace the err instanceof ApiError ? err.message : t(fallback) anti-
pattern -- which showed raw English backend text for the common case and
only used the localized fallback for the rare network-failure case -- at
all 13 call sites across 7 files.

New frontend/src/api/errorMessages.ts (describeApiError) resolves a
caught error to a localized {title, explanation, nextStep?, technical}
by checking the 32 known AppError codes first, then known HTTP statuses
(401/403/404/409/422/500), then a fully generic fallback. New
ApiErrorNotice (PageChrome.tsx) renders title/explanation/nextStep with
the raw text demoted to a "Technical details"/"Details techniques"
disclosure -- never shown as the primary message.

ApiError itself is split out of client.ts into a standalone
api/apiError.ts with no import.meta.env dependency, so errorMessages.ts
(and its tests) can be loaded outside a Vite/browser context.
2026-08-04 03:08:07 +02:00

181 lines
7.6 KiB
JSON

{
"generic": {
"title": "Une erreur s'est produite",
"explanation": "Cette action n'a pas pu être terminée. Veuillez réessayer."
},
"codes": {
"VEHICLE_NOT_FOUND": {
"title": "Véhicule introuvable",
"explanation": "Ce véhicule est introuvable. Il a peut-être été supprimé, ou la référence est incorrecte."
},
"BOOKING_NOT_FOUND": {
"title": "Réservation introuvable",
"explanation": "Cette réservation est introuvable. Elle a peut-être été supprimée, ou la référence est incorrecte."
},
"CUSTOMER_NOT_FOUND": {
"title": "Client introuvable",
"explanation": "Cette fiche client est introuvable."
},
"ENTITY_NOT_FOUND": {
"title": "Fiche introuvable",
"explanation": "La fiche sous-jacente à cette action est introuvable."
},
"EVENT_NOT_FOUND": {
"title": "Tâche d'automatisation introuvable",
"explanation": "Cet événement d'automatisation est introuvable."
},
"ISSUE_NOT_FOUND": {
"title": "Problème de qualité des données introuvable",
"explanation": "Ce problème de qualité des données est introuvable."
},
"ISSUE_NOT_OPEN": {
"title": "Le problème n'est plus ouvert",
"explanation": "Ce problème a déjà été résolu, reporté ou rejeté.",
"nextStep": "Actualisez la page pour voir son état actuel."
},
"BOOKING_NOT_ACTIVE": {
"title": "La réservation n'est pas active",
"explanation": "Seule une réservation réservée ou active peut être utilisée pour cette action."
},
"INVALID_BOOKING_STATE": {
"title": "La réservation est dans le mauvais état",
"explanation": "L'état actuel de cette réservation ne permet pas cette action."
},
"NOT_RETRYABLE": {
"title": "Cette tâche ne peut pas être relancée",
"explanation": "Seule une livraison échouée peut être relancée."
},
"CONFLICT_STILL_PRESENT": {
"title": "Le conflit n'a pas été résolu",
"explanation": "L'application de ce changement n'a pas résolu le conflit sous-jacent.",
"nextStep": "Consultez à nouveau la recommandation avant de réessayer."
},
"OVERLAP_STILL_PRESENT": {
"title": "Le chevauchement n'a pas été résolu",
"explanation": "Le blocage de cette réservation n'a pas supprimé le chevauchement ; un autre engagement subsiste."
},
"EMPTY_VALUE": {
"title": "Un champ requis est vide",
"explanation": "Ce champ ne peut pas rester vide.",
"nextStep": "Saisissez une valeur et réessayez."
},
"NO_FIELDS_PROVIDED": {
"title": "Aucune modification fournie",
"explanation": "Au moins un champ doit être complété pour continuer."
},
"INVALID_FIELD": {
"title": "Champ non autorisé ici",
"explanation": "L'un des champs fournis n'est pas autorisé pour cette action."
},
"INVALID_FIELD_OVERRIDE": {
"title": "Ce champ ne peut pas être fusionné",
"explanation": "L'un des champs sélectionnés ne peut pas être utilisé dans cette fusion."
},
"INVALID_SURVIVOR": {
"title": "Sélection non valide",
"explanation": "La fiche que vous souhaitez conserver doit être l'une des deux fiches comparées."
},
"INVALID_BOOKING_REFERENCE": {
"title": "Référence de réservation non valide ici",
"explanation": "La réservation sélectionnée ne fait pas partie des réservations liées à ce problème."
},
"INVALID_EVENT_ID": {
"title": "Référence d'événement non valide",
"explanation": "Cette référence d'événement d'automatisation n'est pas valide."
},
"INVALID_IDEMPOTENCY_KEY": {
"title": "La demande n'a pas pu être répétée en toute sécurité",
"explanation": "La clé de suivi de cette demande n'est pas valide.",
"nextStep": "Rechargez la page et réessayez."
},
"IDEMPOTENCY_KEY_REUSED": {
"title": "Cette action a déjà été soumise",
"explanation": "Une demande identique a déjà été traitée, avec un résultat différent.",
"nextStep": "Rechargez la page pour voir l'état actuel avant de réessayer."
},
"CORRECTED_VALUE_REQUIRED": {
"title": "Une valeur corrigée est requise",
"explanation": "Le choix « corriger le relevé » nécessite de saisir la valeur corrigée."
},
"CORRECTION_BELOW_CANONICAL": {
"title": "La correction est inférieure au relevé confirmé",
"explanation": "Un kilométrage corrigé ne peut jamais être inférieur au dernier relevé confirmé."
},
"NOT_A_DUPLICATE_ISSUE": {
"title": "Type de problème incorrect",
"explanation": "Cette action s'applique uniquement aux problèmes de client potentiellement en double."
},
"NOT_A_MISSING_FIELD_ISSUE": {
"title": "Type de problème incorrect",
"explanation": "Cette action s'applique uniquement aux problèmes de champ obligatoire manquant."
},
"NOT_AN_ODOMETER_ISSUE": {
"title": "Type de problème incorrect",
"explanation": "Cette action s'applique uniquement aux problèmes d'anomalie de kilométrage."
},
"NOT_AN_OVERLAP_ISSUE": {
"title": "Type de problème incorrect",
"explanation": "Cette action s'applique uniquement aux problèmes de chevauchement de réservations."
},
"NOT_A_STATUS_CONFLICT_ISSUE": {
"title": "Type de problème incorrect",
"explanation": "Cette action s'applique uniquement aux problèmes de conflit de statut du véhicule."
},
"UNSUPPORTED_ENTITY": {
"title": "Non pris en charge pour ce type de fiche",
"explanation": "Cette action n'est pas disponible pour ce type de fiche."
},
"MANUAL_REVIEW_REQUIRED": {
"title": "Évaluation manuelle requise",
"explanation": "Les faits concernant ce véhicule se contredisent, ce qui rend tout changement automatique non sûr.",
"nextStep": "Reportez ou rejetez ce problème, ou examinez-le manuellement."
},
"NO_CONFLICT_DETECTED": {
"title": "Rien à appliquer",
"explanation": "Le statut actuel correspond déjà aux faits, il n'y a donc plus rien à appliquer."
},
"RECOMMENDATION_STALE": {
"title": "La situation a changé entre-temps",
"explanation": "Les faits sous-jacents ont changé depuis l'affichage de cette recommandation.",
"nextStep": "Consultez à nouveau la recommandation avant de l'appliquer."
},
"UNAUTHORIZED_SERVICE": {
"title": "Échec de l'autorisation du service",
"explanation": "Cette demande automatisée n'a pas pu être autorisée."
}
},
"http": {
"401": {
"title": "Session expirée",
"explanation": "Votre session a expiré.",
"nextStep": "Veuillez vous reconnecter."
},
"403": {
"title": "Accès refusé",
"explanation": "Vous n'avez pas la permission d'effectuer cette action."
},
"404": {
"title": "Introuvable",
"explanation": "Cette fiche est introuvable."
},
"409": {
"title": "Cette action n'est plus possible",
"explanation": "L'état sous-jacent a changé depuis le chargement de cette page.",
"nextStep": "Actualisez la page et réessayez."
},
"422": {
"title": "Échec de la validation",
"explanation": "Les informations fournies ne sont pas valides."
},
"500": {
"title": "Erreur serveur",
"explanation": "Un problème est survenu de notre côté."
},
"network": {
"title": "Connexion indisponible",
"explanation": "La connexion au serveur est actuellement indisponible.",
"nextStep": "Vérifiez votre connexion et réessayez."
}
}
}