Files
Hermes-ui/packages/client/src/i18n/locales/fr.ts
T
ekkoandClaude Sonnet 4.6 46bc2cf12e Release v0.5.9 (#435)
* fix: add missing i18n key and unify session data source (#408)

- Add `chat.sessionNotFound` translation key to all 8 locales
- Fix history page data source inconsistency:
  - Change `getHermesSession` to prioritize database over CLI
  - Now consistent with `listHermesSessions` behavior
  - Prevents "session in list but detail not found" issue
- Update CI workflow to trigger on base branch PRs
- Remove debug log from sessions-db

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: filter special characters and emoji in speech playback (#409)

- Update extractReadableText to filter special characters like *#
- Only keep common punctuation marks for speech synthesis
- Remove emoji, symbols, and special unicode characters
- Improve text-to-speech readability

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add drawer panel with mobile sidebar support and customizable button (#412)

* feat: add drawer panel with mobile sidebar support

- Add DrawerPanel component with Terminal and Files tabs
- Extract TerminalPanel and FilesPanel from existing views
- Add mobile sidebar toggle functionality with overlay
- Add rainbow breathing light effect to drawer button
- Remove Tools section from AppSidebar (Terminal/Files entries)
- Add i18n support for drawer and file tree
- Optimize mobile button layout and spacing
- Fix z-index hierarchy for proper layering
- Add responsive sidebar behavior (PC: always visible, Mobile: toggle)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: customize drawer button with arc rainbow border

- Change drawer button to semi-circle shape贴着右边
- Add arrow icon pointing left (向左箭头)
- Add rainbow border from top to bottom through semi-circle arc
- Slow down animation from 4s to 8s for smoother effect
- Move drawer button wrapper to messages area only (not贯穿header和input)
- Add semi-transparent accent color background to button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: resolve profile switching state sync issue (#414) (#415)

* fix: resolve profile switching state sync issue (#414)

Fix bug where switching to a different profile would still show the
old profile name in the UI and prevent switching back to default.

Root cause:
- Frontend relied entirely on fetchProfiles() return value to set
  activeProfileName
- Backend Hermes CLI may return stale active flag due to timing
  issues between profile use and profile list commands
- This caused frontend to display wrong profile and prevented
  switching back to default

Solution:
- Immediately set activeProfileName when switchProfile API succeeds
- Don't rely solely on listProfiles() result which may have stale data
- Use activeProfileName instead of activeProfile?.name in ProfileSelector

Changes:
- profiles store: Set activeProfileName immediately after successful switch
- ProfileSelector: Use activeProfileName computed property
- Add test to verify activeProfileName updates on switch

Fixes #414

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refine: improve error handling for profile switching failures

Add proper error handling for edge cases:
- If fetchProfiles() fails after successful switch, keep the updated
  activeProfileName (don't let fetchProfiles failure undo the switch)
- Add test cases to verify:
  1. API failure doesn't change state
  2. fetchProfiles failure doesn't affect successful switch

This ensures the UI remains consistent even when profile list refresh
fails after a successful profile switch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refine: add rollback mechanism for profile switching verification

Add backend verification after profile switch:
- Save old activeProfileName before setting new value
- After fetchProfiles, verify backend reports expected active profile
- If backend reports different profile, rollback frontend state and return false
- This handles edge case where API returns 200 but backend didn't actually switch

Test cases:
-  Normal switch: updates and verifies successfully
-  API failure: doesn't change state
-  fetchProfiles failure: assumes success (API returned 200)
-  Backend verification fails: rolls back to old profile

This ensures frontend state always matches backend reality, even in
edge cases where hermes profile use succeeded but gateway/cleanup
steps failed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refine: add user feedback for profile operations

Improve user experience with success/error messages:
- ProfileSelector: Add error message when switch fails
- ProfileCard: Add success message before reload on switch
- ProfileSelector: Use async/await for better error handling
- ProfileCard: Add 500ms delay before reload to show success message

Before: Silent failures, no feedback
After: Clear success/error messages for all operations

Example feedback:
- Success: "已切换到配置 qinghe"
- Failure: "切换配置失败,网关可能需要手动重启"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: update frontend changelog for v0.5.7 (#419)

* docs: update frontend changelog for v0.5.7

- Update changelog.ts with v0.5.7 release date and changes
- Add i18n translation keys for all languages (en, zh, de, es, fr, ja, ko, pt)
- Include v0.5.7 changelog entries:
  - Optimize context compression and session sync
  - Add startup delays to prevent database race conditions

Changes:
- packages/client/src/data/changelog.ts: Update v0.5.7 entry
- packages/client/src/i18n/locales/*.ts: Add changelog translation section

This enables the changelog modal in the UI to display v0.5.7 release notes.

* feat: add v0.5.7 changelog translations to all supported languages

Add new_0_5_7_1, new_0_5_7_2, and new_0_5_7_3 changelog entries to all
locale files (en, zh, de, es, fr, ja, ko, pt) with proper translations
for each language.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove duplicate changelog sections causing syntax errors

Remove duplicate changelog object sections that were causing TypeScript
syntax errors in all locale files (en, zh, de, es, fr, ja, ko, pt).
The actual changelog entries are already correctly placed in the main
changelog section of each file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add v0.5.8 changelog and fix profile parsing issue

Add v0.5.8 changelog entries based on PRs merged since v0.5.7:
- Drawer panel with mobile sidebar support (#412)
- Profile switching state sync fix (#414)
- Speech playback special character filtering (#409)
- Missing i18n key and session data source unification (#408)
- Vite build optimization for faster Docker builds (#403)

Also fix issue #417: Profile names with long hyphenated names fail
to parse in profile list regex. Change \s{2,} to \s+ to handle
compressed column spacing when profile names are long.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove enter key submit from profile creation and rename modals

Remove @keyup.enter handlers from NInput components in:
- ProfileCreateModal: prevent accidental profile creation when pressing enter
- ProfileRenameModal: prevent accidental profile rename when pressing enter

Users must now explicitly click the confirm button to submit, preventing
unintended profile operations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: allow free text input for profile names

Remove frontend character filtering from profile creation and rename
modals. Users can now input any characters including spaces and
uppercase letters to test backend Hermes CLI validation.

Changes:
- ProfileCreateModal: Remove toLowerCase() and character filtering
- ProfileRenameModal: Remove toLowerCase() and character filtering
- Use v-model:value binding instead of :value with @input

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: improve error handling for profile creation

Display backend error messages when profile creation fails instead of
generic "failed" message. This helps users understand why their
profile name was rejected (e.g., invalid characters).

Changes:
- API layer: Capture and return error messages from backend
- ProfileCreateModal: Display specific error message from backend

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add profile name validation with i18n support

Add client-side validation for profile names to prevent invalid input
before sending to backend. Only lowercase letters, numbers, underscores,
and hyphens are allowed.

Changes:
- ProfileCreateModal: Add input validation with real-time feedback
- ProfileRenameModal: Add input validation with real-time feedback
- Add nameValidation i18n key for all 8 languages
- Filter invalid characters on input and show warning message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: revert profile parsing regex changes

Revert the regex changes in hermes-cli.ts and gateway-manager.ts
back to requiring \s{2,} (at least 2 spaces). Since frontend now
validates profile names to only allow lowercase letters, numbers,
underscores, and hyphens, the relaxed regex is no longer needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: revert profile parsing regex changes

Revert the regex changes in gateway-manager.ts and hermes-cli.ts
back to requiring \s{2,} (at least 2 spaces). Since frontend now
validates profile names to only allow lowercase letters, numbers,
underscores, and hyphens, the relaxed regex is no longer needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: remove tooltip from drawer button

Remove the NTooltip wrapper from the floating drawer button.
The "Terminal & Files" tooltip is no longer shown on hover.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Update assets images (#421)

Updated two asset images in the client package.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: bump version to 0.5.8

Release v0.5.8

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: improve profile list parsing to handle long profile names (#425)

Fixed issue #423 where long profile names caused parsing failures.

Changes:
- gateway-manager.ts: Use `.+?` instead of `\S+` to match profile names, allowing names that overflow table column width
- hermes-cli.ts: Use `\s+` instead of `\s{2,}` for first delimiter to handle cases where long profile names reduce spacing to 1 space

The regex now correctly parses profile output even when profile names are long enough to compress table formatting, ensuring all profiles appear in the UI regardless of name length.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add GitHub issue templates

Add structured issue templates to guide users when submitting issues:
- Bug Report template with version info, reproduction steps, and environment details
- Feature Request template with problem statement, solution, and priority
- General Issue template for questions that don't fit other categories
- Config to enable blank issues and provide contact links to documentation and discussions

Templates use YAML forms for better structure and validation of required fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: unify profile management across the application (#432)

This commit addresses long-standing profile inconsistency issues by establishing
`~/.hermes/active_profile` file as the single source of truth for all profile
operations throughout the application.

## Changes

### Backend (Server)

**1. profiles.ts - Enhanced profile switching**
- Switch from CLI polling to direct file verification (Hermes CLI writes synchronously)
- Verify `active_profile` file with quick retry (max 2 attempts × 100ms = 300ms)
- Update GatewayManager only after file verification succeeds
- Add comprehensive logging for debugging

**2. profiles.ts - Authoritative API responses**
- Override CLI's active flag with `active_profile` file in `list()` endpoint
- Add warning when CLI output differs from file (detects inconsistencies)
- Ensures API responses always match actual runtime state

**3. jobs.ts - Use authoritative profile source**
- `resolveProfile()` falls back to `getActiveProfileName()` when no profile in request
- Ensures jobs operate on correct profile even if frontend doesn't specify

**4. cron-history.ts - Fix run history to respect active profile**
- Changed from fixed `~/.hermes/cron/output/` to `getActiveProfileDir()/cron/output/`
- Run history now correctly switches with profile (e.g., `~/.hermes/profiles/hermes/cron/output/`)

**5. proxy-handler.ts - Add fallback to authoritative source**
- If no profile in request headers/query, read from `getActiveProfileName()`
- Prevents proxy from using wrong default profile

### Frontend (Client)

**1. api/client.ts - Simplified profile resolution**
- Prioritize `useProfilesStore().activeProfileName` over localStorage
- localStorage fallback only for early initialization

**2. api/hermes/chat.ts - Consistent profile resolution**
- Same pattern: store first, localStorage fallback only during init

**3. stores/session-browser-prefs.ts - Clean up fallback logic**
- Prioritize store, remove redundant localStorage read

## Problem Solved

Previously, multiple components had different ways of determining the active profile:
- CLI output (◆ marker) - could be stale
- GatewayManager memory - startup cache only
- localStorage - frontend cache
- Various fallbacks scattered across codebase

This caused inconsistencies where:
- Frontend showed one profile but API used another
- Jobs ran on wrong profile
- Run history displayed wrong data
- Profile switches appeared to fail (but actually succeeded)

## Solution

All components now derive the active profile from the same authoritative source:
- `~/.hermes/active_profile` file (written synchronously by `hermes profile use`)
- `getActiveProfileName()` function (reads the file)
- Single source of truth = no inconsistencies

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add v0.5.9 changelog entries (#434)

- Add unified profile management across the application
- Add GitHub issue and pull request templates

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 12:46:26 +08:00

803 lines
36 KiB
TypeScript
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 {
// Login
login: {
title: 'Hermes Web UI',
description: 'Entrez votre jeton d\'acces pour continuer. Retrouvez-le dans les journaux de demarrage du serveur.',
placeholder: 'Jeton d\'acces',
submit: 'Connexion',
tokenRequired: 'Veuillez entrer votre jeton d\'acces',
invalidToken: 'Jeton invalide',
connectionFailed: 'Impossible de se connecter au serveur',
passwordLogin: 'Mot de passe',
tokenLogin: 'Jeton',
usernamePlaceholder: 'Nom d\'utilisateur',
passwordPlaceholder: 'Mot de passe',
credentialsRequired: 'Veuillez entrer le nom d\'utilisateur et le mot de passe',
invalidCredentials: 'Nom d\'utilisateur ou mot de passe incorrect',
passwordMismatch: 'Les mots de passe ne correspondent pas',
passwordTooShort: 'Le mot de passe doit contenir au moins 6 caracteres',
setupSuccess: 'Login par mot de passe configure avec succes',
passwordChanged: 'Mot de passe change avec succes',
passwordRemoved: 'Login par mot de passe supprime',
setupPassword: 'Configurer le login par mot de passe',
changePassword: 'Changer le mot de passe',
changeUsername: 'Changer le nom d\'utilisateur',
removePasswordLogin: 'Supprimer',
username: 'Nom d\'utilisateur',
currentPassword: 'Mot de passe actuel',
newPassword: 'Nouveau mot de passe',
confirmPassword: 'Confirmer le mot de passe',
newUsername: 'Nouveau nom d\'utilisateur',
usernameChanged: 'Nom d\'utilisateur change avec succes',
usernameTooShort: 'Le nom d\'utilisateur doit contenir au moins 2 caracteres',
setupDescription: 'Configurez un nom d\'utilisateur et un mot de passe pour un login rapide. Le jeton d\'acces reste disponible.',
removeConfirm: 'Voulez-vous vraiment supprimer le login par mot de passe? Vous devrez utiliser le jeton d\'acces.',
passwordLoginNotConfigured: 'Login par mot de passe non configure',
passwordLoginConfigured: 'Login par mot de passe active ({username})',
},
// Common
common: {
loading: 'Chargement...',
cancel: 'Annuler',
retry: 'Réessayer',
delete: 'Supprimer',
edit: 'Modifier',
save: 'Enregistrer',
saved: 'Enregistre',
update: 'Mettre a jour',
create: 'Creer',
saveFailed: 'Echec de l\'enregistrement',
deleteFailed: 'Echec de la suppression',
ok: 'OK',
copied: 'Copie',
copy: 'Copier',
noData: 'Aucune donnee',
fetch: 'Recuperer',
add: 'Ajouter',
enable: 'Activer',
disable: 'Desactiver',
configured: 'Configure',
notConfigured: 'Non configure',
confirm: 'Confirmer',
expand: 'Developper',
collapse: 'Reduire',
},
// Sidebar
sidebar: {
chat: 'Discussion',
search: 'Rechercher',
history: 'Historique',
jobs: 'Taches planifiees',
models: 'Modeles',
profiles: 'Profils',
skills: 'Competences',
memory: 'Memoire',
logs: 'Journaux',
usage: 'Utilisation',
channels: 'Canaux',
terminal: 'Terminal',
files: 'Fichiers',
groupChat: 'Chat de groupe',
groupConversation: 'Conversation',
settings: 'Parametres',
connected: 'Connecte',
disconnected: 'Deconnecte',
updateTip: 'Executez "hermes-web-ui update" dans le terminal pour mettre a jour',
updateVersion: 'Mettre a jour vers v{version}',
updating: 'Mise a jour...',
updateSuccess: 'Mise a jour terminee, veuillez redemarrer le serveur',
updateFailed: 'Echec de la mise a jour',
logout: 'Deconnexion',
nodeVersionWarning: 'Node.js v{version} detecte. Veuillez passer a la version 23 ou ulterieure.',
changelog: 'Journal des modifications',
noChangelog: 'Aucun journal disponible',
},
// Drawer
drawer: {
terminal: 'Terminal',
files: 'Espace de travail',
},
// Chat
chat: {
contextRemaining: 'restant',
emptyState: 'Demarrer une conversation avec Hermes Agent',
inputPlaceholder: 'Tapez un message... (Entree pour envoyer, Shift+Entree pour un saut de ligne)',
attachFiles: 'Joindre des fichiers',
stop: 'Arreter',
send: 'Envoyer',
contextUsed: 'Contexte utilise :',
sessions: 'Sessions',
webUiSessions: 'Sessions Web UI/API Server',
sessionScopeHint: 'Le chat affiche uniquement les sessions Web UI/API Server. Les sessions CLI, Telegram, Discord, Cron et autres canaux sont en lecture seule dans Historique.',
openHistory: 'Ouvrir lhistorique',
hermesHistory: 'Historique Hermes',
historyScopeHint: 'Sessions dhistorique Hermes en lecture seule, regroupées par source.',
noSessions: 'Aucune session',
newChat: 'Nouvelle discussion',
deleteSession: 'Supprimer cette session ?',
sessionDeleted: 'Session supprimee',
rename: 'Renommer',
pin: 'Épingler',
unpin: 'Désépingler',
pinned: 'Épinglés',
chatMode: 'Chat',
liveMode: 'Direct',
liveSessions: 'Sessions en direct',
recentBadge: 'Récent',
linkedSessions: '{count} sessions liées',
noVisibleMessages: 'Aucun message visible par lhumain.',
monitorRoleUser: 'Utilisateur',
monitorRoleAssistant: 'Assistant',
copySessionId: "Copier l'ID de session",
renamed: 'Renomme',
renameFailed: 'Echec du renommage',
renameSession: 'Renommer la session',
sessionNotFound: 'Session non trouvee',
enterNewTitle: 'Entrez un nouveau titre',
other: 'Autre',
runFailed: 'Echec de l\'execution',
error: 'Erreur',
tool: 'Outil',
arguments: 'Arguments',
result: 'Resultat',
truncated: '... (tronque)',
executionDuration: 'Execution time', thinkingLabel: 'Raisonnement',
thinkingInProgress: 'En réflexion…',
thinkingShow: 'Afficher le raisonnement',
thinkingHide: 'Masquer le raisonnement',
thinkingDuration: 'Observé {duration}',
thinkingChars: '{count} caractères',
copyBubble: 'Copier le message',
copiedBubble: 'Message copié',
copyFailed: 'Échec de la copie',
playSpeech: 'Lire à voix haute',
pauseSpeech: 'Pause',
resumeSpeech: 'Reprendre',
stopSpeech: 'Arrêter',
speechNotSupported: 'Reproduction vocale non prise en charge dans ce navigateur',
},
// Jobs
jobs: {
title: 'Taches planifiees',
createJob: 'Creer une tache',
editJob: 'Modifier la tache',
noJobs: 'Aucune tache planifiee. Creez-en une pour commencer.',
name: 'Nom',
namePlaceholder: 'Nom de la tache',
schedule: 'Planification (expression Cron)',
schedulePlaceholder: 'ex. 0 9 * * *',
quickPresets: 'Presets rapides',
selectPreset: 'Selectionner un preset...',
presetEveryMinute: 'Chaque minute',
presetEvery5Min: 'Toutes les 5 minutes',
presetEveryHour: 'Chaque heure',
presetEveryDay: 'Tous les jours a 00:00',
presetEveryDay9: 'Tous les jours a 09:00',
presetEveryMonday: 'Chaque lundi a 09:00',
presetEveryMonth: 'Le 1er de chaque mois a 09:00',
prompt: 'Invite',
promptPlaceholder: 'L\'invite a executer',
deliverTarget: 'Cible de livraison',
origin: 'Origine',
local: 'Local',
repeatCount: 'Nombre de repetitions (facultatif)',
modelPlaceholder: 'Modele par defaut',
repeatPlaceholder: 'Laisser vide pour infini',
jobCreated: 'Tache creee',
jobUpdated: 'Tache mise a jour',
nameRequired: 'Le nom est requis',
scheduleRequired: 'La planification est requise',
loadFailed: 'Echec du chargement de la tache',
jobPaused: 'Tache en pause',
jobResumed: 'Tache reprise',
jobTriggered: 'Job declenche',
modelUpdated: 'Modele mis a jour',
jobDeleted: 'Tache supprimee',
status: {
running: 'En cours',
paused: 'En pause',
disabled: 'Desactivee',
scheduled: 'Planifiee',
},
info: {
model: 'Modele',
schedule: 'Planification',
lastRun: 'Derniere execution',
nextRun: 'Prochaine execution',
deliver: 'Livraison',
repeat: 'Repetition',
},
action: {
pause: 'Pause',
pauseJob: 'Mettre en pause',
resume: 'Reprendre',
resumeJob: 'Reprendre la tache',
runNow: 'Executer maintenant',
triggerImmediately: 'Déclencher immédiatement',
},
runHistory: {
title: 'Historique',
runs: 'exécutions',
noRuns: 'Aucun historique trouvé.',
},
},
// Skills
skills: {
title: 'Competences',
searchPlaceholder: 'Rechercher des competences...',
noMatch: 'Aucune competence ne correspond a votre recherche',
noSkills: 'Aucune competence trouvee',
backTo: 'Retour a',
attachedFiles: 'Fichiers joints',
loadFailed: 'Echec du chargement de la competence',
fileLoadFailed: 'Echec du chargement du fichier',
modified: "Modifi\u00e9 par l'utilisateur",
archived: 'Archivé',
pinned: 'Épinglé',
pin: 'Épingler la compétence',
unpin: 'Désépingler la compétence',
pinFailed: "Impossible de changer le statut d'épinglage",
toggleFailed: 'Echec de l\'activation/desactivation de la competence',
source: {
builtin: 'Intégré',
hub: 'Hub',
local: 'Local',
},
},
// Memory
memory: {
title: 'Memoire',
refresh: 'Actualiser',
loadFailed: 'Echec du chargement de la memoire',
myNotes: 'Mes notes',
noNotes: 'Aucune note pour l\'instant.',
notesPlaceholder: 'Ecrivez vos notes...',
userProfile: 'Profil utilisateur',
noProfile: 'Aucun profil pour l\'instant.',
profilePlaceholder: 'Ecrivez votre profil...',
soul: 'Ame',
noSoul: 'Aucune configuration d\'ame pour l\'instant.',
soulPlaceholder: 'Ecrivez la configuration de l\'ame...',
},
// Models
models: {
title: 'Modeles',
addProvider: 'Ajouter un fournisseur',
providerType: 'Type de fournisseur',
preset: 'Preset',
custom: 'Personnalise',
selectProvider: 'Selectionner un fournisseur',
chooseProvider: 'Choisir un fournisseur...',
name: 'Nom',
autoGeneratedName: 'Genere automatiquement a partir de l\'URL de base',
baseUrl: 'URL de base',
region: 'Région',
regionIntl: 'International',
regionCn: 'Chine continentale',
baseUrlPlaceholder: 'ex. https://api.example.com/v1',
apiKey: 'Cle API',
apiKeyPlaceholder: 'sk-...',
defaultModel: 'Modele par defaut',
selectOrInput: 'Sélectionner ou saisir un modèle...',
selectModel: 'Selectionner un modele...',
providerAdded: 'Fournisseur ajoute',
providerDeleted: 'Fournisseur supprime',
deleteProvider: 'Supprimer le fournisseur',
deleteConfirm: 'Etes-vous sur de vouloir supprimer "{name}" ?',
codexLoginTitle: 'Connexion OpenAI Codex',
codexWaiting: 'Entrez ce code sur la page d\'autorisation pour vous connecter :',
codexCopyCode: 'Code copié',
codexOpenLink: 'Ouvrir la page d\'autorisation',
codexApproved: 'Connexion réussie',
codexExpired: 'L\'autorisation a expiré. Veuillez réessayer.',
nousLoginTitle: 'Connexion Nous Portal',
nousWaiting: 'Entrez ce code sur la page d\'autorisation:',
nousCopyCode: 'Code copié',
nousOpenLink: 'Ouvrir la page d\'autorisation',
nousApproved: 'Connexion réussie',
nousDenied: 'Autorisation refusée',
nousExpired: 'Autorisation expirée',
copilotLoginTitle: 'Connexion GitHub Copilot',
copilotWaiting: 'Ouvrez GitHub et saisissez le code ci-dessous pour autoriser. La fenêtre se fermera automatiquement après approbation.',
copilotCopyCode: 'Code copié',
copilotOpenLink: 'Ouvrir la page d\'autorisation GitHub',
copilotApproved: 'Connexion réussie !',
copilotDenied: 'Autorisation refusée.',
copilotExpired: 'Le lien d\'autorisation a expiré. Veuillez réessayer.',
copilotAddDetectedTitle: 'GitHub Copilot détecté',
copilotAddDetected: 'Un token OAuth GitHub Copilot a été détecté sur cette machine. Cliquez sur Ajouter pour activer Copilot dans Hermes.',
copilotAddSourceEnv: 'Source : ~/.hermes/.env (COPILOT_GITHUB_TOKEN)',
copilotAddSourceGhCli: 'Source : gh CLI (gh auth token)',
copilotAddSourceAppsJson: 'Source : extension Copilot de VS Code (apps.json)',
copilotDeleteHintEnv: 'Cela supprimera COPILOT_GITHUB_TOKEN dans ~/.hermes/.env. Les autres outils ne sont pas affectés.',
copilotDeleteHintGhCli: 'Copilot sera masqué dans Hermes. Votre connexion gh CLI n\'est pas affectée — `gh auth status` indiquera toujours que vous êtes connecté.',
copilotDeleteHintAppsJson: 'Copilot sera masqué dans Hermes. Votre extension Copilot de VS Code reste connectée.',
customBadge: 'PERSONNALISÉ',
previewBadge: 'APERÇU',
disabledBadge: 'INDISPONIBLE',
disabledTooltip: "Ce modèle n'est pas disponible pour votre compte.",
customModelPlaceholder: 'Nom du modèle personnalisé',
customModelHint: 'Entrée pour charger',
noProviders: 'Aucun fournisseur trouve. Ajoutez un fournisseur personnalise pour commencer.',
builtIn: 'Integre',
customType: 'Personnalise',
provider: 'Fournisseur',
contextLength: 'Longueur du contexte',
contextLengthPlaceholder: 'ex. 200000 (facultatif)',
local: 'Local ({host})',
selectProviderRequired: 'Veuillez selectionner un fournisseur',
baseUrlRequired: 'L\'URL de base est requise',
apiKeyRequired: 'La cle API est requise',
modelRequired: 'Le modele par defaut est requis',
enterBaseUrl: 'Veuillez d\'abord entrer l\'URL de base',
unexpectedFormat: 'Format de reponse inattendu',
foundModels: '{count} modeles trouves',
fetchFailed: 'Echec de la recuperation des modeles',
},
// Profiles
profiles: {
title: 'Profils',
create: 'Creer un profil',
import: 'Importer',
export: 'Exporter',
rename: 'Renommer',
delete: 'Supprimer',
switchTo: 'Passer a',
switchConfirm: 'Le passage au profil "{name}" redemarrera la passerelle. Continuer ?',
switchSuccess: 'Profil "{name}" actif',
switchFailed: 'Echec du changement de profil. La passerelle peut necessiter un redemarrage manuel.',
createSuccess: 'Profil "{name}" cree',
createFailed: 'Echec de la creation du profil',
renameSuccess: 'Profil renomme',
renameFailed: 'Echec du renommage du profil',
deleteConfirm: 'Etes-vous sur de vouloir supprimer le profil "{name}" ?',
deleteSuccess: 'Profil supprime',
deleteFailed: 'Echec de la suppression du profil',
exportSuccess: 'Profil exporte',
exportFailed: 'Echec de l\'exportation du profil',
importSuccess: 'Profil importe',
importFailed: 'Echec de l\'importation du profil',
importSelectFile: 'Selectionner un fichier d\'archive',
importInvalidFile: 'Veuillez selectionner une archive valide (.tar.gz, .tgz, .gz, .zip)',
name: 'Nom du profil',
namePlaceholder: 'Lettres, chiffres et tirets uniquement',
nameValidation: 'Le nom du profil ne peut contenir que des lettres minuscules, des chiffres, des tirets bas et des tirets',
newName: 'Nouveau nom',
newNamePlaceholder: 'Entrez un nouveau nom',
cloneFromCurrent: 'Cloner depuis le profil actuel',
cloneCleanupNotice: 'Lors du clonage, les identifiants de plateformes exclusives (Weixin / Telegram / Slack, etc.) sont automatiquement ignorés pour éviter les conflits avec le profil source',
cloneStrippedCredentials: '{count} identifiant(s) exclusif(s) supprimé(s) : {list}',
cloneDisabledPlatforms: '{count} plateforme(s) désactivée(s) : {list}',
cloneStrippedConfigCredentials: '{count} identifiant(s) intégré(s) supprimé(s) de config.yaml : {list}',
archivePath: 'Chemin de l\'archive',
archivePathPlaceholder: 'Chemin serveur du fichier d\'archive',
importName: 'Nom du profil (facultatif)',
importNamePlaceholder: 'Laisser vide pour utiliser le nom de l\'archive',
active: 'Actif',
model: 'Modele',
gateway: 'Passerelle',
alias: 'Alias',
provider: 'Fournisseur',
path: 'Chemin',
skills: 'Competences',
hasEnv: 'A un .env',
hasSoulMd: 'A un soul.md',
noProfiles: 'Aucun profil trouve. Creez-en un pour commencer.',
},
// Logs
logs: {
title: 'Journaux',
all: 'Tout',
searchPlaceholder: 'Rechercher...',
refresh: 'Actualiser',
noEntries: 'Aucune entree de journal',
},
// Settings
settings: {
title: 'Parametres',
saved: 'Enregistre',
saveFailed: 'Echec de l\'enregistrement',
tabs: {
display: 'Affichage',
account: 'Compte',
agent: 'Agent',
memory: 'Memoire',
session: 'Session',
privacy: 'Confidentialite',
apiServer: 'Serveur API',
},
display: {
streaming: 'Reponses en continu',
streamingHint: 'Afficher les reponses de l\'IA en temps reel',
compact: 'Mode compact',
compactHint: 'Reduire l\'espacement des messages',
showReasoning: 'Afficher le raisonnement',
showReasoningHint: 'Afficher le processus de reflexion du modele',
showCost: 'Afficher le cout',
showCostHint: 'Afficher l\'utilisation des jetons dans les reponses',
inlineDiffs: 'Diffs en ligne',
inlineDiffsHint: 'Afficher les changements de code en ligne',
bellOnComplete: 'Son de fin',
bellOnCompleteHint: 'Jouer un son lorsque l\'IA a termine',
busyInputMode: 'Mode saisie active',
busyInputModeHint: 'Permettre la saisie pendant le traitement de l\'IA',
theme: 'Theme',
themeHint: 'Choisir clair, sombre ou suivre les preferences du systeme',
themeLight: 'Clair',
themeDark: 'Sombre',
themeSystem: 'Systeme',
},
agent: {
maxTurns: 'Tours maximum',
maxTurnsHint: 'Nombre maximum de tours d\'interaction par conversation',
gatewayTimeout: 'Delai d\'attente de la passerelle',
gatewayTimeoutHint: 'Delai d\'attente de la requete en secondes',
restartDrainTimeout: 'Delai de vidange au redemarrage',
restartDrainTimeoutHint: 'Delai de vidange avant redemarrage en secondes',
toolEnforcement: 'Application des outils',
toolEnforcementHint: 'Controler le mode d\'execution des appels d\'outils',
auto: 'Automatique',
always: 'Toujours',
never: 'Jamais',
},
memory: {
enabled: 'Activer la memoire',
enabledHint: 'Permettre a l\'IA de memoriser le contexte de conversation',
userProfile: 'Profil utilisateur',
userProfileHint: 'Permettre a l\'IA de memoriser les preferences utilisateur',
charLimit: 'Limite de caracteres de la memoire',
charLimitHint: 'Nombre maximum de caracteres pour MEMORY.md',
userCharLimit: 'Limite de caracteres du profil utilisateur',
userCharLimitHint: 'Nombre maximum de caracteres pour USER.md',
},
session: {
mode: 'Mode de reinitialisation',
modeHint: 'Condition de declenchement de la reinitialisation de session',
modeBoth: 'Inactivite + Planifie',
modeIdle: 'Inactivite uniquement',
modeHourly: 'Planifie uniquement',
idleMinutes: 'Delai d\'inactivite',
idleMinutesHint: 'Temps d\'attente avant reinitialisation automatique (minutes)',
atHour: 'Heure de reinitialisation planifiee',
humanOnly: 'Afficher uniquement les sessions humaines',
humanOnlyHint: 'Masquer par défaut le bruit des sous-agents et du moniteur de session',
liveMonitorHumanOnly: 'Moniteur live : nafficher que les sessions humaines',
liveMonitorHumanOnlyHint: 'Masquer par défaut le bruit des sous-agents et du moniteur de session dans le moniteur live',
atHourHint: 'Reinitialiser la session a cette heure chaque jour',
},
privacy: {
redactPii: 'Masquer les DPI',
redactPiiHint: 'Detecter et masquer automatiquement les informations sensibles (mots de passe, cles, etc.)',
},
apiServer: {
enable: 'Activer',
enableHint: 'Activer le serveur API',
host: 'Hote',
hostHint: 'Adresse d\'ecoute',
port: 'Port',
portHint: 'Port d\'ecoute',
key: 'Cle',
keyHint: 'Cle d\'acces API',
cors: 'Origines CORS',
corsHint: 'Sources cross-origin autorisees',
},
},
// Platform channel settings
platform: {
requireMention: "Exiger une mention {'@'}",
requireMentionGroup: "Exiger une mention {'@'} dans les groupes pour repondre",
requireMentionChannel: "Exiger une mention {'@'} dans les canaux pour repondre",
requireMentionRoom: "Exiger une mention {'@'} dans les salles pour repondre",
reactions: 'Reactions',
reactionsHint: 'Reagir aux messages avec des emoji',
freeResponseChats: 'Discussions en reponse libre',
freeResponseChatsHint: "ID de discussions repondant sans mention {'@'} (separes par des virgules)",
freeResponseChannels: 'Canaux en reponse libre',
freeResponseChannelsHint: "ID de canaux repondant sans mention {'@'} (separes par des virgules)",
freeResponseRooms: 'Salles en reponse libre',
freeResponseRoomsHint: "ID de salles repondant sans mention {'@'} (separes par des virgules)",
mentionPatterns: 'Motifs de mention personnalises',
mentionPatternsHint: 'Motifs de declenchement supplementaires',
autoThread: 'Fil automatique',
autoThreadHint: "Creer automatiquement des fils de reponse apres une mention {'@'}",
autoThreadHintRoom: 'Creer automatiquement des fils de reponse dans les salles',
dmMentionThreads: 'Fils de mention en MP',
dmMentionThreadsHint: 'Utiliser des fils de reponse pour les mentions en MP',
allowBots: 'Autoriser les messages de bots',
allowBotsHint: 'Repondre aux messages d\'autres bots',
allowedChannels: 'Canaux autorises',
allowedChannelsHint: 'Liste blanche des ID de canaux (separes par des virgules)',
ignoredChannels: 'Canaux ignores',
ignoredChannelsHint: 'Canaux ou le bot ne repond jamais (separes par des virgules)',
noThreadChannels: 'Canaux sans fil',
noThreadChannelsHint: 'Canaux ou le bot repond sans fil (separes par des virgules)',
exclusiveTokenWarning: 'Cette plateforme utilise un verrou de jeton exclusif. Chaque profil doit utiliser un jeton d\'identite different pour eviter les conflits avec les autres profils.',
botToken: 'Jeton de bot',
botTokenHint: 'Jeton de bot depuis le portail developpeur',
accessToken: 'Jeton d\'acces',
accessTokenHint: 'Jeton d\'acces Matrix',
homeserver: 'URL du serveur domestique',
homeserverHint: 'URL du serveur domestique Matrix',
appId: 'ID de l\'application',
appIdHint: 'ID de l\'application Feishu',
appSecret: 'Secret de l\'application',
appSecretHint: 'Secret de l\'application Feishu',
clientId: 'ID client',
clientIdHint: 'ID client DingTalk',
clientSecret: 'Secret client',
clientSecretHint: 'Secret client DingTalk',
botId: 'ID du bot',
botIdHint: 'ID du bot WeCom',
wecomSecretHint: 'Secret du bot WeCom',
waEnabled: 'Activer WhatsApp',
waEnabledHint: 'Activer WhatsApp via appairage par code QR',
weixinToken: 'Jeton Weixin',
weixinTokenHint: 'Depuis la connexion QR de la CLI weixin (hermes weixin)',
accountId: 'ID de compte',
accountIdHint: 'ID du compte Weixin',
qrLogin: 'Connexion QR',
qrRelogin: 'Reconnexion',
qrFetching: 'Recuperation du code QR...',
qrScanHint: 'Scannez avec WeChat pour vous connecter',
qrScanedHint: 'Scanne, veuillez confirmer sur le telephone...',
},
// Language
language: {
label: 'Langue',
zh: '中文',
en: 'English',
fr: 'Francais',
},
// Terminal
terminal: {
sessions: 'Sessions',
newTab: 'Nouveau terminal',
closeSession: 'Fermer cette session ?',
sessionExited: 'Terminee',
processExited: 'Processus termine avec le code {code}',
},
// Usage
usage: {
title: 'Statistiques d\'utilisation',
refresh: 'Actualiser',
totalTokens: 'Total des jetons',
inputTokens: 'Entree',
outputTokens: 'Sortie',
totalSessions: 'Total des sessions',
avgPerDay: '~{n}/jour en moy.',
estimatedCost: 'Cout est.',
cacheHitRate: 'Taux de succes du cache',
modelBreakdown: 'Repartition par modele',
dailyTrend: 'Utilisation quotidienne (30 derniers jours)',
date: 'Date',
tokens: 'Jetons',
cache: 'Cache',
cacheRead: 'Cache Read',
cacheWrite: 'Cache Write',
sessions: 'Sessions',
cost: 'Cout',
noData: 'Aucune donnee d\'utilisation',
},
// Journal des modifications
changelog: {
new_0_5_6_1: 'Lecture vocale avec Web Speech API: bouton manuel, interrupteur auto-play, animation bordure arc-en-ciel et optimisation mobile',
new_0_5_6_2: 'Parseur JSON LLM robuste avec tolérance au format Python et extraction de texte des événements streaming',
new_0_5_6_3: 'Améliorations des Skills: statistiques d\'utilisation, filtrage par source, compétences archivées, provenance et toggle d\'épinglage',
new_0_5_6_4: 'Statistiques d\'utilisation quotidiennes étendues avec répartition détaillée des tokens incluant la séparation lecture/écriture du cache',
new_0_5_6_5: 'Portée de l\'historique des sessions clarifiée avec descriptions améliorées dans les vues chat et historique',
new_0_5_6_6: 'Repensé la gestion des pièces jointes en utilisant le format de tableau ContentBlock style Anthropic (texte, image, fichier)',
new_0_5_6_7: 'Ajouté la fonctionnalité de téléchargement de fichiers frontend supportant les formats ContentBlock et Markdown avec authentification',
new_0_5_6_8: 'Corrigé le conflit multi-processus causant des réinitialisations de base de données SQLite en éliminant les instances nodemon redondantes',
new_0_5_9_1: 'Unifier la gestion des profils dans toute l\'application avec une API et une gestion d\'état cohérentes',
new_0_5_9_2: 'Ajouter des modèles issues et pull requests GitHub pour un meilleur flux de contribution',
new_0_5_8_1: 'Ajouter le panneau de tiroir avec support de barre latérale mobile et bouton arc-en-ciel personnalisable',
new_0_5_8_2: 'Corriger le problème de synchronisation d\'état de changement de profil avec mise à jour immédiate de l\'UI et vérification du backend',
new_0_5_8_3: 'Filtrer les caractères spéciaux et emoji dans la lecture vocale pour une meilleure synthèse vocale',
new_0_5_8_4: 'Ajouter la clé i18n manquante et unifier la source de données de session pour prioriser la base de données',
new_0_5_8_5: 'Optimiser la configuration de build Vite pour des builds Docker plus rapides avec esbuild et la division de chunks',
new_0_5_7_1: 'Optimiser la compression du contexte pour supporter le contenu riche (images, fichiers) avec amélioration du traitement des messages d\'outils',
new_0_5_7_2: 'Améliorer la synchronisation des sessions avec des insertions par lot et la protection des transactions pour la cohérence des données',
new_0_5_7_3: 'Corriger la réception des événements usage.updated pour assurer un suivi précis des tokens entre les exécutions',
new_0_5_5_1: '🎉 Joyeuse Fête du Travail! Pas de travail aujourd\'hui, merci de votre compréhension',
new_0_5_5_2: 'Ajout d\'une page d\'historique pour les sessions Hermes',
new_0_5_5_3: 'La page d\'historique gère les sessions de manière indépendante',
new_0_5_5_4: 'Chargement automatique de la première session CLI',
new_0_5_5_5: 'Composant HistoryMessageList avec injection de props',
new_0_5_5_6: 'Filtrage des messages vides et des tools sans toolName',
new_0_5_5_7: 'Suppression du cache localStorage des sessions',
new_0_5_5_8: 'Optimisation du changement de profil',
new_0_5_4_2: 'Fix concurrent chat sessions event cross-talk with WebSocket event routing refactoring',
new_0_5_4_3: 'Fix cron job edit payloads with partial PATCH to support long prompt name-only edits',
new_0_5_4_4: 'Fix web terminal Hermes CLI availability after Docker deployment',
new_0_5_4_5: 'Add workspace dialog i18n translations for title and improve session persistence',
new_0_5_4_6: 'Support code block copy feedback with user notifications',
new_0_5_4_7: 'Align usage analytics with Hermes state DB schema',
new_0_5_3_1: 'Improve reasoning process display with persistence across page refreshes',
new_0_5_3_2: 'Optimize stringified array format parsing to extract thinking/text/tool_calls',
new_0_5_3_3: 'Improve log display by removing ellipsis and showing full content',
new_0_5_3_4: 'Add detailed logging for format conversion and parsing',
new_0_5_3_5: 'Optimize token calculation to accurately include tool results',
new_0_5_2_1: 'Convert conversation history to Anthropic format before sending to Gateway',
new_0_5_2_2: 'Add bidirectional reasoning sync between memory and database',
new_0_5_2_3: 'Add message pagination with DESC query + array reverse for performance',
new_0_5_2_4: 'Clean up debug code and unused imports',
new_0_5_2_5: 'Remove auto-resumed event trigger to avoid timing issues',
new_0_5_2_6: 'Use reasoning field consistently across codebase',
new_0_5_1_1: 'Auto-sync Hermes history sessions on first startup',
new_0_5_1_2: 'Fix session sync failure with old Hermes versions (backward compatible)',
new_0_5_1_3: 'Smart cleanup of exclusive platform credentials on profile clone (Telegram, Discord, Slack, etc.)',
new_0_5_1_4: 'Auto-normalize profile names to lowercase to avoid backend validation errors',
new_0_5_1_5: 'Fix tool_call_id missing in tool messages for OpenAI API compatibility',
new_0_5_1_6: 'Unify SQLite table schema management and initialization',
new_0_5_1_7: 'Optimize model list layout in Provider cards (fixed height, tag alignment)',
new_0_5_1_8: 'Fix display issue with single-line long code blocks in user messages',
new_0_5_1_9: 'Fix web terminal rendering errors in Docker deployment',
new_0_5_0_1: 'Self-built chat database and context compression: empty chat history on first entry is expected',
new_0_5_0_2: 'Sessions use WebSocket form, enhanced resume capability',
new_0_4_8_1: 'Safe Mermaid diagram rendering with async render and timeout fallback',
new_0_4_8_2: 'Fix nested markdown fence rendering truncation',
new_0_4_8_3: 'Fix compressed session lineage projection and search',
new_0_4_8_4: 'Optimize session list N+1 queries and fix search 500 on non-CJK input',
new_0_4_8_5: 'Fix forced scroll to bottom when switching back from other tabs',
new_0_4_8_6: 'Smooth session switch with loading transition overlay',
new_0_4_8_7: 'Fix login token validation using Hermes session endpoint',
new_0_4_8_8: 'Fix image attachments broken after page refresh (blob URL persistence)',
new_0_4_8_9: 'Click image attachments to preview in fullscreen overlay',
new_0_4_8_10: 'Move upload directory from temp to ~/.hermes-web-ui/upload',
new_0_4_7_1: 'Affichage en streaming en temps reel des blocs de reflexion/raisonnement',
new_0_4_7_2: 'Ignorer le script de preparation lors du build Docker',
new_0_4_7_3: 'Ameliorations UX mobile du chat de groupe et polissage de l\'interface',
new_0_4_7_4: 'Limiter les jetons restants du contexte a 0 au lieu de negatif',
new_0_4_7_5: 'Ajouter le fournisseur integre Alibaba Coding Plan avec remplacement base_url dans .env',
new_0_4_7_6: 'Ignorer les profils distants au demarrage pour eviter le blocage',
new_0_4_7_7: 'Detecter et afficher les erreurs d\'execution silencieusement ignorees',
new_0_4_7_8: 'Recherche de longueur de contexte sensible au fournisseur',
new_0_4_7_9: 'Reinitialiser config.model lors du changement et resoudre le fournisseur personnalise CLI',
new_0_4_7_10: 'Supprimer base_url_env du .env lors de la suppression du fournisseur integre',
new_0_4_7_11: 'Aligner le fond de la barre laterale du chat de groupe avec la liste des sessions',
new_0_4_5_1: 'Add group chat with multi-agent rooms, @mention routing, and typing status recovery',
new_0_4_5_2: 'Rewrite model-context config to use YAML with context_length setting',
new_0_4_5_3: 'Add gpt-5.5 to OpenAI Codex model list',
new_0_4_5_4: 'Replace jobs proxy with local controller and optimize model loading',
new_0_4_5_5: 'Add i18n support for custom model feature in ModelSelector',
new_0_4_5_6: 'Fix sidebar i18n missing key warnings',
new_0_4_5_7: 'Clear all localStorage on logout',
new_0_4_5_8: 'Add periodic log rotation to prevent unbounded log growth',
new_0_4_2_1: 'Ajouter le suivi de l\'utilisation des tokens et la longueur de contexte dynamique',
new_0_4_2_2: 'Ajouter la modal de recherche de sessions',
new_0_4_2_3: 'Restaurer le systeme de chat de groupe avec Socket.IO et SQLite',
new_0_4_2_4: 'Ajouter les sessions epinglees et le moniteur en direct',
new_0_4_2_5: 'Corriger la detection des fournisseurs integres et l\'appariement des modeles',
},
// Fichiers
files: {
title: 'Fichiers',
tree: 'Arborescence',
list: 'Liste des fichiers',
breadcrumbRoot: 'Accueil',
newFile: 'Nouveau fichier',
newFolder: 'Nouveau dossier',
upload: 'Telecharger',
refresh: 'Actualiser',
open: 'Ouvrir',
edit: 'Modifier',
preview: 'Apercu',
download: 'Telecharger',
copyPath: 'Copier le chemin',
rename: 'Renommer',
delete: 'Supprimer',
name: 'Nom',
size: 'Taille',
modified: 'Modifie',
actions: 'Actions',
emptyDir: 'Dossier vide',
loading: 'Chargement...',
confirmDelete: 'Voulez-vous vraiment supprimer "{name}" ?',
confirmDeleteDir: 'Voulez-vous vraiment supprimer le dossier "{name}" et tout son contenu ?',
deleteFailed: 'Echec de la suppression',
deleted: 'Supprime',
renameTo: 'Renommer en',
newFileName: 'Nom du fichier',
newFolderName: 'Nom du dossier',
created: 'Cree',
createFailed: 'Echec de la creation',
renamed: 'Renomme',
renameFailed: 'Echec du renommage',
uploadSuccess: '{count} fichier(s) televerse(s)',
uploadFailed: 'Echec du televersement',
saveFailed: 'Echec de l\'enregistrement',
saved: 'Enregistre',
unsavedChanges: 'Vous avez des modifications non enregistrees. Annuler ?',
pathCopied: 'Chemin copie',
fileTooLarge: 'Fichier trop volumineux (max 10 Mo)',
permissionDenied: 'Impossible de modifier un fichier protege',
notFound: 'Fichier ou dossier introuvable',
backendError: 'Echec de l\'operation sur le fichier',
dragDropHint: 'Glissez des fichiers ici pour les televerser',
closeEditor: 'Fermer l\'editeur',
closePreview: 'Fermer',
saveFile: 'Enregistrer',
},
// Chat de groupe
groupChat: {
title: 'Chat de groupe',
createRoom: 'Creer un salon',
joinByCode: 'Rejoindre avec un code',
roomName: 'Nom du salon',
roomNamePlaceholder: 'Entrez le nom du salon',
inviteCode: "Code d'invitation",
autoGenerate: 'Generer automatiquement',
noRooms: 'Aucun salon pour le moment',
selectOrCreate: 'Selectionnez ou creez un salon pour commencer a discuter',
agents: 'Agents',
addAgent: 'Ajouter un agent',
selectProfile: 'Selectionnez un profil',
agentAdded: 'Agent ajoute',
agentAlreadyInRoom: "L'agent est deja dans ce salon",
noAgents: 'Aucun agent dans ce salon',
members: 'Membres',
roomCreated: 'Salon cree',
roomDeleted: 'Salon supprime',
deleteRoomConfirm: 'Supprimer ce salon ?',
you: 'Vous',
joined: 'Vous avez rejoint le salon',
joinFailed: 'Echec de la connexion au salon',
inputPlaceholder: 'Tapez un message... (Entree pour envoyer)',
enterCode: "Entrez le code d'invitation",
yourName: 'Votre nom',
yourNamePlaceholder: "Entrez votre nom d'affichage",
yourDescription: 'Description (facultatif)',
yourDescriptionPlaceholder: 'Decrivez-vous aux autres...',
agentName: 'Nom de l\'agent',
agentNamePlaceholder: 'Nom personnalise (vide = nom du profil)',
agentDesc: 'Description de l\'agent',
agentDescPlaceholder: 'Decrivez le role de cet agent...',
agentReplying: 'est en train de répondre...',
agentCompressing: 'compresse le contexte...',
compressionSettings: 'Paramètres de compression',
triggerTokens: 'Seuil de tokens',
triggerTokensDesc: 'Seuil de tokens pour déclencher la compression',
maxHistoryTokens: 'Max tokens historique',
maxHistoryTokensDesc: 'Maximum de tokens pour le contexte compressé',
tailMessageCount: 'Messages récents',
tailMessageCountDesc: 'Nombre de messages récents à conserver',
compressionConfig: 'Config. compression',
compressNow: 'Comprimer maintenant',
compressingInProgress: 'Compression en cours',
compressionSaved: 'Configuration enregistrée',
},
// Telechargement
download: {
downloading: 'Telechargement...',
downloadFailed: 'Echec du telechargement',
fileNotFound: 'Fichier introuvable ou supprime',
fileTooLarge: 'Fichier trop volumineux (limite depassee)',
backendError: 'Echec de la lecture du fichier, l\'environnement distant est peut-etre indisponible',
backendTimeout: 'Delai de lecture du fichier depasse',
unsupportedBackend: 'Le backend de terminal actuel ne prend pas en charge le telechargement de fichiers',
invalidPath: 'Chemin de fichier invalide',
download: 'Telecharger',
downloadFile: 'Telecharger le fichier',
},
}