1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2025-05-17 22:52:46 +00:00

Compare commits

..

No commits in common. "7732a737bb0851240cca8485389b1919ac574379" and "188b83ce2d69b17ffe48db50343141b020d44b58" have entirely different histories.

6 changed files with 215 additions and 212 deletions

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: TFJM\n" "Project-Id-Version: TFJM\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-07 09:33+0200\n" "POT-Creation-Date: 2024-04-03 23:29+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n" "Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -29,15 +29,15 @@ msgstr "équipes"
#: draw/admin.py:53 draw/admin.py:71 draw/admin.py:88 draw/models.py:26 #: draw/admin.py:53 draw/admin.py:71 draw/admin.py:88 draw/models.py:26
#: participation/admin.py:79 participation/admin.py:140 #: participation/admin.py:79 participation/admin.py:140
#: participation/admin.py:171 participation/models.py:656 #: participation/admin.py:171 participation/models.py:648
#: participation/models.py:680 participation/models.py:861 #: participation/models.py:672 participation/models.py:853
#: registration/models.py:674 #: registration/models.py:674
#: registration/templates/registration/payment_form.html:53 #: registration/templates/registration/payment_form.html:53
msgid "tournament" msgid "tournament"
msgstr "tournoi" msgstr "tournoi"
#: draw/admin.py:92 draw/models.py:234 draw/models.py:433 #: draw/admin.py:92 draw/models.py:234 draw/models.py:433
#: participation/models.py:865 #: participation/models.py:857
msgid "round" msgid "round"
msgstr "tour" msgstr "tour"
@ -49,64 +49,64 @@ msgstr "Tirage au sort"
msgid "You are not an organizer." msgid "You are not an organizer."
msgstr "Vous n'êtes pas un⋅e organisateur⋅rice." msgstr "Vous n'êtes pas un⋅e organisateur⋅rice."
#: draw/consumers.py:162 #: draw/consumers.py:153
msgid "The draw is already started." msgid "The draw is already started."
msgstr "Le tirage a déjà commencé." msgstr "Le tirage a déjà commencé."
#: draw/consumers.py:168 #: draw/consumers.py:159
msgid "Invalid format" msgid "Invalid format"
msgstr "Format invalide" msgstr "Format invalide"
#: draw/consumers.py:173 #: draw/consumers.py:164
#, python-brace-format #, python-brace-format
msgid "The sum must be equal to the number of teams: expected {len}, got {sum}" msgid "The sum must be equal to the number of teams: expected {len}, got {sum}"
msgstr "" msgstr ""
"La somme doit être égale au nombre d'équipes : attendu {len}, obtenu {sum}" "La somme doit être égale au nombre d'équipes : attendu {len}, obtenu {sum}"
#: draw/consumers.py:178 #: draw/consumers.py:169
msgid "There can be at most one pool with 5 teams." msgid "There can be at most one pool with 5 teams."
msgstr "Il ne peut y avoir au plus qu'une seule poule de 5 équipes." msgstr "Il ne peut y avoir au plus qu'une seule poule de 5 équipes."
#: draw/consumers.py:218 #: draw/consumers.py:209
msgid "Draw started!" msgid "Draw started!"
msgstr "Le tirage a commencé !" msgstr "Le tirage a commencé !"
#: draw/consumers.py:240 #: draw/consumers.py:231
#, python-brace-format #, python-brace-format
msgid "The draw for the tournament {tournament} will start." msgid "The draw for the tournament {tournament} will start."
msgstr "Le tirage au sort du tournoi {tournament} va commencer." msgstr "Le tirage au sort du tournoi {tournament} va commencer."
#: draw/consumers.py:251 draw/consumers.py:277 draw/consumers.py:685 #: draw/consumers.py:242 draw/consumers.py:268 draw/consumers.py:676
#: draw/consumers.py:902 draw/consumers.py:991 draw/consumers.py:1013 #: draw/consumers.py:893 draw/consumers.py:982 draw/consumers.py:1004
#: draw/consumers.py:1103 draw/templates/draw/tournament_content.html:5 #: draw/consumers.py:1094 draw/templates/draw/tournament_content.html:5
msgid "The draw has not started yet." msgid "The draw has not started yet."
msgstr "Le tirage au sort n'a pas encore commencé." msgstr "Le tirage au sort n'a pas encore commencé."
#: draw/consumers.py:264 #: draw/consumers.py:255
#, python-brace-format #, python-brace-format
msgid "The draw for the tournament {tournament} is aborted." msgid "The draw for the tournament {tournament} is aborted."
msgstr "Le tirage au sort du tournoi {tournament} est annulé." msgstr "Le tirage au sort du tournoi {tournament} est annulé."
#: draw/consumers.py:304 draw/consumers.py:325 draw/consumers.py:620 #: draw/consumers.py:295 draw/consumers.py:316 draw/consumers.py:611
#: draw/consumers.py:690 draw/consumers.py:907 #: draw/consumers.py:681 draw/consumers.py:898
msgid "This is not the time for this." msgid "This is not the time for this."
msgstr "Ce n'est pas le moment pour cela." msgstr "Ce n'est pas le moment pour cela."
#: draw/consumers.py:317 draw/consumers.py:320 #: draw/consumers.py:308 draw/consumers.py:311
msgid "You've already launched the dice." msgid "You've already launched the dice."
msgstr "Vous avez déjà lancé le dé." msgstr "Vous avez déjà lancé le dé."
#: draw/consumers.py:323 #: draw/consumers.py:314
msgid "It is not your turn." msgid "It is not your turn."
msgstr "Ce n'est pas votre tour." msgstr "Ce n'est pas votre tour."
#: draw/consumers.py:410 #: draw/consumers.py:401
#, python-brace-format #, python-brace-format
msgid "Dices from teams {teams} are identical. Please relaunch your dices." msgid "Dices from teams {teams} are identical. Please relaunch your dices."
msgstr "" msgstr ""
"Les dés des équipes {teams} sont identiques. Merci de relancer vos dés." "Les dés des équipes {teams} sont identiques. Merci de relancer vos dés."
#: draw/consumers.py:1016 #: draw/consumers.py:1007
msgid "This is only available for the final tournament." msgid "This is only available for the final tournament."
msgstr "Cela n'est possible que pour la finale." msgstr "Cela n'est possible que pour la finale."
@ -175,7 +175,7 @@ msgstr "La poule en cours, où les équipes choisissent leurs problèmes"
msgid "rounds" msgid "rounds"
msgstr "tours" msgstr "tours"
#: draw/models.py:257 participation/models.py:879 #: draw/models.py:257 participation/models.py:871
msgid "letter" msgid "letter"
msgstr "lettre" msgstr "lettre"
@ -214,17 +214,17 @@ msgid "Pool {letter}{number}"
msgstr "Poule {letter}{number}" msgstr "Poule {letter}{number}"
#: draw/models.py:414 draw/models.py:441 participation/admin.py:136 #: draw/models.py:414 draw/models.py:441 participation/admin.py:136
#: participation/admin.py:155 participation/models.py:1350 #: participation/admin.py:155 participation/models.py:1340
#: participation/models.py:1359 participation/tables.py:84 #: participation/models.py:1349 participation/tables.py:84
msgid "pool" msgid "pool"
msgstr "poule" msgstr "poule"
#: draw/models.py:415 participation/models.py:1351 #: draw/models.py:415 participation/models.py:1341
msgid "pools" msgid "pools"
msgstr "poules" msgstr "poules"
#: draw/models.py:427 participation/models.py:851 participation/models.py:1520 #: draw/models.py:427 participation/models.py:843 participation/models.py:1510
#: participation/models.py:1550 participation/models.py:1592 #: participation/models.py:1540 participation/models.py:1582
msgid "participation" msgid "participation"
msgstr "participation" msgstr "participation"
@ -248,8 +248,8 @@ msgid ""
msgstr "" msgstr ""
"L'ordre de choix dans la poule, entre 0 et la taille de la poule moins 1." "L'ordre de choix dans la poule, entre 0 et la taille de la poule moins 1."
#: draw/models.py:464 draw/models.py:487 participation/models.py:1373 #: draw/models.py:464 draw/models.py:487 participation/models.py:1363
#: participation/models.py:1557 #: participation/models.py:1547
#, python-brace-format #, python-brace-format
msgid "Problem #{problem}" msgid "Problem #{problem}"
msgstr "Problème n°{problem}" msgstr "Problème n°{problem}"
@ -332,7 +332,7 @@ msgid "Continue draw"
msgstr "Continuer le tirage" msgstr "Continuer le tirage"
#: draw/templates/draw/tournament_content.html:216 participation/admin.py:167 #: draw/templates/draw/tournament_content.html:216 participation/admin.py:167
#: participation/models.py:252 participation/models.py:671 #: participation/models.py:252 participation/models.py:663
#: participation/templates/participation/tournament_harmonize.html:15 #: participation/templates/participation/tournament_harmonize.html:15
#: registration/models.py:157 registration/models.py:665 #: registration/models.py:157 registration/models.py:665
#: registration/tables.py:39 #: registration/tables.py:39
@ -378,8 +378,8 @@ msgstr "Êtes-vous sûr·e de vouloir annuler le tirage au sort ?"
msgid "Close" msgid "Close"
msgstr "Fermer" msgstr "Fermer"
#: draw/views.py:31 participation/views.py:161 participation/views.py:475 #: draw/views.py:31 participation/views.py:156 participation/views.py:470
#: participation/views.py:506 #: participation/views.py:501
msgid "You are not in a team." msgid "You are not in a team."
msgstr "Vous n'êtes pas dans une équipe." msgstr "Vous n'êtes pas dans une équipe."
@ -452,96 +452,96 @@ msgstr "Changelog de type \"{action}\" pour le modèle {model} le {timestamp}"
msgid "valid" msgid "valid"
msgstr "valide" msgstr "valide"
#: participation/admin.py:87 participation/models.py:692 #: participation/admin.py:87 participation/models.py:684
msgid "selected for final" msgid "selected for final"
msgstr "sélectionnée pour la finale" msgstr "sélectionnée pour la finale"
#: participation/admin.py:124 participation/admin.py:183 #: participation/admin.py:124 participation/admin.py:183
#: participation/models.py:1380 participation/tables.py:112 #: participation/models.py:1370 participation/tables.py:112
msgid "defender" msgid "defender"
msgstr "défenseur⋅se" msgstr "défenseur⋅se"
#: participation/admin.py:128 participation/models.py:1387 #: participation/admin.py:128 participation/models.py:1377
#: participation/models.py:1604 #: participation/models.py:1594
msgid "opponent" msgid "opponent"
msgstr "opposant⋅e" msgstr "opposant⋅e"
#: participation/admin.py:132 participation/models.py:1394 #: participation/admin.py:132 participation/models.py:1384
#: participation/models.py:1605 #: participation/models.py:1595
msgid "reporter" msgid "reporter"
msgstr "rapporteur⋅rice" msgstr "rapporteur⋅rice"
#: participation/admin.py:187 participation/models.py:1555 #: participation/admin.py:187 participation/models.py:1545
msgid "problem" msgid "problem"
msgstr "numéro de problème" msgstr "numéro de problème"
#: participation/forms.py:32 #: participation/forms.py:30
msgid "This name is already used." msgid "This name is already used."
msgstr "Ce nom est déjà utilisé." msgstr "Ce nom est déjà utilisé."
#: participation/forms.py:39 participation/models.py:42 #: participation/forms.py:37 participation/models.py:42
msgid "The trigram must be composed of three uppercase letters." msgid "The trigram must be composed of three uppercase letters."
msgstr "Le trigramme doit être composé de trois lettres majuscules." msgstr "Le trigramme doit être composé de trois lettres majuscules."
#: participation/forms.py:42 #: participation/forms.py:40
msgid "This trigram is already used." msgid "This trigram is already used."
msgstr "Ce trigramme est déjà utilisé." msgstr "Ce trigramme est déjà utilisé."
#: participation/forms.py:57 #: participation/forms.py:55
msgid "No team was found with this access code." msgid "No team was found with this access code."
msgstr "Aucune équipe n'a été trouvée avec ce code d'accès." msgstr "Aucune équipe n'a été trouvée avec ce code d'accès."
#: participation/forms.py:61 participation/views.py:477 #: participation/forms.py:59 participation/views.py:472
msgid "The team is already validated or the validation is pending." msgid "The team is already validated or the validation is pending."
msgstr "La validation de l'équipe est déjà faite ou en cours." msgstr "La validation de l'équipe est déjà faite ou en cours."
#: participation/forms.py:90 participation/forms.py:350 #: participation/forms.py:88 participation/forms.py:340
#: registration/forms.py:122 registration/forms.py:144 #: registration/forms.py:122 registration/forms.py:144
#: registration/forms.py:166 registration/forms.py:188 #: registration/forms.py:166 registration/forms.py:188
#: registration/forms.py:237 registration/forms.py:270 #: registration/forms.py:237 registration/forms.py:270
msgid "The uploaded file size must be under 2 Mo." msgid "The uploaded file size must be under 2 Mo."
msgstr "Le fichier envoyé doit peser moins de 2 Mo." msgstr "Le fichier envoyé doit peser moins de 2 Mo."
#: participation/forms.py:92 registration/forms.py:124 #: participation/forms.py:90 registration/forms.py:124
#: registration/forms.py:146 registration/forms.py:168 #: registration/forms.py:146 registration/forms.py:168
#: registration/forms.py:190 registration/forms.py:239 #: registration/forms.py:190 registration/forms.py:239
#: registration/forms.py:272 #: registration/forms.py:272
msgid "The uploaded file must be a PDF, PNG of JPEG file." msgid "The uploaded file must be a PDF, PNG of JPEG file."
msgstr "Le fichier envoyé doit être au format PDF, PNG ou JPEG." msgstr "Le fichier envoyé doit être au format PDF, PNG ou JPEG."
#: participation/forms.py:110 #: participation/forms.py:108
msgid "I engage myself to participate to the whole TFJM²." msgid "I engage myself to participate to the whole TFJM²."
msgstr "Je m'engage à participer à l'intégralité du TFJM²." msgstr "Je m'engage à participer à l'intégralité du TFJM²."
#: participation/forms.py:125 #: participation/forms.py:123
msgid "Message to address to the team:" msgid "Message to address to the team:"
msgstr "Message à adresser à l'équipe :" msgstr "Message à adresser à l'équipe :"
#: participation/forms.py:160 #: participation/forms.py:158
msgid "The uploaded file size must be under 5 Mo." msgid "The uploaded file size must be under 5 Mo."
msgstr "Le fichier envoyé doit peser moins de 5 Mo." msgstr "Le fichier envoyé doit peser moins de 5 Mo."
#: participation/forms.py:162 participation/forms.py:352 #: participation/forms.py:160 participation/forms.py:342
msgid "The uploaded file must be a PDF file." msgid "The uploaded file must be a PDF file."
msgstr "Le fichier envoyé doit être au format PDF." msgstr "Le fichier envoyé doit être au format PDF."
#: participation/forms.py:166 #: participation/forms.py:164
msgid "The PDF file must not have more than 30 pages." msgid "The PDF file must not have more than 30 pages."
msgstr "Le fichier PDF ne doit pas avoir plus de 30 pages." msgstr "Le fichier PDF ne doit pas avoir plus de 30 pages."
#: participation/forms.py:220 #: participation/forms.py:218
msgid "Add" msgid "Add"
msgstr "Ajouter" msgstr "Ajouter"
#: participation/forms.py:235 #: participation/forms.py:233
msgid "This user already exists, but is a participant." msgid "This user already exists, but is a participant."
msgstr "Cet⋅te utilisateur⋅rice existe déjà, mais en tant que participant⋅e." msgstr "Cet⋅te utilisateur⋅rice existe déjà, mais en tant que participant⋅e."
#: participation/forms.py:246 #: participation/forms.py:244
msgid "Spreadsheet file:" msgid "CSV file:"
msgstr "Fichier tableur :" msgstr "Tableur au format CSV :"
#: participation/forms.py:272 #: participation/forms.py:268
msgid "" msgid ""
"This file contains non-UTF-8 and non-ISO-8859-1 content. Please send your " "This file contains non-UTF-8 and non-ISO-8859-1 content. Please send your "
"sheet as a CSV file." "sheet as a CSV file."
@ -549,30 +549,30 @@ msgstr ""
"Ce fichier contient des éléments non-UTF-8 et non-ISO-8859-1. Merci " "Ce fichier contient des éléments non-UTF-8 et non-ISO-8859-1. Merci "
"d'envoyer votre tableur au format CSV." "d'envoyer votre tableur au format CSV."
#: participation/forms.py:293 #: participation/forms.py:283
msgid "Can't determine the pool size. Are you sure your file is correct?" msgid "Can't determine the pool size. Are you sure your file is correct?"
msgstr "" msgstr ""
"Impossible de déterminer la taille de la poule. Êtes-vous sûr⋅e que le " "Impossible de déterminer la taille de la poule. Êtes-vous sûr⋅e que le "
"fichier est correct ?" "fichier est correct ?"
#: participation/forms.py:313 #: participation/forms.py:303
msgid "The following note is higher of the maximum expected value:" msgid "The following note is higher of the maximum expected value:"
msgstr "La note suivante est supérieure au maximum attendu :" msgstr "La note suivante est supérieure au maximum attendu :"
#: participation/forms.py:319 #: participation/forms.py:309
msgid "The following user was not found:" msgid "The following user was not found:"
msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :" msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :"
#: participation/forms.py:333 #: participation/forms.py:323
msgid "The defender, the opponent and the reporter must be different." msgid "The defender, the opponent and the reporter must be different."
msgstr "" msgstr ""
"Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es." "Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es."
#: participation/forms.py:337 #: participation/forms.py:327
msgid "This defender did not work on this problem." msgid "This defender did not work on this problem."
msgstr "Ce⋅tte défenseur⋅se ne travaille pas sur ce problème." msgstr "Ce⋅tte défenseur⋅se ne travaille pas sur ce problème."
#: participation/forms.py:356 #: participation/forms.py:346
msgid "The PDF file must not have more than 2 pages." msgid "The PDF file must not have more than 2 pages."
msgstr "Le fichier PDF ne doit pas avoir plus de 2 pages." msgstr "Le fichier PDF ne doit pas avoir plus de 2 pages."
@ -797,28 +797,28 @@ msgstr "finale"
msgid "Google Sheet ID" msgid "Google Sheet ID"
msgstr "ID de la feuille Google Sheets" msgstr "ID de la feuille Google Sheets"
#: participation/models.py:657 registration/admin.py:125 #: participation/models.py:649 registration/admin.py:125
msgid "tournaments" msgid "tournaments"
msgstr "tournois" msgstr "tournois"
#: participation/models.py:686 #: participation/models.py:678
msgid "valid team" msgid "valid team"
msgstr "équipe valide" msgstr "équipe valide"
#: participation/models.py:687 #: participation/models.py:679
msgid "The participation got the validation of the organizers." msgid "The participation got the validation of the organizers."
msgstr "La participation a été validée par les organisateur⋅rices." msgstr "La participation a été validée par les organisateur⋅rices."
#: participation/models.py:693 #: participation/models.py:685
msgid "The team is selected for the final tournament." msgid "The team is selected for the final tournament."
msgstr "L'équipe est sélectionnée pour la finale." msgstr "L'équipe est sélectionnée pour la finale."
#: participation/models.py:700 #: participation/models.py:692
#, python-brace-format #, python-brace-format
msgid "Participation of the team {name} ({trigram})" msgid "Participation of the team {name} ({trigram})"
msgstr "Participation de l'équipe {name} ({trigram})" msgstr "Participation de l'équipe {name} ({trigram})"
#: participation/models.py:707 #: participation/models.py:699
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>The team {trigram} has {nb_missing_payments} missing payments. Each " "<p>The team {trigram} has {nb_missing_payments} missing payments. Each "
@ -831,11 +831,11 @@ msgstr ""
"notification de bourse) pour participer au tournoi.</p><p>Les participant⋅es " "notification de bourse) pour participer au tournoi.</p><p>Les participant⋅es "
"qui n'ont pas encore payé sont : {participants}.</p>" "qui n'ont pas encore payé sont : {participants}.</p>"
#: participation/models.py:715 #: participation/models.py:707
msgid "Missing payments" msgid "Missing payments"
msgstr "Paiements manquants" msgstr "Paiements manquants"
#: participation/models.py:722 #: participation/models.py:714
msgid "" msgid ""
"<p>The solutions for the tournament of {tournament} are due on the {date:%Y-" "<p>The solutions for the tournament of {tournament} are due on the {date:%Y-"
"%m-%d %H:%M}.</p><p>You have currently sent <strong>{nb_solutions}</strong> " "%m-%d %H:%M}.</p><p>You have currently sent <strong>{nb_solutions}</strong> "
@ -850,11 +850,11 @@ msgstr ""
"pouvez envoyer vos solutions sur <a href='{url}'>votre page de " "pouvez envoyer vos solutions sur <a href='{url}'>votre page de "
"participation</a>.</p>" "participation</a>.</p>"
#: participation/models.py:731 #: participation/models.py:723
msgid "Solutions due" msgid "Solutions due"
msgstr "Rendu des solutions" msgstr "Rendu des solutions"
#: participation/models.py:737 registration/models.py:518 #: participation/models.py:729 registration/models.py:518
msgid "" msgid ""
"<p>The draw of the solutions for the tournament {tournament} is planned on " "<p>The draw of the solutions for the tournament {tournament} is planned on "
"the {date:%Y-%m-%d %H:%M}. You can join it on <a href='{url}'>this link</a>." "the {date:%Y-%m-%d %H:%M}. You can join it on <a href='{url}'>this link</a>."
@ -864,11 +864,11 @@ msgstr ""
"{date:%d/%m/%Y %H:%M}. Vous pouvez y participer sur <a href='{url}'>ce lien</" "{date:%d/%m/%Y %H:%M}. Vous pouvez y participer sur <a href='{url}'>ce lien</"
"a>.</p>" "a>.</p>"
#: participation/models.py:743 registration/models.py:525 #: participation/models.py:735 registration/models.py:525
msgid "Draw of solutions" msgid "Draw of solutions"
msgstr "Tirage au sort des solutions" msgstr "Tirage au sort des solutions"
#: participation/models.py:754 #: participation/models.py:746
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>The solutions draw is ended. You can check the result on <a " "<p>The solutions draw is ended. You can check the result on <a "
@ -880,7 +880,7 @@ msgstr ""
"tour, vous défendrez <a href='{solution_url}'>votre solution du problème " "tour, vous défendrez <a href='{solution_url}'>votre solution du problème "
"{problem}</a>.</p>" "{problem}</a>.</p>"
#: participation/models.py:763 participation/models.py:806 #: participation/models.py:755 participation/models.py:798
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>You will oppose the solution of the team {opponent} on the <a " "<p>You will oppose the solution of the team {opponent} on the <a "
@ -891,7 +891,7 @@ msgstr ""
"href='{solution_url}'>problème {problem}</a>. Vous pouvez envoyer votre note " "href='{solution_url}'>problème {problem}</a>. Vous pouvez envoyer votre note "
"de synthèse sur <a href='{passage_url}'>cette page</a>.</p>" "de synthèse sur <a href='{passage_url}'>cette page</a>.</p>"
#: participation/models.py:772 participation/models.py:815 #: participation/models.py:764 participation/models.py:807
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>You will report the solution of the team {reporter} on the <a " "<p>You will report the solution of the team {reporter} on the <a "
@ -902,11 +902,11 @@ msgstr ""
"href='{solution_url}'>problème {problem}</a>. Vous pouvez envoyer votre note " "href='{solution_url}'>problème {problem}</a>. Vous pouvez envoyer votre note "
"de synthèse sur <a href='{passage_url}'>cette page</a>.</p>" "de synthèse sur <a href='{passage_url}'>cette page</a>.</p>"
#: participation/models.py:788 registration/models.py:540 #: participation/models.py:780 registration/models.py:540
msgid "First round" msgid "First round"
msgstr "Premier tour" msgstr "Premier tour"
#: participation/models.py:799 #: participation/models.py:791
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>For the second round, you will defend <a href='{solution_url}'>your " "<p>For the second round, you will defend <a href='{solution_url}'>your "
@ -915,11 +915,11 @@ msgstr ""
"<p>Pour le second tour, vous défendrez <a href='{solution_url}'>votre " "<p>Pour le second tour, vous défendrez <a href='{solution_url}'>votre "
"solution du problème {problem}</a>.</p>" "solution du problème {problem}</a>.</p>"
#: participation/models.py:831 registration/models.py:551 #: participation/models.py:823 registration/models.py:551
msgid "Second round" msgid "Second round"
msgstr "Second tour" msgstr "Second tour"
#: participation/models.py:837 #: participation/models.py:829
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>The tournament {tournament} is ended. You can check the results on the <a " "<p>The tournament {tournament} is ended. You can check the results on the <a "
@ -928,40 +928,40 @@ msgstr ""
"<p>Le tournoi {tournament} est terminé. Vous pouvez consulter les résultats " "<p>Le tournoi {tournament} est terminé. Vous pouvez consulter les résultats "
"sur la <a href='{url}'>page du tournoi</a>.</p>" "sur la <a href='{url}'>page du tournoi</a>.</p>"
#: participation/models.py:842 #: participation/models.py:834
msgid "Tournament ended" msgid "Tournament ended"
msgstr "Tournoi terminé" msgstr "Tournoi terminé"
#: participation/models.py:852 participation/models.py:885 #: participation/models.py:844 participation/models.py:877
msgid "participations" msgid "participations"
msgstr "participations" msgstr "participations"
#: participation/models.py:867 participation/models.py:868 #: participation/models.py:859 participation/models.py:860
#, python-brace-format #, python-brace-format
msgid "Round {round}" msgid "Round {round}"
msgstr "Tour {round}" msgstr "Tour {round}"
#: participation/models.py:891 #: participation/models.py:883
msgid "juries" msgid "juries"
msgstr "jurys" msgstr "jurys"
#: participation/models.py:900 #: participation/models.py:892
msgid "president of the jury" msgid "president of the jury"
msgstr "président⋅e du jury" msgstr "président⋅e du jury"
#: participation/models.py:907 #: participation/models.py:899
msgid "BigBlueButton URL" msgid "BigBlueButton URL"
msgstr "Lien BigBlueButton" msgstr "Lien BigBlueButton"
#: participation/models.py:908 #: participation/models.py:900
msgid "The link of the BBB visio for this pool." msgid "The link of the BBB visio for this pool."
msgstr "Le lien du salon BBB pour cette poule." msgstr "Le lien du salon BBB pour cette poule."
#: participation/models.py:913 #: participation/models.py:905
msgid "results available" msgid "results available"
msgstr "résultats disponibles" msgstr "résultats disponibles"
#: participation/models.py:914 #: participation/models.py:906
msgid "" msgid ""
"Check this case when results become accessible to teams. They stay " "Check this case when results become accessible to teams. They stay "
"accessible to you. Only averages are given." "accessible to you. Only averages are given."
@ -970,37 +970,37 @@ msgstr ""
"Ils restent toujours accessibles pour vous. Seules les moyennes sont " "Ils restent toujours accessibles pour vous. Seules les moyennes sont "
"communiquées." "communiquées."
#: participation/models.py:939 #: participation/models.py:931
msgid "The president of the jury must be part of the jury." msgid "The president of the jury must be part of the jury."
msgstr "Læ président⋅e du jury doit faire partie du jury." msgstr "Læ président⋅e du jury doit faire partie du jury."
#: participation/models.py:1331 #: participation/models.py:1323
#, python-brace-format #, python-brace-format
msgid "The jury {jury} is not part of the jury for this pool." msgid "The jury {jury} is not part of the jury for this pool."
msgstr "{jury} ne fait pas partie du jury pour cette poule." msgstr "{jury} ne fait pas partie du jury pour cette poule."
#: participation/models.py:1344 #: participation/models.py:1334
#, python-brace-format #, python-brace-format
msgid "Pool of day {round} for tournament {tournament} with teams {teams}" msgid "Pool of day {round} for tournament {tournament} with teams {teams}"
msgstr "Poule du jour {round} du tournoi {tournament} avec les équipes {teams}" msgstr "Poule du jour {round} du tournoi {tournament} avec les équipes {teams}"
#: participation/models.py:1364 #: participation/models.py:1354
msgid "position" msgid "position"
msgstr "position" msgstr "position"
#: participation/models.py:1371 #: participation/models.py:1361
msgid "defended solution" msgid "defended solution"
msgstr "solution défendue" msgstr "solution défendue"
#: participation/models.py:1404 #: participation/models.py:1394
msgid "observer" msgid "observer"
msgstr "observateur⋅rice" msgstr "observateur⋅rice"
#: participation/models.py:1409 #: participation/models.py:1399
msgid "penalties" msgid "penalties"
msgstr "pénalités" msgstr "pénalités"
#: participation/models.py:1411 #: participation/models.py:1401
msgid "" msgid ""
"Number of penalties for the defender. The defender will loose a 0.5 " "Number of penalties for the defender. The defender will loose a 0.5 "
"coefficient per penalty." "coefficient per penalty."
@ -1008,124 +1008,124 @@ msgstr ""
"Nombre de pénalités pour l'équipe défenseuse. Elle perd un coefficient 0.5 " "Nombre de pénalités pour l'équipe défenseuse. Elle perd un coefficient 0.5 "
"sur sa présentation orale par pénalité." "sur sa présentation orale par pénalité."
#: participation/models.py:1487 participation/models.py:1490 #: participation/models.py:1477 participation/models.py:1480
#: participation/models.py:1493 participation/models.py:1496 #: participation/models.py:1483 participation/models.py:1486
#, python-brace-format #, python-brace-format
msgid "Team {trigram} is not registered in the pool." msgid "Team {trigram} is not registered in the pool."
msgstr "L'équipe {trigram} n'est pas inscrite dans la poule." msgstr "L'équipe {trigram} n'est pas inscrite dans la poule."
#: participation/models.py:1501 #: participation/models.py:1491
#, python-brace-format #, python-brace-format
msgid "Passage of {defender} for problem {problem}" msgid "Passage of {defender} for problem {problem}"
msgstr "Passage de {defender} pour le problème {problem}" msgstr "Passage de {defender} pour le problème {problem}"
#: participation/models.py:1505 participation/models.py:1514 #: participation/models.py:1495 participation/models.py:1504
#: participation/models.py:1599 participation/models.py:1641 #: participation/models.py:1589 participation/models.py:1631
msgid "passage" msgid "passage"
msgstr "passage" msgstr "passage"
#: participation/models.py:1506 #: participation/models.py:1496
msgid "passages" msgid "passages"
msgstr "passages" msgstr "passages"
#: participation/models.py:1525 #: participation/models.py:1515
msgid "difference" msgid "difference"
msgstr "différence" msgstr "différence"
#: participation/models.py:1526 #: participation/models.py:1516
msgid "Score to add/remove on the final score" msgid "Score to add/remove on the final score"
msgstr "Score à ajouter/retrancher au score final" msgstr "Score à ajouter/retrancher au score final"
#: participation/models.py:1533 #: participation/models.py:1523
msgid "tweak" msgid "tweak"
msgstr "harmonisation" msgstr "harmonisation"
#: participation/models.py:1534 #: participation/models.py:1524
msgid "tweaks" msgid "tweaks"
msgstr "harmonisations" msgstr "harmonisations"
#: participation/models.py:1562 #: participation/models.py:1552
msgid "solution for the final tournament" msgid "solution for the final tournament"
msgstr "solution pour la finale" msgstr "solution pour la finale"
#: participation/models.py:1567 participation/models.py:1610 #: participation/models.py:1557 participation/models.py:1600
msgid "file" msgid "file"
msgstr "fichier" msgstr "fichier"
#: participation/models.py:1577 #: participation/models.py:1567
#, python-brace-format #, python-brace-format
msgid "Solution of team {team} for problem {problem}" msgid "Solution of team {team} for problem {problem}"
msgstr "Solution de l'équipe {team} pour le problème {problem}" msgstr "Solution de l'équipe {team} pour le problème {problem}"
#: participation/models.py:1579 #: participation/models.py:1569
msgid "for final" msgid "for final"
msgstr "pour la finale" msgstr "pour la finale"
#: participation/models.py:1582 #: participation/models.py:1572
msgid "solution" msgid "solution"
msgstr "solution" msgstr "solution"
#: participation/models.py:1583 #: participation/models.py:1573
msgid "solutions" msgid "solutions"
msgstr "solutions" msgstr "solutions"
#: participation/models.py:1616 #: participation/models.py:1606
#, python-brace-format #, python-brace-format
msgid "Synthesis of {team} as {type} for problem {problem} of {defender}" msgid "Synthesis of {team} as {type} for problem {problem} of {defender}"
msgstr "" msgstr ""
"Note de synthèse de l'équipe {team} en tant que {type} pour le problème " "Note de synthèse de l'équipe {team} en tant que {type} pour le problème "
"{problem} de {defender}" "{problem} de {defender}"
#: participation/models.py:1624 #: participation/models.py:1614
msgid "synthesis" msgid "synthesis"
msgstr "note de synthèse" msgstr "note de synthèse"
#: participation/models.py:1625 #: participation/models.py:1615
msgid "syntheses" msgid "syntheses"
msgstr "notes de synthèse" msgstr "notes de synthèse"
#: participation/models.py:1634 #: participation/models.py:1624
msgid "jury" msgid "jury"
msgstr "jury" msgstr "jury"
#: participation/models.py:1646 #: participation/models.py:1636
msgid "defender writing note" msgid "defender writing note"
msgstr "note d'écrit défenseur⋅se" msgstr "note d'écrit défenseur⋅se"
#: participation/models.py:1652 #: participation/models.py:1642
msgid "defender oral note" msgid "defender oral note"
msgstr "note d'oral défenseur⋅se" msgstr "note d'oral défenseur⋅se"
#: participation/models.py:1658 #: participation/models.py:1648
msgid "opponent writing note" msgid "opponent writing note"
msgstr "note d'écrit opposant⋅e" msgstr "note d'écrit opposant⋅e"
#: participation/models.py:1664 #: participation/models.py:1654
msgid "opponent oral note" msgid "opponent oral note"
msgstr "note d'oral opposant⋅e" msgstr "note d'oral opposant⋅e"
#: participation/models.py:1670 #: participation/models.py:1660
msgid "reporter writing note" msgid "reporter writing note"
msgstr "note d'écrit rapporteur⋅rice" msgstr "note d'écrit rapporteur⋅rice"
#: participation/models.py:1676 #: participation/models.py:1666
msgid "reporter oral note" msgid "reporter oral note"
msgstr "note d'oral du rapporteur⋅rice" msgstr "note d'oral du rapporteur⋅rice"
#: participation/models.py:1682 #: participation/models.py:1672
msgid "observer note" msgid "observer note"
msgstr "note de l'observation" msgstr "note de l'observation"
#: participation/models.py:1743 #: participation/models.py:1733
#, python-brace-format #, python-brace-format
msgid "Notes of {jury} for {passage}" msgid "Notes of {jury} for {passage}"
msgstr "Notes de {jury} pour le {passage}" msgstr "Notes de {jury} pour le {passage}"
#: participation/models.py:1746 #: participation/models.py:1736
msgid "note" msgid "note"
msgstr "note" msgstr "note"
#: participation/models.py:1747 #: participation/models.py:1737
msgid "notes" msgid "notes"
msgstr "notes" msgstr "notes"
@ -1269,7 +1269,7 @@ msgstr "Envoyer une solution"
#: participation/templates/participation/pool_detail.html:162 #: participation/templates/participation/pool_detail.html:162
#: participation/templates/participation/team_detail.html:210 #: participation/templates/participation/team_detail.html:210
#: participation/templates/participation/upload_motivation_letter.html:13 #: participation/templates/participation/upload_motivation_letter.html:13
#: participation/templates/participation/upload_notes.html:24 #: participation/templates/participation/upload_notes.html:25
#: participation/templates/participation/upload_solution.html:11 #: participation/templates/participation/upload_solution.html:11
#: participation/templates/participation/upload_synthesis.html:18 #: participation/templates/participation/upload_synthesis.html:18
#: registration/templates/registration/upload_health_sheet.html:17 #: registration/templates/registration/upload_health_sheet.html:17
@ -1453,8 +1453,8 @@ msgid "Ranking"
msgstr "Classement" msgstr "Classement"
#: participation/templates/participation/pool_detail.html:136 #: participation/templates/participation/pool_detail.html:136
msgid "Upload notes from a spreadsheet file" msgid "Upload notes from a CSV file"
msgstr "Soumettre les notes à partir d'un tableur" msgstr "Soumettre les notes à partir d'un fichier CSV"
#: participation/templates/participation/pool_detail.html:140 #: participation/templates/participation/pool_detail.html:140
msgid "Download notation spreadsheet" msgid "Download notation spreadsheet"
@ -1658,7 +1658,7 @@ msgid "Invalidate"
msgstr "Invalider" msgstr "Invalider"
#: participation/templates/participation/team_detail.html:209 #: participation/templates/participation/team_detail.html:209
#: participation/views.py:332 #: participation/views.py:327
msgid "Upload motivation letter" msgid "Upload motivation letter"
msgstr "Envoyer la lettre de motivation" msgstr "Envoyer la lettre de motivation"
@ -1667,7 +1667,7 @@ msgid "Update team"
msgstr "Modifier l'équipe" msgstr "Modifier l'équipe"
#: participation/templates/participation/team_detail.html:219 #: participation/templates/participation/team_detail.html:219
#: participation/views.py:469 #: participation/views.py:464
msgid "Leave team" msgid "Leave team"
msgstr "Quitter l'équipe" msgstr "Quitter l'équipe"
@ -1820,12 +1820,14 @@ msgstr "Retour aux détails de l'utilisateur⋅rice"
#: participation/templates/participation/upload_notes.html:11 #: participation/templates/participation/upload_notes.html:11
msgid "" msgid ""
"Remember to export your spreadsheet as a CSV file before uploading it here. "
"Rows that are full of zeros are ignored. Unknown juries are not considered." "Rows that are full of zeros are ignored. Unknown juries are not considered."
msgstr "" msgstr ""
"Les lignes remplies de zéros sont ignorées. Les juré⋅es inconnu⋅es ne sont " "N'oubliez pas d'exporter votre tableur en tant que fichier CSV avant de le "
"pas pris⋅es en compte." "téléverser ici. Les lignes remplies de zéros sont ignorées. Les juré⋅es "
"inconnu⋅es ne sont pas pris⋅es en compte."
#: participation/templates/participation/upload_notes.html:18 #: participation/templates/participation/upload_notes.html:19
msgid "Download empty notation sheet" msgid "Download empty notation sheet"
msgstr "Télécharger la fiche de notation vierge" msgstr "Télécharger la fiche de notation vierge"
@ -1837,44 +1839,44 @@ msgstr "Modèles :"
msgid "Warning: non-free format" msgid "Warning: non-free format"
msgstr "Attention : format non libre" msgstr "Attention : format non libre"
#: participation/views.py:61 tfjm/templates/base.html:79 #: participation/views.py:56 tfjm/templates/base.html:79
#: tfjm/templates/navbar.html:35 #: tfjm/templates/navbar.html:35
msgid "Create team" msgid "Create team"
msgstr "Créer une équipe" msgstr "Créer une équipe"
#: participation/views.py:70 participation/views.py:111 #: participation/views.py:65 participation/views.py:106
msgid "You don't participate, so you can't create a team." msgid "You don't participate, so you can't create a team."
msgstr "Vous ne participez pas, vous ne pouvez pas créer d'équipe." msgstr "Vous ne participez pas, vous ne pouvez pas créer d'équipe."
#: participation/views.py:72 participation/views.py:113 #: participation/views.py:67 participation/views.py:108
msgid "You are already in a team." msgid "You are already in a team."
msgstr "Vous êtes déjà dans une équipe." msgstr "Vous êtes déjà dans une équipe."
#: participation/views.py:102 tfjm/templates/base.html:74 #: participation/views.py:97 tfjm/templates/base.html:74
#: tfjm/templates/navbar.html:40 #: tfjm/templates/navbar.html:40
msgid "Join team" msgid "Join team"
msgstr "Rejoindre une équipe" msgstr "Rejoindre une équipe"
#: participation/views.py:162 participation/views.py:507 #: participation/views.py:157 participation/views.py:502
msgid "You don't participate, so you don't have any team." msgid "You don't participate, so you don't have any team."
msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe." msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe."
#: participation/views.py:188 #: participation/views.py:183
#, python-brace-format #, python-brace-format
msgid "Detail of team {trigram}" msgid "Detail of team {trigram}"
msgstr "Détails de l'équipe {trigram}" msgstr "Détails de l'équipe {trigram}"
#: participation/views.py:217 #: participation/views.py:212
msgid "You don't participate, so you can't request the validation of the team." msgid "You don't participate, so you can't request the validation of the team."
msgstr "" msgstr ""
"Vous ne participez pas, vous ne pouvez pas demander la validation de " "Vous ne participez pas, vous ne pouvez pas demander la validation de "
"l'équipe." "l'équipe."
#: participation/views.py:220 #: participation/views.py:215
msgid "The validation of the team is already done or pending." msgid "The validation of the team is already done or pending."
msgstr "La validation de l'équipe est déjà faite ou en cours." msgstr "La validation de l'équipe est déjà faite ou en cours."
#: participation/views.py:223 #: participation/views.py:218
msgid "" msgid ""
"The team can't be validated: missing email address confirmations, " "The team can't be validated: missing email address confirmations, "
"authorizations, people, motivation letter or the tournament is not set." "authorizations, people, motivation letter or the tournament is not set."
@ -1883,167 +1885,167 @@ msgstr ""
"d'adresse e-mail, soit une autorisation, soit des personnes, soit la lettre " "d'adresse e-mail, soit une autorisation, soit des personnes, soit la lettre "
"de motivation, soit le tournoi n'a pas été choisi." "de motivation, soit le tournoi n'a pas été choisi."
#: participation/views.py:245 #: participation/views.py:240
msgid "You are not an organizer of the tournament." msgid "You are not an organizer of the tournament."
msgstr "Vous n'êtes pas un⋅e organisateur⋅rice du tournoi." msgstr "Vous n'êtes pas un⋅e organisateur⋅rice du tournoi."
#: participation/views.py:248 #: participation/views.py:243
msgid "This team has no pending validation." msgid "This team has no pending validation."
msgstr "L'équipe n'a pas de validation en attente." msgstr "L'équipe n'a pas de validation en attente."
#: participation/views.py:275 #: participation/views.py:270
msgid "You must specify if you validate the registration or not." msgid "You must specify if you validate the registration or not."
msgstr "Vous devez spécifier si vous validez l'inscription ou non." msgstr "Vous devez spécifier si vous validez l'inscription ou non."
#: participation/views.py:310 #: participation/views.py:305
#, python-brace-format #, python-brace-format
msgid "Update team {trigram}" msgid "Update team {trigram}"
msgstr "Mise à jour de l'équipe {trigram}" msgstr "Mise à jour de l'équipe {trigram}"
#: participation/views.py:371 participation/views.py:454 #: participation/views.py:366 participation/views.py:449
#, python-brace-format #, python-brace-format
msgid "Motivation letter of {team}.{ext}" msgid "Motivation letter of {team}.{ext}"
msgstr "Lettre de motivation de {team}.{ext}" msgstr "Lettre de motivation de {team}.{ext}"
#: participation/views.py:403 #: participation/views.py:398
#, python-brace-format #, python-brace-format
msgid "Authorizations of team {trigram}.zip" msgid "Authorizations of team {trigram}.zip"
msgstr "Autorisations de l'équipe {trigram}.zip" msgstr "Autorisations de l'équipe {trigram}.zip"
#: participation/views.py:407 #: participation/views.py:402
#, python-brace-format #, python-brace-format
msgid "Authorizations of {tournament}.zip" msgid "Authorizations of {tournament}.zip"
msgstr "Autorisations du tournoi {tournament}.zip" msgstr "Autorisations du tournoi {tournament}.zip"
#: participation/views.py:423 #: participation/views.py:418
#, python-brace-format #, python-brace-format
msgid "Photo authorization of {participant}.{ext}" msgid "Photo authorization of {participant}.{ext}"
msgstr "Autorisation de droit à l'image de {participant}.{ext}" msgstr "Autorisation de droit à l'image de {participant}.{ext}"
#: participation/views.py:431 #: participation/views.py:426
#, python-brace-format #, python-brace-format
msgid "Parental authorization of {participant}.{ext}" msgid "Parental authorization of {participant}.{ext}"
msgstr "Autorisation parentale de {participant}.{ext}" msgstr "Autorisation parentale de {participant}.{ext}"
#: participation/views.py:439 #: participation/views.py:434
#, python-brace-format #, python-brace-format
msgid "Health sheet of {participant}.{ext}" msgid "Health sheet of {participant}.{ext}"
msgstr "Fiche sanitaire de {participant}.{ext}" msgstr "Fiche sanitaire de {participant}.{ext}"
#: participation/views.py:447 #: participation/views.py:442
#, python-brace-format #, python-brace-format
msgid "Vaccine sheet of {participant}.{ext}" msgid "Vaccine sheet of {participant}.{ext}"
msgstr "Carnet de vaccination de {participant}.{ext}" msgstr "Carnet de vaccination de {participant}.{ext}"
#: participation/views.py:521 #: participation/views.py:516
msgid "The team is not validated yet." msgid "The team is not validated yet."
msgstr "L'équipe n'est pas encore validée." msgstr "L'équipe n'est pas encore validée."
#: participation/views.py:535 #: participation/views.py:530
#, python-brace-format #, python-brace-format
msgid "Participation of team {trigram}" msgid "Participation of team {trigram}"
msgstr "Participation de l'équipe {trigram}" msgstr "Participation de l'équipe {trigram}"
#: participation/views.py:617 #: participation/views.py:612
#, python-brace-format #, python-brace-format
msgid "Payments of {tournament}" msgid "Payments of {tournament}"
msgstr "Paiements de {tournament}" msgstr "Paiements de {tournament}"
#: participation/views.py:713 #: participation/views.py:708
msgid "Notes published!" msgid "Notes published!"
msgstr "Notes publiées !" msgstr "Notes publiées !"
#: participation/views.py:715 #: participation/views.py:710
msgid "Notes hidden!" msgid "Notes hidden!"
msgstr "Notes dissimulées !" msgstr "Notes dissimulées !"
#: participation/views.py:746 #: participation/views.py:741
#, python-brace-format #, python-brace-format
msgid "Harmonize notes of {tournament} - Day {round}" msgid "Harmonize notes of {tournament} - Day {round}"
msgstr "Harmoniser les notes de {tournament} - Jour {round}" msgstr "Harmoniser les notes de {tournament} - Jour {round}"
#: participation/views.py:827 #: participation/views.py:822
msgid "You can't upload a solution after the deadline." msgid "You can't upload a solution after the deadline."
msgstr "Vous ne pouvez pas envoyer de solution après la date limite." msgstr "Vous ne pouvez pas envoyer de solution après la date limite."
#: participation/views.py:944 #: participation/views.py:939
#, python-brace-format #, python-brace-format
msgid "Solutions of team {trigram}.zip" msgid "Solutions of team {trigram}.zip"
msgstr "Solutions de l'équipe {trigram}.zip" msgstr "Solutions de l'équipe {trigram}.zip"
#: participation/views.py:944 #: participation/views.py:939
#, python-brace-format #, python-brace-format
msgid "Syntheses of team {trigram}.zip" msgid "Syntheses of team {trigram}.zip"
msgstr "Notes de synthèse de l'équipe {trigram}.zip" msgstr "Notes de synthèse de l'équipe {trigram}.zip"
#: participation/views.py:961 participation/views.py:976 #: participation/views.py:956 participation/views.py:971
#, python-brace-format #, python-brace-format
msgid "Solutions of {tournament}.zip" msgid "Solutions of {tournament}.zip"
msgstr "Solutions de {tournament}.zip" msgstr "Solutions de {tournament}.zip"
#: participation/views.py:961 participation/views.py:976 #: participation/views.py:956 participation/views.py:971
#, python-brace-format #, python-brace-format
msgid "Syntheses of {tournament}.zip" msgid "Syntheses of {tournament}.zip"
msgstr "Notes de synthèse de {tournament}.zip" msgstr "Notes de synthèse de {tournament}.zip"
#: participation/views.py:985 #: participation/views.py:980
#, python-brace-format #, python-brace-format
msgid "Solutions for pool {pool} of tournament {tournament}.zip" msgid "Solutions for pool {pool} of tournament {tournament}.zip"
msgstr "Solutions pour la poule {pool} du tournoi {tournament}.zip" msgstr "Solutions pour la poule {pool} du tournoi {tournament}.zip"
#: participation/views.py:986 #: participation/views.py:981
#, python-brace-format #, python-brace-format
msgid "Syntheses for pool {pool} of tournament {tournament}.zip" msgid "Syntheses for pool {pool} of tournament {tournament}.zip"
msgstr "Notes de synthèses pour la poule {pool} du tournoi {tournament}.zip" msgstr "Notes de synthèses pour la poule {pool} du tournoi {tournament}.zip"
#: participation/views.py:1028 #: participation/views.py:1023
#, python-brace-format #, python-brace-format
msgid "Jury of pool {pool} for {tournament} with teams {teams}" msgid "Jury of pool {pool} for {tournament} with teams {teams}"
msgstr "Jury de la poule {pool} pour {tournament} avec les équipes {teams}" msgstr "Jury de la poule {pool} pour {tournament} avec les équipes {teams}"
#: participation/views.py:1044 #: participation/views.py:1039
#, python-brace-format #, python-brace-format
msgid "The jury {name} is already in the pool!" msgid "The jury {name} is already in the pool!"
msgstr "{name} est déjà dans la poule !" msgstr "{name} est déjà dans la poule !"
#: participation/views.py:1064 #: participation/views.py:1059
msgid "New TFJM² jury account" msgid "New TFJM² jury account"
msgstr "Nouveau compte de juré⋅e pour le TFJM²" msgstr "Nouveau compte de juré⋅e pour le TFJM²"
#: participation/views.py:1085 #: participation/views.py:1080
#, python-brace-format #, python-brace-format
msgid "The jury {name} has been successfully added!" msgid "The jury {name} has been successfully added!"
msgstr "{name} a été ajouté⋅e avec succès en tant que juré⋅e !" msgstr "{name} a été ajouté⋅e avec succès en tant que juré⋅e !"
#: participation/views.py:1121 #: participation/views.py:1116
#, python-brace-format #, python-brace-format
msgid "The jury {name} has been successfully removed!" msgid "The jury {name} has been successfully removed!"
msgstr "{name} a été retiré⋅e avec succès du jury !" msgstr "{name} a été retiré⋅e avec succès du jury !"
#: participation/views.py:1147 #: participation/views.py:1142
#, python-brace-format #, python-brace-format
msgid "The jury {name} has been successfully promoted president!" msgid "The jury {name} has been successfully promoted president!"
msgstr "{name} a été nommé⋅e président⋅e du jury !" msgstr "{name} a été nommé⋅e président⋅e du jury !"
#: participation/views.py:1175 #: participation/views.py:1170
msgid "The following user is not registered as a jury:" msgid "The following user is not registered as a jury:"
msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :" msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :"
#: participation/views.py:1192 #: participation/views.py:1187
msgid "Notes were successfully uploaded." msgid "Notes were successfully uploaded."
msgstr "Les notes ont bien été envoyées." msgstr "Les notes ont bien été envoyées."
#: participation/views.py:1825 #: participation/views.py:1820
#, python-brace-format #, python-brace-format
msgid "Notation sheets of pool {pool} of {tournament}.zip" msgid "Notation sheets of pool {pool} of {tournament}.zip"
msgstr "Feuilles de notations pour la poule {pool} du tournoi {tournament}.zip" msgstr "Feuilles de notations pour la poule {pool} du tournoi {tournament}.zip"
#: participation/views.py:1830 #: participation/views.py:1825
#, python-brace-format #, python-brace-format
msgid "Notation sheets of {tournament}.zip" msgid "Notation sheets of {tournament}.zip"
msgstr "Feuilles de notation de {tournament}.zip" msgstr "Feuilles de notation de {tournament}.zip"
#: participation/views.py:2007 #: participation/views.py:1976
msgid "You can't upload a synthesis after the deadline." msgid "You can't upload a synthesis after the deadline."
msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite." msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite."

