Merge branch 'improvements' into 'master'

Improvements, bug fixes

See merge request animath/si/plateforme-corres2math!8
This commit is contained in:
Yohann D'ANELLO 2020-12-22 20:36:57 +00:00
commit 4ee5ac309d
14 changed files with 183 additions and 69 deletions

View File

@ -13,7 +13,9 @@ Bonjour {{ user.registration }},
L'équipe « {{ team.name }} » ({{ team.trigram }}) vient de demander à valider son équipe pour participer
au {{ team.participation.get_problem_display }} des Correspondances des Jeunes Mathématicien·ne·s.
Vous pouvez décider d'accepter ou de refuser l'équipe en vous rendant sur la page de l'équipe :
<a href="{% url "participation:team_detail" pk=team.pk %}">{% url "participation:team_detail" pk=team.pk %}</a>
<a href="https://{{ domain }}{% url "participation:team_detail" pk=team.pk %}">
https://{{ domain }}{% url "participation:team_detail" pk=team.pk %}
</a>
</p>
<p>

View File

@ -3,7 +3,7 @@ Bonjour {{ user.registration }},
L'équipe « {{ team.name }} » ({{ team.trigram }}) vient de demander à valider son équipe pour participer
au {{ team.participation.get_problem_display }} des Correspondances des Jeunes Mathématicien·ne·s.
Vous pouvez décider d'accepter ou de refuser l'équipe en vous rendant sur la page de l'équipe :
{% url "participation:team_detail" pk=team.pk %}
https://{{ domain }}{% url "participation:team_detail" pk=team.pk %}
Cordialement,

View File

@ -669,7 +669,7 @@ class TestStudentParticipation(TestCase):
def test_forbidden_access(self):
"""
Load personnal pages and ensure that these are protected.
Load personal pages and ensure that these are protected.
"""
self.user.registration.team = self.team
self.user.registration.save()

View File

@ -5,6 +5,7 @@ from corres2math.lists import get_sympa_client
from corres2math.matrix import Matrix
from corres2math.views import AdminMixin
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.sites.models import Site
from django.core.exceptions import PermissionDenied
from django.core.mail import send_mail
from django.db import transaction
@ -38,6 +39,8 @@ class CreateTeamView(LoginRequiredMixin, CreateView):
def dispatch(self, request, *args, **kwargs):
user = request.user
if not user.is_authenticated:
return super().handle_no_permission()
registration = user.registration
if not registration.participates:
raise PermissionDenied(_("You don't participate, so you can't create a team."))
@ -84,6 +87,8 @@ class JoinTeamView(LoginRequiredMixin, FormView):
def dispatch(self, request, *args, **kwargs):
user = request.user
if not user.is_authenticated:
return super().handle_no_permission()
registration = user.registration
if not registration.participates:
raise PermissionDenied(_("You don't participate, so you can't create a team."))
@ -208,7 +213,7 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
self.object.participation.save()
for admin in AdminRegistration.objects.all():
mail_context = dict(user=admin.user, team=self.object)
mail_context = dict(user=admin.user, team=self.object, domain=Site.objects.first().domain)
mail_plain = render_to_string("participation/mails/request_validation.txt", mail_context)
mail_html = render_to_string("participation/mails/request_validation.html", mail_context)
admin.user.email_user("[Corres2math] Validation d'équipe", mail_plain, html_message=mail_html)
@ -264,6 +269,8 @@ class TeamUpdateView(LoginRequiredMixin, UpdateView):
def dispatch(self, request, *args, **kwargs):
user = request.user
if not user.is_authenticated:
return super().handle_no_permission()
if user.registration.is_admin or user.registration.participates and \
user.registration.team and \
user.registration.team.pk == kwargs["pk"]:
@ -298,6 +305,8 @@ class TeamAuthorizationsView(LoginRequiredMixin, DetailView):
def dispatch(self, request, *args, **kwargs):
user = request.user
if not user.is_authenticated:
return super().handle_no_permission()
if user.registration.is_admin or user.registration.participates and user.registration.team.pk == kwargs["pk"]:
return super().dispatch(request, *args, **kwargs)
raise PermissionDenied
@ -376,6 +385,8 @@ class ParticipationDetailView(LoginRequiredMixin, DetailView):
def dispatch(self, request, *args, **kwargs):
user = request.user
if not user.is_authenticated:
return super().handle_no_permission()
if not self.get_object().valid:
raise PermissionDenied(_("The team is not validated yet."))
if user.registration.is_admin or user.registration.participates \
@ -500,6 +511,8 @@ class UploadVideoView(LoginRequiredMixin, UpdateView):
def dispatch(self, request, *args, **kwargs):
user = request.user
if not user.is_authenticated:
return super().handle_no_permission()
if user.registration.is_admin or user.registration.participates \
and user.registration.team.participation.pk == self.get_object().participation.pk:
return super().dispatch(request, *args, **kwargs)

