a92600c3058f8bc54fd4a2cfa9b10faeb3e63a57
2
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a92600c305 |
feat(i18n): francais comme langue principale, anglais accessible
Le site s'affiche desormais en francais par defaut, avec un selecteur de langue permettant de basculer vers l'anglais. Choix de conception : les chaines sources restent en anglais Elles servent d'identifiants gettext, et le francais est fourni par catalogue avec BABEL_DEFAULT_LOCALE = 'fr'. Le code reste ainsi dans une seule langue -- la meme que ses commentaires et docstrings -- tandis que ce qu'un membre voit est du francais. Consequence qui rend la migration praticable : une chaine non encore traduite retombe en anglais, pas sur un identifiant brut. Les gabarits peuvent donc etre migres un par un sans jamais laisser le site a moitie casse. Selection de la langue (app/i18n.py) 1. choix explicite via le selecteur, garde en session 2. sinon en-tete Accept-Language du navigateur, restreint a fr et en 3. sinon francais Un choix explicite prime toujours, y compris sur un navigateur anglophone. Selecteur Extrait en partiel et inclus dans les deux branches de la mise en page : barre laterale une fois connecte, ET page d'authentification. Quelqu'un qui ne lit pas la langue courante doit pouvoir en changer AVANT de se connecter -- le laisser derriere l'authentification aurait ete un defaut d'accessibilite. Chaque langue est ecrite dans sa propre langue. La route /lang/<locale> valide le Referer avant de rediriger : sans ce controle, elle constituait une redirection ouverte. Migre dans cette passe navigation complete, page de connexion, les cinq pages d'erreur, et l'integralite des messages flash de routes/auth.py. 64 chaines, dont aucune non traduite. Verification 25 tests, dont deux garde-fous d'integrite : un catalogue .mo manquant ou une entree non traduite font echouer la suite. Sans cela, une compilation oubliee servirait de l'anglais partout, en silence et sans rien dans les journaux. Un test existant a du etre corrige, et c'est instructif test_login_failure_message_does_not_reveal_account_existence cherchait la sous-chaine anglaise 'attempt(s) remaining'. La page etant desormais en francais, elle etait absente des deux cotes, l'assertion passait, et le mode strict a signale le faux succes. Le test comparait donc l'anglais, pas le comportement. Il compare desormais les messages flash rendus, quelle que soit la langue. La faille SEC-AUTH-006 reste ouverte, et le test la documente toujours. Les catalogues .po ET .mo sont versionnes : le deploiement est un simple miroir de fichiers, sans etape de compilation. messages.pot, regenerable, ne l'est pas. docs/translations.md documente le processus, les deux pieges (concatenation de phrases, traduction a l'import), et l'etat de la migration. A noter pour la suite : les chaines dans les blocs <script> ne peuvent pas etre balisees telles quelles, il faudra les passer par des attributs data- -- ce qui rejoint le chantier de sortie de unsafe-inline (OPS-010). Co-Authored-By: Claude Opus 5 <[email protected]> |
||
|
|
1b990a84d9 |
test: socle de tests executables et fabrique d'application parametrable
Il n'existait aucun test, et le code n'offrait aucune prise pour en ecrire :
create_app() exigeait SECRET_KEY et DATABASE_URL dans l'environnement,
creait les tables et demarrait un bot Discord. C'etait la cause, pas le
symptome.
create_app(config=None)
Les valeurs par defaut viennent toujours de l'environnement, les
surcharges de l'appelant sont appliquees ensuite, et la validation
vient en dernier pour qu'un test puisse fournir les siennes. Deux
effets de bord passent sous drapeau, actifs par defaut pour que la
production et le developpement se comportent a l'identique :
AUTO_CREATE_TABLES controle db.create_all()
ENABLE_DISCORD_BOT controle start_bot()
FORCE_HTTPS passe egalement en configuration : lu via os.getenv a
chaque requete, il renvoyait un 301 sur tout appel de test.
Suite de tests : 47 tests, 3 xfail, 32 % de couverture.
tests/conftest.py fabriques par role, connexion par le vrai
formulaire, base SQLite temporaire
test_auth_session.py expiration de session, desactivation de
compte, deconnexion
test_security_headers.py en-tetes, non-divulgation sur /health,
echappement de nl2br
test_authorization.py acces anonyme, vertical, horizontal,
validation des entrees, CSRF
Les tests marques xfail(strict=True) decrivent des constats non encore
corriges. Ils echouent par construction ; le mode strict transforme une
reussite inattendue en echec, ce qui signale qu'il faut retirer le
marqueur. Trois subsistent : enumeration de comptes (SEC-AUTH-006), CSP
unsafe-inline (SEC-WEB-001), auto-retrogradation du dernier administrateur
(SEC-AUTHZ-007).
pyproject.toml
Configuration pytest et ruff. Ruff n'avait aucune configuration : la CI
l'executait avec le jeu de regles par defaut. Les 33 F401 de
app/models/__init__.py sont ignores par fichier, c'est une facade de
re-export intentionnelle.
requirements-dev.txt separe l'outillage de test des dependances de
production.
Co-Authored-By: Claude Opus 5 <[email protected]>
|