View File

@ -2,7 +2,6 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import csv import csv
import math
from io import StringIO from io import StringIO
import re import re
from typing import Iterable from typing import Iterable
@ -14,7 +13,6 @@ from django.contrib.auth.models import User
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import FileExtensionValidator from django.core.validators import FileExtensionValidator
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
import pandas
from pypdf import PdfReader from pypdf import PdfReader
from registration.models import VolunteerRegistration from registration.models import VolunteerRegistration
@ -243,50 +241,50 @@ class AddJuryForm(forms.ModelForm):
class UploadNotesForm(forms.Form): class UploadNotesForm(forms.Form):
file = forms.FileField( file = forms.FileField(
label=_("Spreadsheet file:"), label=_("CSV file:"),
validators=[FileExtensionValidator(allowed_extensions=["csv", "ods"])], validators=[FileExtensionValidator(allowed_extensions=["csv"])],
) )
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['file'].widget.attrs['accept'] = 'text/csv,application/vnd.oasis.opendocument.spreadsheet' self.fields['file'].widget.attrs['accept'] = 'text/csv'
def clean(self): def clean(self):
cleaned_data = super().clean() cleaned_data = super().clean()
if 'file' in cleaned_data: if 'file' in cleaned_data:
file = cleaned_data['file'] file = cleaned_data['file']
if file.name.endswith('.csv'): with file:
with file: try:
data: bytes = file.read()
try: try:
data: bytes = file.read() content = data.decode()
try:
content = data.decode()
except UnicodeDecodeError:
# This is not UTF-8, grrrr
content = data.decode('latin1')
table = pandas.read_csv(StringIO(content), sep=None, header=None)
self.process(table, cleaned_data)
except UnicodeDecodeError: except UnicodeDecodeError:
self.add_error('file', _("This file contains non-UTF-8 and non-ISO-8859-1 content. " # This is not UTF-8, grrrr
"Please send your sheet as a CSV file.")) content = data.decode('latin1')
elif file.name.endswith('.ods'): for delimiter in [',', ';', '\t', '|']:
table = pandas.read_excel(file, header=None, engine='odf') if content.split('\n')[0].count(delimiter) > 1:
self.process(table, cleaned_data) break
else:
self.add_error('file',
_("Unable to detect the CSV delimiter. Please use a comma-separated file."))
return cleaned_data
csvfile = csv.reader(StringIO(content), delimiter=delimiter)
self.process(csvfile, cleaned_data)
except UnicodeDecodeError:
self.add_error('file', _("This file contains non-UTF-8 and non-ISO-8859-1 content. "
"Please send your sheet as a CSV file."))
return cleaned_data return cleaned_data
def process(self, df: pandas.DataFrame, cleaned_data: dict): def process(self, csvfile: Iterable[str], cleaned_data: dict):
parsed_notes = {} parsed_notes = {}
valid_lengths = [2 + 6 * 3, 2 + 7 * 4, 2 + 6 * 5] # Per pool sizes valid_lengths = [2 + 6 * 3, 2 + 7 * 4, 2 + 6 * 5] # Per pool sizes
pool_size = 0 pool_size = 0
line_length = 0 line_length = 0
for line in df.values.tolist(): for line in csvfile:
# Remove NaN line = [s.strip() for s in line if s]
line = [s for s in line if s == s]
# Strip cases
line = [str(s).strip() for s in line if str(s)]
if line and line[0] == 'Problème': if line and line[0] == 'Problème':
pool_size = len(line) - 1 pool_size = len(line) - 1
if pool_size < 3 or pool_size > 5: if pool_size < 3 or pool_size > 5:
@ -299,12 +297,12 @@ class UploadNotesForm(forms.Form):
continue continue
name = line[0] name = line[0]
if name.lower() in ["rôle", "juré⋅e", "juré?e", "moyenne", "coefficient", "sous-total", "équipe", "equipe"]: if name.lower() in ["rôle", "juré", "moyenne", "coefficient", "sous-total", "équipe", "equipe"]:
continue continue
notes = line[2:line_length] notes = line[2:line_length]
if not all(s.isnumeric() or s[0] == '-' and s[1:].isnumeric() for s in notes): if not all(s.isnumeric() or s[0] == '-' and s[1:].isnumeric() for s in notes):
continue continue
notes = list(map(lambda x: int(float(x)), notes)) notes = list(map(int, notes))
max_notes = pool_size * ([20, 20, 10, 10, 10, 10] + ([4] if pool_size == 4 else [])) max_notes = pool_size * ([20, 20, 10, 10, 10, 10] + ([4] if pool_size == 4 else []))
for n, max_n in zip(notes, max_notes): for n, max_n in zip(notes, max_notes):
@ -314,7 +312,7 @@ class UploadNotesForm(forms.Form):
+ str(n) + " > " + str(max_n)) + str(n) + " > " + str(max_n))
# Search by volunteer id # Search by volunteer id
jury = VolunteerRegistration.objects.filter(pk=int(float(line[1]))) jury = VolunteerRegistration.objects.filter(pk=line[1])
if jury.count() != 1: if jury.count() != 1:
raise ValidationError({'file': _("The following user was not found:") + " " + name}) raise ValidationError({'file': _("The following user was not found:") + " " + name})
jury = jury.get() jury = jury.get()

