diff --git a/Dockerfile b/Dockerfile index 39e3aa5..fc59134 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ WORKDIR /code # Install LaTeX requirements RUN apt update && \ - apt install -y texlive-latex-extra texlive-fonts-extra texlive-lang-french && \ + apt install -y gettext texlive-latex-extra texlive-fonts-extra texlive-lang-french && \ rm -rf /var/lib/apt/lists/* COPY . /code/ diff --git a/apps/member/management/__init__.py b/apps/member/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/member/management/commands/__init__.py b/apps/member/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/member/management/commands/create_su.py b/apps/member/management/commands/create_su.py new file mode 100644 index 0000000..9d7df58 --- /dev/null +++ b/apps/member/management/commands/create_su.py @@ -0,0 +1,30 @@ +import os +from datetime import date +from getpass import getpass + +from django.core.management import BaseCommand +from member.models import TFJMUser + + +class Command(BaseCommand): + def handle(self, *args, **options): + email = input("Email: ") + password = "1" + confirm_password = "2" + while password != confirm_password: + password = getpass("Password: ") + confirm_password = getpass("Confirm password: ") + if password != confirm_password: + self.stderr.write(self.style.ERROR("Passwords don't match.")) + + user = TFJMUser.objects.create( + email=email, + password="", + role="admin", + year=os.getenv("TFJM_YEAR", date.today().year), + is_active=True, + is_staff=True, + is_superuser=True, + ) + user.set_password(password) + user.save() diff --git a/apps/member/models.py b/apps/member/models.py index 6f562c5..62ed9cf 100644 --- a/apps/member/models.py +++ b/apps/member/models.py @@ -38,7 +38,7 @@ class TFJMUser(AbstractUser): ("female", _("Female")), ("non-binary", _("Non binary")), ], - verbose_name=_("addresss"), + verbose_name=_("address"), ) address = models.CharField( diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..22a99ba --- /dev/null +++ b/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,319 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: TFJM2\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-04-29 02:09+0000\n" +"PO-Revision-Date: 2020-04-29 02:09+0000\n" +"Last-Translator: Yohann D'ANELLO \n" +"Language-Team: fr \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: apps/member/models.py:15 +msgid "email" +msgstr "Adresse électronique" + +#: apps/member/models.py:23 apps/member/models.py:154 +#: apps/tournament/models.py:129 apps/tournament/models.py:146 +msgid "team" +msgstr "équipe" + +#: apps/member/models.py:29 +msgid "birth date" +msgstr "date de naissance" + +#: apps/member/models.py:37 +msgid "Male" +msgstr "Homme" + +#: apps/member/models.py:38 +msgid "Female" +msgstr "Femme" + +#: apps/member/models.py:39 +msgid "Non binary" +msgstr "Non binaire" + +#: apps/member/models.py:41 +#: apps/member/models.py:48 +msgid "address" +msgstr "adresse" + +#: apps/member/models.py:54 +msgid "postal code" +msgstr "code postal" + +#: apps/member/models.py:61 +msgid "city" +msgstr "ville" + +#: apps/member/models.py:68 +msgid "country" +msgstr "pays" + +#: apps/member/models.py:76 +msgid "phone number" +msgstr "numéro de téléphone" + +#: apps/member/models.py:83 +msgid "school" +msgstr "école" + +#: apps/member/models.py:89 +msgid "Seconde or less" +msgstr "Seconde ou inférieur" + +#: apps/member/models.py:90 +msgid "Première" +msgstr "Première" + +#: apps/member/models.py:91 +msgid "Terminale" +msgstr "Terminale" + +#: apps/member/models.py:102 +msgid "responsible name" +msgstr "nom du responsable" + +#: apps/member/models.py:109 +msgid "responsible phone" +msgstr "téléphone du responsable" + +#: apps/member/models.py:115 +msgid "responsible email" +msgstr "email du responsable" + +#: apps/member/models.py:121 apps/tournament/models.py:33 +msgid "description" +msgstr "description" + +#: apps/member/models.py:127 +msgid "admin" +msgstr "administrateur" + +#: apps/member/models.py:128 +msgid "organizer" +msgstr "oragnisateur" + +#: apps/member/models.py:129 +msgid "encadrant" +msgstr "encadrant" + +#: apps/member/models.py:130 +msgid "participant" +msgstr "participant" + +#: apps/member/models.py:135 apps/tournament/models.py:61 +#: apps/tournament/models.py:117 +msgid "year" +msgstr "année" + +#: apps/member/models.py:139 apps/tournament/models.py:139 +msgid "user" +msgstr "utilisateur" + +#: apps/member/models.py:140 +msgid "users" +msgstr "utilisateurs" + +#: apps/member/models.py:147 +msgid "file" +msgstr "fichier" + +#: apps/member/models.py:161 apps/tournament/models.py:69 +#: apps/tournament/models.py:87 +msgid "tournament" +msgstr "tournoi" + +#: apps/member/models.py:167 +msgid "Parental consent" +msgstr "Autorisation parentale" + +#: apps/member/models.py:168 +msgid "Photo consent" +msgstr "Autorisation de droit à l'image" + +#: apps/member/models.py:169 +msgid "Sanitary plug" +msgstr "Fiche sanitaire" + +#: apps/member/models.py:170 +msgid "Motivation letter" +msgstr "Lettre de motivation" + +#: apps/member/models.py:171 apps/tournament/models.py:157 +msgid "Scholarship" +msgstr "Bourse" + +#: apps/member/models.py:172 +msgid "Solution" +msgstr "Solution" + +#: apps/member/models.py:173 +msgid "Synthesis" +msgstr "Synthèse" + +#: apps/member/models.py:175 +msgid "type" +msgstr "type" + +#: apps/member/models.py:180 +msgid "uploaded at" +msgstr "téléversé le" + +#: apps/member/models.py:184 +msgid "abstract document" +msgstr "document abstrait" + +#: apps/member/models.py:185 +msgid "abstract documents" +msgstr "documents abstraits" + +#: apps/member/models.py:190 +msgid "document" +msgstr "document" + +#: apps/member/models.py:191 +msgid "documents" +msgstr "documents" + +#: apps/member/models.py:196 apps/member/models.py:210 +msgid "problem" +msgstr "problème" + +#: apps/member/models.py:204 +msgid "solution" +msgstr "solution" + +#: apps/member/models.py:205 +msgid "solutions" +msgstr "solutions" + +#: apps/member/models.py:218 +msgid "synthesis" +msgstr "synthèse" + +#: apps/member/models.py:219 +msgid "syntheses" +msgstr "synthèses" + +#: apps/tournament/models.py:10 apps/tournament/models.py:76 +msgid "name" +msgstr "nom" + +#: apps/tournament/models.py:16 +msgid "organizers" +msgstr "organisateurs" + +#: apps/tournament/models.py:20 +msgid "size" +msgstr "taille" + +#: apps/tournament/models.py:25 +msgid "place" +msgstr "lieu" + +#: apps/tournament/models.py:29 +msgid "price" +msgstr "prix" + +#: apps/tournament/models.py:37 apps/tournament/models.py:41 +msgid "date start" +msgstr "date de début" + +#: apps/tournament/models.py:45 +msgid "date of registration closing" +msgstr "date de clôture des inscriptions" + +#: apps/tournament/models.py:49 +msgid "date of maximal solution submission" +msgstr "date d'envoi maximal des solutions" + +#: apps/tournament/models.py:53 +msgid "date of maximal syntheses submission" +msgstr "date d'envoi maximal des notes de synthèses" + +#: apps/tournament/models.py:57 +msgid "final tournament" +msgstr "finale" + +#: apps/tournament/models.py:70 +msgid "tournaments" +msgstr "tournois" + +#: apps/tournament/models.py:81 +msgid "trigram" +msgstr "trigramme" + +#: apps/tournament/models.py:92 +msgid "inscription date" +msgstr "date d'inscription" + +#: apps/tournament/models.py:98 apps/tournament/models.py:166 +msgid "Registration not validated" +msgstr "Inscription non validée" + +#: apps/tournament/models.py:99 apps/tournament/models.py:167 +msgid "Waiting for validation" +msgstr "En attente de validation" + +#: apps/tournament/models.py:100 apps/tournament/models.py:168 +msgid "Registration validated" +msgstr "Inscription validée" + +#: apps/tournament/models.py:102 apps/tournament/models.py:170 +msgid "validation status" +msgstr "statut de validation" + +#: apps/tournament/models.py:107 +msgid "selected for final" +msgstr "sélectionnée pour la finale" + +#: apps/tournament/models.py:113 +msgid "access code" +msgstr "code d'accès" + +#: apps/tournament/models.py:130 +msgid "teams" +msgstr "équipes" + +#: apps/tournament/models.py:152 +msgid "Not paid" +msgstr "Non payé" + +#: apps/tournament/models.py:153 +msgid "Credit card" +msgstr "Carte bancaire" + +#: apps/tournament/models.py:154 +msgid "Bank check" +msgstr "Chèque bancaire" + +#: apps/tournament/models.py:155 +msgid "Bank transfer" +msgstr "Virement bancaire" + +#: apps/tournament/models.py:156 +msgid "Cash" +msgstr "Espèces" + +#: apps/tournament/models.py:160 +msgid "payment method" +msgstr "moyen de paiement" + +#: tfjm/settings.py:123 +msgid "English" +msgstr "Anglais" + +#: tfjm/settings.py:124 +msgid "French" +msgstr "Français" diff --git a/tfjm/settings.py b/tfjm/settings.py index fd4844e..a4b4e74 100644 --- a/tfjm/settings.py +++ b/tfjm/settings.py @@ -13,6 +13,8 @@ https://docs.djangoproject.com/en/3.0/ref/settings/ import os import sys +from django.utils.translation import gettext_lazy as _ + # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) @@ -54,6 +56,8 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'django.contrib.sites.middleware.CurrentSiteMiddleware', ] ROOT_URLCONF = 'tfjm.urls' @@ -113,7 +117,12 @@ AUTH_USER_MODEL = 'member.TFJMUser' # Internationalization # https://docs.djangoproject.com/en/3.0/topics/i18n/ -LANGUAGE_CODE = 'fr-fr' +LANGUAGE_CODE = 'en' + +LANGUAGES = [ + ('en', _('English')), + ('fr', _('French')), +] TIME_ZONE = 'UTC' @@ -123,6 +132,8 @@ USE_L10N = True USE_TZ = True +LOCALE_PATHS = [os.path.join(BASE_DIR, "locale")] + # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.0/howto/static-files/