From 210ab6c0d330a2520ebaf1fd1b74c798da1b8012 Mon Sep 17 00:00:00 2001 From: augustin64 Date: Mon, 22 Jan 2024 16:06:03 +0100 Subject: [PATCH] Localization: add python strings --- .gitignore | 4 + README.md | 25 ++ babel.cfg | 2 + default_config.py | 5 +- partitioncloud/__init__.py | 11 +- partitioncloud/modules/albums.py | 45 ++-- partitioncloud/modules/auth.py | 19 +- partitioncloud/modules/groupe.py | 21 +- partitioncloud/modules/logging.py | 2 +- partitioncloud/modules/partition.py | 31 +-- .../translations/en/LC_MESSAGES/messages.po | 224 +++++++++++++++++ .../translations/fr/LC_MESSAGES/messages.po | 226 ++++++++++++++++++ requirements.txt | 1 + 13 files changed, 556 insertions(+), 60 deletions(-) create mode 100644 babel.cfg create mode 100644 partitioncloud/translations/en/LC_MESSAGES/messages.po create mode 100644 partitioncloud/translations/fr/LC_MESSAGES/messages.po diff --git a/.gitignore b/.gitignore index ced5f7e..5bb154a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ # cache **/__pycache__ +# translations +**.mo +**.pot + # config .vscode/ diff --git a/README.md b/README.md index 4963e96..10d96a4 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ git clone https://github.com/partitioncloud/partitioncloud-server.git cd partitioncloud-server # Install dependencies pip install -r requirements.txt +pybabel compile -d partitioncloud/translations # Create database and folders ./make.sh init ``` @@ -66,6 +67,30 @@ Modifier le fichier de configuration créé dans `instance/` ![Recherche](https://github.com/partitioncloud/partitioncloud-server/assets/67148092/745bf3e3-37e9-40cd-80d2-14670bce1a45) +## Translations + +### Créer une nouvelle traduction + +```bash +# Extraire les données +pybabel extract -F babel.cfg -k _l -o partitioncloud/translations/messages.pot . +# Créer un nouveau fichier +pybabel init -i partitioncloud/translations/messages.pot -d partitioncloud/translations -l $COUNTRY_CODE +# Modifier translations/$COUNTRY_CODE/LC_MESSAGES/messages.po +# Ajouter $COUNTRY_CODE dans default_config.py: LANGUAGES +# Compiler les nouvelles translations avant de démarrer le serveur +pybabel compile -d partitioncloud/translations +``` + +### Mettre à jour une traduction + +```bash +# Récupérer les données les plus récentes +pybabel extract -F babel.cfg -k _l -o partitioncloud/translations/messages.pot . +# Les ajouter aux traductions +pybabel update -i partitioncloud/translations/messages.pot -d partitioncloud/translations +``` + ## TODO - [ ] Modifier son mot de passe - [ ] Supprimer un utilisateur diff --git a/babel.cfg b/babel.cfg new file mode 100644 index 0000000..97ebeb8 --- /dev/null +++ b/babel.cfg @@ -0,0 +1,2 @@ +[python: partitioncloud/**.py] +[jinja2: partitioncloud/templates/**.html] \ No newline at end of file diff --git a/default_config.py b/default_config.py index 253e482..d13ae2e 100644 --- a/default_config.py +++ b/default_config.py @@ -26,4 +26,7 @@ MAX_AGE=31 INSTANCE_PATH="instance" # Events to log -ENABLED_LOGS=["NEW_GROUPE", "NEW_ALBUM", "NEW_PARTITION", "NEW_USER", "SERVER_RESTART", "FAILED_LOGIN"] \ No newline at end of file +ENABLED_LOGS=["NEW_GROUPE", "NEW_ALBUM", "NEW_PARTITION", "NEW_USER", "SERVER_RESTART", "FAILED_LOGIN"] + +# Available languages +LANGUAGES=['en', 'fr'] \ No newline at end of file diff --git a/partitioncloud/__init__.py b/partitioncloud/__init__.py index dacea5f..189da59 100644 --- a/partitioncloud/__init__.py +++ b/partitioncloud/__init__.py @@ -10,6 +10,7 @@ import importlib.util from flask import Flask, g, redirect, render_template, request, send_file, flash, session, abort from werkzeug.security import generate_password_hash +from flask_babel import Babel, _ from .modules.utils import User, Album, get_all_albums from .modules import albums, auth, partition, admin, groupe, thumbnails, logging @@ -18,6 +19,12 @@ from .modules.db import get_db app = Flask(__name__) +def get_locale(): + return request.accept_languages.best_match(app.config['LANGUAGES']) + +babel = Babel(app, locale_selector=get_locale) + + def load_config(): app.config.from_object('default_config') @@ -125,10 +132,10 @@ def add_user(): try: if album_uuid != "": user.join_album(album_uuid) - flash(f"Utilisateur {username} créé") + flash(_("Utilisateur %(username)s créé", username=username)) return redirect("/albums") except LookupError: - flash(f"Cet album n'existe pas. L'utilisateur {username} a été créé") + flash(_("Cet album n'existe pas. L'utilisateur %(username)s a été créé", username=username)) return redirect("/albums") flash(error) diff --git a/partitioncloud/modules/albums.py b/partitioncloud/modules/albums.py index 40ca12a..39103b7 100644 --- a/partitioncloud/modules/albums.py +++ b/partitioncloud/modules/albums.py @@ -9,6 +9,7 @@ from typing import TypeVar from flask import (Blueprint, abort, flash, redirect, render_template, request, session, current_app) +from flask_babel import _ from .auth import login_required from .db import get_db @@ -37,7 +38,7 @@ def search_page(): Résultats de recherche """ if "query" not in request.form or request.form["query"] == "": - flash("Aucun terme de recherche spécifié.") + flash(_("Aucun terme de recherche spécifié.")) return redirect("/albums") query = request.form["query"] @@ -119,7 +120,7 @@ def create_album_req(): user = User(user_id=session["user_id"]) if not name or name.strip() == "": - error = "Un nom est requis. L'album n'a pas été créé" + error = _("Un nom est requis. L'album n'a pas été créé") if error is None: uuid = utils.create_album(name) @@ -156,10 +157,10 @@ def join_album(uuid): try: user.join_album(uuid) except LookupError: - flash("Cet album n'existe pas.") + flash(_("Cet album n'existe pas.")) return redirect(request.referrer) - flash("Album ajouté à la collection.") + flash(_("Album ajouté à la collection.")) return redirect(request.referrer) @@ -173,15 +174,15 @@ def quit_album(uuid): album = Album(uuid=uuid) users = album.get_users() if user.id not in [u["id"] for u in users]: - flash("Vous ne faites pas partie de cet album") + flash(_("Vous ne faites pas partie de cet album")) return redirect(request.referrer) if len(users) == 1: - flash("Vous êtes seul dans cet album, le quitter entraînera sa suppression.") + flash(_("Vous êtes seul dans cet album, le quitter entraînera sa suppression.")) return redirect(f"/albums/{uuid}#delete") user.quit_album(uuid) - flash("Album quitté.") + flash(_("Album quitté.")) return redirect("/albums") @@ -200,9 +201,9 @@ def delete_album(uuid): error = None users = album.get_users() if len(users) > 1: - error = "Vous n'êtes pas seul dans cet album." + error = _("Vous n'êtes pas seul dans cet album.") elif len(users) == 1 and users[0]["id"] != user.id: - error = "Vous ne possédez pas cet album." + error = _("Vous ne possédez pas cet album.") if user.access_level == 1: error = None @@ -213,7 +214,7 @@ def delete_album(uuid): album.delete(current_app.instance_path) - flash("Album supprimé.") + flash(_("Album supprimé.")) return redirect("/albums") @@ -236,15 +237,15 @@ def add_partition(album_uuid): source = "upload" # source type: upload, unknown or url if (not user.is_participant(album.uuid)) and (user.access_level != 1): - flash("Vous ne participez pas à cet album.") + flash(_("Vous ne faites pas partie de cet album")) return redirect(request.referrer) error = None if "name" not in request.form: - error = "Un titre est requis." + error = _("Un titre est requis.") elif "file" not in request.files and "partition-uuid" not in request.form: - error = "Aucun fichier n'a été fourni." + error = _("Aucun fichier n'a été fourni.") elif "file" not in request.files: partition_type = "uuid" search_uuid = request.form["partition-uuid"] @@ -256,7 +257,7 @@ def add_partition(album_uuid): (search_uuid,) ).fetchone() if data is None: - error = "Les résultats de la recherche ont expiré." + error = _("Les résultats de la recherche ont expiré.") else: source = data["url"] else: @@ -322,7 +323,7 @@ def add_partition(album_uuid): "status": "ok", "uuid": partition_uuid } - flash(f"Partition {request.form['name']} ajoutée") + flash(_("Partition %(partition_name)s ajoutée", partition_name=request.form['name'])) return redirect(f"/albums/{album.uuid}") @@ -336,13 +337,13 @@ def add_partition_from_search(): error = None if "album-uuid" not in request.form: - error = "Il est nécessaire de sélectionner un album." + error = _("Il est nécessaire de sélectionner un album.") elif "partition-uuid" not in request.form: - error = "Il est nécessaire de sélectionner une partition." + error = _("Il est nécessaire de sélectionner une partition.") elif "partition-type" not in request.form: - error = "Il est nécessaire de spécifier un type de partition." + error = _("Il est nécessaire de spécifier un type de partition.") elif (not user.is_participant(request.form["album-uuid"])) and (user.access_level != 1): - error = "Vous ne participez pas à cet album." + error = _("Vous ne faites pas partie de cet album") if error is not None: flash(error) @@ -362,9 +363,9 @@ def add_partition_from_search(): if data is None: album.add_partition(request.form["partition-uuid"]) - flash("Partition ajoutée.") + flash(_("Partition ajoutée.")) else: - flash("Partition déjà dans l'album.") + flash(_("Partition déjà dans l'album.")) return redirect(f"/albums/{album.uuid}") @@ -376,5 +377,5 @@ def add_partition_from_search(): user=user ) - flash("Type de partition inconnu.") + flash(_("Type de partition inconnu.")) return redirect("/albums") diff --git a/partitioncloud/modules/auth.py b/partitioncloud/modules/auth.py index 8d08c6e..7ada7f1 100644 --- a/partitioncloud/modules/auth.py +++ b/partitioncloud/modules/auth.py @@ -7,6 +7,7 @@ from typing import Optional from flask import (Blueprint, flash, g, redirect, render_template, request, session, url_for, current_app) +from flask_babel import _ from werkzeug.security import check_password_hash, generate_password_hash @@ -23,7 +24,7 @@ def login_required(view): @functools.wraps(view) def wrapped_view(**kwargs): if g.user is None: - flash("Vous devez être connecté pour accéder à cette page.") + flash(_("Vous devez être connecté pour accéder à cette page.")) return redirect(url_for("auth.login")) return view(**kwargs) @@ -50,12 +51,12 @@ def admin_required(view): @functools.wraps(view) def wrapped_view(**kwargs): if g.user is None: - flash("Vous devez être connecté pour accéder à cette page.") + flash(_("Vous devez être connecté pour accéder à cette page.")) return redirect(url_for("auth.login")) user = User(user_id=session.get("user_id")) if user.access_level != 1: - flash("Droits insuffisants.") + flash(_("Droits insuffisants.")) return redirect("/albums") return view(**kwargs) @@ -81,9 +82,9 @@ def create_user(username: str, password: str) -> Optional[str]: """Adds a new user to the database""" error = None if not username: - error = "Un nom d'utilisateur est requis." + error = _("Un nom d'utilisateur est requis.") elif not password: - error = "Un mot de passe est requis." + error = _("Un mot de passe est requis.") try: db = get_db() @@ -96,7 +97,7 @@ def create_user(username: str, password: str) -> Optional[str]: except db.IntegrityError: # The username was already taken, which caused the # commit to fail. Show a validation error. - error = f"Le nom d'utilisateur {username} est déjà pris." + error = _("Le nom d'utilisateur %(username)s est déjà pris.", username=username) return error # may be None @@ -109,7 +110,7 @@ def register(): password for security. """ if current_app.config["DISABLE_REGISTER"]: - flash("L'enregistrement de nouveaux utilisateurs a été désactivé par l'administrateur.") + flash(_("L'enregistrement de nouveaux utilisateurs a été désactivé par l'administrateur.")) return redirect(url_for("auth.login")) if request.method == "POST": @@ -123,7 +124,7 @@ def register(): else: user = User(name=username) - flash("Utilisateur créé avec succès. Vous pouvez vous connecter.") + flash(_("Utilisateur créé avec succès. Vous pouvez vous connecter.")) logging.log( [user.username, user.id, False], @@ -148,7 +149,7 @@ def login(): if (user is None) or not check_password_hash(user["password"], password): logging.log([username], logging.LogEntry.FAILED_LOGIN) - error = "Nom d'utilisateur ou mot de passe incorrect." + error = _("Nom d'utilisateur ou mot de passe incorrect.") if error is None: # store the user id in a new session and return to the index diff --git a/partitioncloud/modules/groupe.py b/partitioncloud/modules/groupe.py index 6991f3a..4b9e367 100644 --- a/partitioncloud/modules/groupe.py +++ b/partitioncloud/modules/groupe.py @@ -4,6 +4,7 @@ Groupe module """ from flask import (Blueprint, abort, flash, redirect, render_template, request, session, current_app) +from flask_babel import _ from .auth import login_required from .db import get_db @@ -67,7 +68,7 @@ def create_groupe(): user = User(user_id=session["user_id"]) if not name or name.strip() == "": - error = "Un nom est requis. Le groupe n'a pas été créé" + error = _("Un nom est requis. Le groupe n'a pas été créé") if error is None: while True: @@ -116,10 +117,10 @@ def join_groupe(uuid): try: user.join_groupe(uuid) except LookupError: - flash("Ce groupe n'existe pas.") + flash(_("Ce groupe n'existe pas.")) return redirect(f"/groupe/{uuid}") - flash("Groupe ajouté à la collection.") + flash(_("Groupe ajouté à la collection.")) return redirect(f"/groupe/{uuid}") @@ -130,15 +131,15 @@ def quit_groupe(uuid): groupe = Groupe(uuid=uuid) users = groupe.get_users() if user.id not in [u["id"] for u in users]: - flash("Vous ne faites pas partie de ce groupe") + flash(_("Vous ne faites pas partie de ce groupe")) return redirect(f"/groupe/{uuid}") if len(users) == 1: - flash("Vous êtes seul dans ce groupe, le quitter entraînera sa suppression.") + flash(_("Vous êtes seul dans ce groupe, le quitter entraînera sa suppression.")) return redirect(f"/groupe/{uuid}#delete") user.quit_groupe(groupe.uuid) - flash("Groupe quitté.") + flash(_("Groupe quitté.")) return redirect("/albums") @@ -151,7 +152,7 @@ def delete_groupe(uuid): error = None users = groupe.get_users() if len(users) > 1: - error = "Vous n'êtes pas seul dans ce groupe." + error = _("Vous n'êtes pas seul dans ce groupe.") if user.access_level == 1 or user.id not in groupe.get_admins(): error = None @@ -162,7 +163,7 @@ def delete_groupe(uuid): groupe.delete(current_app.instance_path) - flash("Groupe supprimé.") + flash(_("Groupe supprimé.")) return redirect("/albums") @@ -181,10 +182,10 @@ def create_album_req(groupe_uuid): error = None if not name or name.strip() == "": - error = "Un nom est requis. L'album n'a pas été créé" + error = _("Un nom est requis. L'album n'a pas été créé") if user.id not in groupe.get_admins(): - error ="Vous n'êtes pas administrateur de ce groupe" + error = _("Vous n'êtes pas administrateur de ce groupe") if error is None: uuid = utils.create_album(name) diff --git a/partitioncloud/modules/logging.py b/partitioncloud/modules/logging.py index 472022e..162c4a5 100644 --- a/partitioncloud/modules/logging.py +++ b/partitioncloud/modules/logging.py @@ -30,7 +30,7 @@ class LogEntry(Enum): def add_entry(entry: str) -> None: - date = datetime.now().strftime("%y-%b-%Y %H:%M:%S") + date = datetime.now().strftime('%y-%b-%Y %H:%M:%S') with open(log_file, 'a', encoding="utf8") as f: f.write(f"[{date}] {entry}\n") diff --git a/partitioncloud/modules/partition.py b/partitioncloud/modules/partition.py index 700b221..0dfe18f 100644 --- a/partitioncloud/modules/partition.py +++ b/partitioncloud/modules/partition.py @@ -6,6 +6,7 @@ import os from uuid import uuid4 from flask import (Blueprint, abort, send_file, render_template, request, redirect, flash, session, current_app) +from flask_babel import _ from .db import get_db from .auth import login_required, admin_required @@ -54,12 +55,12 @@ def add_attachment(uuid): user = User(user_id=session.get("user_id")) if user.id != partition.user_id and user.access_level != 1: - flash("Cette partition ne vous current_appartient pas") + flash(_("Cette partition ne vous appartient pas")) return redirect(request.referrer) error = None # À mettre au propre if "file" not in request.files: - error = "Aucun fichier n'a été fourni." + error = _("Aucun fichier n'a été fourni.") else: if "name" not in request.form or request.form["name"] == "": name = ".".join(request.files["file"].filename.split(".")[:-1]) @@ -67,12 +68,12 @@ def add_attachment(uuid): name = request.form["name"] if name == "": - error = "Pas de nom de fichier" + error = _("Pas de nom de fichier") else: filename = request.files["file"].filename ext = filename.split(".")[-1] if ext not in ["mid", "mp3"]: - error = "Extension de fichier non supportée" + error = _("Extension de fichier non supportée") if error is not None: flash(error) @@ -140,7 +141,7 @@ def edit(uuid): user = User(user_id=session.get("user_id")) if user.access_level != 1 and partition.user_id != user.id: - flash("Vous n'êtes pas autorisé à modifier cette partition.") + flash(_("Vous n'êtes pas autorisé à modifier cette partition.")) return redirect("/albums") if request.method == "GET": @@ -149,11 +150,11 @@ def edit(uuid): error = None if "name" not in request.form or request.form["name"].strip() == "": - error = "Un titre est requis." + error = _("Un titre est requis.") elif "author" not in request.form: - error = "Un nom d'auteur est requis (à minima nul)" + error = _("Un nom d'auteur est requis (à minima nul)") elif "body" not in request.form: - error = "Des paroles sont requises (à minima nulles)" + error = _("Des paroles sont requises (à minima nulles)") if error is not None: flash(error) @@ -165,7 +166,7 @@ def edit(uuid): body=request.form["body"] ) - flash(f"Partition {request.form['name']} modifiée avec succès.") + flash(_("Partition %(name)s modifiée avec succès.", name=request.form['name'])) return redirect("/albums") @@ -195,11 +196,11 @@ def details(uuid): error = None if "name" not in request.form or request.form["name"].strip() == "": - error = "Un titre est requis." + error = _("Un titre est requis.") elif "author" not in request.form: - error = "Un nom d'auteur est requis (à minima nul)" + error = _("Un nom d'auteur est requis (à minima nul)") elif "body" not in request.form: - error = "Des paroles sont requises (à minima nulles)" + error = _("Des paroles sont requises (à minima nulles)") if error is not None: flash(error) @@ -211,7 +212,7 @@ def details(uuid): body=request.form["body"] ) - flash(f"Partition {request.form['name']} modifiée avec succès.") + flash(_("Partition %(name)s modifiée avec succès.", name=request.form['name'])) return redirect("/albums") @@ -226,7 +227,7 @@ def delete(uuid): user = User(user_id=session.get("user_id")) if user.access_level != 1 and partition.user_id != user.id: - flash("Vous n'êtes pas autorisé à supprimer cette partition.") + flash(_("Vous n'êtes pas autorisé à supprimer cette partition.")) return redirect("/albums") if request.method == "GET": @@ -234,7 +235,7 @@ def delete(uuid): partition.delete(current_app.instance_path) - flash("Partition supprimée.") + flash(_("Partition supprimée.")) return redirect("/albums") diff --git a/partitioncloud/translations/en/LC_MESSAGES/messages.po b/partitioncloud/translations/en/LC_MESSAGES/messages.po new file mode 100644 index 0000000..76638ad --- /dev/null +++ b/partitioncloud/translations/en/LC_MESSAGES/messages.po @@ -0,0 +1,224 @@ +# English translations for PROJECT. +# Copyright (C) 2024 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2024-01-22 16:04+0100\n" +"PO-Revision-Date: 2024-01-22 15:38+0100\n" +"Last-Translator: FULL NAME \n" +"Language: en\n" +"Language-Team: en \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.12.1\n" + +#: partitioncloud/__init__.py:136 +#, fuzzy, python-format +msgid "Utilisateur %(username)s créé" +msgstr "Created user %(username)s" + +#: partitioncloud/__init__.py:139 +#, fuzzy, python-format +msgid "Cet album n'existe pas. L'utilisateur %(username)s a été créé" +msgstr "This album does not exists, but user %(username)s has been created" + +#: partitioncloud/modules/albums.py:41 +msgid "Aucun terme de recherche spécifié." +msgstr "Missing search query" + +#: partitioncloud/modules/albums.py:123 partitioncloud/modules/groupe.py:185 +msgid "Un nom est requis. L'album n'a pas été créé" +msgstr "Missing name." + +#: partitioncloud/modules/albums.py:160 +msgid "Cet album n'existe pas." +msgstr "This album does not exist." + +#: partitioncloud/modules/albums.py:163 +msgid "Album ajouté à la collection." +msgstr "Album added to collection." + +#: partitioncloud/modules/albums.py:177 partitioncloud/modules/albums.py:240 +#: partitioncloud/modules/albums.py:346 +msgid "Vous ne faites pas partie de cet album" +msgstr "You are not a member of this album" + +#: partitioncloud/modules/albums.py:181 +msgid "Vous êtes seul dans cet album, le quitter entraînera sa suppression." +msgstr "You are alone here, quitting means deleting this album." + +#: partitioncloud/modules/albums.py:185 +msgid "Album quitté." +msgstr "Album quitted." + +#: partitioncloud/modules/albums.py:204 +msgid "Vous n'êtes pas seul dans cet album." +msgstr "You are not alone in this album." + +#: partitioncloud/modules/albums.py:206 +msgid "Vous ne possédez pas cet album." +msgstr "You don't own this album." + +#: partitioncloud/modules/albums.py:217 +msgid "Album supprimé." +msgstr "Album deleted." + +#: partitioncloud/modules/albums.py:246 partitioncloud/modules/partition.py:153 +#: partitioncloud/modules/partition.py:199 +msgid "Un titre est requis." +msgstr "Missing title" + +#: partitioncloud/modules/albums.py:248 partitioncloud/modules/partition.py:63 +msgid "Aucun fichier n'a été fourni." +msgstr "Missing file" + +#: partitioncloud/modules/albums.py:260 +msgid "Les résultats de la recherche ont expiré." +msgstr "Search results expired" + +#: partitioncloud/modules/albums.py:326 +#, fuzzy, python-format +msgid "Partition %(partition_name)s ajoutée" +msgstr "Score %(partition_name)s added" + +#: partitioncloud/modules/albums.py:340 +msgid "Il est nécessaire de sélectionner un album." +msgstr "Selecting an album is mandatory." + +#: partitioncloud/modules/albums.py:342 +msgid "Il est nécessaire de sélectionner une partition." +msgstr "Selecting a score is mandatory." + +#: partitioncloud/modules/albums.py:344 +msgid "Il est nécessaire de spécifier un type de partition." +msgstr "Please specify a score type." + +#: partitioncloud/modules/albums.py:366 +msgid "Partition ajoutée." +msgstr "Score added" + +#: partitioncloud/modules/albums.py:368 +msgid "Partition déjà dans l'album." +msgstr "Score is already in the album." + +#: partitioncloud/modules/albums.py:380 +msgid "Type de partition inconnu." +msgstr "Unknown score type." + +#: partitioncloud/modules/auth.py:27 partitioncloud/modules/auth.py:54 +msgid "Vous devez être connecté pour accéder à cette page." +msgstr "You need to login to access this resource." + +#: partitioncloud/modules/auth.py:59 +msgid "Droits insuffisants." +msgstr "Missing rights." + +#: partitioncloud/modules/auth.py:85 +msgid "Un nom d'utilisateur est requis." +msgstr "Missing username." + +#: partitioncloud/modules/auth.py:87 +msgid "Un mot de passe est requis." +msgstr "Missing password." + +#: partitioncloud/modules/auth.py:100 +#, python-format +msgid "Le nom d'utilisateur %(username)s est déjà pris." +msgstr "Username %(username)s is not available." + +#: partitioncloud/modules/auth.py:113 +msgid "" +"L'enregistrement de nouveaux utilisateurs a été désactivé par " +"l'administrateur." +msgstr "New users registration is disabled by owner." + +#: partitioncloud/modules/auth.py:127 +msgid "Utilisateur créé avec succès. Vous pouvez vous connecter." +msgstr "Successfully created new user. You can log in." + +#: partitioncloud/modules/auth.py:152 +msgid "Nom d'utilisateur ou mot de passe incorrect." +msgstr "Incorrect username or password" + +#: partitioncloud/modules/groupe.py:71 +msgid "Un nom est requis. Le groupe n'a pas été créé" +msgstr "Missing name." + +#: partitioncloud/modules/groupe.py:120 +msgid "Ce groupe n'existe pas." +msgstr "Unknown group." + +#: partitioncloud/modules/groupe.py:123 +msgid "Groupe ajouté à la collection." +msgstr "Group added to collection." + +#: partitioncloud/modules/groupe.py:134 +msgid "Vous ne faites pas partie de ce groupe" +msgstr "You are not a member of this group." + +#: partitioncloud/modules/groupe.py:138 +msgid "Vous êtes seul dans ce groupe, le quitter entraînera sa suppression." +msgstr "You are alone here, quitting means deleting this group." + +#: partitioncloud/modules/groupe.py:142 +msgid "Groupe quitté." +msgstr "Group quitted." + +#: partitioncloud/modules/groupe.py:155 +msgid "Vous n'êtes pas seul dans ce groupe." +msgstr "You are not alone in this group." + +#: partitioncloud/modules/groupe.py:166 +msgid "Groupe supprimé." +msgstr "Group deleted." + +#: partitioncloud/modules/groupe.py:188 +msgid "Vous n'êtes pas administrateur de ce groupe" +msgstr "You are not admin of this group." + +#: partitioncloud/modules/partition.py:58 +msgid "Cette partition ne vous appartient pas" +msgstr "You don't own this score." + +#: partitioncloud/modules/partition.py:71 +msgid "Pas de nom de fichier" +msgstr "Missing filename." + +#: partitioncloud/modules/partition.py:76 +msgid "Extension de fichier non supportée" +msgstr "Unsupported file type." + +#: partitioncloud/modules/partition.py:144 +msgid "Vous n'êtes pas autorisé à modifier cette partition." +msgstr "You are not allowed to edit this file." + +#: partitioncloud/modules/partition.py:155 +#: partitioncloud/modules/partition.py:201 +msgid "Un nom d'auteur est requis (à minima nul)" +msgstr "Missing author in request body (can be null)." + +#: partitioncloud/modules/partition.py:157 +#: partitioncloud/modules/partition.py:203 +msgid "Des paroles sont requises (à minima nulles)" +msgstr "Missing lyrics (can be null)." + +#: partitioncloud/modules/partition.py:169 +#: partitioncloud/modules/partition.py:215 +#, python-format +msgid "Partition %(name)s modifiée avec succès." +msgstr "Successfully modified %(name)s" + +#: partitioncloud/modules/partition.py:230 +msgid "Vous n'êtes pas autorisé à supprimer cette partition." +msgstr "You are not allowed to delete this score." + +#: partitioncloud/modules/partition.py:238 +msgid "Partition supprimée." +msgstr "Score deleted." + diff --git a/partitioncloud/translations/fr/LC_MESSAGES/messages.po b/partitioncloud/translations/fr/LC_MESSAGES/messages.po new file mode 100644 index 0000000..11f66d7 --- /dev/null +++ b/partitioncloud/translations/fr/LC_MESSAGES/messages.po @@ -0,0 +1,226 @@ +# French translations for PROJECT. +# Copyright (C) 2024 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2024-01-22 16:04+0100\n" +"PO-Revision-Date: 2024-01-22 15:24+0100\n" +"Last-Translator: FULL NAME \n" +"Language: fr\n" +"Language-Team: fr \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.12.1\n" + +#: partitioncloud/__init__.py:136 +#, fuzzy, python-format +msgid "Utilisateur %(username)s créé" +msgstr "Utilisateur %(username)s créé" + +#: partitioncloud/__init__.py:139 +#, fuzzy, python-format +msgid "Cet album n'existe pas. L'utilisateur %(username)s a été créé" +msgstr "Cet album n'existe pas. L'utilisateur %(username)s a été créé" + +#: partitioncloud/modules/albums.py:41 +msgid "Aucun terme de recherche spécifié." +msgstr "Aucun terme de recherche spécifié." + +#: partitioncloud/modules/albums.py:123 partitioncloud/modules/groupe.py:185 +msgid "Un nom est requis. L'album n'a pas été créé" +msgstr "Un nom est requis. L'album n'a pas été créé" + +#: partitioncloud/modules/albums.py:160 +msgid "Cet album n'existe pas." +msgstr "Cet album n'existe pas." + +#: partitioncloud/modules/albums.py:163 +msgid "Album ajouté à la collection." +msgstr "Album ajouté à la collection." + +#: partitioncloud/modules/albums.py:177 partitioncloud/modules/albums.py:240 +#: partitioncloud/modules/albums.py:346 +msgid "Vous ne faites pas partie de cet album" +msgstr "Vous ne faites pas partie de cet album" + +#: partitioncloud/modules/albums.py:181 +msgid "Vous êtes seul dans cet album, le quitter entraînera sa suppression." +msgstr "Vous êtes seul dans cet album, le quitter entraînera sa suppression." + +#: partitioncloud/modules/albums.py:185 +msgid "Album quitté." +msgstr "Album quitté." + +#: partitioncloud/modules/albums.py:204 +msgid "Vous n'êtes pas seul dans cet album." +msgstr "Vous n'êtes pas seul dans cet album." + +#: partitioncloud/modules/albums.py:206 +msgid "Vous ne possédez pas cet album." +msgstr "Vous ne possédez pas cet album." + +#: partitioncloud/modules/albums.py:217 +msgid "Album supprimé." +msgstr "Album supprimé." + +#: partitioncloud/modules/albums.py:246 partitioncloud/modules/partition.py:153 +#: partitioncloud/modules/partition.py:199 +msgid "Un titre est requis." +msgstr "Un titre est requis." + +#: partitioncloud/modules/albums.py:248 partitioncloud/modules/partition.py:63 +msgid "Aucun fichier n'a été fourni." +msgstr "Aucun fichier n'a été fourni." + +#: partitioncloud/modules/albums.py:260 +msgid "Les résultats de la recherche ont expiré." +msgstr "Les résultats de la recherche ont expiré." + +#: partitioncloud/modules/albums.py:326 +#, fuzzy, python-format +msgid "Partition %(partition_name)s ajoutée" +msgstr "Partition %(partition_name)s ajoutée" + +#: partitioncloud/modules/albums.py:340 +msgid "Il est nécessaire de sélectionner un album." +msgstr "Il est nécessaire de sélectionner un album." + +#: partitioncloud/modules/albums.py:342 +msgid "Il est nécessaire de sélectionner une partition." +msgstr "Il est nécessaire de sélectionner une partition." + +#: partitioncloud/modules/albums.py:344 +msgid "Il est nécessaire de spécifier un type de partition." +msgstr "Il est nécessaire de spécifier un type de partition." + +#: partitioncloud/modules/albums.py:366 +msgid "Partition ajoutée." +msgstr "Partition ajoutée." + +#: partitioncloud/modules/albums.py:368 +msgid "Partition déjà dans l'album." +msgstr "Partition déjà dans l'album." + +#: partitioncloud/modules/albums.py:380 +msgid "Type de partition inconnu." +msgstr "Type de partition inconnu." + +#: partitioncloud/modules/auth.py:27 partitioncloud/modules/auth.py:54 +msgid "Vous devez être connecté pour accéder à cette page." +msgstr "Vous devez être connecté pour accéder à cette page." + +#: partitioncloud/modules/auth.py:59 +msgid "Droits insuffisants." +msgstr "Droits insuffisants." + +#: partitioncloud/modules/auth.py:85 +msgid "Un nom d'utilisateur est requis." +msgstr "Un nom d'utilisateur est requis." + +#: partitioncloud/modules/auth.py:87 +msgid "Un mot de passe est requis." +msgstr "Un mot de passe est requis." + +#: partitioncloud/modules/auth.py:100 +#, fuzzy, python-format +msgid "Le nom d'utilisateur %(username)s est déjà pris." +msgstr "Le nom d'utilisateur %(username)s est déjà pris." + +#: partitioncloud/modules/auth.py:113 +msgid "" +"L'enregistrement de nouveaux utilisateurs a été désactivé par " +"l'administrateur." +msgstr "" +"L'enregistrement de nouveaux utilisateurs a été désactivé par " +"l'administrateur." + +#: partitioncloud/modules/auth.py:127 +msgid "Utilisateur créé avec succès. Vous pouvez vous connecter." +msgstr "Utilisateur créé avec succès. Vous pouvez vous connecter." + +#: partitioncloud/modules/auth.py:152 +msgid "Nom d'utilisateur ou mot de passe incorrect." +msgstr "Nom d'utilisateur ou mot de passe incorrect." + +#: partitioncloud/modules/groupe.py:71 +msgid "Un nom est requis. Le groupe n'a pas été créé" +msgstr "Un nom est requis. Le groupe n'a pas été créé" + +#: partitioncloud/modules/groupe.py:120 +msgid "Ce groupe n'existe pas." +msgstr "Ce groupe n'existe pas." + +#: partitioncloud/modules/groupe.py:123 +msgid "Groupe ajouté à la collection." +msgstr "Groupe ajouté à la collection." + +#: partitioncloud/modules/groupe.py:134 +msgid "Vous ne faites pas partie de ce groupe" +msgstr "Vous ne faites pas partie de ce groupe" + +#: partitioncloud/modules/groupe.py:138 +msgid "Vous êtes seul dans ce groupe, le quitter entraînera sa suppression." +msgstr "Vous êtes seul dans ce groupe, le quitter entraînera sa suppression." + +#: partitioncloud/modules/groupe.py:142 +msgid "Groupe quitté." +msgstr "Groupe quitté." + +#: partitioncloud/modules/groupe.py:155 +msgid "Vous n'êtes pas seul dans ce groupe." +msgstr "Vous n'êtes pas seul dans ce groupe." + +#: partitioncloud/modules/groupe.py:166 +msgid "Groupe supprimé." +msgstr "Groupe supprimé." + +#: partitioncloud/modules/groupe.py:188 +msgid "Vous n'êtes pas administrateur de ce groupe" +msgstr "Vous n'êtes pas administrateur de ce groupe" + +#: partitioncloud/modules/partition.py:58 +msgid "Cette partition ne vous appartient pas" +msgstr "Cette partition ne vous appartient pas" + +#: partitioncloud/modules/partition.py:71 +msgid "Pas de nom de fichier" +msgstr "Pas de nom de fichier" + +#: partitioncloud/modules/partition.py:76 +msgid "Extension de fichier non supportée" +msgstr "Extension de fichier non supportée" + +#: partitioncloud/modules/partition.py:144 +msgid "Vous n'êtes pas autorisé à modifier cette partition." +msgstr "Vous n'êtes pas autorisé à modifier cette partition." + +#: partitioncloud/modules/partition.py:155 +#: partitioncloud/modules/partition.py:201 +msgid "Un nom d'auteur est requis (à minima nul)" +msgstr "Un nom d'auteur est requis (à minima nul)" + +#: partitioncloud/modules/partition.py:157 +#: partitioncloud/modules/partition.py:203 +msgid "Des paroles sont requises (à minima nulles)" +msgstr "Des paroles sont requises (à minima nulles)" + +#: partitioncloud/modules/partition.py:169 +#: partitioncloud/modules/partition.py:215 +#, fuzzy, python-format +msgid "Partition %(name)s modifiée avec succès." +msgstr "Partition %(name)s modifiée avec succès." + +#: partitioncloud/modules/partition.py:230 +msgid "Vous n'êtes pas autorisé à supprimer cette partition." +msgstr "Vous n'êtes pas autorisé à supprimer cette partition." + +#: partitioncloud/modules/partition.py:238 +msgid "Partition supprimée." +msgstr "Partition supprimée." + diff --git a/requirements.txt b/requirements.txt index 087e383..8a0b15a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ flask +flask-babel google colorama qrcode \ No newline at end of file