View File

@ -45,7 +45,7 @@ class Command(BaseCommand):
self.style.WARNING(f"No spreadsheet found for {tournament}. Please create it first")) self.style.WARNING(f"No spreadsheet found for {tournament}. Please create it first"))
continue continue
channel_id = sha1(f"{tournament.name}-{now.date()}-{site.domain}".encode()).hexdigest() channel_id = sha1(f"{tournament.name}-{timezone.now().date()}-{site.domain}".encode()).hexdigest()
url = f"https://www.googleapis.com/drive/v3/files/{tournament.notes_sheet_id}/watch?supportsAllDrives=true" url = f"https://www.googleapis.com/drive/v3/files/{tournament.notes_sheet_id}/watch?supportsAllDrives=true"
notif_path = reverse('participation:tournament_gsheet_notifications', args=[tournament.pk]) notif_path = reverse('participation:tournament_gsheet_notifications', args=[tournament.pk])
notif_url = f"https://{site.domain}{notif_path}" notif_url = f"https://{site.domain}{notif_path}"

View File

@ -133,7 +133,7 @@
<div class="btn btn-group"> <div class="btn btn-group">
<button class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#uploadNotesModal"> <button class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#uploadNotesModal">
<i class="fas fa-upload"></i> <i class="fas fa-upload"></i>
{% trans "Upload notes from a spreadsheet file" %} {% trans "Upload notes from a CSV file" %}
</button> </button>
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_notes_template' pk=pool.pk %}"> <a class="btn btn-sm btn-info" href="{% url 'participation:pool_notes_template' pk=pool.pk %}">
<i class="fas fa-download"></i> <i class="fas fa-download"></i>

