i18n: backend-localized lookups, suggestions, and static data (10 languages)
Backend CI / Test (push) Has been cancelled
Backend CI / Contract Tests (push) Has been cancelled
Backend CI / Lint (push) Has been cancelled
Backend CI / Secret Scanning (push) Has been cancelled
Backend CI / Build (push) Has been cancelled

- suggestion_service: fix scorer (stringList unmarshal accepts scalar|array;
  anchor scoring on base universal score so bool matches no longer tie); add
  localizeReasons for human-readable, Accept-Language-localized match reasons
- lookup_i18n: localize lookup display names, home-profile options, document
  types/categories via internal/i18n
- static_data_handler: per-locale seeded-data response (display_name, home
  profile options, document types/categories) with per-locale cache + ETag
- settings_handler: invalidate per-locale seeded-data cache on lookup change
  instead of pre-warming a single non-localized blob
- cache_service: per-locale seeded-data keys + ETag
- DTOs: add DisplayName fields (task/residence/contractor)
- translations: add suggestion.reason.* and lookup.* keys across all 10 langs
- cmd/api: extract startup helpers + tests

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey T
2026-06-04 20:54:54 -05:00
parent 25897e913e
commit 12de5a230a
23 changed files with 1671 additions and 703 deletions
+98 -42
View File
@@ -25,7 +25,6 @@
"error.google_signin_not_configured": "La connexion Google n'est pas configuree",
"error.google_signin_failed": "Echec de la connexion Google",
"error.invalid_google_token": "Jeton d'identite Google non valide",
"error.invalid_task_id": "ID de tache non valide",
"error.invalid_residence_id": "ID de propriete non valide",
"error.invalid_contractor_id": "ID de prestataire non valide",
@@ -34,7 +33,6 @@
"error.invalid_user_id": "ID d'utilisateur non valide",
"error.invalid_notification_id": "ID de notification non valide",
"error.invalid_device_id": "ID d'appareil non valide",
"error.task_not_found": "Tache non trouvee",
"error.residence_not_found": "Propriete non trouvee",
"error.contractor_not_found": "Prestataire non trouve",
@@ -43,7 +41,6 @@
"error.user_not_found": "Utilisateur non trouve",
"error.share_code_invalid": "Code de partage non valide",
"error.share_code_expired": "Le code de partage a expire",
"error.task_access_denied": "Vous n'avez pas acces a cette tache",
"error.residence_access_denied": "Vous n'avez pas acces a cette propriete",
"error.contractor_access_denied": "Vous n'avez pas acces a ce prestataire",
@@ -52,10 +49,8 @@
"error.cannot_remove_owner": "Impossible de retirer le proprietaire",
"error.user_already_member": "L'utilisateur est deja membre de cette propriete",
"error.properties_limit_reached": "Vous avez atteint le nombre maximum de proprietes pour votre abonnement",
"error.task_already_cancelled": "La tache est deja annulee",
"error.task_already_archived": "La tache est deja archivee",
"error.failed_to_parse_form": "Echec de l'analyse du formulaire",
"error.task_id_required": "task_id est requis",
"error.invalid_task_id_value": "task_id non valide",
@@ -64,14 +59,12 @@
"error.invalid_residence_id_value": "residence_id non valide",
"error.title_required": "Le titre est requis",
"error.failed_to_upload_file": "Echec du telechargement du fichier",
"message.logged_out": "Deconnexion reussie",
"message.email_verified": "Email verifie avec succes",
"message.verification_email_sent": "Email de verification envoye",
"message.password_reset_email_sent": "Si un compte existe avec cet email, un code de reinitialisation a ete envoye.",
"message.reset_code_verified": "Code verifie avec succes",
"message.password_reset_success": "Mot de passe reinitialise avec succes. Veuillez vous connecter avec votre nouveau mot de passe.",
"message.task_deleted": "Tache supprimee avec succes",
"message.task_in_progress": "Tache marquee comme en cours",
"message.task_cancelled": "Tache annulee",
@@ -79,46 +72,35 @@
"message.task_archived": "Tache archivee",
"message.task_unarchived": "Tache desarchivee",
"message.completion_deleted": "Completion supprimee avec succes",
"message.residence_deleted": "Propriete supprimee avec succes",
"message.user_removed": "Utilisateur retire de la propriete",
"message.tasks_report_generated": "Rapport de taches genere avec succes",
"message.tasks_report_sent": "Rapport de taches genere et envoye a {{.Email}}",
"message.tasks_report_email_failed": "Rapport de taches genere mais l'email n'a pas pu etre envoye",
"message.contractor_deleted": "Prestataire supprime avec succes",
"message.document_deleted": "Document supprime avec succes",
"message.document_activated": "Document active",
"message.document_deactivated": "Document desactive",
"message.notification_marked_read": "Notification marquée comme lue",
"message.all_notifications_marked_read": "Toutes les notifications marquées comme lues",
"message.device_removed": "Appareil supprimé",
"message.subscription_upgraded": "Abonnement mis à niveau avec succès",
"message.subscription_cancelled": "Abonnement annulé. Vous conserverez les avantages Pro jusqu'à la fin de votre période de facturation.",
"message.subscription_restored": "Abonnement restauré avec succès",
"message.file_deleted": "Fichier supprimé avec succès",
"message.static_data_refreshed": "Données statiques actualisées",
"error.notification_not_found": "Notification non trouvée",
"error.invalid_platform": "Plateforme non valide",
"error.upgrade_trigger_not_found": "Déclencheur de mise à niveau non trouvé",
"error.receipt_data_required": "receipt_data est requis pour iOS",
"error.purchase_token_required": "purchase_token est requis pour Android",
"error.no_file_provided": "Aucun fichier fourni",
"error.failed_to_fetch_residence_types": "Échec de la récupération des types de propriété",
"error.failed_to_fetch_task_categories": "Échec de la récupération des catégories de tâches",
"error.failed_to_fetch_task_priorities": "Échec de la récupération des priorités de tâches",
"error.failed_to_fetch_task_frequencies": "Échec de la récupération des fréquences de tâches",
"error.failed_to_fetch_task_statuses": "Échec de la récupération des statuts de tâches",
"error.failed_to_fetch_contractor_specialties": "Échec de la récupération des spécialités des prestataires",
"push.task_due_soon.title": "Tache Bientot Due",
"push.task_due_soon.body": "{{.TaskTitle}} est due le {{.DueDate}}",
"push.task_overdue.title": "Tache en Retard",
@@ -129,44 +111,38 @@
"push.task_assigned.body": "{{.TaskTitle}} vous a ete assignee",
"push.residence_shared.title": "Propriete Partagee",
"push.residence_shared.body": "{{.UserName}} a partage {{.ResidenceName}} avec vous",
"email.welcome.subject": "Bienvenue sur honeyDue !",
"email.verification.subject": "Verifiez Votre Email",
"email.password_reset.subject": "Code de Reinitialisation de Mot de Passe",
"email.tasks_report.subject": "Rapport de Taches pour {{.ResidenceName}}",
"lookup.residence_type.house": "Maison",
"lookup.residence_type.apartment": "Appartement",
"lookup.residence_type.condo": "Copropriete",
"lookup.residence_type.townhouse": "Maison de Ville",
"lookup.residence_type.mobile_home": "Mobil-home",
"lookup.residence_type.condo": "Copropriété",
"lookup.residence_type.townhouse": "Maison de ville",
"lookup.residence_type.mobile_home": "Maison mobile",
"lookup.residence_type.other": "Autre",
"lookup.task_category.plumbing": "Plomberie",
"lookup.task_category.electrical": "Electricite",
"lookup.task_category.hvac": "Climatisation",
"lookup.task_category.appliances": "Electromenager",
"lookup.task_category.exterior": "Exterieur",
"lookup.task_category.interior": "Interieur",
"lookup.task_category.electrical": "Électricité",
"lookup.task_category.hvac": "CVC",
"lookup.task_category.appliances": "Électroménager",
"lookup.task_category.exterior": "Extérieur",
"lookup.task_category.interior": "Intérieur",
"lookup.task_category.landscaping": "Jardinage",
"lookup.task_category.safety": "Securite",
"lookup.task_category.safety": "Sécurité",
"lookup.task_category.cleaning": "Nettoyage",
"lookup.task_category.pest_control": "Lutte Antiparasitaire",
"lookup.task_category.pest_control": "Lutte antiparasitaire",
"lookup.task_category.seasonal": "Saisonnier",
"lookup.task_category.other": "Autre",
"lookup.task_priority.low": "Basse",
"lookup.task_priority.medium": "Moyenne",
"lookup.task_priority.high": "Haute",
"lookup.task_priority.urgent": "Urgente",
"lookup.task_status.pending": "En Attente",
"lookup.task_status.in_progress": "En Cours",
"lookup.task_status.completed": "Terminee",
"lookup.task_status.cancelled": "Annulee",
"lookup.task_status.archived": "Archivee",
"lookup.task_frequency.once": "Une Fois",
"lookup.task_frequency.once": "Une fois",
"lookup.task_frequency.daily": "Quotidien",
"lookup.task_frequency.weekly": "Hebdomadaire",
"lookup.task_frequency.biweekly": "Toutes les 2 Semaines",
@@ -174,18 +150,98 @@
"lookup.task_frequency.quarterly": "Trimestriel",
"lookup.task_frequency.semiannually": "Tous les 6 Mois",
"lookup.task_frequency.annually": "Annuel",
"lookup.contractor_specialty.plumber": "Plombier",
"lookup.contractor_specialty.electrician": "Electricien",
"lookup.contractor_specialty.electrician": "Électricien",
"lookup.contractor_specialty.hvac_technician": "Technicien CVC",
"lookup.contractor_specialty.handyman": "Bricoleur",
"lookup.contractor_specialty.landscaper": "Paysagiste",
"lookup.contractor_specialty.roofer": "Couvreur",
"lookup.contractor_specialty.painter": "Peintre",
"lookup.contractor_specialty.carpenter": "Menuisier",
"lookup.contractor_specialty.pest_control": "Desinsectisation",
"lookup.contractor_specialty.carpenter": "Charpentier",
"lookup.contractor_specialty.pest_control": "Lutte antiparasitaire",
"lookup.contractor_specialty.cleaning": "Nettoyage",
"lookup.contractor_specialty.pool_service": "Service Piscine",
"lookup.contractor_specialty.general_contractor": "Entrepreneur General",
"lookup.contractor_specialty.other": "Autre"
"lookup.contractor_specialty.pool_service": "Service de piscine",
"lookup.contractor_specialty.general_contractor": "Entrepreneur général",
"lookup.contractor_specialty.other": "Autre",
"suggestion.reason.has_pool": "Votre logement a une piscine",
"suggestion.reason.has_sprinkler_system": "Votre logement a un système d'arrosage",
"suggestion.reason.has_septic": "Votre logement a une fosse septique",
"suggestion.reason.has_fireplace": "Votre logement a une cheminée",
"suggestion.reason.has_garage": "Votre logement a un garage",
"suggestion.reason.has_basement": "Votre logement a un sous-sol",
"suggestion.reason.has_attic": "Votre logement a des combles",
"suggestion.reason.heating_type": "Correspond à votre système de chauffage",
"suggestion.reason.cooling_type": "Correspond à votre système de climatisation",
"suggestion.reason.water_heater_type": "Correspond à votre chauffe-eau",
"suggestion.reason.roof_type": "Correspond à votre toiture",
"suggestion.reason.exterior_type": "Correspond à votre extérieur",
"suggestion.reason.flooring_primary": "Correspond à votre revêtement de sol",
"suggestion.reason.landscaping_type": "Correspond à votre aménagement paysager",
"suggestion.reason.property_type": "Recommandé pour votre type de logement",
"suggestion.reason.climate_region": "Recommandé pour votre climat",
"lookup.residence_type.duplex": "Duplex",
"lookup.residence_type.vacation_home": "Maison de vacances",
"lookup.task_category.general": "Général",
"lookup.task_frequency.bi_weekly": "Bimensuel",
"lookup.task_frequency.semi_annually": "Semestriel",
"lookup.task_frequency.custom": "Personnalisé",
"lookup.contractor_specialty.appliance_repair": "Réparation d'électroménager",
"lookup.contractor_specialty.cleaner": "Agent de nettoyage",
"lookup.contractor_specialty.locksmith": "Serrurier",
"lookup.home_profile.gas_furnace": "Fournaise au gaz",
"lookup.home_profile.electric_furnace": "Fournaise électrique",
"lookup.home_profile.heat_pump": "Pompe à chaleur",
"lookup.home_profile.boiler": "Chaudière",
"lookup.home_profile.radiant": "Rayonnant",
"lookup.home_profile.other": "Autre",
"lookup.home_profile.central_ac": "Climatisation centrale",
"lookup.home_profile.window_ac": "Climatiseur de fenêtre",
"lookup.home_profile.evaporative": "Évaporatif",
"lookup.home_profile.none": "Aucun",
"lookup.home_profile.tank_gas": "Réservoir (gaz)",
"lookup.home_profile.tank_electric": "Réservoir (électrique)",
"lookup.home_profile.tankless_gas": "Sans réservoir (gaz)",
"lookup.home_profile.tankless_electric": "Sans réservoir (électrique)",
"lookup.home_profile.solar": "Solaire",
"lookup.home_profile.asphalt_shingle": "Bardeau d'asphalte",
"lookup.home_profile.metal": "Métal",
"lookup.home_profile.tile": "Tuile",
"lookup.home_profile.slate": "Ardoise",
"lookup.home_profile.wood_shake": "Bardeau de bois",
"lookup.home_profile.flat": "Plat",
"lookup.home_profile.brick": "Brique",
"lookup.home_profile.vinyl_siding": "Revêtement vinyle",
"lookup.home_profile.wood_siding": "Revêtement bois",
"lookup.home_profile.stucco": "Stuc",
"lookup.home_profile.stone": "Pierre",
"lookup.home_profile.fiber_cement": "Fibrociment",
"lookup.home_profile.hardwood": "Bois franc",
"lookup.home_profile.laminate": "Stratifié",
"lookup.home_profile.carpet": "Moquette",
"lookup.home_profile.vinyl": "Vinyle",
"lookup.home_profile.concrete": "Béton",
"lookup.home_profile.lawn": "Pelouse",
"lookup.home_profile.desert": "Désert",
"lookup.home_profile.xeriscape": "Xéropaysagisme",
"lookup.home_profile.garden": "Jardin",
"lookup.home_profile.mixed": "Mixte",
"lookup.document_type.warranty": "Garantie",
"lookup.document_type.manual": "Manuel d'utilisation",
"lookup.document_type.receipt": "Reçu/Facture",
"lookup.document_type.inspection": "Rapport d'inspection",
"lookup.document_type.permit": "Permis",
"lookup.document_type.deed": "Acte/Titre",
"lookup.document_type.insurance": "Assurance",
"lookup.document_type.contract": "Contrat",
"lookup.document_type.photo": "Photo",
"lookup.document_type.other": "Autre",
"lookup.document_category.appliance": "Électroménager",
"lookup.document_category.hvac": "CVC",
"lookup.document_category.plumbing": "Plomberie",
"lookup.document_category.electrical": "Électricité",
"lookup.document_category.roofing": "Toiture",
"lookup.document_category.structural": "Structure",
"lookup.document_category.landscaping": "Aménagement paysager",
"lookup.document_category.general": "Général",
"lookup.document_category.other": "Autre"
}