Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
{
|
|
|
|
|
"common": {
|
|
|
|
|
"loading": "Chargement...",
|
|
|
|
|
"save": "Enregistrer",
|
|
|
|
|
"cancel": "Annuler",
|
|
|
|
|
"delete": "Supprimer",
|
|
|
|
|
"edit": "Modifier",
|
|
|
|
|
"create": "Cr\u00e9er",
|
|
|
|
|
"close": "Fermer",
|
|
|
|
|
"confirm": "Confirmer",
|
|
|
|
|
"back": "Retour",
|
|
|
|
|
"next": "Suivant",
|
|
|
|
|
"submit": "Soumettre",
|
|
|
|
|
"search": "Rechercher",
|
|
|
|
|
"filter": "Filtrer",
|
|
|
|
|
"export": "Exporter",
|
|
|
|
|
"import": "Importer",
|
|
|
|
|
"refresh": "Actualiser",
|
|
|
|
|
"actions": "Actions",
|
|
|
|
|
"status": "Statut",
|
|
|
|
|
"name": "Nom",
|
|
|
|
|
"email": "E-mail",
|
|
|
|
|
"role": "R\u00f4le",
|
|
|
|
|
"date": "Date",
|
|
|
|
|
"description": "Description",
|
|
|
|
|
"settings": "Param\u00e8tres",
|
|
|
|
|
"yes": "Oui",
|
|
|
|
|
"no": "Non",
|
|
|
|
|
"all": "Tous",
|
|
|
|
|
"none": "Aucun",
|
|
|
|
|
"noResults": "Aucun r\u00e9sultat trouv\u00e9",
|
|
|
|
|
"error": "Erreur",
|
|
|
|
|
"success": "Succ\u00e8s",
|
|
|
|
|
"warning": "Avertissement",
|
|
|
|
|
"info": "Information",
|
|
|
|
|
"required": "Obligatoire",
|
|
|
|
|
"optional": "Facultatif",
|
|
|
|
|
"total": "Total",
|
|
|
|
|
"page": "Page",
|
|
|
|
|
"of": "de",
|
|
|
|
|
"showing": "Affichage de",
|
|
|
|
|
"entries": "entr\u00e9es",
|
|
|
|
|
"perPage": "par page",
|
|
|
|
|
"language": "Langue",
|
|
|
|
|
"english": "Anglais",
|
|
|
|
|
"french": "Fran\u00e7ais"
|
|
|
|
|
},
|
|
|
|
|
"auth": {
|
|
|
|
|
"signIn": "Se connecter",
|
|
|
|
|
"signOut": "Se d\u00e9connecter",
|
|
|
|
|
"signUp": "S'inscrire",
|
|
|
|
|
"email": "Adresse e-mail",
|
|
|
|
|
"password": "Mot de passe",
|
|
|
|
|
"forgotPassword": "Mot de passe oubli\u00e9 ?",
|
|
|
|
|
"resetPassword": "R\u00e9initialiser le mot de passe",
|
|
|
|
|
"newPassword": "Nouveau mot de passe",
|
|
|
|
|
"confirmPassword": "Confirmer le mot de passe",
|
|
|
|
|
"currentPassword": "Mot de passe actuel",
|
|
|
|
|
"magicLink": "Se connecter avec un lien magique",
|
|
|
|
|
"magicLinkSent": "V\u00e9rifiez votre e-mail pour un lien de connexion",
|
|
|
|
|
"invalidCredentials": "E-mail ou mot de passe invalide",
|
|
|
|
|
"accountLocked": "Compte verrouill\u00e9. R\u00e9essayez plus tard.",
|
|
|
|
|
"setPassword": "D\u00e9finir le mot de passe",
|
|
|
|
|
"passwordRequirements": "Le mot de passe doit contenir au moins 8 caract\u00e8res",
|
|
|
|
|
"passwordsDoNotMatch": "Les mots de passe ne correspondent pas",
|
|
|
|
|
"welcomeBack": "Bon retour",
|
|
|
|
|
"signInDescription": "Entrez votre e-mail pour vous connecter \u00e0 votre compte",
|
|
|
|
|
"orContinueWith": "Ou continuer avec"
|
|
|
|
|
},
|
|
|
|
|
"nav": {
|
|
|
|
|
"dashboard": "Tableau de bord",
|
|
|
|
|
"programs": "Programmes",
|
|
|
|
|
"rounds": "Tours",
|
|
|
|
|
"projects": "Projets",
|
|
|
|
|
"users": "Utilisateurs",
|
|
|
|
|
"evaluations": "\u00c9valuations",
|
|
|
|
|
"assignments": "Affectations",
|
|
|
|
|
"analytics": "Analytique",
|
|
|
|
|
"settings": "Param\u00e8tres",
|
|
|
|
|
"audit": "Journal d'audit",
|
|
|
|
|
"myProjects": "Mes projets",
|
|
|
|
|
"myEvaluations": "Mes \u00e9valuations",
|
|
|
|
|
"profile": "Profil",
|
|
|
|
|
"help": "Aide",
|
|
|
|
|
"notifications": "Notifications",
|
|
|
|
|
"mentoring": "Mentorat",
|
|
|
|
|
"liveVoting": "Vote en direct",
|
|
|
|
|
"applications": "Candidatures",
|
2026-02-11 13:20:52 +01:00
|
|
|
"messages": "Messages",
|
|
|
|
|
"team": "\u00c9quipe",
|
|
|
|
|
"documents": "Documents",
|
|
|
|
|
"awards": "Prix",
|
|
|
|
|
"compare": "Comparer",
|
|
|
|
|
"learningHub": "Centre de ressources",
|
|
|
|
|
"reports": "Rapports"
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
},
|
|
|
|
|
"dashboard": {
|
|
|
|
|
"title": "Tableau de bord",
|
|
|
|
|
"welcome": "Bienvenue, {name}",
|
|
|
|
|
"overview": "Aper\u00e7u",
|
|
|
|
|
"recentActivity": "Activit\u00e9 r\u00e9cente",
|
|
|
|
|
"pendingEvaluations": "\u00c9valuations en attente",
|
|
|
|
|
"completedEvaluations": "\u00c9valuations termin\u00e9es",
|
|
|
|
|
"totalProjects": "Total des projets",
|
|
|
|
|
"activeRounds": "Tours actifs",
|
|
|
|
|
"assignedProjects": "Projets assign\u00e9s",
|
|
|
|
|
"upcomingDeadlines": "\u00c9ch\u00e9ances \u00e0 venir",
|
|
|
|
|
"quickActions": "Actions rapides",
|
|
|
|
|
"noActivity": "Aucune activit\u00e9 r\u00e9cente"
|
|
|
|
|
},
|
|
|
|
|
"programs": {
|
|
|
|
|
"title": "Programmes",
|
|
|
|
|
"createProgram": "Cr\u00e9er un programme",
|
|
|
|
|
"editProgram": "Modifier le programme",
|
|
|
|
|
"programName": "Nom du programme",
|
|
|
|
|
"year": "Ann\u00e9e",
|
|
|
|
|
"status": "Statut",
|
|
|
|
|
"rounds": "Tours",
|
|
|
|
|
"projects": "Projets",
|
|
|
|
|
"noPrograms": "Aucun programme trouv\u00e9",
|
|
|
|
|
"deleteConfirm": "\u00cates-vous s\u00fbr de vouloir supprimer ce programme ?"
|
|
|
|
|
},
|
|
|
|
|
"rounds": {
|
|
|
|
|
"title": "Tours",
|
|
|
|
|
"createRound": "Cr\u00e9er un tour",
|
|
|
|
|
"editRound": "Modifier le tour",
|
|
|
|
|
"roundName": "Nom du tour",
|
|
|
|
|
"roundType": "Type de tour",
|
|
|
|
|
"startDate": "Date de d\u00e9but",
|
|
|
|
|
"endDate": "Date de fin",
|
|
|
|
|
"votingWindow": "Fen\u00eatre de vote",
|
|
|
|
|
"criteria": "Crit\u00e8res d'\u00e9valuation",
|
|
|
|
|
"status": "Statut",
|
|
|
|
|
"active": "Actif",
|
|
|
|
|
"closed": "Cl\u00f4tur\u00e9",
|
|
|
|
|
"upcoming": "\u00c0 venir",
|
|
|
|
|
"noRounds": "Aucun tour trouv\u00e9"
|
|
|
|
|
},
|
|
|
|
|
"projects": {
|
|
|
|
|
"title": "Projets",
|
|
|
|
|
"createProject": "Cr\u00e9er un projet",
|
|
|
|
|
"editProject": "Modifier le projet",
|
|
|
|
|
"projectName": "Titre du projet",
|
|
|
|
|
"teamName": "Nom de l'\u00e9quipe",
|
|
|
|
|
"country": "Pays",
|
|
|
|
|
"category": "Cat\u00e9gorie",
|
|
|
|
|
"status": "Statut",
|
|
|
|
|
"description": "Description",
|
|
|
|
|
"files": "Fichiers",
|
|
|
|
|
"evaluations": "\u00c9valuations",
|
|
|
|
|
"noProjects": "Aucun projet trouv\u00e9",
|
|
|
|
|
"importCsv": "Importer CSV",
|
|
|
|
|
"bulkStatusUpdate": "Mise \u00e0 jour en masse du statut",
|
|
|
|
|
"viewDetails": "Voir les d\u00e9tails",
|
|
|
|
|
"assignMentor": "Assigner un mentor",
|
|
|
|
|
"oceanIssue": "Probl\u00e9matique oc\u00e9anique"
|
|
|
|
|
},
|
|
|
|
|
"evaluations": {
|
|
|
|
|
"title": "\u00c9valuations",
|
|
|
|
|
"submitEvaluation": "Soumettre l'\u00e9valuation",
|
|
|
|
|
"draft": "Brouillon",
|
|
|
|
|
"submitted": "Soumis",
|
|
|
|
|
"score": "Note",
|
|
|
|
|
"feedback": "Commentaires",
|
|
|
|
|
"criteria": "Crit\u00e8res",
|
|
|
|
|
"globalScore": "Note globale",
|
|
|
|
|
"decision": "D\u00e9cision",
|
|
|
|
|
"recommend": "Recommander",
|
|
|
|
|
"doNotRecommend": "Ne pas recommander",
|
|
|
|
|
"saveAsDraft": "Enregistrer comme brouillon",
|
|
|
|
|
"finalSubmit": "Soumission finale",
|
|
|
|
|
"confirmSubmit": "\u00cates-vous s\u00fbr ? Cette action est irr\u00e9versible.",
|
|
|
|
|
"progress": "Progression",
|
|
|
|
|
"completionRate": "Taux de compl\u00e9tion",
|
|
|
|
|
"noEvaluations": "Aucune \u00e9valuation pour le moment",
|
|
|
|
|
"evaluationSummary": "R\u00e9sum\u00e9 de l'\u00e9valuation",
|
|
|
|
|
"strengths": "Points forts",
|
|
|
|
|
"weaknesses": "Points faibles",
|
|
|
|
|
"overallAssessment": "\u00c9valuation globale"
|
|
|
|
|
},
|
|
|
|
|
"users": {
|
|
|
|
|
"title": "Utilisateurs",
|
|
|
|
|
"createUser": "Cr\u00e9er un utilisateur",
|
|
|
|
|
"editUser": "Modifier l'utilisateur",
|
|
|
|
|
"inviteUser": "Inviter un utilisateur",
|
|
|
|
|
"bulkImport": "Importation en masse",
|
|
|
|
|
"sendInvitation": "Envoyer l'invitation",
|
|
|
|
|
"resendInvitation": "Renvoyer l'invitation",
|
|
|
|
|
"role": "R\u00f4le",
|
|
|
|
|
"status": "Statut",
|
|
|
|
|
"active": "Actif",
|
|
|
|
|
"invited": "Invit\u00e9",
|
|
|
|
|
"suspended": "Suspendu",
|
|
|
|
|
"noUsers": "Aucun utilisateur trouv\u00e9",
|
|
|
|
|
"expertiseTags": "Tags d'expertise",
|
|
|
|
|
"maxAssignments": "Affectations max.",
|
|
|
|
|
"lastLogin": "Derni\u00e8re connexion",
|
|
|
|
|
"deleteConfirm": "\u00cates-vous s\u00fbr de vouloir supprimer cet utilisateur ?"
|
|
|
|
|
},
|
|
|
|
|
"assignments": {
|
|
|
|
|
"title": "Affectations",
|
|
|
|
|
"assign": "Affecter",
|
|
|
|
|
"unassign": "D\u00e9saffecter",
|
|
|
|
|
"bulkAssign": "Affectation en masse",
|
|
|
|
|
"smartAssign": "Affectation intelligente",
|
|
|
|
|
"manual": "Manuel",
|
|
|
|
|
"algorithm": "Algorithme",
|
|
|
|
|
"aiAuto": "IA automatique",
|
|
|
|
|
"noAssignments": "Aucune affectation",
|
|
|
|
|
"assignedTo": "Affect\u00e9 \u00e0",
|
|
|
|
|
"assignedBy": "Affect\u00e9 par"
|
|
|
|
|
},
|
|
|
|
|
"files": {
|
|
|
|
|
"title": "Fichiers",
|
|
|
|
|
"upload": "T\u00e9l\u00e9charger un fichier",
|
|
|
|
|
"download": "T\u00e9l\u00e9charger",
|
|
|
|
|
"delete": "Supprimer le fichier",
|
|
|
|
|
"fileName": "Nom du fichier",
|
|
|
|
|
"fileType": "Type de fichier",
|
|
|
|
|
"fileSize": "Taille du fichier",
|
|
|
|
|
"uploadDate": "Date de t\u00e9l\u00e9chargement",
|
|
|
|
|
"noFiles": "Aucun fichier t\u00e9l\u00e9charg\u00e9",
|
|
|
|
|
"dragAndDrop": "Glissez-d\u00e9posez les fichiers ici",
|
|
|
|
|
"maxSize": "Taille maximale du fichier : {size}",
|
|
|
|
|
"version": "Version",
|
|
|
|
|
"versionHistory": "Historique des versions",
|
|
|
|
|
"replaceFile": "Remplacer le fichier",
|
|
|
|
|
"bulkDownload": "T\u00e9l\u00e9chargement en masse"
|
|
|
|
|
},
|
|
|
|
|
"settings": {
|
|
|
|
|
"title": "Param\u00e8tres",
|
|
|
|
|
"general": "G\u00e9n\u00e9ral",
|
|
|
|
|
"branding": "Image de marque",
|
|
|
|
|
"email": "E-mail",
|
|
|
|
|
"security": "S\u00e9curit\u00e9",
|
|
|
|
|
"ai": "Configuration IA",
|
|
|
|
|
"storage": "Stockage",
|
|
|
|
|
"language": "Langue",
|
|
|
|
|
"defaultLanguage": "Langue par d\u00e9faut",
|
|
|
|
|
"availableLanguages": "Langues disponibles",
|
|
|
|
|
"languageDescription": "Configurer les param\u00e8tres de langue de la plateforme",
|
|
|
|
|
"saved": "Param\u00e8tres enregistr\u00e9s avec succ\u00e8s",
|
|
|
|
|
"saveFailed": "\u00c9chec de l'enregistrement des param\u00e8tres"
|
|
|
|
|
},
|
|
|
|
|
"liveVoting": {
|
|
|
|
|
"title": "Vote en direct",
|
|
|
|
|
"session": "Session",
|
|
|
|
|
"startVoting": "D\u00e9marrer le vote",
|
|
|
|
|
"stopVoting": "Arr\u00eater le vote",
|
|
|
|
|
"endSession": "Terminer la session",
|
|
|
|
|
"timeRemaining": "Temps restant",
|
|
|
|
|
"castVote": "Voter",
|
|
|
|
|
"voteSubmitted": "Vote soumis",
|
|
|
|
|
"results": "R\u00e9sultats",
|
|
|
|
|
"juryScore": "Note du jury",
|
|
|
|
|
"audienceScore": "Note du public",
|
|
|
|
|
"weightedTotal": "Total pond\u00e9r\u00e9",
|
|
|
|
|
"noVotes": "Aucun vote pour le moment",
|
|
|
|
|
"votingClosed": "Le vote est clos",
|
|
|
|
|
"presentationSettings": "Param\u00e8tres de pr\u00e9sentation",
|
|
|
|
|
"audienceVoting": "Vote du public"
|
|
|
|
|
},
|
|
|
|
|
"mentor": {
|
|
|
|
|
"title": "Mentorat",
|
|
|
|
|
"myMentees": "Mes mentees",
|
|
|
|
|
"projectDetails": "D\u00e9tails du projet",
|
|
|
|
|
"sendMessage": "Envoyer un message",
|
|
|
|
|
"notes": "Notes",
|
|
|
|
|
"addNote": "Ajouter une note",
|
|
|
|
|
"milestones": "Jalons",
|
|
|
|
|
"completeMilestone": "Marquer comme termin\u00e9",
|
|
|
|
|
"activity": "Activit\u00e9",
|
|
|
|
|
"lastViewed": "Derni\u00e8re consultation",
|
|
|
|
|
"noMentees": "Aucun mentee assign\u00e9"
|
|
|
|
|
},
|
|
|
|
|
"profile": {
|
|
|
|
|
"title": "Profil",
|
|
|
|
|
"editProfile": "Modifier le profil",
|
|
|
|
|
"name": "Nom complet",
|
|
|
|
|
"email": "E-mail",
|
|
|
|
|
"phone": "Num\u00e9ro de t\u00e9l\u00e9phone",
|
|
|
|
|
"country": "Pays",
|
|
|
|
|
"bio": "Biographie",
|
|
|
|
|
"expertise": "Domaines d'expertise",
|
|
|
|
|
"notifications": "Pr\u00e9f\u00e9rences de notification",
|
|
|
|
|
"digestFrequency": "Fr\u00e9quence du digest",
|
|
|
|
|
"availability": "Disponibilit\u00e9",
|
|
|
|
|
"workload": "Charge de travail pr\u00e9f\u00e9r\u00e9e",
|
|
|
|
|
"changePassword": "Changer le mot de passe",
|
|
|
|
|
"deleteAccount": "Supprimer le compte",
|
|
|
|
|
"deleteAccountConfirm": "Cette action est irr\u00e9versible. Toutes vos donn\u00e9es seront d\u00e9finitivement supprim\u00e9es."
|
|
|
|
|
},
|
|
|
|
|
"onboarding": {
|
|
|
|
|
"welcome": "Bienvenue sur MOPC",
|
|
|
|
|
"setupProfile": "Configurons votre profil",
|
|
|
|
|
"step1": "Informations personnelles",
|
|
|
|
|
"step2": "Expertise et pr\u00e9f\u00e9rences",
|
|
|
|
|
"step3": "V\u00e9rification et finalisation",
|
|
|
|
|
"complete": "Terminer la configuration",
|
|
|
|
|
"skip": "Passer pour le moment"
|
|
|
|
|
},
|
|
|
|
|
"errors": {
|
|
|
|
|
"generic": "Une erreur s'est produite. Veuillez r\u00e9essayer.",
|
|
|
|
|
"notFound": "Page non trouv\u00e9e",
|
|
|
|
|
"unauthorized": "Vous n'\u00eates pas autoris\u00e9 \u00e0 acc\u00e9der \u00e0 cette page",
|
|
|
|
|
"forbidden": "Acc\u00e8s refus\u00e9",
|
|
|
|
|
"serverError": "Erreur interne du serveur",
|
|
|
|
|
"networkError": "Erreur r\u00e9seau. V\u00e9rifiez votre connexion.",
|
|
|
|
|
"sessionExpired": "Votre session a expir\u00e9. Veuillez vous reconnecter.",
|
|
|
|
|
"validationError": "Veuillez v\u00e9rifier le formulaire pour les erreurs"
|
|
|
|
|
},
|
|
|
|
|
"notifications": {
|
|
|
|
|
"title": "Notifications",
|
|
|
|
|
"markAllRead": "Tout marquer comme lu",
|
|
|
|
|
"noNotifications": "Aucune notification",
|
|
|
|
|
"viewAll": "Voir toutes les notifications"
|
|
|
|
|
},
|
|
|
|
|
"coi": {
|
|
|
|
|
"title": "Conflit d'int\u00e9r\u00eats",
|
|
|
|
|
"declaration": "D\u00e9claration de COI",
|
|
|
|
|
"declareConflict": "D\u00e9clarer un conflit d'int\u00e9r\u00eats",
|
|
|
|
|
"noConflict": "Aucun conflit d'int\u00e9r\u00eats",
|
|
|
|
|
"hasConflict": "Conflit d\u00e9clar\u00e9",
|
|
|
|
|
"reason": "Raison du conflit",
|
|
|
|
|
"confirmDeclaration": "Je confirme que cette d\u00e9claration est exacte"
|
|
|
|
|
}
|
|
|
|
|
}
|