diff --git a/src/main/webapp/public/locales/en/cm.json b/src/main/webapp/public/locales/en/cm.json
new file mode 100644
index 0000000..b21846e
--- /dev/null
+++ b/src/main/webapp/public/locales/en/cm.json
@@ -0,0 +1,143 @@
+{
+ "--SélectionnerUnCombattant--": "-- Select a fighter --",
+ "--Tous--": "-- All --",
+ "actuel": "Current",
+ "administration": "Administration",
+ "adresseDuServeur": "Server address",
+ "ajouter": "Add",
+ "ajouterDesCombattants": "Add fighters",
+ "attention": "Warning",
+ "aucuneConfigurationObs": "No OBS configuration found, please import one",
+ "bleu": "Blue",
+ "blue": "Blue",
+ "catégorie": "Category",
+ "chrono.+/-...S": "+/- ... s",
+ "chrono.+10S": "+10 s",
+ "chrono.+1S": "+1 s",
+ "chrono.-10S": "-10 s",
+ "chrono.-1S": "-1 s",
+ "chrono.arrêter": "Stop",
+ "chrono.définirLeTemps": "Set time",
+ "chrono.démarrer": "Start",
+ "chrono.editionTemps": "Time editing",
+ "chrono.entrezLeTempsEnS": "Enter time in seconds",
+ "chrono.recapTemps": "Time: {{temps}}, pause: {{pause}}",
+ "chronomètre": "Stopwatch",
+ "club": "Club",
+ "compétition": "Competition",
+ "compétitionManager": "Competition manager",
+ "config.obs.dossierDesResources": "Resources folder",
+ "config.obs.motDePasseDuServeur": "Server password",
+ "config.obs.warn1": "/! The password will be stored in plain text; it is recommended to use it only on OBS WebSocket and to change it between each competition",
+ "config.obs.ws": "ws://",
+ "configurationObs": "OBS Configuration",
+ "confirm1": "This match already has results; are you sure you want to delete it?",
+ "confirm2.msg": "Do you really want to change the tournament tree size or the loser matches? This will modify existing matches (including possible deletions)!",
+ "confirm2.title": "Tournament tree change",
+ "confirm3.msg": "Do you really want to remove the {{typeStr}} part from the category? This will delete the matches contained in this part!",
+ "confirm3.title": "Change category type",
+ "confirm4.msg": "Do you really want to delete the category {{name}}. This will delete all associated matches!",
+ "confirm4.title": "Delete category",
+ "conserverUniquementLesMatchsTerminés": "Keep only finished matches",
+ "contre": "vs",
+ "créerLesMatchs": "Create matches",
+ "demi-finalesEtFinales": "Semi-finals and finals",
+ "duréePause": "Pause duration",
+ "duréeRound": "Round duration",
+ "editionDeLaCatégorie": "Edit category",
+ "enregister": "Save",
+ "enregistrer": "Save",
+ "epéeBouclier": "Sword and shield",
+ "err1": "A fighter cannot fight themselves!",
+ "err2": "The combat zone name format is invalid. Please separate names with ';'.",
+ "err3": "At least one type (pool or tournament) must be selected.",
+ "erreurLorsDeLaCopieDansLePresse": "Error while copying to clipboard: ",
+ "erreurLorsDeLaCréationDesMatchs": "Error while creating matches: ",
+ "exporter": "Export",
+ "fermer": "Close",
+ "finalesUniquement": "Finals only",
+ "genre": "Gender",
+ "genre.f": "F",
+ "genre.h": "M",
+ "genre.na": "NA",
+ "inscrit": "Registered",
+ "manche": "Round",
+ "matchPourLesPerdantsDuTournoi": "Match for tournament losers:",
+ "matches": "Matches",
+ "modifier": "Edit",
+ "msg1": "There are already matches in this pool; what do you want to do with them?",
+ "neRienConserver": "Keep nothing",
+ "no": "No.",
+ "nom": "Name",
+ "nomDesZonesDeCombat": "Combat zone names <1>(separated by ';')1>",
+ "nouvelle...": "New...",
+ "obs.préfixDesSources": "Source prefix",
+ "pays": "Country",
+ "poids": "Weight",
+ "poule": "Pool",
+ "poulePour": "Pool for: ",
+ "préparation...": "Preparing...",
+ "rouge": "Red",
+ "réinitialiser": "Reset",
+ "résultat": "Result",
+ "sansPoule": "No pool",
+ "sauvegarde": "Backup",
+ "sauvegarder": "Save",
+ "score": "Score",
+ "score.err1": "Cannot end a tournament match in a draw.",
+ "score.spe": "Special scores: -997: disqualified -998: absent -999: forfeit",
+ "scores": "Scores",
+ "secrétariatsDeLice": "Ring secretariats",
+ "select.aucunCombattantDisponible": "No fighters available",
+ "select.aucunCombattantSélectionné": "No fighters selected",
+ "select.msg1": "(0 = disabled)",
+ "select.recherche": "Search",
+ "select.sélectionnerDesCombatants": "Select fighters",
+ "select.à": "to",
+ "serveur": "Server",
+ "suivant": "Next",
+ "supprimer": "Delete",
+ "sélectionneLesModesDaffichage": "Select display modes",
+ "sélectionner": "Select",
+ "terminé": "Finished",
+ "texteCopiéDansLePresse": "Text copied to clipboard! Paste it into an HTML tag on your WordPress.",
+ "toast.createCategory.error": "Error while creating the category",
+ "toast.createCategory.pending": "Creating category...",
+ "toast.createCategory.success": "Category created!",
+ "toast.deleteCategory.error": "Error while deleting the category",
+ "toast.deleteCategory.pending": "Deleting category...",
+ "toast.deleteCategory.success": "Category deleted!",
+ "toast.matchs.create.error": "Error while creating matches.",
+ "toast.matchs.create.pending": "Creating matches in progress...",
+ "toast.matchs.create.success": "Matches created successfully.",
+ "toast.updateCategory.error": "Error while updating the category",
+ "toast.updateCategory.pending": "Updating category...",
+ "toast.updateCategory.success": "Category updated!",
+ "toast.updateMatchScore.error": "Error while updating match score",
+ "toast.updateMatchScore.pending": "Updating match score...",
+ "toast.updateMatchScore.success": "Match score updated!",
+ "toast.updateTrees.error": "Error while updating trees",
+ "toast.updateTrees.init.error": "Error while creating trees",
+ "toast.updateTrees.init.pending": "Creating tournament trees...",
+ "toast.updateTrees.init.success": "Trees created!",
+ "toast.updateTrees.pending": "Updating tournament trees...",
+ "toast.updateTrees.success": "Trees updated!",
+ "tournoi": "Tournament",
+ "tournois": "Tournaments",
+ "tousLesMatchs": "All matches",
+ "toutConserver": "Keep all",
+ "ttm.admin.obs": "Short click: Download resources. Long click: Create OBS configuration",
+ "ttm.admin.scripte": "Copy integration script",
+ "ttm.table.inverserLaPosition": "Reverse fighter positions on this screen",
+ "ttm.table.obs": "Short click: Load configuration and connect. Long click: Ring configuration",
+ "ttm.table.pub_aff": "Open public display",
+ "ttm.table.pub_score": "Show scores on public display",
+ "type": "Type",
+ "téléchargement": "Download",
+ "téléchargementEnCours": "Downloading...",
+ "téléchargementTerminé!": "Download completed!",
+ "uneCatégorie": "a category",
+ "valider": "Validate",
+ "zone": "Zone",
+ "zoneDeCombat": "Combat zone"
+}
diff --git a/src/main/webapp/public/locales/fr/cm.json b/src/main/webapp/public/locales/fr/cm.json
new file mode 100644
index 0000000..6f620c6
--- /dev/null
+++ b/src/main/webapp/public/locales/fr/cm.json
@@ -0,0 +1,143 @@
+{
+ "--SélectionnerUnCombattant--": "-- Sélectionner un combattant --",
+ "--Tous--": "-- Tous --",
+ "actuel": "Actuel",
+ "administration": "Administration",
+ "adresseDuServeur": "Adresse du serveur",
+ "ajouter": "Ajouter",
+ "ajouterDesCombattants": "Ajouter des combattants",
+ "attention": "Attention",
+ "aucuneConfigurationObs": "Aucune configuration OBS trouvée, veuillez en importer une",
+ "bleu": "Bleu",
+ "blue": "Blue",
+ "catégorie": "Catégorie",
+ "chrono.+/-...S": "+/- ... s",
+ "chrono.+10S": "+10 s",
+ "chrono.+1S": "+1 s",
+ "chrono.-10S": "-10 s",
+ "chrono.-1S": "-1 s",
+ "chrono.arrêter": "Arrêter",
+ "chrono.définirLeTemps": "Définir le temps",
+ "chrono.démarrer": "Démarrer",
+ "chrono.editionTemps": "Edition temps",
+ "chrono.entrezLeTempsEnS": "Entrez le temps en s",
+ "chrono.recapTemps": "Temps: {{temps}}, pause: {{pause}}",
+ "chronomètre": "Chronomètre",
+ "club": "Club",
+ "compétition": "Compétition",
+ "compétitionManager": "Compétition manager",
+ "config.obs.dossierDesResources": "Dossier des resources",
+ "config.obs.motDePasseDuServeur": "Mot de passe du serveur",
+ "config.obs.warn1": "/! Le mot de passe va être stoker en claire, il est recommandé de ne l'utiliser que sur obs websocket et d'en changer entre chaque compétition",
+ "config.obs.ws": "ws://",
+ "configurationObs": "Configuration OBS",
+ "confirm1": "Ce match a déjà des résultats, êtes-vous sûr de vouloir le supprimer ?",
+ "confirm2.msg": "Voulez-vous vraiment changer la taille de l'arbre du tournoi ou les matchs pour les perdants ? Cela va modifier les matchs existants (incluant des possibles suppressions)!",
+ "confirm2.title": "Changement de l'arbre du tournoi",
+ "confirm3.msg": "Voulez-vous vraiment enlever la partie {{typeStr}} de la catégorie. Cela va supprimer les matchs contenus dans cette partie !",
+ "confirm3.title": "Changement de type de catégorie",
+ "confirm4.msg": "Voulez-vous vraiment supprimer la catégorie {{name}}. Cela va supprimer tous les matchs associés !",
+ "confirm4.title": "Suppression de la catégorie",
+ "conserverUniquementLesMatchsTerminés": "Conserver uniquement les matchs terminés",
+ "contre": "contre",
+ "créerLesMatchs": "Créer les matchs",
+ "demi-finalesEtFinales": "Demi-finales et finales",
+ "duréePause": "Durée pause",
+ "duréeRound": "Durée round",
+ "editionDeLaCatégorie": "Edition de la catégorie",
+ "enregister": "Enregister",
+ "enregistrer": "Enregistrer",
+ "epéeBouclier": "Epée bouclier",
+ "err1": "Un combattant ne peut pas s'affronter lui-même !",
+ "err2": "Le format du nom des zones de combat est invalide. Veuillez séparer les noms par des ';'.",
+ "err3": "Au moins un type (poule ou tournoi) doit être sélectionné.",
+ "erreurLorsDeLaCopieDansLePresse": "Erreur lors de la copie dans le presse-papier : ",
+ "erreurLorsDeLaCréationDesMatchs": "Erreur lors de la création des matchs: ",
+ "exporter": "Exporter",
+ "fermer": "Fermer",
+ "finalesUniquement": "Finales uniquement",
+ "genre": "Genre",
+ "genre.f": "F",
+ "genre.h": "H",
+ "genre.na": "NA",
+ "inscrit": "Inscrit",
+ "manche": "Manche",
+ "matchPourLesPerdantsDuTournoi": "Match pour les perdants du tournoi:",
+ "matches": "Matches",
+ "modifier": "Modifier",
+ "msg1": "Il y a déjà des matchs dans cette poule, que voulez-vous faire avec ?",
+ "neRienConserver": "Ne rien conserver",
+ "no": "N°",
+ "nom": "Nom",
+ "nomDesZonesDeCombat": "Nom des zones de combat <1>(séparée par des ';')1>",
+ "nouvelle...": "Nouvelle...",
+ "obs.préfixDesSources": "Préfix des sources",
+ "pays": "Pays",
+ "poids": "Poids",
+ "poule": "Poule",
+ "poulePour": "Poule pour: ",
+ "préparation...": "Préparation...",
+ "rouge": "Rouge",
+ "réinitialiser": "Réinitialiser",
+ "résultat": "Résultat",
+ "sansPoule": "Sans poule",
+ "sauvegarde": "Sauvegarde",
+ "sauvegarder": "Sauvegarder",
+ "score": "Score",
+ "score.err1": "Impossible de terminer un match nul en tournois.",
+ "score.spe": "Score speciaux : -997 : disqualifié -998 : absent -999 : forfait",
+ "scores": "Scores",
+ "secrétariatsDeLice": "Secrétariats de lice",
+ "select.aucunCombattantDisponible": "Aucun combattant disponible",
+ "select.aucunCombattantSélectionné": "Aucun combattant sélectionné",
+ "select.msg1": "(0 = désactivé)",
+ "select.recherche": "Recherche",
+ "select.sélectionnerDesCombatants": "Sélectionner des combatants",
+ "select.à": "à",
+ "serveur": "Serveur",
+ "suivant": "Suivant",
+ "supprimer": "Supprimer",
+ "sélectionneLesModesDaffichage": "Sélectionne les modes d'affichage",
+ "sélectionner": "Sélectionner",
+ "terminé": "Terminé",
+ "texteCopiéDansLePresse": "Texte copié dans le presse-papier ! Collez-le dans une balise HTML sur votre WordPress.",
+ "toast.createCategory.error": "Erreur lors de la création de la catégorie",
+ "toast.createCategory.pending": "Création de la catégorie...",
+ "toast.createCategory.success": "Catégorie créée !",
+ "toast.deleteCategory.error": "Erreur lors de la suppression de la catégorie",
+ "toast.deleteCategory.pending": "Suppression de la catégorie...",
+ "toast.deleteCategory.success": "Catégorie supprimée !",
+ "toast.matchs.create.error": "Erreur lors de la création des matchs.",
+ "toast.matchs.create.pending": "Création des matchs en cours...",
+ "toast.matchs.create.success": "Matchs créés avec succès.",
+ "toast.updateCategory.error": "Erreur lors de la mise à jour de la catégorie",
+ "toast.updateCategory.pending": "Mise à jour de la catégorie...",
+ "toast.updateCategory.success": "Catégorie mise à jour !",
+ "toast.updateMatchScore.error": "Erreur lors de la mise à jour du score du match",
+ "toast.updateMatchScore.pending": "Mise à jour du score du match...",
+ "toast.updateMatchScore.success": "Score du match mis à jour !",
+ "toast.updateTrees.error": "Erreur lors de la mise à jour des arbres",
+ "toast.updateTrees.init.error": "Erreur lors de la création des arbres",
+ "toast.updateTrees.init.pending": "Création des arbres du tournoi...",
+ "toast.updateTrees.init.success": "Arbres créés !",
+ "toast.updateTrees.pending": "Mise à jour des arbres du tournoi...",
+ "toast.updateTrees.success": "Arbres mis à jour !",
+ "tournoi": "Tournoi",
+ "tournois": "Tournois",
+ "tousLesMatchs": "Tous les matchs",
+ "toutConserver": "Tout conserver",
+ "ttm.admin.obs": "Clique court : Télécharger les ressources. Clique long : Créer la configuration obs",
+ "ttm.admin.scripte": "Copier le scripte d'intégration",
+ "ttm.table.inverserLaPosition": "Inverser la position des combattants sur cette écran",
+ "ttm.table.obs": "Clique court : Charger la configuration et se connecter. Clique long : Configuration de la lice",
+ "ttm.table.pub_aff": "Ouvrir l'affichage public",
+ "ttm.table.pub_score": "Afficher les scores sur l'affichage public",
+ "type": "Type",
+ "téléchargement": "Téléchargement",
+ "téléchargementEnCours": "Téléchargement en cours...",
+ "téléchargementTerminé!": "Téléchargement terminé !",
+ "uneCatégorie": "une catégorie",
+ "valider": "Valider",
+ "zone": "Zone",
+ "zoneDeCombat": "Zone de combat"
+}
diff --git a/src/main/webapp/src/pages/competition/editor/CMAdmin.jsx b/src/main/webapp/src/pages/competition/editor/CMAdmin.jsx
index bbbaf72..ced95a6 100644
--- a/src/main/webapp/src/pages/competition/editor/CMAdmin.jsx
+++ b/src/main/webapp/src/pages/competition/editor/CMAdmin.jsx
@@ -12,6 +12,9 @@ import {SimpleIconsOBS} from "../../../assets/SimpleIconsOBS.ts";
import JSZip from "jszip";
import {detectOptimalBackground} from "../../../components/SmartLogoBackground.jsx";
import {faGlobe} from "@fortawesome/free-solid-svg-icons";
+import {Trans, useTranslation} from "react-i18next";
+import i18n from "i18next";
+import {getToastMessage} from "../../../utils/Tools.js";
const vite_url = import.meta.env.VITE_URL;
@@ -139,7 +142,7 @@ async function downloadResourcesAsZip(resourceList) {
completed++;
const progress = Math.round((completed / resourceList.length) * 100);
progressBar.style.width = `${progress}%`;
- progressText.textContent = `Téléchargement (${completed}/${resourceList.length}) : ${result.filename}`;
+ progressText.textContent = `${i18n.t('téléchargement')} (${completed}/${resourceList.length}) : ${result.filename}`;
return result;
})
);
@@ -155,13 +158,14 @@ async function downloadResourcesAsZip(resourceList) {
// Fermer la modale
modal.hide();
- progressText.textContent = "Téléchargement terminé !";
+ progressText.textContent = i18n.t('téléchargementTerminé!');
}
function Menu({menuActions, compUuid}) {
const e = document.getElementById("actionMenu")
const longPress = useRef({time: null, timer: null, button: null});
const obsModal = useRef(null);
+ const {t} = useTranslation("cm");
for (const x of tto)
x.dispose();
@@ -224,9 +228,9 @@ function Menu({menuActions, compUuid}) {
initCompetitionApi("${vite_url}/api/public/result/${compUuid}")
`
).then(() => {
- toast.success("Texte copié dans le presse-papier ! Collez-le dans une balise HTML sur votre WordPress.");
+ toast.success(t('texteCopiéDansLePresse'));
}).catch(err => {
- toast.error("Erreur lors de la copie dans le presse-papier : " + err);
+ toast.error(t('erreurLorsDeLaCopieDansLePresse') + err);
});
}
@@ -241,12 +245,12 @@ function Menu({menuActions, compUuid}) {
onMouseDown={() => longPressDown("obs")}
onMouseUp={() => longPressUp("obs")}
data-bs-toggle="tooltip2" data-bs-placement="top"
- data-bs-title="Clique court : Télécharger les ressources. Clique long : Créer la configuration obs"/>
+ data-bs-title={t('ttm.admin.obs')}/>
copyScriptToClipboard()}
data-bs-toggle="tooltip2" data-bs-placement="top"
- data-bs-title="Copier le scripte d'intégration"/>
+ data-bs-title={t('ttm.admin.scripte')}/>
>, document.getElementById("actionMenu"))}