Files
Skald-Circle/web/i18n/fr.js
T
dguiducci e6818408cb
Nightly Build / build (push) Successful in 7m23s
feat: grant a new plugin or connector to everyone by default — the admin's job is now removal, not distribution
The grant junctions (plugin_access, mcp_global_access, mcp_catalog_access)
stay deny-by-default internally, but the rows are written for you at two
moments and never again:

  — an object is CREATED: PluginManager::update_config (first toggle —
    the plugins row's birth), mcp::catalog_upsert, marketplace install,
    mcp::global_enable
  — a user is CREATED: UserManager::register_user

Who is included is the role attrs.auto_grant flag (default true, so every
role predating the attribute behaves like an adult member). The seeded
Children preset sets it to false, which is the whole reason the attribute
exists. Admins are skipped because they hold everything implicitly. The
role editor now exposes the switch as a checkbox.

New crate module: db::access_defaults (seed_new_object, seed_new_user,
set_grant_by_default). Additive columns: grant_by_default on plugins,
mcp_catalog, mcp_global_servers (INTEGER NOT NULL DEFAULT 1).

On the frontend the Roles page gets a "New extensions" column and
checklist; the user's plugin/connector rosters are unchanged. i18n:
en, fr, it.

Docs: new docs/access.md for the assistant, plus index.md cross-link.
CLAUDE.md updated with a full default-access section.
2026-07-29 15:53:51 +01:00

1209 lines
76 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export default {
// ── Navigation ─────────────────────────────────────────────────────────────
'nav.section.workspace': 'Votre espace',
'nav.section.extensions': 'Extensions',
'nav.section.config': 'Configuration',
'nav.section.dev': 'Développement',
'nav.chat': 'Discussion',
'nav.inbox': 'Boîte de réception',
'nav.dashboard': 'Tableau de bord',
'nav.projects': 'Projets',
'nav.tasks': 'Gestionnaire de tâches',
'nav.tasks.running': 'Tâches en cours',
'nav.tasks.cron': 'Tâches Cron',
'nav.tasks.scheduled': 'Tâches planifiées',
'nav.tasks.history': 'Historique',
'nav.models': 'Modèles',
'nav.providers': 'Fournisseurs',
'nav.security': 'Sécurité',
'nav.agents': 'Agents',
'nav.users': 'Utilisateurs',
'nav.roles': 'Rôles',
'nav.connectors': 'Connecteurs',
'nav.plugins': 'Plugins',
'nav.config': 'Paramètres',
'nav.llm_requests': 'Requêtes LLM',
'nav.system_agents': 'Agents système',
// ── Top bar ────────────────────────────────────────────────────────────────
'topbar.profile': 'Profil',
'topbar.logout': 'Déconnexion',
'topbar.account': 'Compte',
'topbar.open_chat': 'Ouvrir la discussion',
'topbar.brand': 'Skald',
'topbar.to_light': 'Passer en mode clair',
'topbar.to_dark': 'Passer en mode sombre',
// ── Chat ───────────────────────────────────────────────────────────────────
'chat.title': 'Skald',
'chat.tab.general': 'Général',
'chat.hello': 'Bonjour ! Comment puis-je vous aider aujourd\'hui ?',
'chat.greeting': 'Salut !',
'chat.greeting.named': 'Bonjour, {name} !',
'chat.greeting.sub': 'Que puis-je faire pour vous aujourd\'hui ?',
'chat.placeholder': 'Message… (Entrée pour envoyer, Maj+Entrée pour une nouvelle ligne)',
'chat.mobile.placeholder': 'Tapez un message…',
'chat.mobile.ask': 'Demandez-moi n\'importe quoi',
'chat.mobile.back_general': 'Retour au général',
'chat.mobile.project': 'Projet',
'chat.mobile.chat': 'Discussion',
'chat.mobile.record_voice': 'Enregistrer la voix',
'chat.mobile.stop_record': 'Arrêter l\'enregistrement',
'mobile.coming_soon': 'Bientôt disponible',
'mobile.nav.inbox': 'Boîte de réception',
'mobile.nav.projects': 'Projets',
'mobile.nav.chat': 'Discussion',
'mobile.nav.alerts': 'Alertes',
'mobile.nav.settings': 'Paramètres',
'mobile.settings.theme': 'Thème',
'mobile.settings.light': 'Clair',
'mobile.settings.dark': 'Sombre',
'mobile.settings.language': 'Langue',
'chat.send': 'Envoyer',
'chat.stop': 'Arrêter',
'chat.thinking': 'Réflexion…',
'chat.reasoning': 'Raisonnement…',
'chat.attach': 'Joindre des fichiers',
'chat.new_session': 'Nouvelle conversation',
'chat.scroll_to_latest': 'Aller aux derniers messages',
'chat.security_group': 'Groupe de sécurité',
'chat.collapse': 'Masquer la discussion',
'chat.close_tab': 'Fermer l\'onglet',
'chat.privacy': 'Privé pour vous',
'chat.privacy.hint': 'Vous seul(e) pouvez voir cette conversation. Partager quoi que ce soit avec le groupe demande toujours une approbation préalable.',
'chat.suggest.1': 'Que pouvez-vous faire ?',
'chat.suggest.2': 'Aidez-moi à planifier ma journée',
'chat.suggest.3': 'Racontez-moi une histoire',
'chat.suggest.4': 'Que savez-vous de moi ?',
'chat.rejected': 'Refusé.',
'chat.rejected_by_user': 'Refusé par l\'utilisateur.',
'chat.truncated': 'Réponse tronquée par la limite de tokens (↓{tokens} tok).',
// ── Copilot render ─────────────────────────────────────────────────────────
'copilot.open_in_viewer': 'Ouvrir dans le visualiseur',
'copilot.unchanged_lines': '⋯ {n} lignes inchangées ⋯',
'copilot.cancel': 'Annuler',
'copilot.clarification_ph': 'Tapez votre réponse…',
'copilot.send': 'Envoyer',
'copilot.result': 'résultat',
'copilot.error_label': 'erreur',
'copilot.not_sent_to_llm': 'Ce message n\'est pas envoyé au LLM',
'copilot.remove': 'Supprimer',
'copilot.result_json': 'résultat · json',
'copilot.changes': 'modifications',
'copilot.view_details': 'Voir les détails',
'tool_detail.title': 'Appel d\'outil',
'tool_detail.target': 'cible',
'tool_detail.input': 'entrée',
'copilot.agent_done': 'terminé',
'copilot.agent_running': 'en cours…',
'copilot.agent_finished': 'fini',
'copilot.status_awaiting': 'En attente d\'approbation',
'copilot.status_cancelled': 'Annulé par l\'utilisateur',
'copilot.status_denied': 'Refusé par la politique',
'copilot.bypass_session': 'Session',
'copilot.bypass_15min': '15 min',
// ── Copilot slash commands ─────────────────────────────────────────────────
'copilot.cmd.help': 'Afficher les commandes disponibles',
'copilot.cmd.clear': 'Démarrer une nouvelle conversation',
'copilot.cmd.new': 'Alias pour /clear',
'copilot.cmd.models': 'Lister les modèles LLM disponibles',
'copilot.cmd.model': 'Sélectionner le modèle pour cette discussion',
'copilot.cmd.context': 'Utilisation des tokens du dernier tour',
'copilot.cmd.cost': 'Dépenses de la session (USD)',
'copilot.cmd.compact': 'Forcer la compaction du contexte',
'copilot.cmd.resettools': 'Supprimer les groupes d\'outils activés',
'copilot.cmd.sethome': 'Définir le web comme accueil des notifications',
// ── LLM Requests ────────────────────────────────────────────────────────────
'llmr.title': 'Requêtes LLM',
'llmr.loading': 'Chargement…',
'llmr.empty': 'Aucune requête trouvée.',
'llmr.total': '{n} lignes',
'llmr.filter.agent_id': 'ID de l\'agent',
'llmr.filter.agent_ph': 'ex. assistant',
'llmr.filter.source': 'Source',
'llmr.filter.source_ph': 'ex. web, event-triage, cron',
'llmr.filter.from': 'De',
'llmr.filter.to': 'À',
'llmr.filter.apply': 'Appliquer',
'llmr.filter.reset': 'Réinitialiser',
'llmr.table.agent': 'Agent',
'llmr.table.source': 'Source',
'llmr.table.model': 'Modèle',
'llmr.table.date': 'Date',
'llmr.table.in_tokens': 'Tokens en entrée',
'llmr.table.out_tokens': 'Tokens en sortie',
'llmr.table.cache_hit': 'Cache hit',
'llmr.cache_read': 'lecture : {n} tk',
'llmr.cache_write': 'écriture : {n} tk',
'llmr.pagination': 'Page {cur} sur {pages} — {total} résultats',
// ── LLM Request Detail ──────────────────────────────────────────────────────
'llmr.detail.back': 'Retour',
'llmr.detail.loading': 'Chargement…',
'llmr.detail.request': 'Requête',
'llmr.detail.no_agent': 'aucun agent',
'llmr.detail.error_badge': 'erreur',
'llmr.detail.purged': 'Charge utile non disponible — cette requête a été purgée par la politique de conservation.',
'llmr.detail.reasoning_label': 'raisonnement',
'llmr.detail.tool_params': 'Paramètres',
'llmr.detail.tool_result': 'Résultat',
'llmr.detail.system_role': 'système',
'llmr.detail.cache_label': 'cache {pct}',
'llmr.detail.stat_input': 'Tokens en entrée',
'llmr.detail.stat_output': 'Tokens en sortie',
'llmr.detail.section_req_headers': 'En-têtes de la requête',
'llmr.detail.section_resp_headers':'En-têtes de la réponse',
'llmr.detail.section_params': 'Paramètres',
'llmr.detail.section_system': 'Prompt système',
'llmr.detail.section_conversation':'Conversation',
'llmr.detail.section_tools': 'Outils définis',
'llmr.detail.section_response': 'Réponse',
'llmr.detail.tools_activated': 'Outils activés (DTL)',
'llmr.detail.tool_reference_loads': 'charge {n}',
'llmr.detail.flag_deferred': 'différé',
'llmr.detail.flag_cached': 'en cache',
// ── Config ──────────────────────────────────────────────────────────────────
'config.title': 'Configuration',
'config.loading': 'Chargement…',
'config.developer': 'Développeur',
'config.error_save':'Erreur lors de l\'enregistrement de "{name}" : {msg}',
'config.enabled': 'Activé',
'config.disabled': 'Désactivé',
'config.llm_model.auto': 'auto',
'config.set.interface.name': 'Interface',
'config.set.interface.desc': 'Aspect et style de l\'interface web.',
'config.set.compaction.name': 'Compaction',
'config.set.compaction.desc': 'Lorsqu\'une conversation devient trop longue, les messages les plus anciens sont résumés par un LLM pour garder le contexte dans les limites.',
'config.prop.ui_locale.name': 'Langue',
'config.prop.ui_locale.desc': 'Langue d\'interface par défaut pour l\'ensemble de l\'instance. Chaque utilisateur peut la modifier dans son profil.',
'config.prop.event_triage__enabled.name': 'Activé',
'config.prop.event_triage__enabled.desc': 'Activer ou désactiver le tri des événements pour toute l\'instance. Lorsqu\'il est désactivé, aucun événement n\'est traité pour personne.',
'config.prop.event_triage__security_group.name': 'Groupe de sécurité',
'config.prop.event_triage__security_group.desc': 'Groupe de permissions d\'outils appliqué à chaque exécution du tri des événements. Il est revérifié selon le rôle de chaque utilisateur : si son rôle n\'autorise pas ce groupe, l\'exécution utilise le groupe par défaut de son rôle. Laissez vide pour toujours utiliser celui du rôle.',
'config.prop.event_triage__interval_minutes.name': 'Intervalle de vérification (minutes)',
'config.prop.event_triage__interval_minutes.desc': 'Temps écoulé entre deux passages pour chaque utilisateur, en minutes. Compté par personne depuis son propre dernier passage. Laissez vide pour utiliser la valeur de config.yml (event_triage.interval_secs).',
'config.prop.memory_lint_private__enabled.name': 'Activé',
'config.prop.memory_lint_private__enabled.desc': 'Activer l\'entretien de la mémoire privée pour toute l\'instance. Lorsqu\'il est désactivé, la mémoire privée de personne n\'est vérifiée.',
'config.prop.memory_lint_private__security_group.name': 'Groupe de sécurité',
'config.prop.memory_lint_private__security_group.desc': 'Groupe de permissions d\'outils appliqué à chaque exécution. Il est revérifié selon le rôle de chaque utilisateur : si son rôle n\'autorise pas ce groupe, l\'exécution utilise le groupe par défaut de son rôle. Laissez vide pour toujours utiliser celui du rôle.',
'config.prop.memory_lint_private__interval_days.name': 'Intervalle (jours)',
'config.prop.memory_lint_private__interval_days.desc': 'Temps écoulé entre deux passages pour chaque utilisateur. Compté par personne depuis son propre dernier passage, et conservé au redémarrage : redémarrer la machine ne réinitialise pas un intervalle long.',
'config.prop.memory_lint_shared__enabled.name': 'Activé',
'config.prop.memory_lint_shared__enabled.desc': 'Activer l\'entretien de la mémoire partagée pour toute l\'instance.',
'config.prop.memory_lint_shared__security_group.name': 'Groupe de sécurité',
'config.prop.memory_lint_shared__security_group.desc': 'Groupe de permissions d\'outils appliqué à chaque exécution, revérifié selon le rôle de l\'administrateur. Laissez vide pour utiliser celui du rôle.',
'config.prop.memory_lint_shared__interval_days.name': 'Intervalle (jours)',
'config.prop.memory_lint_shared__interval_days.desc': 'Temps écoulé entre deux passages sur la mémoire partagée. Conservé au redémarrage : redémarrer la machine ne réinitialise pas un intervalle long.',
'config.prop.compaction_model.name': 'Modèle de compaction',
'config.prop.compaction_model.desc': 'Modèle utilisé pour résumer les conversations compactées, pour toute l\'instance. Un modèle économique suffit généralement. Laissez vide pour une sélection automatique.',
// ── Projects ────────────────────────────────────────────────────────────────
'projects.title': 'Projets',
'projects.btn.new': 'Nouveau projet',
'projects.empty': 'Aucun projet pour le moment. Créez-en un pour commencer.',
'projects.action.edit': 'Modifier',
'projects.action.delete': 'Supprimer',
'projects.card.updated': 'Mis à jour',
'projects.confirm.delete': 'Supprimer le projet "{name}" ? Il sera retiré pour toutes les personnes avec qui il est partagé.',
'projects.badge.owned': 'Le vôtre',
'projects.badge.shared_by': 'Partagé par {name}',
'projects.badge.readonly': 'Lecture seule',
'projects.modal.title_edit': 'Modifier le projet',
'projects.modal.title_new': 'Nouveau projet',
'projects.modal.name': 'Nom',
'projects.modal.name_ph': 'Mon projet',
'projects.modal.desc': 'Description',
'projects.modal.desc_ph': 'À propos de ce projet',
'projects.modal.cancel': 'Annuler',
'projects.modal.saving': 'Enregistrement…',
'projects.modal.save': 'Enregistrer',
'projects.modal.create': 'Créer',
// ── Partage de projet ───────────────────────────────────────────────────────
'projects.share.title': 'Partage',
'projects.share.owner': 'propriétaire',
'projects.share.choose_user': 'Choisir une personne…',
'projects.share.add': 'Ajouter',
'projects.share.all_added': 'Tout le monde a déjà accès.',
'projects.share.remove': 'Retirer',
'projects.share.access.read': 'Lecture',
'projects.share.access.write': 'Écriture',
'projects.share.access.readonly': 'Lecture seule',
'projects.share.access.readwrite':'Lecture et écriture',
'projects.tabs.files': 'Fichiers',
'projects.tabs.sharing': 'Partage',
'projects.files.col.name': 'Nom',
'projects.files.col.created': 'Création',
'projects.files.col.modified': 'Modification',
'projects.files.col.size': 'Taille',
'projects.files.empty': 'Ce dossier est vide.',
'projects.files.refresh': 'Actualiser',
'projects.files.drop': 'Déposez les fichiers ici pour les envoyer',
'projects.files.btn.new_folder': 'Nouveau dossier',
'projects.files.btn.upload': 'Envoyer',
'projects.files.uploading': 'Envoi…',
'projects.files.action.rename': 'Renommer',
'projects.files.action.delete': 'Supprimer',
'projects.files.confirm.delete_file': 'Supprimer « {name} » ?',
'projects.files.confirm.delete_dir': 'Supprimer le dossier « {name} » et tout son contenu ?',
'projects.files.modal.mkdir': 'Nouveau dossier',
'projects.files.modal.rename': 'Renommer « {name} »',
'projects.files.modal.name': 'Nom',
'projects.files.error.name': 'Saisissez un nom valide (sans barres obliques).',
// ── Détail du projet ────────────────────────────────────────────────────────
'project_board.back': 'Projets',
'project_board.open_chat': 'Ouvrir la discussion',
// ── Session detail ──────────────────────────────────────────────────────────
'session.back': 'Retour',
'session.loading': 'Chargement de la session…',
'session.no_session': 'Aucune session chargée.',
'session.no_session_hint': 'Naviguez vers <code>#session/{id}</code> pour voir une session.',
'session.empty': 'Aucun message dans cette session.',
'session.user_role': 'Utilisateur',
'session.assistant_role': 'Assistant',
'session.reasoning_label': 'Raisonnement',
'session.thinking_role': 'Réflexion',
'session.failed': 'échoué',
'session.ephemeral': 'éphémère',
'session.automated': 'automatisé',
'session.live': 'en direct',
'session.agent': 'agent :',
'session.id': 'id :',
'session.sub_agent': 'Sous-agent :',
'session.end_of': 'fin de',
'session.depth': 'profondeur {n}',
'session.synthetic': 'synthétique',
'session.tool_args': 'Arguments',
'session.tool_result': 'Résultat',
'session.tool_error': 'Erreur',
// ── Inbox ──────────────────────────────────────────────────────────────────
'inbox.empty': 'Aucune demande en attente',
'inbox.reject_prompt': 'Motif du refus (facultatif) :',
// ── Approvals ──────────────────────────────────────────────────────────────
'approval.pending': 'En attente de votre accord',
'approval.approved': 'Autorisé',
'approval.rejected': 'Refusé',
'approval.approve': 'Autoriser',
'approval.reject': 'Refuser',
'approval.confirm_reject': 'Confirmer le refus',
'approval.reject_hint': 'Facultatif : dites pourquoi (l\'assistant le lira)',
'approval.bypass_15': 'Autoriser et ignorer les demandes similaires pendant 15 minutes',
'approval.bypass_all': 'Autoriser et ignorer toutes les demandes pour cette session',
// ── Login ──────────────────────────────────────────────────────────────────
'login.title': 'Bon retour',
'login.subtitle': 'Connectez-vous à votre compte.',
'login.username': 'Nom d\'utilisateur',
'login.password': 'Mot de passe',
'login.submit': 'Se connecter',
'login.signing': 'Connexion en cours…',
'login.missing': 'Entrez votre nom d\'utilisateur et votre mot de passe.',
'login.error': 'Nom d\'utilisateur ou mot de passe invalide.',
'login.network': 'Erreur réseau — veuillez réessayer.',
// ── Profile ────────────────────────────────────────────────────────────────
'profile.title': 'Profil',
'profile.account': 'Compte',
'profile.username': 'Nom d\'utilisateur',
'profile.role': 'Rôle',
'profile.name': 'Nom d\'affichage',
'profile.name.ph': 'Votre nom',
'profile.language': 'Langue',
'profile.language.default': 'Par défaut du groupe ({locale})',
'profile.saved': 'Enregistré.',
'profile.pw': 'Changer le mot de passe',
'profile.pw.current': 'Mot de passe actuel',
'profile.pw.new': 'Nouveau mot de passe',
'profile.pw.confirm': 'Confirmer le nouveau mot de passe',
'profile.pw.short': 'Le mot de passe doit contenir au moins 4 caractères.',
'profile.pw.mismatch': 'Les mots de passe ne correspondent pas.',
'profile.pw.changed': 'Mot de passe modifié.',
'profile.pw.submit': 'Changer le mot de passe',
// ── Settings (config page extras) ──────────────────────────────────────────
'config.debug': 'Mode débogage',
'config.debug.desc': 'Afficher les pages développeur (requêtes LLM) dans la barre latérale.',
// ── First-run setup ────────────────────────────────────────────────────────
'setup.title': 'Bienvenue sur Skald',
'setup.subtitle': 'Créez le compte administrateur pour commencer.',
'setup.username': 'Choisissez un nom d\'utilisateur.',
'setup.pw.short': 'Le mot de passe doit contenir au moins 4 caractères.',
'setup.pw.mismatch': 'Les deux mots de passe ne correspondent pas.',
'setup.confirm': 'Confirmer le mot de passe',
'setup.language': 'Langue de l\'interface',
'setup.profile': 'Type d\'instance',
'setup.encrypt': 'Chiffrer mon historique de conversations',
'setup.warn': 'votre mot de passe génère la clé de chiffrement. Si vous l\'oubliez, tout votre historique de conversations sera définitivement perdu — il n\'y a aucune récupération possible.',
'setup.warn.strong': 'Attention :',
'setup.submit': 'Créer le compte',
'setup.creating': 'Création…',
'setup.network': 'Erreur réseau — veuillez réessayer.',
// ── Dashboard ───────────────────────────────────────────────────────────────
'dashboard.status.loading': 'Chargement…',
'dashboard.status.no_models': 'Aucun modèle LLM',
'dashboard.status.online': 'En ligne et prêt',
'dashboard.status.degraded': 'Dégradé',
'dashboard.status.offline': 'Tous les modèles hors ligne',
'dashboard.stats.loading': 'Chargement des statistiques…',
'dashboard.stats.empty': 'Aucune requête LLM dans la plage sélectionnée.',
'dashboard.stats.requests': 'Requêtes {per}',
'dashboard.stats.tokens': 'Tokens {per}',
'dashboard.stats.latency': 'Latence moyenne (ms)',
'dashboard.stats.models': 'Modèles',
'dashboard.stats.per_min': '/ min',
'dashboard.stats.per_hour': '/ heure',
'dashboard.stats.per_day': '/ jour',
'dashboard.stats.range.hour': '1h',
'dashboard.stats.range.day': '24h',
'dashboard.stats.range.week': '7j',
'dashboard.stats.range.month': '30j',
'dashboard.stats.chart.input': 'Entrée',
'dashboard.stats.chart.output': 'Sortie',
'dashboard.stats.chart.cached': 'En cache',
'dashboard.stats.chart.non_cached': 'Non en cache',
'dashboard.stats.chart.cache_hit': 'Cache hit : {pct}%',
'dashboard.hero.subtitle': 'Votre centre de commande IA — recherche, code, planification et orchestration. Tout en un seul endroit.',
'dashboard.banner.no_models.title': 'Aucun modèle LLM configuré.',
'dashboard.banner.no_models.desc': 'Commencez par ajouter un fournisseur (Anthropic, OpenAI, OpenRouter…), puis ajoutez au moins un modèle dans la section Modèles.',
'dashboard.banner.no_models.action': 'Ajouter un fournisseur',
'dashboard.section.stats': 'Statistiques LLM',
'dashboard.section.pending': 'En attente',
'dashboard.section.guide': 'Guide rapide',
'dashboard.tip.honcho.title': 'Activer Honcho',
'dashboard.tip.honcho.desc': 'Mémoire persistante à long terme — l\'agent apprend vos préférences au fil du temps. Demandez au Copilot de l\'activer.',
'dashboard.refresh': 'Actualiser',
'dashboard.guide.chat.title': 'Discussion',
'dashboard.guide.chat.desc': 'Votre page d\'accueil est une conversation — elle sait tout : demandez-lui d\'exécuter des agents, d\'activer des plugins, d\'écrire du code ou de rechercher sur le web.',
'dashboard.guide.inbox.title': 'Boîte de réception',
'dashboard.guide.inbox.desc': 'Approbations en attente et questions des agents qui nécessitent votre intervention avant que les tâches en arrière-plan puissent continuer.',
'dashboard.guide.agents.title': 'Agents',
'dashboard.guide.agents.desc': 'Sous-agents spécialisés (ingénieur, architecte, QA…). Chacun a un prompt système ciblé, un ensemble d\'outils et une sélection de modèle.',
'dashboard.guide.cron.title': 'Cron',
'dashboard.guide.cron.desc': 'Tâches planifiées qui s\'exécutent automatiquement à intervalles réguliers, même lorsque le Copilot est inactif.',
'dashboard.guide.models.title': 'Modèles',
'dashboard.guide.models.desc': 'Gérez les modèles LLM, de transcription et de génération d\'images. Glissez-déposez pour réorganiser la priorité.',
'dashboard.guide.providers.title': 'Fournisseurs',
'dashboard.guide.providers.desc': 'Ajoutez des clés API pour les fournisseurs LLM (Anthropic, OpenAI, OpenRouter, Ollama…).',
'dashboard.guide.security.title': 'Sécurité',
'dashboard.guide.security.desc': 'Définissez des règles pour approuver ou refuser automatiquement les appels d\'outils — évitez les invites de confirmation répétitives.',
// ── Models (hub + sections) ─────────────────────────────────────────────────
'models.hub.title': 'Modèles',
'models.hub.subtitle': 'Configurez les fournisseurs LLM, de transcription et de génération d\'images.',
'models.hub.count.none': 'Aucun modèle',
'models.hub.count.one': '1 modèle',
'models.hub.count.many': '{n} modèles',
'models.hub.card.llm.title': 'LLM',
'models.hub.card.llm.desc': 'Modèles de discussion et de complétion pour les agents et les outils',
'models.hub.card.transcribe.title': 'Transcription',
'models.hub.card.transcribe.desc': 'Modèles de synthèse vocale via le cloud ou un plugin local',
'models.hub.card.image.title': 'Génération d\'images',
'models.hub.card.image.desc': 'Modèles texte-vers-image via API cloud',
'models.hub.card.tts.title': 'Synthèse vocale',
'models.hub.card.tts.desc': 'Modèles de synthèse vocale via le cloud ou un plugin local',
'models.back': 'Retour aux modèles',
'models.add': 'Ajouter',
'models.add_model': 'Ajouter un modèle',
'models.add_first': 'Ajouter votre premier modèle',
'models.edit': 'Modifier',
'models.delete': 'Supprimer',
'models.saving': 'Enregistrement…',
'models.save_changes': 'Enregistrer les modifications',
'models.cancel': 'Annuler',
'models.search': 'Rechercher des modèles…',
'models.loading': 'Chargement des modèles…',
'models.no_results': 'Aucun modèle trouvé',
'models.enter_id': 'Entrer l\'ID du modèle manuellement',
'models.managed_plugin': 'Géré par plugin',
'models.readonly_plugin': 'Les modèles avec le badge <strong>Plugin</strong> sont en lecture seule — gérés automatiquement par le plugin qui les a enregistrés.',
'models.readonly_plugin_full': 'Les modèles avec le badge <strong>Plugin</strong> sont en lecture seule — gérés automatiquement par le plugin qui les a enregistrés. Pour en ajouter, modifier ou supprimer, demandez directement à l\'agent : il dispose de toute la documentation nécessaire.',
'models.default': 'défaut',
'models.move_up': 'Monter',
'models.move_down': 'Descendre',
'models.strength.very_high': 'Très élevée',
'models.strength.high': 'Élevée',
'models.strength.average': 'Moyenne',
'models.strength.low': 'Faible',
'models.strength.very_low': 'Très faible',
'models.strength.none': '— aucun —',
'models.reasoning.off': '— désactivé —',
'models.reasoning.label': 'Raisonnement',
'models.reasoning.thinking': 'Raisonnement (réflexion)',
'models.strength': 'Puissance',
'models.priority': 'Priorité',
'models.default_model': 'Modèle par défaut',
'models.extra_params': 'Paramètres supplémentaires',
'models.extra_params_hint': '(JSON, facultatif)',
'models.model_id': 'ID du modèle',
'models.model_id_hint': '(envoyé à l\'API)',
'models.model_id_immutable': 'L\'ID du modèle ne peut pas être modifié après la création.',
'models.name_alias': 'Nom / Alias',
'models.name_alias_hint': '(facultatif)',
'models.name_alias_ph': 'identique à l\'ID du modèle',
'models.edit_title': 'Modifier {name}',
'models.edit_info': 'L\'ID du modèle et le fournisseur ne peuvent pas être modifiés. Pour utiliser un modèle différent, ajoutez une nouvelle entrée.',
'models.name_help': 'Utilisé pour référencer ce modèle (p. ex. dans le <code>client</code> d\'un agent). Doit être unique.',
'models.no_providers_llm': 'Ajoutez d\'abord un <strong>fournisseur</strong>, puis revenez ici pour ajouter des modèles.',
'models.no_providers_transcribe': 'Aucun fournisseur ne prend encore en charge la transcription. Ajoutez d\'abord un fournisseur <strong>OpenAI</strong> ou <strong>OpenRouter</strong>.',
'models.no_providers_image': 'Aucun fournisseur ne prend encore en charge la génération d\'images. Ajoutez d\'abord un fournisseur <strong>OpenRouter</strong>.',
'models.no_providers_tts': 'Aucun fournisseur ne prend encore en charge la TTS. Ajoutez d\'abord un fournisseur <strong>OpenAI</strong>.',
'models.list_empty_llm': 'Aucun modèle configuré pour le moment.',
'models.list_empty_transcribe': 'Aucun modèle de transcription configuré.',
'models.list_empty_image': 'Aucun modèle de génération d\'images configuré.',
'models.list_empty_tts': 'Aucun modèle TTS configuré.',
'models.list_empty_add_hint': 'Cliquez sur <strong>Ajouter</strong> pour ajouter un modèle cloud.',
'models.list_empty_whisper': 'Activez le plugin <strong>Whisper Local</strong> pour la transcription sur l\'appareil.',
'models.source': 'Source',
'models.source_plugin': 'Plugin',
'models.source_cloud': 'Cloud',
'models.name_col': 'Nom',
'models.provider_col': 'Fournisseur',
'models.model_id_col': 'ID du modèle',
'models.language_col': 'Langue',
'models.language_auto': 'auto',
'models.choose_provider': 'Choisir un fournisseur',
'models.add_model_title': 'Ajouter un modèle',
'models.model_label': 'Modèle',
'models.add_model_provider': 'Ajouter un modèle {type} — Choisir un fournisseur',
'models.add_model_type': 'Ajouter un modèle {type}',
'models.priority_hint': 'Nombre plus bas = essayé en premier. Défaut : 100.',
'models.priority_hint_short': 'Nombre plus bas = utilisé en premier. Défaut : 100.',
'models.status_healthy': 'En santé',
'models.status_degraded': 'Dégradé',
'models.status_down': 'Hors ligne',
'models.llm.title': 'Modèles LLM',
'models.transcribe.title': 'Modèles de transcription',
'models.image.title': 'Modèles de génération d\'images',
'models.tts.title': 'Modèles de synthèse vocale',
'models.confirm_delete': 'Supprimer le modèle {type} "{name}" ?',
'models.error.save_order': 'Échec de l\'enregistrement de l\'ordre : {msg}',
'models.error.load_models': 'Échec du chargement des modèles : {msg}',
'models.error.invalid_json': 'Paramètres supplémentaires : JSON invalide',
'models.error.select_model': 'Sélectionnez un modèle',
'models.label.sent_to_api': '(envoyé à l\'API)',
'models.label.optional': '(facultatif)',
'models.label.bcp47': '(BCP-47, facultatif)',
'models.label.required_elevenlabs': '(facultatif — requis pour ElevenLabs)',
'models.label.shown_to_llm': '(facultatif — montré au LLM)',
'models.label.response_fmt': 'Format de réponse',
'models.label.response_fmt_hint': '(facultatif)',
'models.label.description': 'Description',
'models.label.description_hint': '(facultatif)',
'models.label.instructions': 'Instructions',
'models.label.instructions_hint': '(facultatif — montré au LLM)',
'models.label.voice_id': 'ID vocal',
'models.label.voice_id_hint': '(facultatif — requis pour ElevenLabs)',
'models.label.max_output': 'Max tokens de sortie',
'models.label.max_output_hint': '(facultatif)',
'models.ph.model_id': 'ex. gpt-4o',
'models.ph.model_id_transcribe': 'ex. openai/whisper-1',
'models.ph.model_id_tts': 'ex. tts-1-hd',
'models.ph.model_id_image': 'ex. x-ai/grok-2-vision',
'models.ph.name_alias': 'identique à l\'ID du modèle',
'models.ph.language': 'ex. fr, en — laissez vide pour détection automatique',
'models.ph.voice_id': 'ex. alloy, Kore, 21m00Tcm4TlvDq8ikWAM',
'models.ph.description': 'ex. Haute qualité, lent — idéal pour les longues réponses',
'models.ph.instructions': 'ex. Parlez d\'un ton calme et neutre. Marquez une légère pause entre les phrases.',
'models.ph.max_tokens': 'jusqu\'à {n}',
'models.form.model_lock': 'L\'ID du modèle ne peut pas être modifié après la création.',
'models.form.voice_hint': 'Voix du locuteur. OpenAI : <code>alloy</code>/<code>echo</code>/<code>nova</code>… (défaut <code>alloy</code> si vide) ; Gemini : <code>Kore</code>/<code>Puck</code>/<code>Zephyr</code>… ; ElevenLabs : l\'ID vocal.',
'models.form.instructions_hint': 'Guide vocal/tonal injecté dans le prompt système LLM lorsque ce modèle est actif.',
'models.form.response_hint': 'Format audio demandé au fournisseur. Laissez vide sauf si le modèle en nécessite un spécifique — p. ex. Gemini TTS n\'accepte que le format <code>pcm</code>.',
'models.form.response_default': 'Défaut du fournisseur (mp3)',
'models.form.priority_img': 'Nombre plus bas = essayé en premier. Défaut : 100.',
'models.form.name_as_provider': 'Nom / Alias <span class="text-muted fw-normal">(utilisé comme provider_id dans l\'outil LLM)</span>',
'models.tts.cost_multiplier': 'Multiplicateur de coût par rapport au taux de base',
'models.llm.price_tooltip': 'Entrée/Sortie par 1M de tokens',
// ── Approval rules ─────────────────────────────────────────────────────────
'approval.action.require': 'Exiger',
'approval.action.allow': 'Autoriser',
'approval.action.deny': 'Refuser',
'approval.chip.unset': '—',
'approval.chip.req': 'Req',
'approval.category.filesystem': 'Système de fichiers',
'approval.category.shell': 'Shell',
'approval.category.subagent': 'Agents',
'approval.category.introspection': 'Introspection',
'approval.category.config': 'Configuration',
'approval.category.dynamic': 'Dynamique',
'approval.fs.allow_read': 'Autoriser la lecture',
'approval.fs.allow_write': 'Autoriser l\'écriture',
'approval.fs.deny': 'Refuser',
'approval.fs.require': 'Exiger',
'approval.fs.default': 'Exiger (défaut système)',
'approval.error.enter_path': 'Entrez un chemin de répertoire.',
'approval.error.tool_required': 'Le motif d\'outil est requis.',
'approval.error.override_prio': 'Les règles de dérogation doivent avoir une priorité < 0.',
'approval.error.lowprio_range': 'Les règles de faible priorité doivent avoir une priorité entre 1 et {max}.',
'approval.tool.any': 'Tout outil',
'approval.tool.any_mcp': 'Tout outil MCP',
'approval.tool.search': 'Rechercher des outils…',
'approval.tool.no_results': 'Aucun résultat',
'approval.tool.group_builtin': 'Intégré',
'approval.tool.group_glob': 'Glob',
'approval.tool.group_mcp': 'MCP · {server}',
'approval.form.new_override': 'Nouvelle règle de dérogation',
'approval.form.new_lowprio': 'Nouvelle règle de faible priorité',
'approval.form.edit': 'Modifier la règle',
'approval.form.tool_pattern': 'Motif d\'outil',
'approval.form.tool_pattern_ph': 'ex. mcp__whatsapp__* ou execute_cmd',
'approval.form.tool_pattern_hint': 'Utilisez <code>*</code> comme joker de fin, p. ex. <code>mcp__whatsapp__*</code>',
'approval.form.select_tool': 'Sélectionner un outil',
'approval.form.path_pattern': 'Motif de chemin',
'approval.form.path_pattern_ph': 'ex. data/* ou data/notes/*',
'approval.form.path_pattern_hint': 'Filtrer par chemin de fichier. Utilisez <code>*</code> comme joker.',
'approval.form.action': 'Action',
'approval.form.priority': 'Priorité',
'approval.form.priority_override_hint': 'Doit être <strong>&lt; 0</strong> (p. ex. 10)',
'approval.form.priority_lowprio_hint': 'Doit être <strong>1 {max}</strong>',
'approval.form.source': 'Source',
'approval.form.source_any': 'Toute',
'approval.form.agent_id': 'ID de l\'agent',
'approval.form.agent_id_ph': 'assistant (vide = toute)',
'approval.form.note': 'Note',
'approval.form.note_ph': 'Brève description…',
'approval.form.cancel': 'Annuler',
'approval.form.saving': 'Enregistrement…',
'approval.form.save': 'Enregistrer',
'approval.card.priority': 'Priorité',
'approval.card.edit': 'Modifier',
'approval.card.delete': 'Supprimer',
'approval.card.remove': 'Retirer',
'approval.matrix.title': 'Par outil',
'approval.matrix.subtitle': 'priorité = 0 · nom d\'outil exact · aucun filtre de chemin/source',
'approval.matrix.loading': 'Chargement des outils…',
'approval.fs.title': 'Système de fichiers',
'approval.fs.subtitle': 'accès lecture/écriture par chemin',
'approval.fs.empty': 'Aucune règle de chemin pour le moment — ajoutez-en une ci-dessous.',
'approval.fs.add_ph': 'Ajouter un chemin de répertoire, p. ex. docs',
'approval.fs.default_label': 'Défaut',
'approval.fs.default_hint': 'chemins non correspondants',
'approval.sidebar.overrides': 'Dérogations',
'approval.sidebar.overrides_sub': 'priorité < 0 · évaluées en premier',
'approval.sidebar.lowprio': 'Faible priorité',
'approval.sidebar.lowprio_sub': 'priorité 1999998 · évaluées après le par-outil',
'approval.sidebar.add': 'Ajouter',
'approval.sidebar.empty': 'Aucune règle pour le moment.',
'approval.default_bar.title': 'Action par défaut',
'approval.default_bar.hint': 'si aucune règle ne correspond',
'approval.default_bar.unset': 'défaut système : autoriser',
'approval.header.default_badge': 'Défaut',
'approval.header.rule_count': '{n} règle',
'approval.header.rule_count_plural': '{n} règles',
'approval.confirm.delete_fs': 'Supprimer la règle de système de fichiers pour "{path}" ?',
'approval.confirm.delete_rule': 'Supprimer la règle pour "{pattern}" ?',
'approval.label.optional': '(facultatif)',
// ── Security (groups) ───────────────────────────────────────────────────────
'security.title': 'Sécurité',
'security.group_count': '{n} groupe',
'security.group_count_plural': '{n} groupes',
'security.new_group': 'Nouveau groupe',
'security.rename_group': 'Renommer le groupe',
'security.duplicate': 'Dupliquer',
'security.duplicate_title': 'Dupliquer {name}',
'security.duplicating': 'Duplication…',
'security.create_first': 'Créer le premier groupe',
'security.form.id': 'ID',
'security.form.id_ph': 'ex. cron_strict',
'security.form.id_hint': 'Identifiant en minuscules, sans espaces. Ne peut pas être modifié ultérieurement.',
'security.form.name': 'Nom',
'security.form.name_ph': 'ex. Cron strict',
'security.form.description': 'Description',
'security.form.description_ph': 'Brève description…',
'security.form.new_name': 'Nouveau nom',
'security.form.new_id': 'Nouvel ID',
'security.form.copy_info': 'Les <strong>{n}</strong> règle{s} de <em>{name}</em> seront copiées.',
'security.form.cancel': 'Annuler',
'security.form.saving': 'Enregistrement…',
'security.form.save': 'Enregistrer',
'security.card.default_badge': 'Défaut',
'security.card.rule_count': '{n} règle',
'security.card.rule_count_plural': '{n} règles',
'security.card.duplicate': 'Dupliquer',
'security.card.rename': 'Renommer',
'security.card.delete_disabled': 'Impossible de supprimer le groupe par défaut',
'security.card.delete': 'Supprimer le groupe',
'security.confirm.delete': 'Supprimer le groupe "{name}" ?',
'security.confirm.delete_with_rules': 'Supprimer le groupe "{name}" et ses {n} règle{s} ?',
'security.banner.text1': '<strong>Les groupes de permissions</strong> sont des ensembles nommés de règles d\'approbation. Le <strong>profil d\'agent</strong> actif de la session détermine le groupe applicable — les règles de ce groupe sont évaluées en premier, avec le groupe <strong>Défaut</strong> comme solution de repli.',
'security.banner.text2': 'Cliquez sur un groupe pour voir et gérer ses règles. Le groupe <strong>Défaut</strong> ne peut pas être supprimé, mais ses règles peuvent être modifiées librement.',
'security.empty.title': 'Aucun groupe pour le moment.',
'security.error.name_required': 'Le nom est requis.',
'security.error.id_required': 'L\'ID est requis.',
'security.error.group_name_required': 'Le nom du groupe est requis.',
'security.error.group_id_required': 'L\'ID du groupe est requis.',
// ── Roles ───────────────────────────────────────────────────────────────────
'roles.title': 'Rôles',
'roles.count': '{n} rôle',
'roles.count_plural': '{n} rôles',
'roles.new_role': 'Nouveau rôle',
'roles.loading': 'Chargement…',
'roles.empty': 'Aucun rôle.',
'roles.col.id': 'ID',
'roles.col.label': 'Libellé',
'roles.col.group': 'Groupe de permissions',
'roles.col.interface': 'Interface',
'roles.col.assistant': 'Assistant',
'roles.col.auto_grant': 'Nouvelles extensions',
'roles.badge.simple': 'Simple',
'roles.badge.full': 'Complet',
'roles.badge.auto_grant_on': 'Automatiques',
'roles.badge.auto_grant_off': 'Sur demande',
'roles.form.new': 'Nouveau rôle',
'roles.form.edit': 'Modifier {name}',
'roles.form.id': 'ID',
'roles.form.id_hint': '(slug)',
'roles.form.id_ph': 'ex. redacteur',
'roles.form.id_desc': 'Minuscules, sans espaces. Ne peut pas être modifié ultérieurement.',
'roles.form.label': 'Libellé',
'roles.form.group': 'Groupe de sécurité par défaut',
'roles.form.allowed': 'Groupes de sécurité supplémentaires',
'roles.form.allowed_hint': 'Groupes que ce rôle peut aussi choisir à l\'exécution, en plus du groupe par défaut. Les utilisateurs les sélectionnent dans le chat.',
'roles.form.interface': 'Interface',
'roles.form.interface_full': 'Complet — toutes les pages',
'roles.form.interface_simple': 'Simple — discussion uniquement',
'roles.form.interface_hint': 'Les membres avec l\'interface simple voient seulement la discussion et la boîte de réception. Stocké comme <code>ui_mode</code> dans le JSON d\'attributs ci-dessous.',
'roles.form.assistant': 'Assistant par défaut',
'roles.form.assistant_default': 'Par défaut (Assistant)',
'roles.form.assistant_hint': 'L\'agent avec lequel les membres de ce rôle discutent par défaut. Remplaçable par personne plus tard.',
'roles.form.auto_grant': 'Nouveaux plugins et connecteurs',
'roles.form.auto_grant_label': 'Les attribuer automatiquement à ce rôle',
'roles.form.auto_grant_hint': 'Si activé, un plugin ou connecteur que vous installez parvient aussitôt à ce rôle et vous le retirez depuis la page de chaque personne. Désactivez-le pour les rôles qui ne doivent recevoir que ce que vous leur donnez — enfants, invités. Les accès déjà accordés ne sont pas modifiés par cette option.',
'roles.form.attrs': 'Attributs',
'roles.form.attrs_hint': '(JSON, facultatif)',
'roles.form.attrs_ph': '{}',
'roles.form.cancel': 'Annuler',
'roles.form.create': 'Créer',
'roles.form.save': 'Enregistrer',
'roles.error.id_label': 'L\'ID et le libellé sont requis.',
'roles.error.label': 'Le libellé est requis.',
'roles.tooltip.locked': 'Rôle intégré — verrouillé',
'roles.tooltip.edit': 'Modifier',
'roles.tooltip.delete': 'Supprimer',
'roles.confirm.delete': 'Supprimer le rôle "{name}" ?',
// ── Agents ──────────────────────────────────────────────────────────────────
'agents.title': 'Agents',
'agents.loading': 'Chargement…',
'agents.empty': 'Aucun agent trouvé.',
'agents.back': 'Agents',
'agents.section.chat': 'Discussion',
'agents.section.task': 'Exécuteurs de tâches',
'agents.section.system': 'Système',
'agents.strength.very_high': 'Très élevée',
'agents.strength.high': 'Élevée',
'agents.strength.average': 'Moyenne',
'agents.strength.low': 'Faible',
'agents.strength.very_low': 'Très faible',
'agents.detail.meta': 'Métadonnées',
'agents.detail.id': 'ID',
'agents.detail.strength': 'Puissance',
'agents.detail.pinned_model': 'Modèle épinglé',
'agents.detail.memory_files': 'Fichiers mémoire',
'agents.detail.model_order': 'Ordre de résolution des modèles',
'agents.detail.model_order_desc': 'Modèles triés par leur adéquation avec les exigences de cet agent. Le système utilise le premier modèle disponible en partant du haut.',
'agents.detail.no_models': 'Aucun modèle configuré.',
'agents.detail.prompt': 'Prompt système',
'agents.detail.default': 'défaut',
'agents.table.rank': '#',
'agents.table.strength': 'Puissance',
'agents.table.name': 'Nom',
'agents.table.model_id': 'ID du modèle',
'agents.banner.title': '<strong>Vue en lecture seule.</strong> Les agents sont définis par des fichiers dans <code>agents/</code> — pour ajouter, supprimer ou modifier un agent, modifiez le fichier <code>AGENT.md</code> correspondant dans ce répertoire.',
'agents.banner.text': 'Vous pouvez aussi demander au <strong>Copilot</strong> (barre supérieure) de créer un nouvel agent pour vous — décrivez simplement ce qu\'il doit faire et il configurera tous les fichiers automatiquement.',
// ── Connectors ──────────────────────────────────────────────────────────────
'connectors.title': 'Connecteurs',
'connectors.loading': 'Chargement…',
'connectors.search': 'Rechercher des connecteurs…',
'connectors.btn.signin_providers': 'Fournisseurs d\'authentification',
'connectors.empty.installed': 'Aucun connecteur installé pour le moment.',
'connectors.empty.available': 'Rien de disponible pour vous pour le moment.',
'connectors.empty.install_hint': 'Installez-en un depuis le Marketplace pour commencer.',
'connectors.empty.ask_admin': 'Demandez à un administrateur d\'en rendre un disponible.',
'connectors.empty.match': 'Aucun connecteur ne correspond à "{query}".',
'connectors.chip.global': 'global',
'connectors.chip.per_user': 'par utilisateur',
'connectors.chip.local_script': 'script local',
'connectors.chip.auth.api_key': 'Nécessite une clé API',
'connectors.chip.auth.oauth': 'Connexion requise (OAuth)',
'connectors.chip.auth.qr': 'Appairage QR requis',
'connectors.chip.auth.ssh_key': 'Nécessite une clé SSH',
'connectors.status.active': 'actif',
'connectors.status.needs_fix': 'nécessite une correction',
'connectors.status.needs_signin': 'nécessite une connexion',
'connectors.status.enabled': 'activé',
'connectors.status.off': 'désactivé',
'connectors.status.available': 'disponible',
'connectors.providers.title': 'Fournisseurs d\'authentification',
'connectors.providers.desc': 'Applications OAuth par lesquelles les connecteurs par utilisateur se connectent. Une application (p. ex. Google) couvre tous ses services. Le secret client est stocké sur cette machine et ne sera plus jamais affiché.',
'connectors.providers.empty': 'Aucun fournisseur d\'authentification pour le moment.',
'connectors.providers.secret_set': 'secret défini',
'connectors.providers.no_secret': 'pas de secret',
'connectors.providers.no_client_id': '(pas d\'ID client)',
'connectors.providers.add_google': 'Ajouter Google',
'connectors.providers.add_other': 'Ajouter autre',
'connectors.providers.save': 'Enregistrer',
'connectors.providers.cancel': 'Annuler',
'connectors.providers.delete_confirm': 'Supprimer le fournisseur d\'authentification "{name}" ?\n\nLes connecteurs qui l\'utilisent ne pourront plus se connecter.',
'connectors.providers.error.name_client': 'Le nom et l\'ID client sont requis.',
'connectors.providers.error.secret': 'Un secret client est requis pour un nouveau fournisseur.',
'connectors.providers.field.name': 'ID du fournisseur',
'connectors.providers.field.name_help': 'Le slug référencé par un connecteur (doit correspondre au auth.provider du manifeste).',
'connectors.providers.field.display': 'Nom d\'affichage',
'connectors.providers.field.client_id': 'ID client',
'connectors.providers.field.client_secret': 'Secret client',
'connectors.providers.field.secret_help_new': 'Requis.',
'connectors.providers.field.secret_help_edit': 'Laissez vide pour conserver le secret stocké.',
'connectors.providers.field.auth_url': 'URL d\'autorisation',
'connectors.providers.field.token_url': 'URL du jeton',
'connectors.providers.field.redirect': 'URI de redirection',
'connectors.providers.field.redirect_help': 'La page de copier-coller. Doit être enregistrée comme redirection autorisée dans la console du fournisseur.',
'connectors.providers.field.extra': 'Paramètres supplémentaires (JSON)',
'connectors.providers.field.extra_help': 'Fusionné dans l\'URL de consentement. Google a besoin de ces deux éléments pour renvoyer un jeton d\'actualisation.',
'connectors.detail.back': 'Retour',
'connectors.detail.global_note': 'S\'exécute une fois pour le groupe, sur l\'hôte. Personne n\'y accède avant d\'y être autorisé.',
'connectors.detail.managed.title': 'Ce connecteur est géré pour vous.',
'connectors.detail.managed.desc': 'Il est activé par un administrateur et vous est accordé — il n\'y a rien à configurer.',
'connectors.detail.config.title_active': 'Configuration',
'connectors.detail.config.title_setup': 'Configurer',
'connectors.detail.config.already_global': 'Déjà activé. Une nouvelle soumission remplace les informations d\'identification stockées.',
'connectors.detail.config.already_user': 'Déjà actif. Une nouvelle soumission remplace les informations d\'identification stockées.',
'connectors.detail.config.api_key': 'Clé API',
'connectors.detail.config.btn_test': 'Tester les informations',
'connectors.detail.config.btn_testing': 'Test…',
'connectors.detail.config.btn_enable_global': 'Activer globalement',
'connectors.detail.config.btn_save_restart': 'Enregistrer et redémarrer',
'connectors.detail.config.btn_disable': 'Désactiver',
'connectors.detail.config.btn_activate': 'Activer',
'connectors.detail.config.btn_deactivate': 'Désactiver',
'connectors.detail.detail_scope_global': 'global',
'connectors.detail.scope_local': 'exécute du code sur cette machine',
'connectors.detail.status.active': 'actif',
'connectors.detail.status.needs_fix': 'nécessite une correction',
'connectors.detail.status.needs_signin': 'nécessite une connexion',
'connectors.detail.confirm.deactivate': 'Désactiver "{name}" ?',
'connectors.detail.confirm.disable_global': 'Désactiver "{name}" ?\n\nCela s\'arrête pour tous ceux qui peuvent l\'utiliser.',
'connectors.detail.oauth.title': 'Se connecter',
'connectors.detail.oauth.desc': 'Se connecte avec {provider}. Vous approuvez l\'accès dans un onglet du navigateur, puis recollez le code que la page vous affiche — rien n\'est stocké sur cette machine tant que vous ne le faites pas.',
'connectors.detail.oauth.scopes': 'Il demandera l\'accès à :',
'connectors.detail.oauth.signed_in': 'Connecté et actif.',
'connectors.detail.oauth.btn_signin': 'Se connecter avec {provider}',
'connectors.detail.oauth.btn_signin_again':'Se connecter à nouveau',
'connectors.detail.oauth.btn_finish': 'Terminer la connexion',
'connectors.detail.oauth.btn_complete': 'Finaliser la connexion',
'connectors.detail.oauth.step1': 'Un onglet s\'est ouvert pour {provider}. Approuvez l\'accès là-bas.',
'connectors.detail.oauth.step1_link': 'Rouvrir la page de connexion',
'connectors.detail.oauth.step2': 'Collez le code que la page vous a donné :',
'connectors.detail.oauth.cancel': 'Annuler',
'connectors.detail.oauth.deactivate': 'Désactiver',
'connectors.detail.test.running': 'Test des informations…',
'connectors.detail.test.skipped': 'Aucune étape de vérification pour ce connecteur.',
'connectors.detail.test.ok_label': 'OK',
'connectors.detail.test.fail_label': 'Échec',
'connectors.detail.test.error_saved': 'Enregistré, mais les informations n\'ont pas été vérifiées — corrigez-les et testez à nouveau.',
'connectors.detail.test.error_verify': 'La vérification a échoué — le connecteur reste désactivé jusqu\'à ce que les informations soient corrigées.',
'connectors.error.no_connector': 'Aucun connecteur nommé "{name}" ne vous est disponible.',
// ── Plugins ─────────────────────────────────────────────────────────────────
'plugins.loading': 'Chargement…',
'plugins.empty.manage': 'Aucun plugin enregistré.',
'plugins.enabled': 'Activé',
'plugins.save_config': 'Enregistrer la config',
'plugins.saved': 'Enregistré.',
'plugin_page.loading': 'Chargement…',
'plugin_page.unavailable': 'Page non disponible (plugin désactivé ou page non accordée).',
'plugins.badge.user_page': 'page utilisateur',
'plugins.access.desc': "Qui peut voir et utiliser ce plugin. L'accès se donne depuis la page de chaque personne, à côté de ses connecteurs. Les administrateurs y ont toujours accès.",
'plugins.access.nobody': "Personne n'a encore accès à ce plugin.",
'plugins.access.manage': 'Gérer les accès depuis Utilisateurs',
'plugins.error.required': '« {field} » est requis.',
'plugins.catalog.configure': 'Configurer',
'plugins.health.ok': 'actif',
'plugins.health.off': 'arrêté',
'plugins.health.needs_config': 'à configurer',
'plugins.health.not_running': 'non démarré',
'plugins.badge.instance_config': 'réglages dinstance',
'plugins.detail.back': 'Retour aux plugins',
'plugins.detail.config.title': 'Configuration de linstance',
'plugins.detail.config.empty': 'Ce plugin na aucun réglage dinstance.',
'plugins.detail.config.custom_page': 'Ce plugin possède sa propre page de configuration.',
'plugins.detail.config.open': 'Ouvrir la configuration',
'plugins.detail.access.title': 'Accès utilisateurs',
'plugins.detail.not_found': 'Aucun plugin nommé « {id} ».',
// ── Providers ───────────────────────────────────────────────────────────────
'providers.title': 'Fournisseurs',
'providers.add': 'Ajouter',
'providers.add_first': 'Ajouter votre premier fournisseur',
'providers.empty': 'Aucun fournisseur configuré pour le moment.',
'providers.count': '{n}',
'providers.card.models_title': 'Modèles utilisant ce fournisseur',
'providers.card.api_key_configured': 'Clé API configurée',
'providers.card.api_key_missing': 'Clé API manquante',
'providers.card.edit': 'Modifier',
'providers.card.delete': 'Supprimer',
'providers.card.base_url': 'URL de base',
'providers.modal.add': 'Ajouter un fournisseur',
'providers.modal.edit': 'Modifier le fournisseur',
'providers.modal.name': 'Nom',
'providers.modal.name_ph': 'ex. Mon Anthropic',
'providers.modal.type': 'Type',
'providers.modal.api_key': 'Clé API',
'providers.modal.api_key_ph': 'Laissez vide pour conserver la clé existante',
'providers.modal.base_url': 'URL de base',
'providers.modal.base_url_ollama': 'http://localhost:11434',
'providers.modal.base_url_oai': 'http://localhost:1234/v1',
'providers.modal.description': 'Description',
'providers.modal.description_optional': '(facultatif)',
'providers.modal.cancel': 'Annuler',
'providers.modal.saving': 'Enregistrement…',
'providers.modal.save_changes': 'Enregistrer les modifications',
'providers.modal.add_provider': 'Ajouter un fournisseur',
'providers.confirm.delete': 'Supprimer le fournisseur "{name}" ? Tous les modèles associés seront également supprimés.',
// ── Agents système ──────────────────────────────────────────────────────────
'system_agents.title': 'Agents système',
'system_agents.subtitle': 'Agents en arrière-plan exécutés à intervalles réguliers, sans que vous ayez à le demander. Chacun travaille sur vos propres données et vous prévient directement ; les exécutions ci-dessous sont les vôtres et personne d\'autre ne les voit.',
'system_agents.loading': 'Chargement…',
'system_agents.empty': 'Aucune exécution.',
'system_agents.empty_hint': 'Une exécution n\'est enregistrée que lorsqu\'il y a de nouveaux événements à examiner.',
'system_agents.total': '{n} total',
'system_agents.refresh': 'Actualiser',
'system_agents.table.agent': 'Agent',
'system_agents.table.started': 'Démarrée',
'system_agents.table.status': 'Statut',
'system_agents.table.duration': 'Durée',
'system_agents.table.result': 'Résultat',
'system_agents.status.running': 'En cours',
'system_agents.status.completed': 'Terminée',
'system_agents.status.failed': 'Échouée',
'system_agents.status.cancelled': 'Annulée',
'system_agents.stat.events_processed': 'événements',
'system_agents.stat.notifications_emitted': 'notifications',
'system_agents.stat.notes_examined': 'notes lues',
'system_agents.pagination': 'Page {cur} sur {pages} — {total} exécutions',
'system_agents.tab.all': 'Tous',
'system_agents.settings': 'Paramètres',
'system_agents.agent.event-triage.name': 'Tri des événements',
'system_agents.agent.event-triage.desc': 'Lit les événements reçus par vos connecteurs — nouveaux e-mails, changements d\'agenda, messages entrants — décide lesquels méritent votre attention et ne vous signale que ceux-là. Il s\'exécute pour une personne à la fois et ne lit que les événements de cette personne.',
'system_agents.agent.memory-lint-private.name': 'Entretien de la mémoire privée',
'system_agents.agent.memory-lint-private.desc': 'Une vérification périodique de votre mémoire. Elle recherche les faits dont la date est passée, les questions qui vous ont été posées et restées sans réponse, les notes que l\'index a perdues de vue et les doublons à fusionner — puis vous dit ce qu\'elle a trouvé. Elle ne modifie jamais vos notes.',
'system_agents.agent.memory-lint-shared.name': 'Entretien de la mémoire partagée',
'system_agents.agent.memory-lint-shared.desc': 'La même vérification sur la mémoire partagée du groupe, plus le problème qui n\'existe que là : quelque chose de privé écrit là où tous les membres peuvent le lire. La mémoire partagée n\'appartient à personne, cet agent s\'exécute donc en tant qu\'administrateur et lui adresse son rapport. Il ne modifie jamais rien.',
// ── File viewer ─────────────────────────────────────────────────────────────
'fv.back': 'Retour',
'fv.download': 'Télécharger',
'fv.mode_preview': 'Afficher l\'aperçu',
'fv.mode_source': 'Afficher la source',
'fv.binary_unavailable': 'Aperçu non disponible pour ce type de fichier.',
'fv.latex_failed': 'Échec de la compilation LaTeX — affichage de la source à la place',
'fv.tab_view': 'Afficher',
'fv.tab_edit': 'Modifier',
'fv.dirty_badge': 'Modifications non enregistrées',
'fv.dirty_warn': 'Abandonner les modifications non enregistrées ?',
'fv.save': 'Enregistrer',
'fv.saving': 'Enregistrement…',
'fv.cancel': 'Annuler',
'fv.edit_placeholder': 'Écrire en Markdown…',
'fv.edit_hint': 'Basculer vers Afficher pour l\'aperçu',
'fv.conflict_title': 'Le fichier a été modifié à distance pendant votre modification. Que voulez-vous faire ?',
'fv.conflict_reload': 'Recharger la version distante',
'fv.conflict_copy': 'Copier les miennes, puis recharger',
'fv.conflict_overwrite': 'Écraser',
// ── Marketplace ─────────────────────────────────────────────────────────────
'marketplace.title': 'Marketplace',
'marketplace.btn.connectors': 'Connecteurs',
'marketplace.action.refetch': 'Recharger le flux',
'marketplace.not_admin': 'Le Marketplace est géré par l\'administrateur.',
'marketplace.not_admin_link': 'Les connecteurs installés par l\'administrateur apparaissent sur la page <a href="#connectors">Connecteurs</a>.',
'marketplace.desc': 'Connecteurs vérifiés que vous pouvez ajouter au catalogue de cette machine. Installer n\'active rien — cela rend un connecteur <em>disponible</em>.',
'marketplace.feed_unreachable': 'Marketplace inaccessible — {error}',
'marketplace.loading': 'Chargement du flux…',
'marketplace.filter.search': 'Rechercher des connecteurs…',
'marketplace.filter.scope': 'Portée',
'marketplace.filter.type': 'Type',
'marketplace.filter.all': 'Tous',
'marketplace.filter.global': 'Global',
'marketplace.filter.per_user': 'Par utilisateur',
'marketplace.filter.remote': 'Distant',
'marketplace.filter.local': 'Local',
'marketplace.grid.empty_feed': 'Le flux est vide.',
'marketplace.grid.no_match': 'Aucun connecteur ne correspond à ces filtres.',
'marketplace.card.installed': 'installé',
'marketplace.card.scope_global': 'global',
'marketplace.card.scope_per_user': 'par utilisateur',
'marketplace.card.type_script': 'script local',
'marketplace.card.type_remote': 'distant',
'marketplace.card.files_one': '{n} fichier, vérifié SHA-256 à l\'installation',
'marketplace.card.files_other': '{n} fichiers, vérifiés SHA-256 à l\'installation',
'marketplace.card.oauth_scopes_one': 'Demande {n} portée OAuth',
'marketplace.card.oauth_scopes_other': 'Demande {n} portées OAuth',
'marketplace.card.installing': 'Installation…',
'marketplace.card.reinstall': 'Réinstaller',
'marketplace.card.install': 'Installer',
'marketplace.card.homepage': 'Page d\'accueil',
'marketplace.confirm.install_warn': 'Ceci met du code sur cette machine :\n • {n} fichier(s), chacun vérifié avec SHA-256\n • installé dans ./connectors/{id}/',
'marketplace.confirm.install_body':'Installer "{name}" dans le catalogue ?\n\nInstaller ne l\'active pas.',
// ── Users ───────────────────────────────────────────────────────────────────
'users.title': 'Utilisateurs',
'users.loading': 'Chargement…',
'users.empty': 'Aucun utilisateur.',
'users.count_one': '{n} utilisateur',
'users.count_other': '{n} utilisateurs',
'users.btn.new': 'Nouvel utilisateur',
'users.table.username': 'Nom d\'utilisateur',
'users.table.display_name': 'Nom d\'affichage',
'users.table.role': 'Rôle',
'users.table.db': 'BD',
'users.table.status': 'Statut',
'users.badge.encrypted': 'Chiffré',
'users.badge.cleartext': 'En clair',
'users.badge.active': 'Actif',
'users.badge.inactive': 'Inactif',
'users.action.delete': 'Supprimer',
'users.detail.back': 'Utilisateurs',
'users.detail.profile': 'Profil',
'users.detail.connectors': 'Connecteurs',
'users.detail.plugins': 'Plugins',
'users.detail.security': 'Sécurité',
'users.detail.saved': 'Enregistré',
'users.detail.delete_hint': 'Supprime cet utilisateur, sa base de données et tout l\'historique des conversations.',
'users.detail.no_such': 'Utilisateur introuvable.',
'users.conn.globals': 'Connecteurs partagés',
'users.conn.catalog': 'Connecteurs personnels',
'users.conn.hint_global': 'Disponible pour cet utilisateur dès que vous l\'activez.',
'users.conn.hint_catalog': 'Cet utilisateur peut les activer et se connecter lui-même depuis sa page Connecteurs.',
'users.conn.empty': 'Aucun connecteur enregistré pour le moment.',
'users.conn.disabled': 'désactivé',
'users.plug.hint': "Cochez les plugins que cet utilisateur peut voir et utiliser. Un plugin désactivé peut être accordé dès maintenant : il apparaîtra quand vous l'activerez.",
'users.plug.empty': 'Aucun plugin disponible.',
'users.plug.admin_note': "Les administrateurs peuvent utiliser tout plugin activé, quelles que soient les cases cochées ici.",
'users.modal.create_title': 'Nouvel utilisateur',
'users.modal.username': 'Nom d\'utilisateur',
'users.modal.display_name': 'Nom d\'affichage',
'users.modal.optional': '(facultatif)',
'users.modal.role': 'Rôle',
'users.modal.birthdate': 'Date de naissance',
'users.modal.sex': 'Sexe',
'users.modal.notes': 'Notes',
'users.modal.notes_hint': 'Incluses dans le profil montré aux agents.',
'users.modal.password': 'Mot de passe',
'users.modal.new_password': 'Nouveau mot de passe',
'users.modal.encrypt': 'Chiffrer l\'historique des conversations',
'users.modal.encrypt_warn': '<strong>Attention :</strong> si le mot de passe est perdu, l\'historique des conversations est définitivement irrécupérable.',
'users.modal.active': 'Actif',
'users.modal.only_cleartext': 'Fonctionne uniquement pour les utilisateurs en clair (non chiffrés).',
'users.modal.cancel': 'Annuler',
'users.modal.create_btn': 'Créer',
'users.modal.save_btn': 'Enregistrer',
'users.modal.reset_btn': 'Réinitialiser',
'users.error.required_username_pw': 'Le nom d\'utilisateur et le mot de passe sont requis.',
'users.error.required_username': 'Le nom d\'utilisateur est requis.',
'users.error.password_empty': 'Le mot de passe ne peut pas être vide.',
'users.confirm.delete': 'Supprimer l\'utilisateur "{username}" ? Cela efface définitivement sa base de données et tout l\'historique des conversations.',
// ── Connecteurs : ajout / saisie manuelle ────────────────────────────────────
'connectors.add.btn': 'Ajouter un connecteur',
'connectors.add.marketplace': 'Depuis le Marketplace',
'connectors.add.marketplace_desc': 'Connecteurs vérifiés, fichiers vérifiés par SHA-256.',
'connectors.add.manual': 'Manuellement',
'connectors.add.manual_desc': 'Vous fournissez la configuration, et vous en portez la responsabilité.',
'connectors.action.remove': 'Retirer',
'connectors.new.back': 'Retour',
'connectors.new.title': 'Ajouter un connecteur manuellement',
'connectors.new.script_warn': '<i class="bi bi-exclamation-triangle me-1"></i>Un script local exécute du code sur cette machine. Rien ne le vérifie — contrairement au Marketplace, il n\'y a pas de condensé à contrôler.',
'connectors.new.name': 'Nom',
'connectors.new.name_hint': 'slug',
'connectors.new.scope': 'Portée',
'connectors.new.type': 'Type',
'connectors.new.transport': 'Transport',
'connectors.new.command': 'Commande',
'connectors.new.command_ph': 'python3',
'connectors.new.script_path': 'Chemin du script',
'connectors.new.script_path_hint': 'comme <connecteur>/<fichier>, sous ./connectors',
'connectors.new.url': 'URL',
'connectors.new.args': 'Arguments',
'connectors.new.args_hint': 'un par ligne',
'connectors.new.config_schema': 'Clés secrètes/env requises',
'connectors.new.config_schema_hint': 'virgule/nouvelle ligne',
'connectors.new.auth': 'Auth',
'connectors.new.friendly': 'Nom convivial',
'connectors.new.desc': 'Description',
'connectors.new.desc_hint': 'le LLM lit ceci pour décider d\'activer le connecteur',
'connectors.new.cancel': 'Annuler',
'connectors.new.save': 'Ajouter le connecteur',
'connectors.new.error_name': 'Le nom est requis.',
'connectors.confirm.remove': 'Retirer "{name}" ?\n\nTout ce qui a déjà été activé continuera de fonctionner.',
// ── Cron ────────────────────────────────────────────────────────────────────
'cron.title': 'Tâches Cron',
'cron.count_one': '{n} tâche',
'cron.count_other': '{n} tâches',
'cron.empty.title': 'Aucune tâche cron récurrente.',
'cron.empty.hint': 'Demandez à l\'agent d\'en créer une avec <code>execute_task</code>.',
'cron.badge.running': 'en cours',
'cron.badge.disabled': 'désactivée',
'cron.badge.idle': 'inactive',
'cron.action.delete': 'Supprimer',
'cron.card.label_agent': 'Agent',
'cron.card.label_last_run': 'Dernière exécution',
'cron.card.label_next_run': 'Prochaine exécution',
'cron.card.enabled': 'Activée',
'cron.card.disabled': 'Désactivée',
'cron.confirm.delete': 'Supprimer la tâche "{title}" ?',
// ── Common ─────────────────────────────────────────────────────────────────
'common.save': 'Enregistrer',
'common.saving': 'Enregistrement…',
'common.cancel': 'Annuler',
'common.loading': 'Chargement…',
'common.saved': 'Enregistré',
// ── Shared Folders (blueprint §6) ────────────────────────────────────────────
'nav.shared_folders': 'Dossiers partagés',
'sf.title': 'Dossiers partagés',
'sf.count': '{n} dossier',
'sf.count_plural': '{n} dossiers',
'sf.new': 'Nouveau dossier',
'sf.loading': 'Chargement…',
'sf.empty': 'Aucun dossier partagé pour le moment.',
'sf.empty_hint': 'Créez-en un pour partager des fichiers avec d\'autres membres.',
'sf.note.propagation': 'L\'ajout ou le retrait d\'un membre est appliqué immédiatement à son espace de travail.',
'sf.members': 'Membres',
'sf.no_members': 'Aucun membre pour le moment — seulement vous (admin) pouvez accéder à ce dossier.',
'sf.no_desc': 'Pas encore de description — ajoutez-en une pour que l\'assistant sache quoi garder ici.',
'sf.all_added': 'Tous les disponibles sont déjà membres.',
'sf.choose_user': 'Choisir un membre…',
'sf.add': 'Ajouter',
'sf.remove': 'Retirer',
'sf.edit_desc': 'Modifier la description',
'sf.delete': 'Supprimer',
'sf.access.label': 'Accès',
'sf.access.read': 'Lecture',
'sf.access.write': 'Écriture',
'sf.access.readonly': 'Lecture seule',
'sf.access.readwrite': 'Lecture et écriture',
'sf.confirm.delete': 'Supprimer le dossier partagé "{name}" ?\n\nLes membres perdent l\'accès. Les fichiers sur le disque ne sont pas touchés.',
'sf.confirm.remove_member': 'Retirer {name} de "{folder}" ?',
'sf.error.name': 'Un nom de dossier est requis.',
'sf.form.new': 'Nouveau dossier partagé',
'sf.form.edit': 'Modifier "{name}"',
'sf.form.name': 'Nom du dossier',
'sf.form.name_hint': '(lettres, chiffres, tirets — pas de barres obliques)',
'sf.form.name_ph': 'documents',
'sf.form.name_desc': 'Devient shared/<name> dans l\'espace de travail de chaque membre. Ne peut pas être renommé ultérieurement.',
'sf.form.desc': 'À quoi ça sert ?',
'sf.form.desc_desc': 'L\'assistant lit ceci pour décider quoi stocker ici et quand chercher. Rédigez-le comme des instructions pour l\'assistant.',
'sf.form.desc_ph': 'Factures, contrats et garanties. Enregistrez les PDFs et échéances ici ; vérifiez ici quand on vous interroge sur une facture ou une garantie.',
'sf.form.create': 'Créer',
'sf.form.save': 'Enregistrer',
'sf.form.cancel': 'Annuler',
};