View File

@ -72,10 +72,13 @@ class PhotoAuthorizationForm(forms.ModelForm):
Form to send a photo authorization.
"""
def clean_photo_authorization(self):
file = self.files["photo_authorization"]
if file.content_type not in ["application/pdf", "image/png", "image/jpeg"]:
raise ValidationError(_("The uploaded file must be a PDF, PNG of JPEG file."))
return self.cleaned_data["photo_authorization"]
if "photo_authorization" in self.files:
file = self.files["photo_authorization"]
if file.size > 2e6:
raise ValidationError(_("The uploaded file size must be under 2 Mo."))
if file.content_type not in ["application/pdf", "image/png", "image/jpeg"]:
raise ValidationError(_("The uploaded file must be a PDF, PNG of JPEG file."))
return self.cleaned_data["photo_authorization"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

View File

@ -19,7 +19,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
</p>
{% else %}
<p>
{% trans "The link was invalid. The token may have expired. Please send us an email to activate your account." %}
{% if user.is_authenticated and user.registration.email_confirmed %}
{% trans "The link was invalid. The token may have expired, or your account is already activated. However, your account seems to be already valid." %}
{% else %}
{% trans "The link was invalid. The token may have expired, or your account is already activated. Please send us an email to activate your account." %}
{% endif %}
</p>
{% endif %}
</div>

View File

@ -5,13 +5,14 @@ from corres2math.tokens import email_validation_token
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.management import call_command
from django.test import TestCase
from django.urls import reverse
from django.utils import timezone
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
from participation.models import Phase
from participation.models import Phase, Team
from .models import AdminRegistration, CoachRegistration, StudentRegistration
@ -35,6 +36,24 @@ class TestIndexPage(TestCase):
response = self.client.get(reverse("registration:user_detail", args=(1,)))
self.assertRedirects(response, reverse("login") + "?next=" + reverse("registration:user_detail", args=(1,)))
Team.objects.create()
response = self.client.get(reverse("participation:team_detail", args=(1,)))
self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:team_detail", args=(1,)))
response = self.client.get(reverse("participation:update_team", args=(1,)))
self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:update_team", args=(1,)))
response = self.client.get(reverse("participation:create_team"))
self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:create_team"))
response = self.client.get(reverse("participation:join_team"))
self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:join_team"))
response = self.client.get(reverse("participation:team_authorizations", args=(1,)))
self.assertRedirects(response, reverse("login") + "?next="
+ reverse("participation:team_authorizations", args=(1,)))
response = self.client.get(reverse("participation:participation_detail", args=(1,)))
self.assertRedirects(response, reverse("login") + "?next="
+ reverse("participation:participation_detail", args=(1,)))
response = self.client.get(reverse("participation:upload_video", args=(1,)))
self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:upload_video", args=(1,)))
class TestRegistration(TestCase):
def setUp(self) -> None:
@ -268,6 +287,14 @@ class TestRegistration(TestCase):
))
self.assertEqual(response.status_code, 200)
# Don't send too large files
response = self.client.post(reverse("registration:upload_user_photo_authorization",
args=(self.student.registration.pk,)), data=dict(
photo_authorization=SimpleUploadedFile("file.pdf", content=int(0).to_bytes(2000001, "big"),
content_type="application/pdf"),
))
self.assertEqual(response.status_code, 200)
response = self.client.post(reverse("registration:upload_user_photo_authorization",
args=(self.student.registration.pk,)), data=dict(
photo_authorization=open("corres2math/static/Autorisation de droit à l'image - majeur.pdf", "rb"),

View File

@ -1,7 +1,5 @@
import os
from django_tables2 import SingleTableView
from corres2math.tokens import email_validation_token
from corres2math.views import AdminMixin
from django.conf import settings
@ -15,11 +13,12 @@ from django.urls import reverse_lazy
from django.utils.http import urlsafe_base64_decode
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, DetailView, RedirectView, TemplateView, UpdateView, View
from django_tables2 import SingleTableView
from magic import Magic
from participation.models import Phase
from .forms import CoachRegistrationForm, PhotoAuthorizationForm, SignupForm, StudentRegistrationForm, UserForm
from .models import StudentRegistration, Registration
from .models import Registration, StudentRegistration
from .tables import RegistrationTable

View File

@ -3,3 +3,6 @@
* * * * * cd /code && python manage.py send_mail -c 1
* * * * * cd /code && python manage.py retry_deferred -c 1
0 0 * * * cd /code && python manage.py purge_mail_log 7 -c 1
# Rebuild search index
0 * * * * cd /code && python manage.py update_index -v 0

View File

@ -0,0 +1,40 @@
{% extends "base.html" %}
{% block contenttitle %}
<h1>À propos</h1>
{% endblock %}
{% block content %}
<p>
La plateforme d'inscription des Correspondances des Jeunes Mathématiciennes a été développée entre 2019 et 2021
par Yohann D'ANELLO, bénévole pour l'association Animath. Elle est vouée à être utilisée par les participants
pour intéragir avec les organisateurs et les autres participants.
</p>
<p>
La plateforme est développée avec le framework <a href="https://www.djangoproject.com/">Django</a> et le code
source est accessible librement sur <a href="https://gitlab.com/animath/si/plateforme-corres2math">Gitlab</a>.
Le code est distribué sous la licence <a href="https://www.gnu.org/licenses/gpl-3.0.html">GNU GPL v3</a>,
qui vous autorise à consulter le code, à le partager, à réutiliser des parties du code et à contribuer.
</p>
<p>
Le site principal présent sur <a href="https://inscription.correspondances-maths.fr/">https://inscription.correspondances-maths.fr</a>
est hébergé chez <a href="https://www.scaleway.com/fr/">Scaleway</a>.
</p>
<p>
Les données collectées par cette plateforme sont utilisées uniquement dans le cadre des Correspondances et sont
détruites dès l'action touche à sa fin, soit au plus tard 1 an après le début de l'action. Sur autorisation
explicite, des informations de contact peuvent être conservées afin d'être tenu au courant des actions futures
de l'association Animath. Aucune information personnelle n'est collectée à votre insu. Aucune information
personnelle n'est cédée à des tiers.
</p>
<p>
Pour toute demande ou réclammation, merci de nous contacter à l'adresse
<a target="_blank" href="mailto:&#99;&#111;&#110;&#116;&#97;&#99;&#116;&#64;&#99;&#111;&#114;&#114;&#101;&#115;&#112;&#111;&#110;&#100;&#97;&#110;&#99;&#101;&#115;&#45;&#109;&#97;&#116;&#104;&#115;&#46;&#102;&#114;">
&#99;&#111;&#110;&#116;&#97;&#99;&#116;&#64;&#99;&#111;&#114;&#114;&#101;&#115;&#112;&#111;&#110;&#100;&#97;&#110;&#99;&#101;&#115;&#45;&#109;&#97;&#116;&#104;&#115;&#46;&#102;&#114;
</a>.
</p>
{% endblock %}

View File

@ -192,7 +192,7 @@
class="form-inline">
<span class="text-muted mr-1">
<a target="_blank" href="mailto:&#99;&#111;&#110;&#116;&#97;&#99;&#116;&#64;&#99;&#111;&#114;&#114;&#101;&#115;&#112;&#111;&#110;&#100;&#97;&#110;&#99;&#101;&#115;&#45;&#109;&#97;&#116;&#104;&#115;&#46;&#102;&#114;"
class="text-muted">{% trans "Contact us" %}</a> &mdash;
class="text-muted"><i class="fas fa-envelope"></i> {% trans "Contact us" %}</a>
</span>
{% csrf_token %}
<select title="language" name="language"
@ -207,10 +207,15 @@
{{ lang_name }} ({{ lang_code }})
</option>
{% endfor %}
</select>
</select> &nbsp;
<noscript>
<input type="submit">
</noscript>
</noscript> &nbsp;
<a target="_blank" class="text-muted" href="{% url "about" %}">{% trans "About" %}</a> &nbsp; &mdash; &nbsp;
<a target="_blank" class="text-muted"
href="https://gitlab.com/animath/si/plateforme-corres2math">
<i class="fab fa-gitlab"></i>
</a>
</form>
</div>
<div class="col text-right">

View File

@ -23,7 +23,8 @@ from registration.views import PhotoAuthorizationView
from .views import AdminSearchView
urlpatterns = [
path('', TemplateView.as_view(template_name="index.html", extra_context=dict(title="Accueil")), name='index'),
path('', TemplateView.as_view(template_name="index.html"), name='index'),
path('about/', TemplateView.as_view(template_name="about.html"), name='about'),
path('i18n/', include('django.conf.urls.i18n')),
path('admin/doc/', include('django.contrib.admindocs.urls')),
path('admin/', admin.site.urls, name="admin"),

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Corres2math\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-12-11 14:03+0100\n"
"POT-Creation-Date: 2020-12-22 21:30+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Yohann D'ANELLO <yohann.danello@animath.fr>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -324,12 +324,12 @@ msgstr ""
"contacter :)"
#: apps/participation/templates/participation/create_team.html:11
#: corres2math/templates/base.html:242
#: corres2math/templates/base.html:247
msgid "Create"
msgstr "Créer"
#: apps/participation/templates/participation/join_team.html:11
#: corres2math/templates/base.html:237
#: corres2math/templates/base.html:242
msgid "Join"
msgstr "Rejoindre"
@ -503,7 +503,7 @@ msgstr "Définir l'équipe qui recevra votre vidéo"
#: apps/participation/templates/participation/participation_detail.html:181
#: apps/participation/templates/participation/participation_detail.html:233
#: apps/participation/views.py:499
#: apps/participation/views.py:510
msgid "Upload video"
msgstr "Envoyer la vidéo"
@ -538,7 +538,7 @@ msgid "Update question"
msgstr "Modifier la question"
#: apps/participation/templates/participation/participation_detail.html:217
#: apps/participation/views.py:475
#: apps/participation/views.py:486
msgid "Delete question"
msgstr "Supprimer la question"
@ -548,8 +548,8 @@ msgid "Display synthesis"
msgstr "Afficher la synthèse"
#: apps/participation/templates/participation/phase_list.html:10
#: apps/participation/views.py:518 corres2math/templates/base.html:68
#: corres2math/templates/base.html:70 corres2math/templates/base.html:226
#: apps/participation/views.py:531 corres2math/templates/base.html:68
#: corres2math/templates/base.html:70 corres2math/templates/base.html:231
msgid "Calendar"
msgstr "Calendrier"
@ -661,7 +661,7 @@ msgid "Update team"
msgstr "Modifier l'équipe"
#: apps/participation/templates/participation/team_detail.html:127
#: apps/participation/views.py:328
#: apps/participation/views.py:337
msgid "Leave team"
msgstr "Quitter l'équipe"
@ -670,53 +670,53 @@ msgid "Are you sure that you want to leave this team?"
msgstr "Êtes-vous sûr·e de vouloir quitter cette équipe ?"
#: apps/participation/templates/participation/team_list.html:6
#: corres2math/templates/base.html:230
#: corres2math/templates/base.html:235
msgid "All teams"
msgstr "Toutes les équipes"
#: apps/participation/views.py:36 corres2math/templates/base.html:84
#: corres2math/templates/base.html:241
#: apps/participation/views.py:37 corres2math/templates/base.html:84
#: corres2math/templates/base.html:246
msgid "Create team"
msgstr "Créer une équipe"
#: apps/participation/views.py:43 apps/participation/views.py:89
#: apps/participation/views.py:46 apps/participation/views.py:94
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."
#: apps/participation/views.py:45 apps/participation/views.py:91
#: apps/participation/views.py:48 apps/participation/views.py:96
msgid "You are already in a team."
msgstr "Vous êtes déjà dans une équipe."
#: apps/participation/views.py:82 corres2math/templates/base.html:89
#: corres2math/templates/base.html:236
#: apps/participation/views.py:85 corres2math/templates/base.html:89
#: corres2math/templates/base.html:241
msgid "Join team"
msgstr "Rejoindre une équipe"
#: apps/participation/views.py:142 apps/participation/views.py:334
#: apps/participation/views.py:367
#: apps/participation/views.py:147 apps/participation/views.py:343
#: apps/participation/views.py:376
msgid "You are not in a team."
msgstr "Vous n'êtes pas dans une équipe."
#: apps/participation/views.py:143 apps/participation/views.py:368
#: apps/participation/views.py:148 apps/participation/views.py:377
msgid "You don't participate, so you don't have any team."
msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe."
#: apps/participation/views.py:165
#: apps/participation/views.py:170
#, python-brace-format
msgid "Detail of team {trigram}"
msgstr "Détails de l'équipe {trigram}"
#: apps/participation/views.py:197
#: apps/participation/views.py:202
msgid "You don't participate, so you can't request the validation of the team."
msgstr ""
"Vous ne participez pas, vous ne pouvez pas demander la validation de "
"l'équipe."
#: apps/participation/views.py:200
#: apps/participation/views.py:205
msgid "The validation of the team is already done or pending."
msgstr "La validation de l'équipe est déjà faite ou en cours."
#: apps/participation/views.py:203
#: apps/participation/views.py:208
msgid ""
"The team can't be validated: missing email address confirmations, photo "
"authorizations, people or the chosen problem is not set."
@ -725,51 +725,51 @@ msgstr ""
"d'adresse e-mail, soit une autorisation parentale, soit des personnes soit "
"le problème n'a pas été choisi."
#: apps/participation/views.py:222
#: apps/participation/views.py:227
msgid "You are not an administrator."
msgstr "Vous n'êtes pas administrateur."
#: apps/participation/views.py:225
#: apps/participation/views.py:230
msgid "This team has no pending validation."
msgstr "L'équipe n'a pas de validation en attente."
#: apps/participation/views.py:249
#: apps/participation/views.py:254
msgid "You must specify if you validate the registration or not."
msgstr "Vous devez spécifier si vous validez l'inscription ou non."
#: apps/participation/views.py:277
#: apps/participation/views.py:284
#, python-brace-format
msgid "Update team {trigram}"
msgstr "Mise à jour de l'équipe {trigram}"
#: apps/participation/views.py:314 apps/registration/views.py:284
#: apps/participation/views.py:323 apps/registration/views.py:283
#, python-brace-format
msgid "Photo authorization of {student}.{ext}"
msgstr "Autorisation de droit à l'image de {student}.{ext}"
#: apps/participation/views.py:318
#: apps/participation/views.py:327
#, python-brace-format
msgid "Photo authorizations of team {trigram}.zip"
msgstr "Autorisations de droit à l'image de l'équipe {trigram}.zip"
#: apps/participation/views.py:336
#: apps/participation/views.py:345
msgid "The team is already validated or the validation is pending."
msgstr "La validation de l'équipe est déjà faite ou en cours."
#: apps/participation/views.py:380
#: apps/participation/views.py:391
msgid "The team is not validated yet."
msgstr "L'équipe n'est pas encore validée."
#: apps/participation/views.py:390
#: apps/participation/views.py:401
#, python-brace-format
msgid "Participation of team {trigram}"
msgstr "Participation de l'équipe {trigram}"
#: apps/participation/views.py:427
#: apps/participation/views.py:438
msgid "Create question"
msgstr "Créer une question"
#: apps/participation/views.py:527
#: apps/participation/views.py:540
msgid "Calendar update"
msgstr "Mise à jour du calendrier"
@ -789,7 +789,11 @@ msgstr "encadrant"
msgid "This email address is already used."
msgstr "Cette adresse e-mail est déjà utilisée."
#: apps/registration/forms.py:77
#: apps/registration/forms.py:78
msgid "The uploaded file size must be under 2 Mo."
msgstr "Le fichier envoyé doit peser moins de 2 Mo."
#: apps/registration/forms.py:80
msgid "The uploaded file must be a PDF, PNG of JPEG file."
msgstr "Le fichier envoyé doit être au format PDF, PNG ou JPEG."
@ -891,13 +895,21 @@ msgstr "Votre email a été validé avec succès."
msgid "You can now <a href=\"%(login_url)s\">log in</a>."
msgstr "Vous pouvez désormais vous <a href=\"%(login_url)s\">connecter</a>."
#: apps/registration/templates/registration/email_validation_complete.html:22
#: apps/registration/templates/registration/email_validation_complete.html:23
msgid ""
"The link was invalid. The token may have expired. Please send us an email to "
"activate your account."
"The link was invalid. The token may have expired, or your account is already "
"activated. However, your account seems to be already valid."
msgstr ""
"Le lien est invalide. Le jeton a peut-être expiré. Merci de nous envoyer un "
"mail pour activer votre compte."
"Le lien est invalide. Le jeton a peut-être expiré, ou votre compte est déjà "
"activé. Toutefois, il semble que votre compte est déjà valide."
#: apps/registration/templates/registration/email_validation_complete.html:25
msgid ""
"The link was invalid. The token may have expired, or your account is already "
"activated. Please send us an email to activate your account."
msgstr ""
"Le lien est invalide. Le jeton a peut-être expiré, ou votre compte est déjà "
"activé. Merci de nous envoyer un mail pour activer votre compte."
#: apps/registration/templates/registration/email_validation_email_sent.html:10
msgid "Account activation"
@ -966,8 +978,8 @@ msgid "Your password has been set. You may go ahead and log in now."
msgstr "Votre mot de passe a été changé. Vous pouvez désormais vous connecter."
#: apps/registration/templates/registration/password_reset_complete.html:10
#: corres2math/templates/base.html:139 corres2math/templates/base.html:246
#: corres2math/templates/base.html:247
#: corres2math/templates/base.html:139 corres2math/templates/base.html:251
#: corres2math/templates/base.html:252
#: corres2math/templates/registration/login.html:7
#: corres2math/templates/registration/login.html:8
#: corres2math/templates/registration/login.html:25
@ -1024,7 +1036,7 @@ msgstr "Réinitialiser mon mot de passe"
#: apps/registration/templates/registration/signup.html:5
#: apps/registration/templates/registration/signup.html:8
#: apps/registration/templates/registration/signup.html:20
#: apps/registration/views.py:33
#: apps/registration/views.py:32
msgid "Sign up"
msgstr "Inscription"
@ -1101,40 +1113,40 @@ msgid "Update user"
msgstr "Modifier l'utilisateur"
#: apps/registration/templates/registration/user_detail.html:77
#: apps/registration/views.py:247
#: apps/registration/views.py:246
msgid "Upload photo authorization"
msgstr "Téléverser l'autorisation de droit à l'image"
#: apps/registration/views.py:41
#: apps/registration/views.py:40
msgid "You can't register now."
msgstr "Vous ne pouvez pas vous inscrire maintenant."
#: apps/registration/views.py:85
#: apps/registration/views.py:84
msgid "Email validation"
msgstr "Validation de l'adresse mail"
#: apps/registration/views.py:87
#: apps/registration/views.py:86
msgid "Validate email"
msgstr "Valider l'adresse mail"
#: apps/registration/views.py:126
#: apps/registration/views.py:125
msgid "Email validation unsuccessful"
msgstr "Échec de la validation de l'adresse mail"
#: apps/registration/views.py:137
#: apps/registration/views.py:136
msgid "Email validation email sent"
msgstr "Mail de confirmation de l'adresse mail envoyé"
#: apps/registration/views.py:145
#: apps/registration/views.py:144
msgid "Resend email validation link"
msgstr "Renvoyé le lien de validation de l'adresse mail"
#: apps/registration/views.py:181
#: apps/registration/views.py:180
#, python-brace-format
msgid "Detail of user {user}"
msgstr "Détails de l'utilisateur {user}"
#: apps/registration/views.py:211
#: apps/registration/views.py:210
#, python-brace-format
msgid "Update user {user}"
msgstr "Mise à jour de l'utilisateur {user}"
@ -1263,7 +1275,11 @@ msgstr ""
msgid "Contact us"
msgstr "Nous contacter"
#: corres2math/templates/base.html:233
#: corres2math/templates/base.html:214
msgid "About"
msgstr "À propos"
#: corres2math/templates/base.html:238
msgid "Search results"
msgstr "Résultats de la recherche"

View File

@ -5,6 +5,7 @@ upstream corres2math {
server {
listen 80;
server_name corres2math;
client_max_body_size 50M;
location / {
proxy_pass http://corres2math;