diff --git a/frontend/app/locales/fr.json b/frontend/app/locales/fr.json
new file mode 100644
index 00000000..3d20c430
--- /dev/null
+++ b/frontend/app/locales/fr.json
@@ -0,0 +1,163 @@
+{
+ "auth.back": "Retour",
+ "auth.email-address": "Adresse email",
+ "auth.loading": "Chargement...",
+ "auth.oauth-button": "Connexion avec {provider}",
+ "auth.or": "ou",
+ "auth.signin": "Se connecter",
+ "auth.submit": "Soumettre",
+ "auth.symbols-restriction": "Le nom d'utilisateur ne doit contenir que des lettres, nombres, tirets bas et espaces.",
+ "auth.user-not-found": "Aucun utilisateur n'a été trouvé",
+ "auth.username": "Nom d'utilisateur",
+ "authPanel.disable-comments": "Désactiver les commentaires",
+ "authPanel.disabled-cookies": "Activez les cookies pour vous connecter ou ouvrez les commentaires dans une",
+ "authPanel.enable-comments": "Activer les commentaires",
+ "authPanel.enable-cookies": "Activez les cookies pour vous connecter et commenter",
+ "authPanel.hide-settings": "Cacher les paramètres",
+ "authPanel.logged-as": "Vous êtes connecté en tant que",
+ "authPanel.logout": "Se déconnecter",
+ "authPanel.new-page": "nouvelle page",
+ "authPanel.read-only": "Lecture seule",
+ "authPanel.request-to-delete-data": "Demander la suppression de mes données",
+ "authPanel.show-settings": "Afficher les paramètres",
+ "blockingDuration.day": "pour un jour",
+ "blockingDuration.month": "pour un mois",
+ "blockingDuration.permanently": "définitivement",
+ "blockingDuration.week": "pour une semaine",
+ "comment.block": "Bloquer",
+ "comment.block-user": "Voulez-vous bloquer {userName} {duration} ?",
+ "comment.blocked-user": "Bloqué",
+ "comment.blocking-period": "Durée de blocage",
+ "comment.cancel": "Annuler",
+ "comment.controversy": "Controverse : {value}",
+ "comment.copied": "Copié !",
+ "comment.copy": "Copier",
+ "comment.delete": "Supprimer",
+ "comment.delete-message": "Voulez-vous supprimer ce commentaire ?",
+ "comment.deleted-comment": "Ce commentaire a été supprimé",
+ "comment.deleted-user": "Supprimé",
+ "comment.edit": "Modifier",
+ "comment.expired-time": "La période de modification est expirée.",
+ "comment.go-to-parent": "Aller au commentaire parent",
+ "comment.hide": "Cacher",
+ "comment.hide-user-comment": "Voulez-vous cacher les commentaires de {userName} ?",
+ "comment.pin": "Epingler",
+ "comment.pin-comment": "Voulez-vous épingler ce commentaire ?",
+ "comment.reply": "Répondre",
+ "comment.time": "{day} à {time}",
+ "comment.toggle-verification": "Définir le statut de vérification",
+ "comment.unblock": "Débloquer",
+ "comment.unblock-user": "Voulez-vous débloquer cet utilisateur ?",
+ "comment.unpin": "Désépingler",
+ "comment.unpin-comment": "Voulez-vous désépingler ce commentaire ?",
+ "comment.unverified-user": "Utilisateur non vérifié",
+ "comment.unverify-user": "Voulez-vous marquer {userName} comme non vérifié ?",
+ "comment.verified-user": "Utilisateur vérifié",
+ "comment.verify-user": "Voulez-vous marquer {userName} comme vérifié ?",
+ "comment.vote-error": "Erreur lors du vote : {voteErrorMessage}",
+ "commentForm.anonymous-uploading-disabled": "Le partage d'images est désactivé pour les utilisateurs anonymes. Veuillez vous connecter.",
+ "commentForm.exceeded-size": "Le fichier {fileName} dépasse la taille limite de {maxImageSize}",
+ "commentForm.input-placeholder": "Votre commentaire ici",
+ "commentForm.new-comment": "Nouveau commentaire",
+ "commentForm.notice-about-styling": "La syntaxe Markdown est supportée",
+ "commentForm.preview": "Prévisualiser",
+ "commentForm.reply": "Répondre",
+ "commentForm.save": "Enregistrer",
+ "commentForm.send": "Envoyer",
+ "commentForm.subscribe-by": "Suivre par",
+ "commentForm.subscribe-or": "ou",
+ "commentForm.unauthorized-uploading-disabled": "Le partage d'images est désactivé pour les utilisateurs non autorisés. Veuillez vous connecter.",
+ "commentForm.unexpected-error": "Quelque chose s'est mal passé. Veuillez réessayer plus tard.",
+ "commentForm.upload-file-fail": "Le téléchargement de {fileName} a échoué : \"{errorMessage}\"",
+ "commentForm.uploading": "Téléchargement en cours...",
+ "commentForm.uploading-file": "téléchargement de {fileName}...",
+ "commentSort.sort-by": "Tri : ",
+ "commentsSort.best": "Le meilleur en premier",
+ "commentsSort.least-controversial": "Le moins controversé en premier",
+ "commentsSort.least-recently-updated": "Mis à jour le moins récemment en premier",
+ "commentsSort.most-controversial": "Le plus controversé en premier",
+ "commentsSort.newest": "Le plus récent en premier",
+ "commentsSort.oldest": "Le plus vieux en premier",
+ "commentsSort.recently-updated": "Mis à jour le plus récemment en premier",
+ "commentsSort.worst": "Le pire en premier",
+ "errors.0": "Quelque chose s'est mal passé. Veuillez réessayer plus tard.",
+ "errors.1": "Commentaire introuvable. Rafraichissez la page et réessayez.",
+ "errors.10": "La période d'édition de ce commentaire a expiré, vous ne pouvez plus l'éditer.",
+ "errors.11": "Il y a déjà des réponses à ce commentaire, vous ne pouvez plus l'éditer.",
+ "errors.12": "Impossible d'enregistrer votre vote. Veuillez réessayer plus tard.",
+ "errors.13": "Vous ne pouvez pas voter pour votre propre commentaire.",
+ "errors.14": "Vous avez déjà voté pour ce commentaire.",
+ "errors.15": "Il y a trop de votes pour ce commentaire.",
+ "errors.16": "Le score de ce commentaire ne peut pas descendre plus bas.",
+ "errors.17": "Action rejetée. Veuillez réessayer plus tard.",
+ "errors.18": "Le fichier demandé ne peut pas être trouvé.",
+ "errors.2": "Failed to unmarshal incoming request.",
+ "errors.3": "Vous n'avez pas l'autorisation de faire ceci.",
+ "errors.4": "Données de commentaire invalides.",
+ "errors.5": "Commentaire introuvable. Rafraichissez la page et réessayez.",
+ "errors.6": "Site introuvable. Rafraichissez la page et réessayez.",
+ "errors.7": "L'utilisateur a été bloqué.",
+ "errors.8": "L'utilisateur a été bloqué.",
+ "errors.9": "Comment changing failed. Please try again a bit later.",
+ "errors.failed-fetch": "Impossible de récupérer les donnés. Veuillez vérifier votre connexion Internet ou réessayez plus tard",
+ "errors.forbidden": "Interdit.",
+ "errors.not-authorized": "Non autorisé.",
+ "errors.to-many-request": "You have reached maximum request limit.",
+ "errors.unexpected-error": "Une erreur inattendue s'est produite.",
+ "root.pinned-comments": "Commentaires épinglés",
+ "root.powered-by": "Propulsé par Remark42",
+ "root.show-more": "Afficher plus",
+ "settings.block": "bloquer",
+ "settings.block-time": "jusqu'au {day} à {time}",
+ "settings.block-user": "Voulez-vous bloquer {userName} ?",
+ "settings.blocked-users-header": "Utilisateurs bloqués :",
+ "settings.blocked-users-title": "Utilisateurs bloqués",
+ "settings.hidden-user-header": "Utilisateurs cachés :",
+ "settings.hidden-users-title": "Utilisateurs cachés",
+ "settings.hide": "cacher",
+ "settings.no-blocked-users": "Il n'y a pas d'utilisateurs bloqués.",
+ "settings.no-hidden-users": "Il n'y a pas d'utilisateurs cachés.",
+ "settings.permanently": "définitivement",
+ "settings.show": "afficher",
+ "settings.unblock": "débloquer",
+ "settings.unblock-user": "Voulez-vous débloquer {userName} ?",
+ "settings.unknown": "inconnu",
+ "subscribeByEmail.back": "Retour",
+ "subscribeByEmail.close": "Fermer",
+ "subscribeByEmail.email": "Email",
+ "subscribeByEmail.have-been-subscribed": "Vous vous êtes abonné par email aux mises à jour",
+ "subscribeByEmail.have-been-unsubscribed": "Votre abonnement par email aux mises à jour a été interrompu.",
+ "subscribeByEmail.only-registered-users": "Disponible uniquement aux utilisateurs enregistrés",
+ "subscribeByEmail.submit": "Soumettre",
+ "subscribeByEmail.subscribe": "S'abonner",
+ "subscribeByEmail.subscribe-by-email": "S'abonner par email",
+ "subscribeByEmail.subscribe-to-replies": "S'abonner aux réponses",
+ "subscribeByEmail.subscribed": "Vous êtes abonné par email aux mises à jour",
+ "subscribeByEmail.unsubscribe": "Se désabonner",
+ "subscribeByRSS.button-title": "S'abonner au flux RSS",
+ "subscribeByRSS.replies": "Réponses",
+ "subscribeByRSS.site": "Site",
+ "subscribeByRSS.thread": "Sujet",
+ "subscribeByRSS.title": "RSS",
+ "token": "Jeton",
+ "token.expired": "Le jeton a expiré",
+ "token.invalid": "Le jeton est invalide",
+ "toolbar.attach-image": "Cliquez pour joindre une image, glissez-déposez-la ou collez-la du presse-papier",
+ "toolbar.bold": "Ajouter du texte en gras {shortcut}",
+ "toolbar.code": "Insérer du code",
+ "toolbar.header": "Ajouter un titre",
+ "toolbar.italic": "Ajouter du texte en italique {shortcut}",
+ "toolbar.link": "Ajouter un lien {shortcut}",
+ "toolbar.ordered-list": "Ajouter une liste numérotée",
+ "toolbar.quote": "Insérer une citation",
+ "toolbar.unordered-list": "Ajouter une liste à puces",
+ "user-info.last-comments": "Derniers commentaires par {userName}",
+ "user-info.unexpected-error": "Quelque chose s'est mal passé",
+ "vote.anonymous": "Les utilisateurs anonymes ne peuvent pas voter",
+ "vote.deleted": "Vous ne pouvez pas voter pour un commentaire supprimé",
+ "vote.guest": "Connectez-vous pour voter",
+ "vote.only-positive": "Vous ne pouvez voter que positivement",
+ "vote.only-post-page": "Vous ne pouvez voter que sur la page de l'article",
+ "vote.own-comment": "Vous ne pouvez pas voter pour votre propre commentaire.",
+ "vote.readonly": "Vous ne pouvez pas voter sur un sujet en lecture seule"
+}
diff --git a/frontend/app/utils/getLocale.ts b/frontend/app/utils/getLocale.ts
index e042b0db..0b32343d 100644
--- a/frontend/app/utils/getLocale.ts
+++ b/frontend/app/utils/getLocale.ts
@@ -1,3 +1,3 @@
export function getLocale(params: { locale?: string; [key: string]: unknown }): string {
- return params.locale || 'en';
+ return params.locale || 'fr';
}
diff --git a/frontend/app/utils/loadLocale.ts b/frontend/app/utils/loadLocale.ts
index 187b516a..8e23275e 100644
--- a/frontend/app/utils/loadLocale.ts
+++ b/frontend/app/utils/loadLocale.ts
@@ -36,6 +36,9 @@ export async function loadLocale(locale: string): Promise
if (locale === 'be') {
return import(/* webpackChunkName: "be" */ '../locales/be.json').then((res) => res.default).catch(() => enMessages);
}
+ if (locale === 'fr') {
+ return import(/* webpackChunkName: "fr" */ '../locales/fr.json').then((res) => res.default).catch(() => enMessages);
+ }
return enMessages;
}
diff --git a/frontend/tasks/supportedLocales.json b/frontend/tasks/supportedLocales.json
index 2c49a0f5..8373bb68 100644
--- a/frontend/tasks/supportedLocales.json
+++ b/frontend/tasks/supportedLocales.json
@@ -1 +1 @@
-["en", "ru", "de", "fi", "es", "zh", "tr", "bg", "ua", "pl", "vi", "be"]
+["en", "ru", "de", "fi", "es", "zh", "tr", "bg", "ua", "pl", "vi", "be", "fr"]