Files
Hermes-ui/packages/client/src/i18n/locales/es.ts
T
ekko 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

export default {
// Login
login: {
title: 'Hermes Web UI',
description: 'Introduce tu token de acceso para continuar. Encuentralo en los registros de inicio del servidor.',
placeholder: 'Token de acceso',
submit: 'Iniciar sesion',
tokenRequired: 'Por favor, introduce tu token de acceso',
invalidToken: 'Token invalido',
connectionFailed: 'No se puede conectar al servidor',
passwordLogin: 'Contrasena',
tokenLogin: 'Token',
usernamePlaceholder: 'Nombre de usuario',
passwordPlaceholder: 'Contrasena',
credentialsRequired: 'Por favor, introduzca nombre de usuario y contrasena',
invalidCredentials: 'Nombre de usuario o contrasena incorrectos',
passwordMismatch: 'Las contrasenas no coinciden',
passwordTooShort: 'La contrasena debe tener al menos 6 caracteres',
setupSuccess: 'Login con contrasena configurado correctamente',
passwordChanged: 'Contrasena cambiada correctamente',
passwordRemoved: 'Login con contrasena eliminado',
setupPassword: 'Configurar login con contrasena',
changePassword: 'Cambiar contrasena',
changeUsername: 'Cambiar nombre de usuario',
removePasswordLogin: 'Eliminar',
username: 'Nombre de usuario',
currentPassword: 'Contrasena actual',
newPassword: 'Nueva contrasena',
confirmPassword: 'Confirmar contrasena',
newUsername: 'Nuevo nombre de usuario',
usernameChanged: 'Nombre de usuario cambiado correctamente',
usernameTooShort: 'El nombre de usuario debe tener al menos 2 caracteres',
setupDescription: 'Configure un nombre de usuario y contrasena para un inicio de sesion rapido. El token de acceso seguira funcionando.',
removeConfirm: 'Esta seguro de eliminar el login con contrasena? Necesitara usar el token de acceso.',
passwordLoginNotConfigured: 'Login con contrasena no configurado',
passwordLoginConfigured: 'Login con contrasena habilitado ({username})',
},
// Common
common: {
loading: 'Cargando...',
cancel: 'Cancelar',
retry: 'Reintentar',
delete: 'Eliminar',
edit: 'Editar',
save: 'Guardar',
saved: 'Guardado',
update: 'Actualizar',
create: 'Crear',
saveFailed: 'Error al guardar',
deleteFailed: 'Error al eliminar',
ok: 'OK',
copied: 'Copiado',
copy: 'Copiar',
noData: 'Sin datos',
fetch: 'Obtener',
add: 'Anadir',
enable: 'Activar',
disable: 'Desactivar',
configured: 'Configurado',
notConfigured: 'No configurado',
confirm: 'Confirmar',
expand: 'Expandir',
collapse: 'Contraer',
},
// Sidebar
sidebar: {
chat: 'Chat',
search: 'Buscar',
history: 'Historial',
jobs: 'Tareas programadas',
models: 'Modelos',
profiles: 'Perfiles',
skills: 'Habilidades',
memory: 'Memoria',
logs: 'Registros',
usage: 'Uso',
channels: 'Canales',
terminal: 'Terminal',
files: 'Archivos',
groupChat: 'Chat grupal',
groupConversation: 'Conversación',
settings: 'Configuracion',
connected: 'Conectado',
disconnected: 'Desconectado',
updateTip: 'Ejecuta "hermes-web-ui update" en la terminal para actualizar',
updateVersion: 'Actualizar a v{version}',
updating: 'Actualizando...',
updateSuccess: 'Actualizacion completa, por favor reinicia el servidor',
updateFailed: 'Error al actualizar',
logout: 'Cerrar sesion',
nodeVersionWarning: 'Se detecto Node.js v{version}. Actualiza a la version 23 o posterior.',
changelog: 'Registro de cambios',
noChangelog: 'No hay registro de cambios',
},
// Drawer
drawer: {
terminal: 'Terminal',
files: 'Espacio de trabajo',
},
// Chat
chat: {
contextRemaining: 'restante',
emptyState: 'Inicia una conversacion con Hermes Agent',
inputPlaceholder: 'Escribe un mensaje... (Enter para enviar, Shift+Enter para nueva linea)',
attachFiles: 'Adjuntar archivos',
stop: 'Detener',
send: 'Enviar',
contextUsed: 'Contexto utilizado:',
sessions: 'Sesiones',
webUiSessions: 'Sesiones de Web UI/API Server',
sessionScopeHint: 'Chat solo muestra sesiones de Web UI/API Server. Las sesiones de CLI, Telegram, Discord, Cron y otros canales son de solo lectura en Historial.',
openHistory: 'Abrir historial',
hermesHistory: 'Historial de Hermes',
historyScopeHint: 'Sesiones del historial de Hermes, de solo lectura y agrupadas por origen.',
noSessions: 'Sin sesiones',
newChat: 'Nuevo chat',
deleteSession: 'Eliminar esta sesion?',
sessionDeleted: 'Sesion eliminada',
rename: 'Renombrar',
pin: 'Fijar',
unpin: 'Desfijar',
pinned: 'Fijados',
chatMode: 'Chat',
liveMode: 'En vivo',
liveSessions: 'Sesiones en vivo',
recentBadge: 'Reciente',
linkedSessions: '{count} vinculadas',
noVisibleMessages: 'No hay mensajes visibles para humanos.',
monitorRoleUser: 'Usuario',
monitorRoleAssistant: 'Asistente',
copySessionId: 'Copiar ID de sesión',
renamed: 'Renombrada',
renameFailed: 'Error al renombrar',
renameSession: 'Renombrar sesion',
sessionNotFound: 'Sesion no encontrada',
enterNewTitle: 'Introduce un nuevo titulo',
other: 'Otro',
runFailed: 'Error en la ejecucion',
error: 'Error',
tool: 'Herramienta',
arguments: 'Argumentos',
result: 'Resultado',
truncated: '... (truncado)',
executionDuration: 'Execution time', thinkingLabel: 'Pensamiento',
thinkingInProgress: 'Pensando…',
thinkingShow: 'Mostrar pensamiento',
thinkingHide: 'Ocultar pensamiento',
thinkingDuration: 'Observado {duration}',
thinkingChars: '{count} caracteres',
copyBubble: 'Copiar mensaje',
copiedBubble: 'Mensaje copiado',
copyFailed: 'Error al copiar',
playSpeech: 'Reproducir voz',
pauseSpeech: 'Pausa',
resumeSpeech: 'Reanudar',
stopSpeech: 'Detener',
speechNotSupported: 'Reproducción de voz no soportada en este navegador',
},
// Jobs
jobs: {
title: 'Tareas programadas',
createJob: 'Crear tarea',
editJob: 'Editar tarea',
noJobs: 'No hay tareas programadas aun. Crea una para comenzar.',
name: 'Nombre',
namePlaceholder: 'Nombre de la tarea',
schedule: 'Programacion (expresion Cron)',
schedulePlaceholder: 'ej. 0 9 * * *',
quickPresets: 'Presets rapidos',
selectPreset: 'Seleccionar un preset...',
presetEveryMinute: 'Cada minuto',
presetEvery5Min: 'Cada 5 minutos',
presetEveryHour: 'Cada hora',
presetEveryDay: 'Todos los dias a las 00:00',
presetEveryDay9: 'Todos los dias a las 09:00',
presetEveryMonday: 'Cada lunes a las 09:00',
presetEveryMonth: 'El dia 1 de cada mes a las 09:00',
prompt: 'Prompt',
promptPlaceholder: 'El prompt a ejecutar',
deliverTarget: 'Destino de entrega',
origin: 'Origen',
local: 'Local',
repeatCount: 'Repeticiones (opcional)',
modelPlaceholder: 'Modelo por defecto',
repeatPlaceholder: 'Dejar vacio para infinito',
jobCreated: 'Tarea creada',
jobUpdated: 'Tarea actualizada',
nameRequired: 'El nombre es obligatorio',
scheduleRequired: 'La programacion es obligatoria',
loadFailed: 'Error al cargar la tarea',
jobPaused: 'Tarea en pausa',
jobResumed: 'Tarea reanudada',
jobTriggered: 'Job ejecutado',
modelUpdated: 'Modelo actualizado',
jobDeleted: 'Tarea eliminada',
status: {
running: 'En ejecucion',
paused: 'En pausa',
disabled: 'Desactivada',
scheduled: 'Programada',
},
info: {
model: 'Modelo',
schedule: 'Programacion',
lastRun: 'Ultima ejecucion',
nextRun: 'Proxima ejecucion',
deliver: 'Entrega',
repeat: 'Repeticion',
},
action: {
pause: 'Pausar',
pauseJob: 'Pausar tarea',
resume: 'Reanudar',
resumeJob: 'Reanudar tarea',
runNow: 'Ejecutar ahora',
triggerImmediately: 'Ejecutar inmediatamente',
},
runHistory: {
title: 'Historial',
runs: 'ejecuciones',
noRuns: 'No se encontró historial.',
},
},
// Skills
skills: {
title: 'Habilidades',
searchPlaceholder: 'Buscar habilidades...',
noMatch: 'Ninguna habilidad coincide con tu busqueda',
noSkills: 'No se encontraron habilidades',
backTo: 'Volver a',
attachedFiles: 'Archivos adjuntos',
loadFailed: 'Error al cargar la habilidad',
fileLoadFailed: 'Error al cargar el archivo',
modified: 'Modificado por el usuario',
archived: 'Archivado',
pinned: 'Fijado',
pin: 'Fijar habilidad',
unpin: 'Desfijar habilidad',
pinFailed: 'Error al cambiar estado de fijacion',
toggleFailed: 'Error al activar/desactivar la habilidad',
source: {
builtin: 'Integrado',
hub: 'Hub',
local: 'Local',
},
},
// Memory
memory: {
title: 'Memoria',
refresh: 'Actualizar',
loadFailed: 'Error al cargar la memoria',
myNotes: 'Mis notas',
noNotes: 'Sin notas aun.',
notesPlaceholder: 'Escribe tus notas...',
userProfile: 'Perfil de usuario',
noProfile: 'Sin perfil aun.',
profilePlaceholder: 'Escribe tu perfil...',
soul: 'Alma',
noSoul: 'Sin configuracion de alma aun.',
soulPlaceholder: 'Escribe la configuracion del alma...',
},
// Models
models: {
title: 'Modelos',
addProvider: 'Anadir proveedor',
providerType: 'Tipo de proveedor',
preset: 'Preset',
custom: 'Personalizado',
selectProvider: 'Seleccionar proveedor',
chooseProvider: 'Elige un proveedor...',
name: 'Nombre',
autoGeneratedName: 'Generado automaticamente desde la URL base',
baseUrl: 'URL base',
region: 'Región',
regionIntl: 'Internacional',
regionCn: 'China continental',
baseUrlPlaceholder: 'ej. https://api.example.com/v1',
apiKey: 'Clave API',
apiKeyPlaceholder: 'sk-...',
defaultModel: 'Modelo predeterminado',
selectOrInput: 'Seleccionar o ingresar un modelo...',
selectModel: 'Seleccionar un modelo...',
providerAdded: 'Proveedor anadido',
providerDeleted: 'Proveedor eliminado',
deleteProvider: 'Eliminar proveedor',
deleteConfirm: 'Estas seguro de que quieres eliminar "{name}"?',
codexLoginTitle: 'Inicio de sesión de OpenAI Codex',
codexWaiting: 'Ingrese este código en la página de autorización para iniciar sesión:',
codexCopyCode: 'Código copiado',
codexOpenLink: 'Abrir página de autorización',
codexApproved: 'Inicio de sesión exitoso',
codexExpired: 'La autorización ha expirado. Por favor, inténtelo de nuevo.',
nousLoginTitle: 'Inicio de sesión de Nous Portal',
nousWaiting: 'Ingrese este código en la página de autorización:',
nousCopyCode: 'Código copiado',
nousOpenLink: 'Abrir página de autorización',
nousApproved: 'Inicio de sesión exitoso',
nousDenied: 'Autorización denegada',
nousExpired: 'Autorización expirada',
copilotLoginTitle: 'Inicio de sesión de GitHub Copilot',
copilotWaiting: 'Abra GitHub e introduzca el código de dispositivo a continuación para autorizar. La ventana se cerrará automáticamente tras la aprobación.',
copilotCopyCode: 'Código copiado',
copilotOpenLink: 'Abrir la página de autorización de GitHub',
copilotApproved: '¡Inicio de sesión exitoso!',
copilotDenied: 'Autorización denegada.',
copilotExpired: 'El enlace de autorización ha caducado. Vuelva a intentarlo.',
copilotAddDetectedTitle: 'GitHub Copilot detectado',
copilotAddDetected: 'Se detectó un token OAuth de GitHub Copilot en este equipo. Haz clic en Agregar para habilitar Copilot en Hermes.',
copilotAddSourceEnv: 'Origen: ~/.hermes/.env (COPILOT_GITHUB_TOKEN)',
copilotAddSourceGhCli: 'Origen: gh CLI (gh auth token)',
copilotAddSourceAppsJson: 'Origen: extensión Copilot de VS Code (apps.json)',
copilotDeleteHintEnv: 'Esto borrará COPILOT_GITHUB_TOKEN en ~/.hermes/.env. Otras herramientas no se verán afectadas.',
copilotDeleteHintGhCli: 'Copilot se ocultará de Hermes. Tu sesión de gh CLI no se verá afectada — `gh auth status` seguirá mostrando que estás conectado.',
copilotDeleteHintAppsJson: 'Copilot se ocultará de Hermes. La extensión Copilot de VS Code seguirá conectada.',
customBadge: 'PERSONALIZADO',
previewBadge: 'VISTA PREVIA',
disabledBadge: 'NO DISPONIBLE',
disabledTooltip: "Este modelo no está disponible para tu cuenta.",
customModelPlaceholder: 'Nombre del modelo personalizado',
customModelHint: 'Enter para cargar',
noProviders: 'No se encontraron proveedores. Anade un proveedor personalizado para comenzar.',
builtIn: 'Integrado',
customType: 'Personalizado',
provider: 'Proveedor',
contextLength: 'Longitud del contexto',
contextLengthPlaceholder: 'ej. 200000 (opcional)',
local: 'Local ({host})',
selectProviderRequired: 'Por favor, selecciona un proveedor',
baseUrlRequired: 'La URL base es obligatoria',
apiKeyRequired: 'La clave API es obligatoria',
modelRequired: 'El modelo predeterminado es obligatorio',
enterBaseUrl: 'Por favor, introduce primero la URL base',
unexpectedFormat: 'Formato de respuesta inesperado',
foundModels: '{count} modelos encontrados',
fetchFailed: 'Error al obtener los modelos',
},
// Profiles
profiles: {
title: 'Perfiles',
create: 'Crear perfil',
import: 'Importar',
export: 'Exportar',
rename: 'Renombrar',
delete: 'Eliminar',
switchTo: 'Cambiar a',
switchConfirm: 'Cambiar al perfil "{name}" reiniciara la pasarela. Continuar?',
switchSuccess: 'Se ha cambiado al perfil "{name}"',
switchFailed: 'Error al cambiar de perfil. Es posible que la pasarela necesite un reinicio manual.',
createSuccess: 'Perfil "{name}" creado',
createFailed: 'Error al crear el perfil',
renameSuccess: 'Perfil renombrado',
renameFailed: 'Error al renombrar el perfil',
deleteConfirm: 'Estas seguro de que quieres eliminar el perfil "{name}"?',
deleteSuccess: 'Perfil eliminado',
deleteFailed: 'Error al eliminar el perfil',
exportSuccess: 'Perfil exportado',
exportFailed: 'Error al exportar el perfil',
importSuccess: 'Perfil importado',
importFailed: 'Error al importar el perfil',
importSelectFile: 'Seleccionar archivo de archivo',
importInvalidFile: 'Por favor, selecciona un archivo valido (.tar.gz, .tgz, .gz, .zip)',
name: 'Nombre del perfil',
namePlaceholder: 'Solo letras, numeros y guiones',
nameValidation: 'El nombre del perfil solo puede contener letras minúsculas, números, guiones bajos y guiones',
newName: 'Nuevo nombre',
newNamePlaceholder: 'Introduce un nuevo nombre',
cloneFromCurrent: 'Clonar desde el perfil actual',
cloneCleanupNotice: 'Al clonar se omiten automáticamente las credenciales exclusivas de plataforma (Weixin / Telegram / Slack, etc.) para evitar conflictos con el perfil de origen',
cloneStrippedCredentials: 'Se eliminaron {count} credenciales exclusivas: {list}',
cloneDisabledPlatforms: 'Se deshabilitaron {count} plataforma(s): {list}',
cloneStrippedConfigCredentials: 'Se eliminaron {count} credencial(es) integradas de config.yaml: {list}',
archivePath: 'Ruta del archivo',
archivePathPlaceholder: 'Ruta del servidor al archivo de archivo',
importName: 'Nombre del perfil (opcional)',
importNamePlaceholder: 'Dejar vacio para usar el nombre del archivo',
active: 'Activo',
model: 'Modelo',
gateway: 'Pasarela',
alias: 'Alias',
provider: 'Proveedor',
path: 'Ruta',
skills: 'Habilidades',
hasEnv: 'Tiene .env',
hasSoulMd: 'Tiene soul.md',
noProfiles: 'No se encontraron perfiles. Crea uno para comenzar.',
},
// Logs
logs: {
title: 'Registros',
all: 'Todos',
searchPlaceholder: 'Buscar...',
refresh: 'Actualizar',
noEntries: 'Sin entradas de registro',
},
// Settings
settings: {
title: 'Configuracion',
saved: 'Guardado',
saveFailed: 'Error al guardar',
tabs: {
display: 'Pantalla',
account: 'Cuenta',
agent: 'Agente',
memory: 'Memoria',
session: 'Sesion',
privacy: 'Privacidad',
apiServer: 'Servidor API',
},
display: {
streaming: 'Respuestas en streaming',
streamingHint: 'Mostrar respuestas de la IA en tiempo real',
compact: 'Modo compacto',
compactHint: 'Reducir el espaciado entre mensajes',
showReasoning: 'Mostrar razonamiento',
showReasoningHint: 'Mostrar el proceso de pensamiento del modelo',
showCost: 'Mostrar costo',
showCostHint: 'Mostrar uso de tokens en las respuestas',
inlineDiffs: 'Diffs en linea',
inlineDiffsHint: 'Mostrar cambios de codigo en linea',
bellOnComplete: 'Sonido de finalizacion',
bellOnCompleteHint: 'Reproducir un sonido cuando la IA termina',
busyInputMode: 'Modo de entrada ocupada',
busyInputModeHint: 'Permitir entrada mientras la IA procesa',
theme: 'Tema',
themeHint: 'Elige claro, oscuro o seguir la preferencia del sistema',
themeLight: 'Claro',
themeDark: 'Oscuro',
themeSystem: 'Sistema',
},
agent: {
maxTurns: 'Turnos maximos',
maxTurnsHint: 'Rondas maximas de interaccion por conversacion',
gatewayTimeout: 'Tiempo de espera de la pasarela',
gatewayTimeoutHint: 'Tiempo de espera de la peticion en segundos',
restartDrainTimeout: 'Tiempo de drenado al reiniciar',
restartDrainTimeoutHint: 'Tiempo de drenado antes de reiniciar en segundos',
toolEnforcement: 'Aplicacion de herramientas',
toolEnforcementHint: 'Controlar el modo de ejecucion de llamadas a herramientas',
auto: 'Automatico',
always: 'Siempre',
never: 'Nunca',
},
memory: {
enabled: 'Activar memoria',
enabledHint: 'Permitir que la IA recuerde el contexto de la conversacion',
userProfile: 'Perfil de usuario',
userProfileHint: 'Permitir que la IA recuerde las preferencias del usuario',
charLimit: 'Limite de caracteres de memoria',
charLimitHint: 'Maximo de caracteres para MEMORY.md',
userCharLimit: 'Limite de caracteres del perfil de usuario',
userCharLimitHint: 'Maximo de caracteres para USER.md',
},
session: {
mode: 'Modo de reinicio',
modeHint: 'Condicion de activacion del reinicio de sesion',
modeBoth: 'Inactividad + Programado',
modeIdle: 'Solo inactividad',
modeHourly: 'Solo programado',
idleMinutes: 'Tiempo de inactividad',
idleMinutesHint: 'Tiempo de espera antes del reinicio automatico (minutos)',
atHour: 'Hora de reinicio programado',
humanOnly: 'Mostrar solo sesiones humanas',
humanOnlyHint: 'Oculta por defecto el ruido de subagentes y del monitor de sesiones',
liveMonitorHumanOnly: 'Monitor en vivo: mostrar solo sesiones humanas',
liveMonitorHumanOnlyHint: 'Oculta por defecto el ruido de subagentes y del monitor de sesiones en el monitor en vivo',
atHourHint: 'Reiniciar sesion a esta hora todos los dias',
},
privacy: {
redactPii: 'Ocultar informacion personal',
redactPiiHint: 'Detectar y ocultar automaticamente informacion sensible (contrasenas, claves, etc.)',
},
apiServer: {
enable: 'Activar',
enableHint: 'Activar servidor API',
host: 'Host',
hostHint: 'Direccion de escucha',
port: 'Puerto',
portHint: 'Puerto de escucha',
key: 'Clave',
keyHint: 'Clave de acceso API',
cors: 'Origenes CORS',
corsHint: 'Fuentes cross-origin permitidas',
},
},
// Platform channel settings
platform: {
requireMention: "Requerir mencion {'@'}",
requireMentionGroup: "Requerir mencion {'@'} en grupos para responder",
requireMentionChannel: "Requerir mencion {'@'} en canales para responder",
requireMentionRoom: "Requerir mencion {'@'} en salas para responder",
reactions: 'Reacciones',
reactionsHint: 'Reaccionar a mensajes con emoji',
freeResponseChats: 'Chats de respuesta libre',
freeResponseChatsHint: "IDs de chats que responden sin mencion {'@'} (separados por comas)",
freeResponseChannels: 'Canales de respuesta libre',
freeResponseChannelsHint: "IDs de canales que responden sin mencion {'@'} (separados por comas)",
freeResponseRooms: 'Salas de respuesta libre',
freeResponseRoomsHint: "IDs de salas que responden sin mencion {'@'} (separados por comas)",
mentionPatterns: 'Patrones de mencion personalizados',
mentionPatternsHint: 'Patrones de activacion adicionales',
autoThread: 'Hilo automatico',
autoThreadHint: "Crear automaticamente hilos de respuesta despues de mencion {'@'}",
autoThreadHintRoom: 'Crear automaticamente hilos de respuesta en salas',
dmMentionThreads: 'Hilos de mencion en MD',
dmMentionThreadsHint: 'Usar hilos de respuesta para menciones en mensajes directos',
allowBots: 'Permitir mensajes de bots',
allowBotsHint: 'Responder a mensajes de otros bots',
allowedChannels: 'Canales permitidos',
allowedChannelsHint: 'Lista blanca de IDs de canales (separados por comas)',
ignoredChannels: 'Canales ignorados',
ignoredChannelsHint: 'Canales donde el bot nunca responde (separados por comas)',
noThreadChannels: 'Canales sin hilo',
noThreadChannelsHint: 'Canales donde el bot responde sin hilos (separados por comas)',
exclusiveTokenWarning: 'Esta plataforma usa bloqueo exclusivo de token. Cada perfil debe usar un token de identidad distinto para evitar conflictos con otros perfiles.',
botToken: 'Token del bot',
botTokenHint: 'Token del bot del portal de desarrolladores',
accessToken: 'Token de acceso',
accessTokenHint: 'Token de acceso de Matrix',
homeserver: 'URL del homeserver',
homeserverHint: 'URL del homeserver de Matrix',
appId: 'ID de aplicacion',
appIdHint: 'ID de aplicacion de Feishu',
appSecret: 'Secreto de aplicacion',
appSecretHint: 'Secreto de aplicacion de Feishu',
clientId: 'ID de cliente',
clientIdHint: 'ID de cliente de DingTalk',
clientSecret: 'Secreto de cliente',
clientSecretHint: 'Secreto de cliente de DingTalk',
botId: 'ID del bot',
botIdHint: 'ID del bot de WeCom',
wecomSecretHint: 'Secreto del bot de WeCom',
waEnabled: 'Activar WhatsApp',
waEnabledHint: 'Activar WhatsApp mediante emparejamiento por codigo QR',
weixinToken: 'Token de Weixin',
weixinTokenHint: 'Desde el inicio de sesion QR de la CLI de weixin (hermes weixin)',
accountId: 'ID de cuenta',
accountIdHint: 'ID de cuenta de Weixin',
qrLogin: 'Inicio de sesion QR',
qrRelogin: 'Volver a iniciar sesion',
qrFetching: 'Obteniendo codigo QR...',
qrScanHint: 'Escanea con WeChat para iniciar sesion',
qrScanedHint: 'Escaneado, por favor confirma en el telefono...',
},
// Language
language: {
label: 'Idioma',
zh: '中文',
en: 'English',
es: 'Espanol',
},
// Terminal
terminal: {
sessions: 'Sesiones',
newTab: 'Nueva terminal',
closeSession: 'Cerrar esta sesion?',
sessionExited: 'Finalizada',
processExited: 'Proceso finalizado con codigo {code}',
},
// Usage
usage: {
title: 'Estadisticas de uso',
refresh: 'Actualizar',
totalTokens: 'Total de tokens',
inputTokens: 'Entrada',
outputTokens: 'Salida',
totalSessions: 'Total de sesiones',
avgPerDay: '~{n}/dia de promedio',
estimatedCost: 'Costo est.',
cacheHitRate: 'Tasa de acierto de cache',
modelBreakdown: 'Desglose por modelo',
dailyTrend: 'Uso diario (ultimos 30 dias)',
date: 'Fecha',
tokens: 'Tokens',
cache: 'Caché',
cacheRead: 'Cache Read',
cacheWrite: 'Cache Write',
sessions: 'Sesiones',
cost: 'Costo',
noData: 'Sin datos de uso',
},
// Registro de cambios
changelog: {
new_0_5_6_1: 'Reproducción de voz con Web Speech API: botón manual, interruptor auto-play, animación de borde arcoíris y optimización móvil',
new_0_5_6_2: 'Parser LLM JSON robusto con tolerancia a formato Python y extracción de texto de eventos streaming',
new_0_5_6_3: 'Mejoras de Skills: estadísticas de uso, filtrado de fuentes, skills archivados, procedencia y toggle de fijado',
new_0_5_6_4: 'Estadísticas diarias de uso expandidas con desglose detallado de tokens incluyendo separación de lectura/escritura de caché',
new_0_5_6_5: 'Ámbito del historial de sesiones aclarado con descripciones mejoradas en vistas de chat e historial',
new_0_5_6_6: 'Rediseñado el manejo de adjuntos usando formato de matriz ContentBlock estilo Anthropic (texto, imagen, archivo)',
new_0_5_6_7: 'Añadida funcionalidad de descarga de archivos en frontend soportando formatos ContentBlock y Markdown con autenticación',
new_0_5_6_8: 'Corregido conflicto de múltiples procesos que causaba reinicios de base de datos SQLite eliminando instancias nodemon redundantes',
new_0_5_9_1: 'Unificar la gestión de perfiles en toda la aplicación con API y gestión de estado consistentes',
new_0_5_9_2: 'Añadir plantillas de issues y pull requests de GitHub para un mejor flujo de contribución',
new_0_5_8_1: 'Añadir panel de cajón con soporte de barra lateral móvil y botón arcoíris personalizable',
new_0_5_8_2: 'Corregir problema de sincronización de estado de cambio de perfil con actualización inmediata de UI y verificación de backend',
new_0_5_8_3: 'Filtrar caracteres especiales y emoji en reproducción de voz para mejor síntesis de voz',
new_0_5_8_4: 'Añadir clave i18n faltante y unificar fuente de datos de sesión para priorizar base de datos',
new_0_5_8_5: 'Optimizar configuración de build Vite para builds Docker más rápidas con esbuild y división de chunks',
new_0_5_7_1: 'Optimizar compresión de contexto para soportar contenido rico (imágenes, archivos) con mejora en el manejo de mensajes de herramientas',
new_0_5_7_2: 'Mejorar sincronización de sesiones con inserciones por lotes y protección de transacciones para consistencia de datos',
new_0_5_7_3: 'Corregir recepción de eventos usage.updated para asegurar seguimiento preciso de tokens entre ejecuciones',
new_0_5_5_1: '🎉 ¡Feliz Día del Trabajo! Hoy no se trabaja, agradezcan su comprensión',
new_0_5_5_2: 'Añadida página de historial para sesiones Hermes',
new_0_5_5_3: 'La página de historial gestiona sesiones de forma independiente',
new_0_5_5_4: 'Carga automática de primera sesión CLI',
new_0_5_5_5: 'Componente HistoryMessageList con inyección de props',
new_0_5_5_6: 'Filtrado de mensajes vacíos y tools sin toolName',
new_0_5_5_7: 'Eliminado caché de sesiones localStorage, datos del backend',
new_0_5_5_8: 'Optimizado cambio de perfil, eliminadas llamadas de cachete obsoletas',
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: 'Visualizacion en streaming en tiempo real de bloques de pensamiento/razonamiento',
new_0_4_7_2: 'Omitir script de preparacion durante la construccion Docker',
new_0_4_7_3: 'Mejoras en la experiencia movil del chat grupal y pulido de UI',
new_0_4_7_4: 'Limitar los tokens restantes del contexto a 0 en lugar de negativos',
new_0_4_7_5: 'Agregar proveedor integrado Alibaba Coding Plan con anulacion de base_url en .env',
new_0_4_7_6: 'Omitir perfiles remotos al inicio para evitar bloqueos',
new_0_4_7_7: 'Detectar y mostrar errores de ejecucion silenciosamente tragados',
new_0_4_7_8: 'Consulta de longitud de contexto consciente del proveedor',
new_0_4_7_9: 'Restablecer config.model al cambiar y resolver proveedor personalizado CLI',
new_0_4_7_10: 'Limpiar base_url_env de .env al eliminar proveedor integrado',
new_0_4_7_11: 'Alinear el fondo de la barra lateral del chat grupal con la lista de sesiones',
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: 'Agregar seguimiento de uso de tokens y longitud de contexto dinamico',
new_0_4_2_2: 'Agregar modal de busqueda de sesiones',
new_0_4_2_3: 'Restaurar sistema de chat grupal con Socket.IO y SQLite',
new_0_4_2_4: 'Agregar sesiones fijas y monitor en vivo en la pagina de chat',
new_0_4_2_5: 'Corregir deteccion de proveedores integrados y coincidencia de modelos',
},
// Archivos
files: {
title: 'Archivos',
tree: 'Arbol de directorios',
list: 'Lista de archivos',
breadcrumbRoot: 'Inicio',
newFile: 'Nuevo archivo',
newFolder: 'Nueva carpeta',
upload: 'Subir',
refresh: 'Actualizar',
open: 'Abrir',
edit: 'Editar',
preview: 'Vista previa',
download: 'Descargar',
copyPath: 'Copiar ruta',
rename: 'Renombrar',
delete: 'Eliminar',
name: 'Nombre',
size: 'Tamano',
modified: 'Modificado',
actions: 'Acciones',
emptyDir: 'Directorio vacio',
loading: 'Cargando...',
confirmDelete: '?Seguro que quiere eliminar "{name}"?',
confirmDeleteDir: '?Seguro que quiere eliminar el directorio "{name}" y todo su contenido?',
deleteFailed: 'Error al eliminar',
deleted: 'Eliminado',
renameTo: 'Renombrar a',
newFileName: 'Nombre del archivo',
newFolderName: 'Nombre de la carpeta',
created: 'Creado',
createFailed: 'Error al crear',
renamed: 'Renombrado',
renameFailed: 'Error al renombrar',
uploadSuccess: '{count} archivo(s) subido(s)',
uploadFailed: 'Error al subir',
saveFailed: 'Error al guardar',
saved: 'Guardado',
unsavedChanges: 'Tiene cambios sin guardar. ?Descartar?',
pathCopied: 'Ruta copiada',
fileTooLarge: 'Archivo demasiado grande (max 10MB)',
permissionDenied: 'No se puede modificar un archivo protegido',
notFound: 'Archivo o directorio no encontrado',
backendError: 'Error en la operacion de archivo',
dragDropHint: 'Arrastra archivos aqui para subir',
closeEditor: 'Cerrar editor',
closePreview: 'Cerrar',
saveFile: 'Guardar',
},
// Chat grupal
groupChat: {
title: 'Chat grupal',
createRoom: 'Crear sala',
joinByCode: 'Unirse con codigo',
roomName: 'Nombre de la sala',
roomNamePlaceholder: 'Ingrese el nombre de la sala',
inviteCode: 'Codigo de invitacion',
autoGenerate: 'Generar automaticamente',
noRooms: 'Aun no hay salas',
selectOrCreate: 'Seleccione o cree una sala para comenzar a chatear',
agents: 'Agentes',
addAgent: 'Agregar agente',
selectProfile: 'Seleccione un perfil',
agentAdded: 'Agente agregado',
agentAlreadyInRoom: 'El agente ya esta en esta sala',
noAgents: 'No hay agentes en esta sala',
members: 'Miembros',
roomCreated: 'Sala creada',
roomDeleted: 'Sala eliminada',
deleteRoomConfirm: '¿Eliminar esta sala?',
you: 'Tú',
joined: 'Se unio a la sala',
joinFailed: 'Error al unirse a la sala',
inputPlaceholder: 'Escriba un mensaje... (Enter para enviar)',
enterCode: 'Ingrese el codigo de invitacion',
yourName: 'Tu nombre',
yourNamePlaceholder: 'Ingresa tu nombre para mostrar',
yourDescription: 'Descripcion (opcional)',
yourDescriptionPlaceholder: 'Cuentales a los demas quien eres...',
agentName: 'Nombre del agente',
agentNamePlaceholder: 'Nombre personalizado (vacío = nombre del perfil)',
agentDesc: 'Descripción del agente',
agentDescPlaceholder: 'Describe lo que hace este agente...',
agentReplying: 'está respondiendo...',
agentCompressing: 'está comprimiendo contexto...',
compressionSettings: 'Configuración de compresión',
triggerTokens: 'Tokens de activación',
triggerTokensDesc: 'Umbral de tokens para activar la compresión',
maxHistoryTokens: 'Tokens máximos de historial',
maxHistoryTokensDesc: 'Máximo de tokens para el contexto comprimido',
tailMessageCount: 'Mensajes recientes',
tailMessageCountDesc: 'Número de mensajes recientes a conservar sin comprimir',
compressionConfig: 'Config. de compresión',
compressNow: 'Comprimir ahora',
compressingInProgress: 'Compresión en progreso',
compressionSaved: 'Configuración guardada',
},
// Descarga
download: {
downloading: 'Descargando...',
downloadFailed: 'Error en la descarga',
fileNotFound: 'Archivo no encontrado o eliminado',
fileTooLarge: 'Archivo demasiado grande (excede el limite)',
backendError: 'Error al leer el archivo, el entorno remoto puede no estar disponible',
backendTimeout: 'Tiempo de lectura del archivo agotado',
unsupportedBackend: 'El backend del terminal actual no admite la descarga de archivos',
invalidPath: 'Ruta de archivo invalida',
download: 'Descargar',
downloadFile: 'Descargar archivo',
},
}