View File

@ -9,6 +9,7 @@
<div class="alert alert-warning"> <div class="alert alert-warning">
{% url 'participation:pool_jury' pk=pool.jury as jury_url %} {% url 'participation:pool_jury' pk=pool.jury as jury_url %}
{% blocktrans trimmed with jury_url=jury_url %} {% blocktrans trimmed with jury_url=jury_url %}
Remember to export your spreadsheet as a CSV file before uploading it here.
Rows that are full of zeros are ignored. Rows that are full of zeros are ignored.
Unknown juries are not considered. Unknown juries are not considered.
{% endblocktrans %} {% endblocktrans %}

View File

@ -13,10 +13,12 @@ django-polymorphic~=3.1.0
django-tables2~=2.7.0 django-tables2~=2.7.0
djangorestframework~=3.14.0 djangorestframework~=3.14.0
django-rest-polymorphic~=0.1.10 django-rest-polymorphic~=0.1.10
google-api-python-client~=2.124.0
google-auth-httplib2~=0.2.0
google-auth-oauthlib~=1.2.0
gspread~=6.1.0 gspread~=6.1.0
gunicorn~=21.2.0 gunicorn~=21.2.0
odfpy~=1.4.1 odfpy~=1.4.1
pandas~=2.2.1
phonenumbers~=8.13.27 phonenumbers~=8.13.27
psycopg2-binary~=2.9.9 psycopg2-binary~=2.9.9
pypdf~=3.17.4 pypdf~=3.17.4