diff --git a/packages/app/src/context/language.tsx b/packages/app/src/context/language.tsx index 91b514de3..7d65af75e 100644 --- a/packages/app/src/context/language.tsx +++ b/packages/app/src/context/language.tsx @@ -8,18 +8,20 @@ import { dict as zh } from "@/i18n/zh" import { dict as ko } from "@/i18n/ko" import { dict as de } from "@/i18n/de" import { dict as es } from "@/i18n/es" +import { dict as fr } from "@/i18n/fr" import { dict as uiEn } from "@opencode-ai/ui/i18n/en" import { dict as uiZh } from "@opencode-ai/ui/i18n/zh" import { dict as uiKo } from "@opencode-ai/ui/i18n/ko" import { dict as uiDe } from "@opencode-ai/ui/i18n/de" import { dict as uiEs } from "@opencode-ai/ui/i18n/es" +import { dict as uiFr } from "@opencode-ai/ui/i18n/fr" -export type Locale = "en" | "zh" | "ko" | "de" | "es" +export type Locale = "en" | "zh" | "ko" | "de" | "es" | "fr" type RawDictionary = typeof en & typeof uiEn type Dictionary = i18n.Flatten -const LOCALES: readonly Locale[] = ["en", "zh", "ko", "de", "es"] +const LOCALES: readonly Locale[] = ["en", "zh", "ko", "de", "es", "fr"] function detectLocale(): Locale { if (typeof navigator !== "object") return "en" @@ -31,6 +33,7 @@ function detectLocale(): Locale { if (language.toLowerCase().startsWith("ko")) return "ko" if (language.toLowerCase().startsWith("de")) return "de" if (language.toLowerCase().startsWith("es")) return "es" + if (language.toLowerCase().startsWith("fr")) return "fr" } return "en" @@ -51,6 +54,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont if (store.locale === "ko") return "ko" if (store.locale === "de") return "de" if (store.locale === "es") return "es" + if (store.locale === "fr") return "fr" return "en" }) @@ -66,6 +70,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont if (locale() === "zh") return { ...base, ...i18n.flatten({ ...zh, ...uiZh }) } if (locale() === "de") return { ...base, ...i18n.flatten({ ...de, ...uiDe }) } if (locale() === "es") return { ...base, ...i18n.flatten({ ...es, ...uiEs }) } + if (locale() === "fr") return { ...base, ...i18n.flatten({ ...fr, ...uiFr }) } return { ...base, ...i18n.flatten({ ...ko, ...uiKo }) } }) @@ -77,6 +82,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont ko: "language.ko", de: "language.de", es: "language.es", + fr: "language.fr", } const label = (value: Locale) => t(labelKey[value]) diff --git a/packages/app/src/i18n/de.ts b/packages/app/src/i18n/de.ts index ebb45f967..81b14b329 100644 --- a/packages/app/src/i18n/de.ts +++ b/packages/app/src/i18n/de.ts @@ -277,6 +277,7 @@ export const dict = { "language.ko": "Koreanisch", "language.de": "Deutsch", "language.es": "Spanisch", + "language.fr": "Französisch", "toast.language.title": "Sprache", "toast.language.description": "Zu {{language}} gewechselt", diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index 6a020eeab..81d3f1043 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -271,6 +271,7 @@ export const dict = { "language.ko": "Korean", "language.de": "German", "language.es": "Spanish", + "language.fr": "French", "toast.language.title": "Language", "toast.language.description": "Switched to {{language}}", diff --git a/packages/app/src/i18n/es.ts b/packages/app/src/i18n/es.ts index d5fef0487..16c70853f 100644 --- a/packages/app/src/i18n/es.ts +++ b/packages/app/src/i18n/es.ts @@ -272,6 +272,7 @@ export const dict = { "language.ko": "Coreano", "language.de": "Alemán", "language.es": "Español", + "language.fr": "Francés", "toast.language.title": "Idioma", "toast.language.description": "Cambiado a {{language}}", diff --git a/packages/app/src/i18n/fr.ts b/packages/app/src/i18n/fr.ts new file mode 100644 index 000000000..6b03aee14 --- /dev/null +++ b/packages/app/src/i18n/fr.ts @@ -0,0 +1,562 @@ +export const dict = { + "command.category.suggested": "Suggéré", + "command.category.view": "Affichage", + "command.category.project": "Projet", + "command.category.provider": "Fournisseur", + "command.category.server": "Serveur", + "command.category.session": "Session", + "command.category.theme": "Thème", + "command.category.language": "Langue", + "command.category.file": "Fichier", + "command.category.terminal": "Terminal", + "command.category.model": "Modèle", + "command.category.mcp": "MCP", + "command.category.agent": "Agent", + "command.category.permissions": "Permissions", + + "theme.scheme.system": "Système", + "theme.scheme.light": "Clair", + "theme.scheme.dark": "Sombre", + + "command.sidebar.toggle": "Basculer la barre latérale", + "command.project.open": "Ouvrir un projet", + "command.provider.connect": "Connecter un fournisseur", + "command.server.switch": "Changer de serveur", + "command.session.previous": "Session précédente", + "command.session.next": "Session suivante", + "command.session.archive": "Archiver la session", + + "command.palette": "Palette de commandes", + + "command.theme.cycle": "Changer de thème", + "command.theme.set": "Utiliser le thème : {{theme}}", + "command.theme.scheme.cycle": "Changer de schéma de couleurs", + "command.theme.scheme.set": "Utiliser le schéma de couleurs : {{scheme}}", + + "command.language.cycle": "Changer de langue", + "command.language.set": "Utiliser la langue : {{language}}", + + "command.session.new": "Nouvelle session", + "command.file.open": "Ouvrir un fichier", + "command.file.open.description": "Rechercher des fichiers et des commandes", + "command.terminal.toggle": "Basculer le terminal", + "command.review.toggle": "Basculer la revue", + "command.terminal.new": "Nouveau terminal", + "command.terminal.new.description": "Créer un nouvel onglet de terminal", + "command.steps.toggle": "Basculer les étapes", + "command.steps.toggle.description": "Afficher ou masquer les étapes du message actuel", + "command.message.previous": "Message précédent", + "command.message.previous.description": "Aller au message utilisateur précédent", + "command.message.next": "Message suivant", + "command.message.next.description": "Aller au message utilisateur suivant", + "command.model.choose": "Choisir le modèle", + "command.model.choose.description": "Sélectionner un modèle différent", + "command.mcp.toggle": "Basculer MCP", + "command.mcp.toggle.description": "Basculer les MCPs", + "command.agent.cycle": "Changer d'agent", + "command.agent.cycle.description": "Passer à l'agent suivant", + "command.agent.cycle.reverse": "Changer d'agent (inverse)", + "command.agent.cycle.reverse.description": "Passer à l'agent précédent", + "command.model.variant.cycle": "Changer l'effort de réflexion", + "command.model.variant.cycle.description": "Passer au niveau d'effort suivant", + "command.permissions.autoaccept.enable": "Accepter automatiquement les modifications", + "command.permissions.autoaccept.disable": "Arrêter l'acceptation automatique des modifications", + "command.session.undo": "Annuler", + "command.session.undo.description": "Annuler le dernier message", + "command.session.redo": "Rétablir", + "command.session.redo.description": "Rétablir le dernier message annulé", + "command.session.compact": "Compacter la session", + "command.session.compact.description": "Résumer la session pour réduire la taille du contexte", + "command.session.fork": "Bifurquer à partir du message", + "command.session.fork.description": "Créer une nouvelle session à partir d'un message précédent", + "command.session.share": "Partager la session", + "command.session.share.description": "Partager cette session et copier l'URL dans le presse-papiers", + "command.session.unshare": "Ne plus partager la session", + "command.session.unshare.description": "Arrêter de partager cette session", + + "palette.search.placeholder": "Rechercher des fichiers et des commandes", + "palette.empty": "Aucun résultat trouvé", + "palette.group.commands": "Commandes", + "palette.group.files": "Fichiers", + + "dialog.provider.search.placeholder": "Rechercher des fournisseurs", + "dialog.provider.empty": "Aucun fournisseur trouvé", + "dialog.provider.group.popular": "Populaire", + "dialog.provider.group.other": "Autre", + "dialog.provider.tag.recommended": "Recommandé", + "dialog.provider.anthropic.note": "Connectez-vous avec Claude Pro/Max ou une clé API", + + "dialog.model.select.title": "Sélectionner un modèle", + "dialog.model.search.placeholder": "Rechercher des modèles", + "dialog.model.empty": "Aucun résultat de modèle", + "dialog.model.manage": "Gérer les modèles", + "dialog.model.manage.description": "Personnalisez les modèles qui apparaissent dans le sélecteur.", + + "dialog.model.unpaid.freeModels.title": "Modèles gratuits fournis par OpenCode", + "dialog.model.unpaid.addMore.title": "Ajouter plus de modèles de fournisseurs populaires", + + "dialog.provider.viewAll": "Voir tous les fournisseurs", + + "provider.connect.title": "Connecter {{provider}}", + "provider.connect.title.anthropicProMax": "Connexion avec Claude Pro/Max", + "provider.connect.selectMethod": "Sélectionnez la méthode de connexion pour {{provider}}.", + "provider.connect.method.apiKey": "Clé API", + "provider.connect.status.inProgress": "Autorisation en cours...", + "provider.connect.status.waiting": "En attente d'autorisation...", + "provider.connect.status.failed": "Échec de l'autorisation : {{error}}", + "provider.connect.apiKey.description": + "Entrez votre clé API {{provider}} pour connecter votre compte et utiliser les modèles {{provider}} dans OpenCode.", + "provider.connect.apiKey.label": "Clé API {{provider}}", + "provider.connect.apiKey.placeholder": "Clé API", + "provider.connect.apiKey.required": "La clé API est requise", + "provider.connect.opencodeZen.line1": + "OpenCode Zen vous donne accès à un ensemble sélectionné de modèles fiables et optimisés pour les agents de codage.", + "provider.connect.opencodeZen.line2": + "Avec une seule clé API, vous aurez accès à des modèles tels que Claude, GPT, Gemini, GLM et plus encore.", + "provider.connect.opencodeZen.visit.prefix": "Visitez ", + "provider.connect.opencodeZen.visit.suffix": " pour récupérer votre clé API.", + "provider.connect.oauth.code.visit.prefix": "Visitez ", + "provider.connect.oauth.code.visit.link": "ce lien", + "provider.connect.oauth.code.visit.suffix": + " pour récupérer votre code d'autorisation afin de connecter votre compte et utiliser les modèles {{provider}} dans OpenCode.", + "provider.connect.oauth.code.label": "Code d'autorisation {{method}}", + "provider.connect.oauth.code.placeholder": "Code d'autorisation", + "provider.connect.oauth.code.required": "Le code d'autorisation est requis", + "provider.connect.oauth.code.invalid": "Code d'autorisation invalide", + "provider.connect.oauth.auto.visit.prefix": "Visitez ", + "provider.connect.oauth.auto.visit.link": "ce lien", + "provider.connect.oauth.auto.visit.suffix": + " et entrez le code ci-dessous pour connecter votre compte et utiliser les modèles {{provider}} dans OpenCode.", + "provider.connect.oauth.auto.confirmationCode": "Code de confirmation", + "provider.connect.toast.connected.title": "{{provider}} connecté", + "provider.connect.toast.connected.description": "Les modèles {{provider}} sont maintenant disponibles.", + + "model.tag.free": "Gratuit", + "model.tag.latest": "Dernier", + + "common.search.placeholder": "Rechercher", + "common.loading": "Chargement", + "common.cancel": "Annuler", + "common.submit": "Soumettre", + "common.save": "Enregistrer", + "common.saving": "Enregistrement...", + "common.default": "Défaut", + "common.attachment": "pièce jointe", + + "prompt.placeholder.shell": "Entrez une commande shell...", + "prompt.placeholder.normal": 'Demandez n\'importe quoi... "{{example}}"', + "prompt.mode.shell": "Shell", + "prompt.mode.shell.exit": "esc pour quitter", + + "prompt.example.1": "Corriger un TODO dans la base de code", + "prompt.example.2": "Quelle est la pile technique de ce projet ?", + "prompt.example.3": "Réparer les tests échoués", + "prompt.example.4": "Expliquer comment fonctionne l'authentification", + "prompt.example.5": "Trouver et corriger les vulnérabilités de sécurité", + "prompt.example.6": "Ajouter des tests unitaires pour le service utilisateur", + "prompt.example.7": "Refactoriser cette fonction pour être plus lisible", + "prompt.example.8": "Que signifie cette erreur ?", + "prompt.example.9": "Aidez-moi à déboguer ce problème", + "prompt.example.10": "Générer la documentation de l'API", + "prompt.example.11": "Optimiser les requêtes de base de données", + "prompt.example.12": "Ajouter une validation d'entrée", + "prompt.example.13": "Créer un nouveau composant pour...", + "prompt.example.14": "Comment déployer ce projet ?", + "prompt.example.15": "Vérifier mon code pour les meilleures pratiques", + "prompt.example.16": "Ajouter la gestion des erreurs à cette fonction", + "prompt.example.17": "Expliquer ce modèle regex", + "prompt.example.18": "Convertir ceci en TypeScript", + "prompt.example.19": "Ajouter des logs dans toute la base de code", + "prompt.example.20": "Quelles dépendances sont obsolètes ?", + "prompt.example.21": "Aidez-moi à écrire un script de migration", + "prompt.example.22": "Implémenter la mise en cache pour ce point de terminaison", + "prompt.example.23": "Ajouter la pagination à cette liste", + "prompt.example.24": "Créer une commande CLI pour...", + "prompt.example.25": "Comment fonctionnent les variables d'environnement ici ?", + + "prompt.popover.emptyResults": "Aucun résultat correspondant", + "prompt.popover.emptyCommands": "Aucune commande correspondante", + "prompt.dropzone.label": "Déposez des images ou des PDF ici", + "prompt.slash.badge.custom": "personnalisé", + "prompt.context.active": "actif", + "prompt.context.includeActiveFile": "Inclure le fichier actif", + "prompt.action.attachFile": "Joindre un fichier", + "prompt.action.send": "Envoyer", + "prompt.action.stop": "Arrêter", + + "prompt.toast.pasteUnsupported.title": "Collage non supporté", + "prompt.toast.pasteUnsupported.description": "Seules les images ou les PDF peuvent être collés ici.", + "prompt.toast.modelAgentRequired.title": "Sélectionnez un agent et un modèle", + "prompt.toast.modelAgentRequired.description": "Choisissez un agent et un modèle avant d'envoyer un message.", + "prompt.toast.worktreeCreateFailed.title": "Échec de la création de l'arbre de travail", + "prompt.toast.sessionCreateFailed.title": "Échec de la création de la session", + "prompt.toast.shellSendFailed.title": "Échec de l'envoi de la commande shell", + "prompt.toast.commandSendFailed.title": "Échec de l'envoi de la commande", + "prompt.toast.promptSendFailed.title": "Échec de l'envoi du message", + + "dialog.mcp.title": "MCPs", + "dialog.mcp.description": "{{enabled}} sur {{total}} activés", + "dialog.mcp.empty": "Aucun MCP configuré", + + "mcp.status.connected": "connecté", + "mcp.status.failed": "échoué", + "mcp.status.needs_auth": "nécessite auth", + "mcp.status.disabled": "désactivé", + + "dialog.fork.empty": "Aucun message à partir duquel bifurquer", + + "dialog.directory.search.placeholder": "Rechercher des dossiers", + "dialog.directory.empty": "Aucun dossier trouvé", + + "dialog.server.title": "Serveurs", + "dialog.server.description": "Changez le serveur OpenCode auquel cette application se connecte.", + "dialog.server.search.placeholder": "Rechercher des serveurs", + "dialog.server.empty": "Aucun serveur pour l'instant", + "dialog.server.add.title": "Ajouter un serveur", + "dialog.server.add.url": "URL du serveur", + "dialog.server.add.placeholder": "http://localhost:4096", + "dialog.server.add.error": "Impossible de se connecter au serveur", + "dialog.server.add.checking": "Vérification...", + "dialog.server.add.button": "Ajouter", + "dialog.server.default.title": "Serveur par défaut", + "dialog.server.default.description": + "Se connecter à ce serveur au lancement de l'application au lieu de démarrer un serveur local. Nécessite un redémarrage.", + "dialog.server.default.none": "Aucun serveur sélectionné", + "dialog.server.default.set": "Définir le serveur actuel comme défaut", + "dialog.server.default.clear": "Effacer", + + "dialog.project.edit.title": "Modifier le projet", + "dialog.project.edit.name": "Nom", + "dialog.project.edit.icon": "Icône", + "dialog.project.edit.icon.alt": "Icône du projet", + "dialog.project.edit.icon.hint": "Cliquez ou faites glisser une image", + "dialog.project.edit.icon.recommended": "Recommandé : 128x128px", + "dialog.project.edit.color": "Couleur", + + "context.breakdown.title": "Répartition du contexte", + "context.breakdown.note": + "Répartition approximative des jetons d'entrée. \"Autre\" inclut les définitions d'outils et les frais généraux.", + "context.breakdown.system": "Système", + "context.breakdown.user": "Utilisateur", + "context.breakdown.assistant": "Assistant", + "context.breakdown.tool": "Appels d'outils", + "context.breakdown.other": "Autre", + + "context.systemPrompt.title": "Prompt système", + "context.rawMessages.title": "Messages bruts", + + "context.stats.session": "Session", + "context.stats.messages": "Messages", + "context.stats.provider": "Fournisseur", + "context.stats.model": "Modèle", + "context.stats.limit": "Limite de contexte", + "context.stats.totalTokens": "Total des jetons", + "context.stats.usage": "Utilisation", + "context.stats.inputTokens": "Jetons d'entrée", + "context.stats.outputTokens": "Jetons de sortie", + "context.stats.reasoningTokens": "Jetons de raisonnement", + "context.stats.cacheTokens": "Jetons de cache (lecture/écriture)", + "context.stats.userMessages": "Messages utilisateur", + "context.stats.assistantMessages": "Messages assistant", + "context.stats.totalCost": "Coût total", + "context.stats.sessionCreated": "Session créée", + "context.stats.lastActivity": "Dernière activité", + + "context.usage.tokens": "Jetons", + "context.usage.usage": "Utilisation", + "context.usage.cost": "Coût", + "context.usage.clickToView": "Cliquez pour voir le contexte", + + "language.en": "Anglais", + "language.zh": "Chinois", + "language.ko": "Coréen", + "language.de": "Allemand", + "language.es": "Espagnol", + "language.fr": "Français", + + "toast.language.title": "Langue", + "toast.language.description": "Passé à {{language}}", + + "toast.theme.title": "Thème changé", + "toast.scheme.title": "Schéma de couleurs", + + "toast.permissions.autoaccept.on.title": "Acceptation auto des modifications", + "toast.permissions.autoaccept.on.description": + "Les permissions de modification et d'écriture seront automatiquement approuvées", + "toast.permissions.autoaccept.off.title": "Arrêt acceptation auto des modifications", + "toast.permissions.autoaccept.off.description": + "Les permissions de modification et d'écriture nécessiteront une approbation", + + "toast.model.none.title": "Aucun modèle sélectionné", + "toast.model.none.description": "Connectez un fournisseur pour résumer cette session", + + "toast.file.loadFailed.title": "Échec du chargement du fichier", + + "toast.session.share.copyFailed.title": "Échec de la copie de l'URL dans le presse-papiers", + "toast.session.share.success.title": "Session partagée", + "toast.session.share.success.description": "URL de partage copiée dans le presse-papiers !", + "toast.session.share.failed.title": "Échec du partage de la session", + "toast.session.share.failed.description": "Une erreur s'est produite lors du partage de la session", + + "toast.session.unshare.success.title": "Session non partagée", + "toast.session.unshare.success.description": "Session non partagée avec succès !", + "toast.session.unshare.failed.title": "Échec de l'annulation du partage", + "toast.session.unshare.failed.description": "Une erreur s'est produite lors de l'annulation du partage de la session", + + "toast.session.listFailed.title": "Échec du chargement des sessions pour {{project}}", + + "toast.update.title": "Mise à jour disponible", + "toast.update.description": + "Une nouvelle version d'OpenCode ({{version}}) est maintenant disponible pour installation.", + "toast.update.action.installRestart": "Installer et redémarrer", + "toast.update.action.notYet": "Pas encore", + + "error.page.title": "Quelque chose s'est mal passé", + "error.page.description": "Une erreur s'est produite lors du chargement de l'application.", + "error.page.details.label": "Détails de l'erreur", + "error.page.action.restart": "Redémarrer", + "error.page.action.checking": "Vérification...", + "error.page.action.checkUpdates": "Vérifier les mises à jour", + "error.page.action.updateTo": "Mettre à jour vers {{version}}", + "error.page.report.prefix": "Veuillez signaler cette erreur à l'équipe OpenCode", + "error.page.report.discord": "sur Discord", + "error.page.version": "Version : {{version}}", + + "error.dev.rootNotFound": + "Élément racine introuvable. Avez-vous oublié de l'ajouter à votre index.html ? Ou peut-être que l'attribut id est mal orthographié ?", + + "error.globalSync.connectFailed": + "Impossible de se connecter au serveur. Y a-t-il un serveur en cours d'exécution à `{{url}}` ?", + + "error.chain.unknown": "Erreur inconnue", + "error.chain.causedBy": "Causé par :", + "error.chain.apiError": "Erreur API", + "error.chain.status": "Statut : {{status}}", + "error.chain.retryable": "Réessayable : {{retryable}}", + "error.chain.responseBody": "Corps de la réponse :\n{{body}}", + "error.chain.didYouMean": "Vouliez-vous dire : {{suggestions}}", + "error.chain.modelNotFound": "Modèle introuvable : {{provider}}/{{model}}", + "error.chain.checkConfig": "Vérifiez votre configuration (opencode.json) pour les noms de fournisseur/modèle", + "error.chain.mcpFailed": + "Le serveur MCP \"{{name}}\" a échoué. Notez qu'OpenCode ne supporte pas encore l'authentification MCP.", + "error.chain.providerAuthFailed": "Échec de l'authentification du fournisseur ({{provider}}) : {{message}}", + "error.chain.providerInitFailed": + 'Échec de l\'initialisation du fournisseur "{{provider}}". Vérifiez les identifiants et la configuration.', + "error.chain.configJsonInvalid": "Le fichier de configuration à {{path}} n'est pas un JSON(C) valide", + "error.chain.configJsonInvalidWithMessage": + "Le fichier de configuration à {{path}} n'est pas un JSON(C) valide : {{message}}", + "error.chain.configDirectoryTypo": + 'Le répertoire "{{dir}}" dans {{path}} n\'est pas valide. Renommez le répertoire en "{{suggestion}}" ou supprimez-le. C\'est une faute de frappe courante.', + "error.chain.configFrontmatterError": "Échec de l'analyse du frontmatter dans {{path}} :\n{{message}}", + "error.chain.configInvalid": "Le fichier de configuration à {{path}} est invalide", + "error.chain.configInvalidWithMessage": "Le fichier de configuration à {{path}} est invalide : {{message}}", + + "notification.permission.title": "Permission requise", + "notification.permission.description": "{{sessionTitle}} dans {{projectName}} a besoin d'une permission", + "notification.question.title": "Question", + "notification.question.description": "{{sessionTitle}} dans {{projectName}} a une question", + "notification.action.goToSession": "Aller à la session", + + "notification.session.responseReady.title": "Réponse prête", + "notification.session.error.title": "Erreur de session", + "notification.session.error.fallbackDescription": "Une erreur s'est produite", + + "home.recentProjects": "Projets récents", + "home.empty.title": "Aucun projet récent", + "home.empty.description": "Commencez par ouvrir un projet local", + + "session.tab.session": "Session", + "session.tab.review": "Revue", + "session.tab.context": "Contexte", + "session.review.filesChanged": "{{count}} fichiers modifiés", + "session.review.loadingChanges": "Chargement des modifications...", + "session.review.empty": "Aucune modification dans cette session pour l'instant", + "session.messages.renderEarlier": "Afficher les messages précédents", + "session.messages.loadingEarlier": "Chargement des messages précédents...", + "session.messages.loadEarlier": "Charger les messages précédents", + "session.messages.loading": "Chargement des messages...", + + "session.context.addToContext": "Ajouter {{selection}} au contexte", + + "session.new.worktree.main": "Branche principale", + "session.new.worktree.mainWithBranch": "Branche principale ({{branch}})", + "session.new.worktree.create": "Créer un nouvel arbre de travail", + "session.new.lastModified": "Dernière modification", + + "session.header.search.placeholder": "Rechercher {{project}}", + + "session.share.popover.title": "Publier sur le web", + "session.share.popover.description.shared": + "Cette session est publique sur le web. Elle est accessible à toute personne disposant du lien.", + "session.share.popover.description.unshared": + "Partager la session publiquement sur le web. Elle sera accessible à toute personne disposant du lien.", + "session.share.action.share": "Partager", + "session.share.action.publish": "Publier", + "session.share.action.publishing": "Publication...", + "session.share.action.unpublish": "Dépublier", + "session.share.action.unpublishing": "Dépublication...", + "session.share.action.view": "Voir", + "session.share.copy.copied": "Copié", + "session.share.copy.copyLink": "Copier le lien", + + "lsp.tooltip.none": "Aucun serveur LSP", + "lsp.label.connected": "{{count}} LSP", + + "prompt.loading": "Chargement du prompt...", + "terminal.loading": "Chargement du terminal...", + "terminal.title": "Terminal", + "terminal.title.numbered": "Terminal {{number}}", + + "common.closeTab": "Fermer l'onglet", + "common.dismiss": "Ignorer", + "common.requestFailed": "La demande a échoué", + "common.moreOptions": "Plus d'options", + "common.learnMore": "En savoir plus", + "common.rename": "Renommer", + "common.reset": "Réinitialiser", + "common.delete": "Supprimer", + "common.close": "Fermer", + "common.edit": "Modifier", + "common.loadMore": "Charger plus", + + "sidebar.settings": "Paramètres", + "sidebar.help": "Aide", + "sidebar.workspaces.enable": "Activer les espaces de travail", + "sidebar.workspaces.disable": "Désactiver les espaces de travail", + "sidebar.gettingStarted.title": "Commencer", + "sidebar.gettingStarted.line1": + "OpenCode inclut des modèles gratuits pour que vous puissiez commencer immédiatement.", + "sidebar.gettingStarted.line2": + "Connectez n'importe quel fournisseur pour utiliser des modèles, y compris Claude, GPT, Gemini etc.", + "sidebar.project.recentSessions": "Sessions récentes", + "sidebar.project.viewAllSessions": "Voir toutes les sessions", + + "settings.section.desktop": "Bureau", + "settings.tab.general": "Général", + "settings.tab.shortcuts": "Raccourcis", + + "settings.general.section.appearance": "Apparence", + "settings.general.section.notifications": "Notifications système", + "settings.general.section.sounds": "Effets sonores", + + "settings.general.row.language.title": "Langue", + "settings.general.row.language.description": "Changer la langue d'affichage pour OpenCode", + "settings.general.row.appearance.title": "Apparence", + "settings.general.row.appearance.description": "Personnaliser l'apparence d'OpenCode sur votre appareil", + "settings.general.row.theme.title": "Thème", + "settings.general.row.theme.description": "Personnaliser le thème d'OpenCode.", + "settings.general.row.font.title": "Police", + "settings.general.row.font.description": "Personnaliser la police mono utilisée dans les blocs de code", + + "settings.general.notifications.agent.title": "Agent", + "settings.general.notifications.agent.description": + "Afficher une notification système lorsque l'agent a terminé ou nécessite une attention", + "settings.general.notifications.permissions.title": "Permissions", + "settings.general.notifications.permissions.description": + "Afficher une notification système lorsqu'une permission est requise", + "settings.general.notifications.errors.title": "Erreurs", + "settings.general.notifications.errors.description": "Afficher une notification système lorsqu'une erreur se produit", + + "settings.general.sounds.agent.title": "Agent", + "settings.general.sounds.agent.description": "Jouer un son lorsque l'agent a terminé ou nécessite une attention", + "settings.general.sounds.permissions.title": "Permissions", + "settings.general.sounds.permissions.description": "Jouer un son lorsqu'une permission est requise", + "settings.general.sounds.errors.title": "Erreurs", + "settings.general.sounds.errors.description": "Jouer un son lorsqu'une erreur se produit", + + "settings.shortcuts.title": "Raccourcis clavier", + "settings.shortcuts.reset.button": "Rétablir les défauts", + "settings.shortcuts.reset.toast.title": "Raccourcis réinitialisés", + "settings.shortcuts.reset.toast.description": "Les raccourcis clavier ont été réinitialisés aux valeurs par défaut.", + "settings.shortcuts.conflict.title": "Raccourci déjà utilisé", + "settings.shortcuts.conflict.description": "{{keybind}} est déjà assigné à {{titles}}.", + "settings.shortcuts.unassigned": "Non assigné", + "settings.shortcuts.pressKeys": "Appuyez sur les touches", + + "settings.shortcuts.group.general": "Général", + "settings.shortcuts.group.session": "Session", + "settings.shortcuts.group.navigation": "Navigation", + "settings.shortcuts.group.modelAndAgent": "Modèle et agent", + "settings.shortcuts.group.terminal": "Terminal", + "settings.shortcuts.group.prompt": "Prompt", + + "settings.providers.title": "Fournisseurs", + "settings.providers.description": "Les paramètres des fournisseurs seront configurables ici.", + "settings.models.title": "Modèles", + "settings.models.description": "Les paramètres des modèles seront configurables ici.", + "settings.agents.title": "Agents", + "settings.agents.description": "Les paramètres des agents seront configurables ici.", + "settings.commands.title": "Commandes", + "settings.commands.description": "Les paramètres des commandes seront configurables ici.", + "settings.mcp.title": "MCP", + "settings.mcp.description": "Les paramètres MCP seront configurables ici.", + + "settings.permissions.title": "Permissions", + "settings.permissions.description": "Contrôlez les outils que le serveur peut utiliser par défaut.", + "settings.permissions.section.tools": "Outils", + "settings.permissions.toast.updateFailed.title": "Échec de la mise à jour des permissions", + + "settings.permissions.action.allow": "Autoriser", + "settings.permissions.action.ask": "Demander", + "settings.permissions.action.deny": "Refuser", + + "settings.permissions.tool.read.title": "Lire", + "settings.permissions.tool.read.description": "Lecture d'un fichier (correspond au chemin du fichier)", + "settings.permissions.tool.edit.title": "Modifier", + "settings.permissions.tool.edit.description": + "Modifier des fichiers, y compris les modifications, écritures, patchs et multi-modifications", + "settings.permissions.tool.glob.title": "Glob", + "settings.permissions.tool.glob.description": "Correspondre aux fichiers utilisant des modèles glob", + "settings.permissions.tool.grep.title": "Grep", + "settings.permissions.tool.grep.description": + "Rechercher dans le contenu des fichiers à l'aide d'expressions régulières", + "settings.permissions.tool.list.title": "Lister", + "settings.permissions.tool.list.description": "Lister les fichiers dans un répertoire", + "settings.permissions.tool.bash.title": "Bash", + "settings.permissions.tool.bash.description": "Exécuter des commandes shell", + "settings.permissions.tool.task.title": "Tâche", + "settings.permissions.tool.task.description": "Lancer des sous-agents", + "settings.permissions.tool.skill.title": "Compétence", + "settings.permissions.tool.skill.description": "Charger une compétence par son nom", + "settings.permissions.tool.lsp.title": "LSP", + "settings.permissions.tool.lsp.description": "Exécuter des requêtes de serveur de langage", + "settings.permissions.tool.todoread.title": "Lire Todo", + "settings.permissions.tool.todoread.description": "Lire la liste de tâches", + "settings.permissions.tool.todowrite.title": "Écrire Todo", + "settings.permissions.tool.todowrite.description": "Mettre à jour la liste de tâches", + "settings.permissions.tool.webfetch.title": "Récupération Web", + "settings.permissions.tool.webfetch.description": "Récupérer le contenu d'une URL", + "settings.permissions.tool.websearch.title": "Recherche Web", + "settings.permissions.tool.websearch.description": "Rechercher sur le web", + "settings.permissions.tool.codesearch.title": "Recherche de code", + "settings.permissions.tool.codesearch.description": "Rechercher du code sur le web", + "settings.permissions.tool.external_directory.title": "Répertoire externe", + "settings.permissions.tool.external_directory.description": "Accéder aux fichiers en dehors du répertoire du projet", + "settings.permissions.tool.doom_loop.title": "Boucle infernale", + "settings.permissions.tool.doom_loop.description": "Détecter les appels d'outils répétés avec une entrée identique", + + "workspace.new": "Nouvel espace de travail", + "workspace.type.local": "local", + "workspace.type.sandbox": "bac à sable", + "workspace.create.failed.title": "Échec de la création de l'espace de travail", + "workspace.delete.failed.title": "Échec de la suppression de l'espace de travail", + "workspace.resetting.title": "Réinitialisation de l'espace de travail", + "workspace.resetting.description": "Cela peut prendre une minute.", + "workspace.reset.failed.title": "Échec de la réinitialisation de l'espace de travail", + "workspace.reset.success.title": "Espace de travail réinitialisé", + "workspace.reset.success.description": "L'espace de travail correspond maintenant à la branche par défaut.", + "workspace.status.checking": "Vérification des modifications non fusionnées...", + "workspace.status.error": "Impossible de vérifier le statut git.", + "workspace.status.clean": "Aucune modification non fusionnée détectée.", + "workspace.status.dirty": "Modifications non fusionnées détectées dans cet espace de travail.", + "workspace.delete.title": "Supprimer l'espace de travail", + "workspace.delete.confirm": 'Supprimer l\'espace de travail "{{name}}" ?', + "workspace.delete.button": "Supprimer l'espace de travail", + "workspace.reset.title": "Réinitialiser l'espace de travail", + "workspace.reset.confirm": 'Réinitialiser l\'espace de travail "{{name}}" ?', + "workspace.reset.button": "Réinitialiser l'espace de travail", + "workspace.reset.archived.none": "Aucune session active ne sera archivée.", + "workspace.reset.archived.one": "1 session sera archivée.", + "workspace.reset.archived.many": "{{count}} sessions seront archivées.", + "workspace.reset.note": "Cela réinitialisera l'espace de travail pour correspondre à la branche par défaut.", +} diff --git a/packages/app/src/i18n/ko.ts b/packages/app/src/i18n/ko.ts index 87be2871f..fefb7c723 100644 --- a/packages/app/src/i18n/ko.ts +++ b/packages/app/src/i18n/ko.ts @@ -274,6 +274,7 @@ export const dict = { "language.ko": "한국어", "language.de": "독일어", "language.es": "스페인어", + "language.fr": "프랑스어", "toast.language.title": "언어", "toast.language.description": "{{language}}(으)로 전환됨", diff --git a/packages/app/src/i18n/zh.ts b/packages/app/src/i18n/zh.ts index 3c557ae8e..c0b6d7c15 100644 --- a/packages/app/src/i18n/zh.ts +++ b/packages/app/src/i18n/zh.ts @@ -270,6 +270,7 @@ export const dict = { "language.ko": "韩语", "language.de": "德语", "language.es": "西班牙语", + "language.fr": "法语", "toast.language.title": "语言", "toast.language.description": "已切换到{{language}}", diff --git a/packages/ui/src/i18n/fr.ts b/packages/ui/src/i18n/fr.ts new file mode 100644 index 000000000..abc01b3fe --- /dev/null +++ b/packages/ui/src/i18n/fr.ts @@ -0,0 +1,90 @@ +export const dict = { + "ui.sessionReview.title": "Modifications de la session", + "ui.sessionReview.diffStyle.unified": "Unifié", + "ui.sessionReview.diffStyle.split": "Divisé", + "ui.sessionReview.expandAll": "Tout développer", + "ui.sessionReview.collapseAll": "Tout réduire", + + "ui.sessionTurn.steps.show": "Afficher les étapes", + "ui.sessionTurn.steps.hide": "Masquer les étapes", + "ui.sessionTurn.summary.response": "Réponse", + "ui.sessionTurn.diff.showMore": "Afficher plus de modifications ({{count}})", + + "ui.sessionTurn.retry.retrying": "nouvelle tentative", + "ui.sessionTurn.retry.inSeconds": "dans {{seconds}}s", + + "ui.sessionTurn.status.delegating": "Délégation du travail", + "ui.sessionTurn.status.planning": "Planification des prochaines étapes", + "ui.sessionTurn.status.gatheringContext": "Collecte du contexte", + "ui.sessionTurn.status.searchingCodebase": "Recherche dans la base de code", + "ui.sessionTurn.status.searchingWeb": "Recherche sur le web", + "ui.sessionTurn.status.makingEdits": "Application des modifications", + "ui.sessionTurn.status.runningCommands": "Exécution des commandes", + "ui.sessionTurn.status.thinking": "Réflexion", + "ui.sessionTurn.status.thinkingWithTopic": "Réflexion - {{topic}}", + "ui.sessionTurn.status.gatheringThoughts": "Rassemblement des idées", + "ui.sessionTurn.status.consideringNextSteps": "Examen des prochaines étapes", + + "ui.messagePart.diagnostic.error": "Erreur", + "ui.messagePart.title.edit": "Modifier", + "ui.messagePart.title.write": "Écrire", + "ui.messagePart.option.typeOwnAnswer": "Tapez votre propre réponse", + "ui.messagePart.review.title": "Passez en revue vos réponses", + + "ui.list.loading": "Chargement", + "ui.list.empty": "Aucun résultat", + "ui.list.emptyWithFilter.prefix": "Aucun résultat pour", + "ui.list.emptyWithFilter.suffix": "", + + "ui.messageNav.newMessage": "Nouveau message", + + "ui.textField.copyToClipboard": "Copier dans le presse-papiers", + "ui.textField.copied": "Copié", + + "ui.imagePreview.alt": "Aperçu de l'image", + + "ui.tool.read": "Lire", + "ui.tool.list": "Lister", + "ui.tool.glob": "Glob", + "ui.tool.grep": "Grep", + "ui.tool.webfetch": "Webfetch", + "ui.tool.shell": "Shell", + "ui.tool.patch": "Patch", + "ui.tool.todos": "Tâches", + "ui.tool.todos.read": "Lire les tâches", + "ui.tool.questions": "Questions", + "ui.tool.agent": "Agent {{type}}", + + "ui.common.file.one": "fichier", + "ui.common.file.other": "fichiers", + "ui.common.question.one": "question", + "ui.common.question.other": "questions", + + "ui.common.add": "Ajouter", + "ui.common.cancel": "Annuler", + "ui.common.confirm": "Confirmer", + "ui.common.dismiss": "Ignorer", + "ui.common.next": "Suivant", + "ui.common.submit": "Soumettre", + + "ui.permission.deny": "Refuser", + "ui.permission.allowAlways": "Toujours autoriser", + "ui.permission.allowOnce": "Autoriser une fois", + + "ui.message.expand": "Développer le message", + "ui.message.collapse": "Réduire le message", + "ui.message.copy": "Copier", + "ui.message.copied": "Copié !", + "ui.message.attachment.alt": "pièce jointe", + + "ui.patch.action.deleted": "Supprimé", + "ui.patch.action.created": "Créé", + "ui.patch.action.moved": "Déplacé", + "ui.patch.action.patched": "Corrigé", + + "ui.question.subtitle.answered": "{{count}} répondu(s)", + "ui.question.answer.none": "(pas de réponse)", + "ui.question.review.notAnswered": "(non répondu)", + "ui.question.multiHint": "(sélectionnez tout ce qui s'applique)", + "ui.question.custom.placeholder": "Tapez votre réponse...", +}