From 267067410723df511d51bc09bfc890c79fb38a58 Mon Sep 17 00:00:00 2001 From: Alberto Punter Date: Thu, 23 Jul 2026 16:07:08 +0200 Subject: [PATCH] fix(i18n): re-sync and complete es-ES translations with latest release/v3.8.49 (#8289) --- src/i18n/messages/es.json | 8394 +++++++++++++++++++------------------ 1 file changed, 4207 insertions(+), 4187 deletions(-) diff --git a/src/i18n/messages/es.json b/src/i18n/messages/es.json index bb2d5c391e..06e1f09a06 100644 --- a/src/i18n/messages/es.json +++ b/src/i18n/messages/es.json @@ -4,19 +4,19 @@ "cancel": "Cancelar", "delete": "Eliminar", "loading": "Cargando...", - "selectOption": "Seleccionar una opción", + "selectOption": "Select an option", "error": "Se produjo un error", "success": "Éxito", "confirm": "¿Estás seguro?", "refresh": "Actualizar", "close": "Cerrar", - "previousPage": "Página anterior", - "nextPage": "Página siguiente", - "capsLockOn": "Bloq Mayús está activado", - "dismissNotification": "Descartar notificación", - "toggleColumns": "Alternar columnas", - "confirmTitle": "Confirmar", - "confirmAction": "Confirmar", + "previousPage": "Previous page", + "nextPage": "Next page", + "capsLockOn": "Caps Lock is on", + "dismissNotification": "Dismiss notification", + "toggleColumns": "Toggle columns", + "confirmTitle": "Confirm", + "confirmAction": "Confirm", "add": "Añadir", "edit": "Editar", "search": "Buscar", @@ -33,7 +33,7 @@ "noData": "No hay datos disponibles", "nothingHere": "Nothing here yet", "configure": "Configurar", - "manualConfig": "Configuración manual", + "manualConfig": "Manual config", "manage": "Administrar", "name": "Nombre", "actions": "Acciones", @@ -42,7 +42,7 @@ "model": "Modelo", "models": "modelos", "provider": "Proveedor", - "unknownProvider": "Proveedor desconocido", + "unknownProvider": "Unknown provider", "account": "Cuenta", "time": "Hora", "details": "Detalles", @@ -153,17 +153,17 @@ "goToDashboard": "Go to Dashboard", "checkSystemStatus": "Check System Status", "selectModel": "Select Model", - "addModel": "Añadir modelo", - "effortNone": "Ninguno", - "effortLow": "Bajo", - "effortMedium": "Medio", - "effortHigh": "Alto", - "effortExtraHigh": "Extra alto", - "effortMax": "Máx", + "addModel": "Add model", + "effortNone": "None", + "effortLow": "Low", + "effortMedium": "Medium", + "effortHigh": "High", + "effortExtraHigh": "Extra high", + "effortMax": "Max", "effortUltra": "Ultra", - "reasoningEffort": "Esfuerzo de razonamiento", + "reasoningEffort": "Reasoning effort", "wireApi": "Wire API", - "modelAliases": "Alias de modelos", + "modelAliases": "Model aliases", "combos": "Combos", "noModelsFound": "No models found", "clear": "Clear", @@ -414,7 +414,7 @@ "cloudBenefitAccess": "Cloud Benefit Access", "maxRetries": "Max Retries", "queueTimeout": "Queue Timeout", - "queueDepth": "Profundidad de la cola", + "queueDepth": "Queue Depth", "addProvider": "Add Provider", "realtime": "Realtime", "totalTranslations": "Total Translations", @@ -704,42 +704,42 @@ "tokensRedeemCode": "Canjear código", "tokensRedeemCodePlaceholder": "Introduce el código de invitación", "tokensYourActiveInvites": "Tus invitaciones activas", - "tokensTransferSuccess": "Transferencia exitosa ({idempotencyKey})", - "tokensTransferFailed": "Transferencia fallida", - "tokensCreateInviteFailed": "Error al crear la invitación", - "tokensRevokeInviteFailed": "Error al revocar la invitación", - "tokensRedeemSuccess": "Invitación canjeada. Servidor: {server}", - "tokensRedeemFailed": "Error al canjear la invitación", - "tokensConnectServerFailed": "Error al conectar el servidor", - "tokensDisconnectServerFailed": "Error al desconectar el servidor", - "tokensAmount": "Cantidad", - "tokensSending": "Enviando...", - "tokensFrom": "De", - "tokensTo": "Para", - "tokensReason": "Motivo", - "tokensDate": "Fecha", - "tokensSent": "Enviado", - "tokensReceived": "Recibido", - "tokensCreatingInvite": "Creando...", - "tokensCreateInvite": "Crear invitación", - "tokensInviteCreated": "Código de invitación creado", - "tokensRedeeming": "Canjeando...", - "tokensRedeem": "Canjear", - "tokensInviteUses": "{used}/{max} usos", - "tokensRevoked": "REVOCADO", - "tokensRevoke": "Revocar", - "tokensConnecting": "Conectando...", - "tokensConnectServer": "Conectar servidor", - "tokensNoServersConnected": "No hay servidores conectados. Conéctate a un servidor de la comunidad para compartir tablas de clasificación.", + "tokensTransferSuccess": "Transfer successful ({idempotencyKey})", + "tokensTransferFailed": "Transfer failed", + "tokensCreateInviteFailed": "Failed to create invite", + "tokensRevokeInviteFailed": "Failed to revoke invite", + "tokensRedeemSuccess": "Invite redeemed. Server: {server}", + "tokensRedeemFailed": "Failed to redeem invite", + "tokensConnectServerFailed": "Failed to connect server", + "tokensDisconnectServerFailed": "Failed to disconnect server", + "tokensAmount": "Amount", + "tokensSending": "Sending...", + "tokensFrom": "From", + "tokensTo": "To", + "tokensReason": "Reason", + "tokensDate": "Date", + "tokensSent": "Sent", + "tokensReceived": "Received", + "tokensCreatingInvite": "Creating...", + "tokensCreateInvite": "Create Invite", + "tokensInviteCreated": "Invite code created", + "tokensRedeeming": "Redeeming...", + "tokensRedeem": "Redeem", + "tokensInviteUses": "{used}/{max} uses", + "tokensRevoked": "REVOKED", + "tokensRevoke": "Revoke", + "tokensConnecting": "Connecting...", + "tokensConnectServer": "Connect Server", + "tokensNoServersConnected": "No servers connected. Connect to a community server to share leaderboards.", "tokensServerStatus": { - "connected": "Conectado", - "disconnected": "Desconectado", - "pending": "Pendiente", - "syncing": "Sincronizando", + "connected": "Connected", + "disconnected": "Disconnected", + "pending": "Pending", + "syncing": "Syncing", "error": "Error" }, - "tokensLastSync": "Última sincronización: {date}", - "tokensDisconnect": "Desconectar", + "tokensLastSync": "Last sync: {date}", + "tokensDisconnect": "Disconnect", "tierCoverageTitle": "Cobertura de nivel", "tierCoverageSubtitle": "Proveedores configurados por nivel alternativo", "batchDetailCopyId": "Copiar identificación", @@ -763,26 +763,26 @@ "batchFileDetailCopyId": "Copiar identificación", "batchFileDetailClose": "Cerrar", "batchFileDetailFailedToLoad": "No se pudo cargar el contenido del archivo", - "batchFileDetailLoadError": "Error al cargar el contenido del archivo", + "batchFileDetailLoadError": "Error loading file contents", "batchFilesListSearchPlaceholder": "Buscar por ID o nombre de archivo...", "batchFilesListFilesTable": "Archivos", - "batchFilesCount": "{count, plural, one {# archivo} other {# archivos}}", - "batchFilesAllPurposes": "Todos los propósitos", - "batchFilesFilename": "Nombre de archivo", - "batchFilesPurpose": "Propósito", - "batchFilesExpires": "Caduca", - "batchFilesNoneFound": "No se encontraron archivos", - "batchFilesNeverExpires": "Nunca", - "batchFileInUseByActiveBatch": "Archivo en uso por un lote activo", + "batchFilesCount": "{count, plural, one {# file} other {# files}}", + "batchFilesAllPurposes": "All purposes", + "batchFilesFilename": "Filename", + "batchFilesPurpose": "Purpose", + "batchFilesExpires": "Expires", + "batchFilesNoneFound": "No files found", + "batchFilesNeverExpires": "Never", + "batchFileInUseByActiveBatch": "File in use by an active batch", "batchFilePurpose": { - "batch": "Entrada de lote", - "batch-output": "Salida de lote", - "fine-tune": "Ajuste fino", - "assistants": "Asistentes" + "batch": "Batch input", + "batch-output": "Batch output", + "fine-tune": "Fine-tuning", + "assistants": "Assistants" }, "batchPageLoadingMore": "Cargando más…", "recommended": "Recomendado", - "understand": "Entiendo", + "understand": "I understand", "batchConceptTitle": "Batch processing", "batchConceptSubtitle": "Process thousands of requests asynchronously at ~50% of the cost (24h window). Ideal for evaluations, classification, and embeddings.", "batchConceptHowItWorks": "How it works", @@ -814,22 +814,22 @@ "wizardDropOrPick": "Drop a file or click to pick", "wizardCsvMappingTitle": "Map CSV columns → request fields", "wizardCsvMappingAddField": "Add field", - "wizardCsvNoColumns": "No se detectaron columnas en el encabezado CSV.", - "wizardCsvIgnoreColumn": "— ignorar —", - "wizardCsvCustomIdMapped": "custom_id mapeado", - "wizardCsvContentMapped": "Campo de contenido mapeado (messages, input o prompt)", - "wizardCsvApplyMapping": "Aplicar mapeo", - "wizardCsvRowsParsed": "{count} filas analizadas", - "wizardCsvRowsSkipped": "{count} filas omitidas", - "wizardCsvRowError": "Fila {row}: {reason}", + "wizardCsvNoColumns": "No columns detected in CSV header.", + "wizardCsvIgnoreColumn": "— ignore —", + "wizardCsvCustomIdMapped": "custom_id mapped", + "wizardCsvContentMapped": "Content field mapped (messages, input, or prompt)", + "wizardCsvApplyMapping": "Apply mapping", + "wizardCsvRowsParsed": "{count} rows parsed", + "wizardCsvRowsSkipped": "{count} rows skipped", + "wizardCsvRowError": "Row {row}: {reason}", "wizardValidationOk": "All lines valid", - "wizardValidating": "Validando…", - "wizardValidationParseFailed": "Error de validación — no se pudo analizar el contenido.", - "wizardValidationSummary": "{lines} líneas · {ids} custom_ids únicos", - "wizardValidationErrorCount": "{count, plural, one {# error encontrado} other {# errores encontrados}}", - "wizardValidationDuplicateIds": "custom_ids duplicados detectados:", - "wizardValidationFirstErrors": "Errores (primeros {count}):", - "wizardValidationLine": "Línea {line}", + "wizardValidating": "Validating…", + "wizardValidationParseFailed": "Validation failed — could not parse content.", + "wizardValidationSummary": "{lines} lines · {ids} unique custom_ids", + "wizardValidationErrorCount": "{count, plural, one {# error} other {# errors}} found", + "wizardValidationDuplicateIds": "Duplicate custom_ids detected:", + "wizardValidationFirstErrors": "Errors (first {count}):", + "wizardValidationLine": "Line {line}", "wizardValidationErrors": "Validation errors", "wizardValidationPreview": "Preview (first 5 requests)", "wizardValidationSamplingNote": "File is large — validated by sampling (first 1000 + last 100 lines). Full validation runs server-side.", @@ -930,9 +930,9 @@ "batchActionRetryError": "Failed to retry failed requests. Try again.", "batchConceptRetentionNote": "Results and error files are retained for 30 days (Anthropic: 29 days)" }, - "disabled": "Deshabilitado", - "featureFlagOmnirouteEmergencyFallbackDescription": "Enrutar las solicitudes con presupuesto agotado al proveedor/modelo de respaldo gratuito de emergencia.", - "featureFlagArenaEloSyncEnabledDescription": "Habilitar la sincronización periódica de ELO de la tabla de clasificación de Arena AI para los rankings de inteligencia de modelos.", + "disabled": "Disabled", + "featureFlagOmnirouteEmergencyFallbackDescription": "Route budget-exhausted requests to the emergency free fallback provider/model.", + "featureFlagArenaEloSyncEnabledDescription": "Enable periodic Arena AI leaderboard ELO sync for model intelligence rankings.", "sidebar": { "home": "Inicio", "dashboard": "Panel de control", @@ -956,7 +956,7 @@ "skills": "Skills", "omniSkills": "OmniSkills", "agentSkills": "Habilidades del agente", - "chaosConfig": "Modo Caos", + "chaosConfig": "Chaos Mode", "docs": "Documentación", "issues": "Problemas", "endpoints": "Endpoints", @@ -1048,19 +1048,21 @@ "contextCcr": "CCR", "contextLlmlingua": "LLMLingua", "combosLive": "Combo Studio", - "combosLiveSubtitle": "Cascada de enrutamiento en vivo", + "combosLiveSubtitle": "Live routing cascade", "compressionStudio": "Compression Studio", - "contextSettingsSubtitle": "Valores predeterminados globales", - "contextHeadroomSubtitle": "Compactación tabular", - "contextSessionDedupSubtitle": "Deduplicación entre turnos", - "contextCcrSubtitle": "Recuperar marcadores", - "contextLlmlinguaSubtitle": "Poda semántica", - "contextLiteSubtitle": "Limpieza rápida de espacios en blanco", - "contextAggressiveSubtitle": "Resumen y envejecimiento", - "contextUltraSubtitle": "Poda heurística", - "contextOmniglyphSubtitle": "Contexto como imágenes", - "compressionStudioSubtitle": "Cascada de motores en vivo", - "chaosConfigSubtitle": "Ejecución paralela multimodelo", + "compressionExclusions": "Exclusions", + "contextSettingsSubtitle": "Global defaults", + "contextHeadroomSubtitle": "Tabular compaction", + "contextSessionDedupSubtitle": "Cross-turn deduplication", + "contextCcrSubtitle": "Retrieve markers", + "contextLlmlinguaSubtitle": "Semantic pruning", + "contextLiteSubtitle": "Fast whitespace cleanup", + "contextAggressiveSubtitle": "Summary and aging", + "contextUltraSubtitle": "Heuristic pruning", + "contextOmniglyphSubtitle": "Context as images", + "compressionStudioSubtitle": "Live engine cascade", + "compressionExclusionsSubtitle": "Per-model/endpoint bypass", + "chaosConfigSubtitle": "Multi-model parallel execution", "routingSection": "Routing", "protocolsSection": "Protocols", "agentsAiSection": "Agents & AI", @@ -1083,10 +1085,10 @@ "analyticsComboHealth": "Combo Health", "analyticsCompression": "Compression", "costsBudget": "Budget", - "costsFreeTiers": "Presupuesto del nivel gratuito", - "costsFreeTiersSubtitle": "Asignaciones mensuales de tokens gratuitos", - "freeProviderRankings": "Rankings de proveedores gratuitos", - "freeProviderRankingsSubtitle": "Los mejores proveedores gratuitos clasificados por puntuaciones ELO del modelo", + "costsFreeTiers": "Free-Tier Budget", + "costsFreeTiersSubtitle": "Monthly free-token allowances", + "freeProviderRankings": "Free Provider Rankings", + "freeProviderRankingsSubtitle": "Best free providers ranked by model ELO scores", "costsQuotaShare": "Quota Sharing", "costsPricing": "Pricing", "logsProxy": "Proxy Logs", @@ -1098,12 +1100,13 @@ "settingsAppearance": "Appearance", "settingsAi": "AI Settings", "settingsSecurity": "Security", - "settingsAccessTokens": "Tokens de acceso", + "settingsAccessTokens": "Access Tokens", "settingsFeatureFlags": "Banderas de características", + "settingsCache": "Cache", "settingsAuthz": "Authz", "settingsRouting": "Routing", "settingsResilience": "Resilience", - "modelLockout": "Bloqueo de modelos", + "modelLockout": "Model Lockout", "settingsAdvanced": "Advanced", "omniProxySection": "OmniProxy", "quotaTracker": "Provider Quota", @@ -1150,8 +1153,8 @@ "analyticsCompressionSubtitle": "Token savings stats", "analyticsSearchSubtitle": "Search tool analytics", "analyticsEvalsSubtitle": "Eval suite results", - "providerStats": "Estadísticas del proveedor", - "providerStatsSubtitle": "Métricas de latencia y rendimiento", + "providerStats": "Provider Stats", + "providerStatsSubtitle": "Latency and performance metrics", "logsSubtitle": "Application logs", "logsProxySubtitle": "Proxy traffic logs", "consoleLogsSubtitle": "Console output", @@ -1171,7 +1174,7 @@ "agentSkillsSubtitle": "A2A skill registry", "mcpSubtitle": "MCP server controls", "a2aSubtitle": "A2A protocol server", - "pluginsSubtitle": "Marketplace e instalaciones de plugins", + "pluginsSubtitle": "Plugin marketplace & installs", "mediaSubtitle": "Cached media files", "batchFilesSubtitle": "Batch input/output files", "settingsSubtitle": "All settings", @@ -1182,44 +1185,45 @@ "settingsResilienceSubtitle": "Retries and breakers", "settingsAdvancedSubtitle": "Power user options", "settingsSecuritySubtitle": "Auth and encryption", - "settingsAccessTokensSubtitle": "Tokens de CLI con alcance para el modo remoto", + "settingsAccessTokensSubtitle": "Scoped CLI tokens for remote mode", "settingsFeatureFlagsSubtitle": "Alternar capacidades del sistema", + "settingsCacheSubtitle": "Model catalog and response caching", "settingsSidebar": "Sidebar", "settingsSidebarSubtitle": "Customize sidebar layout", "settingsAuthzSubtitle": "Inventario de rutas y política de omisión", "docsSubtitle": "Documentation", "issuesSubtitle": "Report a bug", "changelogSubtitle": "Release notes", - "costsQuotaPlans": "Planes y cuotas", - "costsQuotaPlansSubtitle": "Configurar planes por proveedor", - "activity": "Actividad", - "activitySubtitle": "Feed amigable de eventos recientes", - "logsGroup": "Registros", - "systemGroup": "Sistema", - "costsOverview": "Información general", - "costsOverviewSubtitle": "Análisis de costos consolidado", + "costsQuotaPlans": "Plans & Quotas", + "costsQuotaPlansSubtitle": "Configure plans by provider", + "activity": "Activity", + "activitySubtitle": "Friendly feed of recent events", + "logsGroup": "Logs", + "systemGroup": "System", + "costsOverview": "Overview", + "costsOverviewSubtitle": "Consolidated cost analysis", "agentBridge": "Agent Bridge", - "agentBridgeSubtitle": "Interceptar el tráfico del agente del IDE", - "trafficInspector": "Inspector de tráfico", - "trafficInspectorSubtitle": "Monitorear llamadas de LLM + depurar cualquier tráfico HTTPS", - "cliCode": "Código CLI", - "cliCodeSubtitle": "Herramientas de código que apuntan a OmniRoute", - "cliAgents": "Agentes de CLI", - "cliAgentsSubtitle": "Agentes de CLI autónomos", - "acpAgents": "Agentes ACP", - "acpAgentsSubtitle": "CLIs generadas por OmniRoute", - "skipToContent": "Saltar al contenido", - "mainNavigation": "Navegación principal", - "unpinSection": "Desanclar sección", - "pinSectionOpen": "Anclar sección abierta", - "reloadPage": "Recargar página", - "dragReorderSection": "Arrastrar para reordenar sección", - "dragReorderItem": "Arrastrar para reordenar", - "cannotHide": "Este elemento no se puede ocultar", - "alwaysVisible": "Siempre visible", - "groupSeparatorLabel": "Separador", - "discovery": "Descubrimiento", - "discoverySubtitle": "Escanear proveedores para obtener acceso gratuito" + "agentBridgeSubtitle": "Intercept IDE agent traffic", + "trafficInspector": "Traffic Inspector", + "trafficInspectorSubtitle": "Monitor LLM calls + debug any HTTPS traffic", + "cliCode": "CLI Code", + "cliCodeSubtitle": "Code tools pointing to OmniRoute", + "cliAgents": "CLI Agents", + "cliAgentsSubtitle": "Autonomous CLI agents", + "acpAgents": "ACP Agents", + "acpAgentsSubtitle": "CLIs spawned by OmniRoute", + "skipToContent": "Skip to content", + "mainNavigation": "Main navigation", + "unpinSection": "Unpin section", + "pinSectionOpen": "Pin section open", + "reloadPage": "Reload Page", + "dragReorderSection": "Drag to reorder section", + "dragReorderItem": "Drag to reorder", + "cannotHide": "This item cannot be hidden", + "alwaysVisible": "Always visible", + "groupSeparatorLabel": "Separator", + "discovery": "Discovery", + "discoverySubtitle": "Scan providers for free access" }, "webhooks": { "title": "Ganchos web", @@ -1274,84 +1278,84 @@ "back": "Atrás", "next": "Siguiente", "finish": "Finalizar", - "step1Desc": "Seleccione el sistema de integración de destino para este webhook." + "step1Desc": "Selecciona el sistema de integración destino para este webhook." }, "howItWorks": { - "step1": "Elija un proveedor de integración (por ejemplo, Slack, Discord, webhook personalizado) y configure los detalles de la conexión.", - "step2": "Configure los eventos del sistema a los que suscribirse (por ejemplo, errores de finalización, alternativas de modelo o límites de uso).", - "step3": "Verifique la configuración enviando una carga útil de prueba para asegurarse de que el endpoint la reciba.", - "step4": "Proteja su endpoint validando el encabezado X-Webhook-Signature HMAC-SHA256 utilizando el secreto del webhook.", - "title": "Cómo funcionan los webhooks", - "customOnly": "Solo aplicable para integraciones de endpoints personalizados.", - "hmacRecipeTitle": "Receta de verificación HMAC", - "hmacRecipe": "Para verificar las cargas útiles de webhook en Node.js, calcule el HMAC-SHA256 del cuerpo de la solicitud sin procesar utilizando su clave secreta. Compárelo con el encabezado X-Webhook-Signature utilizando timingSafeEqual.", - "timeoutNote": "Las entregas de webhook tienen un tiempo de espera de 10 segundos.", - "retryNote": "Las entregas fallidas se reintentan hasta 5 veces con retroceso exponencial.", - "docsLink": "Lea la guía completa para desarrolladores de Webhooks", + "step1": "Elige un proveedor de integración (p. ej., Slack, Discord, webhook personalizado) y configura los detalles de conexión.", + "step2": "Configura los eventos del sistema a los que suscribirse (p. ej., errores de completado, fallbacks de modelo o límites de uso).", + "step3": "Verifica la configuración enviando una carga útil de prueba para asegurarte de que el punto de conexión la recibe.", + "step4": "Protege tu extremo validando el encabezado X-Webhook-Signature HMAC-SHA256 utilizando el secreto del webhook.", + "title": "Cómo funcionan los Webhooks", + "customOnly": "Solo aplicable para integraciones con extremos personalizados.", + "hmacRecipeTitle": "Fórmula de verificación HMAC", + "hmacRecipe": "Para verificar cargas de webhook en Node.js, calcula el HMAC-SHA256 del cuerpo sin procesar usando tu clave secreta y compáralo con X-Webhook-Signature usando timingSafeEqual.", + "timeoutNote": "Los envíos de webhooks tienen un tiempo de espera de 10 segundos.", + "retryNote": "Los envíos fallidos se reintentan hasta 5 veces con reintento exponencial.", + "docsLink": "Leer la guía completa para desarrolladores de Webhooks", "hmacRecipePython": "Verificación HMAC en Python: hmac.new(secret, body, hashlib.sha256).hexdigest()", "hmacRecipeBash": "Verificación HMAC en Bash: echo -n \"$body\" | openssl dgst -sha256 -hmac \"$secret\"" }, "deliveries": { - "title": "Registros de entrega", - "loadFailed": "Error al cargar los registros de entrega del webhook.", - "empty": "Aún no se han registrado entregas. Active un evento o envíe una carga útil de prueba.", - "status": "Estado", - "event": "Evento", - "latency": "Latencia", - "at": "Enviado el" + "title": "Delivery Logs", + "loadFailed": "Failed to load webhook delivery logs.", + "empty": "No deliveries recorded yet. Trigger an event or send a test payload.", + "status": "Status", + "event": "Event", + "latency": "Latency", + "at": "Sent At" }, "kinds": { - "comingSoon": "Próximamente", + "comingSoon": "Coming Soon", "slack": "Slack", - "slackDesc": "Publique eventos del sistema directamente en un canal de Slack", + "slackDesc": "Post system events directly into a Slack channel", "telegram": "Telegram", - "telegramDesc": "Envíe mensajes de eventos usando un bot de Telegram", + "telegramDesc": "Send event messages using a Telegram bot", "discord": "Discord", - "discordDesc": "Entregue actualizaciones en tiempo real directamente a un servidor de Discord", - "custom": "Webhook personalizado", - "customDesc": "Entregue cargas útiles de eventos del sistema a cualquier endpoint HTTPS", - "email": "Notificación por correo electrónico", - "emailDesc": "Reciba actualizaciones de resumen por correo electrónico", + "discordDesc": "Deliver real-time updates directly to a Discord server", + "custom": "Custom Webhook", + "customDesc": "Deliver system event payloads to any HTTPS endpoint", + "email": "Email Notification", + "emailDesc": "Receive summary updates via email", "pagerduty": "PagerDuty", - "pagerdutyDesc": "Active alertas en PagerDuty para problemas críticos del sistema", + "pagerdutyDesc": "Trigger alerts on PagerDuty for critical system issues", "teams": "Microsoft Teams", - "teamsDesc": "Reenvíe notificaciones del sistema a canales de Microsoft Teams" + "teamsDesc": "Forward system notifications to Microsoft Teams channels" }, - "testPayloadSent": "Carga útil de prueba enviada", + "testPayloadSent": "Prueba enviada", "testResponse": "Respuesta de prueba", "validateUrl": { - "checking": "Comprobando URL...", - "ok": "La URL es válida", - "blockedPrivate": "La URL es una dirección privada bloqueada", - "invalidUrl": "Formato de URL no válido" + "checking": "Checking URL...", + "ok": "URL is valid", + "blockedPrivate": "URL is a blocked private address", + "invalidUrl": "Invalid URL format" }, "custom": { - "endpointUrl": "URL del endpoint", + "endpointUrl": "Endpoint URL", "endpointUrlPlaceholder": "https://api.yourdomain.com/webhook", - "secretKey": "Clave secreta", - "secretKeyPlaceholder": "Introduzca la clave secreta o déjela en blanco para generarla automáticamente", - "secretKeyHint": "Se utiliza para firmar el encabezado de la carga útil para la autenticación." + "secretKey": "Secret Key", + "secretKeyPlaceholder": "Enter secret key or leave blank to auto-generate", + "secretKeyHint": "Used to sign the payload header for authentication." }, "discord": { - "webhookUrl": "URL del webhook de Discord", + "webhookUrl": "Discord Webhook URL", "webhookUrlPlaceholder": "https://discord.com/api/webhooks/...", - "webhookUrlHint": "La URL del webhook copiada de la configuración de integración de tu canal de Discord.", - "tutorial": "Cómo crear un webhook de Discord:" + "webhookUrlHint": "The webhook URL copied from your Discord channel integration settings.", + "tutorial": "How to create a Discord webhook:" }, "slack": { - "webhookUrl": "URL del webhook de Slack", + "webhookUrl": "Slack Webhook URL", "webhookUrlPlaceholder": "https://hooks.slack.com/services/...", - "webhookUrlHint": "La URL del webhook copiada de la integración de Webhooks entrantes de Slack.", - "tutorial": "Cómo crear un webhook de Slack:" + "webhookUrlHint": "The webhook URL copied from your Slack Incoming Webhooks integration.", + "tutorial": "How to create a Slack webhook:" }, "telegram": { - "botToken": "Token del bot de Telegram", + "botToken": "Telegram Bot Token", "botTokenPlaceholder": "123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ", - "botTokenHint": "El token de la API HTTP recibido de @BotFather al crear tu bot.", - "chatId": "ID de chat / Canal de Telegram", - "chatIdPlaceholder": "-100123456789 o @nombre_de_canal", - "chatIdHint": "El identificador numérico único o el nombre de usuario público del chat/canal.", - "tutorial": "Cómo configurar el webhook de Telegram:" + "botTokenHint": "The HTTP API token received from @BotFather when creating your bot.", + "chatId": "Telegram Chat ID / Channel", + "chatIdPlaceholder": "-100123456789 or @channelname", + "chatIdHint": "The unique numerical identifier or public username of the chat/channel.", + "tutorial": "How to configure Telegram webhook:" } }, "compliance": { @@ -1422,7 +1426,7 @@ "a2aNoTasks": "No se registraron tareas A2A.", "a2aLoadingTasks": "Cargando tareas A2A...", "actor": "Actor", - "actorPlaceholder": "Filtrar por actor", + "actorPlaceholder": "Filter by actor", "eventTypes": { "apiKey.activate": "Clave de API activada", "apiKey.ban": "Clave de API bloqueada", @@ -1473,11 +1477,11 @@ }, "header": { "logout": "Cerrar sesión", - "quickNavigation": "Navegación rápida", - "quickNavigationTitle": "Navegación rápida (⌘K / Ctrl+K)", - "openQuickNavigation": "Abrir navegación rápida", - "switchToLightMode": "Cambiar al modo claro", - "switchToDarkMode": "Cambiar al modo oscuro", + "quickNavigation": "Quick nav", + "quickNavigationTitle": "Quick navigation (⌘K / Ctrl+K)", + "openQuickNavigation": "Open quick navigation", + "switchToLightMode": "Switch to light mode", + "switchToDarkMode": "Switch to dark mode", "language": "Idioma", "providers": "Proveedores", "providerDescription": "Gestiona tus conexiones de proveedores de IA", @@ -1546,12 +1550,13 @@ "settingsGeneralDescription": "Storage, database, and general instance configuration", "settingsAppearanceDescription": "Theme, branding, and visual customization", "settingsAiDescription": "AI behaviors, thinking budgets, vision, and memory settings", + "settingsCacheDescription": "TTL for model catalog cache entries", "settingsSecurityDescription": "Authentication, authorization, and access control settings", "featureFlags": "Banderas de características", "featureFlagsDescription": "Capacidades del sistema de control y características experimentales.", "featureFlagsActive": "{count} activo", "featureFlagsInactive": "{count} inactivo", - "featureFlagsOverrides": "{count} Anulaciones de base de datos", + "featureFlagsOverrides": "{count} Ajustes específicos de base de datos", "featureFlagsSearch": "Buscar banderas...", "featureFlagsCategoryAll": "Todos", "featureFlagsCategorySecurity": "Seguridad", @@ -1564,8 +1569,8 @@ "featureFlagsSourceEnv": "ENV", "featureFlagsSourceDefault": "DEF", "featureFlagsReset": "Reiniciar", - "featureFlagsResetAll": "Restablecer todas las anulaciones", - "featureFlagsResetAllConfirm": "¿Está seguro de que desea restablecer todas las anulaciones de indicadores de funciones? Esto revertirá todos los indicadores a sus valores ENV o predeterminados.", + "featureFlagsResetAll": "Restablecer todas las Ajustes específicos", + "featureFlagsResetAllConfirm": "¿Está seguro de que desea restablecer todas las Ajustes específicos de indicadores de funciones? Esto revertirá todos los indicadores a sus valores ENV o predeterminados.", "featureFlagsRestartRequired": "Es necesario reiniciar para aplicar", "featureFlagsNoResults": "Ninguna bandera coincide con tu búsqueda", "featureFlagsSaved": "Bandera actualizada", @@ -1575,109 +1580,109 @@ "settingsAdvancedDescription": "Advanced payload rules, request limits, and proxy API settings", "mitmProxyDescription": "Configure MITM proxy settings for traffic inspection and debugging", "oneProxyDescription": "Configure 1Proxy settings for advanced proxy chaining", - "omniSkillsDescription": "Instalar y administrar habilidades de sandbox para la ejecución automatizada de prompts y herramientas" + "omniSkillsDescription": "Install and manage sandbox skills for automated prompt and tool execution" }, "cloudSyncStatus": { - "synced": "Sincronizado", - "syncing": "Sincronizando...", - "off": "Sincronización desactivada", - "error": "Error de sincronización", - "disabled": "Deshabilitado", - "connected": "conectado", - "disconnected": "desconectado", - "lastSync": "Sincronización de configuración remota {status} — Última sincronización: {time}", - "statusLabel": "Estado de sincronización de configuración remota: {status}" + "synced": "Synced", + "syncing": "Syncing...", + "off": "Sync off", + "error": "Sync error", + "disabled": "Disabled", + "connected": "connected", + "disconnected": "disconnected", + "lastSync": "Remote settings sync {status} — Last sync: {time}", + "statusLabel": "Remote settings sync status: {status}" }, "breadcrumbs": { - "ariaLabel": "Ruta de navegación", - "dashboard": "Panel de control", - "providers": "Proveedores", + "ariaLabel": "Breadcrumb", + "dashboard": "Dashboard", + "providers": "Providers", "combos": "Combos", - "settings": "Configuración", + "settings": "Settings", "general": "General", - "appearance": "Apariencia", - "ai": "Configuración de IA", - "routing": "Enrutamiento", - "resilience": "Resiliencia", - "advanced": "Avanzado", - "accessTokens": "Tokens de acceso", - "featureFlags": "Flags de función", + "appearance": "Appearance", + "ai": "AI Settings", + "routing": "Routing", + "resilience": "Resilience", + "advanced": "Advanced", + "accessTokens": "Access Tokens", + "featureFlags": "Feature Flags", "logs": "Logs", - "auditLog": "Registro de auditoría", - "console": "Consola", - "logger": "Registrador", - "translator": "Traductor", + "auditLog": "Audit Log", + "console": "Console", + "logger": "Logger", + "translator": "Translator", "playground": "Playground", - "add": "Añadir", - "edit": "Editar", - "apiKeys": "Claves de API", - "models": "Modelos", - "cliCode": "Código CLI", - "cliAgents": "Agentes CLI", - "acpAgents": "Agentes ACP", + "add": "Add", + "edit": "Edit", + "apiKeys": "API Keys", + "models": "Models", + "cliCode": "CLI Code", + "cliAgents": "CLI Agents", + "acpAgents": "ACP Agents", "endpoint": "Endpoint", - "apiManager": "Gestor de API", - "context": "Contexto", - "compression": "Compresión", - "services": "Servicios", - "analytics": "Analítica", - "costs": "Costos", - "health": "Salud", + "apiManager": "API Manager", + "context": "Context", + "compression": "Compression", + "services": "Services", + "analytics": "Analytics", + "costs": "Costs", + "health": "Health", "runtime": "Runtime", "webhooks": "Webhooks", - "home": "Inicio", - "activity": "Actividad", - "agentSkills": "Habilidades de agente", - "comboHealth": "Salud del combo", - "evals": "Evaluaciones", - "search": "Buscar", - "utilization": "Utilización", - "apiEndpoints": "Endpoints de API", - "audit": "Auditoría", + "home": "Home", + "activity": "Activity", + "agentSkills": "AgentSkills", + "comboHealth": "Combo Health", + "evals": "Evals", + "search": "Search", + "utilization": "Utilization", + "apiEndpoints": "API Endpoints", + "audit": "Audit", "a2a": "A2A", "mcp": "MCP", - "batch": "Lote", - "files": "Archivos", - "media": "Medios", - "cache": "Caché", - "changelog": "Registro de cambios", - "chaos": "Caos", - "cloudAgents": "Agentes en la nube", - "live": "En vivo", + "batch": "Batch", + "files": "Files", + "media": "Media", + "cache": "Cache", + "changelog": "Changelog", + "chaos": "Chaos", + "cloudAgents": "Cloud Agents", + "live": "Live", "studio": "Studio", - "aggressive": "Agresivo", - "caveman": "Cavernícola", + "aggressive": "Aggressive", + "caveman": "Caveman", "ccr": "CCR", - "headroom": "Margen", + "headroom": "Headroom", "lite": "Lite", "llmlingua": "LLMLingua", "omniglyph": "OmniGlyph", "rtk": "RTK", - "sessionDedup": "Deduplicación de sesiones", + "sessionDedup": "Session Dedup", "ultra": "Ultra", - "budget": "Presupuesto", - "pricing": "Precios", - "quotaShare": "Cuota compartida", - "discovery": "Descubrimiento", - "freeProviderRankings": "Clasificación de proveedores gratuitos", - "freeTiers": "Niveles gratuitos", - "gamification": "Gamificación", - "leaderboard": "Tabla de clasificación", - "limits": "Límites", - "profile": "Perfil", + "budget": "Budget", + "pricing": "Pricing", + "quotaShare": "Quota Share", + "discovery": "Discovery", + "freeProviderRankings": "Free Provider Rankings", + "freeTiers": "Free Tiers", + "gamification": "Gamification", + "leaderboard": "Leaderboard", + "limits": "Limits", + "profile": "Profile", "plugins": "Plugins", - "providerStats": "Estadísticas del proveedor", - "new": "Nuevo", - "quota": "Cuota", + "providerStats": "Provider Stats", + "new": "New", + "quota": "Quota", "relay": "Relay", - "searchTools": "Herramientas de búsqueda", - "security": "Seguridad", - "sidebar": "Barra lateral", + "searchTools": "Search Tools", + "security": "Security", + "sidebar": "Sidebar", "tokens": "Tokens", - "tools": "Herramientas", - "agentBridge": "Puente de agentes", - "trafficInspector": "Inspector de tráfico", - "usage": "Uso" + "tools": "Tools", + "agentBridge": "Agent Bridge", + "trafficInspector": "Traffic Inspector", + "usage": "Usage" }, "home": { "quickStart": "Inicio rápido", @@ -1724,102 +1729,102 @@ "title": "Analítica", "usageAnalyticsTitle": "Análisis de uso", "diversityScoreTitle": "Diversidad de proveedores", - "diversityScoreDesc": "Captura de la concentración de proveedores para la ventana de tráfico reciente.", + "diversityScoreDesc": "Muestra la concentración de proveedores para la ventana de tráfico reciente.", "diversityShannonEntropy": "Entropía de Shannon", - "diversityWindow": "Ventana: {count} reqs · Últimos {mins} min", + "diversityWindow": "Ventana: {count} solic. · Últimos {mins} mins", "diversityHealthy": "Distribución saludable", - "diversityRiskHigh": "Alto riesgo de dependencia del proveedor", - "diversityRiskModerate": "Distribución moderada", - "diversityScoreLabel": "puntuación", - "diversityHigherExplanation": "Los valores más altos significan que el tráfico está distribuido entre múltiples proveedores.", - "diversityNoData": "No hay datos de uso reciente disponibles.", - "chartRequests": "Solicitudes", - "chartInput": "Entrada", - "chartOutput": "Salida", + "diversityRiskHigh": "High Vendor Lock-in Risk", + "diversityRiskModerate": "Moderate Distribution", + "diversityScoreLabel": "score", + "diversityHigherExplanation": "Higher values mean traffic is spread across multiple providers.", + "diversityNoData": "No recent usage data available.", + "chartRequests": "Requests", + "chartInput": "Input", + "chartOutput": "Output", "chartTotal": "Total", - "chartCost": "Costo", - "chartShare": "Proporción", - "chartServiceTier": "Nivel de servicio", - "chartServiceTierSplit": "División de costo Rápido / Estándar", - "chartCostPct": "{pct}% del costo", - "chartUsageDetail": "Detalle de uso", - "chartCacheRead": "Lectura de caché", - "chartCostByProvider": "Costo por proveedor", - "chartNoCostData": "Sin datos de costo", - "chartModelUsageOverTime": "Uso del modelo a lo largo del tiempo", - "chartNoData": "Sin datos", - "chartWeekly": "Semanal", - "activitySummary": "{active} días activos · {tokens} tokens · {days} días", + "chartCost": "Cost", + "chartShare": "Share", + "chartServiceTier": "Service Tier", + "chartServiceTierSplit": "Fast / Standard cost split", + "chartCostPct": "{pct}% of cost", + "chartUsageDetail": "Usage Detail", + "chartCacheRead": "Cache read", + "chartCostByProvider": "Cost by Provider", + "chartNoCostData": "No cost data", + "chartModelUsageOverTime": "Model Usage Over Time", + "chartNoData": "No data", + "chartWeekly": "Weekly", + "activitySummary": "{active} active days · {tokens} tokens · {days} days", "activityCellTitle": "{date}: {tokens} tokens", - "activityLess": "Menos", - "activityMore": "Más", - "chartApiKeyBreakdown": "Desglose de claves API", - "chartApiKey": "Clave API", - "mostActiveDay": "Día más activo", + "activityLess": "Less", + "activityMore": "More", + "chartApiKeyBreakdown": "API Key Breakdown", + "chartApiKey": "API Key", + "mostActiveDay": "Most Active Day", "datedTokenCount": "{date} · {tokens} tokens", - "noDataLast7Days": "Sin datos en los últimos 7 días", - "requestTokenSummary": "{requests} solicitudes · {tokens} tokens", - "chartByAccount": "Por cuenta", - "chartByApiKey": "Por clave API", - "unknownApiKey": "Clave API desconocida", - "chartModelBreakdown": "Desglose de modelos", - "chartModel": "Modelo", - "chartProvider": "Proveedor", - "chartProviderBreakdown": "Desglose de proveedores", - "chartDate": "Fecha", - "chartRequestsByProviderDate": "Solicitudes por proveedor y fecha", - "filterAllKeys": "Todas las claves", - "filterSearchKeys": "Buscar claves…", - "filterNoKeysMatch": "Ninguna clave coincide", - "filterOneKey": "1 clave", - "filterMultipleKeys": "{count} claves", - "rangeToday": "Hoy", - "rangeYesterday": "Ayer", - "rangeLast3Days": "Últimos 3 días", - "rangeThisWeek": "Esta semana", - "rangeLast14Days": "Últimos 14 días", - "rangeThisMonth": "Este mes", - "rangeQuickSelect": "Selección rápida", - "rangeStart": "Inicio", - "rangeEnd": "Fin", - "rangeCancel": "Cancelar", - "rangeApply": "Aplicar", - "rangeErrorInvalid": "El inicio debe ser anterior al fin", + "noDataLast7Days": "No data in the last 7 days", + "requestTokenSummary": "{requests} requests · {tokens} tokens", + "chartByAccount": "By Account", + "chartByApiKey": "By API Key", + "unknownApiKey": "Unknown API key", + "chartModelBreakdown": "Model Breakdown", + "chartModel": "Model", + "chartProvider": "Provider", + "chartProviderBreakdown": "Provider Breakdown", + "chartDate": "Date", + "chartRequestsByProviderDate": "Requests by Provider & Date", + "filterAllKeys": "All Keys", + "filterSearchKeys": "Search keys…", + "filterNoKeysMatch": "No keys match", + "filterOneKey": "1 key", + "filterMultipleKeys": "{count} keys", + "rangeToday": "Today", + "rangeYesterday": "Yesterday", + "rangeLast3Days": "Last 3 days", + "rangeThisWeek": "This week", + "rangeLast14Days": "Last 14 days", + "rangeThisMonth": "This month", + "rangeQuickSelect": "Quick Select", + "rangeStart": "Start", + "rangeEnd": "End", + "rangeCancel": "Cancel", + "rangeApply": "Apply", + "rangeErrorInvalid": "Start must be before end", "period1D": "1D", "period7D": "7D", "period30D": "30D", "period90D": "90D", "periodYTD": "YTD", - "periodAll": "Todo", - "totalTokens": "Tokens totales", - "inputTokens": "Tokens de entrada", - "outputTokens": "Tokens de salida", - "estCost": "Costo est.", - "infraTitle": "Infraestructura", - "infraAccounts": "Cuentas", - "infraProviders": "Proveedores", - "infraApiKeys": "Claves de API", - "infraModels": "Modelos", - "perfTitle": "Rendimiento", - "perfAvgTokens": "Tokens/solic. promedio", - "perfCostReq": "Costo/solic.", - "perfIoRatio": "Relación E/S", - "perfFastReq": "Solicitudes rápidas", - "highlightsTitle": "Destacados", - "highlightsTopModel": "Modelo principal", - "highlightsTopProvider": "Proveedor principal", - "highlightsBusiestDay": "Día de mayor actividad", - "highlightsDiversity": "Diversidad", - "highlightsFallbackRate": "Tasa de fallback", - "customRange": "Personalizado", + "periodAll": "All", + "totalTokens": "Total de tokens", + "inputTokens": "Input Tokens", + "outputTokens": "Output Tokens", + "estCost": "Est. Cost", + "infraTitle": "Infrastructure", + "infraAccounts": "Accounts", + "infraProviders": "Providers", + "infraApiKeys": "API Keys", + "infraModels": "Models", + "perfTitle": "Performance", + "perfAvgTokens": "Avg Tokens/Req", + "perfCostReq": "Cost/Req", + "perfIoRatio": "I/O Ratio", + "perfFastReq": "Fast Requests", + "highlightsTitle": "Highlights", + "highlightsTopModel": "Top Model", + "highlightsTopProvider": "Top Provider", + "highlightsBusiestDay": "Busiest Day", + "highlightsDiversity": "Diversity", + "highlightsFallbackRate": "Fallback Rate", + "customRange": "Rango personalizado", "overviewDescription": "Supervise sus patrones de uso de API, consumo de tokens, costos y tendencias de actividad en todos los proveedores y modelos.", "evalsDescription": "Ejecute conjuntos de evaluación para probar y validar sus puntos finales de LLM. Compare la calidad del modelo, detecte regresiones y compare la latencia.", "overview": "Descripción general", "evals": "evaluaciones", - "search": "Buscar", + "search": "Search", "utilization": "Utilización", - "routeTrace": "Rastreo de ruta", - "sectionsAria": "Secciones de analíticas", + "routeTrace": "Route Trace", + "sectionsAria": "Analytics sections", "utilizationDescription": "Tendencias de uso de cuota del proveedor y seguimiento de límites de tasa", "modelStatus": "Estado del modelo", "modelStatusCooldown": "Enfriamiento", @@ -1850,83 +1855,83 @@ "comboHealthTitle": "salud combinada", "comboHealthUnableToLoad": "No se puede cargar la salud combinada", "comboHealthGettingStarted": "Empezando", - "comboHealthForecastTitle": "Pronóstico de costo y cuota", - "comboHealthForecastDescription": "Proyección lineal a partir del tráfico histórico del combo e instantáneas de cuota.", - "comboHealthQuotaRisk": "Riesgo de cuota {level}", - "comboHealthConfidence": "Confianza {level}", - "comboHealthProjectedCost": "Costo proyectado", - "comboHealthCostHistory": "historial {total} · {daily}/día", - "comboHealthProjectedRequests": "Solicitudes proyectadas", - "comboHealthRequestsInRange": "{count} en el rango seleccionado", - "comboHealthWorstProjectedQuota": "Peor cuota proyectada", - "comboHealthNoDepletionEstimate": "Sin estimación de agotamiento", - "comboHealthDaysToExhaust": "{days}d para agotarse", - "comboHealthTraffic": "tráfico", - "comboHealthProjectedQuota": "Cuota proyectada", - "comboHealthPricingCoverage": "Cobertura de precios", - "comboHealthAutopilotTitle": "Piloto automático de salud del combo", - "comboHealthAutopilotDescription": "Recomendaciones priorizadas a partir de la salud del combo, pronósticos, cuotas y salud del proveedor.", - "comboHealthIssues": "Problemas", - "comboHealthActionable": "{count} accionables", - "comboHealthDown": "Caído", - "comboHealthDegraded": "Degradado", - "comboHealthHealthy": "Saludable", - "comboHealthNoActiveIssues": "No se detectaron problemas de salud del combo activos para el rango seleccionado.", - "comboHealthScoringInspector": "Inspector de puntuación inteligente", - "comboHealthReadOnlyRecompute": "Recálculo de solo lectura", - "comboHealthScoringDescription": "Explicación a nivel de factor para la clasificación de objetivos utilizando la salud actual, el pronóstico y las heurísticas de enrutamiento.", - "comboHealthTask": "Tarea: {task}", - "comboHealthSelectedRank": "Posición seleccionada #1", + "comboHealthForecastTitle": "Cost & quota forecast", + "comboHealthForecastDescription": "Linear projection from historical combo traffic and quota snapshots.", + "comboHealthQuotaRisk": "{level} quota risk", + "comboHealthConfidence": "{level} confidence", + "comboHealthProjectedCost": "Projected cost", + "comboHealthCostHistory": "history {total} · {daily}/day", + "comboHealthProjectedRequests": "Projected requests", + "comboHealthRequestsInRange": "{count} in selected range", + "comboHealthWorstProjectedQuota": "Worst projected quota", + "comboHealthNoDepletionEstimate": "No depletion estimate", + "comboHealthDaysToExhaust": "{days}d to exhaust", + "comboHealthTraffic": "traffic", + "comboHealthProjectedQuota": "Projected quota", + "comboHealthPricingCoverage": "Pricing coverage", + "comboHealthAutopilotTitle": "Combo Health Autopilot", + "comboHealthAutopilotDescription": "Prioritized recommendations from combo health, forecasts, quotas, and provider health.", + "comboHealthIssues": "Issues", + "comboHealthActionable": "{count} actionable", + "comboHealthDown": "Down", + "comboHealthDegraded": "Degraded", + "comboHealthHealthy": "Healthy", + "comboHealthNoActiveIssues": "No active combo health issues detected for the selected range.", + "comboHealthScoringInspector": "Intelligent scoring inspector", + "comboHealthReadOnlyRecompute": "Read-only recompute", + "comboHealthScoringDescription": "Factor-level explanation for target ranking using current health, forecast, and routing heuristics.", + "comboHealthTask": "Task: {task}", + "comboHealthSelectedRank": "Selected rank #1", "comboHealthFactor": { - "quota": "Cuota", - "health": "Salud", - "costInv": "Costo", - "latencyInv": "Latencia", - "taskFit": "Ajuste a la tarea", - "stability": "Estabilidad", - "tierPriority": "Nivel", - "tierAffinity": "Ajuste de nivel", - "specificityMatch": "Especificidad", - "contextAffinity": "Contexto", - "resetWindowAffinity": "Ventana de restablecimiento" + "quota": "Quota", + "health": "Health", + "costInv": "Cost", + "latencyInv": "Latency", + "taskFit": "Task fit", + "stability": "Stability", + "tierPriority": "Tier", + "tierAffinity": "Tier fit", + "specificityMatch": "Specificity", + "contextAffinity": "Context", + "resetWindowAffinity": "Reset window" }, - "comboHealthQuotaValue": "Cuota {value}", - "comboHealthLatencyValue": "Latencia {value}ms", - "comboHealthIssueCount": "Problemas {count}", - "comboHealthNoInspectableTargets": "No hay destinos inspeccionables para este combo.", + "comboHealthQuotaValue": "Quota {value}", + "comboHealthLatencyValue": "Latency {value}ms", + "comboHealthIssueCount": "Issues {count}", + "comboHealthNoInspectableTargets": "No inspectable targets for this combo.", "comboHealthAutopilotState": { - "down": "Caído", - "degraded": "Requiere atención", - "healthy": "Saludable" + "down": "Down", + "degraded": "Needs attention", + "healthy": "Healthy" }, - "comboHealthModelProviderCount": "{models} modelos en {providers} proveedores", - "comboHealthGiniCoefficient": "Coeficiente de Gini", - "comboHealthRequestCount": "{count} solicitudes", - "comboHealthQuotaHealthDescription": "Menor cuota restante entre proveedores con señales de tendencia cortas.", - "comboHealthRemainingQuota": "Cuota restante {value}", + "comboHealthModelProviderCount": "{models} models across {providers} providers", + "comboHealthGiniCoefficient": "Gini coefficient", + "comboHealthRequestCount": "{count} requests", + "comboHealthQuotaHealthDescription": "Lowest remaining quota across providers with short trend signals.", + "comboHealthRemainingQuota": "Remaining quota {value}", "comboHealthTrend": { - "improving": "Mejorando", - "declining": "Empeorando", - "stable": "Estable" + "improving": "Improving", + "declining": "Declining", + "stable": "Stable" }, - "comboHealthUsageSkewDescription": "Cuota de solicitudes y cuota de tokens del modelo dentro de este combo.", - "comboHealthShareSummary": "Cuota de solicitudes {requests} · Cuota de tokens {tokens}", - "comboHealthPerformance": "Rendimiento", - "comboHealthPerformanceDescription": "Fiabilidad y capacidad de procesamiento para el tráfico enrutado del combo.", - "comboHealthExecutionTargetsDescription": "Métricas de tiempo de ejecución a nivel de paso y visibilidad de cuota para destinos estructurados del combo.", + "comboHealthUsageSkewDescription": "Model request share and token share within this combo.", + "comboHealthShareSummary": "Request share {requests} · Token share {tokens}", + "comboHealthPerformance": "Performance", + "comboHealthPerformanceDescription": "Reliability and throughput for routed combo traffic.", + "comboHealthExecutionTargetsDescription": "Step-level runtime metrics and quota visibility for structured combo targets.", "comboHealthRequestShort": "{count} req", - "comboHealthQuotaScope": "Ámbito de la cuota: {scope}", - "comboHealthTrendValue": "Tendencia: {trend}", - "comboHealthFetchFailed": "Error al obtener los datos de salud del combo", - "unknownError": "Error desconocido", - "comboHealthIntro": "Supervise la presión de cuota, el uso sesgado de modelos y el rendimiento de entrega por combo.", - "comboHealthForecastHorizon": "Pronóstico {value}", - "comboHealthNoData": "No hay datos de salud del combo disponibles", - "comboHealthNoDataDescription": "Las instantáneas de cuota del combo y las solicitudes enrutadas aparecerán aquí una vez que el tráfico comience a fluir.", - "comboHealthStepCreate": "Cree combos en Combos con múltiples proveedores", - "comboHealthStepSend": "Envíe solicitudes a los endpoints del combo para generar datos de tráfico", - "comboHealthStepAutomatic": "Las métricas de salud aparecerán automáticamente a medida que se enruten las solicitudes", - "comboHealthTracking": "Rastreando {count} combos para {range}", + "comboHealthQuotaScope": "Quota scope: {scope}", + "comboHealthTrendValue": "Trend: {trend}", + "comboHealthFetchFailed": "Failed to fetch combo health data", + "unknownError": "Unknown error", + "comboHealthIntro": "Monitor quota pressure, skewed model usage, and delivery performance by combo.", + "comboHealthForecastHorizon": "{value} forecast", + "comboHealthNoData": "No combo health data available", + "comboHealthNoDataDescription": "Combo quota snapshots and routed requests will appear here after traffic starts flowing.", + "comboHealthStepCreate": "Create combos in Combos with multiple providers", + "comboHealthStepSend": "Send requests to combo endpoints to generate traffic data", + "comboHealthStepAutomatic": "Health metrics will appear automatically as requests are routed", + "comboHealthTracking": "Tracking {count} combos for {range}", "compressionAnalyticsTotalRequests": "Solicitudes totales", "compressionAnalyticsTokensSaved": "Fichas guardadas", "compressionAnalyticsAvgSavings": "Ahorro promedio", @@ -1938,26 +1943,26 @@ "compressionAnalyticsTotalTokens": "fichas totales", "compressionAnalyticsCacheTokens": "Fichas de caché", "compressionAnalyticsNoDataYet": "Aún no hay datos de compresión", - "compressionAnalyticsLoading": "Cargando analíticas de compresión…", - "compressionAnalyticsNoDataDescription": "Las solicitudes de compresión aparecerán aquí después de la primera solicitud a través de /v1/chat/completions con la compresión habilitada.", - "rangeLast24h": "Últimas 24h", - "rangeLast7d": "Últimos 7d", - "rangeLast30d": "Últimos 30d", - "rangeAllTime": "Todo el tiempo", - "compressionAnalyticsModeStats": "{count} solicitudes · {tokens} tokens ahorrados", - "compressionAnalyticsSkipped": " · {count} omitidas (no-op)", - "compressionAnalyticsRealTokens": "{count} tokens reales", - "compressionAnalyticsValidationRestores": "restauraciones de validación", - "compressionAnalyticsRealUsageReceipts": "Recibos de uso real", - "compressionAnalyticsSources": "Fuentes", - "compressionAnalyticsModeBreakdown": "Desglose por modo", - "compressionAnalyticsProviderBreakdown": "Desglose por proveedor", - "compressionAnalyticsLast24HoursActivity": "Últimas 24 horas (Actividad)", - "compressionAnalyticsChartPoint": "{hour}: {count} solicitudes, {tokens} tokens ahorrados", - "compressionAnalyticsMaxRequests": "Máx. solicitudes/hora: {count}", - "compressionAnalyticsMaxTokens": "Máx. tokens/hora: {count}", - "compressionAnalyticsStartTracking": "Usa POST /v1/chat/completions con la configuración de compresión para comenzar a rastrear las analíticas de compresión.", - "compressionAnalyticsInfo": "Analíticas de compresión: Ahorro de tokens rastreado por modo (off, lite, standard, aggressive, ultra, RTK, stacked), motor, combo de compresión y proveedor. Pasa el cursor sobre los gráficos para ver detalles. Usa el selector de tiempo para ver diferentes períodos de tiempo.", + "compressionAnalyticsLoading": "Loading compression analytics…", + "compressionAnalyticsNoDataDescription": "Compression requests will appear here after the first request through /v1/chat/completions with compression enabled.", + "rangeLast24h": "Last 24h", + "rangeLast7d": "Last 7d", + "rangeLast30d": "Last 30d", + "rangeAllTime": "All time", + "compressionAnalyticsModeStats": "{count} requests · {tokens} tokens saved", + "compressionAnalyticsSkipped": " · {count} skipped (no-op)", + "compressionAnalyticsRealTokens": "{count} real tokens", + "compressionAnalyticsValidationRestores": "validation restores", + "compressionAnalyticsRealUsageReceipts": "Real Usage Receipts", + "compressionAnalyticsSources": "Sources", + "compressionAnalyticsModeBreakdown": "Mode Breakdown", + "compressionAnalyticsProviderBreakdown": "Provider Breakdown", + "compressionAnalyticsLast24HoursActivity": "Last 24 Hours (Activity)", + "compressionAnalyticsChartPoint": "{hour}: {count} requests, {tokens} tokens saved", + "compressionAnalyticsMaxRequests": "Max requests/hour: {count}", + "compressionAnalyticsMaxTokens": "Max tokens/hour: {count}", + "compressionAnalyticsStartTracking": "Use POST /v1/chat/completions with compression configuration to start tracking compression analytics.", + "compressionAnalyticsInfo": "Compression analytics: Token savings tracked per mode (off, lite, standard, aggressive, ultra, RTK, stacked), engine, compression combo, and provider. Hover over charts for details. Use the time selector to view different time periods.", "searchAnalyticsTotalSearches": "Búsquedas totales", "searchAnalyticsCacheHitRate": "Tasa de aciertos de caché", "searchAnalyticsTotalCost": "Costo Total", @@ -1970,78 +1975,78 @@ "providerUtilizationLatestSnapshot": "Instantánea de la última cuota", "providerUtilizationRemainingCapacity": "Capacidad restante", "utilizationRange": { - "1h": "Última hora", - "24h": "Últimas 24 horas", - "7d": "Últimos 7 días", - "30d": "Últimos 30 días" + "1h": "Last hour", + "24h": "Last 24 hours", + "7d": "Last 7 days", + "30d": "Last 30 days" }, - "providerUtilizationGlobalView": "Vista global", - "providerUtilizationAccountSplit": "Desglose por cuenta", - "providerUtilizationLoading": "Cargando datos de utilización…", - "retrying": "Reintentando…", - "retry": "Reintentar", - "providerUtilizationNoDataDescription": "Las instantáneas de cuota del proveedor aparecerán aquí después de que se recopilen los datos de utilización.", - "providerUtilizationStepConnect": "Conecta proveedores a través de OAuth o claves de API en Proveedores", - "providerUtilizationStepEnable": "Habilita el seguimiento de cuotas usando el proveedor en un combo o solicitud directa", - "providerUtilizationStepAutomatic": "Los datos aparecerán automáticamente a medida que se recopilen las instantáneas de cuota", - "statusExhausted": "Agotado", - "statusLow": "Bajo", - "statusHealthy": "Saludable", - "remainingQuota": "Cuota restante", - "routeTraceTitle": "Vista de traza de ruta", - "routeTraceDescription": "Inspecciona la traza de solicitud persistida: destino seleccionado, factores de enrutamiento, evidencia de respaldo, reproducción de puntuación actual, latencia, tokens y estado del destino.", - "routeTraceRequestLog": "Registro de solicitud", - "routeWeight": "Peso {weight}%", - "routeNoRelatedEvidence": "Aún no se ha persistido evidencia del destino relacionado.", - "unknown": "desconocido", - "selected": "Seleccionado", - "routeNoStepId": "sin id de paso", - "routeNoStep": "sin paso", - "routeMatchesTopTarget": "Coincide con el destino principal actual", - "routeDiffersFromTop": "Difiere del principal actual", - "routeTargetMissingNow": "Falta el destino ahora", - "routeNotComboRouted": "No enrutado por combo", - "routeWhyTarget": "¿Por qué este destino?", - "routeWhyTargetSubtitle": "Metadatos exactos de tiempo de ejecución más reproducción de puntuación de solo lectura", - "routeExactRuntimeLog": "Registro exacto de tiempo de ejecución", - "routeCallLogsExact": "call_logs exacto", - "routeReadOnlyRecompute": "Recálculo de solo lectura", - "routeRuntimeRankNow": "Clasificación de tiempo de ejecución actual", - "routeRuntimeScoreNow": "Puntuación de tiempo de ejecución actual", - "routeWouldSelectNow": "Seleccionaría ahora", - "routeNoRecomputeCandidates": "No se puede recalcular la clasificación de candidatos de combo para esta solicitud.", - "runtime": "Tiempo de ejecución", - "routeTopNow": "Principal actual", - "routeFetchLogsFailed": "Error al obtener los registros de solicitudes", - "routeExplainFailed": "Error al explicar la ruta", - "direct": "directo", - "routeUnableToLoad": "No se puede cargar la explicación de la ruta", - "routeNoRequestLogs": "No hay registros de solicitudes disponibles", - "routeNoRequestLogsDescription": "Envíe tráfico a través de OmniRoute primero. Las explicaciones de ruta se generan a partir de registros de llamadas estructurados persistidos.", - "routeDecisionSummary": "Resumen de la decisión", - "routeConfidence": "{confidence} de confianza", - "routeScore": "Puntuación de ruta", - "latency": "Latencia", - "routeRecentSuccess": "Éxito reciente", - "routeAvgTargetLatency": "Latencia promedio del destino", - "routeSelectedTarget": "Destino seleccionado", - "provider": "Proveedor", - "model": "Modelo", - "account": "Cuenta", - "connection": "Conexión", + "providerUtilizationGlobalView": "Global View", + "providerUtilizationAccountSplit": "Account Split", + "providerUtilizationLoading": "Loading utilization data…", + "retrying": "Retrying…", + "retry": "Retry", + "providerUtilizationNoDataDescription": "Provider quota snapshots will appear here after utilization data is collected.", + "providerUtilizationStepConnect": "Connect providers through OAuth or API keys in Providers", + "providerUtilizationStepEnable": "Enable quota tracking by using the provider in a combo or direct request", + "providerUtilizationStepAutomatic": "Data will appear automatically as quota snapshots are collected", + "statusExhausted": "Exhausted", + "statusLow": "Low", + "statusHealthy": "Healthy", + "remainingQuota": "Remaining quota", + "routeTraceTitle": "Route Trace View", + "routeTraceDescription": "Inspect the persisted request trace: selected target, routing factors, fallback evidence, current scoring replay, latency, tokens and target health.", + "routeTraceRequestLog": "Request log", + "routeWeight": "Weight {weight}%", + "routeNoRelatedEvidence": "No related target evidence persisted yet.", + "unknown": "unknown", + "selected": "Selected", + "routeNoStepId": "no step id", + "routeNoStep": "no step", + "routeMatchesTopTarget": "Matches current top target", + "routeDiffersFromTop": "Differs from current top", + "routeTargetMissingNow": "Target missing now", + "routeNotComboRouted": "Not combo routed", + "routeWhyTarget": "Why this target?", + "routeWhyTargetSubtitle": "Exact runtime metadata plus read-only scoring replay", + "routeExactRuntimeLog": "Exact runtime log", + "routeCallLogsExact": "call_logs exact", + "routeReadOnlyRecompute": "Read-only recompute", + "routeRuntimeRankNow": "Runtime rank now", + "routeRuntimeScoreNow": "Runtime score now", + "routeWouldSelectNow": "Would select now", + "routeNoRecomputeCandidates": "No combo candidate ranking can be recomputed for this request.", + "runtime": "Runtime", + "routeTopNow": "Top now", + "routeFetchLogsFailed": "Failed to fetch request logs", + "routeExplainFailed": "Failed to explain route", + "direct": "direct", + "routeUnableToLoad": "Unable to load route explanation", + "routeNoRequestLogs": "No request logs available", + "routeNoRequestLogsDescription": "Send traffic through OmniRoute first. Route explanations are generated from persisted structured call logs.", + "routeDecisionSummary": "Decision summary", + "routeConfidence": "{confidence} confidence", + "routeScore": "Route score", + "latency": "Latency", + "routeRecentSuccess": "Recent success", + "routeAvgTargetLatency": "Avg target latency", + "routeSelectedTarget": "Selected target", + "provider": "Provider", + "model": "Model", + "account": "Account", + "connection": "Connection", "combo": "Combo", - "routeStep": "Paso", + "routeStep": "Step", "tokens": "Tokens", "notAvailable": "n/a", - "routeTokenCounts": "{input} entrada · {output} salida", - "routeEvidence": "Evidencia", - "routeFactors": "Factores de enrutamiento", - "routeFactorsSubtitle": "Señales ponderadas utilizadas para esta explicación", - "routeFallbackTimeline": "Cronología de respaldo y destino", - "routeFallbackTimelineSubtitle": "Inferido a partir de los registros de llamadas persistidos en torno a esta solicitud", - "routeRecommendations": "Recomendaciones", - "routeLimitations": "Limitaciones", - "routeNoKnownLimitations": "No hay limitaciones conocidas para esta explicación." + "routeTokenCounts": "{input} in · {output} out", + "routeEvidence": "Evidence", + "routeFactors": "Routing factors", + "routeFactorsSubtitle": "Weighted signals used for this explanation", + "routeFallbackTimeline": "Fallback and target timeline", + "routeFallbackTimelineSubtitle": "Inferred from persisted call logs around this request", + "routeRecommendations": "Recommendations", + "routeLimitations": "Limitations", + "routeNoKnownLimitations": "No known limitations for this explanation." }, "apiManager": { "title": "Claves API", @@ -2096,9 +2101,9 @@ "ownUsageVisibilityDesc": "Permite que esta clave llame a su endpoint de estado para ver su uso en USD, porcentaje de presupuesto y totales de tokens.", "sharedAccountQuotaVisibility": "Cuota de cuenta compartida", "sharedAccountQuotaVisibilityDesc": "Permite que esta clave vea la cuota de cuenta upstream compartida cuando hay una conexión explícita configurada.", - "localUsageCommand": "Permitir comando de uso local", - "localUsageCommandDesc": "Permite que esta clave de API use @@om-usage para recuperar información de uso y cuota en caché sin llamar a un proveedor ascendente.", - "localUsageCommandBadge": "Cmd de uso", + "localUsageCommand": "Allow local usage command", + "localUsageCommandDesc": "Allows this API key to use @@om-usage to retrieve cached usage and quota information without calling an upstream provider.", + "localUsageCommandBadge": "Usage cmd", "keyCreated": "Clave API creada", "keyCreatedSuccess": "¡Clave creada exitosamente!", "keyCreatedNote": "Copie y almacene esta clave ahora; no se volverá a mostrar.", @@ -2109,11 +2114,11 @@ "endpointsRestricted": "Restricted to {count} endpoint{count, plural, one {} other {s}}.", "autoResolve": "Auto-Resolve", "autoResolveDesc": "Auto-resolve ambiguous model names to native provider for this API key.", - "streamDefaultMode": "Compatibilidad predeterminada de stream", - "streamDefaultModeDesc": "Controla los indicadores `stream` omitidos para esta clave. El modo JSON devuelve respuestas sin streaming a menos que el cliente solicite SSE explícitamente.", - "streamDefaultLegacy": "Heredado", - "streamDefaultJson": "Compatible con JSON", - "streamDefaultBadge": "Stream JSON predeterminado", + "streamDefaultMode": "Stream Default Compatibility", + "streamDefaultModeDesc": "Controls omitted `stream` flags for this key. JSON mode returns non-streaming responses unless the client explicitly requests SSE.", + "streamDefaultLegacy": "Legacy", + "streamDefaultJson": "JSON Compatible", + "streamDefaultBadge": "JSON stream default", "keyActive": "Key Active", "keyActiveDesc": "Enable or disable this API key. Disabled keys are immediately rejected with 403.", "accessSchedule": "Access Schedule", @@ -2158,10 +2163,10 @@ "copyMaskedKey": "Copiar clave enmascarada", "keyOnlyAvailableAtCreation": "Full key available only at creation time — copy it when you first create the key", "modelsCount": "{count, plural, one {# model} other {# models}}", - "devicesCount": "{count, plural, one {# dispositivo} other {# dispositivos}}", - "devicesTooltip": "{count, plural, one {# dispositivo con IP/User-Agent distinto visto con esta clave (últimos 30 min)} other {# dispositivos con IP/User-Agent distintos vistos con esta clave (últimos 30 min)}}", + "devicesCount": "{count, plural, one {# device} other {# devices}}", + "devicesTooltip": "{count, plural, one {# distinct IP/User-Agent device seen with this key (last 30 min)} other {# distinct IP/User-Agent devices seen with this key (last 30 min)}}", "lastUsedOn": "Último: {date}", - "viewCostsFor": "Ver costos de {name}", + "viewCostsFor": "View costs for {name}", "editPermissions": "Editar permisos", "deleteKey": "Eliminar clave", "regenerateKey": "Regenerar clave", @@ -2172,19 +2177,19 @@ "models": "{count} modelos", "permissionsTitle": "Permisos: {name}", "allowAllDesc": "Esta clave puede acceder a todos los modelos disponibles.", - "restrictLoading": "Cargando catálogo de modelos…", - "restrictCatalogUnavailable": "Catálogo de modelos no disponible; esta clave tiene {selectedCount} restricciones de modelos seleccionadas.", + "restrictLoading": "Loading model catalog…", + "restrictCatalogUnavailable": "Model catalog unavailable; this key has {selectedCount} selected model restrictions.", "restrictDesc": "Esta clave puede acceder a {selectedCount} de {totalModels} modelos.", "selectedCount": "{count} seleccionado", "maxActiveSessions": "Sesiones activas máximas", - "maxActiveSessionsDescription": "0 = ilimitado. Devuelve 429 cuando esta clave supera las sesiones persistentes simultáneas.", - "throttleDelay": "Retardo de limitación", - "throttleDelayDescription": "Añade un retardo fijo antes de que se enruten las solicitudes para esta clave. 0 = sin ralentización.", - "expandClaudeCodeFamilies": "Expandir familias de Claude Code", - "removeClaudeCodeDefault": "Eliminar valor predeterminado de Claude Code", - "allowedCombos": "Combinaciones permitidas", - "allCombosAllowed": "Esta clave puede usar cualquier combinación.", - "restrictedComboCount": "Restringido a {count, plural, one {# combinación} other {# combinaciones}}.", + "maxActiveSessionsDescription": "0 = unlimited. Return 429 when this key exceeds concurrent sticky sessions.", + "throttleDelay": "Throttle Delay", + "throttleDelayDescription": "Add a fixed delay before requests for this key are routed. 0 = no slowdown.", + "expandClaudeCodeFamilies": "Expand Claude Code families", + "removeClaudeCodeDefault": "Remove Claude Code default", + "allowedCombos": "Allowed Combos", + "allCombosAllowed": "This key can use any combo.", + "restrictedComboCount": "Restricted to {count, plural, one {# combo} other {# combos}}.", "apiManagerCustomRateLimits": "Límites de tarifas personalizadas", "apiManagerCustomRateLimitsDesc": "Anule los límites predeterminados globales. Déjelo vacío para usar los valores predeterminados.", "apiManagerRateLimitRequestsPlaceholder": "Solicitudes", @@ -2203,24 +2208,24 @@ "filterStatus": "ESTADO", "filterType": "TIPO", "filterAll": "Todos", - "filterStatusActive": "Activo", - "filterStatusDisabled": "Desactivado", - "filterStatusBanned": "Baneado", - "filterStatusExpired": "Expirado", - "filterTypeStandard": "Estándar", - "filterTypeManage": "Administrar", - "filterTypeRestricted": "Restringido", - "shownOf": "{shown} de {total} mostrados", - "emptyFilterTitle": "Ninguna clave coincide con tus filtros", - "emptyFilterClear": "Borrar filtros", - "disableNonPublicModels": "Deshabilitar modelos no públicos", - "disableNonPublicModelsDesc": "Rechazar solicitudes de modelos que no se hayan detectado o no estén marcados como públicos en el catálogo del proveedor", - "normalKeysSection": "Claves normales", - "quotaKeysSection": "Claves de cuota", - "bypassProviderQuota": "Omitir límites de cuota del proveedor", - "bypassProviderQuotaDescription": "Permite que esta clave ignore la política de límites del proveedor/cuenta ascendente durante el enrutamiento. Las cuotas en USD de la clave de API se siguen aplicando.", - "quotaPill": "CUOTA", - "quotaModeOnly": "Solo qtSd" + "filterStatusActive": "Active", + "filterStatusDisabled": "Disabled", + "filterStatusBanned": "Banned", + "filterStatusExpired": "Expired", + "filterTypeStandard": "Standard", + "filterTypeManage": "Manage", + "filterTypeRestricted": "Restricted", + "shownOf": "{shown} of {total} shown", + "emptyFilterTitle": "No keys match your filters", + "emptyFilterClear": "Clear filters", + "disableNonPublicModels": "Disable Non-Public Models", + "disableNonPublicModelsDesc": "Reject requests for models that are not discovered or not marked as public in the provider catalog", + "normalKeysSection": "Normal keys", + "quotaKeysSection": "Quota keys", + "bypassProviderQuota": "Bypass provider quota cutoffs", + "bypassProviderQuotaDescription": "Allows this key to ignore upstream provider/account cutoff policy during routing. API key USD quotas still apply.", + "quotaPill": "QUOTA", + "quotaModeOnly": "qtSd-only" }, "auditLog": { "title": "Registro de auditoría", @@ -2259,75 +2264,75 @@ "videoDescription": "Create videos with AnimateDiff, Stable Video Diffusion via ComfyUI or SD WebUI.", "musicDescription": "Compose music using Stable Audio Open or MusicGen via ComfyUI.", "kinds": { - "embedding": "Embedding", + "embedding": "Incrustación (Embedding)", "image": "Imagen", - "imageToText": "Imagen a texto", - "tts": "Texto a voz", - "stt": "Voz a texto", - "webSearch": "Búsqueda web", - "webFetch": "Extracción web", - "video": "Video", + "imageToText": "Imagen a Texto", + "tts": "Texto a Voz (TTS)", + "stt": "Voz a Texto (STT)", + "webSearch": "Web Search", + "webFetch": "Web Fetch", + "video": "Vídeo", "music": "Música", "ocr": "OCR" }, - "noProviders": "Aún no hay proveedores configurados para este tipo.", - "addConnection": "Añadir conexión", - "backToProviders": "Volver a proveedores", - "connections": "{count} conexiones", - "noConnections": "Aún no hay conexiones — añade una desde la página del proveedor.", - "loading": "Cargando...", - "suggestedModels": "Modelos sugeridos del proveedor", - "imageGeneration": "Generación de imágenes", - "imageToText": "Imagen a texto", - "imageToTextComingSoon": "El playground integrado de imagen a texto estará disponible cuando se implemente /api/v1/images/understanding.", - "disabled": "Deshabilitado", - "videoGeneration": "Generación de video", - "musicGeneration": "Generación de música", - "textToSpeech": "Texto a voz", - "transcription": "Transcripción", - "imagePromptPlaceholder": "Un paisaje sereno con montañas al atardecer...", - "videoPromptPlaceholder": "Un timelapse de una flor floreciendo...", - "musicPromptPlaceholder": "Música electrónica animada con pads de sintetizador...", - "speechTextPlaceholder": "¡Hola! Te damos la bienvenida a OmniRoute, tu pasarela de IA inteligente...", - "transcriptionPlaceholder": "Sube un archivo de audio para transcribir...", - "noImagesReturned": "No se devolvieron imágenes. Es posible que el proveedor haya aceptado la solicitud pero haya devuelto datos vacíos.", - "generatedImageAlt": "Imagen generada {index}", - "save": "Guardar", - "enterTextToSynthesize": "Por favor, introduce texto para sintetizar.", - "selectAudioToTranscribe": "Por favor, selecciona un archivo de audio para transcribir.", - "noSpeechDetected": "No se detectó voz en el archivo de audio. Si subiste música o un archivo en silencio, prueba con un archivo de audio con palabras habladas. Proveedor: \"{provider}\".", - "emptyTranscription": "La transcripción devolvió texto vacío. Es posible que el audio no contenga voz reconocible o que la clave de API de \"{provider}\" no sea válida. Consulta Panel de control → Registros → Proxy para obtener más detalles.", - "topazRequiresImage": "Topaz requiere una imagen de entrada.", - "enterPrompt": "Por favor, introduce un prompt.", - "enhanceThisImage": "Mejorar esta imagen", - "failedToReadFile": "Error al leer el archivo", - "generationFailed": "Error en la generación", - "requestFailed": "Error en la solicitud ({status})", - "provider": "Proveedor", - "credentialsRequired": "Requiere la clave de API de en Proveedores", - "voice": "Voz", - "format": "Formato", - "audioVideoFile": "Archivo de audio / vídeo", - "fileTooLarge": "Archivo demasiado grande ({size}). Máximo permitido: {max}.", - "audioVideoFileHint": "Admite archivos de audio y vídeo de hasta 4 GB", - "sourceImage": "Imagen de origen", - "sourceImageHint": "Opcional para flujos de trabajo de imagen a imagen, edición y escalado.", - "maskImage": "Imagen de máscara", - "maskImageHint": "Opcional. Utilizado por modelos de tipo inpaint que admiten máscaras.", - "text": "Texto", - "promptOptional": "Prompt (opcional)", - "enhancementInstructionsPlaceholder": "Instrucciones de mejora opcionales...", - "synthesizing": "Sintetizando...", - "transcribing": "Transcribiendo...", - "synthesizeSpeech": "Sintetizar voz", - "transcribeAudio": "Transcribir audio", - "generateModality": "Generar {modality}", - "apiKeyRequired": "Clave de API requerida", - "configureApiKeys": "Configura las claves de API en Proveedores", - "downloadFormat": "Descargar {format}", - "noTextReturned": "No se devolvió ningún texto", - "wordTimestamps": "Marcas de tiempo a nivel de palabra ({count} palabras)", - "providerCount": "{count} proveedores" + "noProviders": "No providers configured for this kind yet.", + "addConnection": "Add Connection", + "backToProviders": "Back to Providers", + "connections": "{count} Connections", + "noConnections": "No connections yet — add one from the provider page.", + "loading": "Loading...", + "suggestedModels": "Suggested models from provider", + "imageGeneration": "Image Generation", + "imageToText": "Image to Text", + "imageToTextComingSoon": "The inline Image-to-Text playground will be available when /api/v1/images/understanding is implemented.", + "disabled": "Disabled", + "videoGeneration": "Video Generation", + "musicGeneration": "Music Generation", + "textToSpeech": "Text to Speech", + "transcription": "Transcription", + "imagePromptPlaceholder": "A serene landscape with mountains at sunset...", + "videoPromptPlaceholder": "A timelapse of a flower blooming...", + "musicPromptPlaceholder": "Upbeat electronic music with synth pads...", + "speechTextPlaceholder": "Hello! Welcome to OmniRoute, your intelligent AI gateway...", + "transcriptionPlaceholder": "Upload an audio file to transcribe...", + "noImagesReturned": "No images returned. The provider might have accepted the request but returned empty data.", + "generatedImageAlt": "Generated image {index}", + "save": "Save", + "enterTextToSynthesize": "Please enter text to synthesize.", + "selectAudioToTranscribe": "Please select an audio file to transcribe.", + "noSpeechDetected": "No speech detected in the audio file. If you uploaded music or a silent file, try an audio file with spoken words. Provider: \"{provider}\".", + "emptyTranscription": "Transcription returned empty text. The audio may contain no recognizable speech, or the \"{provider}\" API key may be invalid. Check Dashboard → Logs → Proxy for details.", + "topazRequiresImage": "Topaz requires an input image.", + "enterPrompt": "Please enter a prompt.", + "enhanceThisImage": "Enhance this image", + "failedToReadFile": "Failed to read file", + "generationFailed": "Generation failed", + "requestFailed": "Request failed ({status})", + "provider": "Provider", + "credentialsRequired": "Requires API key in Providers", + "voice": "Voice", + "format": "Format", + "audioVideoFile": "Audio / Video File", + "fileTooLarge": "File too large ({size}). Maximum allowed: {max}.", + "audioVideoFileHint": "Supports audio and video files up to 4 GB", + "sourceImage": "Source Image", + "sourceImageHint": "Optional for image-to-image, editing and upscale workflows.", + "maskImage": "Mask Image", + "maskImageHint": "Optional. Used by inpaint-style models that support masks.", + "text": "Text", + "promptOptional": "Prompt (optional)", + "enhancementInstructionsPlaceholder": "Optional enhancement instructions...", + "synthesizing": "Synthesizing...", + "transcribing": "Transcribing...", + "synthesizeSpeech": "Synthesize Speech", + "transcribeAudio": "Transcribe Audio", + "generateModality": "Generate {modality}", + "apiKeyRequired": "API Key Required", + "configureApiKeys": "Configure API keys in Providers", + "downloadFormat": "Download {format}", + "noTextReturned": "No text returned", + "wordTimestamps": "Word-level timestamps ({count} words)", + "providerCount": "{count} providers" }, "search": { "searchQuery": "Search Query", @@ -2408,8 +2413,8 @@ "freeQuota": "Free quota/mo", "scrapeUrl": "URL to scrape", "scrapeUrlPlaceholder": "https://example.com", - "scrapeUrlRequired": "La URL es obligatoria", - "scrapeUrlInvalid": "URL no válida — debe comenzar con http:// o https://", + "scrapeUrlRequired": "URL is required", + "scrapeUrlInvalid": "Invalid URL — it must start with http:// or https://", "scrapeExtract": "Extract", "scrapeExtracting": "Extracting…", "scrapeFullPage": "Full page", @@ -2423,8 +2428,8 @@ "scrapeMetadata": "Metadata", "scrapeProvider": "Provider", "scrapeSize": "Size", - "scrapeEmptyState": "Introduce una URL para extraer su contenido", - "scrapeProvidersAvailable": "Proveedores disponibles: Firecrawl, Jina Reader, Tavily, TinyFish.", + "scrapeEmptyState": "Enter a URL to extract its content", + "scrapeProvidersAvailable": "Available providers: Firecrawl, Jina Reader, Tavily, TinyFish.", "compareRun": "Compare", "compareRunning": "Comparing…", "autoProvider": "Auto (cheapest)", @@ -2435,78 +2440,78 @@ "rerankModelLabel": "Rerank model", "noneOption": "None", "size": "Size", - "configurationPane": "Panel de configuración", - "configuration": "Configuración", - "status": "Estado", - "compareProviderHint": "Selecciona hasta 4 proveedores en la pestaña Comparar para compararlos lado a lado.", - "history": "Historial", - "historyHint": "El historial está disponible en la pestaña Buscar.", - "noActiveProvider": "No hay ningún proveedor de búsqueda activo", - "configureMoreProviders": "Configurar más proveedores", - "links": "Enlaces", - "contentTruncated": "Contenido truncado a 256 KB (tamaño original: {size})", - "viewFullRaw": "Ver todo el contenido sin procesar", - "rawScrapedContent": "Contenido extraído sin procesar", - "rawContent": "Contenido sin procesar — {size}", - "closeRawModal": "Cerrar modal de contenido sin procesar", + "configurationPane": "Configuration pane", + "configuration": "Configuration", + "status": "Status", + "compareProviderHint": "Select up to 4 providers on the Compare tab to compare them side by side.", + "history": "History", + "historyHint": "History is available on the Search tab.", + "noActiveProvider": "No active search provider", + "configureMoreProviders": "Configure more providers", + "links": "Links", + "contentTruncated": "Content truncated to 256 KB (original size: {size})", + "viewFullRaw": "View full raw content", + "rawScrapedContent": "Raw scraped content", + "rawContent": "Raw content — {size}", + "closeRawModal": "Close raw content modal", "httpError": "Error {status}", - "failed": "Fallido", - "requestFailed": "Error en la solicitud", + "failed": "Failed", + "requestFailed": "Request failed", "embedding": "Embedding", - "embeddingSample": "¡Hola, mundo!", - "image": "Imagen", - "imageSample": "Un paisaje sereno con montañas al atardecer", - "music": "Música", - "musicSample": "Piano de jazz alegre con percusión ligera", - "noAudioUrl": "No hay URL de audio en la respuesta: {response}", - "documentUrl": "URL del documento", - "fileTooLarge25Mb": "Archivo demasiado grande — máx. 25 MB", - "selectAudioFirst": "Por favor, selecciona primero un archivo de audio.", - "speechToText": "Voz a texto", - "chooseFile": "Elegir archivo…", - "audioFormats25Mb": "mp3, wav, m4a, ogg, flac — máx. 25 MB", - "textToSpeech": "Texto a voz", - "ttsSample": "Hola, esta es una prueba de texto a voz.", + "embeddingSample": "Hello, world!", + "image": "Image", + "imageSample": "A serene landscape with mountains at sunset", + "music": "Music", + "musicSample": "Upbeat jazz piano with light percussion", + "noAudioUrl": "No audio URL in response: {response}", + "documentUrl": "Document URL", + "fileTooLarge25Mb": "File too large — max 25 MB", + "selectAudioFirst": "Please select an audio file first.", + "speechToText": "Speech to Text", + "chooseFile": "Choose file…", + "audioFormats25Mb": "mp3, wav, m4a, ogg, flac — max 25 MB", + "textToSpeech": "Text to Speech", + "ttsSample": "Hello, this is a text-to-speech test.", "video": "Video", - "videoSample": "Un time-lapse de nubes sobre una cadena montañosa", + "videoSample": "A time-lapse of clouds over a mountain range", "webFetch": "Web Fetch", - "webSearchSample": "¿Qué es el gateway de IA OmniRoute?", - "noActiveProviderDescription": "No hay ningún proveedor de búsqueda activo. Configure uno en Proveedores.", - "configureProviders": "Configurar proveedores", - "compareQuery": "Consulta a comparar", - "compareQueryPlaceholder": "tendencias de inteligencia artificial 2026", - "selectedProviders": "Proveedores ({count} seleccionados):", - "selectAll": "Seleccionar todo", - "clear": "Limpiar", - "maxCompareProviders": "Se puede comparar un máximo de {count} proveedores a la vez.", - "compareResults": "Resultados — “{query}”", - "resultCount": "{count} resultados", - "noResults": "Sin resultados", - "sharedResultTitle": "En común con otro proveedor", - "sharedResult": "En común", - "overlapSummary": "{first} vs {second}: {overlap} en común", - "compareEmptyTitle": "Seleccione proveedores e introduzca una consulta para comparar", - "compareEmptyDescription": "Los resultados se mostrarán lado a lado con la latencia, el coste y el solapamiento de URL" + "webSearchSample": "What is OmniRoute AI gateway?", + "noActiveProviderDescription": "No active search provider. Configure one in Providers.", + "configureProviders": "Configure providers", + "compareQuery": "Query to compare", + "compareQueryPlaceholder": "artificial intelligence trends 2026", + "selectedProviders": "Providers ({count} selected):", + "selectAll": "Select all", + "clear": "Clear", + "maxCompareProviders": "A maximum of {count} providers can be compared at once.", + "compareResults": "Results — “{query}”", + "resultCount": "{count} results", + "noResults": "No results", + "sharedResultTitle": "In common with another provider", + "sharedResult": "In common", + "overlapSummary": "{first} vs {second}: {overlap} in common", + "compareEmptyTitle": "Select providers and enter a query to compare", + "compareEmptyDescription": "Results will be shown side by side with latency, cost, and URL overlap" }, "cliTools": { "title": "Herramientas CLI", - "classifierCompatTitle": "Compatibilidad del clasificador de permisos automáticos", - "classifierCompatDescription": "Cortocircuitar el clasificador de seguridad --permission-mode auto de Claude Code con una respuesta de autorización sintética para que las rutas de respaldo no fallen en modo cerrado. Desactivado por defecto.", - "classifierCompatCycle": "Ciclo: desactivado → auto → siempre", - "classifierCompatLoadFailed": "Error al cargar la configuración", + "classifierCompatTitle": "Auto-permission classifier compatibility", + "classifierCompatDescription": "Short-circuit Claude Code’s --permission-mode auto security classifier with a synthetic allow response so fallback routes do not fail closed. Off by default.", + "classifierCompatCycle": "Cycle: off → auto → always", + "classifierCompatLoadFailed": "Failed to load setting", "classifierCompatMode": { - "off": "Desactivado", + "off": "Off", "auto": "Auto", - "always": "Siempre" + "always": "Always" }, - "failedSave": "Error al guardar", - "profileSyncTitle": "Sincronización automática de perfiles de CLI", - "profileSyncDescription": "Una vez sincronizados los modelos de los proveedores, regenerar automáticamente los perfiles de las herramientas de CLI a partir del catálogo activo. Desactivado por defecto: solo se escriben los archivos de perfil; la configuración activa/predeterminada nunca se modifica.", - "profileSyncLoadFailed": "Error al cargar las configuraciones", - "codexProfiles": "Perfiles de Codex", - "codexProfilesDescription": "Regenerar ~/.codex/*.config.toml después de la detección de modelos.", - "claudeProfiles": "Perfiles de Claude Code", - "claudeProfilesDescription": "Regenerar cada ~/.claude/profiles/…/settings.json después de la detección de modelos.", + "failedSave": "Failed to save", + "profileSyncTitle": "CLI profile auto-sync", + "profileSyncDescription": "After provider models are synchronized, automatically regenerate CLI tool profiles from the live catalog. Off by default — only profile files are written; the active/default configuration is never changed.", + "profileSyncLoadFailed": "Failed to load settings", + "codexProfiles": "Codex profiles", + "codexProfilesDescription": "Regenerate ~/.codex/*.config.toml after model discovery.", + "claudeProfiles": "Claude Code profiles", + "claudeProfilesDescription": "Regenerate each ~/.claude/profiles/…/settings.json after model discovery.", "noActiveProviders": "No hay proveedores activos", "noActiveProvidersDesc": "Primero agregue y conecte proveedores para configurar las herramientas CLI.", "mapModels": "Modelos de mapas", @@ -2516,17 +2521,17 @@ "instructions": "Instrucciones", "modelMapping": "Mapeo de modelos", "reasoningEffort": "Esfuerzo de razonamiento para {model}", - "effortNone": "Ninguno", - "effortLow": "Bajo", - "effortMedium": "Medio", - "effortHigh": "Alto", - "effortExtraHigh": "Extra alto", - "effortMax": "Máximo", + "effortNone": "None", + "effortLow": "Low", + "effortMedium": "Medium", + "effortHigh": "High", + "effortExtraHigh": "Extra high", + "effortMax": "Max", "effortUltra": "Ultra", "wireApi": "Wire API", - "modelAliases": "Alias de modelos", - "addModel": "Agregar modelo", - "routeModelPlaceholder": "Enrutar {model} a...", + "modelAliases": "Model aliases", + "addModel": "Add model", + "routeModelPlaceholder": "Route {model} to...", "baseUrl": "URL básica", "apiKey": "Clave API", "configured": "Configurado", @@ -2584,13 +2589,13 @@ "mappingsSaved": "¡Asignaciones guardadas!", "failedSaveMappings": "No se pudieron guardar las asignaciones", "reasoningEffortDefault": "Predeterminado", - "reasoningEffortHint": "Predeterminado conserva el esfuerzo de razonamiento enviado por el agente", + "reasoningEffortHint": "El valor predeterminado conserva el esfuerzo de razonamiento enviado por el agente", "reasoningEffortTier": { - "none": "Ninguno", - "low": "Bajo", - "medium": "Medio", - "high": "Alto", - "xhigh": "Muy alto" + "none": "None", + "low": "Low", + "medium": "Medium", + "high": "High", + "xhigh": "XHigh" }, "howItWorks": "Cómo funciona:", "antigravityHowWorksDesc": "Antigravity envía solicitudes al punto final de Google. MITM los intercepta y los redirige a OmniRoute.", @@ -2693,19 +2698,19 @@ "copilot": "Úselo cuando desee una experiencia de usuario estilo chat Copilot mientras aplica las claves de OmniRoute y las reglas de enrutamiento.", "amp": "Use when you want Amp CLI routed through OmniRoute with stable shorthand aliases and OpenAI-compatible setup.", "hermes": "Úselo cuando necesite un asistente de IA nativo de terminal liviano para tareas rápidas.", - "hermes-agent": "Úselo cuando necesite Hermes Agent (de Nousresearch) con modelos predeterminados, de delegación, de visión y auxiliares enrutados a través de OmniRoute.", + "hermes-agent": "Utilizar cuando necesites el agente Hermes (de Nousresearch) con modelos predeterminados, de delegación, visión y auxiliares enrutados mediante OmniRoute.", "custom": "Úselo para implementaciones de herramientas personalizadas o configuraciones genéricas compatibles con OpenAI." }, "toolDescriptions": { "antigravity": "IDE antigravedad de Google con MITM", "claude": "CLI del Código Antrópico Claude", "codex": "CLI del Códice OpenAI", - "grok-build": "Agente de programación TUI xAI Grok Build con soporte para proveedor personalizado", + "grok-build": "xAI Grok Build TUI coding agent with custom provider support", "droid": "Asistente de IA de droide de fábrica", "openclaw": "Asistente de IA Open Claw", "cline": "CLI del asistente de codificación AI de Cline", "kilo": "CLI del Asistente de Inteligencia Artificial de Kilo Code", - "qwen": "Qwen Code CLI", + "qwen": "Alibaba Qwen Code CLI", "cursor": "Editor de código AI del cursor", "continue": "Continuar Asistente de IA", "opencode": "OpenCode AI coding agent (Terminal)", @@ -2716,22 +2721,22 @@ "hermes": "Asistente de terminal de IA de Hermes", "hermes-agent": "Hermes Agent (de Nousresearch) - IA de terminal avanzada con soporte multimodelo (delegación, visión, compresión, etc.)", "custom": "Generador de configuración CLI o SDK genérico compatible con OpenAI", - "aider": "CLI de programación en pareja con IA Aider con una URL base compatible con OpenAI", - "forge": "CLI del agente de programación ForgeCode con un proveedor personalizado", - "cursor-cli": "CLI de Cursor Agent en modo de agente headless", - "roo": "Asistente de IA Roo Code para VS Code", - "jcode": "Agente de programación de terminal jcode", - "deepseek-tui": "Agente de programación TUI de DeepSeek escrito en Rust", - "codewhale": "Agente de programación CodeWhale, el sucesor de DeepSeek TUI", - "smelt": "CLI del agente de programación Smelt", - "pi": "Agente de programación de terminal Pi ligero", - "crush": "Agente de programación de terminal Crush de Charm", - "goose": "CLI del agente autónomo Goose", - "interpreter": "CLI del agente de programación autónomo Open Interpreter", - "omp": "Agente de programación de terminal Oh My Pi", - "letta": "Agente de CLI Letta con memoria persistente y uso de herramientas", - "warp": "Terminal Warp AI con soporte para proveedor personalizado", - "agent-deck": "Orquestador multiagente Agent Deck" + "aider": "Aider AI pair-programming CLI with an OpenAI-compatible base URL", + "forge": "ForgeCode coding agent CLI with a custom provider", + "cursor-cli": "Cursor Agent CLI in headless agent mode", + "roo": "Roo Code AI assistant for VS Code", + "jcode": "jcode terminal coding agent", + "deepseek-tui": "DeepSeek TUI coding agent written in Rust", + "codewhale": "CodeWhale coding agent, the successor to DeepSeek TUI", + "smelt": "Smelt coding agent CLI", + "pi": "Lightweight Pi terminal coding agent", + "crush": "Crush terminal coding agent by Charm", + "goose": "Goose autonomous agent CLI", + "interpreter": "Open Interpreter autonomous coding agent CLI", + "omp": "Oh My Pi terminal coding agent", + "letta": "Letta CLI agent with persistent memory and tool use", + "warp": "Warp AI terminal with custom provider support", + "agent-deck": "Agent Deck multi-agent orchestrator" }, "guides": { "cursor": { @@ -2882,56 +2887,56 @@ "customCliEndpointHint": "Dirija cualquier cliente compatible con OpenAI a la URL base de OmniRoute /v1. El punto final de finalización del chat sin procesar es {endpoint}. Utilice el bloque JSON cuando la herramienta quiera un objeto proveedor, o el script env cuando lea variables OPENAI_*.", "customCliEnvBlockTitle": "Fragmento de entorno/shell", "customCliJsonBlockTitle": "Bloque JSON del proveedor", - "networkError": "Error de red", - "other": "Otro", - "preview": "Vista previa", - "refreshAll": "Actualizar todo", - "hermesRoleDefault": "Predeterminado (principal)", - "hermesRoleDefaultDesc": "Modelo de conversación principal", - "hermesRoleDelegation": "Delegación (subagentes)", - "hermesRoleDelegationDesc": "Modelo de orquestador y subagente", - "hermesRoleVision": "Visión", - "hermesRoleVisionDesc": "Comprensión de imágenes y capturas de pantalla", - "hermesRoleCompression": "Compresión", - "hermesRoleCompressionDesc": "Compresión y resumen de prompts", - "hermesRoleWebExtract": "Extracción web", - "hermesRoleWebExtractDesc": "Extracción de contenido de páginas web", - "hermesRoleSkillsHub": "Centro de habilidades", - "hermesRoleSkillsHubDesc": "Razonamiento de habilidades y uso de herramientas", - "hermesRoleApproval": "Aprobación", - "hermesRoleApprovalDesc": "Decisiones de seguridad y aprobación", - "hermesSelectBeforePreview": "Seleccione modelos para los roles, o asegúrese de que los roles estén cargados, antes de la vista previa.", - "hermesPreviewFailed": "Error al generar la vista previa", - "hermesSavedTo": "Guardado en {path}", - "hermesFirstSetupTitle": "Configurado por primera vez a través de OmniRoute el {date}", - "hermesSinceSetup": "{time} desde la configuración", + "networkError": "Network error", + "other": "Other", + "preview": "Preview", + "refreshAll": "Refresh all", + "hermesRoleDefault": "Default (main)", + "hermesRoleDefaultDesc": "Primary conversation model", + "hermesRoleDelegation": "Delegation (subagents)", + "hermesRoleDelegationDesc": "Orchestrator and sub-agent model", + "hermesRoleVision": "Vision", + "hermesRoleVisionDesc": "Image and screenshot understanding", + "hermesRoleCompression": "Compression", + "hermesRoleCompressionDesc": "Prompt compression and summarization", + "hermesRoleWebExtract": "Web Extract", + "hermesRoleWebExtractDesc": "Web page content extraction", + "hermesRoleSkillsHub": "Skills Hub", + "hermesRoleSkillsHubDesc": "Skills and tool-use reasoning", + "hermesRoleApproval": "Approval", + "hermesRoleApprovalDesc": "Safety and approval decisions", + "hermesSelectBeforePreview": "Select models for roles, or ensure the roles are loaded, before previewing.", + "hermesPreviewFailed": "Failed to generate preview", + "hermesSavedTo": "Saved to {path}", + "hermesFirstSetupTitle": "First set up via OmniRoute on {date}", + "hermesSinceSetup": "{time} since setup", "hermesConfiguredRoles": "{configured}/{total} roles", - "hermesQuickApply": "Aplique rápidamente el mismo modelo a todos los roles:", - "hermesApplyModelToAll": "Aplicar {model} a cada rol", - "hermesViaOmniRoute": "{provider} (a través de OmniRoute)", - "hermesNotOmniRoute": "{provider} (no OmniRoute)", - "hermesRemovePendingRole": "Eliminar este rol de los cambios pendientes", - "hermesApply": "Aplicar a Hermes Agent", - "hermesRolesWillUpdate": "{count, plural, one {# rol será actualizado} other {# roles serán actualizados}}", - "hermesPreviewPath": "Vista previa — se escribirá en ~/.hermes/config.yaml", - "hermesSaveDescription": "Guarda el modelo seleccionado para cada rol en", + "hermesQuickApply": "Quickly apply the same model to all roles:", + "hermesApplyModelToAll": "Apply {model} to every role", + "hermesViaOmniRoute": "{provider} (via OmniRoute)", + "hermesNotOmniRoute": "{provider} (not OmniRoute)", + "hermesRemovePendingRole": "Remove this role from pending changes", + "hermesApply": "Apply to Hermes Agent", + "hermesRolesWillUpdate": "{count, plural, one {# role will be updated} other {# roles will be updated}}", + "hermesPreviewPath": "Preview — will write to ~/.hermes/config.yaml", + "hermesSaveDescription": "Saves the selected model for each role into", "copilotConfigGenerator": "Generador de configuración de GitHub Copilot", - "copilotGeneratorDescriptionPrefix": "Genera el", - "copilotGeneratorDescriptionSuffix": "bloque para VS Code GitHub Copilot usando el patrón de proveedor de Azure. Seleccione los modelos que desee y luego copie el JSON en su archivo de configuración.", - "copilotCompatibilityWarning": "Esta configuración utiliza la solución alternativa del proveedor de Azure para listas de modelos personalizados. Probado con VS Code ≥ 1.109 y GitHub Copilot Chat ≥ v0.37. Las actualizaciones futuras de la extensión pueden cambiar este comportamiento.", + "copilotGeneratorDescriptionPrefix": "Generates the", + "copilotGeneratorDescriptionSuffix": "block for VS Code GitHub Copilot using the Azure vendor pattern. Select the models you want, then copy the JSON into your config file.", + "copilotCompatibilityWarning": "This configuration uses the Azure vendor workaround for custom model lists. Tested with VS Code ≥ 1.109 and GitHub Copilot Chat ≥ v0.37. Future extension updates may change this behavior.", "copilotApiKey": "Clave API", - "copilotSelectModels": "Seleccionar modelos ({selected}/{total})", - "selectAll": "Seleccionar todo", - "loadingModels": "Cargando modelos...", - "advancedOptions": "Opciones avanzadas", - "vision": "Visión", - "copilotCopyConfigForModels": "Copiar configuración ({count, plural, one {# modelo} other {# modelos}})", + "copilotSelectModels": "Select models ({selected}/{total})", + "selectAll": "Select all", + "loadingModels": "Loading models...", + "advancedOptions": "Advanced options", + "vision": "Vision", + "copilotCopyConfigForModels": "Copy config ({count, plural, one {# model} other {# models}})", "copilotFilterModelsPlaceholder": "Filtrar modelos...", "copilotMaxInputTokens": "Fichas de entrada máximas", "copilotMaxOutputTokens": "Fichas de salida máxima", "copilotToolCalling": "Llamada de herramientas", "copilotPasteInto": "Pegar en:", - "copilotReloadInstruction": "Luego reinicie VS Code y configure la clave API en el prompt de entrada.", + "copilotReloadInstruction": "Then reload VS Code and set the API key in the input prompt.", "wireApiChatCompletions": "Finalizaciones de chat (/chat/completions)", "wireApiResponses": "API de respuestas (/respuestas)" }, @@ -2961,8 +2966,8 @@ "leastLatency": "Menor latencia", "comboName": "Nombre combinado", "comboNamePlaceholder": "mi-combo", - "comboDescription": "Descripción", - "comboDescriptionPlaceholder": "Nota opcional que describe esta combinación", + "comboDescription": "Description", + "comboDescriptionPlaceholder": "Optional note describing this combo", "deleteConfirm": "¿Eliminar esta combinación?", "noCombosYet": "Aún no hay combinaciones", "comboCreated": "Combo creado exitosamente", @@ -2998,20 +3003,21 @@ "randomDesc": "Selección aleatoria uniforme y luego recurrir a los modelos restantes.", "leastUsedDesc": "Elige el modelo con menos solicitudes y equilibra la carga a lo largo del tiempo.", "costOptimizedDesc": "Rutas al modelo más barato primero según el precio", + "cacheOptimizedDesc": "Routes each reusable prompt prefix consistently to the same provider account", "resetAware": "RR con reconocimiento de reinicio", "resetAwareDesc": "Equilibra la cuota restante con los restablecimientos semanales y de 5 h, y luego realiza todos contra todos puntuaciones similares", "strictRandom": "Strict Random", "strictRandomDesc": "Shuffle deck — uses each model once before reshuffling", - "fusion": "Fusión", - "fusionDesc": "Envía el prompt a cada modelo del panel en paralelo, luego un modelo juez sintetiza una respuesta final", - "fusionJudgeModel": "Modelo juez", - "fusionJudgeModelHelp": "Modelo que sintetiza las respuestas del panel en una respuesta final. Dejar vacío para usar el primer modelo del panel.", - "fusionMinPanel": "Mínimo de panel", - "fusionMinPanelHelp": "Respuestas exitosas del panel requeridas antes de que los rezagados obtengan una ventana de gracia (por defecto 2).", - "fusionStragglerGraceMs": "Gracia para rezagados (ms)", - "fusionStragglerGraceMsHelp": "Cuánto tiempo esperar a los modelos lentos del panel una vez alcanzado el cuórum (por defecto 8000).", - "fusionPanelHardTimeoutMs": "Tiempo de espera estricto del panel (ms)", - "fusionPanelHardTimeoutMsHelp": "Límite absoluto para que un modelo colgado no detenga a todo el panel (por defecto 90000).", + "fusion": "Fusion", + "fusionDesc": "Fans the prompt to every panel model in parallel, then a judge model synthesizes one final answer", + "fusionJudgeModel": "Judge model", + "fusionJudgeModelHelp": "Model that synthesizes the panel answers into one final response. Leave empty to use the first panel model.", + "fusionMinPanel": "Min panel", + "fusionMinPanelHelp": "Successful panel answers required before stragglers get a grace window (default 2).", + "fusionStragglerGraceMs": "Straggler grace (ms)", + "fusionStragglerGraceMsHelp": "How long to wait for slow panel models once quorum is reached (default 8000).", + "fusionPanelHardTimeoutMs": "Panel hard timeout (ms)", + "fusionPanelHardTimeoutMsHelp": "Absolute cap so one hung model can't stall the whole panel (default 90000).", "models": "Modelos", "autoBalance": "Equilibrio automático", "advancedSettings": "Configuración avanzada", @@ -3033,45 +3039,45 @@ "moveDown": "Bajar", "removeModel": "Quitar", "saving": "Guardando...", - "liveNoProviders": "Aún no se han observado proveedores.", - "liveFleetDataHint": "Los datos de la flota llegan a través de eventos de combo en vivo.", - "liveActiveCount": "Activos ({count})", - "liveErrorCount": "Errores ({count})", - "liveInactiveCount": "Inactivos ({count})", - "liveNoRun": "No hay ninguna ejecución de combo disponible.", - "liveDataHint": "Los datos en vivo llegan a través del canal de combo WebSocket.", - "liveDisconnected": "Transmisión en vivo desactivada — WebSocket desconectado. Mostrando el último estado conocido.", - "liveSelectCombo": "Seleccionar combo", - "liveSelectComboPlaceholder": "— seleccionar combo —", - "liveTargetCount": "{count, plural, one {# objetivo} other {# objetivos}}", - "liveSingle": "Individual", - "liveFleet": "Flota", - "playgroundStatusAvailable": "Disponible", - "playgroundStatusNoQuota": "Sin cuota", - "playgroundStatusDegraded": "Degradado", + "liveNoProviders": "No providers observed yet.", + "liveFleetDataHint": "Fleet data arrives through live combo events.", + "liveActiveCount": "Active ({count})", + "liveErrorCount": "Errors ({count})", + "liveInactiveCount": "Inactive ({count})", + "liveNoRun": "No combo run available.", + "liveDataHint": "Live data arrives through the WebSocket combo channel.", + "liveDisconnected": "Live disabled — WebSocket disconnected. Showing last known state.", + "liveSelectCombo": "Select combo", + "liveSelectComboPlaceholder": "— select combo —", + "liveTargetCount": "{count, plural, one {# target} other {# targets}}", + "liveSingle": "Single", + "liveFleet": "Fleet", + "playgroundStatusAvailable": "Available", + "playgroundStatusNoQuota": "No Quota", + "playgroundStatusDegraded": "Degraded", "playgroundStatusError": "Error", - "playgroundStatusUnknown": "Desconocido", - "playgroundNetworkError": "Error de red durante la simulación", - "playgroundTitle": "Playground de combos", - "playgroundDescription": "Simule cómo se enrutarán las solicitudes a través de sus combos", - "playgroundConfiguration": "Configuración", - "playgroundNoCombosConfigured": "No hay combos configurados", - "active": "activo", - "inactive": "inactivo", - "playgroundEstimatedPromptTokens": "Tokens de prompt estimados", - "playgroundSimulating": "Simulando...", - "playgroundSimulateRoute": "Simular ruta", - "playgroundRoutingPath": "Ruta de enrutamiento", - "playgroundStrategy": "Estrategia", - "playgroundEstimatedCost": "Costo est.", - "playgroundEstimatedLatency": "Latencia est.", + "playgroundStatusUnknown": "Unknown", + "playgroundNetworkError": "Network error during simulation", + "playgroundTitle": "Combo Playground", + "playgroundDescription": "Simulate how requests will be routed through your combos", + "playgroundConfiguration": "Configuration", + "playgroundNoCombosConfigured": "No combos configured", + "active": "active", + "inactive": "inactive", + "playgroundEstimatedPromptTokens": "Estimated Prompt Tokens", + "playgroundSimulating": "Simulating...", + "playgroundSimulateRoute": "Simulate Route", + "playgroundRoutingPath": "Routing Path", + "playgroundStrategy": "Strategy", + "playgroundEstimatedCost": "Est. Cost", + "playgroundEstimatedLatency": "Est. Latency", "playgroundFallback": "fallback", - "playgroundWeight": "peso {value}", - "playgroundWarningCount": "Advertencias ({count})", - "playgroundErrorCount": "Errores ({count})", - "playgroundEmptyHint": "Selecciona un combo y haz clic en Simular ruta para ver la ruta de enrutamiento.", - "playgroundNoCombosYet": "Aún no se han configurado combos.", - "playgroundCreateFirst": "Crea uno primero", + "playgroundWeight": "weight {value}", + "playgroundWarningCount": "Warnings ({count})", + "playgroundErrorCount": "Errors ({count})", + "playgroundEmptyHint": "Select a combo and click Simulate Route to see the routing path.", + "playgroundNoCombosYet": "No combos configured yet.", + "playgroundCreateFirst": "Create one first", "weighted": "ponderado", "leastUsed": "Menos utilizado", "costOpt": "Opción de costo", @@ -3161,7 +3167,7 @@ "failoverBeforeRetry": "Cuando está habilitado, cualquier error ascendente desencadena una conmutación por error inmediata al siguiente destino combinado, omitiendo todos los reintentos y las URL alternativas.", "maxSetRetries": "Número de veces que se reintenta el conjunto de objetivos completo cuando todos los objetivos fallan. 0 = ningún reintento de nivel establecido.", "setRetryDelayMs": "Retraso entre reintentos de nivel establecido, lo que da tiempo a los problemas transitorios para resolverse.", - "disableSessionStickiness": "Rota a una conexión diferente en cada solicitud en lugar de vincular una conversación completa a una sola conexión mediante el hash del primer mensaje. Invalida el valor predeterminado global. Déjalo en Heredar para conservar los aciertos de caché de prompts en chats de varios turnos." + "disableSessionStickiness": "Rotate to a different connection on every request instead of pinning a whole conversation to one connection by the first-message hash. Overrides the global default. Leave on Inherit to preserve prompt-cache hits for multi-turn chats." }, "templatesTitle": "Quick templates", "templatesDescription": "Apply a starting profile, then adjust models and config.", @@ -3213,16 +3219,16 @@ "intelligentPanelTitle": "Intelligent Routing Dashboard", "intelligentPanelDesc": "Real-time scoring and health status for this auto-routing combo.", "configOnlyStatus": "Vista de configuración", - "configOnlyHint": "Este panel solo muestra las entradas de enrutamiento. El estado del disyuntor en tiempo real está disponible en la página de Salud.", - "routingInputs": "Entradas de enrutamiento", - "routingInputsHint": "El paquete de modo y la ponderación permanecen aquí; el estado de ejecución del disyuntor permanece en la página de Salud.", - "emailVisibilityHint": "Los correos electrónicos de las cuentas aquí siguen el interruptor de privacidad global.", - "emailVisibilityTooltip": "Usa el icono del ojo para mostrar u ocultar los correos electrónicos de las cuentas de forma global en combos, proveedores y pantallas de cuotas.", - "manualModel": "Modelo manual", - "manualModelInvalid": "Introduce un modelo como proveedor/modelo.", - "manualModelUnknownProvider": "Prefijo de proveedor desconocido.", - "builderDynamicAccountShort": "Cuenta dinámica", - "builderNeedValidName": "Define un nombre de combo válido antes de continuar.", + "configOnlyHint": "Este panel muestra solo los parámetros de enrutamiento. El estado del disyuntor en tiempo real está en la página de Salud.", + "routingInputs": "Parámetros de enrutamiento", + "routingInputsHint": "El paquete de modos y los pesos se mantienen aquí; el estado del disyuntor en tiempo real se mantiene en la página de Salud.", + "emailVisibilityHint": "Los correos de cuentas aquí siguen el selector global de privacidad.", + "emailVisibilityTooltip": "Use the eye icon to reveal or hide account emails globally across combos, providers and quota screens.", + "manualModel": "Manual model", + "manualModelInvalid": "Enter a model as provider/model.", + "manualModelUnknownProvider": "Unknown provider prefix.", + "builderDynamicAccountShort": "Dynamic account", + "builderNeedValidName": "Define a valid combo name before continuing.", "statusOverview": "Status Overview", "normalOperation": "Normal Operation", "allProvidersHealthy": "Providers are reporting healthy routing conditions.", @@ -3251,9 +3257,9 @@ "budgetCapLabel": "Budget Cap (USD / request)", "budgetCapPlaceholder": "No limit", "advancedWeightsTitle": "Advanced: Scoring Weights", - "nestedComboFlatten": "Aplanar combos anidados", - "nestedComboExecute": "Ejecutar combos anidados como destinos", - "effectiveRoutingShare": "Cuota de enrutamiento efectiva (peso ÷ total)", + "nestedComboFlatten": "Flatten nested combos", + "nestedComboExecute": "Execute nested combos as targets", + "effectiveRoutingShare": "Effective routing share (weight ÷ total)", "weightQuota": "Quota", "weightHealth": "Health", "weightCostInv": "Cost", @@ -3261,6 +3267,7 @@ "weightTaskFit": "Task Fit", "weightStability": "Stability", "weightTierPriority": "Tier", + "weightCacheAffinity": "Cache Hit Affinity", "reviewIntelligentTitle": "Intelligent Routing Config", "strategyRecommendations": { "priority": { @@ -3458,13 +3465,13 @@ "browseLegacyCatalog": "Explorar el catálogo combinado heredado", "agentFeaturesTitle": "Funciones del agente", "agentFeaturesDescription": "Habilite funciones avanzadas para los agentes que usan este combo", - "responseValidationTitle": "Validación de respuesta", - "responseValidationHelp": "Pasar al siguiente destino cuando un cuerpo 200 OK no supere estas comprobaciones (contenido del asistente).", - "responseValidationForbidden": "Subcadenas prohibidas (una por línea)", - "responseValidationRequired": "Subcadenas requeridas (una por línea)", - "responseValidationMinLength": "Longitud mínima del contenido (caracteres)", - "responseValidationJsonPaths": "Comprobaciones de JSON-path", - "responseValidationAddCheck": "+ Añadir comprobación", + "responseValidationTitle": "Response validation", + "responseValidationHelp": "Fail over to the next target when a 200 OK body fails these checks (assistant content).", + "responseValidationForbidden": "Forbidden substrings (one per line)", + "responseValidationRequired": "Required substrings (one per line)", + "responseValidationMinLength": "Minimum content length (chars)", + "responseValidationJsonPaths": "JSON-path checks", + "responseValidationAddCheck": "+ Add check", "agentFeaturesSystemMessageOverride": "Anular mensaje del sistema", "agentFeaturesSystemMessagePlaceholder": "Eres un asistente experto...", "agentFeaturesSystemMessageHint": "Anulación de mensajes del sistema para agentes", @@ -3479,14 +3486,12 @@ "agentFeaturesContextLengthErrorRange": "La longitud del contexto debe estar entre 1000 y 2000000", "compressionOverride": "Anulación de compresión", "modePack": "Paquete de modo", - "disableSessionStickiness": "Desactivar la persistencia de sesión", - "sessionStickinessEnabled": "Persistencia activada", - "sessionStickinessDisabled": "Persistencia desactivada", - "kimiPresetTitle": "Ajuste preestablecido de Kimi Coding", - "kimiPresetDescription": "Kimi K3 como modelo principal (Moonshot API), con transición automática a sus conexiones de Kimi Code (kimi-coding, kimi-web) cuando estén configuradas.", - "kimiPresetCta": "Añadir ajuste preestablecido", - "cacheOptimizedDesc": "Routes each reusable prompt prefix consistently to the same provider account", - "weightCacheAffinity": "Cache Hit Affinity" + "disableSessionStickiness": "Disable session stickiness", + "sessionStickinessEnabled": "Stickiness on", + "sessionStickinessDisabled": "Stickiness off", + "kimiPresetTitle": "Kimi Coding preset", + "kimiPresetDescription": "Kimi K3 as the primary model (Moonshot API), with automatic fallback to your Kimi Code connections (kimi-coding, kimi-web) when configured.", + "kimiPresetCta": "Add preset" }, "costs": { "title": "Costos", @@ -3553,7 +3558,7 @@ "currentPeriod": "Mitad actual", "exportCSV": "Exportar como CSV", "exportJSON": "Exportar como JSON", - "legacyFreeLabel": "Heredado / Gratis", + "legacyFreeLabel": "Heredado / Gratuito", "costExplorerTitle": "Cost Explorer", "costExplorerDescription": "Explore spend by provider, model, API key, account, or service tier.", "groupProvider": "Provider", @@ -3562,13 +3567,13 @@ "groupAccount": "Account", "groupServiceTier": "Service Tier", "serviceTierFast": "Rápido", - "serviceTierFlex": "Flex", + "serviceTierFlex": "Flexible", "serviceTierStandard": "Estándar", "serviceTierBreakdownTitle": "Nivel de servicio", - "serviceTierBreakdownSubtitle": "División Rápido / Flex / Estándar", - "serviceTierUsageSaved": "uso guardado", - "serviceTierCostSaved": "guardado", - "serviceTierCostShareSuffix": "de costo", + "serviceTierBreakdownSubtitle": "Fast / Flex / Standard split", + "serviceTierUsageSaved": "usage saved", + "serviceTierCostSaved": "saved", + "serviceTierCostShareSuffix": "of cost", "dimension": "Dimension", "share": "Share", "legacyOrFree": "Legacy / Free", @@ -3774,108 +3779,108 @@ "apiEndpointsSearchPlaceholder": "Buscar puntos finales...", "apiEndpointsRequiresAuth": "Requiere autenticación", "apiEndpointsNoMatch": "Ningún punto final coincide con su filtro", - "endpointSections": "Secciones de endpoints", + "endpointSections": "Endpoint sections", "tabMcp": "MCP", "tabA2a": "A2A", - "tabContextSources": "Fuentes de contexto", - "activeEndpoints": "Endpoints activos", + "tabContextSources": "Context Sources", + "activeEndpoints": "Active Endpoints", "activeLocal": "Local", - "activeCloud": "Nube", - "copyUrlTitle": "Copiar {url}", - "statusRunning": "En ejecución", - "tunnels": "Túneles", - "activeTunnelCount": "{active} / {total} activos", + "activeCloud": "Cloud", + "copyUrlTitle": "Copy {url}", + "statusRunning": "Running", + "tunnels": "Tunnels", + "activeTunnelCount": "{active} / {total} active", "badgeLocal": "LOCAL", - "badgeProtected": "PROTEGIDO", - "badgeInternal": "INTERNO", - "catalogLoadFailed": "La solicitud del catálogo de API falló con HTTP {status}", - "catalogLoadFailedGeneric": "Error al cargar el catálogo de API", - "apiKeysLoadFailed": "Error al cargar las claves de API ({status})", - "apiKeysLoadFailedGeneric": "Error al cargar las claves de API", - "apiKeyRevealDisabled": "La revelación de claves de API está desactivada (ALLOW_API_KEY_REVEAL). Cámbielo en la página de Feature Flags o pegue una clave de API manualmente.", - "apiKeyRevealFailed": "Error al revelar la clave de API ({status})", - "apiKeyRevealInvalid": "La revelación de la clave de API devolvió una respuesta no válida", - "apiKeyRequired": "Se requiere una clave de API para este endpoint.", - "requestFailed": "Error en la solicitud ({status})", + "badgeProtected": "PROTECTED", + "badgeInternal": "INTERNAL", + "catalogLoadFailed": "API catalog request failed with HTTP {status}", + "catalogLoadFailedGeneric": "Failed to load API catalog", + "apiKeysLoadFailed": "Failed to load API keys ({status})", + "apiKeysLoadFailedGeneric": "Failed to load API keys", + "apiKeyRevealDisabled": "API key reveal is disabled (ALLOW_API_KEY_REVEAL). Change it on the Feature Flags page or paste an API key manually.", + "apiKeyRevealFailed": "Failed to reveal API key ({status})", + "apiKeyRevealInvalid": "API key reveal returned an invalid response", + "apiKeyRequired": "An API key is required for this endpoint.", + "requestFailed": "Request failed ({status})", "errorStatus": "Error", - "catalogStats": "{endpoints} endpoints en {categories} categorías", - "catalogUnavailableDescription": "No se pudo cargar la especificación OpenAPI.", - "openJsonResponse": "Abrir respuesta JSON", - "all": "Todos", - "more": "+{count} más", - "showInternalTooltip": "Mostrar u ocultar rutas internas (ocultas por defecto)", - "bearerAuth": "Autenticación Bearer", - "requestBody": "Cuerpo de la solicitud", - "close": "Cerrar", - "tryIt": "Probar", - "example": "Ejemplo", - "apiKey": "Clave de API", - "switchToSelection": "Cambiar a selección", - "enterManually": "Introducir manualmente", - "pasteApiKey": "Pega tu clave API aquí", - "noActiveApiKeys": "No se encontraron claves API activas. Activa la entrada manual para pegar una.", - "requestBodyJson": "Cuerpo de la solicitud (JSON)", - "sending": "Enviando...", - "sendRequest": "Enviar solicitud", - "dataSchemas": "Esquemas de datos", - "vscodeAliasTitle": "Alias de token de VS Code", - "vscodeAliasDescriptionReady": "URL de compatibilidad listas para pegar que usan el endpoint /api/v1/vscode/TOKEN/...", - "vscodeAliasDescriptionError": "Mostrando URL de marcador de posición porque no se pudieron cargar las claves de CLI en esta sesión.", - "vscodeAliasDescriptionLoading": "Cargando claves de CLI. Se muestran URL de marcador de posición hasta que haya una clave disponible.", - "vscodeAliasDescriptionPlaceholder": "Mostrando URL de marcador de posición. Crea o activa una clave API en Herramientas de CLI para reemplazar TOKEN.", - "vscodeAliasManage": "Herramientas de CLI", - "vscodeAliasBaseLabel": "Base de VS Code", - "vscodeAliasModelsLabel": "Modelos de VS Code", - "vscodeAliasChatLabel": "Chat de VS Code", + "catalogStats": "{endpoints} endpoints across {categories} categories", + "catalogUnavailableDescription": "The OpenAPI specification could not be loaded.", + "openJsonResponse": "Open JSON response", + "all": "All", + "more": "+{count} more", + "showInternalTooltip": "Show or hide internal routes (hidden by default)", + "bearerAuth": "Bearer Auth", + "requestBody": "Request Body", + "close": "Close", + "tryIt": "Try It", + "example": "Example", + "apiKey": "API Key", + "switchToSelection": "Switch to Selection", + "enterManually": "Enter Manually", + "pasteApiKey": "Paste your API key here", + "noActiveApiKeys": "No active API keys found. Toggle manual entry to paste one.", + "requestBodyJson": "Request Body (JSON)", + "sending": "Sending...", + "sendRequest": "Send Request", + "dataSchemas": "Data Schemas", + "vscodeAliasTitle": "VS Code Token Alias", + "vscodeAliasDescriptionReady": "Ready-to-paste compatibility URLs using the /api/v1/vscode/TOKEN/... endpoint.", + "vscodeAliasDescriptionError": "Showing placeholder URLs because CLI keys could not be loaded in this session.", + "vscodeAliasDescriptionLoading": "Loading CLI keys. Placeholder URLs are shown until a key is available.", + "vscodeAliasDescriptionPlaceholder": "Showing placeholder URLs. Create or activate an API key in CLI Tools to replace TOKEN.", + "vscodeAliasManage": "CLI Tools", + "vscodeAliasBaseLabel": "VS Code base", + "vscodeAliasModelsLabel": "VS Code models", + "vscodeAliasChatLabel": "VS Code chat", "localServer": "Servidor local", "cloudOmniroute": "OmniRuta en la nube", "copyUrl": "Copiar URL", - "badgeLoopbackTooltip": "Este endpoint solo es accesible localmente (solo loopback)", - "badgeAlwaysProtectedTooltip": "Este endpoint siempre está protegido y requiere autorización", - "badgeInternalTooltip": "Este es un endpoint interno del sistema", + "badgeLoopbackTooltip": "Este extremo solo es accesible localmente (loopback)", + "badgeAlwaysProtectedTooltip": "Este extremo siempre está protegido y requiere autorización", + "badgeInternalTooltip": "Este es un extremo interno del sistema", "tierAll": "Todos", "tierAuth": "Autenticado", "tierLoopback": "Loopback", - "tierAlwaysProtected": "Siempre protegido", + "tierAlwaysProtected": "Always Protected", "tierPublic": "Público", - "hideInternal": "Ocultar internos", - "showInternal": "Mostrar internos", + "hideInternal": "Hide Internal", + "showInternal": "Show Internal", "customSystemPromptTitle": "Custom System Prompt", "customSystemPromptDescription": "Inject a custom system prompt into every model request", "customSystemPromptPlaceholder": "e.g. Always respond in pirate speak...", - "obsidianEnterToken": "Por favor, introduce un token de API de Obsidian", - "obsidianConnectFailed": "Error al conectar", - "obsidianConnectionFailed": "Error de conexión", - "obsidianDisconnectFailed": "Error al desconectar", - "obsidianEnterVaultPath": "Por favor, introduce la ruta del directorio de la bóveda", - "obsidianWebdavEnabledMessage": "Sincronización WebDAV activada. Configura tu dispositivo móvil a continuación.", - "obsidianEnableWebdavFailed": "Error al activar WebDAV", - "obsidianWebdavDisabledMessage": "Sincronización WebDAV desactivada", - "obsidianDisableWebdavFailed": "Error al desactivar WebDAV", - "obsidianConnected": "Conectado", - "obsidianNotConnected": "No conectado", - "obsidianWebdavSync": "Sincronización WebDAV", - "obsidianDescription": "Busca, lee, escribe y gestiona notas en Obsidian a través de modelos de IA enrutados", - "obsidianRestToken": "Token de la API REST local de Obsidian", - "obsidianApiKeyPlaceholder": "Clave API de Obsidian", - "obsidianConnect": "Conectar", - "obsidianBaseUrlOptional": "URL base (opcional)", - "obsidianPortWarning": "El puerto 27124 es el endpoint de MCP (HTTPS, certificado autofirmado). La API REST utiliza HTTP en el puerto 27123.", - "obsidianRemoteVaultHint": "Predeterminado: {defaultUrl}. Para bóvedas remotas, introduce la IP de Tailscale + puerto (p. ej., http://100.x.x.x:27123). Activa el complemento Local REST API en la máquina que ejecuta Obsidian.", - "obsidianTokenConfigured": "Token configurado. Las herramientas de Obsidian están disponibles a través de MCP.", - "obsidianDisconnect": "Desconectar", - "obsidianVaultSync": "Sincronización de bóveda (WebDAV)", - "obsidianVaultSyncDescription": "Sincroniza tu bóveda con Obsidian móvil usando WebDAV a través de Tailscale. Obsidian móvil tiene soporte WebDAV integrado; no se necesitan complementos.", - "obsidianVaultDirectoryPath": "Ruta del directorio de la bóveda", - "obsidianEnable": "Activar", - "obsidianWebdavEnabled": "Sincronización WebDAV activada", - "obsidianDisable": "Desactivar", - "obsidianConfigureMobile": "Configurar Obsidian móvil", - "obsidianMobileInstructions": "En Obsidian móvil: Configuración → Sincronización → WebDAV → introduce lo siguiente:", - "obsidianWebdavUrl": "URL de WebDAV", - "obsidianUsername": "Nombre de usuario", - "obsidianPassword": "Contraseña", - "obsidianTailscaleHint": "Usa tu IP de Tailscale en lugar de localhost si te conectas desde el móvil. Ambos dispositivos deben estar en la misma red de Tailscale." + "obsidianEnterToken": "Please enter an Obsidian API token", + "obsidianConnectFailed": "Failed to connect", + "obsidianConnectionFailed": "Connection failed", + "obsidianDisconnectFailed": "Failed to disconnect", + "obsidianEnterVaultPath": "Please enter the vault directory path", + "obsidianWebdavEnabledMessage": "WebDAV sync enabled. Configure your mobile device below.", + "obsidianEnableWebdavFailed": "Failed to enable WebDAV", + "obsidianWebdavDisabledMessage": "WebDAV sync disabled", + "obsidianDisableWebdavFailed": "Failed to disable WebDAV", + "obsidianConnected": "Connected", + "obsidianNotConnected": "Not connected", + "obsidianWebdavSync": "WebDAV Sync", + "obsidianDescription": "Search, read, write, and manage notes in Obsidian through routed AI models", + "obsidianRestToken": "Obsidian Local REST API Token", + "obsidianApiKeyPlaceholder": "Obsidian API key", + "obsidianConnect": "Connect", + "obsidianBaseUrlOptional": "Base URL (optional)", + "obsidianPortWarning": "Port 27124 is the MCP endpoint (HTTPS, self-signed certificate). The REST API uses HTTP on port 27123.", + "obsidianRemoteVaultHint": "Default: {defaultUrl}. For remote vaults, enter the Tailscale IP + port (e.g., http://100.x.x.x:27123). Enable the Local REST API plugin on the machine running Obsidian.", + "obsidianTokenConfigured": "Token configured. Obsidian tools are available via MCP.", + "obsidianDisconnect": "Disconnect", + "obsidianVaultSync": "Vault Sync (WebDAV)", + "obsidianVaultSyncDescription": "Sync your vault to Obsidian mobile using WebDAV over Tailscale. Obsidian mobile has built-in WebDAV support — no plugins needed.", + "obsidianVaultDirectoryPath": "Vault Directory Path", + "obsidianEnable": "Enable", + "obsidianWebdavEnabled": "WebDAV sync enabled", + "obsidianDisable": "Disable", + "obsidianConfigureMobile": "Configure Obsidian Mobile", + "obsidianMobileInstructions": "In Obsidian mobile: Settings → Sync → WebDAV → enter the following:", + "obsidianWebdavUrl": "WebDAV URL", + "obsidianUsername": "Username", + "obsidianPassword": "Password", + "obsidianTailscaleHint": "Use your Tailscale IP instead of localhost if connecting from mobile. Both devices must be on the same Tailscale network." }, "endpoints": { "tabProxy": "Endpoint Proxy", @@ -3908,17 +3913,17 @@ "disableLabel": "Desactivar {label}", "enableLabel": "Activar {label}", "transportMode": "Modo de transporte", - "transportStdioDesc": "Local — El IDE genera el proceso a través de omniroute --mcp", + "transportStdioDesc": "Local — El IDE ejecuta el proceso a través de omniroute --mcp", "transportSseDesc": "Remoto — Server-Sent Events sobre HTTP", - "transportStreamableHttpDesc": "Remoto — HTTP bidireccional moderno", - "copy": "Copiar", + "transportStreamableHttpDesc": "Remote — Modern bidirectional HTTP", + "copy": "Copy", "mcpDashboardCopyUrl": "Copiar URL", - "mcpDisabledTitle": "MCP está desactivado", - "mcpDisabledDesc": "Activa MCP arriba para configurar el modo de transporte y ver la telemetría del servidor.", - "mcpIntro": "Model Context Protocol — {tools} herramientas en {scopes} ámbitos, {transports} transportes (stdio / SSE / Streamable HTTP).", - "mcpStep1": "Ejecutar a través de {code}", - "mcpStep2": "Configura tu cliente MCP para conectarte a través del transporte stdio.", - "mcpStep3": "Invoca herramientas como {code1} y {code2}.", + "mcpDisabledTitle": "MCP is disabled", + "mcpDisabledDesc": "Enable MCP above to configure transport mode and view server telemetry.", + "mcpIntro": "Model Context Protocol — {tools} tools across {scopes} scopes, {transports} transports (stdio / SSE / Streamable HTTP).", + "mcpStep1": "Run via {code}", + "mcpStep2": "Configure your MCP client to connect over stdio transport.", + "mcpStep3": "Invoke tools like {code1} and {code2}.", "pid": "PID", "sessionUptime": "tiempo de actividad de la sesión", "lastHeartbeat": "último latido", @@ -4043,12 +4048,12 @@ "offline": "Desconectado", "disableLabel": "Desactivar {label}", "enableLabel": "Activar {label}", - "a2aDisabledTitle": "A2A está desactivado", - "a2aDisabledDesc": "Activa A2A arriba para ver la telemetría de tareas, los detalles del agente y las herramientas de validación.", - "a2aIntro": "Endpoint JSON-RPC 2.0 de Agent2Agent — envía tareas, transmite respuestas, cancela trabajos en curso.", - "a2aStep1": "Descubre la tarjeta del agente en {code}.", - "a2aStep2": "Enviar JSON-RPC a {code1} usando {code2} o {code3}.", - "a2aStep3": "Rastrear y cancelar tareas con {code1} y {code2}." + "a2aDisabledTitle": "A2A is disabled", + "a2aDisabledDesc": "Enable A2A above to view task telemetry, agent details, and validation tools.", + "a2aIntro": "Agent2Agent JSON-RPC 2.0 endpoint — send tasks, stream responses, cancel in-flight jobs.", + "a2aStep1": "Discover the agent card at {code}.", + "a2aStep2": "Send JSON-RPC to {code1} using {code2} or {code3}.", + "a2aStep3": "Track and cancel tasks with {code1} and {code2}." }, "memory": { "a": "A", @@ -4058,68 +4063,68 @@ "cancel": "Cancelar", "checkHealth": "comprobar la salud", "checkingHealth": "Comprobando…", - "compactOld": "Compactar antiguas", + "compactOld": "Compact old", "concept": { - "title": "Memoria conversacional", - "description": "OmniRoute aprende de cada conversación, recordando hechos, episodios, procedimientos y conceptos semánticos que hacen que las respuestas sean más precisas y conscientes del contexto.", - "howWorksToggle": "Cómo funciona", - "howWorksContent": "1. Extracción automática: al final de cada respuesta, los hechos y episodios se detectan y guardan automáticamente.\n2. Recuperación: antes de cada respuesta, se buscan las memorias más relevantes mediante FTS5 (exacto), vectorial (semántico) o RRF híbrido.\n3. Inyección: las memorias relevantes se inyectan en el contexto del asistente para mejorar la calidad de la respuesta.\n4. Gestión: use esta página para ver, editar, exportar y compactar memorias antiguas." + "title": "Conversational Memory", + "description": "OmniRoute learns from every conversation, remembering facts, episodes, procedures, and semantic concepts that make responses more accurate and context-aware.", + "howWorksToggle": "How it works", + "howWorksContent": "1. Automatic extraction: at the end of each response, facts and episodes are detected and saved automatically.\n2. Retrieval: before each response, the most relevant memories are searched via FTS5 (exact), vector (semantic), or hybrid RRF.\n3. Injection: relevant memories are injected into the assistant context to improve response quality.\n4. Management: use this page to view, edit, export, and compact old memories." }, "content": "Content", "contentPlaceholder": "Valor o contenido JSON para recordar", "created": "Created", "delete": "Delete", - "deleteConfirmDesc": "Esta acción no se puede deshacer. La memoria se eliminará permanentemente.", - "deleteConfirmTitle": "¿Eliminar memoria?", + "deleteConfirmDesc": "This action cannot be undone. The memory will be permanently removed.", + "deleteConfirmTitle": "Delete memory?", "description": "View and manage stored memory entries", - "editMemory": "Editar memoria", + "editMemory": "Edit memory", "editModal": { - "title": "Editar Memoria", - "metadataLabel": "Metadatos (JSON)", - "metadataInvalid": "JSON no válido", - "saveFailed": "Error al guardar la memoria" + "title": "Edit Memory", + "metadataLabel": "Metadata (JSON)", + "metadataInvalid": "Invalid JSON", + "saveFailed": "Failed to save memory" }, "embedding": { - "autoLabel": "Automático", - "autoDesc": "Usa el mejor disponible: proveedor remoto > estático > transformers", - "remoteLabel": "Proveedor remoto", - "remoteDesc": "Usa embeddings mediante la API del proveedor (requiere clave de API)", - "staticLabel": "Local estático (potion)", - "staticDesc": "Embedding local sin WASM ni dependencias externas", + "autoLabel": "Automatic", + "autoDesc": "Uses best available: remote provider > static > transformers", + "remoteLabel": "Remote provider", + "remoteDesc": "Uses embedding via provider API (requires API key)", + "staticLabel": "Static local (potion)", + "staticDesc": "Local embedding without WASM or external dependencies", "transformersLabel": "Transformers.js (MiniLM)", - "transformersDesc": "Embedding local mediante @huggingface/transformers (~400MB RAM)", - "providerModelLabel": "Proveedor / Modelo", - "noRemoteProviders": "No hay proveedores con clave de API configurada", - "selectProviderModel": "Seleccionar un modelo", - "staticEnabledLabel": "Habilitar Static Potion", - "staticEnabledDesc": "Descargar y usar el modelo potion-base-8M localmente", - "transformersEnabledLabel": "Habilitar Transformers.js", - "transformersEnabledDesc": "Optar por MiniLM local (~400MB RAM, ~3s de inicio en frío)", - "transformersWarning": "Requiere ~400MB de RAM y ~3s de inicio en frío en la primera consulta semántica." + "transformersDesc": "Local embedding via @huggingface/transformers (~400MB RAM)", + "providerModelLabel": "Provider / Model", + "noRemoteProviders": "No providers with configured API key", + "selectProviderModel": "Select a model", + "staticEnabledLabel": "Enable Static Potion", + "staticEnabledDesc": "Download and use potion-base-8M model locally", + "transformersEnabledLabel": "Enable Transformers.js", + "transformersEnabledDesc": "Opt-in for local MiniLM (~400MB RAM, ~3s cold start)", + "transformersWarning": "Requires ~400MB RAM and ~3s cold start on the first semantic query." }, "emptyState": { - "title": "Aún no hay memorias", - "description": "Las memorias se crean automáticamente a partir de las conversaciones. También puede añadirlas manualmente usando el botón de arriba." + "title": "No memories yet", + "description": "Memories are created automatically from conversations. You can also add them manually using the button above." }, "engine": { - "statusTitle": "Estado del motor", - "embeddingTitle": "Fuente de embeddings", - "rerankTitle": "Reordenar (opcional)", - "reindexNow": "Reindexar ahora", - "reindexStarted": "Reindexación iniciada ({pending} pendientes)", - "reindexFailed": "Error al iniciar la reindexación", - "keywordLabel": "Palabra clave (FTS5)", - "keywordReason": "Búsqueda por palabra clave siempre disponible", + "statusTitle": "Engine Status", + "embeddingTitle": "Embedding Source", + "rerankTitle": "Rerank (optional)", + "reindexNow": "Reindex now", + "reindexStarted": "Reindexing started ({pending} pending)", + "reindexFailed": "Failed to start reindexing", + "keywordLabel": "Keyword (FTS5)", + "keywordReason": "Keyword search always available", "embeddingLabel": "Embedding", - "vectorStoreLabel": "Almacén de vectores", + "vectorStoreLabel": "Vector Store", "qdrantLabel": "Qdrant", - "rerankLabel": "Reordenamiento", - "qdrantDisabled": "Deshabilitado", - "qdrantOk": "Operativo ({latencyMs}ms)", - "qdrantError": "Error de conexión", - "needsReindex": "{count} memoria(s) necesitan reindexación", - "configureCta": "Configurar", - "vectorStoreInstallHint": "Para habilitar la búsqueda vectorial: npm install sqlite-vec (requiere Node.js nativo, no WASM), luego reinicie." + "rerankLabel": "Rerank", + "qdrantDisabled": "Disabled", + "qdrantOk": "Healthy ({latencyMs}ms)", + "qdrantError": "Connection error", + "needsReindex": "{count} memory(ies) need reindexing", + "configureCta": "Configure", + "vectorStoreInstallHint": "To enable vector search: npm install sqlite-vec (needs native Node.js, not WASM), then restart." }, "episodic": "Episodic", "export": "Export", @@ -4127,8 +4132,8 @@ "healthUnknown": "Salud desconocida", "hitRate": "Hit Rate", "import": "Import", - "importError": "Error al importar el archivo", - "importResult": "{imported} importados, {skipped} omitidos", + "importError": "Failed to import file", + "importResult": "{imported} imported, {skipped} skipped", "key": "Key", "keyPlaceholder": "por ej. tema.preferencias.de.usuario", "loading": "Loading memories...", @@ -4139,126 +4144,126 @@ "pipelineError": "error de canalización", "pipelineOk": "Canalización correcta ({latencyMs}ms)", "playground": { - "infoTitle": "Playground de memoria", - "infoDesc": "Simule lo que se recuperaría para una consulta determinada. No se modifica ninguna memoria — vista previa de solo lectura.", - "queryLabel": "Consulta de prueba", - "queryPlaceholder": "Escriba una pregunta o frase de prueba...", - "strategyLabel": "Estrategia", - "strategyExact": "Exacta (FTS5)", - "strategySemantic": "Semántica (vectorial)", - "strategyHybrid": "Híbrida (RRF)", - "budgetLabel": "Presupuesto (tokens)", - "simulate": "Simular", - "resultsTitle": "{count} resultado(s)", - "resolutionTitle": "Resolución de búsqueda", + "infoTitle": "Memory Playground", + "infoDesc": "Simulate what would be retrieved for a given query. No memories are modified — read-only preview.", + "queryLabel": "Test query", + "queryPlaceholder": "Type a question or test phrase...", + "strategyLabel": "Strategy", + "strategyExact": "Exact (FTS5)", + "strategySemantic": "Semantic (vector)", + "strategyHybrid": "Hybrid (RRF)", + "budgetLabel": "Budget (tokens)", + "simulate": "Simulate", + "resultsTitle": "{count} result(s)", + "resolutionTitle": "Search resolution", "resolutionEmbedding": "Embedding", - "resolutionStore": "Almacén de vectores", - "resolutionStrategy": "Estrategia utilizada", - "rerankApplied": "Reordenamiento aplicado", - "fallback": "Respaldo", - "noResults": "No se encontraron memorias para esta consulta.", - "tokensUsed": "tokens utilizados", - "none": "ninguno", - "errorFetch": "Error al obtener la vista previa" + "resolutionStore": "Vector store", + "resolutionStrategy": "Strategy used", + "rerankApplied": "Rerank applied", + "fallback": "Fallback", + "noResults": "No memories found for this query.", + "tokensUsed": "tokens used", + "none": "none", + "errorFetch": "Failed to fetch preview" }, "previous": "Anterior", "procedural": "Procedural", "qdrant": { - "title": "Qdrant (Almacén de vectores de nivel 2)", - "description": "Integración opcional de Qdrant para búsqueda semántica escalable", - "enableLabel": "Habilitar Qdrant", - "enableDesc": "Cuando está habilitado, Qdrant se utiliza como el almacén de vectores principal", - "banner": "Almacén de vectores de nivel 2 — una alternativa externa y escalable al sqlite-vec integrado (nivel 1). Habilítelo solo si tiene un conjunto de memorias muy grande o desea memoria compartida entre instancias; la mayoría de los usuarios tienen suficiente con sqlite-vec. Cuando está habilitado, se convierte en el almacén principal y recurre automáticamente a sqlite-vec si no está accesible.", - "hostHelp": "Docker local: http://localhost:6333 · Qdrant Cloud: URL de su clúster", - "collectionHelp": "Cualquier nombre — OmniRoute lo crea en el primer uso", - "embeddingModelHelp": "Establece la dimensión del vector automáticamente en el primer uso. Las memorias existentes no se rellenan retroactivamente y cambiar el modelo después de que existan datos requiere una colección nueva.", - "testConnection": "Probar conexión", - "testing": "Probando...", - "statusActive": "Activo", + "title": "Qdrant (Vector Store Tier 2)", + "description": "Optional Qdrant integration for scalable semantic search", + "enableLabel": "Enable Qdrant", + "enableDesc": "When enabled, Qdrant is used as the primary vector store", + "banner": "Tier 2 vector store — an external, scalable alternative to the built-in sqlite-vec (Tier 1). Enable it only if you have a very large memory set or want shared memory across instances; most users are fine on sqlite-vec. When enabled it becomes the primary store and automatically falls back to sqlite-vec if unreachable.", + "hostHelp": "Local Docker: http://localhost:6333 · Qdrant Cloud: your cluster URL", + "collectionHelp": "Any name — OmniRoute creates it on first use", + "embeddingModelHelp": "Sets the vector dimension automatically on first use. Existing memories are not back-filled, and changing the model after data exists needs a fresh collection.", + "testConnection": "Test connection", + "testing": "Testing...", + "statusActive": "Active", "statusError": "Error", - "statusDisabled": "Deshabilitado", - "healthOk": "Conexión correcta ({latencyMs}ms)", - "healthError": "Error de conexión", - "saved": "Configuración guardada", - "saveError": "Error al guardar", - "portLabel": "Puerto", - "embeddingModelLabel": "Modelo de embedding", - "optional": "opcional", - "apiKeyKeepPlaceholder": "Dejar en blanco para mantener la clave actual", - "apiKeyOptional": "Dejar en blanco si no se usa autenticación", - "removeApiKey": "Eliminar", - "quickSelectModel": "Selección rápida", - "searchTestTitle": "Prueba de búsqueda semántica", - "searchPlaceholder": "Escribe una consulta de prueba...", - "searching": "Buscando...", - "search": "Buscar", - "cleanupTitle": "Limpiar puntos antiguos", - "cleanupDesc": "Eliminar puntos de Qdrant para memorias caducadas (período de retención).", - "cleaning": "Limpiando...", - "cleanNow": "Limpiar ahora", - "cleanupSuccess": "{count} punto(s) eliminado(s)", - "cleanupFailed": "Error en la limpieza" + "statusDisabled": "Disabled", + "healthOk": "Connection OK ({latencyMs}ms)", + "healthError": "Connection error", + "saved": "Settings saved", + "saveError": "Failed to save", + "portLabel": "Port", + "embeddingModelLabel": "Embedding Model", + "optional": "optional", + "apiKeyKeepPlaceholder": "Leave blank to keep current key", + "apiKeyOptional": "Leave blank if not using authentication", + "removeApiKey": "Remove", + "quickSelectModel": "Quick select", + "searchTestTitle": "Semantic search test", + "searchPlaceholder": "Type a test query...", + "searching": "Searching...", + "search": "Search", + "cleanupTitle": "Clean up old points", + "cleanupDesc": "Remove Qdrant points for expired memories (retention period).", + "cleaning": "Cleaning...", + "cleanNow": "Clean now", + "cleanupSuccess": "{count} point(s) removed", + "cleanupFailed": "Cleanup failed" }, "rerank": { - "enableLabel": "Habilitar Rerank", - "enableDesc": "Reordena los resultados con un modelo de reranking después de la búsqueda", - "warning": "Rerank añade +200-500ms de latencia y un coste adicional por solicitud. Usar con moderación.", - "providerModelLabel": "Proveedor / Modelo de Rerank", - "noProviderWithKey": "No hay ningún proveedor con clave API configurada. Configura un proveedor para usar rerank.", - "selectProviderModel": "Seleccionar un proveedor/modelo" + "enableLabel": "Enable Rerank", + "enableDesc": "Reorders results with a reranking model after search", + "warning": "Rerank adds +200-500ms latency and additional cost per request. Use sparingly.", + "providerModelLabel": "Rerank Provider / Model", + "noProviderWithKey": "No provider with configured API key. Configure a provider to use rerank.", + "selectProviderModel": "Select a provider/model" }, "save": "Guardar", - "saving": "Guardando...", + "saving": "Saving...", "search": "Search memories...", "semantic": "Semantic", "summarize": { - "title": "Compactar memorias antiguas", - "noCandidates": "No hay memorias aptas para compactación (criterio: >30 días de antigüedad).", - "candidatesDesc": "{count} memorias se compactarán en resúmenes. Esta acción no se puede deshacer.", - "confirm": "Compactar ahora" + "title": "Compact old memories", + "noCandidates": "No memories eligible for compaction (criteria: >30 days old).", + "candidatesDesc": "{count} memories will be compacted into summaries. This action cannot be undone.", + "confirm": "Compact now" }, "tabs": { - "memories": "Memorias", + "memories": "Memories", "playground": "Playground", - "engine": "Motor" + "engine": "Engine" }, "title": "Memory Management", "tokensUsed": "Tokens Used", "tooltip": { - "totalEntries": "Total de memorias almacenadas para esta clave de API", - "tokensUsed": "Total estimado de tokens ocupados por memorias activas", - "hitRate": "Tasa de aciertos de caché de lectura por ID (no precisión de recuperación semántica)", - "factual": "Hechos objetivos y permanentes del contexto del usuario", - "episodic": "Eventos y experiencias del historial de conversaciones", - "procedural": "Procedimientos, flujos de trabajo e instrucciones que el asistente debe seguir", - "semantic": "Conceptos, preferencias y conocimiento del dominio" + "totalEntries": "Total memories stored for this API key", + "tokensUsed": "Estimated total tokens occupied by active memories", + "hitRate": "Read-by-ID cache hit rate (not semantic recall accuracy)", + "factual": "Objective, permanent facts from user context", + "episodic": "Events and experiences from conversation history", + "procedural": "Procedures, workflows, and instructions the assistant should follow", + "semantic": "Concepts, preferences, and domain knowledge" }, "totalEntries": "Total Entries", "type": "Type", - "memoryEnabled": "Memoria habilitada" + "memoryEnabled": "Memory enabled" }, "skills": { "title": "Skills", "description": "Manage and monitor AI skills", "skillsTab": "Skills", "executionsTab": "Executions", - "selectSkillToInspect": "Selecciona una habilidad a la izquierda para inspeccionarla.", - "schemaTab": "Esquema", - "handlerTab": "Manejador", - "inputSchema": "Esquema de entrada", - "outputSchema": "Esquema de salida", - "handlerCode": "Código del manejador", - "handlerUnavailable": "Manejador no disponible", - "runTestPlaceholder": "Ejecutar prueba (marcador de posición)", - "setModeAria": "Establecer modo {mode}", - "uninstallSkill": "Desinstalar habilidad", + "selectSkillToInspect": "Select a skill on the left to inspect.", + "schemaTab": "Schema", + "handlerTab": "Handler", + "inputSchema": "Input Schema", + "outputSchema": "Output Schema", + "handlerCode": "Handler Code", + "handlerUnavailable": "Handler not available", + "runTestPlaceholder": "Run test (placeholder)", + "setModeAria": "Set mode {mode}", + "uninstallSkill": "Uninstall skill", "sandboxTab": "Sandbox", "loading": "Loading skills...", "noSkills": "No skills found", "noExecutions": "No executions found", "enabled": "Enabled", "disabled": "Disabled", - "delete": "Eliminar", + "delete": "Delete", "version": "Version", "tableDescription": "Description", "skill": "Skill", @@ -4279,41 +4284,41 @@ "filterSkillsPlaceholder": "Filtrar habilidades por nombre, descripción o etiqueta", "allModes": "Todos los modos", "totalSkills": "Total de habilidades", - "enabledSkills": "Habilitado", + "enabledSkills": "Activadas", "totalExecutions": "Ejecuciones", "successRate": "Tasa de éxito", - "marketplaceTab": "Marketplace", - "applyFilters": "Aplicar filtros", - "popularDefaultsLabel": "Populares por defecto para el proveedor seleccionado:", - "onMode": "ACTIVADO", - "offMode": "DESACTIVADO", + "marketplaceTab": "Mercado de habilidades", + "applyFilters": "Apply filters", + "popularDefaultsLabel": "Popular by default for selected provider:", + "onMode": "ON", + "offMode": "OFF", "autoMode": "AUTO", - "installSkillButton": "Instalar habilidad", - "installSkillModalTitle": "Instalar habilidad", - "installJsonPlaceholder": "Pega el JSON del manifiesto de la habilidad aquí...", + "installSkillButton": "Install Skill", + "installSkillModalTitle": "Install Skill", + "installJsonPlaceholder": "Paste skill manifest JSON here...", "installing": "Instalando...", "installSuccess": "Habilidad instalada ({id})", - "installError": "Error de instalación", - "invalidJson": "JSON no válido", - "searchMarketplacePlaceholder": "Buscar habilidades...", - "searchMarketplace": "Buscar en el Marketplace", - "marketplaceEmpty": "No se encontraron habilidades en el marketplace", - "marketplaceError": "Error en la búsqueda", - "installingFromMarketplace": "Instalando desde el marketplace...", - "popularSkills": "Habilidades populares", + "installError": "Install failed", + "invalidJson": "Invalid JSON", + "searchMarketplacePlaceholder": "Search skills...", + "searchMarketplace": "Search Marketplace", + "marketplaceEmpty": "No skills found in marketplace", + "marketplaceError": "Search failed", + "installingFromMarketplace": "Installing from marketplace...", + "popularSkills": "Popular Skills", "skillsMarketplace": "Mercado de habilidades", - "searching": "Buscando...", - "pageInfo": "Página {page} de {totalPages} ({total} en total)", - "previous": "Anterior", - "next": "Siguiente", - "activeProvider": "Proveedor activo:", - "changeInSettings": "Cambia esto en Configuración → Memoria y habilidades.", - "installs": "instalaciones", - "marketplaceSkillsMpHint": "Configura tu clave de API de SkillsMP en Configuración para explorar el marketplace.", - "marketplaceSkillsShHint": "Busca en el directorio abierto skills.sh para descubrir e instalar habilidades de agentes.", - "installSkillModalDesc": "Pega un JSON de manifiesto de habilidad o sube un archivo .json.", - "uploadJson": "Subir JSON", - "cancel": "Cancelar", + "searching": "Searching...", + "pageInfo": "Page {page} of {totalPages} ({total} total)", + "previous": "Previous", + "next": "Next", + "activeProvider": "Active provider:", + "changeInSettings": "Change this in Settings → Memory & Skills.", + "installs": "installs", + "marketplaceSkillsMpHint": "Configure your SkillsMP API key in Settings to browse the marketplace.", + "marketplaceSkillsShHint": "Search the skills.sh open directory to discover and install agent skills.", + "installSkillModalDesc": "Paste a skill manifest JSON or upload a .json file.", + "uploadJson": "Upload JSON", + "cancel": "Cancel", "installSkill": "Instalar habilidad" }, "health": { @@ -4395,27 +4400,27 @@ "throttleStatus": "Throttle: {value}", "lastHeaderUpdate": "Header update: {age}", "databaseHealth": "Estado de la base de datos", - "databaseHealthDescription": "Diagnostica y repara filas obsoletas de cuota/dominio y referencias rotas de combinaciones.", - "status": "Estado", - "attentionNeeded": "Requiere atención", - "repairs": "Reparaciones", - "repairing": "Reparando...", - "runAutoRepair": "Ejecutar autorreparación", - "repairBackupCreated": "Se creó una copia de seguridad de reparación antes de modificar.", - "sessionActivity": "Actividad de la sesión", - "activeCount": "{count} activos", - "requestCount": "{count, plural, one {# solicitud} other {# solicitudes}}", - "idleSeconds": "{count}s inactivo", - "ageSeconds": "{count}s de antigüedad", - "quotaMonitors": "Monitores de cuota", - "alerting": "En alerta", - "errors": "Errores", - "degradationFull": "Completo", - "degradationReduced": "Reducido", - "degradationMinimal": "Mínimo", - "degradationDefault": "Predeterminado", - "sinceTime": "Desde {time}", - "retryIn": "reintentar en {duration}", + "databaseHealthDescription": "Diagnose and repair stale quota/domain rows and broken combo references.", + "status": "Status", + "attentionNeeded": "Attention needed", + "repairs": "Repairs", + "repairing": "Repairing...", + "runAutoRepair": "Run Auto-Repair", + "repairBackupCreated": "A repair backup was created before mutating.", + "sessionActivity": "Session Activity", + "activeCount": "{count} active", + "requestCount": "{count, plural, one {# request} other {# requests}}", + "idleSeconds": "{count}s idle", + "ageSeconds": "{count}s age", + "quotaMonitors": "Quota Monitors", + "alerting": "Alerting", + "errors": "Errors", + "degradationFull": "Full", + "degradationReduced": "Reduced", + "degradationMinimal": "Minimal", + "degradationDefault": "Default", + "sinceTime": "Since {time}", + "retryIn": "retry in {duration}", "stickyBoundSessions": "Sesiones encuadernadas", "sessionsByApiKey": "Sesiones por clave API", "noActiveSessionsTracked": "Aún no se han registrado sesiones activas.", @@ -4423,33 +4428,33 @@ "gracefulDegradationStatus": "Estado de degradación elegante", "additionalModels": "+{count} más modelos", "providerHealthMatrixTitle": "Matriz de salud de proveedores", - "providerHealthMatrixDescription": "Estados de proveedor × cuenta × modelo a partir de disyuntores, enfriamientos, bloqueos y registros.", + "providerHealthMatrixDescription": "Estados de Proveedor × Cuenta × Modelo obtenidos de disyuntores, enfriamientos, bloqueos y registros.", "healthMatrixRange": "Rango de la matriz de salud", - "providerFilter": "Filtro de proveedores", + "providerFilter": "Filtro de proveedor", "onlyIssues": "Solo problemas", - "refresh": "Actualizar", - "accounts": "Cuentas", - "models": "Modelos", - "issues": "Problemas", - "loadingProviderHealthMatrix": "Cargando matriz de estado de proveedores...", - "failedProviderHealthMatrix": "Error al cargar la matriz de estado de proveedores: {error}", - "noProvidersMatchedFilters": "Ningún proveedor coincide con los filtros actuales.", - "modelPillSummary": "{requests} req · {successRate} éxito · {latency} prom.", - "modelLockoutSummary": "{reason} · {duration} restante", - "locked": "bloqueado", - "inferred": "inferido", - "inactive": "Inactivo", - "noConnectionId": "sin id de conexión", - "accountModelSummary": "{connectionId} · {count} modelos", - "cooldown": "enfriamiento", - "durationRemaining": "{duration} restante", - "noSyncedModelsOrTraffic": "Aún no hay modelos sincronizados ni tráfico reciente.", - "providerRowSummary": "{active}/{total} cuentas activas · {requests} req · {successRate} éxito · {latency} prom.", - "cooldownCount": "{count} en enfriamiento", - "lockoutCount": "{count} bloqueos", - "issueCount": "{count} problemas", - "score": "Puntuación", - "lastRequest": "Última solicitud", + "refresh": "Refresh", + "accounts": "Accounts", + "models": "Models", + "issues": "Issues", + "loadingProviderHealthMatrix": "Loading provider health matrix...", + "failedProviderHealthMatrix": "Failed to load Provider Health Matrix: {error}", + "noProvidersMatchedFilters": "No providers matched the current filters.", + "modelPillSummary": "{requests} req · {successRate} success · {latency} avg", + "modelLockoutSummary": "{reason} · {duration} left", + "locked": "locked", + "inferred": "inferred", + "inactive": "Inactive", + "noConnectionId": "no connection id", + "accountModelSummary": "{connectionId} · {count} models", + "cooldown": "Enfriamiento", + "durationRemaining": "{duration} remaining", + "noSyncedModelsOrTraffic": "No synced models or recent traffic yet.", + "providerRowSummary": "{active}/{total} active accounts · {requests} req · {successRate} success · {latency} avg", + "cooldownCount": "{count} cooldown", + "lockoutCount": "{count} lockouts", + "issueCount": "{count} issues", + "score": "Score", + "lastRequest": "Last request", "lastError": "Último error" }, "telemetry": { @@ -4579,14 +4584,14 @@ "account": "Account", "elapsed": "Elapsed", "activeStage": "Etapa", - "activeStageUnknown": "Aún no enviado al upstream", + "activeStageUnknown": "Aún no se ha enviado al servidor superior", "activeStageRegistered": "Registrado", - "activeStagePayloadPrepared": "Payload preparado", - "activeStageWaitingAccountSlot": "Esperando slot de cuenta", - "activeStageWaitingRateLimit": "Esperando al limitador de tasa", - "activeStageRateLimitSlotAcquired": "Slot de límite de tasa adquirido", - "activeStageSendingToProvider": "Enviando al upstream", - "activeStageProviderResponseStarted": "Respuesta del upstream iniciada", + "activeStagePayloadPrepared": "Carga útil preparada", + "activeStageWaitingAccountSlot": "Esperando ranura de cuenta", + "activeStageWaitingRateLimit": "Waiting for rate limiter", + "activeStageRateLimitSlotAcquired": "Rate limit slot acquired", + "activeStageSendingToProvider": "Sending to upstream", + "activeStageProviderResponseStarted": "Upstream response started", "count": "Count", "payloads": "Payloads", "viewPayloads": "View", @@ -4598,14 +4603,14 @@ "export": "Export", "exporting": "Exporting...", "exportFailed": "Export failed", - "cleanHistoryButton": "Limpiar historial", - "cleanHistoryTitle": "¿Limpiar el historial de registros?", - "cleanHistoryMessage": "Esto borra permanentemente todas las filas de registros de solicitudes, las filas de detalles heredadas y los archivos de artefactos locales en DATA_DIR/call_logs. La página en vivo se actualizará después de la limpieza.", - "cleanHistoryConfirm": "Limpiar historial", - "cleanHistoryCancel": "Cancelar", - "cleanHistorySuccess": "Se limpiaron {deleted} entradas de registro, {deletedArtifacts} artefactos y {deletedDetailedLogs} filas de detalles heredadas.", - "cleanHistoryEmpty": "No se encontró ningún historial de registro de solicitudes.", - "cleanHistoryFailed": "Error al limpiar el historial de registro.", + "cleanHistoryButton": "Clean history", + "cleanHistoryTitle": "Clean log history?", + "cleanHistoryMessage": "This permanently clears all request log rows, legacy detail rows, and local artifact files under DATA_DIR/call_logs. The live page will refresh after cleanup.", + "cleanHistoryConfirm": "Clean history", + "cleanHistoryCancel": "Cancel", + "cleanHistorySuccess": "Cleaned {deleted} log entries, {deletedArtifacts} artifacts, and {deletedDetailedLogs} legacy detail rows.", + "cleanHistoryEmpty": "No request log history was found.", + "cleanHistoryFailed": "Failed to clean log history.", "timeRange": "Time Range", "lastNHours": "Last {hours}", "defaultRange": "default", @@ -4613,27 +4618,27 @@ "fetchFailed": "Failed to fetch logs", "copyFailed": "Failed to copy log entry", "copyLogEntry": "Copy log entry", - "filterByLevel": "Filtrar por nivel de registro", - "searchPlaceholder": "Buscar registros…", - "searchAria": "Buscar entradas de registro", - "disableAutoScroll": "Desactivar desplazamiento automático", - "enableAutoScroll": "Activar desplazamiento automático", - "autoScroll": "Desplazamiento automático", - "entryCount": "{count, plural, one {# entrada} other {# entradas}}", - "lastHour": "Última 1h", - "updatedAt": "Actualizado {time}", - "fileLoggingRequired": "Asegúrese de que la aplicación esté escribiendo los registros en un archivo (APP_LOG_TO_FILE=true)", - "consoleAria": "Registros de la consola de la aplicación", - "applicationConsole": "Consola de la aplicación", - "emptyFileLoggingHint": "Asegúrese de que APP_LOG_TO_FILE=true esté configurado en su archivo .env" + "filterByLevel": "Filter by log level", + "searchPlaceholder": "Search logs…", + "searchAria": "Search log entries", + "disableAutoScroll": "Disable auto-scroll", + "enableAutoScroll": "Enable auto-scroll", + "autoScroll": "Auto-scroll", + "entryCount": "{count, plural, one {# entry} other {# entries}}", + "lastHour": "Last 1h", + "updatedAt": "Updated {time}", + "fileLoggingRequired": "Make sure the application is writing logs to a file (APP_LOG_TO_FILE=true)", + "consoleAria": "Application console logs", + "applicationConsole": "Application Console", + "emptyFileLoggingHint": "Ensure APP_LOG_TO_FILE=true is set in your .env file" }, - "compressionLogTitle": "Registro de compresión", - "compressionLogEmpty": "Aún no hay solicitudes comprimidas. Las estadísticas de compresión aparecerán aquí cuando se procesen solicitudes con la compresión habilitada.", + "compressionLogTitle": "Compression Log", + "compressionLogEmpty": "No compressed requests yet. Compression stats will appear here when requests are processed with compression enabled.", "tokens": "tokens" }, "onboarding": { "welcome": "Bienvenido", - "tiers": "Niveles", + "tiers": "Tiers", "security": "Seguridad", "test": "prueba", "ready": "¡Listo!", @@ -4676,8 +4681,8 @@ "apiKeyHelp": "Una clave API es una contraseña para los servicios de IA. Obtenga uno del sitio web de su proveedor (por ejemplo, platform.openai.com, console.anthropic.com).", "tier": { "subtitle": "OmniRoute organiza a los proveedores en tres niveles para que las rutas prefieran primero la ruta más confiable y de menor costo.", - "flowCaption": "Las solicitudes fluyen primero a través de sus cuotas de suscripción, luego por proveedores económicos de pago por token y, por último, por proveedores de nivel gratuito: automático, sin configuración.", - "afterSetup": "después de la configuración.", + "flowCaption": "Requests flow through your subscription quotas first, then pay-per-token cheap providers, then free-tier providers — automatic, zero-config.", + "afterSetup": "after setup.", "tier1": { "label": "Clientes premium", "description": "CLI de primera clase con flujos de autenticación nativos y modelos de razonamiento." @@ -4697,7 +4702,7 @@ }, "providers": { "title": "Proveedores", - "Account Deactivated": "Cuenta desactivada", + "Account Deactivated": "Account Deactivated", "allProviders": "Todos los proveedores", "audioProviders": "Proveedores de audio", "showFreeOnly": "Sólo gratis", @@ -4705,50 +4710,50 @@ "addFirstProvider": "Añade tu primer proveedor", "addFirstProviderDesc": "Conecte un proveedor de IA para comenzar a enrutar solicitudes a través de OmniRoute. Puede utilizar proveedores gratuitos, claves API o cuentas OAuth.", "learnMore": "Más información", - "importFromFile": "Importar desde archivo", - "importFromFileTitle": "Importar proveedores desde archivo", - "importFromFileDescription": "Suba un archivo CSV o JSON que contenga varios proveedores (cada fila puede ser de un tipo de proveedor diferente). Revise las filas analizadas a continuación y elija cuáles importar.", - "importFromFileChoose": "Elegir archivo", - "importFromFileSelectHint": "{count} de {total} seleccionados", - "importFromFileColProvider": "Proveedor", - "importFromFileColName": "Nombre", - "importFromFileColBaseUrl": "URL base", - "importFromFileErrorLine": "Fila {line}: {reason}", - "importErrorMissingProvider": "falta el proveedor", - "importErrorMissingName": "falta el nombre", - "importErrorMissingApiKey": "falta la clave API", - "importErrorInvalidPriority": "prioridad no válida (debe ser de 1 a 100)", - "importErrorMalformedRow": "fila con formato incorrecto", - "importErrorNotArray": "el archivo debe contener una matriz JSON", - "importFromFileImporting": "Importando…", - "importFromFileImport": "Importar {count} proveedores", - "importFromFileResult": "Se importaron {success} proveedores ({failed} fallidos)", + "importFromFile": "Import from file", + "importFromFileTitle": "Import providers from file", + "importFromFileDescription": "Upload a CSV or JSON file listing multiple providers (each row can be a different provider type). Review the parsed rows below and pick which ones to import.", + "importFromFileChoose": "Choose file", + "importFromFileSelectHint": "{count} of {total} selected", + "importFromFileColProvider": "Provider", + "importFromFileColName": "Name", + "importFromFileColBaseUrl": "Base URL", + "importFromFileErrorLine": "Row {line}: {reason}", + "importErrorMissingProvider": "missing provider", + "importErrorMissingName": "missing name", + "importErrorMissingApiKey": "missing API key", + "importErrorInvalidPriority": "invalid priority (must be 1-100)", + "importErrorMalformedRow": "malformed row", + "importErrorNotArray": "file must contain a JSON array", + "importFromFileImporting": "Importing…", + "importFromFileImport": "Import {count} providers", + "importFromFileResult": "Imported {success} providers ({failed} failed)", "adaptaTutorial": { - "title": "Cómo conectar Adapta Web", - "introPrefix": "Adapta se autentica a través de Clerk. El token", - "introSuffix": "es un JWT de larga duración que permite a OmniRoute actualizar las sesiones automáticamente.", - "or": "o", - "step1Title": "Abrir el chat de Adapta", - "step1DescPrefix": "Abrir", - "step1DescSuffix": "e inicia sesión con tu cuenta Gold o Business.", - "step2Title": "Abrir DevTools", - "step2DescPrefix": "Presiona", - "step2DescSuffix": "para abrir las Herramientas de desarrollo.", - "step3Title": "Ve a Application → Cookies", - "step3DescPrefix": "En", - "step3DescMiddle": "expande", - "step3DescSuffix": "y haz clic en", - "step4Title": "Copia el valor de la cookie para", - "step4DescPrefix": "Busca la cookie llamada", - "step4DescMiddle": "en la lista. Haz clic en ella y copia el contenido de la", - "step4DescSuffix": "columna. Comienza con", - "step5Title": "Pégalo aquí y guarda", - "step5DescPrefix": "Haz clic en", - "step5DescMiddle": "pega el", - "step5DescSuffix": "valor en el campo API Key, luego guarda. OmniRoute actualizará la sesión automáticamente.", - "tipLabel": "Consejo:", - "tipPrefix": "La", - "tipSuffix": "cookie es de larga duración, normalmente dura meses. Solo necesitas renovarla si cierras sesión o si Adapta invalida la sesión." + "title": "How to connect Adapta Web", + "introPrefix": "Adapta authenticates through Clerk. The token", + "introSuffix": "is a long-lived JWT that lets OmniRoute refresh sessions automatically.", + "or": "or", + "step1Title": "Open Adapta chat", + "step1DescPrefix": "Open", + "step1DescSuffix": "and sign in with your Gold or Business account.", + "step2Title": "Open DevTools", + "step2DescPrefix": "Press", + "step2DescSuffix": "to open Developer Tools.", + "step3Title": "Go to Application → Cookies", + "step3DescPrefix": "In the", + "step3DescMiddle": "expand", + "step3DescSuffix": "and click", + "step4Title": "Copy the cookie value for", + "step4DescPrefix": "Find the cookie named", + "step4DescMiddle": "in the list. Click it and copy the content from the", + "step4DescSuffix": "column. It starts with", + "step5Title": "Paste it here and save", + "step5DescPrefix": "Click", + "step5DescMiddle": "paste the", + "step5DescSuffix": "value into the API Key field, then save. OmniRoute will refresh the session automatically.", + "tipLabel": "Tip:", + "tipPrefix": "The", + "tipSuffix": "cookie is long-lived, usually for months. You only need to renew it if you sign out or Adapta invalidates the session." }, "editProvider": "Editar proveedor", "deleteProvider": "Eliminar proveedor", @@ -4778,38 +4783,38 @@ "reorderByAvailability": "Reordenar", "reorderByAvailabilityTitle": "Reordenar conexiones por disponibilidad", "reorderByAvailabilityError": "No se pudieron reordenar las conexiones por disponibilidad", - "distributeProxies": "Distribuir proxies", - "distributing": "Distribuyendo...", - "selectedCount": "{count, plural, one {# seleccionado} other {# seleccionados}}", - "accountsCount": "{count, plural, one {# cuenta} other {# cuentas}}", + "distributeProxies": "Distribute Proxies", + "distributing": "Distributing...", + "selectedCount": "{count, plural, one {# selected} other {# selected}}", + "accountsCount": "{count, plural, one {# account} other {# accounts}}", "testAllOAuth": "Pruebe todas las conexiones OAuth", "testAllFree": "Pruebe todas las conexiones gratuitas", "testAllApiKey": "Pruebe todas las conexiones de clave API", "testAllCompatible": "Pruebe todas las conexiones compatibles", - "testAllModels": "Probar todos los modelos", - "testAllModelsConfirm": "¿Probar todos los modelos visibles? Los modelos fallidos se ocultarán si la ocultación automática está activada.", - "testingAllModels": "Probando {done}/{total}...", - "testAllResults": "{ok} de {total} modelos funcionando", - "noModelsToTest": "Ningún modelo coincide con el filtro actual", - "showAllModels": "Todos", - "showVisibleOnly": "Solo visibles", - "freeFilterAll": "Todos", - "freeFilterFreeOnly": "Solo gratis", - "freeFilterPaidOnly": "Solo de pago", - "sortFreeFirst": "Gratis primero", - "showHiddenOnly": "Solo ocultos", - "filterByVisibility": "Filtrar por visibilidad", - "autoHideFailed": "Ocultar automáticamente modelos fallidos", - "autoHideFailedHint": "Cuando está habilitado, Probar todo oculta los fallos no transitorios de los catálogos públicos como /v1/models. Las pruebas de un solo modelo nunca se ocultan automáticamente.", + "testAllModels": "Test all models", + "testAllModelsConfirm": "Test all visible models? Failed models will be hidden if auto-hide is enabled.", + "testingAllModels": "Testing {done}/{total}...", + "testAllResults": "{ok} of {total} models working", + "noModelsToTest": "No models match the current filter", + "showAllModels": "All", + "showVisibleOnly": "Visible only", + "freeFilterAll": "All", + "freeFilterFreeOnly": "Free only", + "freeFilterPaidOnly": "Paid only", + "sortFreeFirst": "Free first", + "showHiddenOnly": "Hidden only", + "filterByVisibility": "Filter by visibility", + "autoHideFailed": "Auto-hide failed models", + "autoHideFailedHint": "When enabled, Test all hides non-transient failures from public catalogs such as /v1/models. Single-model tests never auto-hide.", "connected": "{count} Conectado", "errorCount": "{count} Error ({code})", "errorCountNoCode": "{count} Error", - "testAllCompleted": "Probados {total} modelos: {ok} OK, {failed} fallidos", - "modelAutoHidden": "Modelo {model} ocultado automáticamente (prueba fallida)", + "testAllCompleted": "Tested {total} models: {ok} OK, {failed} failed", + "modelAutoHidden": "Model {model} auto-hidden (test failed)", "filterAll": "Todos", - "filterVisible": "Solo visibles", - "filterHidden": "Solo ocultos", - "modelsHiddenCount": "{count} ocultos", + "filterVisible": "Visible only", + "filterHidden": "Hidden only", + "modelsHiddenCount": "{count} hidden", "warningCount": "{count} Advertencia", "noConnections": "Sin conexiones", "expiredBadge": "Expired", @@ -4818,20 +4823,20 @@ "freeTierAvailable": "Nivel gratuito disponible", "hasFreeTooltip": "Nivel gratuito disponible", "noAuthLabel": "Sin autenticación", - "noAuthProviders": "Sin proveedores de autenticación", - "upstreamProxyLabel": "Proxy upstream", - "freeAggregated": "Todos los proveedores con nivel gratuito (también se muestran en su categoría nativa)", + "noAuthProviders": "Proveedores sin autenticación", + "upstreamProxyLabel": "Proxy superior", + "freeAggregated": "Todos los proveedores con nivel gratuito (también mostrados en su categoría nativa)", "deprecated": "En desuso", "deprecatedProvider": "Este proveedor ha quedado obsoleto.", "riskNotice": { - "title": "Antes de continuar", - "tooltip": "Proveedor con advertencias de uso — haz clic para ver los detalles", - "oauth": "Este proveedor utiliza tu sesión oficial del producto/OAuth, que no está autorizada para el uso de proxy/enrutador. No recomendamos el uso intensivo de agentes autónomos (estilo OpenCloud, flujos largos de varios pasos, lotes grandes); el upstream puede reaccionar restringiendo o prohibiendo la cuenta. Úsalo bajo tu propio riesgo.", - "webCookie": "Este proveedor se autentica a través de las cookies de tu sesión web. El servicio upstream puede invalidar la sesión en cualquier momento, lo que requerirá que vuelvas a iniciar sesión. No se recomienda para operaciones prolongadas sin supervisión. Úsalo bajo tu propio riesgo.", - "deprecated": "Este proveedor fue descontinuado por su upstream y puede dejar de funcionar sin previo aviso. Las conexiones existentes pueden seguir funcionando hasta que el upstream elimine por completo el acceso. Considera alternativas.", - "dontShowAgain": "No volver a mostrar esto para este proveedor", - "understand": "Entiendo, continuar", - "cancel": "Cancelar" + "title": "Before continuing", + "tooltip": "Provider with usage caveats — click for details", + "oauth": "This provider uses your official product session/OAuth, which is not authorized for proxy/router use. We don't recommend intensive autonomous agent usage (OpenCloud-style, long multi-step flows, large batches) — the upstream may react by restricting or banning the account. Use at your own risk.", + "webCookie": "This provider authenticates through your web session cookies. The upstream service may invalidate the session at any time, requiring you to log in again. Not recommended for long unattended operations. Use at your own risk.", + "deprecated": "This provider was discontinued by its upstream and may stop working without notice. Existing connections may continue working until the upstream fully removes access. Consider alternatives.", + "dontShowAgain": "Don't show this again for this provider", + "understand": "I understand, continue", + "cancel": "Cancel" }, "disabled": "Discapacitado", "enableProvider": "Habilitar proveedor", @@ -4895,8 +4900,8 @@ "prefixHint": "Requerido. Prefijo único para nombres de modelos.", "nameHint": "Requerido. Una etiqueta amigable para este nodo.", "baseUrlHint": "Requerido. URL base de la API del proveedor.", - "iconUrlLabel": "URL del icono", - "iconUrlHint": "Opcional. URL de la imagen que se muestra como icono de este proveedor.", + "iconUrlLabel": "Icon URL", + "iconUrlHint": "Optional. Image URL shown as this provider's icon.", "anthropicPrefixPlaceholder": "producto ac", "openaiPrefixPlaceholder": "oc-prod", "anthropicBaseUrlPlaceholder": "https://api.anthropic.com/v1", @@ -4913,25 +4918,26 @@ "batchDeleteSelected": "Delete Selected ({count})", "batchDeleteConfirm": "Delete {count} connection(s)? This action cannot be undone.", "batchDeleteSuccess": "Deleted {count} connection(s)", - "batchActivateSelected": "Activar", - "batchDeactivateSelected": "Desactivar", - "batchRetestSelected": "Volver a probar", - "batchActivateSuccess": "Activada(s) {count} conexión(es)", - "batchDeactivateSuccess": "Desactivada(s) {count} conexión(es)", - "batchUpdatePartial": "{count} actualizadas, {skipped} omitidas (ya no existen)", - "batchUpdateNone": "No se actualizó ninguna conexión (es posible que ya no existan)", - "batchRetestLimit": "Volver a probar hasta {max} conexiones a la vez", - "noConnectionsToTest": "No hay conexiones coincidentes para probar", - "batchDeleteConfirmTitle": "Eliminar conexiones", - "batchDeleteConfirmButton": "Eliminar", + "batchActivateSelected": "Activate", + "batchDeactivateSelected": "Deactivate", + "batchRetestSelected": "Retest", + "batchActivateSuccess": "Activated {count} connection(s)", + "batchDeactivateSuccess": "Deactivated {count} connection(s)", + "batchUpdatePartial": "{count} updated, {skipped} skipped (no longer exist)", + "batchUpdateNone": "No connections were updated (they may no longer exist)", + "batchRetestLimit": "Retest up to {max} connections at a time", + "noConnectionsToTest": "No matching connections to test", + "batchDeleteConfirmTitle": "Delete connections", + "batchDeleteConfirmButton": "Delete", "filterActive": "Activo", "filterError": "Error", "filterBanned": "Bloqueado", "filterCreditsExhausted": "Créditos agotados", - "noFilteredConnections": "Ninguna conexión coincide con el filtro actual.", + "accountSearchPlaceholder": "Search accounts…", + "noFilteredConnections": "No connections match the current filter.", "failedSetAlias": "No se pudo establecer el alias", - "setAliasSuccess": "Alias {alias} establecido", - "deleteAliasSuccess": "Alias {alias} eliminado", + "setAliasSuccess": "Alias {alias} set", + "deleteAliasSuccess": "Alias {alias} deleted", "failedSaveConnection": "No se pudo guardar la conexión", "failedSaveConnectionRetry": "No se pudo guardar la conexión. Por favor inténtalo de nuevo.", "failedRetestConnection": "No se pudo volver a probar la conexión", @@ -4965,8 +4971,8 @@ "connectionCount": "{count} conexión(es)", "fetchingModels": "Recuperando modelos disponibles...", "failedFetchModels": "No se pudieron recuperar los modelos", - "noFreeModelsFound": "No se encontraron modelos gratuitos para este proveedor — no se importó nada.", - "fetchModelsSuccess": "Se encontraron {count} nuevos modelos", + "noFreeModelsFound": "No free models found for this provider — nothing imported.", + "fetchModelsSuccess": "Found {count} new models", "fetchModelsFailed": "Could not auto-fetch models (you can retry from settings)", "noModelsFound": "No se encontraron modelos", "importFailed": "Importación fallida", @@ -4986,15 +4992,15 @@ "removeModel": "Quitar modelo", "rateLimitProtected": "Protegido", "rateLimitUnprotected": "Desprotegido", - "providerQuotaShort": "Cuota", - "hideConnectionFromProviderQuota": "Ocultar esta cuenta de la Cuota del proveedor", - "showConnectionInProviderQuota": "Mostrar esta cuenta en la Cuota del proveedor", - "quotaVisibilityUpdateFailed": "Error al actualizar la visibilidad de la Cuota del proveedor", + "providerQuotaShort": "Quota", + "hideConnectionFromProviderQuota": "Hide this account from Provider Quota", + "showConnectionInProviderQuota": "Show this account in Provider Quota", + "quotaVisibilityUpdateFailed": "Failed to update Provider Quota visibility", "enableRateLimitProtection": "Haga clic para habilitar la protección del límite de velocidad", "disableRateLimitProtection": "Haga clic para desactivar la protección del límite de velocidad", - "testAllProgress": "Probados {done}/{total}", - "testAllFailedHidden": "{count} modelos fallidos ocultados", - "testAllDone": "Todos los modelos probados", + "testAllProgress": "Tested {done}/{total}", + "testAllFailedHidden": "{count} failed models hidden", + "testAllDone": "All models tested", "productionKey": "Clave de producción", "enterNewApiKey": "Ingrese la nueva clave API", "codexApplyModalTitle": "Aplicar al códice local", @@ -5013,8 +5019,8 @@ "optional": "Opcional", "anthropicCompatibleName": "Compatible antrópico", "openaiCompatibleName": "Compatible con OpenAI", - "compatibleDefaultModelLabel": "Modelo predeterminado", - "compatibleDefaultModelHint": "Introduzca el ID del modelo exactamente como lo espera su punto de conexión compatible. Este modelo se guardará como el predeterminado de la conexión.", + "compatibleDefaultModelLabel": "Default Model", + "compatibleDefaultModelHint": "Enter the model ID exactly as your compatible endpoint expects it. This model will be saved as the connection default.", "failedImportModels": "No se pudieron importar modelos", "noModelsReturnedFromEndpoint": "No se devolvieron modelos desde el punto final /models.", "importingModelsProgress": "Importando {current} de {total} modelos...", @@ -5072,20 +5078,20 @@ "errorTypeNetworkError": "error de red", "errorTypeTestUnsupported": "Prueba no compatible", "errorTypeUpstreamError": "Error ascendente", - "errorTypeCreditsExhausted": "Sin créditos", - "errorTypeBanned": "403 Prohibido", + "errorTypeCreditsExhausted": "No credits", + "errorTypeBanned": "403 Banned", "proxySourceGlobal": "Mundial", "proxySourceProvider": "Proveedor", "proxySourceKey": "clave", "proxyConfiguredBySource": "Proxy ({source}): {host}", - "proxyOn": "Proxy activado", - "proxyOff": "Directo (omitir proxy)", - "proxyEnabledTitle": "El proxy está habilitado para esta conexión", - "proxyDisabledTitle": "Conexión directa: omite todos los proxies (incluido el proxy global) para esta conexión", - "perKeyProxyOn": "Por clave", - "perKeyProxyOff": "Conexión", - "perKeyProxyEnabledTitle": "Asignación de proxy por clave habilitada para este proveedor", - "perKeyProxyDisabledTitle": "Asignación de proxy por clave deshabilitada para este proveedor", + "proxyOn": "Proxy On", + "proxyOff": "Direct (bypass proxy)", + "proxyEnabledTitle": "Proxy is enabled for this connection", + "proxyDisabledTitle": "Direct connection — bypasses every proxy (including the global proxy) for this connection", + "perKeyProxyOn": "Per-key", + "perKeyProxyOff": "Connection", + "perKeyProxyEnabledTitle": "Per-key proxy assignment enabled for this provider", + "perKeyProxyDisabledTitle": "Per-key proxy assignment disabled for this provider", "autoPriority": "Automático: {priority}", "proxy": "apoderado", "retestAuthentication": "Volver a probar la autenticación", @@ -5116,44 +5122,44 @@ "compatProtocolOpenAI": "OpenAI Chat Completions", "compatProtocolOpenAIResponses": "OpenAI Responses API", "compatProtocolClaude": "Anthropic Messages", - "targetFormatLabel": "Formato de destino", - "targetFormatHint": "Invalida el formato de transmisión ascendente. Usa 'Anthropic Messages' para enrutar proveedores compatibles con OpenAI (por ejemplo, opencode-go) a través del punto de conexión /v1/messages.", - "targetFormatAuto": "Predeterminado (auto)", + "targetFormatLabel": "Target Format", + "targetFormatHint": "Override the upstream wire format. Use 'Anthropic Messages' to route OpenAI-compatible providers (e.g. opencode-go) through the /v1/messages endpoint.", + "targetFormatAuto": "Default (auto)", "targetFormatGemini": "Gemini", "targetFormatAntigravity": "Antigravity", - "contextWindowOverrideLabel": "Invalidación de la ventana de contexto", - "contextWindowOverridePlaceholder": "ej. 131072", - "contextWindowOverrideHint": "Establezca manualmente la ventana de contexto real de este modelo (tokens) cuando el proveedor la informe incorrectamente. Prevalece sobre los valores detectados automáticamente o del catálogo y evita que el enrutamiento combinado descarte el modelo.", - "contextWindowOverrideInvalid": "La invalidación de la ventana de contexto debe ser un número entero positivo de tokens", - "visionCapableLabel": "Compatible con visión", - "visionCapableHint": "Marque manualmente este modelo como compatible con visión cuando los metadatos de detección del proveedor no informen de una modalidad de entrada de imagen (común en backends locales o autohospedados).", - "compatParamFiltersLabel": "Filtros de parámetros", - "compatBlockedParamsHint": "Parámetros bloqueados (eliminados de las solicitudes)", - "compatAllowedParamsHint": "Parámetros permitidos (reincorporados tras la denegación)", - "paramFiltersSectionTitle": "Filtros de parámetros", - "paramFiltersSectionHint": "Elimine o vuelva a agregar parámetros de solicitud antes de enviarlos a este proveedor. Se utiliza para evitar errores 400 de proveedores que rechazan ciertos parámetros (por ejemplo, NVIDIA NIM rechaza thinking).", - "paramFiltersBlockedLabel": "Parámetros bloqueados", - "paramFiltersBlockedHint": "Estos parámetros se eliminan de las solicitudes salientes (lista de denegación).", - "paramFiltersAllowedLabel": "Parámetros permitidos", - "paramFiltersAllowedHint": "Estos parámetros se vuelven a añadir después de la eliminación de la lista de denegación (solo si el cliente los envió).", - "paramFiltersAutoLearnLabel": "Autoaprendizaje a partir de errores 400", - "paramFiltersAutoLearnHint": "Cuando está habilitado, si el upstream devuelve un 400 con \"Unsupported parameter: X\", el parámetro se añade automáticamente a la lista de bloqueo y se reintenta la solicitud.", - "paramFiltersSaving": "Guardando…", - "paramFiltersSaveChanges": "Guardar cambios", - "paramFiltersResetToDefault": "Restablecer a los valores predeterminados", - "paramFiltersLoadError": "Error al cargar la configuración del filtro de parámetros: {error}", - "paramFiltersSaveSuccess": "Configuración del filtro de parámetros guardada", - "paramFiltersSaveError": "Error al guardar la configuración del filtro de parámetros: {error}", - "paramFiltersResetSuccess": "Configuración del filtro de parámetros restablecida a los valores predeterminados", - "paramFiltersResetError": "Error al restablecer la configuración del filtro de parámetros: {error}", - "interceptionSectionTitle": "Intercepción de herramientas web", - "interceptionSectionHint": "Enrutar las llamadas a las herramientas nativas web_search / web_fetch de este proveedor a través de los propios endpoints de búsqueda y obtención de OmniRoute en lugar de permitir que el proveedor las ejecute de forma nativa. Desactivado por defecto; el comportamiento existente no cambia.", - "interceptSearchLabel": "Interceptar web_search", - "interceptSearchHint": "Reescribir las llamadas a la herramienta nativa web_search hacia /v1/search de OmniRoute.", - "interceptFetchLabel": "Interceptar web_fetch", - "interceptFetchHint": "Reescribir las llamadas a la herramienta nativa web_fetch hacia /v1/web/fetch de OmniRoute.", - "interceptionLoadError": "Error al cargar la configuración de intercepción: {error}", - "interceptionSaveError": "Error al guardar la configuración de intercepción: {error}", + "contextWindowOverrideLabel": "Context Window Override", + "contextWindowOverridePlaceholder": "e.g. 131072", + "contextWindowOverrideHint": "Manually set this model's real context window (tokens) when the provider misreports it. Wins over auto-detected/catalog values and prevents combo routing from dropping the model.", + "contextWindowOverrideInvalid": "Context window override must be a positive whole number of tokens", + "visionCapableLabel": "Vision capable", + "visionCapableHint": "Manually flag this model as vision-capable when the provider's discovery metadata doesn't report an image input modality (common for self-hosted/local backends).", + "compatParamFiltersLabel": "Param Filters", + "compatBlockedParamsHint": "Blocked params (stripped from requests)", + "compatAllowedParamsHint": "Allowed params (re-added after deny)", + "paramFiltersSectionTitle": "Param Filters", + "paramFiltersSectionHint": "Strip or re-add request parameters before sending to this provider. Used to avoid 400 errors from providers that reject certain params (e.g. NVIDIA NIM rejects thinking).", + "paramFiltersBlockedLabel": "Blocked parameters", + "paramFiltersBlockedHint": "These params are stripped from outgoing requests (denylist).", + "paramFiltersAllowedLabel": "Allowed parameters", + "paramFiltersAllowedHint": "These params are re-added after denylist stripping (only if the client sent them).", + "paramFiltersAutoLearnLabel": "Auto-learn from 400 errors", + "paramFiltersAutoLearnHint": "When enabled, if the upstream returns a 400 with \"Unsupported parameter: X\", the param is automatically added to the block list and the request retried.", + "paramFiltersSaving": "Saving…", + "paramFiltersSaveChanges": "Save Changes", + "paramFiltersResetToDefault": "Reset to Default", + "paramFiltersLoadError": "Failed to load param filter config: {error}", + "paramFiltersSaveSuccess": "Param filter config saved", + "paramFiltersSaveError": "Failed to save param filter config: {error}", + "paramFiltersResetSuccess": "Param filter config reset to defaults", + "paramFiltersResetError": "Failed to reset param filter config: {error}", + "interceptionSectionTitle": "Web Tool Interception", + "interceptionSectionHint": "Route this provider's native web_search / web_fetch tool calls through OmniRoute's own search and fetch endpoints instead of letting the provider run them natively. Off by default — existing behavior is unchanged.", + "interceptSearchLabel": "Intercept web_search", + "interceptSearchHint": "Rewrite native web_search tool calls to OmniRoute's /v1/search.", + "interceptFetchLabel": "Intercept web_fetch", + "interceptFetchHint": "Rewrite native web_fetch tool calls to OmniRoute's /v1/web/fetch.", + "interceptionLoadError": "Failed to load interception settings: {error}", + "interceptionSaveError": "Failed to save interception settings: {error}", "compatUpstreamHeadersLabel": "Extra upstream headers", "compatUpstreamHeadersHint": "High-privilege setting — same trust level as editing provider API credentials; only trusted admins should use it. Merged after OmniRoute adds auth from the provider API key. If a custom header uses the same name as an existing one (e.g. Authorization), your value fully replaces the auto-generated header (including the Bearer token) — the upstream only sees what you typed, not the key from settings. Misconfiguration can cause 401 or broken upstream auth. One row per header (e.g. extra Authentication for some gateways). Hover or focus the value to preview. Saves on blur, outside click, or closing this panel.", "compatUpstreamHeaderName": "Header name", @@ -5163,8 +5169,8 @@ "compatBadgeUpstreamHeaders": "Headers", "perModelQuotaLabel": "Per Model Quota Label", "perModelQuotaDescription": "Per Model Quota Description", - "importFreeModelsOnlyLabel": "Importar solo modelos gratuitos", - "importFreeModelsOnlyHint": "Cuando está habilitado, solo se importan los modelos gratuitos de este proveedor. Se omiten los modelos de pago.", + "importFreeModelsOnlyLabel": "Import only free models", + "importFreeModelsOnlyHint": "When enabled, only this provider's free models are imported. Paid models are skipped.", "perModelQuotaToggle": "Alternar cuota por modelo", "modelId": "ID del modelo", "customModelPlaceholder": "por ej. gpt-4.5-turbo", @@ -5211,9 +5217,9 @@ "editCompatibleTitle": "Editar {type} Compatible", "compatibleBaseUrlHint": "Root URL of your {type}-compatible API. Use Advanced Settings for custom endpoint paths.", "apiKeyForCheck": "Clave API (para verificación)", - "testModelIdLabel": "ID del modelo (opcional)", - "testModelIdPlaceholder": "p. ej., mi-id-de-modelo", - "testModelIdHint": "Si el proveedor carece de un endpoint /models, introduzca un ID de modelo para validarlo a través de /chat/completions en su lugar.", + "testModelIdLabel": "Model ID (optional)", + "testModelIdPlaceholder": "e.g. my-model-id", + "testModelIdHint": "If the provider lacks a /models endpoint, enter a model ID to validate via /chat/completions instead.", "compatibleProdPlaceholder": "{type} Compatible (Prod.)", "tokenRefreshed": "Token refreshed successfully", "tokenRefreshFailed": "Token refresh failed", @@ -5297,19 +5303,19 @@ "codexAuthApplyFailed": "Failed to apply Codex auth.json locally", "codexAuthExported": "Codex auth.json exported", "codexAuthExportFailed": "Failed to export Codex auth.json", - "codexCliGuideButton": "Guía de la CLI de Codex", - "codexCliGuideTitle": "Guía de la CLI de Codex", - "codexCliGuideLoading": "Cargando guía...", - "codexCliGuideLoadFailed": "No se pudo cargar la guía.", - "codexExternalLinkButton": "Enlace externo de Codex", - "codexExternalLinkModalTitle": "Enlace externo de Codex", - "codexExternalLinkModalDescription": "Comparta este enlace de un solo uso con la persona que autenticará la cuenta de Codex. Deberá abrirlo en su propio navegador, completar el inicio de sesión de OpenAI y la conexión se registrará aquí. El enlace caduca en 15 minutos.", - "codexExternalLinkGenerating": "Generando enlace...", - "codexExternalLinkWaiting": "Esperando la autenticación del navegador. Esta ventana se actualiza automáticamente.", - "codexExternalLinkCreateFailed": "Error al generar el enlace.", - "codexExternalLinkNetworkError": "No se pudo contactar con el servidor.", - "codexExternalLinkConnected": "Cuenta de Codex conectada a través del enlace externo.", - "codexExternalLinkExpired": "El enlace caducó antes de completarse.", + "codexCliGuideButton": "Codex CLI Guide", + "codexCliGuideTitle": "Codex CLI Guide", + "codexCliGuideLoading": "Loading guide...", + "codexCliGuideLoadFailed": "Could not load the guide.", + "codexExternalLinkButton": "External Codex link", + "codexExternalLinkModalTitle": "External Codex link", + "codexExternalLinkModalDescription": "Share this single-use link with the person who will authenticate the Codex account. They open it in their own browser, complete the OpenAI login, and the connection is registered here. The link expires in 15 minutes.", + "codexExternalLinkGenerating": "Generating link...", + "codexExternalLinkWaiting": "Waiting for browser authentication. This window refreshes automatically.", + "codexExternalLinkCreateFailed": "Failed to generate the link.", + "codexExternalLinkNetworkError": "Could not contact the server.", + "codexExternalLinkConnected": "Codex account connected through the external link.", + "codexExternalLinkExpired": "The link expired before completion.", "importCodexAuth": "Importar autenticación", "codexImportModalTitle": "Importar autenticación del Codex", "codexImportTabSingle": "soltero", @@ -5350,8 +5356,8 @@ "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", - "clientIdentityLabel": "Identidad del cliente", - "clientIdentityHint": "Opcional. Agrega encabezados de huella digital del cliente (por ejemplo, User-Agent) que coinciden con una CLI conocida para pasarelas compatibles que esperan uno.", + "clientIdentityLabel": "Client Identity", + "clientIdentityHint": "Optional. Adds client fingerprint headers (e.g. User-Agent) matching a known CLI for compatible gateways that expect one.", "statusDeactivated": "Deactivated (Manual)", "statusBanned": "Banned / Sandbox Violation", "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted", @@ -5390,8 +5396,8 @@ "grokWebCookieHint": "Grok Web Cookie Hint", "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", - "disableCoolingDescription": "Omitir el tiempo de espera transitorio para que esta conexión siga siendo elegible incluso después de errores recuperables (los estados terminales como prohibido/expirado aún se aplican).", - "disableCoolingLabel": "Desactivar el tiempo de espera para esta conexión", + "disableCoolingDescription": "Skip the transient cooldown so this connection stays eligible even after recoverable errors (terminal states like banned/expired still apply).", + "disableCoolingLabel": "Disable cooldown for this connection", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", "bulkPasteDuplicatesIgnored": "{count, plural, one {1 duplicate skipped} other {# duplicates skipped}}", "bulkPasteHint": "Paste one API key per line. Empty lines are ignored and duplicate keys are skipped.", @@ -5457,12 +5463,12 @@ "apiKeyWarningAlertTitle": "API Key Warning", "googlePseInfo": "Google Pse Info", "antigravityProjectIdHint": "Anulación opcional para solicitudes de Antigravity Cloud Code. Déjelo en blanco para utilizar el proyecto descubierto durante Google OAuth.", - "antigravityClientProfileLabel": "Perfil de cliente", - "antigravityClientProfileHint": "Elija qué identidad de cliente de Antigravity presenta OmniRoute a la API.", + "antigravityClientProfileLabel": "Client profile", + "antigravityClientProfileHint": "Choose which Antigravity client identity OmniRoute presents to the API.", "antigravityClientProfileIde": "IDE", "antigravityClientProfileCli": "Harness / CLI", - "codexFastTierActiveChip": "El nivel Codex Fast está activo", - "tierFast": "Rápido", + "codexFastTierActiveChip": "Codex Fast tier is active", + "tierFast": "Fast", "antigravityProjectIdLabel": "ID del proyecto de Google Cloud", "antigravityProjectIdPlaceholder": "mi-id-proyecto-gcp", "grokWebCookiePlaceholder": "Grok Web Cookie Placeholder", @@ -5477,17 +5483,17 @@ "localProviderBaseUrlHint": "Local Provider Base Url Hint", "localProviders": "Local Providers", "maxConcurrentWholeNumberError": "Max Concurrent Whole Number Error", - "m365TierLabel": "Nivel de Copilot", - "m365TierHint": "Elija qué superficie de Microsoft 365 Copilot utiliza esta conexión. Individual es el BizChat de consumo predeterminado; Educación y Empresa (trabajo) optan por las superficies de su inquilino.", - "m365TierIndividualOption": "Individual (predeterminado)", - "m365TierEduOption": "Educación", - "m365TierEnterpriseOption": "Empresa / Trabajo", - "tierOverrideLabel": "Anulación de nivel", - "tierOverrideAuto": "Auto (el enrutamiento decide)", - "tierOverrideFree": "Gratuito", - "tierOverrideCheap": "Económico", + "m365TierLabel": "Copilot tier", + "m365TierHint": "Choose which Microsoft 365 Copilot surface this connection uses. Individual is the default consumer BizChat; Education and Enterprise (work) opt into their tenant surfaces.", + "m365TierIndividualOption": "Individual (default)", + "m365TierEduOption": "Education", + "m365TierEnterpriseOption": "Enterprise / Work", + "tierOverrideLabel": "Tier override", + "tierOverrideAuto": "Auto (routing decides)", + "tierOverrideFree": "Free", + "tierOverrideCheap": "Cheap", "tierOverridePremium": "Premium", - "tierOverrideHelpText": "Fije este proveedor a un nivel de enrutamiento en lugar de permitir que OmniRoute lo infiera a partir del precio del modelo.", + "tierOverrideHelpText": "Pin this provider to a routing tier instead of letting OmniRoute infer it from model pricing.", "museSparkWebCookieHint": "Muse Spark Web Cookie Hint", "museSparkWebCookiePlaceholder": "Muse Spark Web Cookie Placeholder", "oauth": "Oauth", @@ -5501,16 +5507,16 @@ "personalAccessTokenLabel": "Personal Access Token Label", "qoderPatHint": "Qoder Pat Hint", "qoderPatPlaceholder": "Qoder Pat Placeholder", - "rateLimitOverridesSection": "Anulaciones de límite de tasa", - "rateLimitOverridesMaxConcurrentHint": "Anulación de solicitudes concurrentes máximas para esta conexión. Anula el límite a nivel de cuenta.", - "rateLimitOverridesMaxConcurrentLabel": "Máximo de concurrentes (límite de tasa)", - "rateLimitOverridesMinTimeHint": "Tiempo mínimo (ms) entre solicitudes. Anula el retraso predeterminado del limitador de tasa.", - "rateLimitOverridesMinTimeLabel": "Intervalo mín. (ms)", - "rateLimitOverridesRpmHint": "Máximo de solicitudes por minuto para esta conexión. Anula el valor predeterminado del proveedor.", - "rateLimitOverridesRpmLabel": "RPM (Solicitudes/min)", - "rateLimitOverridesTpdHint": "Máximo de tokens por día para esta conexión. Anula el valor predeterminado del proveedor.", - "rateLimitOverridesTpdLabel": "TPD (Tokens/día)", - "rateLimitOverridesTpmHint": "Máximo de tokens por minuto para esta conexión. Anula el valor predeterminado del proveedor.", + "rateLimitOverridesSection": "Rate Limit Overrides", + "rateLimitOverridesMaxConcurrentHint": "Max concurrent requests override for this connection. Overrides the account-level cap.", + "rateLimitOverridesMaxConcurrentLabel": "Max Concurrent (Rate Limit)", + "rateLimitOverridesMinTimeHint": "Minimum time (ms) between requests. Overrides the default rate limiter delay.", + "rateLimitOverridesMinTimeLabel": "Min Interval (ms)", + "rateLimitOverridesRpmHint": "Max requests per minute for this connection. Overrides the provider default.", + "rateLimitOverridesRpmLabel": "RPM (Requests/min)", + "rateLimitOverridesTpdHint": "Max tokens per day for this connection. Overrides the provider default.", + "rateLimitOverridesTpdLabel": "TPD (Tokens/day)", + "rateLimitOverridesTpmHint": "Max tokens per minute for this connection. Overrides the provider default.", "rateLimitOverridesTpmLabel": "TPM (Tokens/min)", "refreshOauthTokenTitle": "Refresh Oauth Token Title", "regionHint": "Region Hint", @@ -5526,7 +5532,7 @@ "searchProvider": "Search Provider", "searchProviderDesc": "Search Provider Desc", "searchProviders": "Buscar proveedores...", - "searchByModel": "Buscar por modelo…", + "searchByModel": "Search by model…", "searchProvidersHeading": "Search Providers Heading", "searxngBaseUrlHint": "Searxng Base Url Hint", "searxngInfo": "Searxng Info", @@ -5559,45 +5565,45 @@ "webCookieProviders": "Web Cookie Providers", "weeklyShort": "Weekly Short", "xiaomiMimoBaseUrlHint": "Xiaomi Mimo Base Url Hint", - "globalCodexServiceMode": "Modo de servicio global de Codex", - "connect": "Conectar", - "manualApiKey": "Clave API manual", - "addPat": "Agregar PAT", - "experimentalOauth": "OAuth experimental", - "importAuth": "Importar autenticación", - "importGrokAuth": "Importar autenticación de Grok Build", - "zedImportTitle": "Importar desde Zed Keychain", - "zedImportDescription": "Descubre las credenciales de proveedores de IA (OpenAI, Anthropic, Google, Mistral, xAI) almacenadas por Zed IDE en el llavero del sistema operativo e impórtalas como conexiones. Zed IDE debe estar instalado en esta máquina.", + "globalCodexServiceMode": "Global Codex service mode", + "connect": "Connect", + "manualApiKey": "Manual API key", + "addPat": "Add PAT", + "experimentalOauth": "Experimental OAuth", + "importAuth": "Import auth", + "importGrokAuth": "Import Grok Build auth", + "zedImportTitle": "Import from Zed Keychain", + "zedImportDescription": "Discover AI provider credentials (OpenAI, Anthropic, Google, Mistral, xAI) stored by Zed IDE in the OS keychain and import them as connections. Zed IDE must be installed on this machine.", "zedImportButton": "Zed Import Button", "zedImportFailed": "Zed Import Failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", + "zedImportSuccess": "Se han importado {credentials} credencial(es) de Zed para {providers} proveedor(es)", "zedImporting": "Zed Importing", - "zedNoCredentials": "No se encontraron credenciales de Zed en el llavero", - "zedUnsupportedCredentials": "Se encontraron {count} credenciales en el llavero, pero ninguna coincide con los proveedores compatibles", - "zedManualTitle": "Importación manual de token", - "zedManualDescription": "Usa esto cuando OmniRoute se ejecute en Docker o el llavero no esté disponible. Pega la clave de API que Zed almacenó en ~/.config/zed/settings.json, o cópiala desde el panel de configuración de Zed AI.", - "zedPasteApiKey": "Pegar clave de API…", - "zedSaving": "Guardando…", - "zedImportAction": "Importar", - "zedManualImportFailed": "Error en la importación manual", - "zedManualImportSuccess": "Token de {provider} importado desde Zed", - "grokImportTitle": "Importar autenticación de Grok Build", - "grokImportDescription": "Importa tu archivo de Grok Build ~/.grok/auth.json. Puedes obtenerlo ejecutando grok login en tu terminal.", - "grokUploadFile": "Subir archivo", - "grokPasteJson": "Pegar JSON", - "grokInvalidAuth": "Este no es un archivo auth.json de Grok Build válido. Se esperaba un objeto con una clave que contenga un JWT.", - "grokParseFailed": "No se pudo analizar el JSON", - "grokImportFailed": "Error al importar la autenticación de Grok Build", - "grokImportSuccess": "Conexión de Grok Build importada correctamente", - "grokValidToken": "Se detectó un token de Grok Build válido", - "grokRefreshIncluded": "Token de actualización incluido — la renovación automática de tokens está activada", - "grokRefreshMissing": "No se encontró ningún token de actualización — vuelve a importar después de que el token expire", - "grokConnectionName": "Nombre de la conexión (opcional)", - "grokSaving": "Guardando…", - "grokSaveConnection": "Guardar conexión", + "zedNoCredentials": "No Zed credentials found in the keychain", + "zedUnsupportedCredentials": "Found {count} keychain credential(s), but none matched supported providers", + "zedManualTitle": "Manual Token Import", + "zedManualDescription": "Use this when OmniRoute runs in Docker or the keychain is unavailable. Paste the API key that Zed stored under ~/.config/zed/settings.json, or copy it from the Zed AI settings panel.", + "zedPasteApiKey": "Paste API key…", + "zedSaving": "Saving…", + "zedImportAction": "Import", + "zedManualImportFailed": "Manual import failed", + "zedManualImportSuccess": "Imported {provider} token from Zed", + "grokImportTitle": "Import Grok Build Auth", + "grokImportDescription": "Import your Grok Build ~/.grok/auth.json file. You can get it by running grok login in your terminal.", + "grokUploadFile": "Upload file", + "grokPasteJson": "Paste JSON", + "grokInvalidAuth": "This is not a valid Grok Build auth.json file. Expected an object with a key containing a JWT.", + "grokParseFailed": "Could not parse JSON", + "grokImportFailed": "Failed to import Grok Build auth", + "grokImportSuccess": "Grok Build connection imported successfully", + "grokValidToken": "Valid Grok Build token detected", + "grokRefreshIncluded": "Refresh token included — automatic token renewal is enabled", + "grokRefreshMissing": "No refresh token found — re-import after the token expires", + "grokConnectionName": "Connection name (optional)", + "grokSaving": "Saving…", + "grokSaveConnection": "Save Connection", "freeTierProviders": "Proveedores de nivel gratuito", "freeTierLabel": "Nivel gratuito disponible", "freeTierProvidersDesc": "Proveedores con niveles gratuitos: algunos requieren un registro de clave API, otros no necesitan ninguna credencial.", @@ -5614,35 +5620,35 @@ "providerDetailPathAutoDetectedAllOs": "La ruta se detecta automáticamente por sistema operativo (Linux/Mac/Windows).", "providerDetailMyClaudeAccountPlaceholder": "Mi cuenta Claude", "providerDetailPathAutoDetected": "La ruta se detecta automáticamente por sistema operativo (Linux/Mac).", - "compatBlockedParamsPlaceholder": "thinking, … (separado por comas)", - "compatAllowedParamsPlaceholder": "reasoning, … (separado por comas)", - "compatSaving": "guardando…", - "paramFiltersBlockedPlaceholder": "thinking, reasoning_budget, … (separado por comas)", - "paramFiltersAllowedPlaceholder": "reasoning, … (separado por comas)", - "customGatewayNamePlaceholder": "Mi Gateway", - "inherit": "Heredar", - "claudeImportEntryName": "entrada {number}", - "claudeImportParseError": "error de análisis", - "claudeImportNoValidEntries": "No hay entradas válidas para importar", + "compatBlockedParamsPlaceholder": "thinking, … (comma-separated)", + "compatAllowedParamsPlaceholder": "reasoning, … (comma-separated)", + "compatSaving": "saving…", + "paramFiltersBlockedPlaceholder": "thinking, reasoning_budget, … (comma-separated)", + "paramFiltersAllowedPlaceholder": "reasoning, … (comma-separated)", + "customGatewayNamePlaceholder": "My Gateway", + "inherit": "Inherit", + "claudeImportEntryName": "entry {number}", + "claudeImportParseError": "parse error", + "claudeImportNoValidEntries": "No valid entries to import", "webFetch": "Web Fetch", - "webFetchTooltip": "Proveedores que extraen contenido de URL web (HTML → Markdown, scrape, captura de pantalla)", - "webFetchProvidersHeading": "Proveedores de Web Fetch", - "compatibleProvidersDesc": "Endpoints compatibles con OpenAI y Anthropic que alojas o configuras. Apunta cualquier SDK de OpenAI a tu propia URL y enruta las solicitudes aquí.", - "oauthProvidersDesc": "Proveedores autenticados a través de OAuth — inicia sesión una vez y OmniRoute se encarga de la rotación de tokens automáticamente.", + "webFetchTooltip": "Providers that extract content from web URLs (HTML → Markdown, scrape, screenshot)", + "webFetchProvidersHeading": "Web Fetch Providers", + "compatibleProvidersDesc": "OpenAI-compatible and Anthropic-compatible endpoints you host or configure. Point any OpenAI SDK to your own URL and route requests here.", + "oauthProvidersDesc": "Providers authenticated via OAuth — sign in once and OmniRoute handles token rotation automatically.", "webCookieProvidersDesc": "Estos proveedores utilizan sesiones web del navegador, cookies o tokens web en lugar de claves API. Abra un proveedor para agregar la credencial de sesión requerida.", - "apiKeyProvidersDesc": "Proveedores estándar de claves de API. Agrega tu clave una vez y OmniRoute enrutará, reintentará y limitará la frecuencia en tu nombre.", - "noAuthProvidersDesc": "Endpoints abiertos que no requieren credenciales — listos para usar de inmediato sin ningún registro.", - "upstreamProxyProvidersDesc": "Enrute el tráfico saliente a través de un proxy ascendente antes de que llegue al proveedor. Útil para redes corporativas o inspección de tráfico.", - "webFetchProvidersDesc": "Proveedores que obtienen y extraen contenido de URL web. Úselos para fundamentar los prompts con datos web en tiempo real.", - "aggregatorsGatewaysDesc": "Agregadores multiproveedor y gateways de IA que exponen una única API unificada para docenas de modelos subyacentes.", - "enterpriseCloudDesc": "Modelos de nivel empresarial y alojados en la nube con SLA mejorados, certificaciones de cumplimiento y capacidad dedicada.", - "cloudAgentProvidersDesc": "Agentes autónomos en la nube que ejecutan tareas de larga duración con aprobación de planes y seguimiento de estado en tiempo real.", - "localProvidersDesc": "Modelos autohospedados que se ejecutan en su propio hardware. Ningún dato sale de su infraestructura.", - "searchProvidersDesc": "Proveedores de búsqueda web y de documentos. Adjúntelos a las llamadas de LLM para la Generación Aumentada por Recuperación.", - "audioProvidersDesc": "Proveedores de texto a voz y de voz a texto para E/S de voz y pipelines de transcripción de audio.", - "embeddingRerankProvidersDesc": "Proveedores de embeddings vectoriales y reranking para búsqueda semántica, pipelines de RAG y puntuación de similitud.", - "imageProvidersDesc": "Proveedores de generación de imágenes y visión — cree imágenes a partir de texto o analice las existentes.", - "videoProvidersDesc": "Proveedores de generación de video. Cree videoclips cortos a partir de prompts de texto o imágenes.", + "apiKeyProvidersDesc": "Standard API key providers. Add your key once and OmniRoute routes, retries, and rate-limits on your behalf.", + "noAuthProvidersDesc": "Open endpoints that require no credentials — ready to use immediately without any sign-up.", + "upstreamProxyProvidersDesc": "Route outbound traffic through an upstream proxy before it reaches the provider. Useful for corporate networks or traffic inspection.", + "webFetchProvidersDesc": "Providers that fetch and extract content from web URLs. Use them to ground prompts with live web data.", + "aggregatorsGatewaysDesc": "Multi-provider aggregators and AI gateways that expose a single unified API across dozens of underlying models.", + "enterpriseCloudDesc": "Enterprise-tier and cloud-hosted models with enhanced SLAs, compliance certifications, and dedicated capacity.", + "cloudAgentProvidersDesc": "Autonomous cloud agents that execute long-running tasks with plan approval and live status tracking.", + "localProvidersDesc": "Self-hosted models running on your own hardware. No data leaves your infrastructure.", + "searchProvidersDesc": "Web and document search providers. Attach them to LLM calls for Retrieval-Augmented Generation.", + "audioProvidersDesc": "Text-to-speech and speech-to-text providers for voice I/O and audio transcription pipelines.", + "embeddingRerankProvidersDesc": "Vector embedding and reranking providers for semantic search, RAG pipelines, and similarity scoring.", + "imageProvidersDesc": "Image generation and vision providers — create images from text or analyse existing ones.", + "videoProvidersDesc": "Video generation providers. Create short video clips from text prompts or images.", "onboardingWizard": "Asistente de incorporación de proveedores", "onboardingWizardShort": "Asistente de incorporación", "onboardingWizardDescription": "Conecte proveedores de clave API, compatibles personalizados y OAuth con validación, persistencia y una prueba de conexión inmediata.", @@ -5710,203 +5716,211 @@ "onboardingOAuthFlowDescription": "OmniRoute abrirá el flujo OAuth existente para este proveedor. Después de iniciar sesión, el asistente recarga la conexión guardada y ejecuta la misma prueba de conexión que la página del proveedor.", "onboardingStartOAuthFlow": "Iniciar flujo de OAuth", "onboardingProviderDescriptions": { - "360ai": "Obtenga la clave API en ai.360.cn", - "agentrouter": "Obtenga $200 en créditos gratuitos en https://agentrouter.org/register — sin necesidad de tarjeta de crédito.", - "agnes": "Obtenga la clave API en agnes-ai.com", - "aimlapi": "Nivel gratuito pausado (2026) — AI/ML API ahora es solo de pago por uso (recarga mínima de $20); sin créditos gratuitos recurrentes.", - "ai21": "$10 en créditos de prueba al registrarse (válidos por 3 meses), sin necesidad de tarjeta de crédito", - "alibaba": "Conecte Alibaba con una clave API.", - "alibaba-cn": "Conecte Alibaba (China) con una clave API.", - "bailian-coding-plan": "Conecte Alibaba Coding Plan con una clave API.", - "bedrock": "Integración nativa de Bedrock: el descubrimiento de modelos utiliza los modelos fundacionales y perfiles de inferencia de Bedrock, mientras que el chat utiliza las API regionales Bedrock Runtime Converse/ConverseStream.", - "anthropic": "Conecte Anthropic con una clave API.", - "api-airforce": "Obtenga su clave API en https://panel.api.airforce — endpoint compatible con OpenAI en https://api.airforce/v1", - "arcee-ai": "Obtenga la clave API en arcee.ai", - "azure-ai": "Foundry utiliza la superficie v1 de OpenAI con nombres de implementación como modelos. OmniRoute normaliza las URL de recursos raíz a los endpoints v1 chat y /models.", - "azure-openai": "Use su clave API de Azure OpenAI. La URL base debe ser el endpoint de su recurso, por ejemplo, https://my-resource.openai.azure.com.", - "bai": "Clave API Bearer para el gateway de LLM compatible con OpenAI de b.ai (diferente de TheB.AI). Cree una clave en https://docs.b.ai, luego use https://api.b.ai/v1 como la URL base compatible con OpenAI.", - "baichuan": "Obtenga la clave API en platform.baichuan-ai.com", - "baidu": "Obtenga la clave API en console.bce.baidu.com", - "qianfan": "Use una clave API de Qianfan de Baidu AI Cloud. El endpoint predeterminado es compatible con OpenAI v2.", - "baseten": "$30 en créditos de prueba gratuitos para inferencia de GPU", - "bazaarlink": "Cree una clave API gratuita en https://bazaarlink.ai — el modelo 'auto:free' enruta a inferencia de costo cero. Todos los modelos utilizan el formato proveedor/nombre-modelo, por ejemplo, xiaomi/mimo-v2.5-pro.", - "black-forest-labs": "Conecte Black Forest Labs con una clave API.", - "blackbox": "Nivel gratuito: chat básico ilimitado más Minimax-M2.5, sin necesidad de tarjeta de crédito", - "bluesminds": "Obtenga su clave API en https://www.bluesminds.com — endpoint compatible con OpenAI en https://api.bluesminds.com/v1 con créditos diarios gratuitos. Los modelos VIP (Claude Opus 4.5, Gemini 2.5 Pro) consumen créditos pi.", - "byteplus": "Conecte BytePlus ModelArk con una clave API.", - "bytez": "$1 en créditos gratuitos, se renueva cada 4 semanas", - "cerebras": "Prueba gratuita: 1M de tokens/día, 30K TPM, 5 RPM — sin tarjeta de crédito.", - "charm-hyper": "Cree una clave API en https://hyper.charm.land, luego péguela aquí como un token Bearer.", - "chutes": "Clave API Bearer para el gateway compatible con OpenAI de Chutes.", - "clarifai": "Clarifai expone chat, respuestas y /models compatibles con OpenAI en /v2/ext/openai/v1. Los modelos públicos/comunitarios normalmente requieren un PAT; las claves con alcance de aplicación solo funcionan para recursos dentro de esa aplicación.", - "cloudflare-ai": "Requiere token de API E ID de cuenta (se encuentra en dash.cloudflare.com)", - "codestral": "Conectar Codestral con una clave de API.", - "cohere": "Prueba gratuita: 1.000 llamadas de API al mes para pruebas, no se requiere tarjeta de crédito", - "command-code": "Cree o copie una clave de API de Command Code, luego péguela aquí como un token Bearer.", - "coze": "Obtenga la clave de API en coze.com/open/api", - "crof": "Conectar CrofAI con una clave de API.", - "databricks": "Conectar Databricks con una clave de API.", - "datarobot": "La puerta de enlace predeterminada cataloga los modelos activos de /genai/llmgw/catalog/. También se admiten URL de implementación para solicitudes de chat directas compatibles con OpenAI.", - "deepinfra": "Créditos de registro gratuitos para pruebas de API y exploración de modelos", - "deepseek": "5M de tokens gratuitos al registrarse - no se requiere tarjeta de crédito", - "dgrid": "Cree una clave de API de DGrid en https://dgrid.ai, luego use https://api.dgrid.ai/v1 como la URL base compatible con OpenAI.", - "dify": "Obtenga la clave de API de su instancia de Dify.", - "digitalocean": "Conectar DigitalOcean con una clave de API.", - "dit": "dit.ai (Distributed Intelligence Trade) es un enrutador/puerta de enlace compatible con OpenAI con precios dinámicos por solicitud, que expone /v1/chat/completions en https://api.dit.ai/v1. OmniRoute utiliza el protocolo OpenAI; los análisis de gastos/ahorros se encuentran en el panel de dit.ai.", - "doubao": "Obtenga la clave de API en console.volcengine.com", - "empower": "Empower expone chat compatible con OpenAI en https://app.empower.dev/api/v1 con soporte para llamadas a herramientas en empower-functions.", - "factory": "Obtenga su clave de API de Factory en https://app.factory.ai/settings/api-keys, luego péguela como un token Bearer. Punto de conexión compatible con OpenAI en https://api.factory.ai/v1.", - "fal-ai": "Conectar Fal.ai con una clave de API.", - "featherless-ai": "Nivel gratuito disponible — no se requiere tarjeta de crédito", - "fenayai": "Clave de API Bearer para la puerta de enlace compatible con OpenAI de FenayAI.", - "firecrawl": "Conectar Firecrawl con una clave de API.", - "fireworks": "$1 de crédito inicial gratuito al registrarse para pruebas de API", - "freeaiapikey": "Proxy de API con descuento para más de 40 modelos, incluidos GPT-5, Claude Opus 4.6, Claude Sonnet 4.6, Qwen 3.5. Obtenga su clave de API en https://freeaiapikey.com/dashboard. URL base: https://freeaiapikey.com/v1.", - "freemodel-dev": "Obtenga $300 en créditos de API gratuitos en https://freemodel.dev — sin necesidad de información de pago. Punto de conexión compatible con OpenAI. Modelos GPT-5.4 y GPT-5.5 disponibles.", - "friendliai": "Nivel gratuito para inferencia sin servidor — no se requiere tarjeta de crédito", - "gemini": "Gratis para siempre: 1.500 req/día para Gemini 2.5 Flash — sin tarjeta de crédito, obtenga la clave en aistudio.google.com", - "gigachat": "Conectar GigaChat (Sber) con una clave de API.", - "github-models": "Cree un PAT de GitHub con el alcance 'models: read' en github.com/settings/tokens", - "gitlab": "Token de acceso personal de GitLab para la API pública de Code Suggestions. Configure una URL base autohospedada cuando no use gitlab.com.", - "gitlawb-gmi": "Obtenga su clave de API desde el panel de Gitlawb Opengateway.", - "gitlawb": "Obtenga su clave de API desde el panel de Gitlawb Opengateway.", - "glm": "Conectar GLM Coding con una clave de API.", - "glm-cn": "Conectar GLM Coding (China) con una clave de API.", - "glmt": "Perfil GLM preestablecido con mayor presupuesto de tokens, pensamiento habilitado y tiempo de espera más largo.", - "getgoapi": "Conectar GoAPI con una clave de API.", - "groq": "Nivel gratuito: 30 RPM / 14.4K RPD — sin tarjeta de crédito", - "hackclub": "Inicie sesión con su cuenta de Hack Club en ai.hackclub.com.", - "haiper": "Obtenga la clave de API en haiper.ai/haiper-api", - "heroku": "Conectar Heroku AI con una clave de API.", - "hcnsec": "Obtén la clave de API en api.hcnsec.cn", - "huggingface": "API de inferencia gratuita para miles de modelos (Whisper, VITS, SDXL…)", - "hyperbolic": "$1-5 en créditos de prueba al registrarse para inferencia serverless", - "watsonx": "La pasarela de modelos de watsonx expone /chat/completions y /models compatibles con OpenAI en /ml/gateway/v1.", - "ideogram": "Obtén la clave de API en ideogram.ai/docs/api", - "iflytek": "Obtén la clave de API en console.xfyun.cn", - "inference-net": "$25 en créditos gratuitos al registrarse más becas de investigación disponibles", - "jina-ai": "Clave de API Bearer para la API de rerank de Jina AI.", - "jina-reader": "Conecta Jina Reader con una clave de API.", - "kenari": "Kenari expone un endpoint de chat completions compatible con OpenAI en https://kenari.id/v1/chat/completions, además de un catálogo /v1/models en vivo que cubre Claude, GPT, DeepSeek, GLM, Kimi y más. OmniRoute utiliza el protocolo de OpenAI y lista los modelos mediante passthrough.", - "kie": "Conecta KIE.AI con una clave de API.", - "kilo-gateway": "Conecta Kilo Gateway con una clave de API.", - "kimi": "Conecta Kimi con una clave de API.", - "kimi-coding-apikey": "Conecta Kimi Coding (API Key) con una clave de API.", - "lambda-ai": "Conecta Lambda AI con una clave de API.", - "laozhang": "Conecta LaoZhang AI con una clave de API.", - "leonardo": "Obtén la clave de API en leonardo.ai/developer", - "liquid": "Obtén la clave de API en liquid.ai", - "llamagate": "Conecta LlamaGate con una clave de API.", - "llm7": "Funciona sin clave de API (usa 'unused' como clave). Obtén un token gratuito en token.llm7.io para límites más altos.", - "longcat": "Gratis: concesión única de 10M de tokens tras registrarse en la cuenta + verificación KYC (LongCat-2.0). Solo una vez — no es una asignación diaria/mensual recurrente.", - "maritalk": "Conecta Maritalk con una clave de API.", - "meta-llama": "Conecta Meta Llama API con una clave de API.", - "minimax-cn": "Conecta Minimax (China) con una clave de API.", - "minimax": "Conecta Minimax Coding con una clave de API.", - "mistral": "Nivel Experiment gratuito: acceso con límite de frecuencia a todos los modelos, no se requiere tarjeta de crédito", - "modal": "Modal suele servir aplicaciones compatibles con OpenAI alojadas por el usuario en /v1. OmniRoute sondeará /v1/models y enrutará el tráfico de chat a /v1/chat/completions.", - "modelscope": "Nivel gratuito a través de ModelScope API-Inference — se requiere cuenta de Alibaba.", - "monsterapi": "Obtén la clave de API en monsterapi.ai", - "moonshot": "Conecta Moonshot AI con una clave de API.", - "morph": "Nivel gratuito: 250K créditos/mes, $0", - "nanogpt": "Conecta NanoGPT con una clave de API.", - "nebius": "~$1 en créditos de prueba al registrarse para pruebas de API", - "nlpcloud": "NLP Cloud utiliza una API de chatbot propietaria en lugar de chat/completions de OpenAI. OmniRoute adapta los mensajes de OpenAI a input/context/history y expone un catálogo local de modelos de chatbot compatibles.", - "nomic": "Obtén la clave de API en atlas.nomic.ai", - "nous-research": "Nous expone una superficie /v1 compatible con OpenAI con un amplio catálogo remoto de /models. El endpoint /chat/completions requiere una clave de API válida para inferencia programática.", - "novita": "$0.50 en créditos de prueba al registrarse (válidos durante aproximadamente 1 año)", - "nscale": "$5 en créditos gratuitos al registrarse para pruebas de inferencia", - "nube": "Conecta Nube.sh con una clave de API.", - "nvidia": "Acceso dev gratuito: ~40 RPM, 70+ modelos (Kimi K2.5, GLM 4.7, DeepSeek V3.2...)", - "oci": "OCI expone endpoints de chat y responses compatibles con OpenAI. El Project ID es opcional en OmniRoute, pero puede ser necesario para Responses y flujos de trabajo agénticos.", - "ollama-cloud": "Conecta Ollama Cloud con una clave de API.", - "openadapter": "OpenAdapter expone un endpoint de chat completions compatible con OpenAI en https://api.openadapter.in/v1/chat/completions, agregando más de 70 modelos de código abierto (DeepSeek, Qwen, Kimi, MiniMax, GLM, Llama, Mistral, …). OmniRoute utiliza el protocolo de OpenAI.", - "openai": "Conecta OpenAI con una clave de API.", - "opencode-go": "Conecta OpenCode Go con una clave de API.", - "opencode-zen": "Conecta OpenCode Zen con una clave de API.", - "openrouter": "Modelos gratuitos a $0/token con el sufijo :free - 20 RPM / 200 RPD", - "openvecta": "Créditos gratuitos al registrarse para inferencia compatible con OpenAI en LLM, embeddings y modelos de razonamiento", - "orcarouter": "Crea una clave de API (comienza con sk-orca-) en https://www.orcarouter.ai y luego pégala como un token Bearer. Endpoint compatible con OpenAI en https://api.orcarouter.ai/v1.", - "ovhcloud": "Conecta OVHcloud AI con una clave de API.", - "perplexity": "Conecta Perplexity con una clave de API.", - "piapi": "Conecta PiAPI con una clave de API.", - "pioneer": "$75 en créditos de uso gratuitos — no se requiere tarjeta de crédito", - "poe": "Poe expone chat y responses compatibles con OpenAI en https://api.poe.com/v1, con comprobaciones de saldo autenticadas en /usage/current_balance.", - "pollinations": "Nivel gratuito sin clave: openai, openai-fast, openai-large, qwen-coder, mistral, deepseek, grok, gemini-flash-lite-3.1, perplexity-fast, perplexity-reasoning. Los modelos premium (claude, gemini, midijourney) requieren una clave de API de Pollinations de enter.pollinations.ai.", - "publicai": "Requiere una clave de API — crédito único al registrarse, luego de pago", - "puter": "Obtén el token en puter.com/dashboard → Copy Auth Token", - "qiniu": "Crea una clave de API de inferencia de Qiniu AI en https://portal.qiniu.com/ai-inference/api-key y luego pégala aquí como un token Bearer. Endpoint compatible con OpenAI en https://api.qnaigc.com/v1, que actúa como proxy para DeepSeek, Claude, Kimi y más detrás de una sola clave.", - "recraft": "Conecta Recraft con una clave de API.", - "reka": "Reka Chat es compatible con OpenAI en /v1. OmniRoute sondea /v1/models y enruta el tráfico de chat a /v1/chat/completions.", - "requesty": "Crea una clave de API en https://app.requesty.ai y luego pégala aquí como un token Bearer. Endpoint compatible con OpenAI en https://router.requesty.ai/v1, con un catálogo /v1/models en vivo.", - "runwayml": "La generación de video de Runway se basa en tareas. OmniRoute envía trabajos de texto a video o de imagen a video, sondea /v1/tasks/[id] y normaliza las salidas de video finalizadas en la respuesta tipo OpenAI de /v1/videos/generations.", - "sambanova": "$5 en créditos gratuitos al registrarse (validez de 30 días), no se requiere tarjeta de crédito", - "sap": "El descubrimiento de modelos utiliza /v2/lm/scenarios/foundation-models/models en AI_API_URL. Las solicitudes de chat utilizan deploymentUrl/chat/completions y requieren AI-Resource-Group.", - "scaleway": "1M de tokens gratuitos para cuentas nuevas — compatible con UE/RGPD (París), Qwen3 235B y Llama 70B", - "sensenova": "Obtén la clave de API en platform.sensenova.cn", - "siliconflow": "$1 en créditos gratuitos más modelos permanentemente gratuitos tras la verificación de identidad", - "snowflake": "Conecta Snowflake Cortex con una clave de API.", - "sparkdesk": "Obtén la clave de API en console.xfyun.cn", - "stability-ai": "Conecta Stability AI con una clave de API.", - "stepfun": "Obtén la clave de API en platform.stepfun.com", - "sumopod": "SumoPod expone un endpoint de chat completions compatible con OpenAI en https://ai.sumopod.com/v1/chat/completions, además de un catálogo /v1/models en vivo. OmniRoute utiliza el protocolo de OpenAI y lista los modelos mediante passthrough.", - "suno": "Pega la cookie de sesión de suno.ai (autenticación de Clerk)", - "synthetic": "Conecta Synthetic con una clave de API.", - "tencent": "Obtén la clave de API en console.cloud.tencent.com", - "thebai": "Clave de API Bearer para el gateway compatible con OpenAI de TheB.AI.", - "tinyfish": "X-API-Key de agent.tinyfish.ai/api-keys", - "together": "Conecta Together AI con una clave de API.", - "tokenrouter": "TokenRouter expone un endpoint de chat completions compatible con OpenAI en https://api.tokenrouter.com/v1/chat/completions, además de un catálogo /v1/models funcional. OmniRoute utiliza el protocolo de OpenAI.", - "topaz": "Conecta Topaz con una clave de API.", - "udio": "Pega la cookie de sesión de udio.com (autenticación de Supabase)", - "uncloseai": "No se requiere autenticación. La API acepta cualquier cadena no vacía como clave de identificación.", - "upstage": "Conecta Upstage con una clave de API.", - "v0-vercel": "Conecta v0 (Vercel) con una clave de API.", - "venice": "Conecta Venice.ai con una clave de API.", - "vercel-ai-gateway": "Conecta Vercel AI Gateway con una clave de API.", - "vertex": "Proporciona el JSON de la cuenta de servicio o el access_token de OAuth", - "vertex-partner": "Proporciona el mismo JSON de la cuenta de servicio utilizado para los modelos de socios de Vertex AI.", - "volcengine": "Conecta Volcengine con una clave de API.", - "voyage-ai": "Clave de API Bearer para las API de embeddings y rerank de Voyage AI.", - "wafer": "Clave de API de https://wafer.ai", - "wandb": "Conecta Weights & Biases Inference con una clave de API.", - "x5lab": "X5Lab expone un endpoint de chat completions compatible con OpenAI en https://api.x5lab.dev/v1/chat/completions, además de un catálogo /v1/models en vivo. OmniRoute utiliza el protocolo de OpenAI y lista los modelos mediante passthrough.", - "xai": "Conecta xAI (Grok) con una clave de API.", - "xiaomi-mimo": "Conecta Xiaomi MiMo con una clave de API.", - "yi": "Obtén la clave de API en platform.lingyiwanwu.com", - "zai": "Clave de API de https://open.bigmodel.cn/usercenter/apikeys", - "zenmux": "ZenMux expone un endpoint de chat completions compatible con OpenAI en /api/v1/chat/completions, además de superficies de protocolo de Anthropic Messages (/api/anthropic/v1/messages) y Google Gemini (/api/vertex-ai). OmniRoute utiliza el protocolo de OpenAI.", - "galadriel": "Conecta Galadriel con una clave de API.", - "predibase": "$25 en créditos de prueba gratuita (validez de 30 días)", - "chenzk": "Gateway compatible con OpenAI con un catálogo de modelos en vivo en chenzk.top.", - "freepik": "Genera imágenes con la API Mystic de Freepik.", - "freetheai": "Gateway gratuito compatible con OpenAI con soporte para modelos passthrough.", - "g4f-gemini": "Proxy inverso gratuito sin clave de g4f.space a Gemini, limitado a 5 solicitudes por minuto.", - "g4f-groq": "Proxy inverso gratuito sin clave de g4f.space a Groq, limitado a 5 solicitudes por minuto.", - "g4f-nvidia": "Proxy inverso gratuito sin clave de g4f.space a NVIDIA NIM, limitado a 5 solicitudes por minuto.", - "g4f-ollama": "Gateway de Ollama alojado gratuito y sin clave de g4f.space, limitado a 5 solicitudes por minuto.", - "g4f-pollinations": "Proxy inverso gratuito sin clave de g4f.space a Pollinations, limitado a 5 solicitudes por minuto.", - "mixedbread": "Crea embeddings con la API de Mixedbread.", - "segmind": "Genera imágenes y vídeos con los modelos alojados de Segmind.", - "amazon-q": "Utiliza el mismo AWS Builder ID o flujo de refresh-token importado que Kiro, pero mantiene las conexiones de Amazon Q separadas.", - "antigravity": "Conecta Antigravity con el flujo de OAuth existente.", - "agy": "Importa tu inicio de sesión de la CLI de Antigravity (`agy`) (pega/sube su archivo de token), detecta automáticamente un inicio de sesión de la CLI local o inicia sesión con Google. Comparte el backend de Antigravity (incl. modelos de Claude).", - "claude": "Conecta Claude Code con el flujo de OAuth existente.", - "cline": "Conecta Cline con el flujo de OAuth existente.", - "cursor": "Conecta Cursor IDE con el flujo de OAuth existente.", - "github": "Conecta GitHub Copilot con el flujo de OAuth existente.", - "gitlab-duo": "Aplicación OAuth con ámbitos ai_features + read_user. Configura GITLAB_DUO_OAUTH_CLIENT_ID y opcionalmente GITLAB_DUO_OAUTH_CLIENT_SECRET en esta instancia de OmniRoute.", - "kilocode": "Conecta Kilo Code con el flujo de OAuth existente.", - "kimi-coding": "Conecta Kimi Coding con el flujo de OAuth existente.", - "kiro": "Nivel gratuito: 50 créditos/mes (~25K–100K tokens). ⚠️ Los ToS de Kiro prohíben el uso de proxies/harness de terceros.", - "codex": "Conectar OpenAI Codex con el flujo de OAuth existente.", - "qwen": "Conectar Qwen Code con el flujo de OAuth existente." + "360ai": "Get API key at ai.360.cn", + "agentrouter": "Get $200 free credits at https://agentrouter.org/register — no credit card required.", + "agnes": "Get API key at agnes-ai.com", + "aimlapi": "Free tier paused (2026) — AI/ML API is now pay-as-you-go only (min $20 top-up); no recurring free credits.", + "ai21": "$10 trial credits on signup (valid 3 months), no credit card required", + "alibaba": "Connect Alibaba with an API key.", + "alibaba-cn": "Connect Alibaba (China) with an API key.", + "bailian-coding-plan": "Connect Alibaba Coding Plan with an API key.", + "bedrock": "Native Bedrock integration: model discovery uses Bedrock foundation models and inference profiles, while chat uses the regional Bedrock Runtime Converse/ConverseStream APIs.", + "anthropic": "Connect Anthropic with an API key.", + "ant-ling": "Register and create an API key at the Ant Ling API console (https://chat.ant-ling.com/open), then paste it here. OmniRoute routes chat traffic to https://api.ant-ling.com/v1/chat/completions; the provider is OpenAI-compatible and also exposes an Anthropic-compatible surface.", + "api-airforce": "Get your API key from https://panel.api.airforce — OpenAI-compatible endpoint at https://api.airforce/v1", + "arcee-ai": "Get API key at arcee.ai", + "azure-ai": "Foundry uses the OpenAI v1 surface with deployment names as models. OmniRoute normalizes root resource URLs to the v1 chat and /models endpoints.", + "azure-openai": "Use your Azure OpenAI API key. Base URL should be your resource endpoint, for example https://my-resource.openai.azure.com.", + "bai": "Bearer API key for the b.ai OpenAI-compatible LLM gateway (distinct from TheB.AI). Create a key at https://docs.b.ai, then use https://api.b.ai/v1 as the OpenAI-compatible base URL.", + "baichuan": "Get API key at platform.baichuan-ai.com", + "baidu": "Get API key at console.bce.baidu.com", + "qianfan": "Use a Qianfan API key from Baidu AI Cloud. The default endpoint is OpenAI-compatible v2.", + "baseten": "$30 free trial credits for GPU inference", + "bazaarlink": "Create a free API key at https://bazaarlink.ai — model 'auto:free' routes to zero-cost inference. All models use the provider/model-name format, e.g. xiaomi/mimo-v2.5-pro.", + "black-forest-labs": "Connect Black Forest Labs with an API key.", + "blackbox": "Free tier: unlimited basic chat plus Minimax-M2.5, no credit card required", + "bluesminds": "Get your API key at https://www.bluesminds.com — OpenAI-compatible endpoint at https://api.bluesminds.com/v1 with free daily credits. VIP models (Claude Opus 4.5, Gemini 2.5 Pro) consume pi credits.", + "byteplus": "Connect BytePlus ModelArk with an API key.", + "bytez": "$1 free credits, refreshes every 4 weeks", + "cerebras": "Free Trial: 1M tokens/day, 30K TPM, 5 RPM — no credit card.", + "charm-hyper": "Create an API key at https://hyper.charm.land, then paste it here as a Bearer token.", + "chutes": "Bearer API key for the Chutes OpenAI-compatible gateway.", + "clarifai": "Clarifai exposes OpenAI-compatible chat, responses and /models on /v2/ext/openai/v1. Public/community models typically require a PAT; app-scoped keys only work for resources inside that app.", + "cloudflare-ai": "Requires API Token AND Account ID (found at dash.cloudflare.com)", + "clova-studio": "CLOVA Studio (HyperCLOVA X) is OpenAI-compatible on /v1/openai. OmniRoute probes /v1/openai/models and routes chat traffic to /v1/openai/chat/completions. Uses the current clovastudio.stream.ntruss.com host — the legacy clovastudio.apigw.ntruss.com endpoint is being deprecated.", + "codestral": "Connect Codestral with an API key.", + "cohere": "Free Trial: 1,000 API calls/month for testing, no credit card required", + "command-code": "Create or copy an API key from Command Code, then paste it here as a Bearer token.", + "coze": "Get API key at coze.com/open/api", + "crof": "Connect CrofAI with an API key.", + "databricks": "Connect Databricks with an API key.", + "datarobot": "The default gateway catalogs active models from /genai/llmgw/catalog/. Deployment URLs are also supported for direct OpenAI-compatible chat requests.", + "deepinfra": "Free signup credits for API testing and model exploration", + "deepseek": "5M free tokens on signup - no credit card required", + "dgrid": "Create a DGrid API key at https://dgrid.ai, then use https://api.dgrid.ai/v1 as the OpenAI-compatible base URL.", + "dify": "Get API key from your Dify instance.", + "digitalocean": "Connect DigitalOcean with an API key.", + "dit": "dit.ai (Distributed Intelligence Trade) is an OpenAI-compatible router/gateway with dynamic per-request pricing, exposing /v1/chat/completions at https://api.dit.ai/v1. OmniRoute uses the OpenAI protocol; spend/savings analytics live in the dit.ai dashboard.", + "doubao": "Get API key at console.volcengine.com", + "empower": "Empower exposes OpenAI-compatible chat on https://app.empower.dev/api/v1 with tool-calling support on empower-functions.", + "factory": "Get your Factory API key at https://app.factory.ai/settings/api-keys, then paste it as a Bearer token. OpenAI-compatible endpoint at https://api.factory.ai/v1.", + "fal-ai": "Connect Fal.ai with an API key.", + "featherless-ai": "Free tier available — no credit card required", + "fenayai": "Bearer API key for the FenayAI OpenAI-compatible gateway.", + "firecrawl": "Connect Firecrawl with an API key.", + "fireworks": "$1 free starter credits on signup for API testing", + "freeaiapikey": "Discounted API proxy for 40+ models including GPT-5, Claude Opus 4.6, Claude Sonnet 4.6, Qwen 3.5. Get your API key at https://freeaiapikey.com/dashboard. Base URL: https://freeaiapikey.com/v1.", + "freemodel-dev": "Get $300 free API credits at https://freemodel.dev — no payment info required. OpenAI-compatible endpoint. GPT-5.4 and GPT-5.5 models available.", + "friendliai": "Free tier for serverless inference — no credit card required", + "gemini": "Free forever: 1,500 req/day for Gemini 2.5 Flash — no credit card, get key at aistudio.google.com", + "gigachat": "Connect GigaChat (Sber) with an API key.", + "github-models": "Create a GitHub PAT with 'models: read' scope at github.com/settings/tokens", + "gitlab": "GitLab personal access token for the public Code Suggestions API. Configure a self-hosted base URL when not using gitlab.com.", + "gitlawb-gmi": "Get your API key from Gitlawb Opengateway dashboard.", + "gitlawb": "Get your API key from Gitlawb Opengateway dashboard.", + "glm": "Connect GLM Coding with an API key.", + "glm-cn": "Connect GLM Coding (China) with an API key.", + "glmt": "Preset GLM profile with higher token budget, thinking enabled, and longer timeout.", + "getgoapi": "Connect GoAPI with an API key.", + "groq": "Free tier: 30 RPM / 14.4K RPD — no credit card", + "hackclub": "Sign in with your Hack Club account at ai.hackclub.com.", + "haiper": "Get API key at haiper.ai/haiper-api", + "heroku": "Connect Heroku AI with an API key.", + "hcnsec": "Get API key at api.hcnsec.cn", + "huggingface": "Free Inference API for thousands of models (Whisper, VITS, SDXL…)", + "hyperbolic": "$1-5 trial credits on signup for serverless inference", + "watsonx": "The watsonx model gateway exposes OpenAI-compatible /chat/completions and /models under /ml/gateway/v1.", + "ideogram": "Get API key at ideogram.ai/docs/api", + "iflytek": "Get API key at console.xfyun.cn", + "inception": "Inception Labs is OpenAI-compatible at https://api.inceptionlabs.ai/v1. mercury-2 is the first diffusion LLM (dLLM) in the catalog — 5-10x faster generation than comparable autoregressive models, with tool calling, json_mode, and structured outputs.", + "inference-net": "$25 free credits on signup plus research grants available", + "internlm": "Free monthly quota ~1M input / 3M output tokens (~10 RPM)", + "jina-ai": "Bearer API key for the Jina AI rerank API.", + "jina-reader": "Connect Jina Reader with an API key.", + "kenari": "Kenari exposes an OpenAI-compatible chat completions endpoint at https://kenari.id/v1/chat/completions, plus a live /v1/models catalog covering Claude, GPT, DeepSeek, GLM, Kimi and more. OmniRoute uses the OpenAI protocol and lists models via passthrough.", + "kie": "Connect KIE.AI with an API key.", + "kilo-gateway": "Connect Kilo Gateway with an API key.", + "kimi": "Connect Kimi with an API key.", + "kimi-coding-apikey": "Connect Kimi Coding (API Key) with an API key.", + "lambda-ai": "Connect Lambda AI with an API key.", + "laozhang": "Connect LaoZhang AI with an API key.", + "leonardo": "Get API key at leonardo.ai/developer", + "liquid": "Get API key at liquid.ai", + "llamagate": "Connect LlamaGate with an API key.", + "llm7": "Works without API key (use 'unused' as key). Get free token at token.llm7.io for higher limits.", + "longcat": "Free: one-time 10M-token grant after account signup + KYC verification (LongCat-2.0). One-time only — not a recurring daily/monthly allowance.", + "maritalk": "Connect Maritalk with an API key.", + "meta-llama": "Connect Meta Llama API with an API key.", + "minimax-cn": "Connect Minimax (China) with an API key.", + "minimax": "Connect Minimax Coding with an API key.", + "mistral": "Free Experiment tier: rate-limited access to all models, no credit card required", + "modal": "Modal commonly serves user-hosted OpenAI-compatible apps on /v1. OmniRoute will probe /v1/models and route chat traffic to /v1/chat/completions.", + "modelscope": "Free tier via ModelScope API-Inference — Alibaba account required.", + "monsterapi": "Get API key at monsterapi.ai", + "moonshot": "Connect Kimi with an API key.", + "morph": "Free tier: 250K credits/month, $0", + "nanogpt": "Connect NanoGPT with an API key.", + "nebius": "~$1 trial credits on signup for API testing", + "nlpcloud": "NLP Cloud uses a proprietary chatbot API instead of OpenAI chat/completions. OmniRoute adapts OpenAI messages to input/context/history and exposes a local catalog of supported chatbot models.", + "nomic": "Get API key at atlas.nomic.ai", + "nous-research": "Nous exposes an OpenAI-compatible /v1 surface with a large remote /models catalog. The /chat/completions endpoint requires a valid API key for programmatic inference.", + "novita": "$0.50 trial credits on signup (valid about 1 year)", + "nscale": "$5 free credits on signup for inference testing", + "nube": "Connect Nube.sh with an API key.", + "nvidia": "Free dev access: ~40 RPM, 70+ models (Kimi K2.5, GLM 4.7, DeepSeek V3.2...)", + "oci": "OCI exposes OpenAI-compatible chat and responses endpoints. Project ID is optional in OmniRoute but may be required for Responses and agentic workflows.", + "ollama-cloud": "Connect Ollama Cloud with an API key.", + "openadapter": "OpenAdapter exposes an OpenAI-compatible chat completions endpoint at https://api.openadapter.in/v1/chat/completions, aggregating 70+ open-source models (DeepSeek, Qwen, Kimi, MiniMax, GLM, Llama, Mistral, …). OmniRoute uses the OpenAI protocol.", + "openai": "Connect OpenAI with an API key.", + "opencode-go": "Connect OpenCode Go with an API key.", + "opencode-zen": "Connect OpenCode Zen with an API key.", + "openrouter": "Free models at $0/token with :free suffix - 20 RPM / 200 RPD", + "openvecta": "Free credits on signup for OpenAI-compatible inference across LLMs, embeddings, and reasoning models", + "orcarouter": "Create an API key (starts with sk-orca-) at https://www.orcarouter.ai, then paste it as a Bearer token. OpenAI-compatible endpoint at https://api.orcarouter.ai/v1.", + "ovhcloud": "Connect OVHcloud AI with an API key.", + "perplexity": "Connect Perplexity with an API key.", + "piapi": "Connect PiAPI with an API key.", + "pioneer": "$75 free usage credits — no credit card required", + "plamo": "PLaMo is OpenAI-compatible at https://api.platform.preferredai.jp/v1. Built by Preferred Networks and optimized for Japanese. Docs are primarily in Japanese.", + "poe": "Poe exposes OpenAI-compatible chat and responses on https://api.poe.com/v1, with authenticated balance checks on /usage/current_balance.", + "pollinations": "Free keyless tier: openai, openai-fast, openai-large, qwen-coder, mistral, deepseek, grok, gemini-flash-lite-3.1, perplexity-fast, perplexity-reasoning. Premium models (claude, gemini, midijourney) require a Pollinations API key from enter.pollinations.ai.", + "publicai": "Requires an API key — one-time signup credit, then paid", + "puter": "Get token at puter.com/dashboard → Copy Auth Token", + "qiniu": "Create a Qiniu AI inference API key at https://portal.qiniu.com/ai-inference/api-key, then paste it here as a Bearer token. OpenAI-compatible endpoint at https://api.qnaigc.com/v1, proxying DeepSeek, Claude, Kimi and more behind one key.", + "recraft": "Connect Recraft with an API key.", + "reka": "Reka Chat is OpenAI-compatible on /v1. OmniRoute probes /v1/models and routes chat traffic to /v1/chat/completions.", + "requesty": "Create an API key at https://app.requesty.ai, then paste it here as a Bearer token. OpenAI-compatible endpoint at https://router.requesty.ai/v1, with a live /v1/models catalog.", + "runwayml": "Runway video generation is task-based. OmniRoute submits text-to-video or image-to-video jobs, polls /v1/tasks/[id], and normalizes the finished video outputs back into the OpenAI-like /v1/videos/generations response.", + "sambanova": "$5 free credits on signup (30-day validity), no credit card required", + "sap": "Model discovery uses /v2/lm/scenarios/foundation-models/models on AI_API_URL. Chat requests use deploymentUrl/chat/completions and require AI-Resource-Group.", + "sarvam": "Sarvam AI is OpenAI-compatible on /v1. OmniRoute probes /v1/models and routes chat traffic to /v1/chat/completions. Models are tuned for Indic languages.", + "scaleway": "1M free tokens for new accounts — EU/GDPR compliant (Paris), Qwen3 235B & Llama 70B", + "sensenova": "Get API key at platform.sensenova.cn", + "siliconflow": "$1 free credits plus permanently free models after identity verification", + "snowflake": "Connect Snowflake Cortex with an API key.", + "sparkdesk": "Get API key at console.xfyun.cn", + "stability-ai": "Connect Stability AI with an API key.", + "stepfun": "Get API key at platform.stepfun.com", + "sumopod": "SumoPod exposes an OpenAI-compatible chat completions endpoint at https://ai.sumopod.com/v1/chat/completions, plus a live /v1/models catalog. OmniRoute uses the OpenAI protocol and lists models via passthrough.", + "suno": "Paste session cookie from suno.ai (Clerk auth)", + "synthetic": "Connect Synthetic with an API key.", + "tencent": "Get API key at console.cloud.tencent.com", + "thebai": "Bearer API key for the TheB.AI OpenAI-compatible gateway.", + "tinyfish": "X-API-Key from agent.tinyfish.ai/api-keys", + "together": "Connect Together AI with an API key.", + "tokenrouter": "TokenRouter exposes an OpenAI-compatible chat completions endpoint at https://api.tokenrouter.com/v1/chat/completions, plus a working /v1/models catalog. OmniRoute uses the OpenAI protocol.", + "topaz": "Connect Topaz with an API key.", + "typhoon": "Typhoon is OpenAI-compatible on /v1. Built by SCB 10X (Thailand); typhoon-v2.5-30b-a3b-instruct is a thai-first, multilingual model.", + "udio": "Paste session cookie from udio.com (Supabase auth)", + "uncloseai": "No auth required. API accepts any non-empty string as key for identification.", + "upstage": "Connect Upstage with an API key.", + "v0-vercel": "Connect v0 (Vercel) with an API key.", + "venice": "Connect Venice.ai with an API key.", + "vercel-ai-gateway": "Connect Vercel AI Gateway with an API key.", + "vertex": "Provide Service Account JSON or OAuth access_token", + "vertex-partner": "Provide the same Service Account JSON used for Vertex AI partner models.", + "volcengine": "Connect Volcengine with an API key.", + "voyage-ai": "Bearer API key for Voyage AI embeddings and rerank APIs.", + "wafer": "API key from https://wafer.ai", + "wandb": "Connect Weights & Biases Inference with an API key.", + "writer": "Writer Palmyra is OpenAI-compatible at https://api.writer.com/v1. palmyra-x5 offers a 1M-token context window.", + "x5lab": "X5Lab exposes an OpenAI-compatible chat completions endpoint at https://api.x5lab.dev/v1/chat/completions, plus a live /v1/models catalog. OmniRoute uses the OpenAI protocol and lists models via passthrough.", + "xai": "Connect xAI (Grok) with an API key.", + "xiaomi-mimo": "Connect Xiaomi MiMo with an API key.", + "yi": "Get API key at platform.lingyiwanwu.com", + "zai": "API key from https://open.bigmodel.cn/usercenter/apikeys", + "zenmux": "ZenMux exposes an OpenAI-compatible chat completions endpoint at /api/v1/chat/completions, plus Anthropic Messages (/api/anthropic/v1/messages) and Google Gemini (/api/vertex-ai) protocol surfaces. OmniRoute uses the OpenAI protocol.", + "galadriel": "Connect Galadriel with an API key.", + "predibase": "$25 free trial credits (30-day validity)", + "chenzk": "OpenAI-compatible gateway with a live model catalog at chenzk.top.", + "freepik": "Generate images with Freepik's Mystic API.", + "freetheai": "Free OpenAI-compatible gateway with passthrough model support.", + "g4f-gemini": "Free no-key g4f.space reverse proxy to Gemini, limited to 5 requests per minute.", + "g4f-groq": "Free no-key g4f.space reverse proxy to Groq, limited to 5 requests per minute.", + "g4f-nvidia": "Free no-key g4f.space reverse proxy to NVIDIA NIM, limited to 5 requests per minute.", + "g4f-ollama": "Free no-key hosted Ollama gateway from g4f.space, limited to 5 requests per minute.", + "g4f-pollinations": "Free no-key g4f.space reverse proxy to Pollinations, limited to 5 requests per minute.", + "mixedbread": "Create embeddings with the Mixedbread API.", + "segmind": "Generate images and videos with Segmind's hosted models.", + "amazon-q": "Uses the same AWS Builder ID or imported refresh-token flow as Kiro, but keeps Amazon Q connections separate.", + "antigravity": "Connect Antigravity with the existing OAuth flow.", + "agy": "Import your Antigravity CLI (`agy`) login (paste/upload its token file), auto-detect a local CLI login, or sign in with Google. Shares the Antigravity backend (incl. Claude models).", + "claude": "Connect Claude Code with the existing OAuth flow.", + "cline": "Connect Cline with the existing OAuth flow.", + "cursor": "Connect Cursor IDE with the existing OAuth flow.", + "github": "Connect GitHub Copilot with the existing OAuth flow.", + "gitlab-duo": "OAuth application with ai_features + read_user scopes. Configure GITLAB_DUO_OAUTH_CLIENT_ID and optionally GITLAB_DUO_OAUTH_CLIENT_SECRET on this OmniRoute instance.", + "kilocode": "Connect Kilo Code with the existing OAuth flow.", + "kimi-coding": "Connect Kimi Coding with the existing OAuth flow.", + "kiro": "Free tier: 50 credits/month (~25K–100K tokens). ⚠️ Kiro ToS prohibits third-party proxy/harness use.", + "codex": "Connect OpenAI Codex with the existing OAuth flow.", + "qwen": "Connect Qwen Code with the existing OAuth flow." }, "passthroughModelsDescription": "{provider} acepta ID de modelo nativo del proveedor. Importe desde /models o agregue ID personalizados para enrutamiento.", "bedrockModelsDescription": "Los modelos de Amazon Bedrock tienen como alcance la región de AWS. Importe desde /models o agregue ID de modelo Bedrock habilitados en la región seleccionada.", "bedrockModelPlaceholder": "antrópico.claude-soneto-4-6", "addProviderSessionCookieTitle": "Agregar cookie de sesión {provider}", - "openWebProviderSite": "Abrir {host}", + "openWebProviderSite": "Open {host}", "addProviderWebTokenTitle": "Agregar token web {provider}", "addProviderConnectionTitle": "Agregar conexión {provider}", "webTokenCredentialLabel": "token de sesión web", @@ -5929,26 +5943,25 @@ "webSessionCredentialValidationFailed": "Error en la validación de credenciales de sesión. Inicie sesión nuevamente, copie una credencial nueva e inténtelo nuevamente.", "checkCookie": "comprobar galleta", "checkWebToken": "ficha de cheque", - "huggingchatLabel": "HuggingChat (Gratis)", - "huggingchatDesc": "Chat de LLM gratuito a través de huggingface.co/chat", + "huggingchatLabel": "HuggingChat (Free)", + "huggingchatDesc": "Free LLM chat via huggingface.co/chat", "poeWebLabel": "Poe Web", - "poeWebDesc": "Chat multimodelo a través de poe.com", + "poeWebDesc": "Multi-model chat via poe.com", "veniceWebLabel": "Venice Web", - "veniceWebDesc": "Chat de IA centrado en la privacidad", + "veniceWebDesc": "Privacy-focused AI chat", "v0VercelWebLabel": "v0 Vercel Web", - "v0VercelWebDesc": "Generación de código con IA a través de v0.dev", + "v0VercelWebDesc": "AI code generation via v0.dev", "kimiWebLabel": "Kimi Web", - "kimiWebDesc": "Chat de consumo de Moonshot AI a través de www.kimi.com (internacional, API Connect-RPC)", + "kimiWebDesc": "Moonshot AI consumer chat via www.kimi.com (international, Connect-RPC API)", "doubaoWebLabel": "Dola Web", - "doubaoWebDesc": "Chat de IA de ByteDance a través de dola.com", - "overrideBaseUrlAdvanced": "Avanzado: sobrescribir URL base", - "overrideBaseUrlHint": "Avanzado: apunta este proveedor integrado a un endpoint personalizado. Déjalo en blanco para usar el valor predeterminado.", - "bulkAddFormatHintCloudflare": "Una clave por línea. Formato: name|accountId|apiKey (ID de cuenta de Cloudflare + token de API).", - "lmarenaWebCookieHint": "Abre arena.ai, inicia sesión y luego copia el encabezado Cookie completo de una solicitud de Network. Incluye arena-auth-prod-v1.0 y arena-auth-prod-v1.1 (y fragmentos adicionales si están presentes), preferiblemente con cf_clearance. No pegues solo la cookie vacía arena-auth-prod-v1. Opcional: providerSpecificData.recaptchaV3Token si create-evaluation sigue devolviendo 403.", - "kimiOfficialSupporterBadge": "Amigo Fundador", - "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) es el amigo fundador de código abierto de OmniRoute", - "kimiPartnerLinkNote": "Enlace de afiliado — apoya a OmniRoute sin costo adicional para usted", - "accountSearchPlaceholder": "Search accounts…" + "doubaoWebDesc": "ByteDance AI chat via dola.com", + "overrideBaseUrlAdvanced": "Advanced: override base URL", + "overrideBaseUrlHint": "Advanced: point this built-in provider at a custom endpoint. Leave blank to use the default.", + "bulkAddFormatHintCloudflare": "One key per line. Format: name|accountId|apiKey (Cloudflare account ID + API token).", + "lmarenaWebCookieHint": "Open arena.ai, sign in, then copy the full Cookie header from a Network request. Include arena-auth-prod-v1.0 and arena-auth-prod-v1.1 (and further chunks if present), preferably with cf_clearance. Do not paste only the empty arena-auth-prod-v1 cookie. Optional: providerSpecificData.recaptchaV3Token if create-evaluation still returns 403.", + "kimiOfficialSupporterBadge": "Official Supporter", + "kimiOfficialSupporterTooltip": "Kimi (Moonshot AI) is an official OmniRoute launch partner", + "kimiPartnerLinkNote": "Partner link — supports OmniRoute at no extra cost to you" }, "settings": { "title": "Configuración", @@ -5958,69 +5971,69 @@ "routing": "Enrutamiento", "cache": "caché", "resilience": "Resiliencia", - "description": "Descripción", - "enable": "Habilitar", - "disable": "Deshabilitar", - "update": "Actualizar", + "description": "Description", + "enable": "Enable", + "disable": "Disable", + "update": "Update", "routingSettingsIntro": "Controla cómo se enrutan, transforman y envían sus solicitudes a proveedores de IA.", "routingOpDropParagraphContainsLabel": "Descartar párrafo (contiene)", - "routingOpDropParagraphStartsWithLabel": "Descartar párrafo (empieza con)", + "routingOpDropParagraphStartsWithLabel": "Descartar párrafo (empieza por)", "routingOpReplaceTextLabel": "Reemplazar texto", - "routingOpReplaceRegexLabel": "Reemplazar regex", + "routingOpReplaceRegexLabel": "Reemplazar expresión regular", "routingOpDropBlockContainsLabel": "Descartar bloque (contiene)", - "routingOpPrependSystemBlockLabel": "Anteponer bloque de sistema", - "routingOpAppendSystemBlockLabel": "Anexar bloque de sistema", - "routingOpInjectBillingHeaderLabel": "Inyectar encabezado de facturación", - "routingOpObfuscateWordsLabel": "Ofuscar palabras (ZWJ)", - "routingOpDropParagraphContainsDesc": "Elimina cualquier párrafo (bloque de texto dividido por líneas en blanco) dentro del prompt del sistema cuyo texto contenga CUALQUIERA de las subcadenas listadas. Úsalo para eliminar huellas digitales de clientes de terceros como 'github.com/anomalyco/opencode' o 'docs.openwebui.com' que el clasificador de Anthropic marca.", - "routingOpDropParagraphStartsWithDesc": "Elimina cualquier párrafo que EMPIECE CON uno de los prefijos listados. Úsalo para líneas de identidad como 'You are OpenCode' o 'You are Open WebUI' que anuncian el cliente que realiza la llamada.", - "routingOpReplaceTextDesc": "Reemplaza una subcadena literal por otra subcadena literal. Úsalo para frases desencadenantes conocidas; p. ej., reescribir 'Here is some useful information about the environment you are running in:' como 'Environment context you are running in:' (una frase desencadenante validada empíricamente).", - "routingOpReplaceRegexDesc": "Reemplaza el texto que coincide con una expresión regular. Úsalo cuando necesites patrones (clases de caracteres, espacios en blanco opcionales, delimitadores) en lugar de subcadenas literales. Si un patrón está mal formado, se detecta en tiempo de ejecución cuando se ejecuta la operación.", - "routingOpDropBlockContainsDesc": "Elimina bloques de sistema COMPLETOS (no solo párrafos) cuyo texto contenga cualquiera de las subcadenas listadas. Úsalo cuando un bloque entero contenga huellas digitales y quieras eliminarlo; p. ej., una descripción inyectada de un servidor MCP.", - "routingOpPrependSystemBlockDesc": "Inserta un nuevo bloque de texto al PRINCIPIO del array del sistema. Úsalo para añadir la identidad del SDK 'You are a Claude agent, built on Anthropic's Claude Agent SDK.' que espera el clasificador de Anthropic.", - "routingOpAppendSystemBlockDesc": "Inserta un nuevo bloque de texto al FINAL del array del sistema. Úsalo para adiciones cosméticas que no necesitan estar en la posición [0].", - "routingOpInjectBillingHeaderDesc": "Antepone el bloque de texto especial 'x-anthropic-billing-header: cc_version=...; cc_entrypoint=...; cch=...;' que valida el clasificador de Anthropic. Requerido para los endpoints de retransmisión de CC bridge; para el proveedor nativo claude, OmniRoute ya inyecta su propia línea de facturación, por lo que esta op suele ser redundante allí.", - "routingOpObfuscateWordsDesc": "Inserta un carácter Zero-Width-Joiner después de la primera letra de cada palabra listada, de modo que 'opencode' se convierte en 'o‍pencode'. Se lee idéntico para los humanos pero elude las coincidencias de palabras del clasificador. Se aplica a bloques del sistema, mensajes de usuario/asistente y descripciones de herramientas.", - "routingNeedlesHint": "Lista de subcadenas. Un párrafo coincide si contiene CUALQUIERA de ellas. Añada una por línea mediante 'Añadir entrada'.", - "routingPrefixesHint": "Lista de cadenas. Un párrafo coincide si comienza con cualquiera de ellas (el espacio en blanco inicial se recorta antes de la coincidencia).", - "routingCaseSensitiveHint": "Cuando está ACTIVADO, 'OpenCode' y 'opencode' son cadenas diferentes. Cuando está DESACTIVADO (predeterminado), la comparación ignora mayúsculas y minúsculas.", - "routingMatchLiteralHint": "Subcadena literal exacta a buscar. Sin sintaxis regex: los caracteres especiales como . * ? se tratan como tales.", - "routingReplacementTextHint": "Cadena de reemplazo. Dejar en blanco para eliminar la coincidencia. La salida conserva el texto circundante.", - "routingAllOccurrencesHint": "Cuando está ACTIVADO (predeterminado), se reemplazan todas las instancias. Cuando está DESACTIVADO, solo se reemplaza la primera coincidencia.", - "routingPatternHint": "Origen de regex de JavaScript. No lo encierre entre barras; solo 'foo(.*)bar'. El servidor rechaza los patrones que no se pueden compilar.", - "routingRegexFlagsHint": "Indicadores de regex de JavaScript (g = todas las coincidencias, i = no distingue mayúsculas/minúsculas, s = el punto coincide con nueva línea, m = multilínea). Predeterminado 'g'.", - "routingBlockTextHint": "Texto completo del nuevo bloque del sistema. Utilice una cadena literal; el bloque del sistema solo almacena texto.", - "routingIdempotencyKeyHint": "Opcional. Si se establece, la op se omite cuando ya está presente un bloque cuyo texto comienza con esta clave. Evita la doble anteposición en los reintentos.", - "routingBillingEntrypointHint": "Valor inyectado como 'cc_entrypoint='. Anthropic acepta 'sdk-cli' (Agent SDK), 'cli' (Claude Code CLI) u otros valores documentados.", - "routingBillingVersionFormatHint": "Cómo se calcula el hash de compilación de 3 caracteres después de cc_version=. 'ex-machina' = sha256 de CCH_SALT+chars-from-first-user-msg+version (por mensaje). 'omniroute-daystamp' = sha256 de YYYY-MM-DD+version (estable por día).", - "routingBillingCchAlgoHint": "Cómo se calcula el token cch= de 5 caracteres. 'sha256-first-user' = sha256 del texto del primer mensaje del usuario. 'xxhash64-body' = la firma a nivel de cuerpo lo completa más tarde. 'static-zero' = marcador de posición literal '00000'.", - "routingObfuscateWordsHint": "Palabras en minúsculas para ofuscar. La inserción de ZWJ se aplica sin distinguir mayúsculas de minúsculas, por lo que 'opencode' también coincide con 'OpenCode' y 'OPENCODE'.", - "routingObfuscateTargetsHint": "Qué regiones del cuerpo escanear en busca de las palabras: bloques del sistema, mensajes de usuario/asistente y/o descripciones de herramientas.", - "routingObfuscateTargetsLabel": "Objetivos", - "routingSummarizeDropParagraphContains": "descartar párrafos que contengan: {items}", - "routingSummarizeDropParagraphStartsWith": "descartar párrafos que comiencen con: {items}", - "routingSummarizeReplaceText": "reemplazar \"{match}\" → \"{replacement}\"", + "routingOpPrependSystemBlockLabel": "Prepend system block", + "routingOpAppendSystemBlockLabel": "Append system block", + "routingOpInjectBillingHeaderLabel": "Inject billing header", + "routingOpObfuscateWordsLabel": "Obfuscate words (ZWJ)", + "routingOpDropParagraphContainsDesc": "Removes any paragraph (text block split on blank lines) inside the system prompt whose text contains ANY of the listed substrings. Use to strip third-party client fingerprints like 'github.com/anomalyco/opencode' or 'docs.openwebui.com' that Anthropic's classifier flags.", + "routingOpDropParagraphStartsWithDesc": "Removes any paragraph that STARTS WITH one of the listed prefixes. Use for identity lines like 'You are OpenCode' or 'You are Open WebUI' that announce the calling client.", + "routingOpReplaceTextDesc": "Replaces a literal substring with another literal substring. Use for known trigger phrases — e.g. rewrite 'Here is some useful information about the environment you are running in:' to 'Environment context you are running in:' (an empirically-validated trigger phrase).", + "routingOpReplaceRegexDesc": "Replaces text matching a regular expression. Use when you need patterns (character classes, optional whitespace, anchors) instead of literal substrings. A malformed pattern is caught at runtime when the op runs.", + "routingOpDropBlockContainsDesc": "Removes ENTIRE system blocks (not just paragraphs) whose text contains any of the listed substrings. Use when a whole block is fingerprint-bearing and you want it gone — e.g. an injected MCP-server description.", + "routingOpPrependSystemBlockDesc": "Inserts a new text block at the FRONT of the system array. Use to add the SDK identity 'You are a Claude agent, built on Anthropic's Claude Agent SDK.' that Anthropic's classifier expects.", + "routingOpAppendSystemBlockDesc": "Inserts a new text block at the END of the system array. Use for cosmetic additions that don't need to be at position [0].", + "routingOpInjectBillingHeaderDesc": "Prepends the special 'x-anthropic-billing-header: cc_version=...; cc_entrypoint=...; cch=...;' text block that Anthropic's classifier validates. Required for CC bridge relay endpoints; for the native claude provider OmniRoute already injects its own billing line so this op is usually redundant there.", + "routingOpObfuscateWordsDesc": "Inserts a Zero-Width-Joiner character after the first letter of each listed word, so 'opencode' becomes 'o‍pencode'. Reads identical to humans but bypasses classifier word matches. Targets system blocks, user/assistant messages, and tool descriptions.", + "routingNeedlesHint": "List of substrings. A paragraph matches if it contains ANY one of them. Add one per line via 'Add entry'.", + "routingPrefixesHint": "List of strings. A paragraph matches if it starts with any one of them (leading whitespace is trimmed before matching).", + "routingCaseSensitiveHint": "When ON, 'OpenCode' and 'opencode' are different strings. When OFF (default), the comparison ignores case.", + "routingMatchLiteralHint": "Exact literal substring to find. No regex syntax — special chars like . * ? are treated as themselves.", + "routingReplacementTextHint": "Replacement string. Leave blank to delete the match. The output preserves surrounding text.", + "routingAllOccurrencesHint": "When ON (default), every instance is replaced. When OFF, only the first match is replaced.", + "routingPatternHint": "JavaScript regex source. Don't wrap in slashes — just 'foo(.*)bar'. Server rejects patterns that fail to compile.", + "routingRegexFlagsHint": "JavaScript regex flags (g = all matches, i = case-insensitive, s = dot matches newline, m = multiline). Default 'g'.", + "routingBlockTextHint": "Full text of the new system block. Use a literal string; the system block stores text only.", + "routingIdempotencyKeyHint": "Optional. If set, the op skips when a block whose text starts with this key is already present. Prevents double-prepend on retries.", + "routingBillingEntrypointHint": "Value injected as 'cc_entrypoint='. Anthropic accepts 'sdk-cli' (Agent SDK), 'cli' (Claude Code CLI), or other documented values.", + "routingBillingVersionFormatHint": "How the 3-char build hash after cc_version= is computed. 'ex-machina' = sha256 of CCH_SALT+chars-from-first-user-msg+version (per-message). 'omniroute-daystamp' = sha256 of YYYY-MM-DD+version (stable per-day).", + "routingBillingCchAlgoHint": "How the 5-char cch= token is computed. 'sha256-first-user' = sha256 of first user message text. 'xxhash64-body' = body-level signing fills it later. 'static-zero' = literal '00000' placeholder.", + "routingObfuscateWordsHint": "Lowercase words to obfuscate. ZWJ insertion is applied case-insensitively, so 'opencode' also matches 'OpenCode' and 'OPENCODE'.", + "routingObfuscateTargetsHint": "Which body regions to scan for the words: system blocks, user/assistant messages, and/or tool descriptions.", + "routingObfuscateTargetsLabel": "Targets", + "routingSummarizeDropParagraphContains": "drop paragraphs containing: {items}", + "routingSummarizeDropParagraphStartsWith": "drop paragraphs starting with: {items}", + "routingSummarizeReplaceText": "replace \"{match}\" → \"{replacement}\"", "routingSummarizeReplaceRegex": "regex /{pattern}/{flags} → \"{replacement}\"", - "routingSummarizeDropBlockContains": "descartar bloques que contengan: {items}", - "routingSummarizePrependSystemBlock": "anteponer bloque: \"{text}\"", - "routingSummarizeAppendSystemBlock": "anexar bloque: \"{text}\"", - "routingSummarizeInjectBillingHeader": "inyectar encabezado de facturación (entrypoint={entrypoint}, version={versionFormat}, cch={cchAlgo})", - "routingSummarizeObfuscateWords": "ofuscar {count} palabra(s) mediante ZWJ en {targets}", - "routingDefaultAutoVariantLKGP": "Último proveedor bueno conocido", - "routingDefaultAutoVariantLKGPDesc": "Último proveedor bueno conocido", - "routingDefaultAutoVariantCoding": "Prioridad de calidad para código", - "routingDefaultAutoVariantCodingDesc": "Prioridad de calidad para código", - "routingDefaultAutoVariantFast": "Enrutamiento de baja latencia", - "routingDefaultAutoVariantFastDesc": "Enrutamiento de baja latencia", - "routingDefaultAutoVariantCheap": "Optimizado para costos", - "routingDefaultAutoVariantCheapDesc": "Optimizado para costos", - "routingDefaultAutoVariantOffline": "Alta disponibilidad", - "routingDefaultAutoVariantOfflineDesc": "Alta disponibilidad", - "routingDefaultAutoVariantSmart": "Mejor descubrimiento (10% de exploración)", - "routingDefaultAutoVariantSmartDesc": "Mejor descubrimiento (10% de exploración)", - "routingOpSummaryCount": "{count, plural, =0 {ninguna op} one {# op} other {# ops}}", - "routingOpEnabled": "habilitado", - "routingOpDisabled": "deshabilitado", + "routingSummarizeDropBlockContains": "drop blocks containing: {items}", + "routingSummarizePrependSystemBlock": "prepend block: \"{text}\"", + "routingSummarizeAppendSystemBlock": "append block: \"{text}\"", + "routingSummarizeInjectBillingHeader": "inject billing header (entrypoint={entrypoint}, version={versionFormat}, cch={cchAlgo})", + "routingSummarizeObfuscateWords": "obfuscate {count} word(s) via ZWJ in {targets}", + "routingDefaultAutoVariantLKGP": "Last Known Good Provider", + "routingDefaultAutoVariantLKGPDesc": "Last Known Good Provider", + "routingDefaultAutoVariantCoding": "Quality-first for code", + "routingDefaultAutoVariantCodingDesc": "Quality-first for code", + "routingDefaultAutoVariantFast": "Low-latency routing", + "routingDefaultAutoVariantFastDesc": "Low-latency routing", + "routingDefaultAutoVariantCheap": "Cost-optimized", + "routingDefaultAutoVariantCheapDesc": "Cost-optimized", + "routingDefaultAutoVariantOffline": "High availability", + "routingDefaultAutoVariantOfflineDesc": "High availability", + "routingDefaultAutoVariantSmart": "Best discovery (10% explore)", + "routingDefaultAutoVariantSmartDesc": "Best discovery (10% explore)", + "routingOpSummaryCount": "{count, plural, =0 {no ops} one {# op} other {# ops}}", + "routingOpEnabled": "enabled", + "routingOpDisabled": "disabled", "routingOpStatusSeparator": " ·", "resilienceSettingsIntro": "Reintento, enfriamiento y respaldo automáticos cuando fallan los proveedores.", "aiSettingsIntro": "Configuraciones específicas de IA para pensar en el presupuesto, el comportamiento del modelo y la compresión.", @@ -6058,7 +6071,7 @@ "memoryDesc": "Persistent cross-session conversational memory", "memoryEnabled": "Enable Memory", "memoryEnabledDesc": "When enabled, OmniRoute will inject relevant past context.", - "memoryTokenCostWarning": "Atención: con la memoria habilitada, OmniRoute inyecta hasta {tokens} tokens de contexto recuperado en cada solicitud de chat; esto aumenta el uso de tokens y el costo. Para omitir la inyección en una solicitud específica, envíe el encabezado \"x-omniroute-no-memory: true\" .", + "memoryTokenCostWarning": "Heads up: with memory enabled, OmniRoute injects up to {tokens} tokens of retrieved context into every chat request — this increases token usage and cost. To skip injection for a specific request, send the \"x-omniroute-no-memory: true\" header.", "maxTokens": "Max Tokens", "retentionDays": "Retention", "recent": "Recent", @@ -6097,31 +6110,31 @@ "modelsDevInfoOrder": "User Override → models.dev → LiteLLM → Hardcoded Default", "systemTheme": "Tema del sistema", "debugToggle": "Enable Debug Mode", - "logToolSourcesToggle": "Registrar fuentes de herramientas", - "logToolSourcesDescription": "Emitir una línea de registro de diagnóstico por solicitud que resuma el recuento de herramientas y el desglose de fuentes de MCP/alojadas/cliente.", + "logToolSourcesToggle": "Log Tool Sources", + "logToolSourcesDescription": "Emit a diagnostic log line per request summarizing tool count and MCP/hosted/client source breakdown.", "homePinProviderQuotaToHome": "Pin Information to Home Page", - "homePinnedSectionsDesc": "Elija qué secciones fijar en la parte superior de la página de inicio.", + "homePinnedSectionsDesc": "Choose which sections to pin to the top of the Home page.", "homeProviderQuotaLimits": "Provider Quota Limits", "homeProviderQuotaLimitsDesc": "Pin the Provider Quota status container (with Refresh All button) to the top of the Home page.", "homeQuickStart": "Quick Start", "homeQuickStartDesc": "Show the Quick Start panel on the Home page.", "homeProviderTopology": "Provider Topology", "homeProviderTopologyDesc": "Show the Provider Topology on the Home page.", - "accountEmailVisibility": "Visibilidad del correo electrónico de la cuenta", - "accountEmailVisibilityDesc": "Mostrar los correos electrónicos completos de las cuentas en las pantallas de proveedores, combos, registros, cuotas y playground. Desactive esto para ocultarlos de forma predeterminada.", - "comboConfigMode": "Modo de configuración de combos", - "comboConfigModeDesc": "Elija cómo se organiza el cuadro de diálogo de creación y edición de combos.", - "comboConfigModeGuided": "Guiado", - "comboConfigModeGuidedDesc": "Utilizar el creador de combos paso a paso actual.", - "comboConfigModeExpert": "Experto", - "comboConfigModeExpertDesc": "Mostrar todas las opciones de combo en una sola página y permitir la entrada directa del modelo.", - "providerQuotaAutoRefresh": "Actualización automática de la cuota del proveedor", - "providerQuotaAutoRefreshDesc": "Actualizar la vista de Límites del proveedor automáticamente mientras permanezca abierta.", - "providerQuotaAutoRefreshToggle": "Actualización automática", - "providerQuotaAutoRefreshToggleDesc": "Actualizar la vista de cuotas cada pocos minutos mientras la página esté visible.", - "providerQuotaAutoRefreshInterval": "Intervalo de actualización", - "providerQuotaAutoRefreshIntervalDesc": "Con qué frecuencia debe actualizarse la vista de cuotas, en segundos.", - "seconds": "segundos", + "accountEmailVisibility": "Account email visibility", + "accountEmailVisibilityDesc": "Show full account emails across providers, combos, logs, quota, and playground screens. Turn this off to mask them by default.", + "comboConfigMode": "Combo configuration mode", + "comboConfigModeDesc": "Choose how the combo create and edit dialog is organized.", + "comboConfigModeGuided": "Guided", + "comboConfigModeGuidedDesc": "Use the current step-by-step combo builder.", + "comboConfigModeExpert": "Expert", + "comboConfigModeExpertDesc": "Show every combo option on one page and enable direct model entry.", + "providerQuotaAutoRefresh": "Provider Quota auto refresh", + "providerQuotaAutoRefreshDesc": "Refresh the Provider Limits view automatically while it stays open.", + "providerQuotaAutoRefreshToggle": "Automatic refresh", + "providerQuotaAutoRefreshToggleDesc": "Refresh the quota view every few minutes while the page is visible.", + "providerQuotaAutoRefreshInterval": "Refresh interval", + "providerQuotaAutoRefreshIntervalDesc": "How often the quota view should refresh, in seconds.", + "seconds": "seconds", "sidebarVisibilityToggle": "Show Sidebar Items", "enableCache": "Habilitar caché", "cacheTTL": "TTL de caché", @@ -6155,17 +6168,17 @@ "autoDisableDescription": "Permanently mark provider connections as deactivated if they return specific terminal ban signals (e.g. HTTP 403 'verify your account'). This removes them from the combo rotation.", "autoDisableThreshold": "Ban Threshold", "autoDisableThresholdDesc": "Consecutive ban signals required before permanent deactivation.", - "customBannedSignals": "Palabras clave prohibidas", - "customBannedSignalsDesc": "Palabras clave adicionales que activan la detección de baneo permanente de la cuenta. Las palabras clave integradas siempre se aplican.", - "customBannedSignalsPlaceholder": "p. ej., api key revoked", - "noCustomBannedSignals": "Sin palabras clave personalizadas. Solo están activas las palabras clave integradas.", + "customBannedSignals": "Banned Keywords", + "customBannedSignalsDesc": "Additional keywords that trigger permanent account ban detection. Built-in keywords always apply.", + "customBannedSignalsPlaceholder": "e.g. api key revoked", + "noCustomBannedSignals": "No custom keywords. Only built-in keywords are active.", "resilienceStructureTitle": "Resilience Structure", "resilienceStructureDesc": "Esta página solo configura el comportamiento. El estado del interruptor activo se muestra en la página Salud. El reintento específico del combo y el control de espacios por turnos permanecen en la configuración del combo.", "enableThinking": "Habilitar el pensamiento", "maxThinkingTokens": "Fichas de pensamiento máximo", "enableProxy": "Habilitar proxy", - "perKeyProxyEnabled": "Habilitar la asignación de proxy por clave", - "perKeyProxyEnabledDesc": "Cuando está habilitado, cada conexión de proveedor puede usar su propia asignación de proxy", + "perKeyProxyEnabled": "Enable per-key proxy assignment", + "perKeyProxyEnabledDesc": "When enabled, each provider connection can use its own proxy assignment", "proxyUrl": "URL de proxy", "pricingRates": "Formato de tarifas de precios", "currentPricing": "Resumen de precios actuales", @@ -6236,13 +6249,13 @@ "uploadFavicon": "Upload Favicon", "resetFavicon": "Reset Favicon", "faviconPreview": "Favicon Preview", - "logoFileTooLarge": "El archivo del logotipo debe ser de menos de 500 KB", - "faviconFileTooLarge": "El archivo del favicon debe ser de menos de 50 KB", - "invalidLogoFileType": "Tipo de archivo no válido. Suba un archivo PNG, JPG, SVG, GIF o WebP.", - "invalidFaviconFileType": "Tipo de archivo no válido. Suba un archivo PNG, ICO, SVG, GIF o WebP.", - "failedToReadFile": "Error al leer el archivo", - "startOnLogin": "Iniciar al iniciar sesión", - "startOnLoginDesc": "Iniciar automáticamente OmniRoute al arrancar el sistema y ejecutarlo de forma silenciosa en la bandeja del sistema.", + "logoFileTooLarge": "Logo file must be less than 500KB", + "faviconFileTooLarge": "Favicon file must be less than 50KB", + "invalidLogoFileType": "Invalid file type. Please upload PNG, JPG, SVG, GIF, or WebP.", + "invalidFaviconFileType": "Invalid file type. Please upload PNG, ICO, SVG, GIF, or WebP.", + "failedToReadFile": "Failed to read file", + "startOnLogin": "Start on Login", + "startOnLoginDesc": "Automatically launch OmniRoute on system startup and run silently in the background tray.", "flushCache": "Vaciar caché", "flushing": "Sonrojándose…", "size": "Tamaño", @@ -6252,19 +6265,19 @@ "globalProxy": "Proxy global", "globalProxyDesc": "Configure un proxy saliente global para todas las llamadas API. Los proveedores individuales, los combos y las claves pueden anular esto.", "noGlobalProxy": "No hay ningún proxy global configurado", - "proxyPool": "Pool de proxies", - "freePool": "Pool gratuito", - "proxyDocumentation": "Documentación del proxy", - "proxyGlobalConfigTab": "Configuración global", - "proxyPoolTab": "Pool de proxies", - "freePoolTab": "Pool gratuito", - "proxyDocumentationTab": "Documentación", - "proxySubscriptionsTab": "Suscripciones", + "proxyPool": "Proxy Pool", + "freePool": "Free Pool", + "proxyDocumentation": "Proxy Documentation", + "proxyGlobalConfigTab": "Global Config", + "proxyPoolTab": "Proxy Pool", + "freePoolTab": "Free Pool", + "proxyDocumentationTab": "Documentation", + "proxySubscriptionsTab": "Subscriptions", "proxySubscription": { "error": { - "LOCAL_CORE_ENDPOINT_INVALID": "El endpoint del núcleo de proxy local no es válido; se ignoraron los nodos SS/VMess/Trojan/VLESS.", - "NEEDS_CORE_NOT_CONFIGURED": "Esta suscripción tiene nodos que necesitan un núcleo de proxy local (SS/VMess/Trojan/VLESS); no se enrutan hasta que configure el endpoint SOCKS5 del núcleo local.", - "NO_USABLE_NODES": "La suscripción no produjo nodos utilizables (http/https/socks5 o nodos con un endpoint de núcleo local)." + "LOCAL_CORE_ENDPOINT_INVALID": "Local proxy-core endpoint is invalid; SS/VMess/Trojan/VLESS nodes were ignored.", + "NEEDS_CORE_NOT_CONFIGURED": "This subscription has nodes that need a local proxy core (SS/VMess/Trojan/VLESS); they are not routed until you configure the local-core SOCKS5 endpoint.", + "NO_USABLE_NODES": "Subscription yielded no usable nodes (http/https/socks5 or nodes with a local core endpoint)." } }, "bulkHealthcheck": "Bulk Healthcheck", @@ -6279,74 +6292,74 @@ "healthcheckStatus": "Status", "healthcheckProxyUrl": "Proxy URL", "healthcheckLatency": "Latency", - "proxyDocumentationScopeTitle": "Resolución del ámbito del proxy", - "proxyDocumentationScopeDescBefore": "OmniRoute resuelve el proxy de salida en orden de prioridad:", - "proxyDocumentationScopeOrder": "combo → cuenta → proveedor → global", - "proxyDocumentationScopeDescAfter": ". El ámbito más específico prevalece.", - "proxyDocumentationAddTitle": "Añadir un proxy personalizado", - "proxyDocumentationAddDescBefore": "Vaya a la", - "proxyDocumentationAddDescMiddle": "pestaña → haga clic en", - "proxyDocumentationAddCta": "+ Añadir proxy", - "proxyDocumentationAddDescAfter": ". Complete el tipo (http/https/socks5), host y puerto. Opcionalmente, asígnelo a un ámbito.", - "proxyDocumentationBulkTitle": "Formato de importación masiva", - "proxyDocumentationBulkDesc": "Campos delimitados por barras verticales:", - "proxyDocumentationSocks5DescBefore": "Los proxies SOCKS5 están desactivados por defecto. Establezca", - "proxyDocumentationFreePoolDesc": "La pestaña Pool gratuito agrega proxies de 1proxy, Proxifly e IPLocate. Use ⊕ para probar y promover un proxy a su registro. Solo se añaden los proxies que superan la prueba de conectividad.", - "proxyDocumentationVercelRelayDescBefore": "El Vercel Relay es un relé de borde de salida, no un túnel de entrada. Implementar uno envía las llamadas a la API de LLM a través de las IP dinámicas de Vercel, omitiendo los bloqueos geográficos y los límites de velocidad de los centros de datos. El relé está protegido por un encabezado secreto generado", - "proxyDocumentationVercelRelayDescAfter": "Su token de Vercel se utiliza solo durante la implementación y nunca se almacena.", - "vercelRelayTokenRequired": "El token es obligatorio", - "vercelRelayDeployFailed": "Error en la implementación", - "vercelRelayTokenHint": "El token se utiliza solo durante la implementación; nunca se almacena.", - "denoRelayTokenRequired": "El token de Deno Deploy es obligatorio", - "denoRelayOrgDomainRequired": "El dominio de la organización es obligatorio", - "denoRelayDeployFailed": "Error en Deno Deploy", - "denoRelayTokenHint": "Token de la organización (prefijo ddo_) de console.deno.com → Organización → Configuración → Tokens de organización. Se usa una vez para la implementación y nunca se almacena.", - "denoRelayOrgDomainHint": "El dominio predeterminado de su organización de Deno Deploy (por ejemplo, acme.deno.net). El relé estará accesible en https://..deno.net.", - "proxyFreePoolFilterProtocol": "Filtrar por protocolo", - "proxyFreePoolProtocol": "Protocolo", - "proxyFreePoolCountryPlaceholder": "País (por ejemplo, US)", - "proxyFreePoolFilterCountry": "Filtrar por país", - "proxyFreePoolMinQualityPlaceholder": "Calidad mín.", - "proxyFreePoolMinQualityLabel": "Puntuación de calidad mínima", - "proxyFreePoolSyncAll": "Sincronizar todo", + "proxyDocumentationScopeTitle": "Proxy scope resolution", + "proxyDocumentationScopeDescBefore": "OmniRoute resolves the outbound proxy in priority order:", + "proxyDocumentationScopeOrder": "combo → account → provider → global", + "proxyDocumentationScopeDescAfter": ". The most specific scope wins.", + "proxyDocumentationAddTitle": "Adding a custom proxy", + "proxyDocumentationAddDescBefore": "Go to the", + "proxyDocumentationAddDescMiddle": "tab → click", + "proxyDocumentationAddCta": "+ Add proxy", + "proxyDocumentationAddDescAfter": ". Fill in type (http/https/socks5), host, and port. Optionally assign it to a scope.", + "proxyDocumentationBulkTitle": "Bulk import format", + "proxyDocumentationBulkDesc": "Pipe-delimited fields:", + "proxyDocumentationSocks5DescBefore": "SOCKS5 proxies are disabled by default. Set", + "proxyDocumentationFreePoolDesc": "The Free Pool tab aggregates proxies from 1proxy, Proxifly, and IPLocate. Use ⊕ to test and promote a proxy to your registry. Only proxies that pass the connectivity test are added.", + "proxyDocumentationVercelRelayDescBefore": "The Vercel Relay is an outbound edge relay — not an inbound tunnel. Deploying one sends LLM API calls through Vercel's dynamic IPs, bypassing datacenter geo-blocks and rate limits. The relay is protected by a generated secret header", + "proxyDocumentationVercelRelayDescAfter": "Your Vercel token is used only during deploy and is never stored.", + "vercelRelayTokenRequired": "Token is required", + "vercelRelayDeployFailed": "Deploy failed", + "vercelRelayTokenHint": "Token is used only during deploy — never stored.", + "denoRelayTokenRequired": "Deno Deploy token is required", + "denoRelayOrgDomainRequired": "Organization domain is required", + "denoRelayDeployFailed": "Deno Deploy failed", + "denoRelayTokenHint": "Organization token (prefix ddo_) from console.deno.com → Organization → Settings → Organization Tokens. Used once for deploy and never stored.", + "denoRelayOrgDomainHint": "Your Deno Deploy organization's default domain (e.g. acme.deno.net). The relay will be reachable at https://..deno.net.", + "proxyFreePoolFilterProtocol": "Filter by protocol", + "proxyFreePoolProtocol": "Protocol", + "proxyFreePoolCountryPlaceholder": "Country (e.g. US)", + "proxyFreePoolFilterCountry": "Filter by country", + "proxyFreePoolMinQualityPlaceholder": "Min quality", + "proxyFreePoolMinQualityLabel": "Minimum quality score", + "proxyFreePoolSyncAll": "Sync All", "proxyFreePoolTotal": "Total", - "proxyFreePoolInPool": "En el pool", - "proxyFreePoolAvgQuality": "Calidad media", - "proxyFreePoolSelected": "{count} seleccionados", - "proxyFreePoolAddSelected": "Añadir seleccionados al pool", - "proxyFreePoolAddVisible": "Añadir todos los visibles al pool", - "proxyFreePoolSource": "Origen", - "proxyFreePoolHostPort": "Host:Puerto", - "proxyFreePoolType": "Tipo", - "proxyFreePoolCountry": "País", - "proxyFreePoolQuality": "Calidad", - "proxyFreePoolLatency": "Latencia", - "proxyFreePoolEmpty": "No se encontraron proxies. Haz clic en Sincronizar todo para obtenerlos de las fuentes.", - "proxyToggleSources": "Alternar fuentes de proxy", - "proxyFreePoolTesting": "Probando proxies...", - "proxyFreePoolBulkResult": "{succeeded} agregados, {failed} fallidos", - "proxyFreePoolPageSummary": "Página {page} de {totalPages} ({total} proxies en total)", - "proxyFreePoolTotalSummary": "{total} proxies en total", - "proxyFreePoolSearchPlaceholder": "Buscar host…", - "proxyFreePoolSearchLabel": "Buscar proxies por host", - "proxyFreePoolSortLabel": "Ordenar proxies", - "proxyFreePoolSortQuality": "Calidad", - "proxyFreePoolSortLatency": "Latencia", - "proxyFreePoolSortRecent": "Validados recientemente", - "proxyFreePoolListTotal": "Listados", - "proxyFreePoolLoadMore": "Cargar más", - "close": "Cerrar", - "cancel": "Cancelar", + "proxyFreePoolInPool": "In pool", + "proxyFreePoolAvgQuality": "Avg quality", + "proxyFreePoolSelected": "{count} selected", + "proxyFreePoolAddSelected": "Add selected to pool", + "proxyFreePoolAddVisible": "Add all visible to pool", + "proxyFreePoolSource": "Source", + "proxyFreePoolHostPort": "Host:Port", + "proxyFreePoolType": "Type", + "proxyFreePoolCountry": "Country", + "proxyFreePoolQuality": "Quality", + "proxyFreePoolLatency": "Latency", + "proxyFreePoolEmpty": "No proxies found. Click Sync All to fetch from sources.", + "proxyToggleSources": "Toggle proxy sources", + "proxyFreePoolTesting": "Testing proxies...", + "proxyFreePoolBulkResult": "{succeeded} added, {failed} failed", + "proxyFreePoolPageSummary": "Page {page} of {totalPages} ({total} total proxies)", + "proxyFreePoolTotalSummary": "{total} total proxies", + "proxyFreePoolSearchPlaceholder": "Search host…", + "proxyFreePoolSearchLabel": "Search proxies by host", + "proxyFreePoolSortLabel": "Sort proxies", + "proxyFreePoolSortQuality": "Quality", + "proxyFreePoolSortLatency": "Latency", + "proxyFreePoolSortRecent": "Recently validated", + "proxyFreePoolListTotal": "Listed", + "proxyFreePoolLoadMore": "Load more", + "close": "Close", + "cancel": "Cancel", "globalLabel": "Mundial", "configure": "Configurar", "globalSystemPrompt": "Aviso del sistema global", "saved": "Guardado", - "beforePromptLabel": "Antes del prompt", - "beforePromptDesc": "Inyectado antes de las instrucciones del sistema del agente/proveedor", - "beforePromptPlaceholder": "Instrucciones insertadas antes del prompt del agente/proveedor...", - "afterPromptLabel": "Después del prompt", - "afterPromptDesc": "Inyectado después de las instrucciones del sistema del agente/proveedor", - "afterPromptPlaceholder": "Instrucciones insertadas después del prompt del agente/proveedor...", + "beforePromptLabel": "Before Prompt", + "beforePromptDesc": "Injected before agent/provider system instructions", + "beforePromptPlaceholder": "Instructions inserted before agent/provider prompt...", + "afterPromptLabel": "After Prompt", + "afterPromptDesc": "Injected after agent/provider system instructions", + "afterPromptPlaceholder": "Instructions inserted after agent/provider prompt...", "chars": "{count} caracteres", "thinkingBudgetTitle": "Pensando en el presupuesto", "thinkingBudgetDesc": "Controle el uso del token de razonamiento de IA en todas las solicitudes", @@ -6433,22 +6446,22 @@ "strictRandomDesc": "Shuffle deck — uses each account once before reshuffling", "stickyLimit": "Límite fijo", "stickyLimitDesc": "Llamadas por cuenta antes de cambiar", - "routingStrategyTitle": "Estrategia de enrutamiento", - "routingStrategySubtitle": "Coincidir con 9router: round-robin de cuentas, límites persistentes y rotación de combos", + "routingStrategyTitle": "Routing Strategy", + "routingStrategySubtitle": "Match 9router: account round-robin, sticky limits, and combo rotation", "accountRoundRobin": "Round Robin", - "accountRoundRobinDesc": "Rotar por las cuentas para distribuir la carga", - "comboRoundRobin": "Round Robin de combos", - "comboRoundRobinDesc": "Rotar por los objetivos del combo en lugar de comenzar siempre con el primero", - "comboStickyLimit": "Límite persistente de combo", - "comboStickyLimitDesc": "Llamadas por objetivo de combo antes de cambiar", - "routingStrategyAccountSummary": "Distribuyendo solicitudes entre cuentas con {limit} llamadas por cuenta.", - "routingStrategyFillFirstSummary": "Usando cuentas en orden de prioridad (Llenar primero).", - "routingStrategyComboSummary": " Los combos rotan después de {limit} llamada(s) por objetivo.", - "routingStrategyComboFallbackSummary": " Los combos usan la estrategia configurada de cada combo (prioridad/respaldo predeterminados).", - "providerAccountRoutingTitle": "Enrutamiento multicuentas", - "providerAccountRoutingDesc": "Anular la estrategia de cuenta global para este proveedor (paridad con 9router).", - "providerRoutingStrategy": "Estrategia de cuenta", - "providerRoutingInheritGlobal": "Heredar valor predeterminado global", + "accountRoundRobinDesc": "Cycle through accounts to distribute load", + "comboRoundRobin": "Combo Round Robin", + "comboRoundRobinDesc": "Cycle through combo targets instead of always starting with the first", + "comboStickyLimit": "Combo Sticky Limit", + "comboStickyLimitDesc": "Calls per combo target before switching", + "routingStrategyAccountSummary": "Distributing requests across accounts with {limit} calls per account.", + "routingStrategyFillFirstSummary": "Using accounts in priority order (Fill First).", + "routingStrategyComboSummary": " Combos rotate after {limit} call(s) per target.", + "routingStrategyComboFallbackSummary": " Combos use each combo's configured strategy (default priority/fallback).", + "providerAccountRoutingTitle": "Multi-account routing", + "providerAccountRoutingDesc": "Override global account strategy for this provider (9router parity).", + "providerRoutingStrategy": "Account strategy", + "providerRoutingInheritGlobal": "Inherit global default", "modelAliases": "Alias de modelo", "modelAliasesTitle": "Aliases de Modelo", "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", @@ -6529,12 +6542,12 @@ "comboDefaultsTitle": "Valores predeterminados combinados", "comboDefaultsGuideTitle": "Cómo ajustar los valores predeterminados del combo", "comboDefaultsGuideHint1": "Mantenga bajos los reintentos en flujos de baja latencia; aumente el tiempo de espera solo para tareas de larga generación.", - "comboDefaultsGuideHint2": "Utilice anulaciones de proveedores cuando un proveedor necesite un comportamiento de tiempo de espera/reintento diferente al de los valores predeterminados globales.", + "comboDefaultsGuideHint2": "Utilice Ajustes específicos de proveedores cuando un proveedor necesite un comportamiento de tiempo de espera/reintento diferente al de los valores predeterminados globales.", "globalComboConfig": "Configuración combinada global", - "moveUp": "Mover hacia arriba", - "moveDown": "Mover hacia abajo", - "allProvidersAdded": "Todos los proveedores añadidos", - "noProvidersFound": "No se encontraron proveedores", + "moveUp": "Move up", + "moveDown": "Move down", + "allProvidersAdded": "All providers added", + "noProvidersFound": "No providers found", "defaultStrategy": "Estrategia predeterminada", "defaultStrategyDesc": "Aplicado a nuevos combos sin estrategia explícita.", "comboStrategyAria": "estrategia combinada", @@ -6549,14 +6562,14 @@ "healthCheckDesc": "Verificar previamente la disponibilidad del proveedor", "trackMetrics": "Seguimiento de métricas", "trackMetricsDesc": "Registre métricas de solicitudes por combo", - "providerOverrides": "Anulaciones de proveedores", + "providerOverrides": "Ajustes específicos de proveedores", "providerOverridesDesc": "Anule el tiempo de espera y los reintentos por proveedor. La configuración del proveedor anula los valores predeterminados globales.", "providerMaxRetriesAria": "{provider} reintentos máximos", "providerTimeoutAria": "{provider} tiempo de espera ms", "removeProviderOverrideAria": "Eliminar la anulación de {provider}", - "selectProviderPlaceholder": "Seleccionar proveedor...", - "searchProviderPlaceholder": "Buscar proveedores...", - "searchProviderAria": "Buscar proveedores", + "selectProviderPlaceholder": "Select provider...", + "searchProviderPlaceholder": "Search providers...", + "searchProviderAria": "Search providers", "newProviderNamePlaceholder": "por ej. google, openai...", "newProviderNameAria": "Nuevo nombre del proveedor", "retries": "reintentos", @@ -6565,7 +6578,7 @@ "maxNestingDepth": "Profundidad máxima de anidamiento", "concurrencyPerModel": "Concurrencia / Modelo", "queueTimeout": "Tiempo de espera de cola (ms)", - "queueDepth": "Profundidad de la cola", + "queueDepth": "Queue Depth", "contextRelayHandoffThreshold": "Handoff Threshold", "contextRelayMaxMessages": "Max Messages For Summary", "contextRelaySummaryModel": "Summary Model", @@ -6617,7 +6630,7 @@ "systemStorage": "Sistema y almacenamiento", "allDataLocal": "Todos los datos almacenados localmente en su máquina", "databasePath": "Ruta de la base de datos", - "export": "Exportar", + "export": "Export", "exportDatabase": "Exportar base de datos", "exportAll": "Exportar todo (.tar.gz)", "importDatabase": "Importar base de datos", @@ -6660,34 +6673,34 @@ "errorDuringImport": "Se produjo un error durante la importación.", "modelPricing": "Precios del modelo", "modelPricingDesc": "Configurar tarifas de costo por modelo • Todas las tarifas en tokens de $/1 millón", - "pricingCoverage": "Cobertura", - "pricingAuth": "Autenticación", - "pricingSort": "Ordenar", - "pricingAll": "Todos", - "pricingAuthUnknown": "Desconocido", - "pricingMostModels": "La mayoría de los modelos", - "pricingHighestCoverage": "Mayor cobertura", - "pricingLowestCoverage": "Menor cobertura", - "pricingNameAscending": "Nombre (A–Z)", - "pricingCoverageGaps": "Brechas de cobertura", - "pricingClearFilters": "Limpiar filtros", - "pricingShowingProviders": "Mostrando {visible} de {total}", - "pricingFilteredFrom": "(filtrado de {count})", - "pricingShowMoreProviders": "Mostrar {count} más ({remaining} restantes)", - "modelOverridesTitle": "Sobrescrituras de modelo", - "modelOverridesDesc": "Sobrescribir las capacidades del proveedor/modelo utilizadas por el enrutamiento y la conformación de solicitudes. Los destinos utilizan el mismo formato de proveedor/modelo que las combinaciones.", - "searchModelOverrideTargets": "Buscar proveedor/modelo...", - "selectedModel": "Modelo seleccionado", - "configured": "configurado", - "none": "Ninguno", - "modelOverrideValuePlaceholder": "Valor numérico", - "addKeyValue": "Añadir clave-valor", - "noModelOverrides": "No hay sobrescrituras configuradas para este modelo.", - "modelOverrideLoadFailed": "Error al cargar las sobrescrituras de modelo", - "modelOverrideSaved": "Sobrescritura de modelo guardada", - "modelOverrideRemoved": "Sobrescritura de modelo eliminada", - "modelOverrideSaveFailed": "Error al guardar la sobrescritura de modelo", - "modelOverrideRemoveFailed": "Error al eliminar la sobrescritura de modelo", + "pricingCoverage": "Coverage", + "pricingAuth": "Auth", + "pricingSort": "Sort", + "pricingAll": "All", + "pricingAuthUnknown": "Unknown", + "pricingMostModels": "Most models", + "pricingHighestCoverage": "Highest coverage", + "pricingLowestCoverage": "Lowest coverage", + "pricingNameAscending": "Name (A–Z)", + "pricingCoverageGaps": "Coverage gaps", + "pricingClearFilters": "Clear filters", + "pricingShowingProviders": "Showing {visible} of {total}", + "pricingFilteredFrom": "(filtered from {count})", + "pricingShowMoreProviders": "Show {count} more ({remaining} remaining)", + "modelOverridesTitle": "Model Overrides", + "modelOverridesDesc": "Override provider/model capabilities used by routing and request shaping. Targets use the same provider/model form as combos.", + "searchModelOverrideTargets": "Search provider/model...", + "selectedModel": "Selected model", + "configured": "configured", + "none": "None", + "modelOverrideValuePlaceholder": "Numeric value", + "addKeyValue": "Add key value", + "noModelOverrides": "No overrides configured for this model.", + "modelOverrideLoadFailed": "Failed to load model overrides", + "modelOverrideSaved": "Model override saved", + "modelOverrideRemoved": "Model override removed", + "modelOverrideSaveFailed": "Failed to save model override", + "modelOverrideRemoveFailed": "Failed to remove model override", "registry": "Registro", "priced": "Precio", "searchProvidersModels": "Buscar proveedores o modelos...", @@ -6725,7 +6738,7 @@ "cachedTokenDesc": "Tokens de entrada almacenados en caché (normalmente el 50 % de la tasa de entrada)", "reasoningTokenDesc": "Fichas especiales de razonamiento/pensamiento (retroceso a la tasa de producción)", "cacheCreationTokenDesc": "Tokens utilizados para crear entradas de caché (retroceso a la tasa de entrada)", - "customPricingNote": "Puede anular los precios predeterminados para modelos específicos. Las anulaciones personalizadas tienen prioridad sobre los precios detectados automáticamente.", + "customPricingNote": "Puede anular los precios predeterminados para modelos específicos. Las Ajustes específicos personalizadas tienen prioridad sobre los precios detectados automáticamente.", "editPricing": "Editar precios", "viewFullDetails": "Ver todos los detalles", "themeCoral": "Coral", @@ -6733,12 +6746,12 @@ "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", "lkgpToggleTitle": "Last Known Good Provider (LKGP)", "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", - "echoRequestedModelTitle": "Hacer eco del nombre del modelo solicitado en las respuestas", - "echoRequestedModelDesc": "Cuando está habilitado, el campo `model` de la respuesta devuelve el alias o el nombre del combo que el cliente solicitó en lugar del nombre del modelo ascendente. Corrige clientes estrictos (por ejemplo, Claude Desktop) que rechazan una respuesta cuyo modelo no coincide con la solicitud.", - "webSearchRouteTitle": "Enrutamiento de búsqueda web", - "webSearchRouteDesc": "Cuando una solicitud incluye una herramienta nativa web_search, enruta toda la solicitud a este modelo en lugar del predeterminado — útil para proveedores que no implementan la herramienta de servidor web_search de Anthropic. Dejar en blanco para deshabilitar.", - "webSearchRoutePlaceholder": "Buscar o seleccionar un modelo…", - "paidModelPatternWarning": "Este patrón solo coincide con modelos de pago — habilite los modelos de pago o ajuste el patrón.", + "echoRequestedModelTitle": "Echo requested model name in responses", + "echoRequestedModelDesc": "When enabled, the response `model` field echoes the alias or combo name the client requested instead of the upstream model name. Fixes strict clients (e.g. Claude Desktop) that reject a response whose model does not match the request.", + "webSearchRouteTitle": "Web search routing", + "webSearchRouteDesc": "When a request includes a native web_search tool, route the whole request to this model instead of the default — useful for providers that don't implement Anthropic's web_search server tool. Leave blank to disable.", + "webSearchRoutePlaceholder": "Search or select a model…", + "paidModelPatternWarning": "This pattern only matches paid models — enable paid models or adjust the pattern.", "clearLkgpCache": "Clear LKGP Cache", "lkgpCacheCleared": "LKGP cache cleared successfully", "lkgpCacheClearFailed": "Failed to clear LKGP cache", @@ -6748,24 +6761,26 @@ "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", "purgeLogsFailed": "Failed to purge logs", - "logsDeleted": "{count, plural, =0 {No se purgaron registros expirados} one {Se purgó # registro expirado} other {Se purgaron # registros expirados}}", - "resetUsageData": "Restablecer datos de uso", - "resetUsageDataDesc": "Seleccione qué tan atrás desea eliminar el uso, los registros de solicitudes y los datos analíticos. Se conservan la configuración del proveedor, las conexiones, las claves API, los combos y los ajustes. Esta acción no se puede deshacer.", - "resetUsagePeriod_5m": "5 minutos", - "resetUsagePeriod_1h": "1 hora", - "resetUsagePeriod_3h": "3 horas", - "resetUsagePeriod_6h": "6 horas", - "resetUsagePeriod_12h": "12 horas", - "resetUsagePeriod_1d": "1 día", - "resetUsagePeriod_7d": "7 días", - "resetUsagePeriod_30d": "30 días", - "resetUsagePeriod_all": "Todo el tiempo", - "resetUsageSuccess": "{count, plural, =0 {No se eliminaron filas de datos de uso} one {Restablecer datos de uso (# fila eliminada)} other {Restablecer datos de uso (# filas eliminadas)}}", - "resetUsageFailed": "Error al restablecer los datos de uso", - "reset": "Restablecer", - "resetting": "Restableciendo...", + "logsDeleted": "{count, plural, =0 {No expired logs purged} one {Purged # expired log} other {Purged # expired logs}}", + "resetUsageData": "Reset Usage Data", + "resetUsageDataDesc": "Select how far back you want to delete usage, request logs, and analytics data. Provider configuration, connections, API keys, combos, and settings are preserved. This action cannot be undone.", + "resetUsagePeriod_5m": "5 minutes", + "resetUsagePeriod_1h": "1 hour", + "resetUsagePeriod_3h": "3 hours", + "resetUsagePeriod_6h": "6 hours", + "resetUsagePeriod_12h": "12 hours", + "resetUsagePeriod_1d": "1 day", + "resetUsagePeriod_7d": "7 days", + "resetUsagePeriod_30d": "30 days", + "resetUsagePeriod_all": "All time", + "resetUsageSuccess": "{count, plural, =0 {No usage data rows deleted} one {Reset usage data (# row deleted)} other {Reset usage data (# rows deleted)}}", + "resetUsageFailed": "Failed to reset usage data", + "reset": "Reset", + "resetting": "Resetting...", "contextOpt": "Context Optimized", "contextOptDesc": "Routes based on context window requirements and conversation length", + "cacheOpt": "Cache Optimized", + "cacheOptDesc": "Keeps the same reusable prompt prefix on the same provider account", "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", "weightedDesc": "Distributes traffic by percentage weights across providers", "modelRoutingTitle": "Model Routing Rules", @@ -6819,21 +6834,21 @@ "clearSyncedPricing": "Clear Synced Pricing", "compressionTitle": "Prompt Compression", "compressionDesc": "Reduce token usage by compressing prompts before sending to providers", - "compressionGuidanceFullGuideLink": "Guía completa de compresión", - "compressionGuidanceShow": "Detalles", - "compressionGuidanceHide": "Ocultar detalles", - "compressionGuidanceSafeDefault": "Valor predeterminado seguro", - "compressionGuidanceCacheImpact": "Impacto en caché", - "tokenSaverTitle": "Ahorrador de tokens", - "tokenSaverSubtitle": "Gaste menos tokens en cada solicitud.", - "tokenSaverToolOutput": "Salida de herramientas", - "tokenSaverToolOutputDesc": "Limpiar la salida de git, grep, ls, tree y log antes de que llegue al proveedor.", - "tokenSaverLlmOutput": "Salida del LLM", - "tokenSaverLlmOutputDesc": "Inyectar instrucciones de respuesta concisas sin reescribir la salida del proveedor.", - "tokenSaverInputCompression": "Compresión de entrada", - "tokenSaverInputCompressionDesc": "Reescribir el historial de chat elegible conservando el código, las URL y la intención.", - "tokenSaverFineTunePrefix": "Ajustar cada motor en", - "tokenSaverFineTuneSuffix": "o combinar motores por solicitud en", + "compressionGuidanceFullGuideLink": "Full compression guide", + "compressionGuidanceShow": "Details", + "compressionGuidanceHide": "Hide details", + "compressionGuidanceSafeDefault": "Safe default", + "compressionGuidanceCacheImpact": "Cache impact", + "tokenSaverTitle": "Token Saver", + "tokenSaverSubtitle": "Spend fewer tokens on every request.", + "tokenSaverToolOutput": "Tool output", + "tokenSaverToolOutputDesc": "Clean git, grep, ls, tree, and log output before it reaches the provider.", + "tokenSaverLlmOutput": "LLM output", + "tokenSaverLlmOutputDesc": "Inject terse response instructions without rewriting provider output.", + "tokenSaverInputCompression": "Input compression", + "tokenSaverInputCompressionDesc": "Rewrite eligible chat history while preserving code, URLs, and intent.", + "tokenSaverFineTunePrefix": "Fine-tune each engine on", + "tokenSaverFineTuneSuffix": "or combine engines per request on", "compressionMode": "Compression Mode", "compressionModeOff": "Off", "compressionModeOffDesc": "No compression applied", @@ -6853,11 +6868,11 @@ "compressionUltraMinScore": "Umbral de puntuación mínima", "compressionUltraSlmFallback": "Regreso a lo agresivo", "compressionUltraModelPath": "Ruta del modelo SLM", - "compressionUltraEngine": "Nivel Ultra", - "compressionUltraEngineHeuristic": "Heurístico (Nivel-A, predeterminado)", - "compressionUltraEngineSlm": "SLM (LLMLingua-2, opcional)", - "compressionUltraSlmHint": "SLM descarga un modelo ONNX pequeño en el primer uso (arranque en frío) y recurre de forma transparente al heurístico en caso de tiempo de espera agotado o si no está disponible.", - "compressionUltraSlmPrewarm": "Precalentar el modelo SLM al habilitar", + "compressionUltraEngine": "Ultra tier", + "compressionUltraEngineHeuristic": "Heuristic (Tier-A, default)", + "compressionUltraEngineSlm": "SLM (LLMLingua-2, opt-in)", + "compressionUltraSlmHint": "SLM downloads a small ONNX model on first use (cold-start) and transparently falls back to the heuristic on timeout or if unavailable.", + "compressionUltraSlmPrewarm": "Pre-warm SLM model on enable", "compressionSummarizerEnabled": "Habilitar resumen", "compressionMaxTokensPerMessage": "Tokens máximos por mensaje", "compressionMinSavings": "Umbral mínimo de ahorro", @@ -6869,14 +6884,21 @@ "compressionAutoTrigger": "Auto-Trigger Threshold", "compressionCacheTTL": "Cache TTL", "compressionPreserveSystem": "Preserve System Prompt", - "compressionPreserveSystemAlways": "Siempre", - "compressionPreserveSystemWhenNoCache": "Cuando no haya caché", - "compressionPreserveSystemNever": "Nunca", - "compressionLiveZoneTitle": "Zona activa alineada con la caché", - "compressionLiveZoneDesc": "Mantener estable el prefijo de conversación comprimido y procesar solo los elementos recién agregados.", + "compressionPreserveSystemAlways": "Always", + "compressionPreserveSystemWhenNoCache": "When no cache", + "compressionPreserveSystemNever": "Never", + "compressionLiveZoneTitle": "Cache-aligned Live Zone", + "compressionLiveZoneDesc": "Keep the compressed conversation prefix stable and process only newly appended items.", + "compressionExclusionsTitle": "Compression Exclusions", + "compressionExclusionsDesc": "Model ids or provider/model patterns that must never be compressed. `*` is the only wildcard (e.g. `openai/*`, `*embedding*`). A matching request passes through byte-identical — no compression engine runs.", + "compressionExclusionsPlaceholder": "One pattern per line, e.g.\nopenai/text-embedding-3-large\nanthropic/*", + "compressionExclusionsSave": "Save", + "compressionExclusionsSaved": "Saved", + "compressionExclusionsCount": "{count, plural, one {# exclusion} other {# exclusions}} configured", + "compressionExclusionsEmpty": "No exclusions configured — every model/endpoint is eligible for compression (default behavior).", "compressionCavemanConfig": "Caveman Engine Configuration", "compressionCavemanConfigDesc": "Fine-tune the rule-based compression engine", - "compressionCavemanPanelHint": "Su estado de activación/desactivación y nivel se configuran en el panel:", + "compressionCavemanPanelHint": "Its on/off and level are set in the panel:", "compressionRoles": "Compress Message Roles", "compressionRoleUser": "User", "compressionRoleAssistant": "Assistant", @@ -6891,6 +6913,8 @@ "minutes": "minutos", "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", + "compressionModeCodexResponses": "Respuestas Codex", + "compressionModeCodexResponsesDesc": "Comprime transcripciones de salidas de herramientas según el formato de Respuestas Codex.", "compressionModeStacked": "Stacked", "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", "qdrantTitle": "Qdrant (Vector memory)", @@ -7004,36 +7028,36 @@ "oneproxySuccess": "Éxito", "oneproxyFailed": "Fallido", "routingAntigravitySignatureTitle": "Modo de caché de firma antigravedad", - "routingAntigravitySignatureDesc": "Controla si OmniRoute reutiliza solo las firmas de pensamiento de Gemini almacenadas o si acepta firmas validadas proporcionadas por el cliente en flujos de llamada a herramientas compatibles con Antigravity.", - "routingAntigravitySignatureEnabledLabel": "Habilitado", - "routingAntigravitySignatureEnabledDesc": "Comportamiento actual. Ignorar las firmas proporcionadas por el cliente y seguir usando el flujo almacenado de OmniRoute.", + "routingAntigravitySignatureDesc": "Control whether OmniRoute reuses only stored Gemini thought signatures or accepts validated client-provided signatures in Antigravity-compatible tool-call flows.", + "routingAntigravitySignatureEnabledLabel": "Enabled", + "routingAntigravitySignatureEnabledDesc": "Current behavior. Ignore client-provided signatures and keep using the stored OmniRoute flow.", "routingAntigravitySignatureBypassLabel": "Bypass", - "routingAntigravitySignatureBypassDesc": "Aceptar firmas proporcionadas por el cliente tras una validación ligera y recurrir a la firma almacenada si no son válidas.", - "routingAntigravitySignatureBypassStrictLabel": "Bypass estricto", - "routingAntigravitySignatureBypassStrictDesc": "Requerir una validación completa de protobuf antes de aceptar una firma proporcionada por el cliente.", + "routingAntigravitySignatureBypassDesc": "Accept client-provided signatures after lightweight validation and fall back to the stored signature when invalid.", + "routingAntigravitySignatureBypassStrictLabel": "Bypass Strict", + "routingAntigravitySignatureBypassStrictDesc": "Require full protobuf validation before accepting a client-provided signature.", "routingHeaderFingerprintTitle": "Huella digital del encabezado (por proveedor)", "routingServerRejectedSave": "⚠ El servidor rechazó guardar:", "routingAddTransformOp": "Agregar una operación de transformación", "routingClientCacheControlTitle": "Control de caché del cliente", - "routingClientCacheControlDesc": "Configurar si OmniRoute conserva los marcadores cache_control proporcionados por el cliente", - "routingClientCacheControlAutoDesc": "Para flujos deterministas compatibles con Claude, conservar cache_control proporcionado por el cliente tal cual. Si la solicitud no tiene cache_control, OmniRoute no inyecta ningún marcador propiedad del puente para la compatibilidad con proxys de terceros compatibles con CC.", - "routingClientCacheControlAlwaysLabel": "Conservar siempre", - "routingClientCacheControlAlwaysDesc": "Reenviar siempre los encabezados cache_control proporcionados por el cliente a los proveedores ascendentes tal cual.", - "routingClientCacheControlNeverLabel": "No conservar nunca", - "routingClientCacheControlNeverDesc": "Eliminar siempre los encabezados cache_control del cliente y permitir que OmniRoute gestione la caché donde los flujos del proveedor nativo lo admitan.", + "routingClientCacheControlDesc": "Configure whether OmniRoute preserves client-provided cache_control markers", + "routingClientCacheControlAutoDesc": "For deterministic Claude-compatible flows, preserve client-provided cache_control as-is. If the request has no cache_control, OmniRoute does not inject any bridge-owned markers for CC-compatible third-party proxy compatibility.", + "routingClientCacheControlAlwaysLabel": "Always Preserve", + "routingClientCacheControlAlwaysDesc": "Always forward client-provided cache_control headers to upstream providers as-is.", + "routingClientCacheControlNeverLabel": "Never Preserve", + "routingClientCacheControlNeverDesc": "Always remove client cache_control headers and let OmniRoute manage caching where native provider flows support it.", "routingZeroConfigTitle": "Enrutamiento automático sin configuración", - "routingZeroConfigDesc": "Habilitar la selección automática de proveedor usando el prefijo auto/. Cuando está habilitado, las solicitudes a auto, auto/coding, auto/fast, etc., se enrutarán dinámicamente entre todos los proveedores conectados.", + "routingZeroConfigDesc": "Enable automatic provider selection using the auto/ prefix. When enabled, requests to auto, auto/coding, auto/fast, etc. will dynamically route across all connected providers.", "routingDefaultAutoVariant": "Variante automática predeterminada", "visionBridge": "Puente de visión", - "visionBridgeDesc": "Ejecutar una alternativa automática de visión a texto antes de enrutar solicitudes de imágenes a modelos de solo texto.", - "visionBridgeEnabledLabel": "Habilitado", - "visionBridgeEnabledDesc": "Alternar el puente previo a la llamada que reemplaza las partes de la imagen con texto extraído.", + "visionBridgeDesc": "Run an automatic vision-to-text fallback before routing image requests to text-only models.", + "visionBridgeEnabledLabel": "Enabled", + "visionBridgeEnabledDesc": "Toggle the pre-call bridge that replaces image parts with extracted text.", "visionBridgeModel": "Modelo de puente", "visionBridgeModelPlaceholder": "openai/gpt-4o-mini", - "visionBridgeModelHint": "Cualquier ID de modelo de OmniRoute que admita visión se puede usar aquí.", + "visionBridgeModelHint": "Any OmniRoute model ID that supports vision can be used here.", "visionBridgePrompt": "Aviso de puente", "visionBridgePromptPlaceholder": "Describe esta imagen de manera concisa.", - "visionBridgePromptHint": "Se envía al modelo de visión antes de que la descripción extraída se vuelva a inyectar en la solicitud original.", + "visionBridgePromptHint": "Sent to the vision model before the extracted description is injected back into the original request.", "visionBridgeTimeoutMs": "Tiempo de espera (ms)", "visionBridgeMaxImagesPerRequest": "Máximo de imágenes por solicitud", "resilienceMaxBackoffSteps": "Max backoff steps", @@ -7050,82 +7074,82 @@ "resilienceYes": "si", "resilienceNo": "No", "resilienceDefault": "Default", - "storageDatabaseBackupRetention": "Retención de copia de seguridad de la base de datos", - "storageDatabaseBackups": "Copias de seguridad de la base de datos", - "storageBackupRetentionDescription": "Las copias de seguridad automáticas de SQLite se almacenan en", - "storageBackupRetentionHelp": "Configurar cuántas instantáneas conservar y, opcionalmente, eliminar las copias de seguridad más antiguas que un número seleccionado de días.", - "storageBackupCount": "{count} copias de seguridad", - "storageBackupMaximum": "Máx. {count}", - "storageBackupAgeRetention": "Retención de {count}d", - "storageBackupAgeRetentionOff": "Retención por antigüedad desactivada", - "storageBackupKeepLatest": "Conservar las últimas copias de seguridad", - "storageBackupDeleteOlderThan": "Eliminar más antiguas de (días)", - "storageBackupSaveRetention": "Guardar retención", - "storageBackupCleanOld": "Limpiar copias de seguridad antiguas", - "storageDatabaseStatistics": "Estadísticas de la base de datos", - "storageIntegrityNotChecked": "No comprobado", - "backupRetentionSaved": "Retención de copias de seguridad guardada.", - "backupRetentionSaveFailed": "Error al guardar la retención de copias de seguridad", - "backupCleanupSuccess": "Se eliminaron {backups} conjunto(s) de copia de seguridad y {files} archivo(s).", - "backupCleanupFailed": "Error al limpiar las copias de seguridad de la base de datos", - "purgeQuotaSnapshotsSuccess": "Se purgaron {count} instantáneas de cuota", - "purgeQuotaSnapshotsFailed": "Error al purgar las instantáneas de cuota", - "purgeCallLogsSuccess": "Se purgaron {count} registros de llamadas", - "purgeCallLogsFailed": "Error al purgar los registros de llamadas", - "purgeDetailedLogsSuccess": "Se purgaron {count} registros detallados", - "purgeDetailedLogsFailed": "Error al purgar los registros detallados", - "vacuumCompleted": "VACUUM completado", - "vacuumFailed": "VACUUM falló", - "jsonExportFailed": "Error al exportar JSON", - "invalidJsonFileType": "Tipo de archivo no válido. Solo se permiten archivos .json.", - "legacyJsonImportSuccess": "¡JSON heredado importado correctamente!", - "jsonImportFailed": "Error al importar JSON", - "jsonImportError": "Error durante la importación de JSON", + "storageDatabaseBackupRetention": "Retención de copias de seguridad", + "storageDatabaseBackups": "Database backups", + "storageBackupRetentionDescription": "Automatic SQLite backups are stored in", + "storageBackupRetentionHelp": "Configure how many snapshots to keep and optionally delete backups older than a chosen number of days.", + "storageBackupCount": "{count} backups", + "storageBackupMaximum": "Max {count}", + "storageBackupAgeRetention": "{count}d retention", + "storageBackupAgeRetentionOff": "Age retention off", + "storageBackupKeepLatest": "Keep latest backups", + "storageBackupDeleteOlderThan": "Delete older than days", + "storageBackupSaveRetention": "Save retention", + "storageBackupCleanOld": "Clean old backups", + "storageDatabaseStatistics": "Database Statistics", + "storageIntegrityNotChecked": "Not checked", + "backupRetentionSaved": "Backup retention saved.", + "backupRetentionSaveFailed": "Failed to save backup retention", + "backupCleanupSuccess": "Deleted {backups} backup set(s) and {files} file(s).", + "backupCleanupFailed": "Failed to clean database backups", + "purgeQuotaSnapshotsSuccess": "Purged {count} quota snapshots", + "purgeQuotaSnapshotsFailed": "Failed to purge quota snapshots", + "purgeCallLogsSuccess": "Purged {count} call logs", + "purgeCallLogsFailed": "Failed to purge call logs", + "purgeDetailedLogsSuccess": "Purged {count} detailed logs", + "purgeDetailedLogsFailed": "Failed to purge detailed logs", + "vacuumCompleted": "VACUUM completed", + "vacuumFailed": "VACUUM failed", + "jsonExportFailed": "JSON export failed", + "invalidJsonFileType": "Invalid file type. Only .json files are allowed.", + "legacyJsonImportSuccess": "Legacy JSON imported successfully!", + "jsonImportFailed": "Failed to import JSON", + "jsonImportError": "Error during JSON import", "storagePurgeData": "Purgar datos", - "storagePurgeDataDesc": "Eliminar inmediatamente todos los registros sin aplicar comprobaciones de retención. Usar con precaución.", - "storageRetentionCleanup": "Configuración de retención", - "storageRetentionCleanupDesc": "Configure la retención de registros operativos y la limpieza de copias de seguridad de la base de datos.", - "retentionCallDays": "Llamadas {count}d", + "storagePurgeDataDesc": "Immediately delete all records without applying retention checks. Use with caution.", + "storageRetentionCleanup": "Retention Settings", + "storageRetentionCleanupDesc": "Configure operational record retention and database backup cleanup.", + "retentionCallDays": "Call {count}d", "retentionAppDays": "App {count}d", - "retentionRows": "{count} filas", + "retentionRows": "{count} rows", "retentionQuotaSnapshots": "Instantáneas de cuota (días)", - "retentionCompressionAnalytics": "Análisis de compresión (días)", + "retentionCompressionAnalytics": "Compression Analytics (days)", "retentionMcpAudit": "Auditoría MCP (días)", "retentionA2aEvents": "Eventos A2A (días)", "retentionCallLogs": "Registros de llamadas (días)", "retentionUsageHistory": "Historial de uso (días)", "retentionMemoryEntries": "Entradas de memoria (días)", - "retentionXpAuditLog": "Registro de auditoría de XP (días)", - "saveRetentionSettings": "Guardar configuración de retención", + "retentionXpAuditLog": "XP Audit Log (days)", + "saveRetentionSettings": "Save retention settings", "storageAutoVacuumMode": "Modo de vacío automático", "storageScheduledVacuum": "Vacío programado", "storageVacuumHour": "Hora de vacío (0-23)", "storagePageSize": "Tamaño de página (bytes)", - "storageOptimizationSettings": "Configuración de optimización", - "storageJournalModeNone": "Ninguno", - "storageJournalModeFull": "Completo", + "storageOptimizationSettings": "Optimization Settings", + "storageJournalModeNone": "None", + "storageJournalModeFull": "Full", "storageJournalModeIncremental": "Incremental", - "storageVacuumNever": "Nunca", - "storageVacuumDaily": "Diario", - "storageVacuumWeekly": "Semanal", - "storageVacuumMonthly": "Mensual", - "storageCacheSizeKb": "Tamaño de caché (KB)", - "storageOptimizeOnStartup": "Optimizar al iniciar", - "storageSaveOptimization": "Guardar configuración de optimización", - "storageCompressionAggregation": "Configuración de compresión y agregación", - "storageEnableAggregation": "Habilitar agregación de datos", - "storageRawDataRetention": "Retención de datos sin procesar (días)", - "storageGranularity": "Granularidad", - "storageHourly": "Por horas", - "storageDaily": "Diario", - "storageWeekly": "Semanal", - "storageSaveAggregation": "Guardar ajustes de agregación", - "exportJson": "Exportar JSON", - "importJson": "Importar JSON", - "manualVacuum": "VACUUM manual", - "purgeQuotaSnapshots": "Purgar instantáneas de cuota", - "purgeCallLogs": "Purgar registros de llamadas", - "purgeDetailedLogs": "Purgar registros detallados", + "storageVacuumNever": "Never", + "storageVacuumDaily": "Daily", + "storageVacuumWeekly": "Weekly", + "storageVacuumMonthly": "Monthly", + "storageCacheSizeKb": "Cache Size (KB)", + "storageOptimizeOnStartup": "Optimize on Startup", + "storageSaveOptimization": "Save Optimization Settings", + "storageCompressionAggregation": "Compression & Aggregation Settings", + "storageEnableAggregation": "Enable Data Aggregation", + "storageRawDataRetention": "Raw Data Retention (days)", + "storageGranularity": "Granularity", + "storageHourly": "Hourly", + "storageDaily": "Daily", + "storageWeekly": "Weekly", + "storageSaveAggregation": "Save Aggregation Settings", + "exportJson": "Export JSON", + "importJson": "Import JSON", + "manualVacuum": "Manual VACUUM", + "purgeQuotaSnapshots": "Purge Quota Snapshots", + "purgeCallLogs": "Purge Call Logs", + "purgeDetailedLogs": "Purge Detailed Logs", "storageDatabaseSize": "Tamaño de la base de datos", "storagePageCount": "Conteo de páginas", "storageFreelistCount": "Recuento de listas libres", @@ -7135,109 +7159,109 @@ "storageIntegrityOk": "✓ Aceptar", "storageIntegrityError": "✗Error", "storageUsageTokenBuffer": "Búfer de token de uso", - "storageUsageTokenBufferDesc": "Tokens adicionales añadidos al uso reportado para tener en cuenta la sobrecarga del prompt del sistema.", - "storageUsageTokenBufferHint": "Establecer en 0 para reportar el recuento de tokens brutos del proveedor. Predeterminado: 2000.", - "storageUsageTokenBufferCurrent": "Actual: {value}", - "redisLauncherTitle": "Redis local", - "redisLauncherDesc": "Iniciar con un solo clic un contenedor Redis 7 (Podman o Docker) para la caché de respuestas, el seguimiento de cuotas y la limitación de velocidad.", - "redisLauncherRefresh": "Actualizar", - "redisLauncherStop": "Detener", - "redisLauncherLaunching": "Iniciando...", - "redisLauncherLaunch": "Iniciar Redis", - "redisLauncherContainer": "Contenedor", - "redisLauncherRunning": "En ejecución", - "redisLauncherReachable": "Accesible", + "storageUsageTokenBufferDesc": "Extra tokens added to reported usage to account for system prompt overhead.", + "storageUsageTokenBufferHint": "Set to 0 to report raw provider token counts. Default: 2000.", + "storageUsageTokenBufferCurrent": "Current: {value}", + "redisLauncherTitle": "Local Redis", + "redisLauncherDesc": "One-click launch a Redis 7 container (Podman or Docker) for response cache, quota tracking, and rate limiting.", + "redisLauncherRefresh": "Refresh", + "redisLauncherStop": "Stop", + "redisLauncherLaunching": "Launching...", + "redisLauncherLaunch": "Launch Redis", + "redisLauncherContainer": "Container", + "redisLauncherRunning": "Running", + "redisLauncherReachable": "Reachable", "redisLauncherError": "Error: {message}", - "redisLauncherHint": "Equivalente a ejecutar `omniroute redis up`. El contenedor se llama `omniroute-redis` y escucha en 127.0.0.1:6379.", + "redisLauncherHint": "Equivalent to running `omniroute redis up`. The container is named `omniroute-redis` and listens on 127.0.0.1:6379.", "compressionSettingsAutoTriggerMode": "Modo de disparo automático", "compressionSettingsMcpDescriptionCompression": "Compresión de descripción MCP", - "mcpAccessibilityTitle": "Salida de accesibilidad MCP", + "mcpAccessibilityTitle": "MCP accessibility output", "compressionSettingsCavemanIntensity": "Intensidad cavernícola", "compressionSettingsCavemanOutputMode": "Modo de salida cavernícola", - "compressionSettingsOutputStyles": "Estilos de salida", - "compressionStylesTileTitle": "Estilos de salida", + "compressionSettingsOutputStyles": "Output styles", + "compressionStylesTileTitle": "Output styles", "compressionSettingsOutputIntensity": "Intensidad de salida", "compressionSettingsAutoClarityBypass": "Bypass de claridad automática", - "compressionEffectivePipeline": "Pipeline efectivo:", - "compressionDerivedOff": "desactivado", - "compressionDerivedRuns": "ejecuciones: {pipeline}", - "compressionDerivedMode": "modo: {mode}", - "compressionAdaptiveOff": "Presupuesto de contexto adaptativo: desactivado (activación automática heredada)", - "compressionAdaptiveTarget": "Adaptativo ({mode}, política: {policy}) — objetivo ≈ {target, number} tokens (para una ventana de {contextLimit, number} tokens)", - "compressionOutputStylesDescription": "Inyectar instrucciones de modelado de respuesta sin reescribir la salida del proveedor. Combinar libremente.", - "mcpAccessibilityDescription": "Define el alcance de las salidas de las herramientas MCP (almacén independiente).", - "compressionStylesTileSummary": "{tokens, number} tokens ahorrados · {runs, plural, one {# ejecución estilizada} other {# ejecuciones estilizadas}}", - "compressionStylesTileEmpty": "Aún no hay ejecuciones estilizadas.", + "compressionEffectivePipeline": "Effective pipeline:", + "compressionDerivedOff": "off", + "compressionDerivedRuns": "runs: {pipeline}", + "compressionDerivedMode": "mode: {mode}", + "compressionAdaptiveOff": "Adaptive context budget: off (legacy auto-trigger)", + "compressionAdaptiveTarget": "Adaptive ({mode}, policy: {policy}) — target ≈ {target, number} tokens (for a {contextLimit, number}-token window)", + "compressionOutputStylesDescription": "Inject response-shaping instructions without rewriting provider output. Combine freely.", + "mcpAccessibilityDescription": "Scopes MCP tool outputs (separate store).", + "compressionStylesTileSummary": "{tokens, number} tokens saved · {runs, plural, one {# run styled} other {# runs styled}}", + "compressionStylesTileEmpty": "No styled runs yet.", "compressionLevel": { - "minimal": "Mínimo", - "standard": "Estándar", - "aggressive": "Agresivo", + "minimal": "Minimal", + "standard": "Standard", + "aggressive": "Aggressive", "lite": "Lite", "full": "Full", "ultra": "Ultra" }, "compressionEngine": { "session-dedup": { - "label": "Desduplicación de sesión", - "description": "Desduplicación de bloques entre turnos." + "label": "Session Dedup", + "description": "Cross-turn block deduplication." }, "ccr": { - "label": "CCR (Recuperación)", - "description": "Marcadores de recuperación direccionados por contenido." + "label": "CCR (Retrieval)", + "description": "Content-addressed retrieval markers." }, "lite": { "label": "Lite", - "description": "Limpieza de espacios en blanco y formato." + "description": "Whitespace and format cleanup." }, "rtk": { "label": "RTK", - "description": "Filtrado de salida de comandos." - }, - "headroom": { - "label": "Margen", - "description": "Compactación de JSON tabular." - }, - "relevance": { - "label": "Relevancia", - "description": "Puntuación extractiva de oraciones frente a la última consulta del usuario." - }, - "caveman": { - "label": "Cavernícola", - "description": "Compresión de prosa basada en reglas." - }, - "aggressive": { - "label": "Agresivo", - "description": "Resumir y envejecer turnos antiguos." - }, - "llmlingua": { - "label": "LLMLingua (SLM)", - "description": "Poda semántica (ONNX)." - }, - "ultra": { - "label": "Ultra", - "description": "Poda heurística de tokens con un SLM opcional." - }, - "omniglyph": { - "label": "OmniGlyph", - "description": "Contexto como una imagen (Claude Fable 5, ruta directa)." + "description": "Command-output filtering." }, "codex-responses": { "label": "Responses Tool Output", "description": "Conservative compression for supported Responses tool outputs." + }, + "headroom": { + "label": "Headroom", + "description": "Tabular JSON compaction." + }, + "relevance": { + "label": "Relevance", + "description": "Extractive sentence scoring against the last user query." + }, + "caveman": { + "label": "Caveman", + "description": "Rule-based prose compression." + }, + "aggressive": { + "label": "Aggressive", + "description": "Summarize and age old turns." + }, + "llmlingua": { + "label": "LLMLingua (SLM)", + "description": "Semantic pruning (ONNX)." + }, + "ultra": { + "label": "Ultra", + "description": "Heuristic token pruning with an optional SLM." + }, + "omniglyph": { + "label": "OmniGlyph", + "description": "Context as an image (Claude Fable 5, direct route)." } }, "compressionOutputStyle": { "terse-prose": { - "label": "Prosa concisa", - "description": "Omitir relleno, artículos y rodeos manteniendo exacta la sustancia técnica." + "label": "Terse prose", + "description": "Drop filler, articles, and hedging while keeping technical substance exact." }, "less-code": { - "label": "Menos código", - "description": "Escalera YAGNI: el cambio funcional más pequeño, sin abstracciones no solicitadas." + "label": "Less code", + "description": "YAGNI ladder: smallest working change, no unrequested abstractions." }, "terse-cjk": { - "label": "CJK conciso (文言)", - "description": "Estilo ultra conciso de chino clásico (disponible solo para chino)." + "label": "Terse CJK (文言)", + "description": "Classical-Chinese ultra-terse style (available only for Chinese)." } }, "resilienceWaitForCooldown": "Esperar a que se enfríe", @@ -7253,58 +7277,58 @@ "cliproxyapiUrl": "URL de CLIProxyAPI", "cliproxyapiStatus": "Estado de CLIProxyAPI", "cliproxyapiNotDetected": "No detectado", - "cliproxyapiImportAuthTitle": "Importar cuentas desde CLIProxyAPI", - "cliproxyapiImportAuthDesc": "Importe las cuentas de OAuth que CLIProxyAPI ya guardó en ~/.cli-proxy-api/ como conexiones de OmniRoute, para que no tenga que iniciar sesión en cada cuenta nuevamente. Se importan los tipos de cuenta admitidos (Gemini, Codex, Claude, Antigravity, Qwen, Kimi); los demás se omiten.", - "cliproxyapiImportAuthButton": "Importar cuentas", + "cliproxyapiImportAuthTitle": "Import accounts from CLIProxyAPI", + "cliproxyapiImportAuthDesc": "Import the OAuth accounts CLIProxyAPI already saved in ~/.cli-proxy-api/ as OmniRoute connections, so you don't have to log in to each account again. Supported account types (Gemini, Codex, Claude, Antigravity, Qwen, Kimi) are imported; others are skipped.", + "cliproxyapiImportAuthButton": "Import accounts", "payloadRulesTitle": "Reglas de carga útil", - "payloadRulesDesc": "Configure las mutaciones de la carga útil de la solicitud por modelo y protocolo. Los cambios se guardan en la configuración y se recargan en caliente en el entorno de ejecución inmediatamente después de guardar.", - "payloadRuleDefaultTitle": "predeterminado", - "payloadRuleDefaultDesc": "Aplica los parámetros solo cuando la ruta de destino no está presente en la carga útil saliente.", - "payloadRuleOverrideTitle": "sobrescribir", - "payloadRuleOverrideDesc": "Fuerza los valores en la carga útil, reemplazando cualquier cosa que ya esté presente en esa ruta.", - "payloadRuleFilterTitle": "filtrar", - "payloadRuleFilterDesc": "Elimina los parámetros bloqueados del payload antes de enviar la solicitud upstream.", + "payloadRulesDesc": "Configure request payload mutations by model and protocol. Changes are persisted in settings and hot reloaded into the runtime immediately after save.", + "payloadRuleDefaultTitle": "default", + "payloadRuleDefaultDesc": "Applies params only when the target path is missing from the outgoing payload.", + "payloadRuleOverrideTitle": "override", + "payloadRuleOverrideDesc": "Forces values onto the payload, replacing anything already present at that path.", + "payloadRuleFilterTitle": "filter", + "payloadRuleFilterDesc": "Removes blocked params from the payload before the upstream request is sent.", "payloadRuleDefaultRawTitle": "defaultRaw", - "payloadRuleDefaultRawDesc": "Igual que default, pero los valores de cadena se analizan como JSON primero cuando sea posible. El alias de entrada heredado default-raw también se acepta al guardar.", + "payloadRuleDefaultRawDesc": "Like default, but string values are parsed as JSON first when possible. The legacy input alias default-raw is also accepted on save.", "payloadEditorTitle": "Editor", - "payloadEditorDesc": "Use la estructura del esquema de tiempo de ejecución: default, override, filter, defaultRaw. La API también acepta la clave de entrada heredada default-raw.", - "payloadEditorReady": "Listo", - "payloadResetInfo": "Editor restablecido a la plantilla neutral. Guarde para aplicarla.", - "payloadSaveSuccess": "Reglas de payload guardadas y recargadas en caliente.", - "payloadJsonParseError": "Error de análisis de JSON: {error}", - "payloadMustBeObject": "Las reglas de payload deben ser un objeto JSON.", - "payloadInvalidJson": "Payload JSON no válido.", - "payloadValidJsonRequired": "Las reglas de payload deben ser un JSON válido antes de guardar.", - "savePayloadRules": "Guardar reglas de payload", - "requestLimitsTitle": "Límites de solicitudes", - "requestLimitsDesc": "Configure los límites globales de solicitudes y las protecciones de concurrencia.", - "maxRequestSizeLabel": "Tamaño máximo de solicitud (MB)", - "maxRequestSizeDesc": "Tamaño máximo permitido para solicitudes de API entrantes.", - "maxResponseSizeLabel": "Tamaño máximo de respuesta (MB)", - "maxResponseSizeDesc": "Tamaño máximo permitido para respuestas de API salientes.", - "maxRequestTokensLabel": "Tokens máximos de solicitud", - "maxRequestTokensDesc": "Total máximo de tokens permitidos en una sola solicitud.", - "maxResponseTokensLabel": "Tokens máximos de respuesta", - "maxResponseTokensDesc": "Total máximo de tokens permitidos en una sola respuesta.", + "payloadEditorDesc": "Use the runtime schema shape: default, override, filter, defaultRaw. The API also accepts the legacy input key default-raw.", + "payloadEditorReady": "Ready", + "payloadResetInfo": "Editor reset to the neutral template. Save to apply it.", + "payloadSaveSuccess": "Payload rules saved and hot reloaded.", + "payloadJsonParseError": "JSON parse error: {error}", + "payloadMustBeObject": "Payload rules must be a JSON object.", + "payloadInvalidJson": "Invalid JSON payload.", + "payloadValidJsonRequired": "Payload rules must be valid JSON before saving.", + "savePayloadRules": "Save Payload Rules", + "requestLimitsTitle": "Request Limits", + "requestLimitsDesc": "Configure global request limits and concurrency guards.", + "maxRequestSizeLabel": "Max Request Size (MB)", + "maxRequestSizeDesc": "Maximum allowed size for incoming API requests.", + "maxResponseSizeLabel": "Max Response Size (MB)", + "maxResponseSizeDesc": "Maximum allowed size for outgoing API responses.", + "maxRequestTokensLabel": "Max Request Tokens", + "maxRequestTokensDesc": "Maximum total tokens allowed in a single request.", + "maxResponseTokensLabel": "Max Response Tokens", + "maxResponseTokensDesc": "Maximum total tokens allowed in a single response.", "modelCooldownsTitle": "Modelos en tiempo de reutilización", "modelCooldownsEmpty": "No hay modelos en tiempo de reutilización en este momento.", - "modelCooldownsDescription": "Modelos aislados temporalmente tras un fallo. Cuando el periodo de enfriamiento expira, vuelven automáticamente.", - "modelCooldownsLoadFailed": "Error al cargar los periodos de enfriamiento", - "modelCooldownReactivated": "Modelo reactivado: {model}", - "modelCooldownClearFailed": "Error al borrar el periodo de enfriamiento", - "modelCooldownsAllReactivated": "Se han reactivado todos los modelos en periodo de enfriamiento.", - "modelCooldownsClearFailed": "Error al borrar los periodos de enfriamiento", - "modelCooldownsReactivateAll": "Reactivar todos", - "modelCooldownsReasonRemaining": "motivo: {reason} • restante: {remaining}", - "modelCooldownsReactivate": "Reactivar", - "responsesStateTitle": "Estado de Responses", - "responsesStateDesc": "Controla cómo OmniRoute reenvía previous_response_id.", - "responsesStateModeLabel": "Manejo de previous_response_id", + "modelCooldownsDescription": "Models temporarily isolated after a failure. When the cooldown expires they come back automatically.", + "modelCooldownsLoadFailed": "Failed to load cooldowns", + "modelCooldownReactivated": "Model reactivated: {model}", + "modelCooldownClearFailed": "Failed to clear cooldown", + "modelCooldownsAllReactivated": "All models in cooldown have been reactivated.", + "modelCooldownsClearFailed": "Failed to clear cooldowns", + "modelCooldownsReactivateAll": "Reactivate all", + "modelCooldownsReasonRemaining": "reason: {reason} • remaining: {remaining}", + "modelCooldownsReactivate": "Reactivate", + "responsesStateTitle": "Responses State", + "responsesStateDesc": "Control how OmniRoute forwards previous_response_id.", + "responsesStateModeLabel": "previous_response_id handling", "responsesStateModeAuto": "Auto", - "responsesStateModeStrip": "Eliminar", - "responsesStateModePreserve": "Conservar", - "responsesStateHint": "Auto elimina previous_response_id a menos que una conexión habilite explícitamente el almacenamiento de OpenAI Responses. Eliminar es la opción más segura para clientes sin estado como VS Code Custom Endpoint; el contexto dependerá entonces de que el cliente envíe el historial completo.", - "responsesStateSaveError": "Error al actualizar la configuración del estado de Responses", + "responsesStateModeStrip": "Strip", + "responsesStateModePreserve": "Preserve", + "responsesStateHint": "Auto strips previous_response_id unless a connection explicitly enables OpenAI Responses storage. Strip is safest for stateless clients such as VS Code Custom Endpoint; context then depends on the client sending full history.", + "responsesStateSaveError": "Failed to update Responses state setting", "codexFastTierTitle": "Codex Fast Tier", "codexFastTierDesc": "Inyectar globalmente service_tier=priority para las solicitudes de OpenAI Codex.", "codexFastTierHint": "Cuando está habilitado, OmniRoute añade service_tier=priority a las solicitudes salientes de Codex para las conexiones que aún no especifican un tier. El tier priority requiere una clave API de OpenAI Enterprise o la ruta de Codex con autenticación ChatGPT; otros tipos de claves recibirán un error relacionado con el tier de OpenAI. Los ajustes por conexión en la página del proveedor Codex tienen prioridad.", @@ -7314,13 +7338,13 @@ "codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.", "codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting", "codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}", - "codexFastTierTierLabel": "Nivel de servicio", - "codexFastTierTierPriority": "Prioridad", + "codexFastTierTierLabel": "Service tier", + "codexFastTierTierPriority": "Priority", "codexFastTierTierFlex": "Flex", - "codexFastTierTierDefault": "Predeterminado", - "codexFastTierModelsLabel": "Modelos de nivel rápido", - "codexFastTierModelsHint": "Solo los modelos seleccionados reciben service_tier cuando Fast Tier está habilitado.", - "codexFastTierModelCheckbox": "Habilitar Fast Tier para {model}", + "codexFastTierTierDefault": "Default", + "codexFastTierModelsLabel": "Fast-tier models", + "codexFastTierModelsHint": "Only checked models receive service_tier when Fast Tier is enabled.", + "codexFastTierModelCheckbox": "Enable Fast Tier for {model}", "claudeFastModeTitle": "Claude Fast Mode", "claudeFastModeDesc": "Activar el Fast Mode de Anthropic (speed:\"fast\") en las solicitudes Claude seleccionadas.", "claudeFastModeHint": "Anthropic no admite oficialmente Fast Mode para clientes en modo SDK. Cuando está habilitado, OmniRoute reenvía un encabezado X-CPA-Force-Fast-Mode para que una compilación compatible de CLIProxyAPI pueda reescribir el entrypoint. Solo los modelos Opus listados pasan la verificación del binario de Anthropic. La suscripción, el plan Max y el saldo de créditos Fast Mode siguen aplicándose en el servidor — Anthropic puede devolver out_of_credits incluso con el toggle activado.", @@ -7330,62 +7354,62 @@ "authz": { "cors": { "wildcard": { - "title": "CORS está abierto para todos los orígenes (CORS_ALLOW_ALL=true)", - "desc": "Cualquier sitio web puede llamar a la API de este servidor desde el navegador de un visitante. Úselo solo en redes de confianza — establezca orígenes explícitos en ALLOWED_ORIGINS y deshabilite CORS_ALLOW_ALL en producción." + "title": "CORS is open to every origin (CORS_ALLOW_ALL=true)", + "desc": "Any website can call this server's API from a visitor's browser. Use only on trusted networks — set explicit origins in ALLOWED_ORIGINS and disable CORS_ALLOW_ALL in production." } }, - "title": "Inventario de autorización", - "description": "Clasificación de rutas de 5 niveles con política de bypass en vivo. La lectura muestra la taxonomía completa; las modificaciones vuelven a solicitar la contraseña de administración.", - "loading": "Cargando inventario…", - "loadError": "Error al cargar el inventario de authz", + "title": "Authorization Inventory", + "description": "5-tier route classification with live bypass policy. Read shows the full taxonomy; mutations re-prompt for the management password.", + "loading": "Loading inventory…", + "loadError": "Failed to load authz inventory", "tier": { - "LOCAL_ONLY": "Solo local", - "ALWAYS_PROTECTED": "Siempre protegido", - "MANAGEMENT": "Administración", - "CLIENT_API": "API de cliente", - "PUBLIC": "Público" + "LOCAL_ONLY": "Local only", + "ALWAYS_PROTECTED": "Always protected", + "MANAGEMENT": "Management", + "CLIENT_API": "Client API", + "PUBLIC": "Public" }, "bypass": { - "section": "Bypass de ámbito de administración", + "section": "Manage-scope bypass", "kill_switch": { - "label": "Interruptor de desactivación de bypass", - "desc": "Interruptor maestro. Cuando está desactivado, ningún prefijo LOCAL_ONLY es accesible desde fuera de loopback independientemente de la lista por prefijo." + "label": "Bypass kill-switch", + "desc": "Master toggle. When off, no LOCAL_ONLY prefix is reachable from non-loopback regardless of the per-prefix list." }, "prefix": { - "label": "Prefijos con bypass permitido", - "desc": "Prefijos LOCAL_ONLY a los que las claves de API con ámbito de administración (o sesiones del panel) pueden acceder desde hosts que no sean de loopback.", - "add": "Añadir prefijo", + "label": "Bypassable prefixes", + "desc": "LOCAL_ONLY prefixes that manage-scope API keys (or dashboard sessions) may reach from non-loopback hosts.", + "add": "Add prefix", "placeholder": "/api/mcp/v2/", - "empty": "No hay prefijos configurados. El bypass está efectivamente desactivado." + "empty": "No prefixes configured. Bypass effectively off." }, - "cli_tools_runtime_note": "Prefijo con capacidad de spawn. Denegación en tiempo de compilación; no se puede habilitar el bypass. Se muestra en solo lectura." + "cli_tools_runtime_note": "Spawn-capable prefix. Compile-time deny; cannot be made bypassable. Shown read-only." }, "password": { "prompt": { - "label": "Contraseña actual", - "desc": "Vuelva a confirmar para aplicar los cambios que afectan a la seguridad." + "label": "Current password", + "desc": "Re-confirm to apply security-impacting changes." }, - "placeholder": "Contraseña de administración actual", - "cancel": "Cancelar", - "submit": "Aplicar" + "placeholder": "Current management password", + "cancel": "Cancel", + "submit": "Apply" }, - "save": "Guardar cambios", - "saved": "Configuración de authz actualizada", - "pending": "Cambios sin guardar", + "save": "Save changes", + "saved": "Authz settings updated", + "pending": "Unsaved changes", "badge": { - "bypassable": "Bypass permitido mediante el ámbito de administración", - "strict": "Loopback estricto", - "auth_required": "Autenticación requerida", - "public": "Público", - "always_protected": "Siempre protegido", - "spawn_capable": "Con capacidad de spawn" + "bypassable": "Bypassable via manage scope", + "strict": "Strict loopback", + "auth_required": "Auth required", + "public": "Public", + "always_protected": "Always protected", + "spawn_capable": "Spawn-capable" }, "error": { - "PASSWORD_REQUIRED": "Se requiere la contraseña actual para aplicar estos cambios.", - "PASSWORD_MISMATCH": "La contraseña actual es incorrecta.", - "INSUFFICIENT_SCOPE": "La clave de API carece del ámbito manage.", - "BYPASS_PREFIX_NOT_ALLOWED": "Uno o más prefijos apuntan a rutas con capacidad de spawn y no se pueden omitir.", - "GENERIC": "Error al actualizar la configuración de authz." + "PASSWORD_REQUIRED": "Current password required to apply these changes.", + "PASSWORD_MISMATCH": "Current password is incorrect.", + "INSUFFICIENT_SCOPE": "API key lacks the manage scope.", + "BYPASS_PREFIX_NOT_ALLOWED": "One or more prefixes target spawn-capable routes and cannot be bypassed.", + "GENERIC": "Failed to update authz settings." } }, "resilienceBaseCooldownLabel": "Enfriamiento básico", @@ -7422,108 +7446,104 @@ "resilienceEnableServerWaitDesc": "Cuando está habilitado, OmniRoute espera a que expire el primer tiempo de reutilización y lo vuelve a intentar automáticamente.", "resilienceMaxAttempts": "Intentos máximos", "resilienceMaxWaitPerAttempt": "Espera máxima por intento", - "resilienceComboCooldownWaitTitle": "Espera de enfriamiento de combo de cuota compartida", - "resilienceComboCooldownWaitDesc": "Solo para combos de cuota compartida: espera a que pase un breve enfriamiento transitorio y vuelve a enviar en lugar de devolver un 429 inmediatamente. Nunca espera en quota_exhausted.", - "resilienceComboCooldownWaitToggleDesc": "Solo combos de cuota compartida; nunca espera en quota_exhausted.", - "resilienceComboCooldownMaxWaitMs": "Espera máxima por intento", - "resilienceComboCooldownBudgetMs": "Presupuesto total de espera", - "resilienceQuotaShareConcurrencyTitle": "Concurrencia por conexión de cuota compartida", - "resilienceQuotaShareConcurrencyDesc": "Solo para combos de cuota compartida: cuando una conexión establece un límite de Max Concurrent, serializa las solicitudes concurrentes a esa cuenta de suscripción para que nunca se sobrepase su tope. El exceso de solicitudes espera en la cola en lugar de recibir un 429. El límite proviene del campo Max Concurrent de cada conexión; este interruptor solo activa o desactiva su cumplimiento.", - "resilienceQuotaShareConcurrencyToggleDesc": "Solo combos de cuota compartida; respeta el límite de Max Concurrent de cada conexión.", - "resilienceProviderCooldownTitle": "Enfriamiento del proveedor", - "resilienceProviderCooldownScope": "Todas las solicitudes de combo", - "resilienceProviderCooldownTrigger": "Cuando falla un proveedor/conexión", - "resilienceProviderCooldownEffect": "Omite el proveedor fallido durante un periodo de enfriamiento antes de reintentar", - "resilienceProviderCooldownDesc": "Evita que las solicitudes posteriores vuelvan a recorrer los mismos proveedores con fallos. El enfriamiento escala exponencialmente con los fallos consecutivos.", - "resilienceProviderCooldownEnabled": "Habilitar enfriamiento global de proveedores", - "resilienceProviderCooldownEnabledDesc": "Cuando está habilitado, los proveedores fallidos se rastrean globalmente y se omiten durante un periodo de enfriamiento.", - "resilienceProviderCooldownMin": "Enfriamiento mínimo", - "resilienceProviderCooldownMax": "Enfriamiento máximo", + "resilienceComboCooldownWaitTitle": "Quota-share combo cooldown wait", + "resilienceComboCooldownWaitDesc": "For quota-share combos only: wait out a short transient cooldown and re-dispatch instead of returning a 429 immediately. Never waits on quota_exhausted.", + "resilienceComboCooldownWaitToggleDesc": "Quota-share combos only; never waits on quota_exhausted.", + "resilienceComboCooldownMaxWaitMs": "Maximum wait per attempt", + "resilienceComboCooldownBudgetMs": "Total wait budget", + "resilienceQuotaShareConcurrencyTitle": "Quota-share per-connection concurrency", + "resilienceQuotaShareConcurrencyDesc": "For quota-share combos only: when a connection sets a Max Concurrent cap, serialize concurrent requests to that subscription account so it is never flooded past its ceiling. Excess requests wait in the queue instead of getting a 429. The cap comes from each connection's Max Concurrent field; this switch only enables or disables honoring it.", + "resilienceQuotaShareConcurrencyToggleDesc": "Quota-share combos only; honors each connection's Max Concurrent cap.", + "resilienceProviderCooldownTitle": "Provider Cooldown", + "resilienceProviderCooldownScope": "All combo requests", + "resilienceProviderCooldownTrigger": "When a provider/connection fails", + "resilienceProviderCooldownEffect": "Skips the failed provider for a cooldown period before retrying", + "resilienceProviderCooldownDesc": "Prevents subsequent requests from re-walking the same failing providers. Cooldown scales exponentially with consecutive failures.", + "resilienceProviderCooldownEnabled": "Enable global provider cooldown", + "resilienceProviderCooldownEnabledDesc": "When enabled, failed providers are tracked globally and skipped for a cooldown period.", + "resilienceProviderCooldownMin": "Minimum cooldown", + "resilienceProviderCooldownMax": "Maximum cooldown", "forcedFingerprintTitle": "Siempre activado para {provider}; necesario para la seguridad de las cuentas OAuth y no se puede desactivar.", "forcedFingerprintBadge": "Obligatorio", - "sessionAffinityTitle": "Afinidad de sesión", - "sessionAffinityDesc": "Mantiene una conversación en la misma cuenta durante esta cantidad de segundos, para cualquier proveedor. 0 lo deshabilita.", - "sessionAffinityTtl": "TTL de afinidad (segundos)", - "resetAwareQuotaCacheTitle": "Caché de cuota con reconocimiento de restablecimiento", + "sessionAffinityTitle": "Session affinity", + "sessionAffinityDesc": "Keeps one conversation on the same account for this many seconds, for any provider. 0 disables it.", + "sessionAffinityTtl": "Affinity TTL (seconds)", + "resetAwareQuotaCacheTitle": "Caché de cuotas con reinicio", "resetAwareQuotaCacheDesc": "Almacena en caché la telemetría de cuota solo para pedidos con reconocimiento de reinicio. La verificación previa de cuotas aún protege las solicitudes. 0/0 sigue obteniendo en vivo.", "resetAwareQuotaCacheTtl": "TTL nuevo (segundos)", "resetAwareQuotaCacheMaxStale": "Máximo obsoleto (segundos)", "qdrantCleanupSuccess": "OK: eliminado {count} punto(s) (retención: {days} días)", "qdrantCleanupFailed": "Error de limpieza", "qdrantCleanupError": "Error: {error}", - "vercelRelaySuccess": "Vercel Relay desplegado correctamente", - "vercelRelayButton": "Desplegar Vercel Relay", - "vercelRelayModalTitle": "Desplegar Vercel Relay", - "vercelRelayWarning": "Advertencia: Se requiere un token de despliegue de Vercel. Este token solo se utilizará para crear el relay serverless y OmniRoute nunca lo almacenará.", - "vercelRelayTokenLabel": "Token de acceso de Vercel", - "vercelRelayProjectNameLabel": "Nombre del proyecto de Vercel", - "vercelRelayFreeTierNote": "Los relays son endpoints de proxy ligeros desplegados en el nivel gratuito de Vercel para eludir las limitaciones de red/región locales.", - "vercelRelayDeploying": "Desplegando...", - "vercelRelayDeploy": "Desplegar", - "deployRelayButton": "Desplegar Relay", - "denoRelayButton": "Desplegar Deno Relay", - "denoRelayModalTitle": "Desplegar Deno Relay", - "denoRelayWarning": "Advertencia: Se requiere un token de organización de Deno Deploy. Este token solo se utilizará para crear la aplicación de relay y OmniRoute nunca lo almacenará.", - "denoRelayTokenLabel": "Token de organización de Deno Deploy", - "denoRelayOrgDomainLabel": "Dominio de la organización", - "denoRelayProjectNameLabel": "Nombre de la aplicación Deno", - "denoRelayFreeTierNote": "Deno Deploy v2 se ejecuta en una red perimetral global. Nivel gratuito: 1M de solicitudes y 100 GiB de tráfico saliente al mes, sin límites de CPU por solicitud, hasta 20 aplicaciones activas y 50 dominios personalizados.", - "denoRelayDeploying": "Desplegando...", - "denoRelayDeploy": "Desplegar", - "cloudflareRelaySuccess": "Cloudflare Relay desplegado correctamente", - "cloudflareRelayButton": "Desplegar Cloudflare Relay", - "cloudflareRelayModalTitle": "Desplegar Cloudflare Worker Relay", - "cloudflareRelayWarning": "Despliega un Cloudflare Worker que actúa como proxy para las solicitudes de LLM a través de la red perimetral de Cloudflare, enmascarando la IP del host detrás de direcciones dinámicas de Cloudflare. El Worker aplica un secreto de autenticación de un solo uso para que la URL pública de workers.dev no se pueda reutilizar como un relay abierto.", - "cloudflareRelayTokenHowto": "Crea el token de API en Mi perfil -> Tokens de API -> Crear token -> Token personalizado -> Cuenta / Scripts de Workers / Editar.", - "cloudflareRelayAccountIdLabel": "ID de cuenta de Cloudflare", - "cloudflareRelayAccountIdHint": "Se encuentra en el lado derecho de la página de información general del panel de Cloudflare.", - "cloudflareRelayApiTokenLabel": "Token de API de Cloudflare", - "cloudflareRelayApiTokenHint": "Requiere el permiso 'Workers Scripts: Edit'. El token se utiliza únicamente en el momento del despliegue y nunca se almacena.", - "cloudflareRelayProjectNameLabel": "Nombre del Worker", - "cloudflareRelayFreeTierNote": "Nivel gratuito: 100.000 solicitudes/día por cuenta de Cloudflare.", - "cloudflareRelayDeploying": "Desplegando...", - "cloudflareRelayDeploy": "Desplegar", - "cloudflareRelayCredsRequired": "El ID de cuenta y el token de API son obligatorios", - "cloudflareRelayDeployFailed": "Error al desplegar", - "modelLockout": "Bloqueo de modelos", - "modelLockoutPageDescription": "Configura qué códigos de error HTTP activan el bloqueo por modelo y controla el comportamiento del tiempo de enfriamiento.", - "modelLockoutLoadFailed": "Error al cargar la configuración de bloqueo de modelos", - "modelLockoutSaveFailed": "Error al guardar la configuración de bloqueo de modelos", - "modelLockoutLoading": "Cargando la configuración de bloqueo de modelos...", - "modelLockoutBaseRangeError": "El tiempo de enfriamiento base debe estar entre 5,000ms y 600,000ms", - "modelLockoutMaxRangeError": "El tiempo de enfriamiento máximo debe estar entre 5,000ms y 3,600,000ms", - "modelLockoutOrderError": "El tiempo de enfriamiento máximo debe ser mayor o igual que el tiempo de enfriamiento base", - "modelLockoutStepsRangeError": "Los pasos máximos de backoff deben estar entre 0 y 20", - "removeErrorCode": "Eliminar {code}", - "addErrorCode": "Añadir código de error...", - "suggestions": "Sugerencias:", - "modelLockoutMaxCooldownHint": "≥ Tiempo de enfriamiento base — 3,600,000ms", - "modelLockoutEnabled": "Habilitar bloqueo de modelos", - "modelLockoutEnabledDescription": "Cuando está habilitado, los modelos que fallan con los códigos de error configurados se bloquean temporalmente para evitar bucles de reintento.", - "modelLockoutErrorCodes": "Códigos de error", - "modelLockoutErrorCodesDescription": "Códigos de estado HTTP que activan el bloqueo de modelos. Escribe un código y haz clic en Añadir, o selecciona de las sugerencias.", - "modelLockoutBaseCooldown": "Tiempo de enfriamiento base (ms)", - "modelLockoutBaseCooldownDescription": "Duración inicial del tiempo de enfriamiento en milisegundos antes de que se pueda reintentar un modelo.", - "modelLockoutMaxCooldown": "Tiempo de enfriamiento máximo (ms)", - "modelLockoutMaxCooldownDescription": "Duración máxima del enfriamiento en milisegundos. Evita bloqueos excesivamente largos.", - "modelLockoutExponentialBackoff": "Backoff exponencial", - "modelLockoutExponentialBackoffDescription": "Cuando está habilitado, cada fallo consecutivo aumenta la duración del enfriamiento de forma exponencial.", - "modelLockoutMaxBackoffSteps": "Pasos máximos de backoff", - "modelLockoutMaxBackoffStepsDescription": "Número máximo de pasos de backoff antes de que el enfriamiento deje de aumentar. El límite de Max Cooldown se alcanza primero en la mayoría de las configuraciones, lo que convierte a esto en un tope de seguridad para cuando se aumente Max Cooldown.", - "disableSessionStickiness": "Desactivar la persistencia de sesión", - "disableSessionStickinessDesc": "Las combinaciones round-robin y aleatorias rotan a una conexión diferente en cada solicitud en lugar de fijar una conversación completa a una conexión mediante el hash del primer mensaje. Déjelo desactivado para conservar los aciertos de prompt-cache en chats de varios turnos. Las anulaciones por combinación tienen prioridad.", - "credentialRedaction": "Ocultación de credenciales", - "credentialRedactionDesc": "Oculta claves de API, tokens y secretos del contexto enviado a los proveedores y de las respuestas.", - "enableCredentialRedaction": "Habilitar la ocultación de credenciales", - "enableCredentialRedactionDesc": "Elimina claves de API, tokens, claves privadas y JWT de mensajes, llamadas a herramientas y respuestas.", - "pricingAutoSyncDisabled": "Automatic Sync Disabled", - "pricingAutoSyncEnabled": "Automatic Sync Enabled", - "cacheOpt": "Cache Optimized", - "cacheOptDesc": "Keeps the same reusable prompt prefix on the same provider account", + "vercelRelaySuccess": "Vercel Relay deployed successfully", + "vercelRelayButton": "Deploy Vercel Relay", + "vercelRelayModalTitle": "Deploy Vercel Relay", + "vercelRelayWarning": "Warning: A Vercel deployment token is required. This token will only be used to create the serverless relay and will never be stored by OmniRoute.", + "vercelRelayTokenLabel": "Vercel Access Token", + "vercelRelayProjectNameLabel": "Vercel Project Name", + "vercelRelayFreeTierNote": "Relays are lightweight proxy endpoints deployed on Vercel's free tier to bypass local network/region limitations.", + "vercelRelayDeploying": "Deploying...", + "vercelRelayDeploy": "Deploy", + "deployRelayButton": "Deploy Relay", + "denoRelayButton": "Deploy Deno Relay", + "denoRelayModalTitle": "Deploy Deno Relay", + "denoRelayWarning": "Warning: A Deno Deploy organization token is required. This token will only be used to create the relay app and will never be stored by OmniRoute.", + "denoRelayTokenLabel": "Deno Deploy Organization Token", + "denoRelayOrgDomainLabel": "Organization Domain", + "denoRelayProjectNameLabel": "Deno App Name", + "denoRelayFreeTierNote": "Deno Deploy v2 runs on a global edge network. Free tier: 1M requests & 100GiB outbound traffic per month, no per-request CPU limits, up to 20 active apps & 50 custom domains.", + "denoRelayDeploying": "Deploying...", + "denoRelayDeploy": "Deploy", + "cloudflareRelaySuccess": "Cloudflare Relay deployed successfully", + "cloudflareRelayButton": "Deploy Cloudflare Relay", + "cloudflareRelayModalTitle": "Deploy Cloudflare Worker Relay", + "cloudflareRelayWarning": "Deploys a Cloudflare Worker that proxies LLM requests through Cloudflare's edge network — masking the host IP behind dynamic Cloudflare addresses. The Worker enforces a one-time auth secret so the public workers.dev URL cannot be reused as an open relay.", + "cloudflareRelayTokenHowto": "Create the API token under My Profile -> API Tokens -> Create Token -> Custom Token -> Account / Workers Scripts / Edit.", + "cloudflareRelayAccountIdLabel": "Cloudflare Account ID", + "cloudflareRelayAccountIdHint": "Found on the right side of the Cloudflare dashboard overview page.", + "cloudflareRelayApiTokenLabel": "Cloudflare API Token", + "cloudflareRelayApiTokenHint": "Requires 'Workers Scripts: Edit' permission. The token is used only at deploy time and is never stored.", + "cloudflareRelayProjectNameLabel": "Worker Name", + "cloudflareRelayFreeTierNote": "Free tier: 100,000 requests/day per Cloudflare account.", + "cloudflareRelayDeploying": "Deploying...", + "cloudflareRelayDeploy": "Deploy", + "cloudflareRelayCredsRequired": "Account ID and API Token are required", + "cloudflareRelayDeployFailed": "Deploy failed", + "modelLockout": "Model Lockout", + "modelLockoutPageDescription": "Configure which HTTP error codes trigger per-model lockout and control the cooldown behavior.", + "modelLockoutLoadFailed": "Failed to load model lockout settings", + "modelLockoutSaveFailed": "Failed to save model lockout settings", + "modelLockoutLoading": "Loading model lockout settings...", + "modelLockoutBaseRangeError": "Base Cooldown must be between 5,000ms and 600,000ms", + "modelLockoutMaxRangeError": "Max Cooldown must be between 5,000ms and 3,600,000ms", + "modelLockoutOrderError": "Max Cooldown must be greater than or equal to Base Cooldown", + "modelLockoutStepsRangeError": "Max Backoff Steps must be between 0 and 20", + "removeErrorCode": "Remove {code}", + "addErrorCode": "Add error code...", + "suggestions": "Suggestions:", + "modelLockoutMaxCooldownHint": "≥ Base Cooldown — 3,600,000ms", + "modelLockoutEnabled": "Enable Model Lockout", + "modelLockoutEnabledDescription": "When enabled, models that fail with configured error codes are temporarily locked to prevent retry loops.", + "modelLockoutErrorCodes": "Error Codes", + "modelLockoutErrorCodesDescription": "HTTP status codes that trigger model lockout. Type a code and click Add, or select from suggestions.", + "modelLockoutBaseCooldown": "Base Cooldown (ms)", + "modelLockoutBaseCooldownDescription": "Initial cooldown duration in milliseconds before a model can be retried.", + "modelLockoutMaxCooldown": "Max Cooldown (ms)", + "modelLockoutMaxCooldownDescription": "Maximum cooldown duration in milliseconds. Prevents excessively long lockouts.", + "modelLockoutExponentialBackoff": "Exponential Backoff", + "modelLockoutExponentialBackoffDescription": "When enabled, each consecutive failure increases the cooldown duration exponentially.", + "modelLockoutMaxBackoffSteps": "Max Backoff Steps", + "modelLockoutMaxBackoffStepsDescription": "Maximum number of backoff steps before the cooldown stops growing. The Max Cooldown cap is reached first in most configurations, making this a safety ceiling for when Max Cooldown is raised.", + "disableSessionStickiness": "Disable session stickiness", + "disableSessionStickinessDesc": "Round-robin and random combos rotate to a different connection on every request instead of pinning a whole conversation to one connection by the first-message hash. Leave off to preserve prompt-cache hits for multi-turn chats. Per-combo overrides take precedence.", "promptCacheAffinity": "Prompt-cache locality routing", "promptCacheAffinityDesc": "Prefer the same provider account for matching prompt-cache keys while preserving health and quota failover.", - "compressionModeCodexResponses": "Responses tool output", - "compressionModeCodexResponsesDesc": "Conservative compression for eligible shell, patch, search, build, and JSON outputs" + "credentialRedaction": "Credential Redaction", + "credentialRedactionDesc": "Redact API keys, tokens, and secrets from context sent to providers and from responses.", + "enableCredentialRedaction": "Enable credential redaction", + "enableCredentialRedactionDesc": "Scrubs API keys, tokens, private keys, and JWTs from messages, tool calls, and responses.", + "pricingAutoSyncDisabled": "Automatic Sync Disabled", + "pricingAutoSyncEnabled": "Automatic Sync Enabled" }, "contextRtk": { "title": "RTK Engine", @@ -7564,7 +7584,7 @@ "result": "Result", "previewEmpty": "Run a sample to preview RTK output.", "detected": "Detected", - "masterSwitchOffAlert": "El interruptor principal de Token Saver está en OFF — estos ajustes no afectarán a las solicitudes hasta que lo active desde la página Endpoint.", + "masterSwitchOffAlert": "El interruptor principal de Token Saver está DESACTIVADO — estos ajustes no afectarán a las solicitudes hasta que lo actives en la página de Puntos de conexión.", "tokensFiltered": "Tokens filtered", "filtersActive": "Filters active", "requests": "Requests", @@ -7575,181 +7595,181 @@ "tooltipDedup": "Qué tan agresivamente eliminar las líneas repetidas.", "tooltipMaxChars": "Máximo de caracteres por bloque de salida.", "tooltipMaxLines": "Líneas máximas para evitar la salida del comando. El exceso se trunca.", - "learnDiscoverTitle": "Aprender y descubrir filtros", - "learnDiscoverDesc": "Analice la salida de comandos capturada (la retención de Raw Output debe estar activada) para sugerir nuevos filtros RTK. Solo sugerencias — usted las revisa y las guarda.", - "discoverHeading": "Descubrir ruido repetido", - "discoverButton": "Escanear muestras", - "discoverScanning": "Escaneando…", - "discoverEmpty": "No se encontró ruido repetido. Active la retención de Raw Output y ejecute algunos comandos primero.", - "discoverSamples": "{count} muestra(s) escaneada(s)", - "discoverHits": "{hits}× en todas las muestras", - "learnHeading": "Aprender un filtro para un comando", - "learnCommandPlaceholder": "p. ej., npm install", - "learnButton": "Sugerir filtro", - "learnEmpty": "Aún no hay sugerencias. Escriba un comando que haya ejecutado y escanee.", - "learnSamplesUsed": "Aprendido de {count} muestra(s) coincidente(s)", - "suggestionError": "No se pudieron cargar las sugerencias. Compruebe la autenticación de administración e inténtelo de nuevo.", - "tomlImportTitle": "Importar filtros TOML de RTK", - "tomlImportDesc": "Valide los filtros de esquema v1 TOML de RTK e instálelos globalmente. La instalación escribe en DATA_DIR/rtk/filters.toml; los archivos existentes solo se reemplazan tras una confirmación explícita.", - "tomlChooseFile": "Elegir un archivo TOML", - "tomlImportPlaceholder": "Pegue el contenido de filters.toml de RTK aquí...", - "tomlValidate": "Validar", - "tomlValidating": "Validando…", - "tomlInstall": "Instalar globalmente", - "tomlInstalling": "Instalando…", - "tomlConfirmOverwrite": "Reemplazar el archivo global existente y crear una copia de seguridad", - "tomlValidationPassed": "Validación superada", - "tomlValidationFailed": "Validación completada con pruebas inline fallidas", - "tomlValidationSummary": "{filters} filtro(s), {tests} prueba(s) inline", - "tomlInstalled": "Instalado en {path}", - "tomlBackupCreated": "Se creó una copia de seguridad del archivo anterior.", - "tomlTestCount": "{count} prueba(s)", - "tomlTestPassed": "Aprobado", - "tomlTestFailed": "Fallido", - "tomlImportError": "No se pudo procesar el archivo TOML de RTK.", - "tomlFileReadError": "No se pudo leer el archivo TOML seleccionado." + "learnDiscoverTitle": "Learn & Discover filters", + "learnDiscoverDesc": "Mine your captured command output (Raw Output retention must be on) to suggest new RTK filters. Suggestions only — you review and save them.", + "discoverHeading": "Discover repeated noise", + "discoverButton": "Scan samples", + "discoverScanning": "Scanning…", + "discoverEmpty": "No repeated noise found. Enable Raw Output retention and run a few commands first.", + "discoverSamples": "{count} sample(s) scanned", + "discoverHits": "{hits}× across samples", + "learnHeading": "Learn a filter for a command", + "learnCommandPlaceholder": "e.g. npm install", + "learnButton": "Suggest filter", + "learnEmpty": "No suggestion yet. Type a command you have run and scan.", + "learnSamplesUsed": "Learned from {count} matching sample(s)", + "suggestionError": "Could not load suggestions. Check management auth and try again.", + "tomlImportTitle": "Import RTK TOML filters", + "tomlImportDesc": "Validate RTK TOML schema v1 filters and install them globally. Installation writes DATA_DIR/rtk/filters.toml; existing files are replaced only after explicit confirmation.", + "tomlChooseFile": "Choose a TOML file", + "tomlImportPlaceholder": "Paste RTK filters.toml content here...", + "tomlValidate": "Validate", + "tomlValidating": "Validating…", + "tomlInstall": "Install globally", + "tomlInstalling": "Installing…", + "tomlConfirmOverwrite": "Replace the existing global file and create a backup", + "tomlValidationPassed": "Validation passed", + "tomlValidationFailed": "Validation completed with failing inline tests", + "tomlValidationSummary": "{filters} filter(s), {tests} inline test(s)", + "tomlInstalled": "Installed at {path}", + "tomlBackupCreated": "A backup of the previous file was created.", + "tomlTestCount": "{count} test(s)", + "tomlTestPassed": "Passed", + "tomlTestFailed": "Failed", + "tomlImportError": "Could not process the RTK TOML file.", + "tomlFileReadError": "Could not read the selected TOML file." }, "compressionEngineConfig": { - "loading": "Cargando…", - "loadFailed": "Error al cargar la información del motor.", - "engineNotFound": "Motor \"{engine}\" no encontrado.", - "saveFailed": "Error al guardar la configuración.", - "previewFailed": "Error en la vista previa.", - "panelPointerPrefix": "Active o desactive esta capa y establezca su nivel en", - "compressionSettings": "Ajustes de compresión", - "panelPointerSuffix": ". Esta página solo edita su configuración detallada.", - "configuration": "Configuración", - "noAdditionalConfiguration": "Sin configuración adicional.", - "save": "Guardar", - "saving": "Guardando…", - "globalSettingsOnly": "Esta capa se configura mediante los ajustes globales; todavía no hay ninguna anulación por motor para guardar aquí.", - "preview": "Vista previa", - "previewInput": "Entrada de vista previa", - "processing": "Procesando…", - "previewSample": "El rápido zorro marrón salta sobre el perro perezoso. Este es un mensaje de muestra utilizado para previsualizar la compresión. Contiene suficiente texto para mostrar un ahorro significativo de tokens.", - "originalTokens": "Tokens originales", - "compressedTokens": "Tokens comprimidos", - "savings": "Ahorro", + "loading": "Loading…", + "loadFailed": "Failed to load engine information.", + "engineNotFound": "Engine \"{engine}\" not found.", + "saveFailed": "Failed to save configuration.", + "previewFailed": "Preview failed.", + "panelPointerPrefix": "Turn this layer on or off and set its level in", + "compressionSettings": "Compression Settings", + "panelPointerSuffix": ". This page edits its detailed configuration only.", + "configuration": "Configuration", + "noAdditionalConfiguration": "No additional configuration.", + "save": "Save", + "saving": "Saving…", + "globalSettingsOnly": "This layer is configured by the global settings; there is no per-engine override to save here yet.", + "preview": "Preview", + "previewInput": "Preview input", + "processing": "Processing…", + "previewSample": "The quick brown fox jumps over the lazy dog. This is a sample message used to preview compression. It contains enough text to show meaningful token savings.", + "originalTokens": "Original tokens", + "compressedTokens": "Compressed tokens", + "savings": "Savings", "original": "Original", - "compressed": "Comprimido", - "diff": "Diferencias", - "last7Days": "Últimos 7 días", - "noDataYet": "Aún no hay datos", - "runs": "Ejecuciones", - "tokensSaved": "Tokens ahorrados", - "averageSavings": "Ahorro promedio", + "compressed": "Compressed", + "diff": "Diff", + "last7Days": "Last 7 days", + "noDataYet": "No data yet", + "runs": "Runs", + "tokensSaved": "Tokens saved", + "averageSavings": "Average savings", "diffLabels": { - "change": "Cambio", - "added": "Añadido", - "removed": "Eliminado", - "modified": "Modificado" + "change": "Change", + "added": "Added", + "removed": "Removed", + "modified": "Modified" }, "engines": { "headroom": { "name": "Headroom SmartCrusher", - "description": "Compactación tabular sin pérdidas de arrays JSON homogéneos con marcadores explícitos de recuento de filas." + "description": "Lossless tabular compaction of homogeneous JSON arrays with explicit row-count markers." }, "session-dedup": { - "name": "Deduplicación de sesión", - "description": "Deduplicación de bloques entre turnos con marcadores de contenido recuperables." + "name": "Session Dedup", + "description": "Cross-turn block deduplication with recoverable content markers." }, "ccr": { "name": "CCR", - "description": "Marcadores de recuperación direccionados por contenido para bloques de contexto repetidos." + "description": "Content-addressed retrieval markers for repeated context blocks." }, "llmlingua": { - "name": "LLMLingua-2 (Poda semántica)", - "description": "Clasificación de tokens semánticos basada en ONNX. Comprime solo prosa; los bloques de código y las construcciones preservadas están protegidos. Falla en abierto ante errores del modelo o del worker." + "name": "LLMLingua-2 (Semantic Pruning)", + "description": "ONNX-based semantic token classification. Compresses prose only; code blocks and preserved constructs are protected. Fails open on model or worker errors." }, "lite": { "name": "Lite", - "description": "Reducción rápida de espacios en blanco, resultados de herramientas y URL de imágenes." + "description": "Fast whitespace, tool-result and image URL reduction." }, "aggressive": { - "name": "Agresivo", - "description": "Resumen, compresión de resultados de herramientas y envejecimiento progresivo." + "name": "Aggressive", + "description": "Summarization, tool-result compression and progressive aging." }, "ultra": { "name": "Ultra", - "description": "Poda heurística de tokens con una alternativa de SLM local opcional." + "description": "Heuristic token pruning with an optional local SLM fallback." } }, "fields": { "minBlockChars": { - "label": "Caracteres mínimos del bloque", - "description": "Cantidad mínima de caracteres para que un bloque de sufijo sea candidato a la deduplicación." + "label": "Minimum block characters", + "description": "Minimum character count for a suffix block to be a deduplication candidate." }, "fuzzy": { - "label": "Deduplicación difusa de casi duplicados", - "description": "Activar para reemplazar mensajes completos que sean al menos un 85% similares a un mensaje anterior con un marcador CCR recuperable." + "label": "Fuzzy near-duplicate deduplication", + "description": "Opt in to replace whole messages that are at least about 85% similar to an earlier message with a recoverable CCR marker." }, "minChars": { - "label": "Caracteres mínimos del bloque", - "description": "Cantidad mínima de caracteres para que un bloque sea candidato a CCR." + "label": "Minimum block characters", + "description": "Minimum character count for a block to be a CCR candidate." }, "retrievalRampFactor": { - "label": "Factor de rampa de recuperación (H8)", - "description": "Controla con qué fuerza los bloques recuperados con frecuencia resisten la compresión. Cada recuperación previa aumenta el tamaño mínimo efectivo del bloque de forma lineal; 1 desactiva la rampa." + "label": "Retrieval ramp factor (H8)", + "description": "Controls how strongly frequently retrieved blocks resist compression. Each prior retrieval raises the effective minimum block size linearly; 1 disables the ramp." }, "model": { - "label": "Modelo" + "label": "Model" }, "minTokens": { - "label": "Mínimo de tokens (límite inferior)" + "label": "Minimum tokens (floor)" }, "compressionRate": { - "label": "Tasa de compresión" + "label": "Compression rate" }, "modelPath": { - "label": "Ruta del modelo" + "label": "Model path" }, "minRows": { - "label": "Filas mínimas para compactar", - "description": "Cantidad mínima de filas en un array JSON homogéneo requerida para activar la compactación tabular. Predeterminado: 8." + "label": "Minimum rows to compact", + "description": "Minimum rows in a homogeneous JSON array required to trigger tabular compaction. Default: 8." }, "preserveSystemPrompt": { - "label": "Preservar el mensaje del sistema" + "label": "Preserve system prompt" }, "summarizerEnabled": { - "label": "Activar resumidor" + "label": "Enable summarizer" }, "maxTokensPerMessage": { - "label": "Máximo de tokens por mensaje" + "label": "Maximum tokens per message" }, "minSavingsThreshold": { - "label": "Umbral mínimo de ahorro" + "label": "Minimum savings threshold" }, "minScoreThreshold": { - "label": "Umbral mínimo de puntuación" + "label": "Minimum score threshold" }, "slmFallbackToAggressive": { - "label": "Recurrir a Agresivo" + "label": "Fall back to Aggressive" }, "intensity": { - "label": "Intensidad" + "label": "Intensity" }, "minMessageLength": { - "label": "Longitud mínima del mensaje" + "label": "Minimum message length" } }, "engineFields": { "llmlingua": { "compressionRate": { - "label": "Tasa de compresión (proporción a mantener)" + "label": "Compression rate (keep ratio)" }, "modelPath": { - "label": "Ruta del modelo (anulación sin conexión)" + "label": "Model path (offline override)" } } }, "options": { "model": { - "tinybert": "TinyBERT (57 MB, rápido — predeterminado)", - "bert-base": "BERT-base (710 MB, mayor precisión)" + "tinybert": "TinyBERT (57 MB, fast — default)", + "bert-base": "BERT-base (710 MB, higher accuracy)" }, "intensity": { "lite": "Lite", - "full": "Completo", + "full": "Full", "ultra": "Ultra" } } @@ -7775,243 +7795,243 @@ "save": "Save", "cancel": "Cancel", "enabled": "Enabled", - "loading": "Cargando…", - "hubTitle": "Centro de compresión", - "hubDescription": "Elige qué perfil de compresión se ejecuta globalmente.", - "hideExplanation": "Ocultar explicación", - "howItWorks": "Cómo funciona", - "saveSettingsFailed": "Error al guardar la configuración.", - "explanationIntro": "La compresión reduce los tokens y el costo al reescribir el historial antes de enviarlo al proveedor, conservando el significado.", - "explanationActiveProfile": "Perfil activo: elige qué perfil de compresión se ejecuta globalmente — el Predeterminado derivado del panel o una de tus combinaciones con nombre guardadas.", - "explanationDefault": "Predeterminado (del panel): derivado del interruptor principal y de los selectores por motor que configures en la Configuración de compresión.", - "explanationNamedCombos": "Combinaciones con nombre: canalizaciones guardadas que creas en el editor de combinaciones con nombre. Al seleccionar una, se convierte en el perfil activo para cada solicitud.", - "explanationPreview": "Vista previa: muestra qué motores ejecuta el perfil activo, en orden.", - "activeProfile": "Perfil activo", - "activeProfileDescription": "Elige qué perfil de compresión se ejecuta globalmente — el Predeterminado derivado del panel o una combinación con nombre guardada.", - "defaultFromPanel": "Predeterminado (del panel)", - "runs": "Ejecuta:", - "defaultConfiguredPrefix": "Predeterminado — configurado en", - "compressionSettings": "Configuración de compresión", - "providerDelegated": "Compresión delegada en el proveedor", - "contextEditingClaude": "Edición de contexto (Claude)", - "contextEditingDescription": "Permite al proveedor borrar bloques antiguos de uso de herramientas en el servidor, sin reescribir el mensaje.", - "contextEditingAria": "Edición de contexto", - "contextEditingNote": "Actualmente disponible solo para Claude (Anthropic). Es un modo delegado: el proveedor borra los bloques antiguos de uso de herramientas en el servidor; nosotros no reescribimos el mensaje. No afecta a otros proveedores.", - "namedCombos": "Combinaciones con nombre", - "namedCombosDescription": "Guarda diferentes canalizaciones y asígnalas a combinaciones de enrutamiento específicas.", - "comboNamePlaceholder": "Nombre de la combinación", - "descriptionPlaceholder": "Descripción", - "nameRequired": "Introduce un nombre para la combinación antes de guardar.", - "pipelineRequired": "Añade al menos un paso de canalización antes de guardar.", - "saveComboFailed": "Error al guardar la combinación (HTTP {status}).", - "deleteNamedConfirm": "¿Eliminar la combinación “{name}”?", + "loading": "Loading…", + "hubTitle": "Compression Hub", + "hubDescription": "Pick which compression profile runs globally.", + "hideExplanation": "Hide explanation", + "howItWorks": "How it works", + "saveSettingsFailed": "Failed to save settings.", + "explanationIntro": "Compression reduces tokens and cost by rewriting history before it is sent to the provider while preserving meaning.", + "explanationActiveProfile": "Active profile: chooses which compression profile runs globally — the panel-derived Default or one of your saved named combos.", + "explanationDefault": "Default (from panel): derived from the master switch and per-engine toggles you configure in Compression Settings.", + "explanationNamedCombos": "Named combos: saved pipelines you build in the named-combo editor. Selecting one makes it the active profile for every request.", + "explanationPreview": "Preview: shows which engines the active profile runs, in order.", + "activeProfile": "Active profile", + "activeProfileDescription": "Pick which compression profile runs globally — the panel-derived Default or a saved named combo.", + "defaultFromPanel": "Default (from panel)", + "runs": "Runs:", + "defaultConfiguredPrefix": "Default — configured in", + "compressionSettings": "Compression Settings", + "providerDelegated": "Provider-delegated compression", + "contextEditingClaude": "Context Editing (Claude)", + "contextEditingDescription": "Lets the provider clear old tool-use blocks server-side, without rewriting the message.", + "contextEditingAria": "Context Editing", + "contextEditingNote": "Currently available for Claude (Anthropic) only. It is a delegated mode: the provider clears old tool-use blocks server-side — we do not rewrite the message. It does not affect other providers.", + "namedCombos": "Named combos", + "namedCombosDescription": "Save different pipelines and assign them to specific routing combos.", + "comboNamePlaceholder": "Combo name", + "descriptionPlaceholder": "Description", + "nameRequired": "Enter a combo name before saving.", + "pipelineRequired": "Add at least one pipeline step before saving.", + "saveComboFailed": "Failed to save combo (HTTP {status}).", + "deleteNamedConfirm": "Delete combo “{name}”?", "intensityLite": "Lite", - "intensityFull": "Completa", + "intensityFull": "Full", "intensityUltra": "Ultra", - "active": "Activo", - "languagePacksList": "Paquetes de idioma: {packs}", - "dragToReorder": "Arrastra para reordenar el paso", - "engine": "Motor", - "intensity": "Intensidad" + "active": "Active", + "languagePacksList": "Language packs: {packs}", + "dragToReorder": "Drag to reorder step", + "engine": "Engine", + "intensity": "Intensity" }, "compressionStudio": { - "noRun": "No hay ninguna ejecución de compresión disponible.", - "liveDataHint": "Los datos en tiempo real llegan a través del canal de compresión WebSocket.", - "cockpitView": "Vista de cabina", - "canvas": "Lienzo", - "waterfall": "Cascada", - "replayDone": "Reproducción completada", - "pauseReplay": "Pausar reproducción", - "playReplay": "Iniciar reproducción", - "pause": "Pausar", - "replay": "Reproducción", - "resetReplay": "Restablecer reproducción", - "stepProgress": "paso {current}/{total}", - "inlineView": "En línea", - "splitComingSoon": "Vista dividida (próximamente)", - "inputPlaceholder": "Pega un prompt, la salida de una herramienta o el contexto…", - "activeCombined": "Activo en el flujo combinado", - "requiresOnnx": "requiere un modelo ONNX", - "verifyFidelity": "Verificar fidelidad (rechazar cualquier capa que corrompa el contenido)", - "fuzzyDedup": "Deduplicación difusa (casi duplicado → CCR)", - "protectSensitive": "Proteger contenido sensible (filtro de riesgo)", - "quantumLock": "QuantumLock (estabilizar el prefijo de caché)", - "saliencyHeatmap": "Mapa de calor de saliencia", - "running": "Ejecutando…", - "run": "Ejecutar", - "laneRejected": "rechazado: {reason}", + "noRun": "No compression run available.", + "liveDataHint": "Live data arrives through the WebSocket compression channel.", + "cockpitView": "Cockpit view", + "canvas": "Canvas", + "waterfall": "Waterfall", + "replayDone": "Replay complete", + "pauseReplay": "Pause replay", + "playReplay": "Play replay", + "pause": "Pause", + "replay": "Replay", + "resetReplay": "Reset replay", + "stepProgress": "step {current}/{total}", + "inlineView": "Inline", + "splitComingSoon": "Split view (coming soon)", + "inputPlaceholder": "Paste a prompt, tool output, or context…", + "activeCombined": "Active in the combined flow", + "requiresOnnx": "requires an ONNX model", + "verifyFidelity": "Verify fidelity (reject any layer that corrupts content)", + "fuzzyDedup": "Fuzzy deduplication (near-duplicate → CCR)", + "protectSensitive": "Protect sensitive content (risk gate)", + "quantumLock": "QuantumLock (stabilize the cache prefix)", + "saliencyHeatmap": "Saliency heatmap", + "running": "Running…", + "run": "Run", + "laneRejected": "rejected: {reason}", "error": "error", - "combinedFlow": "Flujo combinado", - "eachLayer": "Cada capa por separado", - "diff": "Diferencia", - "combined": "combinado", - "skipped": "omitir", - "input": "ENTRADA", - "output": "SALIDA", + "combinedFlow": "Combined flow", + "eachLayer": "Each layer separately", + "diff": "Difference", + "combined": "combined", + "skipped": "skip", + "input": "INPUT", + "output": "OUTPUT", "tokenCount": "{count, number} tokens", "tokenShort": "tok", - "provider": "Proveedor", - "judgeModel": "Modelo juez", - "judgeModelPlaceholder": "ej. claude-haiku", - "maxCostUsd": "Límite en USD", - "enterJudgeModel": "Introduce un modelo juez", - "verifying": "Verificando…", - "verifyAll": "Verificar todo", - "spent": "gastado ${spent} / ${cap}", - "capReached": "límite alcanzado", - "loadAb": "Cargar A/B", - "engine": "Motor", - "savings": "Ahorros", - "retention": "Retención", - "outputTokensShort": "Tokens de salida", - "fidelity": "Fidelidad", - "playTab": "Reproducir", - "compareTab": "Comparar", - "encoderComparison": "Codificador A/B — {count} array(s)", - "encoderWinner": "ganador: {winner}", - "encoder": "codificador", + "provider": "Provider", + "judgeModel": "Judge model", + "judgeModelPlaceholder": "e.g. claude-haiku", + "maxCostUsd": "USD cap", + "enterJudgeModel": "Enter a judge model", + "verifying": "Verifying…", + "verifyAll": "Verify all", + "spent": "spent ${spent} / ${cap}", + "capReached": "cap reached", + "loadAb": "Load A/B", + "engine": "Engine", + "savings": "Savings", + "retention": "Retention", + "outputTokensShort": "Output tokens", + "fidelity": "Fidelity", + "playTab": "Play", + "compareTab": "Compare", + "encoderComparison": "Encoder A/B — {count} array(s)", + "encoderWinner": "winner: {winner}", + "encoder": "encoder", "bytes": "bytes", "tokensCl100k": "tokens (cl100k)" }, "omniglyph": { - "preview": "Vista previa", - "description": "Compresión de contexto como imagen. Renderiza el prompt del sistema, la documentación de herramientas y el historial denso como páginas PNG compactas que Claude Fable 5 lee en lugar de texto. Los tokens de imagen se facturan por dimensiones en lugar de caracteres, por lo que el bloque convertido cuesta aproximadamente 10× menos. Solo ruta directa de Anthropic.", - "economicsTitle": "El aspecto económico", + "preview": "Preview", + "description": "Context-as-image compression. Renders the system prompt, tool documentation, and dense history as compact PNG pages that Claude Fable 5 reads instead of text. Image tokens are billed by dimensions rather than characters, so the converted block costs about 10× less. Direct Anthropic route only.", + "economicsTitle": "The economics", "economics": { - "fewerTokens": "menos tokens en el bloque convertido", - "savings": "ahorro de extremo a extremo (medido)", - "imageTokens": "tokens de imagen para una página de 1568×728 (unos 28k caracteres)", - "accuracy": "precisión de lectura en Fable 5 (n=30)" + "fewerTokens": "fewer tokens on the converted block", + "savings": "end-to-end savings (measured)", + "imageTokens": "image tokens for a 1568×728 page (about 28k characters)", + "accuracy": "reading accuracy on Fable 5 (n=30)" }, - "beforeAfterTitle": "Antes → después", - "blockSavings": "−{percent}% de tokens en este bloque", - "realRender": "Un renderizado real de {characters, number} caracteres de documentación densa de herramientas, no una maqueta.", - "textTokens": "Texto · ≈ {tokens, number} tokens", - "renderedTokens": "Página renderizada · ≈ {tokens, number} tokens", - "renderedImageAlt": "Página densa renderizada, {width}×{height}px", - "gatesTitle": "Cuándo se activa", - "gatesDescription": "Fallo cerrado: cada puerta debe superarse, o la solicitud pasa sin cambios (cada omisión se registra como skip:<reason>).", + "beforeAfterTitle": "Before → after", + "blockSavings": "−{percent}% tokens on this block", + "realRender": "A real render of {characters, number} characters of dense tool documentation — not a mockup.", + "textTokens": "Text · ≈ {tokens, number} tokens", + "renderedTokens": "Rendered page · ≈ {tokens, number} tokens", + "renderedImageAlt": "Rendered dense page, {width}×{height}px", + "gatesTitle": "When it fires", + "gatesDescription": "Fail-closed: every gate must pass, or the request passes through untouched (each skip is recorded as skip:<reason>).", "gates": { "model": { - "label": "Modelo", + "label": "Model", "pass": "claude-fable-5", - "why": "Solo Fable 5 lee páginas densas con un 100 % de precisión (medido, n=30). GPT-5.5 y Gemini 2.5 Flash están bloqueados." + "why": "Only Fable 5 reads dense pages at 100% accuracy (measured, n=30). GPT-5.5 and Gemini 2.5 Flash are blocked." }, "transport": { - "label": "Transporte", - "pass": "Anthropic directo", - "why": "Los agregadores remuestrean las imágenes y destruyen la legibilidad; solo la ruta directa es autoritativa." + "label": "Transport", + "pass": "direct Anthropic", + "why": "Aggregators resample images and destroy legibility — only the direct route is authoritative." }, "format": { - "label": "Formato", - "pass": "nativo de Claude", - "why": "El cuerpo debe usar el formato de Claude y nunca debe incluir un rol de sistema dentro de los mensajes." + "label": "Format", + "pass": "native Claude", + "why": "The body must use Claude format and must never put a system role inside messages." }, "profitable": { - "label": "Rentable", - "pass": "suficientemente denso", - "why": "La barrera de coste exacta de parches de 28px decide por solicitud; el texto pequeño o disperso pasa intacto." + "label": "Profitable", + "pass": "dense enough", + "why": "The exact 28px-patch cost gate decides per request; small or sparse text passes through untouched." } }, - "enableTitle": "Habilitar el motor", - "enableDescription": "Se ejecuta al final de la pila (después de que RTK/Caveman limpie el texto y OmniGlyph convierta el resto en imágenes) y también se ejecuta de forma independiente a través del modo omniglyph. Esta es una vista previa y permanece desactivada por defecto hasta que se complete la validación de extremo a extremo.", - "saved": "Guardado.", - "saveFailed": "No se pudo guardar.", - "enableAria": "Habilitar el motor OmniGlyph" + "enableTitle": "Enable the engine", + "enableDescription": "Runs last in the stack (after RTK/Caveman cleans the text, OmniGlyph converts the remainder to images) and also runs standalone through omniglyph mode. This is a preview and remains off by default until end-to-end validation is complete.", + "saved": "Saved.", + "saveFailed": "Could not save.", + "enableAria": "Enable the OmniGlyph engine" }, "embeddedServices": { - "title": "Servicios integrados", - "description": "Motores locales gestionados bajo demanda: CLIProxyAPI, 9Router, Mux y Bifrost. Accesibles solo en loopback.", - "stateRunning": "En ejecución", - "stateStopped": "Detenido", - "stateStarting": "Iniciando", - "stateStopping": "Deteniendo", + "title": "Embedded Services", + "description": "Local engines managed on demand — CLIProxyAPI, 9Router, Mux, and Bifrost. Accessible on loopback only.", + "stateRunning": "Running", + "stateStopped": "Stopped", + "stateStarting": "Starting", + "stateStopping": "Stopping", "stateError": "Error", - "stateNotInstalled": "No instalado", - "stateUnknown": "Desconocido", - "port": "puerto {port}", - "externalBadge": "Gestionado externamente", - "externalTitle": "9Router externo detectado", - "externalDescription": "OmniRoute encontró 9Router en {host}:{port}. Su ciclo de vida, registros, actualizaciones y clave de servicio siguen siendo gestionados por la instalación externa.", - "start": "Iniciar", - "starting": "Iniciando…", - "stop": "Detener", - "stopping": "Deteniendo…", - "restart": "Reiniciar", - "restarting": "Reiniciando…", - "update": "Actualizar", - "updating": "Actualizando…", - "install": "Instalar", - "installing": "Instalando…", - "autoStart": "Inicio automático", - "autoStartDescription": "Iniciar {name} automáticamente cuando se inicie OmniRoute", - "apiKey": "Clave API", - "apiKeyDescription": "Clave utilizada por OmniRoute para autenticarse con {name}", - "keyRotated": "Clave rotada — {name} se reinició para aplicar la nueva clave", - "keyRotateFailed": "Error al rotar la clave", - "keyRevealFailed": "Error al revelar la clave", - "keyRevealEmpty": "Error al revelar: no se devolvió la clave", - "reveal": "Revelar", - "revealing": "Revelando…", - "hide": "Ocultar", - "rotateKey": "Rotar clave", - "rotating": "Rotando…", - "keyAutoHide": "La clave se ocultará automáticamente en 30 segundos.", - "revealTitle": "Mostrar clave API", - "revealConfirm": "Revelar la clave API quedará registrado en el registro de auditoría. ¿Continuar?", - "cancel": "Cancelar", - "install9Router": "Instalar 9Router", - "install9RouterDescription": "Descarga e instala 9Router a través de npm. Requiere aproximadamente 500 MB de espacio en disco.", - "version": "Versión", - "versionHint": "Introduce “latest” o una versión específica (por ejemplo, 1.2.3).", - "servicePort": "Puerto", - "servicePortHint": "OmniRoute y 9Router deben usar puertos diferentes. El puerto predeterminado de 9Router es 20130.", - "installationFailed": "Error de instalación (HTTP {status})", - "installationSucceeded": "9Router se instaló correctamente. Iniciando…", - "networkInstallFailed": "Error de red — no se pudo conectar con el endpoint de instalación", - "availableModels": "Modelos disponibles", - "modelsLoading": "Cargando…", - "modelsDiscovered": "{count, plural, one {# modelo descubierto} other {# modelos descubiertos}}", - "modelsLoadFailed": "Error al cargar los modelos", - "refreshing": "Actualizando…", - "refreshNow": "Actualizar ahora", - "noModels": "No se encontraron modelos. Selecciona “Actualizar ahora” para sincronizar desde el servicio en ejecución.", - "unavailable": "No disponible", - "pageOf": "Página {page} de {total}", - "previous": "Anterior", - "next": "Siguiente", - "providerExposure": "Exposición del proveedor", - "providerExposureDescription": "Exponer los modelos de 9Router como un destino de enrutamiento bajo el prefijo 9router/.", - "providerExposureLabel": "Exponer como 9router/…", - "providerExposureHint": "Cuando está habilitado, los modelos descubiertos aparecen en los selectores de proveedores en todo OmniRoute.", - "providerExposureUpdateFailed": "Error al actualizar (HTTP {status})", - "providerExposureNetworkFailed": "Error de red — no se pudo actualizar la configuración de exposición del proveedor", - "webUi": "Interfaz web de 9Router", - "openNewTab": "Abrir en una pestaña nueva", - "filterLogs": "Filtrar registros…", - "resume": "Reanudar", - "pause": "Pausar", - "clear": "Limpiar", - "download": "Descargar", - "noLogs": "Aún no hay salida de registro.", - "logStreamFailed": "No se pueden transmitir los registros de {name}. Compruebe el acceso local y el estado del servicio.", - "fallbackRouting": "Enrutamiento de respaldo", - "fallbackRoutingDescription": "Reintentar solicitudes fallidas del proveedor a través de CLIProxyAPI", - "enableFallback": "Habilitar respaldo", - "cliproxyUrl": "URL de CLIProxyAPI", - "fallbackCodes": "Códigos de estado de respaldo (separados por comas)", - "invalidUrl": "URL no válida — debe comenzar con http:// o https://", - "saved": "Guardado", - "saveFailed": "Error al guardar la configuración", - "modelMapping": "Mapeo de modelos", - "modelMappingDescription": "Mapee los ID de modelo de OmniRoute a los ID de modelo de CLIProxyAPI (por ejemplo, \"gpt-4o\": \"openai-gpt-4o\")", - "modelMappingEditor": "Editor JSON de mapeo de modelos", - "mappingSaved": "Mapeo guardado", - "mappingSaveFailed": "Error al guardar el mapeo", - "mappingInvalidJson": "JSON no válido.", - "mappingMustBeObject": "El mapeo debe ser un objeto JSON, no un array o un valor primitivo.", - "mappingValueMustBeString": "El valor para la clave “{key}” debe ser una cadena.", - "save": "Guardar" + "stateNotInstalled": "Not installed", + "stateUnknown": "Unknown", + "port": "port {port}", + "externalBadge": "Externally managed", + "externalTitle": "External 9Router detected", + "externalDescription": "OmniRoute found 9Router at {host}:{port}. Its lifecycle, logs, updates, and service key remain managed by the external installation.", + "start": "Start", + "starting": "Starting…", + "stop": "Stop", + "stopping": "Stopping…", + "restart": "Restart", + "restarting": "Restarting…", + "update": "Update", + "updating": "Updating…", + "install": "Install", + "installing": "Installing…", + "autoStart": "Auto-start", + "autoStartDescription": "Launch {name} automatically when OmniRoute starts", + "apiKey": "API Key", + "apiKeyDescription": "Key used by OmniRoute to authenticate with {name}", + "keyRotated": "Key rotated — {name} restarted to apply the new key", + "keyRotateFailed": "Failed to rotate key", + "keyRevealFailed": "Failed to reveal key", + "keyRevealEmpty": "Reveal failed: key not returned", + "reveal": "Reveal", + "revealing": "Revealing…", + "hide": "Hide", + "rotateKey": "Rotate key", + "rotating": "Rotating…", + "keyAutoHide": "Key will be hidden automatically in 30 seconds.", + "revealTitle": "Reveal API Key", + "revealConfirm": "Revealing the API key will be logged in the audit trail. Continue?", + "cancel": "Cancel", + "install9Router": "Install 9Router", + "install9RouterDescription": "Downloads and installs 9Router via npm. Requires approximately 500 MB of disk space.", + "version": "Version", + "versionHint": "Enter “latest” or a specific version (for example, 1.2.3).", + "servicePort": "Port", + "servicePortHint": "OmniRoute and 9Router must use different ports. The default 9Router port is 20130.", + "installationFailed": "Installation failed (HTTP {status})", + "installationSucceeded": "9Router installed successfully. Starting up…", + "networkInstallFailed": "Network error — could not reach the install endpoint", + "availableModels": "Available Models", + "modelsLoading": "Loading…", + "modelsDiscovered": "{count, plural, one {# model discovered} other {# models discovered}}", + "modelsLoadFailed": "Failed to load models", + "refreshing": "Refreshing…", + "refreshNow": "Refresh now", + "noModels": "No models found. Select “Refresh now” to sync from the running service.", + "unavailable": "Unavailable", + "pageOf": "Page {page} of {total}", + "previous": "Previous", + "next": "Next", + "providerExposure": "Provider Exposure", + "providerExposureDescription": "Expose 9Router models as a routing target under the 9router/ prefix.", + "providerExposureLabel": "Expose as 9router/…", + "providerExposureHint": "When enabled, discovered models appear in provider selectors across OmniRoute.", + "providerExposureUpdateFailed": "Failed to update (HTTP {status})", + "providerExposureNetworkFailed": "Network error — could not update the provider exposure setting", + "webUi": "9Router Web UI", + "openNewTab": "Open in new tab", + "filterLogs": "Filter logs…", + "resume": "Resume", + "pause": "Pause", + "clear": "Clear", + "download": "Download", + "noLogs": "No log output yet.", + "logStreamFailed": "Unable to stream {name} logs. Check local access and service status.", + "fallbackRouting": "Fallback Routing", + "fallbackRoutingDescription": "Retry failed provider requests through CLIProxyAPI", + "enableFallback": "Enable fallback", + "cliproxyUrl": "CLIProxyAPI URL", + "fallbackCodes": "Fallback status codes (comma-separated)", + "invalidUrl": "Invalid URL — must start with http:// or https://", + "saved": "Saved", + "saveFailed": "Failed to save setting", + "modelMapping": "Model Mapping", + "modelMappingDescription": "Map OmniRoute model IDs to CLIProxyAPI model IDs (for example, \"gpt-4o\": \"openai-gpt-4o\")", + "modelMappingEditor": "Model mapping JSON editor", + "mappingSaved": "Mapping saved", + "mappingSaveFailed": "Failed to save mapping", + "mappingInvalidJson": "Invalid JSON.", + "mappingMustBeObject": "The mapping must be a JSON object, not an array or primitive value.", + "mappingValueMustBeString": "The value for key “{key}” must be a string.", + "save": "Save" }, "contextCaveman": { "title": "Caveman Engine", @@ -8035,10 +8055,10 @@ "autoDetect": "Auto-detect language", "rulesCount": "{count} rules", "inputCompressionTitle": "Compresión de entrada", - "inputCompressionDesc": "Reescribir el historial de chat con una redacción más corta. Reduce los tokens de entrada en un ~50%.", + "inputCompressionDesc": "Reescribe el historial de chat con palabras más cortas. Reduce los tokens de entrada en un ~50%.", "analyticsTitle": "Compression Analytics", "noAnalytics": "No compression analytics yet.", - "masterDisabledWarning": "El interruptor principal de Token Saver está desactivado — estos ajustes no afectarán a las solicitudes hasta que lo active desde la Configuración de compresión o lo cambie aquí.", + "masterDisabledWarning": "The Token Saver master switch is OFF — these settings will not affect requests until you turn it on from Compression Settings or change it here.", "outputMode": "Modo de salida", "outputModeDesc": "Instructs the LLM to respond in a terse, compact format.", "outputModeTitle": "Output Mode", @@ -8216,14 +8236,14 @@ "translationFailed": "Error de traducción: {error}", "pipelineDebugger": "Depurador de canalización", "translationPipeline": "Canal de traducción", - "loading": "Cargando…", + "loading": "Loading…", "compressionOriginal": "Original", - "compressionCompressed": "Comprimido", - "compressionSaved": "Guardado", - "compressionDuration": "Duración", - "pipelineStepsAria": "Pasos del pipeline", - "copyIntermediateJson": "Copiar JSON intermedio", - "copyOutputJson": "Copiar JSON de salida", + "compressionCompressed": "Compressed", + "compressionSaved": "Saved", + "compressionDuration": "Duration", + "pipelineStepsAria": "Pipeline steps", + "copyIntermediateJson": "Copy intermediate JSON", + "copyOutputJson": "Copy output JSON", "pipelineVisualization": "Visualización de tuberías", "pipelineVisualizationHint": "Envíe un mensaje para ver cómo fluye su solicitud a través de detección → traducción → llamada al proveedor.", "chatTesterDescription": "Envíe mensajes en un formato de cliente específico e inspeccione cada paso del proceso de traducción.", @@ -8289,87 +8309,87 @@ "scenarioVision": "Visión (comprensión de imágenes)", "scenarioSchemaCoercion": "Coerción de esquema (salida estructurada)", "techniques": "Técnicas:", - "friendlyTitle": "Traductor", - "friendlySubtitle": "Use su aplicación existente con cualquier proveedor — sin tener que reescribir el código.", - "conceptHeadline": "Su aplicación habla el \"idioma\" de una API. El Traductor la convierte para usar otro proveedor.", - "conceptDiagramAppLabel": "Su aplicación", - "conceptDiagramSourceLabel": "Formato de origen", + "friendlyTitle": "Translator", + "friendlySubtitle": "Use your existing app with any provider — without rewriting code.", + "conceptHeadline": "Your app speaks one API's \"language\". The Translator converts it to use another provider.", + "conceptDiagramAppLabel": "Your app", + "conceptDiagramSourceLabel": "Source format", "conceptDiagramHubLabel": "OpenAI (hub)", - "conceptDiagramTargetLabel": "Proveedor de destino", - "conceptDiagramExampleApp": "p. ej. Anthropic SDK", + "conceptDiagramTargetLabel": "Target provider", + "conceptDiagramExampleApp": "e.g. Anthropic SDK", "conceptDiagramExampleSource": "claude", "conceptDiagramExampleTarget": "Gemini", - "conceptHowItWorksToggle": "Cómo funciona", - "conceptHowItWorksBody": "Tu aplicación envía una solicitud en su propio formato. El Traductor detecta el formato, lo convierte a través de OpenAI como un centro intermedio (o directamente cuando hay un traductor directo disponible), lo envía al proveedor elegido y devuelve la respuesta convertida de nuevo al formato de tu aplicación.", - "tabTranslate": "Traducir", - "tabMonitor": "Monitorear", - "tabTranslateAriaLabel": "Ir a la pestaña Traducir", - "tabMonitorAriaLabel": "Ir a la pestaña Monitorear", - "simpleAppUsesLabel": "Mi aplicación usa", - "simpleAppUsesHint": "El formato de API que habla tu aplicación (por ejemplo, Anthropic SDK = claude).", - "simpleSendToLabel": "Enviar a", - "simpleSendToHint": "A dónde enviar realmente la solicitud (un proveedor conectado en OmniRoute).", - "simpleStartWithLabel": "Comenzar con", - "simpleStartWithExamplePlaceholder": "Seleccionar un ejemplo predefinido", - "simpleStartWithCustomOption": "Pegar tu solicitud (avanzado)", - "simpleModeLabel": "Modo", - "simpleModePreview": "Solo vista previa de la traducción", - "simpleModeSend": "Enviar y ver respuesta", - "simpleAdvancedToggle": "Avanzado", - "simpleInputPanelTitle": "Entrada", - "simpleInputPanelHint": "Mensaje de texto libre o ejemplo predefinido", - "simpleResultPanelTitle": "Traducción + Respuesta", - "narratedDetected": "✓ Detectado: {format}", - "narratedTranslating": "Traduciendo a {target}...", - "narratedSending": "Enviando a {target}...", - "narratedSuccess": "→ traducido a {target} · respuesta en {latency}ms", - "narratedError": "Falló: {reason}", - "narratedSeeTranslatedJson": "ver JSON traducido", - "narratedSeePipeline": "ver pipeline", - "advancedSectionTitle": "Avanzado", - "advancedSectionSubtitle": "JSON sin procesar, pipeline y herramientas técnicas. Todo aquí es igual que en las pestañas antiguas, solo que reorganizado.", - "advancedRawJsonTitle": "JSON sin procesar (autodetectar + Monaco)", - "advancedRawJsonSubtitle": "Pega una solicitud JSON; el formato se detecta automáticamente.", - "advancedPipelineTitle": "Pipeline intermedio de OpenAI", - "advancedPipelineSubtitle": "Visualiza cada paso de traducción (hub-and-spoke).", + "conceptHowItWorksToggle": "How it works", + "conceptHowItWorksBody": "Your app sends a request in its own format. The Translator detects the format, converts it through OpenAI as an intermediate hub (or directly when a direct translator is available), sends it to the chosen provider, and returns the response converted back to your app's format.", + "tabTranslate": "Translate", + "tabMonitor": "Monitor", + "tabTranslateAriaLabel": "Go to the Translate tab", + "tabMonitorAriaLabel": "Go to the Monitor tab", + "simpleAppUsesLabel": "My app uses", + "simpleAppUsesHint": "The API format your app speaks (e.g. Anthropic SDK = claude).", + "simpleSendToLabel": "Send to", + "simpleSendToHint": "Where to actually send the request (a provider connected in OmniRoute).", + "simpleStartWithLabel": "Start with", + "simpleStartWithExamplePlaceholder": "Select a ready-made example", + "simpleStartWithCustomOption": "Paste your request (advanced)", + "simpleModeLabel": "Mode", + "simpleModePreview": "Preview translation only", + "simpleModeSend": "Send and see response", + "simpleAdvancedToggle": "Advanced", + "simpleInputPanelTitle": "Input", + "simpleInputPanelHint": "Free-text message or ready-made example", + "simpleResultPanelTitle": "Translation + Response", + "narratedDetected": "✓ Detected: {format}", + "narratedTranslating": "Translating to {target}...", + "narratedSending": "Sending to {target}...", + "narratedSuccess": "→ translated to {target} · response in {latency}ms", + "narratedError": "Failed: {reason}", + "narratedSeeTranslatedJson": "see translated JSON", + "narratedSeePipeline": "see pipeline", + "advancedSectionTitle": "Advanced", + "advancedSectionSubtitle": "Raw JSON, pipeline and technical tools. Everything here is the same as the old tabs — just reorganized.", + "advancedRawJsonTitle": "Raw JSON (auto-detect + Monaco)", + "advancedRawJsonSubtitle": "Paste a JSON request; the format is detected automatically.", + "advancedPipelineTitle": "OpenAI intermediate pipeline", + "advancedPipelineSubtitle": "Visualize each translation step (hub-and-spoke).", "advancedStreamTransformTitle": "Stream Transformer (Chat → Responses SSE)", - "advancedStreamTransformSubtitle": "Convierte Chat Completions SSE en Responses API.", - "advancedTestBenchTitle": "Banco de pruebas (8 escenarios)", - "advancedTestBenchSubtitle": "Ejecuta todos los escenarios e informa aprobado/fallido + % de compatibilidad.", - "advancedCompressionTitle": "Vista previa de compresión", - "advancedCompressionSubtitle": "Estima el ahorro de tokens en diferentes modos de compresión.", - "monitorOriginHint": "Los eventos generados por Traducir o el pipeline principal aparecen aquí en tiempo real.", - "monitorEmptyCta": "Ve a la pestaña Traducir y envía una solicitud — aparecerá aquí.", - "monitorOpenTranslateButton": "Ir a Traducir", - "pipelineStepClientRequest": "Solicitud del cliente", - "pipelineStepClientRequestDesc": "Solicitud recibida en formato de cliente", - "pipelineStepFormatDetected": "Formato detectado", - "pipelineStepFormatDetectedDesc": "Formato de origen detectado automáticamente", - "pipelineStepOpenAIIntermediate": "Intermedio de OpenAI", - "pipelineStepOpenAIIntermediateDesc": "Traducido al formato del hub de OpenAI", - "pipelineStepProviderFormat": "Formato del proveedor", - "pipelineStepProviderFormatDesc": "Traducido al formato de destino del proveedor", - "pipelineStepProviderResponse": "Respuesta del proveedor", - "pipelineStepProviderResponseDesc": "Respuesta en streaming del proveedor", - "conceptDiagramArrow1": "habla", - "conceptDiagramArrow2": "traduce", - "conceptDiagramArrow3": "convierte", + "advancedStreamTransformSubtitle": "Converts Chat Completions SSE into Responses API.", + "advancedTestBenchTitle": "Test Bench (8 scenarios)", + "advancedTestBenchSubtitle": "Runs all scenarios and reports pass/fail + compatibility %.", + "advancedCompressionTitle": "Compression Preview", + "advancedCompressionSubtitle": "Estimate token savings across different compression modes.", + "monitorOriginHint": "Events generated by Translate or the main pipeline appear here in real time.", + "monitorEmptyCta": "Go to the Translate tab and send a request — it will appear here.", + "monitorOpenTranslateButton": "Go to Translate", + "pipelineStepClientRequest": "Client Request", + "pipelineStepClientRequestDesc": "Request received in client format", + "pipelineStepFormatDetected": "Format Detected", + "pipelineStepFormatDetectedDesc": "Auto-detected source format", + "pipelineStepOpenAIIntermediate": "OpenAI Intermediate", + "pipelineStepOpenAIIntermediateDesc": "Translated to OpenAI hub format", + "pipelineStepProviderFormat": "Provider Format", + "pipelineStepProviderFormatDesc": "Translated to provider target format", + "pipelineStepProviderResponse": "Provider Response", + "pipelineStepProviderResponseDesc": "Streaming response from provider", + "conceptDiagramArrow1": "speaks", + "conceptDiagramArrow2": "translates", + "conceptDiagramArrow3": "converts", "conceptDiagramExampleHub": "OpenAI", - "conceptDiagramHubTooltip": "Hub intermedio utilizado por el traductor para convertir entre formatos que no tienen un mapeo directo.", - "conceptDiagramSourceTooltip": "El formato de API que habla tu aplicación (por ejemplo, Anthropic SDK = claude).", - "conceptDiagramTargetTooltip": "El proveedor al que realmente se enviará la solicitud.", - "compressionEmptyHint": "Completa el campo de entrada en la pestaña Traducir (Controles simples o JSON sin procesar) para habilitar la vista previa.", - "compressionModeLabel": "Modo de compresión", - "compressionPreviewButton": "Vista previa de la compresión", - "compressionPreviewing": "Previsualizando…", - "compressionPreviewFailed": "Error en la vista previa de la compresión", + "conceptDiagramHubTooltip": "Intermediate hub used by the translator to convert between formats that don't have a direct mapping.", + "conceptDiagramSourceTooltip": "The API format your app speaks (e.g., Anthropic SDK = claude).", + "conceptDiagramTargetTooltip": "The provider where the request will actually be sent.", + "compressionEmptyHint": "Fill in the input field on the Translate tab (Simple Controls or Raw JSON) to enable the preview.", + "compressionModeLabel": "Compression mode", + "compressionPreviewButton": "Preview Compression", + "compressionPreviewing": "Previewing…", + "compressionPreviewFailed": "Compression preview failed", "tokens": "tokens", - "pauseAutoRefresh": "Pausar actualización automática", - "resumeAutoRefresh": "Reanudar actualización automática", - "live": "En vivo", - "copyInput": "Copiar entrada", - "copyOutput": "Copiar salida", - "streamTransformFailed": "Error al transformar el flujo" + "pauseAutoRefresh": "Pause auto-refresh", + "resumeAutoRefresh": "Resume auto-refresh", + "live": "Live", + "copyInput": "Copy input", + "copyOutput": "Copy output", + "streamTransformFailed": "Failed to transform stream" }, "usage": { "title": "Uso", @@ -8422,17 +8442,17 @@ "evaluateStepDescription": "Responses are compared against expected criteria. See pass/fail for each case with latency metrics and detailed feedback.", "evalsStrategyContainsLabel": "Contiene", "evalsStrategyExactLabel": "Coincidencia exacta", - "evalsStrategyRegexLabel": "Regex", + "evalsStrategyRegexLabel": "Expresión regular", "evalsStrategyCustomLabel": "Lógica personalizada", "evalsStrategyContainsDescription": "Comprueba si la salida del LLM contiene la subcadena esperada.", - "evalsStrategyExactDescription": "Comprueba si la salida del LLM coincide exactamente con el valor esperado.", - "evalsStrategyRegexDescription": "Valida la salida del LLM contra un patrón de expresión regular.", - "evalsStrategyCustomDescription": "Lógica de evaluación personalizada (configurada a través de JSON).", - "historyColumnSuiteName": "Nombre de la suite", - "historyColumnTarget": "Objetivo", - "historyColumnPassRate": "Tasa de aprobación", - "historyColumnAvgLatencyMs": "Latencia media", - "historyColumnCreatedAt": "Ejecutado", + "evalsStrategyExactDescription": "Checks if the LLM output exactly matches the expected value.", + "evalsStrategyRegexDescription": "Validates the LLM output against a regular expression pattern.", + "evalsStrategyCustomDescription": "Custom evaluation logic (configured via JSON).", + "historyColumnSuiteName": "Suite Name", + "historyColumnTarget": "Target", + "historyColumnPassRate": "Pass Rate", + "historyColumnAvgLatencyMs": "Avg Latency", + "historyColumnCreatedAt": "Executed", "evalSuites": "Suites de evaluación", "evalSuitesHint": "Click a suite to view test cases, then run to evaluate your LLM endpoints", "evalsLoading": "Cargando suites de evaluación...", @@ -8514,12 +8534,12 @@ "autoRefresh": "Actualización automática", "refreshAll": "Actualizar todo", "loadingQuotas": "Cargando...", - "showMoreQuotas": "Mostrar {count} más", - "showLessQuotas": "Mostrar menos", - "hideQuotaRow": "Ocultar esta fila de cuota", - "showQuotaRow": "Mostrar esta fila de cuota", - "hiddenQuotaRowsLabel": "Oculto:", - "quotaVisibilityUpdateFailed": "Error al actualizar la visibilidad de la cuota", + "showMoreQuotas": "Show {count} more", + "showLessQuotas": "Show less", + "hideQuotaRow": "Hide this quota row", + "showQuotaRow": "Show this quota row", + "hiddenQuotaRowsLabel": "Hidden:", + "quotaVisibilityUpdateFailed": "Failed to update quota visibility", "account": "cuenta", "modelQuotas": "Cuotas modelo", "lastUsed": "Last Refreshed", @@ -8532,12 +8552,12 @@ "notApplicable": "N/A", "rawPlanWithValue": "Plan sin formato: {plan}", "noPlanFromProvider": "Sin plan del proveedor", - "tokenExpiresIn": "El token caduca en {time}", - "tokenExpired": "Token caducado", + "tokenExpiresIn": "Token expires in {time}", + "tokenExpired": "Token expired", "noQuotaData": "Sin datos de cuota", - "cardExpand": "Expandir", - "cardCollapse": "Contraer", - "moreQuotas": "+{count} más", + "cardExpand": "Expand", + "cardCollapse": "Collapse", + "moreQuotas": "+{count} more", "ungrouped": "Ungrouped", "viewFlat": "Flat", "viewByEnvironment": "By Environment", @@ -8554,42 +8574,42 @@ "tierLite": "Lite", "tierUnknown": "Desconocido", "statTotal": "Total", - "statCritical": "Crítico", - "statAlert": "Alerta", - "statHealthy": "Saludable", - "filterPurchaseTypeLabel": "Tipo", - "filterTierLabel": "Nivel", - "purchaseAll": "Todo", - "purchaseOauthSub": "Suscripción", - "purchaseOauthFree": "OAuth gratuito", - "purchaseApiKey": "Clave de API", - "creditsLabel": "Créditos", - "creditBalanceHint": "Saldo restante", - "unlimitedLabel": "Ilimitado", - "refreshing": "Actualizando", - "resetsIn": "Se restablece en", - "usdCost": "Costo en USD", + "statCritical": "Critical", + "statAlert": "Alert", + "statHealthy": "Healthy", + "filterPurchaseTypeLabel": "Type", + "filterTierLabel": "Tier", + "purchaseAll": "All", + "purchaseOauthSub": "Subscription", + "purchaseOauthFree": "OAuth Free", + "purchaseApiKey": "API Key", + "creditsLabel": "Credits", + "creditBalanceHint": "Remaining balance", + "unlimitedLabel": "Unlimited", + "refreshing": "Refreshing", + "resetsIn": "Resets in", + "usdCost": "USD Cost", "editCutoffs": "Editar límites", "forceRefresh": "Actualizar ahora", - "resetCreditsLabel": "Créditos de restablecimiento", - "redeemResetCredit": "Canjear restablecimiento", - "manageResetCredits": "Ver créditos", - "viewResetCredits": "Ver créditos de restablecimiento", - "resetCreditsModalTitle": "Créditos de restablecimiento de Codex", - "resetCreditsModalExplainer": "Los créditos se ordenan por fecha de caducidad. El canje automático siempre utiliza el crédito que caduca primero.", - "resetCreditsLoadFailed": "Error al cargar los créditos de restablecimiento", - "resetCreditsDetailsUnavailable": "Los detalles de los créditos no están disponibles actualmente. Actualice e inténtelo de nuevo.", - "noResetCreditsAvailable": "No hay créditos de restablecimiento disponibles.", - "resetCreditDefaultTitle": "Restablecimiento completo", - "resetCreditExpiresFirst": "Vence primero", - "resetCreditExpiresAt": "Vence {date}", - "resetCreditNoExpiry": "Sin fecha de vencimiento", - "redeemThisResetCredit": "Canjear", - "confirmRedeemResetCreditTitle": "¿Canjear este crédito de restablecimiento?", - "confirmRedeemResetCredit": "Al canjearlo, se restablecen inmediatamente las ventanas de uso de Codex aptas y se consume este crédito de forma permanente.", - "confirmRedeemResetCreditButton": "Canjear crédito", - "resetCreditRedeemed": "Restablecimiento canjeado", - "resetCreditRedeemFailed": "Error al canjear el crédito de restablecimiento", + "resetCreditsLabel": "Reset credits", + "redeemResetCredit": "Redeem reset", + "manageResetCredits": "View credits", + "viewResetCredits": "View reset credits", + "resetCreditsModalTitle": "Codex reset credits", + "resetCreditsModalExplainer": "Credits are ordered by expiration. Automatic redemption always uses the credit that expires first.", + "resetCreditsLoadFailed": "Failed to load reset credits", + "resetCreditsDetailsUnavailable": "Credit details are currently unavailable. Refresh and try again.", + "noResetCreditsAvailable": "No reset credits are available.", + "resetCreditDefaultTitle": "Full reset", + "resetCreditExpiresFirst": "Expires first", + "resetCreditExpiresAt": "Expires {date}", + "resetCreditNoExpiry": "No expiration date", + "redeemThisResetCredit": "Redeem", + "confirmRedeemResetCreditTitle": "Redeem this reset credit?", + "confirmRedeemResetCredit": "Redeeming immediately resets the eligible Codex usage windows and permanently consumes this credit.", + "confirmRedeemResetCreditButton": "Redeem credit", + "resetCreditRedeemed": "Reset redeemed", + "resetCreditRedeemFailed": "Failed to redeem reset credit", "suiteBuilderSaveFailed": "Failed to save suite", "clone": "clonar", "exportSuite": "Exportar", @@ -8703,11 +8723,11 @@ "quotaCutoffsButtonDefault": "Predeterminado", "quotaCutoffsButtonHelp": "Edite los límites de cuota mínima restante para esta cuenta.", "quotaCutoffsButtonDisabled": "Aún no hay períodos de cuota disponibles para esta cuenta.", - "deactivateAccount": "Desactivar cuenta (detener enrutamiento)", - "activateAccount": "Activar cuenta (reanudar enrutamiento)", - "accountActivated": "Cuenta activada", - "accountDeactivated": "Cuenta desactivada", - "toggleActiveFailed": "Error al actualizar el estado de la cuenta", + "deactivateAccount": "Deactivate account (stop routing)", + "activateAccount": "Activate account (resume routing)", + "accountActivated": "Account activated", + "accountDeactivated": "Account deactivated", + "toggleActiveFailed": "Failed to update account status", "quotaCutoffsTitle": "Límites de cuota para {name} ({provider})", "quotaCutoffsExplainer": "Anule el porcentaje de cuota restante mínimo cuando esta cuenta deja de seleccionarse para cada ventana de cuota. Déjelo en blanco para heredar el valor predeterminado del proveedor.", "quotaCutoffsDefaultHint": "Min restante predeterminado: {default}%", @@ -8720,38 +8740,38 @@ "budgetKpiBlocked": "Bloqueado", "budgetKpiAtRisk": "En riesgo", "budgetKpiActiveKeys": "Claves activas", - "budgetPageTitle": "Presupuesto", - "budgetPageDescription": "Establece límites de gasto diarios, semanales y mensuales para cada clave de API.", - "budgetTemplateStorageHint": "{count, plural, one {# plantilla} other {# plantillas}} · editar mediante localStorage:", - "budgetAboveLimitShort": "por encima del límite ⚠", - "budgetOnTrackShort": "según lo previsto", - "budgetAtOrAboveWarning": "≥ umbral de advertencia", - "budgetTemplates": "Plantillas", - "budgetSelectKeysFirst": "Selecciona claves primero para aplicar", - "budgetApplyToSelected": "Aplicar a {count, plural, one {# clave seleccionada} other {# claves seleccionadas}}", - "budgetSelectedTemplateHint": "{count, plural, one {# seleccionado} other {# seleccionados}} · haz clic en una plantilla para aplicar", - "budgetTemplateMonthlyAmount": "${amount}/mes", - "budgetTemplateDailyAmount": "${amount}/día", - "budgetNoKeysSelected": "Ninguna clave seleccionada", - "budgetTemplateApplied": "Se aplicó \"{template}\" a {count, plural, one {# clave} other {# claves}}", - "budgetTemplateApplyFailed": "Error al aplicar la plantilla", + "budgetPageTitle": "Budget", + "budgetPageDescription": "Set daily, weekly, and monthly spending limits for each API key.", + "budgetTemplateStorageHint": "{count, plural, one {# template} other {# templates}} · edit via localStorage:", + "budgetAboveLimitShort": "above limit ⚠", + "budgetOnTrackShort": "on track", + "budgetAtOrAboveWarning": "≥ warning threshold", + "budgetTemplates": "Templates", + "budgetSelectKeysFirst": "Select keys first to apply", + "budgetApplyToSelected": "Apply to {count, plural, one {# selected key} other {# selected keys}}", + "budgetSelectedTemplateHint": "{count, plural, one {# selected} other {# selected}} · click a template to apply", + "budgetTemplateMonthlyAmount": "${amount}/month", + "budgetTemplateDailyAmount": "${amount}/day", + "budgetNoKeysSelected": "No keys selected", + "budgetTemplateApplied": "Applied \"{template}\" to {count, plural, one {# key} other {# keys}}", + "budgetTemplateApplyFailed": "Failed to apply template", "budgetTemplateNames": { - "tpl-prod": "Producción", - "tpl-dev": "Desarrollo", + "tpl-prod": "Production", + "tpl-dev": "Development", "tpl-ci": "CI" }, "budgetStatus": { - "all": "Todos", - "blocked": "Bloqueado", - "alerting": "En alerta", - "warning": "Advertencia", - "safe": "Seguro", - "no-limit": "Sin límite" + "all": "All", + "blocked": "Blocked", + "alerting": "Alerting", + "warning": "Warning", + "safe": "Safe", + "no-limit": "No limit" }, - "budgetColumnKey": "Clave", - "budgetColumnToday": "Hoy", - "budgetColumnMonth": "Mes", - "budgetColumnStatus": "Estado", + "budgetColumnKey": "Key", + "budgetColumnToday": "Today", + "budgetColumnMonth": "Month", + "budgetColumnStatus": "Status", "budgetSearchKeysPlaceholder": "Claves de búsqueda...", "budgetSortPctUsed": "Ordenar: % usado ↓", "budgetSortTodayDollar": "Ordenar: Hoy $ ↓", @@ -8760,23 +8780,23 @@ "budgetColDailyLim": "límite diario", "budgetColMonthlyLim": "límite mensual", "budgetColUsedPct": "% usado", - "percentUsed": "{pct}% usado", + "percentUsed": "{pct}% used", "budgetLoading": "Cargando…", "budgetNoKeysMatch": "Ninguna clave coincide con los filtros", "budgetLinearExtrapolation": "extrapolación lineal", "budgetThisMonthSoFar": "Este mes hasta ahora", "budgetProjectedEndOfMonth": "Fin de mes proyectado", "budgetByProvider": "por proveedor", - "budgetProjection": "Proyección", - "budgetAboveMonthlyLimit": "⚠ por encima de {limit}/mes", - "budgetCostBreakdown30d": "Desglose de costos (30 días)", - "budgetLimits": "Límites", - "budgetResetDaily": "Diario", - "budgetResetWeekly": "Semanal", - "budgetResetMonthly": "Mensual", - "budgetNextReset": "Próximo reinicio", - "budgetHardCapComingSoon": "La política de límite estricto y las alertas por correo electrónico estarán disponibles pronto", - "unknownProvider": "Proveedor desconocido", + "budgetProjection": "Projection", + "budgetAboveMonthlyLimit": "⚠ above {limit}/month", + "budgetCostBreakdown30d": "Cost breakdown (30 days)", + "budgetLimits": "Limits", + "budgetResetDaily": "Daily", + "budgetResetWeekly": "Weekly", + "budgetResetMonthly": "Monthly", + "budgetNextReset": "Next reset", + "budgetHardCapComingSoon": "Hard-cap policy and email alerts are coming soon", + "unknownProvider": "Unknown provider", "budgetDailyDollar": "Diariamente $", "budgetWeeklyDollar": "Semanal $", "budgetMonthlyDollar": "$ Mensual", @@ -8784,10 +8804,10 @@ "quotaAlerts": "Alertas de cuota", "quotaTableRefreshing": "⟳Refrescante...", "noSpendLast30Days": "Sin gastos en los últimos 30 días", - "updatedShort": "Actualizado", - "lastRefreshed": "Última actualización", - "providerQuota": "Cuota del proveedor", - "providerQuotaHomeHint": "Estado en tiempo real en las cuentas conectadas" + "updatedShort": "Updated", + "lastRefreshed": "Last refreshed", + "providerQuota": "Provider Quota", + "providerQuotaHomeHint": "Live status across connected accounts" }, "modals": { "waitingAuth": "Esperando autorización", @@ -8906,7 +8926,7 @@ "restartServerWithNewPassword": "Reinicia el servidor; usará la nueva contraseña", "backToLogin": "Volver a iniciar sesión", "forgotPassword": "¿Olvidaste tu contraseña?", - "continueWithOidc": "Continuar con OIDC", + "continueWithOidc": "Continue with OIDC", "defaultPasswordHint": "Default password: CHANGEME (unless INITIAL_PASSWORD was set)", "Authorization": "Autorización", "Content-Disposition": "Disposición de contenido", @@ -9345,12 +9365,12 @@ "browseAllSkillsOnGithub": "Explora todas las habilidades en GitHub", "apiSkills": "Habilidades API", "cliSkills": "Habilidades CLI", - "apiSkillsSubtitle": "{count} habilidades — controla OmniRoute mediante REST / HTTP", - "cliSkillsSubtitle": "{count} habilidades — controla OmniRoute mediante el binario de terminal omniroute", - "howToUseStep1": "Haz clic en {copyUrl} en la habilidad que quieras que conozca tu agente.", - "howToUseStep2": "En tu agente de IA (Claude, Cursor, Cline…), di:", - "howToUseStep2Code": "Usa la habilidad en [pasted-url]", - "howToUseStep3": "El agente obtiene el SKILL.md y aprende la API o CLI de OmniRoute — no se necesita documentación manual." + "apiSkillsSubtitle": "{count} habilidades — controla OmniRoute a través de REST / HTTP", + "cliSkillsSubtitle": "{count} habilidades — controla OmniRoute a través del binario omniroute de terminal", + "howToUseStep1": "Haz clic en {copyUrl} en la habilidad que deseas que tu agente conozca.", + "howToUseStep2": "En tu agente de IA (Claude, Cursor, Cline…), dile:", + "howToUseStep2Code": "Utiliza la habilidad en [url-pegada]", + "howToUseStep3": "The agent fetches the SKILL.md and learns OmniRoute's API or CLI — no manual docs needed." }, "cloudAgents": { "title": "Agentes de la nube", @@ -9370,27 +9390,27 @@ "taskDetail": "Detalle de la tarea", "noTasks": "Aún no hay tareas. Crea uno para comenzar.", "noTasksTitle": "Aún no hay tareas", - "noTasksDesc": "Crea tu primera tarea para comenzar.", + "noTasksDesc": "Crea tu primera tarea para empezar.", "tasksTab": "Tareas", "agentsTab": "Agentes", "settingsTab": "Configuración", - "agentsEnabled": "Habilitado", - "agentsDisabled": "Deshabilitado", - "filterAllProviders": "Todos los proveedores", - "filterAll": "Todos", - "autoRefreshing": "Actualizando automáticamente", - "viewPR": "Ver Pull Request", - "connected": "Conectado", - "notConnected": "No conectado", - "configure": "Configurar", - "settingsTitle": "Configuración de agentes en la nube", - "settingsDesc": "Configura las preferencias locales para los agentes en la nube.", - "settingEnableAgents": "Habilitar agentes en la nube", - "settingEnableAgentsDesc": "Permitir que OmniRoute orqueste agentes de programación autónomos.", - "settingAutoPR": "Crear PR automáticamente", - "settingAutoPRDesc": "Cuando se complete una tarea, crea automáticamente una Pull Request con los cambios.", - "settingRequireApproval": "Requerir aprobación del plan", - "settingRequireApprovalDesc": "Esperar siempre la aprobación manual antes de que un agente ejecute un plan propuesto.", + "agentsEnabled": "Enabled", + "agentsDisabled": "Disabled", + "filterAllProviders": "All Providers", + "filterAll": "All", + "autoRefreshing": "Auto-refreshing", + "viewPR": "View Pull Request", + "connected": "Connected", + "notConnected": "Not connected", + "configure": "Configure", + "settingsTitle": "Cloud Agent Settings", + "settingsDesc": "Configure local preferences for cloud agents.", + "settingEnableAgents": "Enable cloud agents", + "settingEnableAgentsDesc": "Allow OmniRoute to orchestrate autonomous coding agents.", + "settingAutoPR": "Auto-create PR", + "settingAutoPRDesc": "When a task is completed, automatically create a Pull Request with the changes.", + "settingRequireApproval": "Require plan approval", + "settingRequireApprovalDesc": "Always wait for manual approval before an agent executes a proposed plan.", "untitledTask": "Tarea sin título", "created": "Creado", "conversation": "Conversación", @@ -9413,18 +9433,18 @@ "repositoryUrl": "URL del repositorio", "branch": "Sucursal", "agentDescriptions": { - "jules": "Agente de programación autónomo de Google", - "devin": "Ingeniero de software de IA de Cognition", - "codexCloud": "Agente de programación en la nube de OpenAI", - "cursorCloud": "Agentes en segundo plano / en la nube de Cursor (clave de API oficial)" + "jules": "Google's autonomous coding agent", + "devin": "Cognition's AI software engineer", + "codexCloud": "OpenAI's cloud-based coding agent", + "cursorCloud": "Cursor's Background / Cloud Agents (official API key)" }, "activityTypes": { "plan": "Plan", - "command": "Comando", - "code_change": "Cambio de código", - "message": "Mensaje", + "command": "Command", + "code_change": "Code change", + "message": "Message", "error": "Error", - "completion": "Finalización" + "completion": "Completion" } }, "templateNames": { @@ -9601,11 +9621,11 @@ "cachePerformanceP95Latency": "p95 Latencia (ms)", "retry": "Reintentar", "reasoningAvgChars": "Caracteres promedio", - "tableShare": "Compartir", - "justNow": "hace un momento", - "minutesAgo": "hace {minutes}m", - "hoursAgo": "hace {hours}h", - "daysAgo": "hace {days}d", + "tableShare": "Cuota", + "justNow": "just now", + "minutesAgo": "{minutes}m ago", + "hoursAgo": "{hours}h ago", + "daysAgo": "{days}d ago", "entries": "Entries" }, "proxyConfigModal": { @@ -9711,8 +9731,8 @@ "errorResetFailed": "No se pudo restablecer el precio" }, "proxyRegistry": { - "selectAllProxies": "Seleccionar todos los proxies", - "selectProxy": "Seleccionar {name}", + "selectAllProxies": "Select all proxies", + "selectProxy": "Select {name}", "title": "Title", "description": "Description", "importLegacy": "Import Legacy", @@ -9733,11 +9753,11 @@ "modalEditTitle": "Modal Edit Title", "labelName": "Label Name", "labelType": "Tipo", - "labelFamily": "Familia de IP", + "labelFamily": "IP family", "familyAuto": "Auto (dual-stack)", - "familyIpv4": "Solo IPv4", - "familyIpv6": "Solo IPv6", - "familyHint": "Familia de direcciones de salida. Auto mantiene dual-stack; IPv4/IPv6 fijan este proxy a esa familia (evita una fuga de v4 en un proxy solo IPv6).", + "familyIpv4": "IPv4 only", + "familyIpv6": "IPv6 only", + "familyHint": "Egress address family. Auto keeps dual-stack; IPv4/IPv6 pin this proxy to that family (prevents a v4 leak under an IPv6-only proxy).", "labelHost": "Anfitrión", "labelPort": "Puerto", "labelUsername": "Nombre de usuario", @@ -9786,13 +9806,13 @@ "testSuccess": "✓ {ip}", "testLatency": "{latency}ms", "testFailure": "✗ {error}", - "repair": "Reparar", - "relayAuthMissing": "falta autenticación", - "relayRepairTooltip": "Recupere la autenticación del relay in situ. Si el token no se puede recuperar (p. ej., tras una rotación de STORAGE_ENCRYPTION_KEY), vuelva a desplegar el relay en su lugar.", - "relayRepairRedeployRequired": "La autenticación del relay no se puede recuperar — vuelva a desplegar el relay para escribir un token nuevo.", - "relayRepairFailed": "Error al reparar el relay", - "relayRepairError": "error al reparar", - "relayProbeSummary": "Sondeos de relay: {alive}/{tested} activos", + "repair": "Repair", + "relayAuthMissing": "auth missing", + "relayRepairTooltip": "Recover relay auth in place. If the token is unrecoverable (e.g. after a STORAGE_ENCRYPTION_KEY rotation), redeploy the relay instead.", + "relayRepairRedeployRequired": "Relay auth is unrecoverable — redeploy the relay to write a fresh token.", + "relayRepairFailed": "Relay repair failed", + "relayRepairError": "repair failed", + "relayProbeSummary": "Relay probes: {alive}/{tested} alive", "bulkImport": "Importación masiva", "bulkImportTitle": "Proxies de importación masiva", "bulkImportDescription": "Pegue perfiles de proxy utilizando el formato delimitado por barras verticales. Un proxy por línea. Se actualizarán los servidores proxy existentes (mismo host + puerto).", @@ -9809,37 +9829,37 @@ "bulkImportPreview": "Vista previa", "clearAssignment": "(asignación clara)", "bulkProxyAssignment": "Asignación de proxy masiva", - "testAll": "Probar todo", - "errorTestFailed": "Error al probar los proxies", - "batchSelectedCount": "{count} seleccionados", - "batchDeleteSelected": "Eliminar {count} seleccionados", - "batchActivateSelected": "Habilitar {count} seleccionados", + "testAll": "Test All", + "errorTestFailed": "Failed to test proxies", + "batchSelectedCount": "{count} selected", + "batchDeleteSelected": "Delete {count} selected", + "batchActivateSelected": "Enable {count} selected", "testPassed": "✓ OK", - "close": "Cerrar", - "managePool": "Gestionar pool", - "poolTitle": "Pool de proxies y rotación", - "poolDescription": "Asocie varios proxies a un ámbito y rote las IP de salida entre ellos. Un ámbito con un solo proxy se comporta exactamente como una asignación simple.", - "poolScopeIdLabel": "ID de ámbito", - "poolScopeIdPlaceholder": "id de proveedor / id de conexión / id de combo", - "poolScopeIdRequired": "Se requiere un ID de ámbito para el ámbito de proveedor, cuenta o combo.", - "poolLoad": "Cargar pool", - "poolLoadFailed": "Error al cargar el pool de proxies", - "poolStrategyLabel": "Estrategia de rotación", - "poolStrategyHint": "round-robin alterna los miembros en orden; random selecciona de forma uniforme; sticky mantiene un miembro durante un período; latency-optimized selecciona el más rápido según los registros.", - "poolStrategyFailed": "Error al actualizar la estrategia de rotación", + "close": "Close", + "managePool": "Manage Pool", + "poolTitle": "Proxy Pool & Rotation", + "poolDescription": "Attach multiple proxies to a scope and rotate egress IPs across them. A scope with a single proxy behaves exactly like a plain assignment.", + "poolScopeIdLabel": "Scope ID", + "poolScopeIdPlaceholder": "provider id / connection id / combo id", + "poolScopeIdRequired": "A scope ID is required for provider, account, or combo scope.", + "poolLoad": "Load Pool", + "poolLoadFailed": "Failed to load the proxy pool", + "poolStrategyLabel": "Rotation strategy", + "poolStrategyHint": "round-robin cycles members in order; random picks uniformly; sticky holds one member for a window; latency-optimized picks the fastest based on logs.", + "poolStrategyFailed": "Failed to update the rotation strategy", "strategyRoundRobin": "Round-robin", - "strategyRandom": "Aleatorio", + "strategyRandom": "Random", "strategySticky": "Sticky", - "strategyLatency": "Optimizado por latencia", - "poolMembersLabel": "Miembros del pool ({count})", - "poolNoMembers": "Aún no hay proxies en este pool.", - "poolRemove": "Quitar", - "poolRemoveFailed": "Error al quitar el proxy del pool", - "poolAddLabel": "Agregar un proxy", - "poolAddMember": "Agregar", - "poolAddFailed": "Error al agregar el proxy al pool", - "poolSelectProxy": "Seleccionar un proxy…", - "poolSaveFailed": "Error al guardar la asignación del pool" + "strategyLatency": "Latency-optimized", + "poolMembersLabel": "Pool members ({count})", + "poolNoMembers": "No proxies in this pool yet.", + "poolRemove": "Remove", + "poolRemoveFailed": "Failed to remove the proxy from the pool", + "poolAddLabel": "Add a proxy", + "poolAddMember": "Add", + "poolAddFailed": "Failed to add the proxy to the pool", + "poolSelectProxy": "Select a proxy…", + "poolSaveFailed": "Failed to save pool assignment" }, "playground": { "title": "Title", @@ -9872,17 +9892,17 @@ "endpointOptions": { "chat": "Chat", "responses": "Responses", - "completions": "Completados", + "completions": "Completions", "images": "Images", "embeddings": "Embeddings", "speech": "Speech", "transcription": "Transcription", "video": "Video", "music": "Music", - "moderations": "Moderaciones", + "moderations": "Moderations", "rerank": "Rerank", "search": "Search", - "webFetch": "Extracción web" + "webFetch": "Web fetch" }, "conversationalChat": "Chat conversacional", "clearChat": "Borrar chat", @@ -9904,10 +9924,10 @@ "topP": "Top-p", "presencePenalty": "Presence penalty", "frequencyPenalty": "Frequency penalty", - "reasoningLabel": "Razonamiento", - "thinking": "Pensamiento", - "effort": "Esfuerzo", - "effortDefault": "Predeterminado", + "reasoningLabel": "Reasoning", + "thinking": "Thinking", + "effort": "Effort", + "effortDefault": "Default", "seedPlaceholder": "Random (leave empty)", "presetsLabel": "Presets", "loadPreset": "Load preset", @@ -9921,25 +9941,25 @@ "improvingPrompt": "Improving…", "improvePromptTitle": "Improve your prompt with AI", "setModelFirst": "Set a model first", - "setModelInConfigFirst": "Configura un modelo en el panel de configuración primero.", - "improvePromptFailed": "Error al mejorar el prompt.", - "improvePromptAria": "Mejorar prompt con IA", - "confirmImprovePrompt": "Confirmar mejora del prompt", - "improvePromptDescription": "Esto enviará tu prompt del sistema actual a para generar una versión mejorada.", + "setModelInConfigFirst": "Set a model in the Config pane first.", + "improvePromptFailed": "Improve prompt failed.", + "improvePromptAria": "Improve prompt using AI", + "confirmImprovePrompt": "Confirm improve prompt", + "improvePromptDescription": "This will send your current system prompt to to generate an improved version.", "improveQuotaWarning": "This will consume quota from the model configured in Config.", "improveConfirm": "Improve", "exportCode": "Export code", "exportCodeTitle": "Export Code", - "exportShort": "Exportar", + "exportShort": "Export", "noStateToExport": "No playground state available to export.", - "closeExportModal": "Cerrar modal de exportación", - "close": "Cerrar", - "exportRealKeyWarning": "Advertencia de seguridad: exportación bloqueada — se detectó una clave de API real en la salida. Restablece tu clave de API e inténtalo de nuevo.", - "placeholderHintPrefix": "Reemplazar", - "placeholderHintSuffix": "con tu clave de API real, o establécela como una variable de entorno.", - "copyLangCode": "Copiar código {language}", - "loadingPresets": "Cargando…", - "loadPresetPlaceholder": "Cargar ajuste preestablecido…", + "closeExportModal": "Close export modal", + "close": "Close", + "exportRealKeyWarning": "Security warning: export blocked — a real API key was detected in the output. Please reset your API key and try again.", + "placeholderHintPrefix": "Replace", + "placeholderHintSuffix": "with your actual API key, or set it as an environment variable.", + "copyLangCode": "Copy {language} code", + "loadingPresets": "Loading…", + "loadPresetPlaceholder": "Load preset…", "copyCode": "Copy", "copiedCode": "Copied!", "addModel": "+ Add model", @@ -9947,174 +9967,174 @@ "cancelAll": "Cancel all", "maxColumnsReached": "Maximum {max} columns", "modelPlaceholderCompare": "Model (Cmd+K)…", - "noModel": "Sin modelo", - "statusLabel": "Estado: {status}", + "noModel": "No model", + "statusLabel": "Status: {status}", "status": { - "idle": "inactivo", - "streaming": "transmitiendo", - "done": "completado", + "idle": "idle", + "streaming": "streaming", + "done": "done", "error": "error" }, - "cancelStream": "Cancelar transmisión", - "removeColumn": "Eliminar columna", - "removeModelColumn": "Eliminar columna para {model}", - "readyToRun": "Listo para ejecutar.", + "cancelStream": "Cancel stream", + "removeColumn": "Remove column", + "removeModelColumn": "Remove column for {model}", + "readyToRun": "Ready to run.", "errorLabel": "Error", - "unknownError": "Ocurrió un error desconocido.", - "waitingForResponse": "Esperando respuesta…", + "unknownError": "Unknown error occurred.", + "waitingForResponse": "Waiting for response…", "ttft": "TTFT", "tps": "TPS", "metricsDisclaimer": "client-side estimate", "tokensLabel": "Tokens", "costLabel": "Cost", "costEstimated": "(estimated)", - "ttftTitle": "Tiempo hasta el primer token (estimación del cliente)", - "tpsTitle": "Tokens por segundo (estimación del cliente)", - "tokenCountsTitle": "Tokens de prompt ↑ / Tokens de completado ↓", - "estimatedCostTitle": "Costo estimado (precisión no garantizada)", + "ttftTitle": "Time to first token (client-side estimate)", + "tpsTitle": "Tokens per second (client-side estimate)", + "tokenCountsTitle": "Prompt tokens ↑ / Completion tokens ↓", + "estimatedCostTitle": "Estimated cost (not guaranteed accurate)", "toolsLabel": "Tools", - "toolsCount": "Herramientas ({count})", + "toolsCount": "Tools ({count})", "addTool": "Add tool", - "editTool": "Editar herramienta {name}", - "removeTool": "Eliminar herramienta {name}", + "editTool": "Edit tool {name}", + "removeTool": "Remove tool {name}", "toolNamePlaceholder": "Function name", - "toolNameRequiredPlaceholder": "Nombre de la función *", + "toolNameRequiredPlaceholder": "Function name *", "toolDescPlaceholder": "Description (optional)", - "toolParamsLabel": "Parámetros (esquema JSON)", - "toolParamsJsonSchema": "Esquema JSON para parámetros", + "toolParamsLabel": "Parameters (JSON schema)", + "toolParamsJsonSchema": "JSON schema for parameters", "toolParamsInvalid": "Parameters must be valid JSON", "structuredOutputLabel": "Structured Output", "enableJsonMode": "Enable JSON mode", "disableJsonMode": "Disable JSON mode", "invalidJson": "Invalid JSON", - "jsonMode": "Modo JSON", - "jsonModeDescription": "Fuerza response_format: json_schema", - "schemaName": "Nombre del esquema", - "jsonSchema": "Esquema JSON", - "jsonSchemaEditor": "Editor de esquema JSON", - "schemaValidated": "Esquema validado", - "validateSchema": "Validar esquema", - "seed": "Semilla", - "stopSequences": "Secuencias de parada", - "stopSequencesPlaceholder": "p. ej., \"\\n\\n\" o \"END\"", - "autoProvider": "Automático", + "jsonMode": "JSON mode", + "jsonModeDescription": "Forces response_format: json_schema", + "schemaName": "Schema name", + "jsonSchema": "JSON schema", + "jsonSchemaEditor": "JSON schema editor", + "schemaValidated": "Schema validated", + "validateSchema": "Validate schema", + "seed": "Seed", + "stopSequences": "Stop sequences", + "stopSequencesPlaceholder": "e.g. \"\\n\\n\" or \"END\"", + "autoProvider": "Auto", "httpError": "Error {status}", - "requestCancelled": "Solicitud cancelada", - "networkError": "Error de red", - "regenerateLastResponse": "Regenerar última respuesta", - "regenerate": "Regenerar", - "startConversation": "Inicia una conversación — escribe un mensaje a continuación", + "requestCancelled": "Request cancelled", + "networkError": "Network error", + "regenerateLastResponse": "Regenerate last response", + "regenerate": "Regenerate", + "startConversation": "Start a conversation — type a message below", "role": { - "system": "sistema", - "user": "usuario", - "assistant": "asistente" + "system": "system", + "user": "user", + "assistant": "assistant" }, - "generating": "Generando…", - "typeMessageWithShortcut": "Escribe un mensaje... (Intro para enviar, Mayús+Intro para salto de línea)", - "stop": "Detener", - "noResponseBody": "Sin cuerpo de respuesta", - "comparePromptPlaceholder": "Introduce tu prompt aquí…", - "userPrompt": "Prompt de usuario", - "cancelAllStreams": "Cancelar todas las transmisiones", - "runAllColumns": "Ejecutar todas las columnas", - "newColumnModelName": "Nombre del modelo para la nueva columna", - "addColumn": "Añadir columna", - "addModelColumn": "Añadir columna de modelo", - "columnCount": "{count}/{max} columnas", - "addModelToCompare": "Añadir una columna de modelo para comparar", - "modelsSimultaneously": "Hasta {max} modelos simultáneamente", + "generating": "Generating…", + "typeMessageWithShortcut": "Type a message... (Enter to send, Shift+Enter for newline)", + "stop": "Stop", + "noResponseBody": "No response body", + "comparePromptPlaceholder": "Enter your prompt here…", + "userPrompt": "User prompt", + "cancelAllStreams": "Cancel all streams", + "runAllColumns": "Run all columns", + "newColumnModelName": "Model name for new column", + "addColumn": "Add column", + "addModelColumn": "Add model column", + "columnCount": "{count}/{max} columns", + "addModelToCompare": "Add a model column to compare", + "modelsSimultaneously": "Up to {max} models simultaneously", "running": "Running…", "runLabel": "Run", "enterToolResult": "Enter tool result…", "build": { - "step1Label": "¿Qué probar?", - "step2Label": "Configurar", - "step3Label": "Ejecutar", - "step1Title": "¿Qué quieres probar?", - "step1Subtitle": "Elige la capacidad que quieres explorar en esta sesión.", - "step2Title": "Configurar", - "step2Subtitle": "Configura las herramientas o el esquema JSON que se utilizarán en la solicitud.", - "step3Title": "Ejecutar", - "modeToolsTitle": "Herramientas", - "modeToolsDesc": "Probar llamadas a funciones — define herramientas y observa cómo las invoca el modelo.", + "step1Label": "What to test?", + "step2Label": "Configure", + "step3Label": "Run", + "step1Title": "What do you want to test?", + "step1Subtitle": "Choose the capability you want to explore in this session.", + "step2Title": "Configure", + "step2Subtitle": "Set up the tools or JSON schema that will be used in the request.", + "step3Title": "Run", + "modeToolsTitle": "Tools", + "modeToolsDesc": "Test function calling — define tools and see how the model invokes them.", "modeJsonTitle": "JSON", - "modeJsonDesc": "Probar salida estructurada — restringe la respuesta a un esquema JSON.", - "modeBothTitle": "Herramientas + JSON", - "modeBothDesc": "Combina llamadas a funciones y salida estructurada en una sola solicitud.", - "backButton": "Atrás", - "nextButton": "Siguiente", - "runButton": "Ejecutar", - "promptPlaceholder": "Escribe tu mensaje… (Enter para enviar, Shift+Enter para nueva línea)" + "modeJsonDesc": "Test structured output — constrain the response to a JSON schema.", + "modeBothTitle": "Tools + JSON", + "modeBothDesc": "Combine function calling and structured output in a single request.", + "backButton": "Back", + "nextButton": "Next", + "runButton": "Run", + "promptPlaceholder": "Enter your message… (Enter to send, Shift+Enter for newline)" } }, "miniPlayground": { - "endpoint": "Endpoint", + "endpoint": "Punto de conexión", "apiKey": "Clave API", "model": "Modelo", "voice": "Voz", "speed": "Velocidad", - "input": "Entrada", + "input": "Input", "url": "URL", - "format": "Formato", - "depth": "Profundidad", - "copyCurl": "Copiar cURL", - "copied": "¡Copiado!", - "run": "Ejecutar", - "running": "Ejecutando...", - "response": "Respuesta", - "tunnel": "Túnel", - "send": "Enviar", - "selectKey": "Seleccionar clave", - "testLabel": "Probar", - "expandTest": "Expandir prueba", - "collapseTest": "Contraer prueba", - "revealKey": "Mostrar clave", - "hideKey": "Ocultar clave", - "download": "Descargar", - "play": "Reproducir", - "query": "Consulta", - "numResults": "Máximo de resultados", + "format": "Format", + "depth": "Depth", + "copyCurl": "Copy cURL", + "copied": "Copied!", + "run": "Run", + "running": "Running...", + "response": "Response", + "tunnel": "Tunnel", + "send": "Send", + "selectKey": "Select key", + "testLabel": "Test", + "expandTest": "Expand test", + "collapseTest": "Collapse test", + "revealKey": "Reveal key", + "hideKey": "Hide key", + "download": "Download", + "play": "Play", + "query": "Query", + "numResults": "Max results", "prompt": "Prompt", - "size": "Tamaño", - "duration": "Duración", - "question": "Pregunta", - "audioFile": "Archivo de audio", - "fileTooLarge25Mb": "El archivo es demasiado grande. Tamaño máximo: 25 MB.", - "selectAudioFirst": "Selecciona un archivo de audio primero.", - "speechToText": "Voz a texto", - "chooseFile": "Elegir archivo", - "audioFormats25Mb": "MP3, WAV, M4A, OGG o FLAC · Máximo 25 MB", - "musicSample": "Una pista ambiental tranquila con piano cálido y cuerdas suaves", - "noAudioUrl": "La respuesta no incluyó una URL de audio: {response}", - "music": "Música", - "embeddingSample": "OmniRoute enruta solicitudes de IA a través de múltiples proveedores.", + "size": "Size", + "duration": "Duration", + "question": "Question", + "audioFile": "Audio file", + "fileTooLarge25Mb": "The file is too large. Maximum size: 25 MB.", + "selectAudioFirst": "Select an audio file first.", + "speechToText": "Speech to Text", + "chooseFile": "Choose file", + "audioFormats25Mb": "MP3, WAV, M4A, OGG or FLAC · Maximum 25 MB", + "musicSample": "A calm ambient track with warm piano and soft strings", + "noAudioUrl": "The response did not include an audio URL: {response}", + "music": "Music", + "embeddingSample": "OmniRoute routes AI requests across multiple providers.", "embedding": "Embedding", - "imageSample": "Una ciudad futurista al atardecer, iluminación cinematográfica", - "image": "Imagen", - "ttsSample": "Hola desde OmniRoute. Esta es una prueba de texto a voz.", - "textToSpeech": "Texto a voz", - "videoSample": "Un avión de papel volando sobre una ciudad futurista", + "imageSample": "A futuristic city at sunset, cinematic lighting", + "image": "Image", + "ttsSample": "Hello from OmniRoute. This is a text-to-speech test.", + "textToSpeech": "Text to Speech", + "videoSample": "A paper airplane flying over a futuristic city", "video": "Video", "webFetch": "Web Fetch", - "webSearchSample": "¿Qué es OmniRoute?", - "webSearch": "Búsqueda web", - "documentUrl": "URL del documento", - "browserAudioUnsupported": "Tu navegador no admite audio.", - "browserVideoUnsupported": "Tu navegador no admite video.", - "searchResultFallback": "Resultado {number}", - "noKeysFound": "No se encontraron claves API. Agrega una en la sección Claves.", - "exampleLabel": "Ejemplo", + "webSearchSample": "What is OmniRoute?", + "webSearch": "Web Search", + "documentUrl": "Document URL", + "browserAudioUnsupported": "Your browser does not support audio.", + "browserVideoUnsupported": "Your browser does not support video.", + "searchResultFallback": "Result {number}", + "noKeysFound": "No API keys found. Add one in the Keys section.", + "exampleLabel": "Example", "latency": "{ms}ms", - "statsLine": "{ms}ms · {tokensIn} tokens de entrada / {tokensOut} de salida", - "defaultKey": "(predeterminado)", - "clear": "Limpiar", - "emptyConversation": "Envía un mensaje para iniciar la conversación", - "sendHint": "Shift+Enter para nueva línea · Enter para enviar", - "you": "Tú", - "assistant": "Asistente", + "statsLine": "{ms}ms · {tokensIn} in / {tokensOut} out tokens", + "defaultKey": "(default)", + "clear": "Clear", + "emptyConversation": "Send a message to start the conversation", + "sendHint": "Shift+Enter for newline · Enter to send", + "you": "You", + "assistant": "Assistant", "errorLabel": "Error", - "requestFailed": "La solicitud falló", - "stop": "Detener" + "requestFailed": "Request failed", + "stop": "Stop" }, "requestLogger": { "recording": "Recording", @@ -10182,8 +10202,8 @@ "noLogs": "No logs yet. Make some API calls to see them here.", "noMatchingLogs": "No logs matching current filters.", "callLogsInfo": "Call logs are also saved as JSON files to {dataDir} and rotated based on {retentionDays} and {maxEntries}.", - "loadMore": "Cargar más", - "loadingMore": "Cargando más..." + "loadMore": "Load More", + "loadingMore": "Loading more..." }, "proxyLogger": { "filterAll": "All", @@ -10221,7 +10241,7 @@ "noProxyLogs": "No proxy logs yet. Configure proxies and make API calls to see them here.", "noMatchingLogs": "No logs match the current filters.", "tlsFingerprint": "Chrome 124 TLS Fingerprint", - "colPublicIp": "IP pública" + "colPublicIp": "Public IP" }, "endpointOptions": { "speech": "Speech", @@ -10309,7 +10329,7 @@ "moreSuffix": "+{count} more" }, "quotaShare": { - "weightPercent": "Peso %", + "weightPercent": "Weight %", "title": "Quota Sharing", "description": "Share provider quotas across API keys with % limits", "newPool": "New pool", @@ -10332,9 +10352,9 @@ "capLabel": "cap {value}", "notTrackedYet": "(not tracked yet)", "policy": "Policy", - "apiKeyColumn": "Clave API", - "weightColumn": "Peso", - "fairShareShort": "equitativo", + "apiKeyColumn": "API Key", + "weightColumn": "Weight", + "fairShareShort": "fair", "policyHard": "hard", "policySoft": "soft", "policyBurst": "burst", @@ -10366,85 +10386,85 @@ "policyLabel": "Política:", "resetIn": "restablecer en", "quotaTotal": "total", - "kpiAvgUtilization": "Utilización promedio", - "kpiBorrowingNow": "Tomando prestado ahora", - "conceptTitle": "Cómo funciona Quota Share", - "conceptIntro": "Quota Share divide la cuota de un proveedor entre múltiples claves API mediante un reparto equitativo que conserva el trabajo: cada clave recibe una parte proporcional pero puede tomar prestado del saldo libre sin superar el límite global.", - "conceptFairShare": "Reparto equitativo: cada clave recibe una cuota proporcional a su peso configurado", - "conceptBorrowing": "Préstamo: las claves pueden consumir el saldo libre de otras sin superar el límite", - "conceptGlobalCap": "Límite global estricto: nunca se supera el límite absoluto del proveedor", - "conceptWindows": "Ventanas: 5h, por hora, diario, semanal, mensual — cada una rastreada de forma independiente", - "conceptKeyHowTitle": "Habilitar una clave para la cuota", - "conceptKeyHowDesc": "Cree la clave normalmente en Claves API — aparecerá automáticamente en el paso de claves del asistente. Marque Exclusivo allí para que sea solo de cuota. Sin paso de habilitación separado.", - "conceptExclusiveTitle": "Qué hace \"Exclusivo\"", - "conceptExclusiveDesc": "Una clave exclusiva solo ve/usa los modelos quotaShared-* del grupo — todos los demás modelos se ocultan de su /v1/models y se bloquean.", - "burnRateTitle": "Tasa de consumo", - "burnRateExhaustsIn": "Se agota en", - "dimensionResetIn": "Se restablece en", - "realConsumedColumn": "Consumido", - "deficitColumn": "Déficit", - "borrowingIndicator": "tomando prestado", - "migratedFromLocalStorageNotice": "Grupos migrados correctamente desde localStorage.", - "policyCapAbsoluteLabel": "Límite absoluto", - "policyCapAbsolutePlaceholder": "Límite numérico (opcional)", - "multiDimensionLabel": "Multidimensión", - "stackedBarTitle": "Particiones por clave API", - "usedSuffix": "usado {percent}%", - "wizardTitle": "Nuevo grupo de cuotas", - "editPoolTitle": "Editar grupo", - "saveChanges": "Guardar cambios", - "wizardStep1Label": "Cuenta", - "wizardStep2Label": "Límite", - "wizardStep3Label": "Claves", - "wizardStep1Title": "Elegir conexión del proveedor", - "wizardStep1Subtitle": "Seleccione la cuenta del proveedor para la cual este grupo compartirá la cuota, establezca un nombre y una política predeterminada.", - "wizardStep2Title": "Configurar dimensiones de cuota", - "wizardStep2Subtitle": "Defina las dimensiones del plan de cuota (unidad, ventana, límite) para la conexión elegida. Déjelo sin cambios para mantener la configuración actual.", - "wizardStep3Title": "Asignar claves API", - "wizardStep3Subtitle": "Asigne claves API a este pool con asignaciones de % de peso y límites opcionales.", - "wizardPoolNameLabel": "Nombre del pool", - "wizardPoolNamePlaceholder": "Mi pool de cuotas", - "wizardNext": "Siguiente", - "wizardBack": "Atrás", - "wizardCreatePool": "Crear pool", - "wizardDimensionsEditedNotice": "Dimensiones editadas — se guardarán como una anulación manual cuando se cree el pool.", - "wizardExclusiveLabel": "Cuota exclusiva", - "wizardExclusiveHint": "Cuando está habilitado, estas claves API solo podrán usar los modelos virtuales de este pool (la conciliación de allowedQuotas se aplica al guardar).", - "wizardPreviewLabel": "Vista previa de nombres de modelos virtuales", - "wizardConnectionsLabel": "Conexiones de proveedores", - "wizardPrimaryBadge": "principal", - "wizardAdditionalConnectionsNote": "Las conexiones adicionales usan los límites predeterminados de su catálogo (editable más adelante).", - "wizardSingleProviderNote": "Un pool utiliza un solo proveedor", - "wizardPreviewMoreModels": "+{count} más", - "accountQuotaTitle": "Cuota de la cuenta", + "kpiAvgUtilization": "Avg utilization", + "kpiBorrowingNow": "Borrowing now", + "conceptTitle": "How Quota Share works", + "conceptIntro": "Quota Share divides a provider's quota among multiple API keys using work-conserving fair-share: each key receives a proportional slice but can borrow from the free balance without exceeding the global cap.", + "conceptFairShare": "Fair-share: each key receives quota proportional to its configured weight", + "conceptBorrowing": "Borrowing: keys can consume free balance from others without breaching the cap", + "conceptGlobalCap": "Hard global cap: the provider's absolute limit is never exceeded", + "conceptWindows": "Windows: 5h, hourly, daily, weekly, monthly — each tracked independently", + "conceptKeyHowTitle": "Enabling a key for quota", + "conceptKeyHowDesc": "Create the key normally in API Keys — it appears in the wizard's key step automatically. Tick Exclusive there to make it quota-only. No separate enable step.", + "conceptExclusiveTitle": "What \"Exclusive\" does", + "conceptExclusiveDesc": "An exclusive key only sees/uses the pool's quotaShared-* models — every other model is hidden from its /v1/models and blocked.", + "burnRateTitle": "Burn rate", + "burnRateExhaustsIn": "Exhausts in", + "dimensionResetIn": "Resets in", + "realConsumedColumn": "Consumed", + "deficitColumn": "Deficit", + "borrowingIndicator": "borrowing", + "migratedFromLocalStorageNotice": "Pools successfully migrated from localStorage.", + "policyCapAbsoluteLabel": "Absolute cap", + "policyCapAbsolutePlaceholder": "Numeric limit (optional)", + "multiDimensionLabel": "Multi-dimension", + "stackedBarTitle": "Slices by API key", + "usedSuffix": "used {percent}%", + "wizardTitle": "New quota pool", + "editPoolTitle": "Edit pool", + "saveChanges": "Save changes", + "wizardStep1Label": "Account", + "wizardStep2Label": "Limit", + "wizardStep3Label": "Keys", + "wizardStep1Title": "Choose provider connection", + "wizardStep1Subtitle": "Select the provider account this pool will share quota for, set a name and default policy.", + "wizardStep2Title": "Configure quota dimensions", + "wizardStep2Subtitle": "Define the quota plan dimensions (unit, window, limit) for the chosen connection. Leave unchanged to keep current settings.", + "wizardStep3Title": "Allocate API keys", + "wizardStep3Subtitle": "Assign API keys to this pool with weight % allocations and optional caps.", + "wizardPoolNameLabel": "Pool name", + "wizardPoolNamePlaceholder": "My quota pool", + "wizardNext": "Next", + "wizardBack": "Back", + "wizardCreatePool": "Create pool", + "wizardDimensionsEditedNotice": "Dimensions edited — will be saved as a manual override when the pool is created.", + "wizardExclusiveLabel": "Exclusive quota", + "wizardExclusiveHint": "When enabled, these API keys will only be allowed to use this pool's virtual models (allowedQuotas reconciliation is applied on save).", + "wizardPreviewLabel": "Virtual model names preview", + "wizardConnectionsLabel": "Provider connections", + "wizardPrimaryBadge": "primary", + "wizardAdditionalConnectionsNote": "Additional connections use their catalog default limits (editable later).", + "wizardSingleProviderNote": "A pool uses a single provider", + "wizardPreviewMoreModels": "+{count} more", + "accountQuotaTitle": "Account quota", "accountQuotaNone": "—", - "logTitle": "Registro de uso", - "logEmpty": "Aún no hay uso", - "groupLabel": "Grupo", - "newGroup": "Nuevo grupo", - "renameGroup": "Renombrar grupo", - "groupSelectHint": "Filtrar pools por grupo", - "groupAllocationNote": "Las asignaciones se aplican a todos los pools de este grupo a través de la capa de cuota compartida.", - "groupNamePrompt": "Escriba el nombre del grupo", - "wizardGroupLabel": "Grupo", - "allGroups": "Todos los grupos", - "endpointsTitle": "Endpoints disponibles", - "endpointsHint": "Llame a estos modelos virtuales con cualquier clave asignada — el enrutamiento + la cuota se gestionan por grupo.", - "previewForKey": "Vista previa para la clave", - "previewKeyNone": "(todos los endpoints)", - "endpointsBaseUrl": "URL base", - "endpointsCollapse": "Contraer", - "endpointsExpand": "Expandir", - "endpointsAnthropicNote": "Anthropic nativo", - "endpointsResponsesNote": "Respuestas de OpenAI — codex/github", - "endpointsWsNote": "WebSocket — solo codex", - "betaText": "Quota Share es funcional pero se esperan errores. ¿Encontró alguno? Por favor, repórtelo.", - "betaReportLink": "Reportar un problema", - "deleteGroup": "Eliminar grupo", - "deleteGroupConfirm": "¿Eliminar este grupo? Sus pools deben ser reasignados o eliminados primero.", - "deleteGroupHasPools": "Este grupo todavía tiene pools — reasígnelos o elimínelos primero.", - "ungroupedTitle": "Sin agrupar", - "ungroupedHint": "Estos pools no están asignados a un grupo conocido. Edite un pool para moverlo a un grupo real." + "logTitle": "Usage log", + "logEmpty": "No usage yet", + "groupLabel": "Group", + "newGroup": "New group", + "renameGroup": "Rename group", + "groupSelectHint": "Filter pools by group", + "groupAllocationNote": "Allocations apply to all pools in this group via the shared quota layer.", + "groupNamePrompt": "Enter group name", + "wizardGroupLabel": "Group", + "allGroups": "All groups", + "endpointsTitle": "Available endpoints", + "endpointsHint": "Call these virtual models with any allocated key — routing + quota are handled per group.", + "previewForKey": "Preview for key", + "previewKeyNone": "(all endpoints)", + "endpointsBaseUrl": "Base URL", + "endpointsCollapse": "Collapse", + "endpointsExpand": "Expand", + "endpointsAnthropicNote": "Anthropic-native", + "endpointsResponsesNote": "OpenAI Responses — codex/github", + "endpointsWsNote": "WebSocket — codex only", + "betaText": "Quota Share is functional but bugs are expected. Found one? Please report it.", + "betaReportLink": "Report an issue", + "deleteGroup": "Delete group", + "deleteGroupConfirm": "Delete this group? Its pools must be reassigned or removed first.", + "deleteGroupHasPools": "This group still has pools — reassign or delete them first.", + "ungroupedTitle": "Ungrouped", + "ungroupedHint": "These pools are not assigned to a known group. Edit a pool to move it into a real group." }, "plugins": { "title": "Plugins", @@ -10480,1282 +10500,1282 @@ "status": "Status", "enabled": "Enabled", "disabled": "Disabled", - "installedTab": "Instalado", + "installedTab": "Installed", "marketplaceTab": "Marketplace", - "marketplaceUrlLabel": "URL personalizada del Marketplace", - "marketplaceUrlPlaceholder": "Dejar vacío para el registro oficial de Omniroute", - "saveMarketplaceUrl": "Guardar y recargar", - "marketplaceUrlSaved": "URL del Marketplace actualizada", - "marketplaceEmpty": "No se encontraron plugins en el marketplace.", - "marketplaceInstallComingSoon": "Las instalaciones desde el Marketplace estarán disponibles pronto.", - "verified": "Verificado", - "install": "Instalar", - "installedFromMarketplace": "¡Plugin {name} instalado!", + "marketplaceUrlLabel": "Custom Marketplace URL", + "marketplaceUrlPlaceholder": "Leave empty for official Omniroute registry", + "saveMarketplaceUrl": "Save & Reload", + "marketplaceUrlSaved": "Marketplace URL updated", + "marketplaceEmpty": "No plugins found in marketplace.", + "marketplaceInstallComingSoon": "Marketplace installs are coming soon.", + "verified": "Verified", + "install": "Install", + "installedFromMarketplace": "Plugin {name} installed!", "hooks": "Hooks" }, "quotaPlans": { - "title": "Planes y cuotas", - "description": "Configure planes de cuotas por proveedor — dimensiones (%, solicitudes, tokens, $) y ventanas de tiempo", - "providerLabel": "Proveedor / Conexión", - "detectedPlanLabel": "Plan detectado", - "manualPlanLabel": "Anulación manual", - "unconfiguredLabel": "No configurado — manual requerido", - "dimensionLabel": "Dimensiones", - "addDimension": "Añadir dimensión", - "removeDimension": "Quitar", - "limitLabel": "Límite", + "title": "Plans & Quotas", + "description": "Configure quota plans per provider — dimensions (%, requests, tokens, $) and time windows", + "providerLabel": "Provider / Connection", + "detectedPlanLabel": "Detected plan", + "manualPlanLabel": "Manual override", + "unconfiguredLabel": "Not configured — manual required", + "dimensionLabel": "Dimensions", + "addDimension": "Add dimension", + "removeDimension": "Remove", + "limitLabel": "Limit", "unitOptions": { "percent": "%", - "requests": "solicitudes", + "requests": "requests", "tokens": "tokens", "usd": "USD ($)" }, "windowOptions": { - "5h": "5 horas", - "hourly": "Por hora", - "daily": "Diario", - "weekly": "Semanal", - "monthly": "Mensual" + "5h": "5 hours", + "hourly": "Hourly", + "daily": "Daily", + "weekly": "Weekly", + "monthly": "Monthly" }, - "useCatalogButton": "Usar catálogo", - "saveOverrideButton": "Guardar anulación", - "revertToCatalogButton": "Revertir al catálogo", - "unknownProviderNotice": "Selecciona un proveedor a la izquierda para configurar su plan de cuota.", - "catalogTitle": "Catálogo conocido", - "catalogDescription": "Planes detectados automáticamente para los siguientes proveedores:" + "useCatalogButton": "Use catalog", + "saveOverrideButton": "Save override", + "revertToCatalogButton": "Revert to catalog", + "unknownProviderNotice": "Select a provider on the left to configure its quota plan.", + "catalogTitle": "Known catalog", + "catalogDescription": "Automatically detected plans for the following providers:" }, "activity": { - "title": "Actividad", - "description": "Feed de eventos recientes", - "emptyTitle": "Aún no hay actividad", - "emptyDescription": "Cuando agregues proveedores, crees combos o rotes claves, los eventos aparecerán aquí.", - "todayHeader": "Hoy", - "yesterdayHeader": "Ayer", - "filterAll": "Todos", - "filterProviders": "Proveedores", + "title": "Activity", + "description": "Recent events feed", + "emptyTitle": "No activity yet", + "emptyDescription": "When you add providers, create combos, or rotate keys, events will appear here.", + "todayHeader": "Today", + "yesterdayHeader": "Yesterday", + "filterAll": "All", + "filterProviders": "Providers", "filterCombos": "Combos", - "filterApiKeys": "Claves API", - "filterSettings": "Configuración", - "filterQuota": "Cuota", - "filterAuth": "Autenticación", - "filterSystem": "Sistema", - "filterAria": "Filtrar por tipo de evento", - "refresh": "Actualizar", - "refreshAria": "Actualizar feed de actividad", - "loading": "Cargando", - "loadingActivity": "Cargando actividad…", - "fetchFailed": "Error al obtener la actividad", + "filterApiKeys": "API Keys", + "filterSettings": "Settings", + "filterQuota": "Quota", + "filterAuth": "Auth", + "filterSystem": "System", + "filterAria": "Filter by event type", + "refresh": "Refresh", + "refreshAria": "Refresh activity feed", + "loading": "Loading", + "loadingActivity": "Loading activity…", + "fetchFailed": "Failed to fetch activity", "relative": { - "justNow": "ahora mismo", - "minutesAgo": "hace {n} min", - "hoursAgo": "hace {n} h", - "yesterday": "ayer", - "daysAgo": "hace {n} días" + "justNow": "just now", + "minutesAgo": "{n} min ago", + "hoursAgo": "{n} h ago", + "yesterday": "yesterday", + "daysAgo": "{n} days ago" }, "eventVerb": { - "providerAdded": "{actor} agregó el proveedor {target}", - "providerRemoved": "{actor} eliminó el proveedor {target}", - "providerTested": "{actor} probó el proveedor {target}", - "comboCreated": "{actor} creó el combo {target}", - "comboUpdated": "{actor} actualizó el combo {target}", - "comboDeleted": "{actor} eliminó el combo {target}", - "apiKeyCreated": "{actor} creó la clave API {target}", - "apiKeyRevoked": "{actor} revocó la clave API {target}", - "apiKeyRotated": "{actor} rotó la clave API {target}", - "budgetThreshold": "Límite de presupuesto alcanzado para {target}", - "settingUpdated": "{actor} actualizó la configuración {target}", - "authLogin": "{actor} inició sesión", - "authLogout": "{actor} cerró sesión", - "cloudAgentSession": "Sesión de agente en la nube iniciada para {target}", - "mcpToolRegistered": "Herramienta MCP {target} registrada", - "webhookCreated": "{actor} creó el webhook {target}", - "webhookDeleted": "{actor} eliminó el webhook {target}", - "quotaPoolCreated": "{actor} creó el grupo de cuotas {target}", - "quotaPoolUpdated": "{actor} actualizó el grupo de cuotas {target}", - "quotaPoolDeleted": "{actor} eliminó el grupo de cuotas {target}", - "quotaPlanUpdated": "{actor} actualizó el plan de cuotas {target}", - "quotaStoreDriverChanged": "Controlador de QuotaStore cambiado", - "updateApplied": "Actualización {target} aplicada", - "deployCompleted": "Despliegue completado", - "skillInstalled": "{actor} instaló la habilidad {target}", - "skillRemoved": "{actor} eliminó la habilidad {target}", - "providerCredentialsCreated": "{actor} creó credenciales para {target}", - "providerCredentialsApplied": "Credenciales para {target} aplicadas", - "providerCredentialsUpdated": "{actor} actualizó las credenciales para {target}", - "providerCredentialsRevoked": "{actor} revocó las credenciales para {target}", - "providerCredentialsBatchRevoked": "{actor} revocó credenciales en lote", - "providerCredentialsBatchUpdated": "{actor} actualizó credenciales en lote", - "providerCredentialsBulkCreated": "{actor} creó credenciales de forma masiva", - "providerCredentialsBulkImported": "{actor} importó credenciales de forma masiva", - "providerCredentialsImported": "{actor} importó credenciales", - "providerSsrfBlocked": "Intento de SSRF bloqueado para {target}", - "authLoginSuccess": "{actor} inició sesión", - "authLoginError": "Error de inicio de sesión para {actor}", - "authLoginFailed": "Inicio de sesión fallido para {actor}", - "authLoginLocked": "{actor} bloqueado después de demasiados intentos", - "authLoginMisconfigured": "Configuración de autenticación no válida", - "authLoginSetupRequired": "Se requiere configuración de autenticación", - "authLogoutSuccess": "{actor} cerró sesión", - "syncTokenCreated": "{actor} creó el token de sincronización", - "syncTokenRevoked": "{actor} revocó el token de sincronización", - "settingsUpdate": "{actor} actualizó la configuración", - "settingsUpdateFailed": "Error al actualizar la configuración", - "serviceRevealApiKey": "{actor} reveló la clave API para {target}", + "providerAdded": "{actor} added provider {target}", + "providerRemoved": "{actor} removed provider {target}", + "providerTested": "{actor} tested provider {target}", + "comboCreated": "{actor} created combo {target}", + "comboUpdated": "{actor} updated combo {target}", + "comboDeleted": "{actor} removed combo {target}", + "apiKeyCreated": "{actor} created API key {target}", + "apiKeyRevoked": "{actor} revoked API key {target}", + "apiKeyRotated": "{actor} rotated API key {target}", + "budgetThreshold": "Budget threshold reached for {target}", + "settingUpdated": "{actor} updated setting {target}", + "authLogin": "{actor} signed in", + "authLogout": "{actor} signed out", + "cloudAgentSession": "Cloud agent session started for {target}", + "mcpToolRegistered": "MCP tool {target} registered", + "webhookCreated": "{actor} created webhook {target}", + "webhookDeleted": "{actor} removed webhook {target}", + "quotaPoolCreated": "{actor} created quota pool {target}", + "quotaPoolUpdated": "{actor} updated quota pool {target}", + "quotaPoolDeleted": "{actor} removed quota pool {target}", + "quotaPlanUpdated": "{actor} updated quota plan {target}", + "quotaStoreDriverChanged": "QuotaStore driver changed", + "updateApplied": "Update {target} applied", + "deployCompleted": "Deploy completed", + "skillInstalled": "{actor} installed skill {target}", + "skillRemoved": "{actor} removed skill {target}", + "providerCredentialsCreated": "{actor} created credentials for {target}", + "providerCredentialsApplied": "Credentials for {target} applied", + "providerCredentialsUpdated": "{actor} updated credentials for {target}", + "providerCredentialsRevoked": "{actor} revoked credentials for {target}", + "providerCredentialsBatchRevoked": "{actor} batch-revoked credentials", + "providerCredentialsBatchUpdated": "{actor} batch-updated credentials", + "providerCredentialsBulkCreated": "{actor} bulk-created credentials", + "providerCredentialsBulkImported": "{actor} bulk-imported credentials", + "providerCredentialsImported": "{actor} imported credentials", + "providerSsrfBlocked": "SSRF attempt blocked for {target}", + "authLoginSuccess": "{actor} signed in", + "authLoginError": "Login error for {actor}", + "authLoginFailed": "Login failed for {actor}", + "authLoginLocked": "{actor} locked out after too many attempts", + "authLoginMisconfigured": "Auth configuration invalid", + "authLoginSetupRequired": "Auth setup required", + "authLogoutSuccess": "{actor} signed out", + "syncTokenCreated": "{actor} created sync token", + "syncTokenRevoked": "{actor} revoked sync token", + "settingsUpdate": "{actor} updated settings", + "settingsUpdateFailed": "Settings update failed", + "serviceRevealApiKey": "{actor} revealed API key for {target}", "genericEvent": "{actor} {target}" } }, "agentBridge": { "title": "AgentBridge", - "subtitle": "Use agentes de IDE con modelos OmniRoute — no se requiere configuración", - "riskBannerTitle": "Úselo bajo su propio riesgo", - "riskBannerBody": "AgentBridge intercepta el tráfico HTTPS de los agentes de IDE. Al activarlo, acepta la responsabilidad del cumplimiento de los términos de servicio de cada agente. Nunca lo use en dispositivos o redes donde la inspección TLS esté prohibida.", - "riskBannerDismiss": "Descartar", - "serverCardTitle": "Servidor AgentBridge", - "statusRunning": "En ejecución", - "statusStopped": "Detenido", - "statusActive": "Activo", - "statusDnsOff": "DNS desactivado", - "statusSetupRequired": "Configuración requerida", - "statusInvestigating": "Investigando", - "serverPort": "Puerto", - "serverConns": "Conexiones", - "serverIntercepted": "Interceptado", - "serverLastStarted": "Último inicio", - "startServer": "Iniciar", - "stopServer": "Detener", - "restartServer": "Reiniciar", - "trustCert": "Confiar en certificado", - "downloadCert": "Descargar certificado", - "certManualTitle": "El certificado no se pudo instalar automáticamente (p. ej., dentro de un contenedor). El puente aún puede ejecutarse — confíe en la CA manualmente:", - "regenerateCert": "Regenerar certificado", - "starting": "Iniciando…", - "stopping": "Deteniendo…", - "restarting": "Reiniciando…", - "trusting": "Confiando…", - "regenerating": "Regenerando…", - "upstreamCaLabel": "Certificado CA ascendente (corporativo)", + "subtitle": "Use IDE agents with OmniRoute models — no config required", + "riskBannerTitle": "Use at your own risk", + "riskBannerBody": "AgentBridge intercepts HTTPS traffic from IDE agents. By activating it you accept responsibility for compliance with the terms of service of each agent. Never use on devices or networks where TLS inspection is prohibited.", + "riskBannerDismiss": "Dismiss", + "serverCardTitle": "AgentBridge Server", + "statusRunning": "Running", + "statusStopped": "Stopped", + "statusActive": "Active", + "statusDnsOff": "DNS off", + "statusSetupRequired": "Setup required", + "statusInvestigating": "Investigating", + "serverPort": "Port", + "serverConns": "Connections", + "serverIntercepted": "Intercepted", + "serverLastStarted": "Last started", + "startServer": "Start", + "stopServer": "Stop", + "restartServer": "Restart", + "trustCert": "Trust Cert", + "downloadCert": "Download Cert", + "certManualTitle": "Certificate couldn't be installed automatically (e.g. inside a container). The bridge can still run — trust the CA manually:", + "regenerateCert": "Regenerate Cert", + "starting": "Starting…", + "stopping": "Stopping…", + "restarting": "Restarting…", + "trusting": "Trusting…", + "regenerating": "Regenerating…", + "upstreamCaLabel": "Upstream CA Certificate (corporate)", "upstreamCaPlaceholder": "/etc/ssl/certs/corp-ca.pem", - "upstreamCaTest": "Probar TLS", - "upstreamCaTestOk": "Prueba de TLS superada", - "upstreamCaTestError": "Prueba de TLS fallida — compruebe la ruta y el archivo CA", - "bypassSectionTitle": "Lista de omisión", - "bypassSectionDesc": "Los hosts que coinciden con estos patrones se canalizan directamente (sin descifrado TLS). Los valores predeterminados incluyen banks.gov y SSO corporativo.", - "bypassDefaultsLabel": "Patrones de omisión predeterminados (solo lectura)", - "bypassUserLabel": "Patrones de omisión personalizados (uno por línea, glob o regex)", - "saveBypassList": "Guardar lista de omisión", - "agentListTitle": "Agentes de IDE", - "filterAll": "Todos", - "filterActive": "Activos", - "filterSetupRequired": "Configuración requerida", - "filterInvestigating": "Investigando", - "searchAgents": "Buscar agentes…", - "noAgentsMatch": "Ningún agente coincide con el filtro actual", - "agentHosts": "Hosts interceptados", - "certTrusted": "Certificado de confianza", - "certNotTrusted": "Certificado no confiable", - "investigatingNotice": "Este agente está bajo investigación. Los hosts y la superficie de la API aún se están confirmando. La configuración estará disponible una vez que la API upstream esté documentada.", - "modelMappingsLabel": "Mapeos de modelos", - "sourceModel": "Modelo de origen (nativo del agente)", - "targetModel": "Modelo de destino (OmniRoute)", - "noMappings": "No hay mapeos de modelos configurados. Ejecute el asistente de configuración para detectar modelos automáticamente.", - "selectModel": "Seleccionar…", - "saveMappings": "Guardar mapeos", - "setupWizard": "Asistente de configuración", - "startDns": "Iniciar DNS", - "stopDns": "Detener DNS", - "toggling": "Alternando…", - "viewTraffic": "Ver tráfico", - "emptyNoProvidersTitle": "Aún no hay proveedores configurados", - "emptyNoProvidersBody": "Para usar AgentBridge, primero conecte al menos un proveedor. Será el destino al que se enrutarán las solicitudes del IDE.", - "emptyGoToProviders": "Ir a Proveedores", - "wizardTitle": "Asistente de configuración", - "wizardSubtitle": "Configuración en 3 pasos", - "wizardStep1Label": "Verificar", + "upstreamCaTest": "Test TLS", + "upstreamCaTestOk": "TLS test passed", + "upstreamCaTestError": "TLS test failed — check the path and CA file", + "bypassSectionTitle": "Bypass List", + "bypassSectionDesc": "Hosts matching these patterns are tunneled directly (no TLS decryption). Defaults include banks.gov, and corporate SSO.", + "bypassDefaultsLabel": "Default bypass patterns (read-only)", + "bypassUserLabel": "Custom bypass patterns (one per line, glob or regex)", + "saveBypassList": "Save bypass list", + "agentListTitle": "IDE Agents", + "filterAll": "All", + "filterActive": "Active", + "filterSetupRequired": "Setup required", + "filterInvestigating": "Investigating", + "searchAgents": "Search agents…", + "noAgentsMatch": "No agents match the current filter", + "agentHosts": "Intercepted hosts", + "certTrusted": "Certificate trusted", + "certNotTrusted": "Certificate not trusted", + "investigatingNotice": "This agent is under investigation. Hosts and API surface are still being confirmed. Setup will be available once the upstream API is documented.", + "modelMappingsLabel": "Model mappings", + "sourceModel": "Source model (agent native)", + "targetModel": "Target model (OmniRoute)", + "noMappings": "No model mappings configured. Run setup wizard to auto-detect models.", + "selectModel": "Select…", + "saveMappings": "Save mappings", + "setupWizard": "Setup wizard", + "startDns": "Start DNS", + "stopDns": "Stop DNS", + "toggling": "Toggling…", + "viewTraffic": "View traffic", + "emptyNoProvidersTitle": "No providers configured yet", + "emptyNoProvidersBody": "To use AgentBridge, first connect at least one provider. It will be the destination where IDE requests are routed.", + "emptyGoToProviders": "Go to Providers", + "wizardTitle": "Setup wizard", + "wizardSubtitle": "3-step setup", + "wizardStep1Label": "Verify", "wizardStep2Label": "DNS", - "wizardStep3Label": "Mapeos", - "wizardStep1Desc": "Confirme que el servidor esté en ejecución y que el certificado esté instalado.", - "wizardStep2Desc": "Las siguientes entradas se agregarán a /etc/hosts para redirigir el tráfico a través de AgentBridge:", - "wizardStep3Desc": "Ahora puede configurar los mapeos de modelos en la tarjeta del agente. Reinicie el IDE para aplicar los cambios.", - "wizardStep3Success": "¡El agente está configurado!", - "wizardServerCheck": "Servidor AgentBridge", - "wizardRunning": "en ejecución", - "wizardNotRunning": "no en ejecución", - "wizardCertCheck": "Certificado", - "wizardTrusted": "de confianza", - "wizardNotTrusted": "aún no es de confianza — use el botón Confiar en el certificado", - "wizardTutorialTitle": "Instrucciones de configuración:", - "wizardEnableDns": "Agregar entradas a /etc/hosts", - "wizardDnsAlreadyEnabled": "DNS ya habilitado para este agente", - "enablingDns": "Habilitando…", - "modelSelectorTitle": "Seleccionar modelo de destino", - "modelSelectorSearch": "Buscar modelos…", - "noModelsFound": "No se encontraron modelos", - "quickLinks": "Enlaces rápidos", - "quickLinkProviders": "Configurar proveedores", - "quickLinkInspector": "Ver tráfico en Traffic Inspector", - "unknownError": "Error desconocido", - "maintenanceTitle": "Mantenimiento y diagnóstico", - "maintenanceSubtitle": "Realice una autocomprobación del pipeline de captura, revierta el estado residual del sistema y traslade su configuración entre máquinas.", - "orphanedStateWarning": "Una sesión anterior dejó un estado residual en el sistema (suplantación de DNS, CA o proxy del sistema). Ejecute Reparar para limpiarlo.", - "diagnose": "Diagnosticar", - "diagnosing": "Diagnosticando…", - "diagnoseHealthy": "El pipeline de captura está en buen estado.", - "diagnoseUnhealthy": "El pipeline de captura tiene problemas:", - "repair": "Reparar", - "repairing": "Reparando…", - "repairDone": "Reparado: {items}", - "repairNothing": "Nada que reparar — el estado del sistema está limpio.", - "removeCa": "Eliminar CA", - "removeCaConfirm": "¿Eliminar CA?", - "removeCaDone": "Se eliminó la CA raíz MITM del almacén de confianza del sistema operativo.", - "removing": "Eliminando…", - "confirm": "Confirmar", - "exportConfig": "Exportar configuración", - "exporting": "Exportando…", - "importConfig": "Importar configuración", - "importing": "Importando…", - "importInvalidJson": "El archivo seleccionado no es un JSON válido.", - "importDone": "Importados {bypass} bypass · {hosts} hosts · {agents} agentes", - "save": "Guardar", - "saving": "Guardando…", - "cancel": "Cancelar", - "back": "Atrás", - "next": "Siguiente", - "done": "Listo", - "loading": "Cargando…", - "riskNoticeTitle": "Reconocimiento de riesgos", - "riskNoticeBody": "AgentBridge interceptará el tráfico HTTPS de este agente redirigiendo sus hosts de API mediante DNS. Habilítelo solo si acepta la responsabilidad del cumplimiento de los términos de servicio del agente y de cualquier política de red aplicable.", + "wizardStep3Label": "Mappings", + "wizardStep1Desc": "Confirm the server is running and the certificate is installed.", + "wizardStep2Desc": "The following entries will be added to /etc/hosts to redirect traffic through AgentBridge:", + "wizardStep3Desc": "You can now configure model mappings in the agent card. Restart the IDE to apply changes.", + "wizardStep3Success": "Agent is configured!", + "wizardServerCheck": "AgentBridge server", + "wizardRunning": "running", + "wizardNotRunning": "not running", + "wizardCertCheck": "Certificate", + "wizardTrusted": "trusted", + "wizardNotTrusted": "not yet trusted — use Trust Cert button", + "wizardTutorialTitle": "Setup instructions:", + "wizardEnableDns": "Add /etc/hosts entries", + "wizardDnsAlreadyEnabled": "DNS already enabled for this agent", + "enablingDns": "Enabling…", + "modelSelectorTitle": "Select target model", + "modelSelectorSearch": "Search models…", + "noModelsFound": "No models found", + "quickLinks": "Quick links", + "quickLinkProviders": "Configure providers", + "quickLinkInspector": "View traffic in Traffic Inspector", + "unknownError": "Unknown error", + "maintenanceTitle": "Maintenance & Diagnostics", + "maintenanceSubtitle": "Self-test the capture pipeline, undo leftover system state, and move your setup between machines.", + "orphanedStateWarning": "A previous session left system state behind (DNS spoof, CA, or system proxy). Run Repair to clean it up.", + "diagnose": "Diagnose", + "diagnosing": "Diagnosing…", + "diagnoseHealthy": "Capture pipeline is healthy.", + "diagnoseUnhealthy": "Capture pipeline has problems:", + "repair": "Repair", + "repairing": "Repairing…", + "repairDone": "Repaired: {items}", + "repairNothing": "Nothing to repair — system state is clean.", + "removeCa": "Remove CA", + "removeCaConfirm": "Remove CA?", + "removeCaDone": "MITM root CA removed from the OS trust store.", + "removing": "Removing…", + "confirm": "Confirm", + "exportConfig": "Export config", + "exporting": "Exporting…", + "importConfig": "Import config", + "importing": "Importing…", + "importInvalidJson": "The selected file is not valid JSON.", + "importDone": "Imported {bypass} bypass · {hosts} hosts · {agents} agents", + "save": "Save", + "saving": "Saving…", + "cancel": "Cancel", + "back": "Back", + "next": "Next", + "done": "Done", + "loading": "Loading…", + "riskNoticeTitle": "Risk acknowledgment", + "riskNoticeBody": "AgentBridge will intercept HTTPS traffic from this agent by redirecting its API hosts via DNS. Only enable if you accept responsibility for compliance with the agent's terms of service and any applicable network policies.", "pageMoved": { - "goNow": "Ir ahora", - "message": "El proxy MITM ahora se encuentra en AgentBridge.", - "title": "Esta página se ha movido" + "goNow": "Go now", + "message": "The MITM Proxy now lives under AgentBridge.", + "title": "This page has moved" } }, "providerStats": { - "unknownError": "Error desconocido", - "loading": "Cargando estadísticas de proveedores...", - "loadFailed": "Error al cargar las estadísticas de proveedores: {error}", - "retry": "Reintentar", - "updated": "Actualizado {time}", - "refresh": "Actualizar", - "totalRequests": "Total de solicitudes", - "avgLatency": "Latencia promedio", - "successRate": "Tasa de éxito", - "activeProviders": "Proveedores activos", - "providerBreakdown": "Desglose de proveedores", - "providerCount": "{count} proveedores", - "provider": "Proveedor", - "requests": "Solicitudes", - "success": "Éxito", - "rate": "Tasa", - "tokensIn": "Tokens de entrada", - "tokensOut": "Tokens de salida", - "ttftAfterTool": "TTFT tras herramienta", - "gapAfterTool": "Intervalo tras herramienta", - "model": "Modelo", - "noProviderData": "Aún no se han registrado datos de proveedores.", - "comboMetrics": "Métricas de combinaciones", - "comboMetricsDescription": "Latencia y rendimiento por combinación del streaming", - "avgTtft": "TTFT promedio", - "avgTotal": "Total promedio", - "requestTelemetry": "Telemetría de solicitudes", - "requestTelemetryDescription": "Desglose del pipeline de 7 fases (últimos 5 minutos)" + "unknownError": "Unknown error", + "loading": "Loading provider stats...", + "loadFailed": "Failed to load provider stats: {error}", + "retry": "Retry", + "updated": "Updated {time}", + "refresh": "Refresh", + "totalRequests": "Total Requests", + "avgLatency": "Avg Latency", + "successRate": "Success Rate", + "activeProviders": "Active Providers", + "providerBreakdown": "Provider Breakdown", + "providerCount": "{count} providers", + "provider": "Provider", + "requests": "Requests", + "success": "Success", + "rate": "Rate", + "tokensIn": "Tokens In", + "tokensOut": "Tokens Out", + "ttftAfterTool": "TTFT After Tool", + "gapAfterTool": "Gap After Tool", + "model": "Model", + "noProviderData": "No provider data recorded yet.", + "comboMetrics": "Combo Metrics", + "comboMetricsDescription": "Per-combo latency and throughput from streaming", + "avgTtft": "Avg TTFT", + "avgTotal": "Avg Total", + "requestTelemetry": "Request Telemetry", + "requestTelemetryDescription": "7-phase pipeline breakdown (last 5 minutes)" }, "relay": { - "title": "Proxies de relay serverless", - "description": "Cree endpoints de API públicos que actúen como proxy hacia OmniRoute con limitación de velocidad y control de acceso", - "created": "Token de relay creado", - "createFailed": "Error al crear el token", - "toggleFailed": "Error al alternar el token", - "deleteConfirm": "¿Eliminar este token de relay? Esta acción no se puede deshacer.", - "deleted": "Token eliminado", - "deleteFailed": "Error al eliminar el token", - "cancel": "Cancelar", - "newToken": "Nuevo token de relay", - "createTitle": "Crear token de relay", - "nameRequired": "Nombre *", - "tokenDescription": "Descripción", - "descriptionPlaceholder": "Para mis funciones serverless", - "maxPerMinute": "Máx. solicitudes/minuto", - "maxPerDay": "Máx. solicitudes/día", - "createButton": "Crear token", - "createdTitle": "Token creado — ¡Cópialo ahora!", - "tokenFor": "Token para {name}:", - "shownOnce": "Este token no se volverá a mostrar. Guárdalo de forma segura.", - "dismiss": "Descartar", - "usage": "Uso", - "usageDescription": "Envía solicitudes a tu endpoint de relay:", - "tokenCount": "Tokens de relay ({count})", - "loading": "Cargando...", - "empty": "No hay tokens de relay configurados. Crea uno para empezar.", - "disable": "Desactivar", - "enable": "Activar", - "delete": "Eliminar" + "title": "Serverless Relay Proxies", + "description": "Create public API endpoints that proxy to OmniRoute with rate limiting and access control", + "created": "Relay token created", + "createFailed": "Failed to create token", + "toggleFailed": "Failed to toggle token", + "deleteConfirm": "Delete this relay token? This cannot be undone.", + "deleted": "Token deleted", + "deleteFailed": "Failed to delete token", + "cancel": "Cancel", + "newToken": "New Relay Token", + "createTitle": "Create Relay Token", + "nameRequired": "Name *", + "tokenDescription": "Description", + "descriptionPlaceholder": "For my serverless functions", + "maxPerMinute": "Max Requests/Minute", + "maxPerDay": "Max Requests/Day", + "createButton": "Create Token", + "createdTitle": "Token Created — Copy it now!", + "tokenFor": "Token for {name}:", + "shownOnce": "This token will not be shown again. Store it securely.", + "dismiss": "Dismiss", + "usage": "Usage", + "usageDescription": "Send requests to your relay endpoint:", + "tokenCount": "Relay Tokens ({count})", + "loading": "Loading...", + "empty": "No relay tokens configured. Create one to get started.", + "disable": "Disable", + "enable": "Enable", + "delete": "Delete" }, "trafficInspector": { - "title": "Inspector de tráfico", - "subtitle": "Supervisa las llamadas a LLM y depura el tráfico HTTPS de cualquier aplicación", - "captureModesTitle": "Modos de captura", + "title": "Traffic Inspector", + "subtitle": "Monitor LLM calls and debug any application's HTTPS traffic", + "captureModesTitle": "Capture Modes", "agentBridgeMode": "AgentBridge", - "agentBridgeModeDesc": "Captura el tráfico de todos los agentes de IDE conectados", - "customHostsMode": "Hosts personalizados", - "customHostsModeDesc": "Añade hosts específicos para interceptar", - "httpProxyMode": "Proxy HTTP", - "httpProxyModeDesc": "Usa la variable de entorno HTTP_PROXY", - "systemWideMode": "Todo el sistema", - "systemWideModeDesc": "Intercepta todo el tráfico del sistema (avanzado)", - "tproxyMode": "Descifrado TPROXY", - "tproxyModeUnavailable": "El descifrado TPROXY requiere Linux + root + el complemento nativo", - "filterBarTitle": "Filtros", - "profileLlmOnly": "Solo LLM", - "profileCustom": "Personalizado", - "profileAll": "Todos", - "filterHost": "Filtrar host…", - "filterAgent": "Agente", - "filterStatus": "Estado", - "pauseBtn": "Pausar", - "resumeBtn": "Reanudar", - "clearBtn": "Limpiar", - "exportHar": "Exportar .har", + "agentBridgeModeDesc": "Capture traffic from all connected IDE agents", + "customHostsMode": "Custom Hosts", + "customHostsModeDesc": "Add specific hosts to intercept", + "httpProxyMode": "HTTP Proxy", + "httpProxyModeDesc": "Use HTTP_PROXY environment variable", + "systemWideMode": "System-wide", + "systemWideModeDesc": "Intercept all system traffic (advanced)", + "tproxyMode": "TPROXY Decrypt", + "tproxyModeUnavailable": "TPROXY decrypt requires Linux + root + the native addon", + "filterBarTitle": "Filters", + "profileLlmOnly": "LLM only", + "profileCustom": "Custom", + "profileAll": "All", + "filterHost": "Filter host…", + "filterAgent": "Agent", + "filterStatus": "Status", + "pauseBtn": "Pause", + "resumeBtn": "Resume", + "clearBtn": "Clear", + "exportHar": "Export .har", "recordSession": "REC", - "stopSession": "Detener", - "liveBadge": "en vivo", - "offlineBadge": "sin conexión", - "noRequests": "Aún no se han capturado solicitudes.", - "noRequestsDesc": "Asegúrate de que AgentBridge se esté ejecutando o habilita otro modo de captura.", - "selectRequest": "Selecciona una solicitud para inspeccionarla.", - "tabConversation": "Conversación", - "tabHeaders": "Encabezados", - "tabRequest": "Solicitud", - "tabResponse": "Respuesta", - "tabTiming": "Tiempos", + "stopSession": "Stop", + "liveBadge": "live", + "offlineBadge": "offline", + "noRequests": "No requests captured yet.", + "noRequestsDesc": "Make sure AgentBridge is running or enable another capture mode.", + "selectRequest": "Select a request to inspect it.", + "tabConversation": "Conversation", + "tabHeaders": "Headers", + "tabRequest": "Request", + "tabResponse": "Response", + "tabTiming": "Timing", "tabLlm": "LLM", - "tabStats": "Estadísticas", - "requestHeaders": "Encabezados de solicitud", - "responseHeaders": "Encabezados de respuesta", - "rawEvents": "Eventos sin procesar", - "mergedView": "Vista combinada", - "noBody": "Sin cuerpo.", - "streaming": "transmitiendo…", - "manageHosts": "Administrar hosts", - "copySnippet": "Copiar fragmento de proxy", - "addHost": "Agregar", + "tabStats": "Stats", + "requestHeaders": "Request Headers", + "responseHeaders": "Response Headers", + "rawEvents": "Raw events", + "mergedView": "Merged view", + "noBody": "No body.", + "streaming": "streaming…", + "manageHosts": "Manage hosts", + "copySnippet": "Copy proxy snippet", + "addHost": "Add", "hostPlaceholder": "api.openai.com", - "noHostsYet": "Aún no se han agregado hosts personalizados.", - "noSessionsYet": "Aún no hay sesiones", - "allTraffic": "Todo el tráfico (sin sesión)", - "sessionsDropdown": "Sesiones", - "annotationPlaceholder": "Agregar una nota…", - "contextFingerprint": "Huella digital de contexto", - "llmProvider": "Proveedor detectado", - "llmApiKind": "Tipo de API", - "llmModel": "Modelo", - "llmMessages": "Mensajes", - "llmStream": "Flujo", - "llmMappedTo": "Asignado a", - "llmCostEstimate": "Estimación de costo", - "systemProxyExitWarning": "El proxy de todo el sistema sigue activo — ¿salir de la página de todos modos?", - "customHostsTitle": "Hosts personalizados", - "loading": "Cargando…", - "copied": "¡Copiado!", - "copy": "Copiar", - "httpProxyTitle": "Fragmento de proxy HTTP — puerto {port}", - "notRecording": "No grabando", - "anyStatus": "Cualquier estado", - "liveOnly": "En vivo", - "viewingRecordedSession": "Viendo sesión grabada", - "backToLive": "Volver a en vivo", - "untitledSession": "Sesión sin título", - "contextHistory": "Historial de contexto", - "modelResponse": "Respuesta del modelo", - "conversationNoMessages": "No se encontraron mensajes en esta solicitud.", - "conversationNotAvailable": "Datos de conversación no disponibles. Es posible que esta no sea una solicitud de LLM o que no se haya podido analizar el cuerpo.", - "loadingCharts": "Cargando gráficos…", - "statsErrors": "Errores", - "statsLatency": "Latencia (últimas 50 solicitudes)", - "statsNoData": "Aún no hay solicitudes. Inicie una grabación de sesión para capturar datos para las estadísticas.", - "statsStatusDistribution": "Distribución de estados", - "statsSuccessful": "Exitosas", - "statsTotalRequests": "Total de solicitudes", - "timingProxyOverhead": "Sobrecarga del proxy", - "timingUpstreamResponse": "Respuesta upstream", - "timingNoData": "No hay datos de tiempo disponibles.", - "timingTotalLatency": "Latencia total", - "timingTimestamp": "Marca de tiempo", - "timingMethod": "Método", - "timingStatus": "Estado", - "timingRequestSize": "Tamaño de la solicitud", - "timingResponseSize": "Tamaño de la respuesta", - "pausedNewBadge": "{count} nuevos", - "clearContextFilter": "limpiar", - "invalidHostname": "Nombre de host no válido", - "invalidHost": "Host no válido", - "addHostFailed": "Error al agregar el host", - "networkError": "Error de red", - "close": "Cerrar", - "removeHost": "Eliminar {host}", - "requestDetails": "Detalles de la solicitud", - "filterByContext": "Filtrar por este contexto", - "filteringContext": "Filtrado: contexto {context}", - "clear": "limpiar", - "trafficProfile": "Perfil de tráfico", - "roleSystem": "Sistema", - "roleUser": "Usuario", - "roleAssistant": "Asistente", - "roleTool": "Herramienta", - "expand": "Expandir", - "collapse": "Contraer", - "systemPromptHidden": "Prompt del sistema oculto — haz clic para expandir", - "sessionName": "Sesión {id}", - "sessions": "Sesiones", - "requestCountShort": "{count} peticiones", - "deleteSession": "Eliminar sesión", - "saving": "Guardando…", - "sensitiveHeaders": "Cabeceras sensibles", - "show": "Mostrar", - "hide": "Ocultar", - "name": "Nombre", - "value": "Valor", - "noSseEvents": "Sin eventos SSE", - "noRequestBody": "Sin cuerpo de petición.", - "noResponseBody": "Sin cuerpo de respuesta.", - "formatted": "Formateado", - "raw": "Sin formato" + "noHostsYet": "No custom hosts added yet.", + "noSessionsYet": "No sessions yet", + "allTraffic": "All traffic (no session)", + "sessionsDropdown": "Sessions", + "annotationPlaceholder": "Add a note…", + "contextFingerprint": "Context fingerprint", + "llmProvider": "Detected provider", + "llmApiKind": "API kind", + "llmModel": "Model", + "llmMessages": "Messages", + "llmStream": "Stream", + "llmMappedTo": "Mapped to", + "llmCostEstimate": "Cost estimate", + "systemProxyExitWarning": "System-wide proxy still active — leave page anyway?", + "customHostsTitle": "Custom Hosts", + "loading": "Loading…", + "copied": "Copied!", + "copy": "Copy", + "httpProxyTitle": "HTTP Proxy Snippet — port {port}", + "notRecording": "Not recording", + "anyStatus": "Any status", + "liveOnly": "Live", + "viewingRecordedSession": "Viewing recorded session", + "backToLive": "Back to live", + "untitledSession": "Untitled session", + "contextHistory": "Context History", + "modelResponse": "Model Response", + "conversationNoMessages": "No messages found in this request.", + "conversationNotAvailable": "Conversation data not available. This may not be an LLM request or the body could not be parsed.", + "loadingCharts": "Loading charts…", + "statsErrors": "Errors", + "statsLatency": "Latency (last 50 requests)", + "statsNoData": "No requests yet. Start a session recording to capture data for stats.", + "statsStatusDistribution": "Status distribution", + "statsSuccessful": "Successful", + "statsTotalRequests": "Total requests", + "timingProxyOverhead": "Proxy overhead", + "timingUpstreamResponse": "Upstream response", + "timingNoData": "No timing data available.", + "timingTotalLatency": "Total latency", + "timingTimestamp": "Timestamp", + "timingMethod": "Method", + "timingStatus": "Status", + "timingRequestSize": "Request size", + "timingResponseSize": "Response size", + "pausedNewBadge": "{count} new", + "clearContextFilter": "clear", + "invalidHostname": "Invalid hostname", + "invalidHost": "Invalid host", + "addHostFailed": "Failed to add host", + "networkError": "Network error", + "close": "Close", + "removeHost": "Remove {host}", + "requestDetails": "Request details", + "filterByContext": "Filter by this context", + "filteringContext": "Filtering: context {context}", + "clear": "clear", + "trafficProfile": "Traffic profile", + "roleSystem": "System", + "roleUser": "User", + "roleAssistant": "Assistant", + "roleTool": "Tool", + "expand": "Expand", + "collapse": "Collapse", + "systemPromptHidden": "System prompt hidden — click to expand", + "sessionName": "Session {id}", + "sessions": "Sessions", + "requestCountShort": "{count} reqs", + "deleteSession": "Delete session", + "saving": "Saving…", + "sensitiveHeaders": "Sensitive headers", + "show": "Show", + "hide": "Hide", + "name": "Name", + "value": "Value", + "noSseEvents": "No SSE events", + "noRequestBody": "No request body.", + "noResponseBody": "No response body.", + "formatted": "Formatted", + "raw": "Raw" }, "cliCommon": { "concept": { "code": { - "title": "Código CLI", - "phrase": "Herramientas de código que diriges a OmniRoute", - "flow": "Tú → Código CLI → OmniRoute → Proveedor", - "seeOther": "Ver →" + "title": "CLI Code", + "phrase": "Code tools you point at OmniRoute", + "flow": "You → CLI Code → OmniRoute → Provider", + "seeOther": "See →" }, "agent": { - "title": "Agentes CLI", - "phrase": "Agentes CLI autónomos de propósito general que diriges a OmniRoute", - "flow": "Tú → Agente CLI → OmniRoute → Proveedor", - "seeOther": "Ver →" + "title": "CLI Agents", + "phrase": "Broad-purpose autonomous CLI agents you point at OmniRoute", + "flow": "You → CLI Agent → OmniRoute → Provider", + "seeOther": "See →" }, "acp": { - "title": "Agentes ACP", - "phrase": "CLIs que OmniRoute inicia como backend de ejecución (flujo inverso)", - "flow": "Cliente → OmniRoute → iniciar CLI (stdio/ACP) → respuesta", - "seeOther": "Ver →" + "title": "ACP Agents", + "phrase": "CLIs that OmniRoute spawns as execution backend (reverse flow)", + "flow": "Client → OmniRoute → spawn CLI (stdio/ACP) → response", + "seeOther": "See →" } }, "comparison": { - "title": "Entiende los 3 tipos de CLI en OmniRoute", - "thisPage": "Esta página", - "open": "Abrir →", + "title": "Understand the 3 CLI types in OmniRoute", + "thisPage": "This page", + "open": "Open →", "code": { - "title": "Herramienta de código", - "desc": "Apunta a Omni", - "flow": "tú → CLI → Omni → proveedor", - "examples": "ej.: claude, codex" + "title": "Code tool", + "desc": "Points to Omni", + "flow": "you → CLI → Omni → provider", + "examples": "e.g.: claude, codex" }, "agent": { - "title": "Agente autónomo general", - "desc": "Apunta a Omni", - "flow": "tú → agente → Omni", - "examples": "ej.: hermes, goose" + "title": "Broad autonomous agent", + "desc": "Points to Omni", + "flow": "you → agent → Omni", + "examples": "e.g.: hermes, goose" }, "acp": { - "title": "CLI usado como backend por Omni", - "desc": "Ejecución inversa", - "flow": "Omni → ejecutar CLI → resp", - "examples": "ej.: claude, codex (ACP)" + "title": "CLI used as backend by Omni", + "desc": "Reverse execution", + "flow": "Omni → spawn CLI → resp", + "examples": "e.g.: claude, codex (ACP)" } }, "card": { - "detected": "Detectado", - "notDetected": "No detectado", - "configured": "Configurado", - "notConfigured": "No configurado", - "configure": "Configurar →", - "howToInstall": "Cómo instalar →", - "versionNotFound": "no encontrado", - "manualConfig": "Configuración manual", - "installGuide": "Guía de instalación", + "detected": "Detected", + "notDetected": "Not detected", + "configured": "Configured", + "notConfigured": "Not configured", + "configure": "Configure →", + "howToInstall": "How to install →", + "versionNotFound": "not found", + "manualConfig": "Manual config", + "installGuide": "Install guide", "endpointLabel": "Endpoint", - "baseUrlFull": "URL base completa", - "baseUrlPartial": "URL base parcial", - "refreshDetection": "Actualizar detección", - "alsoAcp": "también ACP", - "connectProviderHint": "Conecta un proveedor en Proveedores" + "baseUrlFull": "Full Base URL", + "baseUrlPartial": "Partial Base URL", + "refreshDetection": "Refresh detection", + "alsoAcp": "also ACP", + "connectProviderHint": "Connect a provider in Providers" }, "detail": { - "back": "Atrás", - "apply": "Guardar", - "reset": "Limpiar", - "manualConfig": "Configuración manual", - "vendor": "Proveedor", - "category": "Tipo", - "detectionStatus": "Detección", - "configStatus": "Configuración", - "baseUrlLabel": "URL base", - "apiKeyLabel": "Clave API", - "modelMappingLabel": "Mapeo de modelos", - "noActiveProviders": "No hay proveedores activos.", - "noActiveProvidersDesc": "Ve a Proveedores para conectar al menos 1 proveedor antes de configurar la CLI.", + "back": "Back", + "apply": "Save", + "reset": "Clear", + "manualConfig": "Manual configuration", + "vendor": "Vendor", + "category": "Type", + "detectionStatus": "Detection", + "configStatus": "Configuration", + "baseUrlLabel": "Base URL", + "apiKeyLabel": "API Key", + "modelMappingLabel": "Model mapping", + "noActiveProviders": "No active providers.", + "noActiveProvidersDesc": "Go to Providers to connect at least 1 provider before configuring the CLI.", "openProviders": "Open Providers →" } }, "cliCode": { - "pageTitle": "Códigos CLI", - "pageSubtitle": "Herramientas de código que apuntan a OmniRoute", - "searchPlaceholder": "Buscar CLI…", - "filterDetectionLabel": "Detección", - "filterBaseUrlLabel": "URL base", - "detectionAll": "Todos", - "detectionInstalled": "Instalado", - "detectionNotFound": "No encontrado", - "baseUrlAll": "Todos", - "baseUrlFull": "Completo", - "baseUrlPartial": "Parcial" + "pageTitle": "CLI Code's", + "pageSubtitle": "Code tools pointing to OmniRoute", + "searchPlaceholder": "Search CLI…", + "filterDetectionLabel": "Detection", + "filterBaseUrlLabel": "Base URL", + "detectionAll": "All", + "detectionInstalled": "Installed", + "detectionNotFound": "Not found", + "baseUrlAll": "All", + "baseUrlFull": "Full", + "baseUrlPartial": "Partial" }, "cliAgents": { - "pageTitle": "Agentes de CLI", - "pageSubtitle": "Agentes de CLI autónomos de propósito general", - "refreshDetection": "Actualizar detección", - "searchPlaceholder": "Buscar agente…", - "detectionFilterLabel": "Detección", - "detectionAll": "Todos", - "detectionInstalled": "Instalado", - "detectionNotInstalled": "No instalado", - "visibleCount": "{count} visibles", - "emptyState": "No se encontraron agentes de CLI con los filtros actuales." + "pageTitle": "CLI Agents", + "pageSubtitle": "Broad-purpose autonomous CLI agents", + "refreshDetection": "Refresh detection", + "searchPlaceholder": "Search agent…", + "detectionFilterLabel": "Detection", + "detectionAll": "All", + "detectionInstalled": "Installed", + "detectionNotInstalled": "Not installed", + "visibleCount": "{count} visible", + "emptyState": "No CLI agents found with the current filters." }, "acpAgents": { - "pageTitle": "Agentes ACP", - "pageSubtitle": "CLIs que OmniRoute inicia como backend de ejecución", - "scanning": "Detectando agentes…", - "refresh": "Actualizar", - "setupGuideTitle": "Guía de configuración", - "setupGuideDetectCliTitle": "Detectar CLI", - "setupGuideDetectCliDesc": "Los agentes se identifican ejecutando el comando --version en PATH.", - "setupGuideCustomAgentTitle": "Añadir agente personalizado", - "setupGuideCustomAgentDesc": "Complete el formulario a continuación para registrar un agente de CLI personalizado.", - "setupGuideCommandMissingTitle": "Comando no encontrado", - "setupGuideCommandMissingDesc": "Compruebe que el binario está en PATH.", - "fingerprintSettingsHint": "Configure el enrutamiento y las huellas digitales en", - "settingsRoutingLink": "Configuración → Enrutamiento", - "installed": "Instalado", - "notFound": "No encontrado", - "builtIn": "Integrado", - "custom": "Personalizado", - "agentUseCaseHint": "Disponible para iniciar a través de ACP.", - "remove": "Eliminar", - "addCustomAgent": "Añadir agente personalizado", - "addCustomAgentDesc": "Registrar un agente de CLI personalizado para ser iniciado a través de ACP.", - "addAgent": "Añadir agente", - "agentName": "Nombre", - "agentNamePlaceholder": "ej.: Mi agente", - "binaryName": "Binario", - "binaryNamePlaceholder": "ej.: myagent", - "versionCommand": "Comando de versión", - "versionCommandPlaceholder": "ej.: myagent --version", - "spawnArgs": "Argumentos de inicio", - "spawnArgsPlaceholder": "ej.: --quiet, --json", - "cliCodeRedirectCta": "Abrir código de CLI" + "pageTitle": "ACP Agents", + "pageSubtitle": "CLIs that OmniRoute spawns as execution backend", + "scanning": "Detecting agents…", + "refresh": "Refresh", + "setupGuideTitle": "Setup guide", + "setupGuideDetectCliTitle": "Detect CLI", + "setupGuideDetectCliDesc": "Agents are identified by running the --version command in PATH.", + "setupGuideCustomAgentTitle": "Add custom agent", + "setupGuideCustomAgentDesc": "Fill in the form below to register a custom CLI agent.", + "setupGuideCommandMissingTitle": "Command not found", + "setupGuideCommandMissingDesc": "Check that the binary is in PATH.", + "fingerprintSettingsHint": "Configure routing and fingerprints in", + "settingsRoutingLink": "Settings → Routing", + "installed": "Installed", + "notFound": "Not found", + "builtIn": "Built-in", + "custom": "Custom", + "agentUseCaseHint": "Available for spawn via ACP.", + "remove": "Remove", + "addCustomAgent": "Add custom agent", + "addCustomAgentDesc": "Register a custom CLI agent to be spawned via ACP.", + "addAgent": "Add agent", + "agentName": "Name", + "agentNamePlaceholder": "e.g.: My Agent", + "binaryName": "Binary", + "binaryNamePlaceholder": "e.g.: myagent", + "versionCommand": "Version command", + "versionCommandPlaceholder": "e.g.: myagent --version", + "spawnArgs": "Spawn arguments", + "spawnArgsPlaceholder": "e.g.: --quiet, --json", + "cliCodeRedirectCta": "Open CLI Code" }, "agentSkills": { "catalog": { "omni-auth": { - "name": "Autenticación", - "description": "Gestione la autenticación de claves de API y los tokens de sesión. Comience aquí para autenticar solicitudes a través de token Bearer, obtener cookies de sesión y configurar los requisitos de inicio de sesión para la API de OmniRoute." + "name": "Authentication", + "description": "Manage API key authentication and session tokens. Start here to authenticate requests via Bearer token, obtain session cookies, and configure login requirements for the OmniRoute API." }, "omni-providers": { - "name": "Proveedores", - "description": "Gestione las conexiones de proveedores, claves de API, flujos de OAuth y pruebas de conexión a través de la API REST. Enumere, añada, actualice, elimine y pruebe integraciones de proveedores de IA (OpenAI, Anthropic, Gemini y más de 160)." + "name": "Providers", + "description": "Manage provider connections, API keys, OAuth flows, and connection tests via the REST API. List, add, update, remove, and test AI provider integrations (OpenAI, Anthropic, Gemini, and 160+)." }, "omni-models": { - "name": "Modelos", - "description": "Consulte los modelos de IA disponibles en todos los proveedores configurados. Enumere modelos, resuelva alias de modelos y explore el catálogo completo de modelos, incluidas las variantes específicas de cada proveedor." + "name": "Models", + "description": "Query available AI models across all configured providers. List models, resolve model aliases, and browse the full model catalog including provider-specific variants." }, "omni-combos-routing": { - "name": "Combos y enrutamiento", - "description": "Cree y gestione combos de enrutamiento con 14 estrategias (prioridad, ponderado, round-robin, Auto-combo, etc.). Configure cadenas de respaldo, pruebe los resultados del enrutamiento y recupere métricas de combos." + "name": "Combos & Routing", + "description": "Create and manage routing combos with 14 strategies (priority, weighted, round-robin, Auto-combo, etc.). Configure fallback chains, test routing outcomes, and retrieve combo metrics." }, "omni-api-keys": { - "name": "Claves de API", - "description": "Cree, enumere, rote y revoque claves de API de OmniRoute. Controle los alcances por clave, los límites de gasto y la expiración. Las claves controlan el acceso a todos los endpoints de proxy y gestión." + "name": "API Keys", + "description": "Create, list, rotate, and revoke OmniRoute API keys. Control per-key scopes, spending limits, and expiration. Keys gate access to all proxy and management endpoints." }, "omni-usage-logs": { - "name": "Uso y registros", - "description": "Acceda a registros de llamadas detallados y análisis de uso. Filtre por proveedor, modelo, rango de tiempo, estado y costo. Exporte registros y agregue el uso de tokens en todas las conexiones." + "name": "Usage & Logs", + "description": "Access detailed call logs and usage analytics. Filter by provider, model, time range, status, and cost. Export logs and aggregate token usage across all connections." }, "omni-budget": { - "name": "Presupuesto y límites de tarifa", - "description": "Configure límites de gasto, cuotas de tokens y políticas de límite de tarifa por clave de API o de forma global. Inspeccione el consumo actual y aplique controles de costos en todos los proveedores." + "name": "Budget & Rate Limits", + "description": "Configure spending limits, token quotas, and rate-limit policies per API key or globally. Inspect current consumption and enforce cost controls across providers." }, "omni-settings": { - "name": "Configuración", - "description": "Lea y realice actualizaciones en la configuración global de la aplicación: prompts del sistema, presupuesto de pensamiento, filtros de IP, reglas de payload, valores predeterminados de combos y configuración de inicio de sesión obligatorio." + "name": "Settings", + "description": "Read and update global application settings: system prompts, thinking budget, IP filters, payload rules, combo defaults, and require-login configuration." }, "omni-proxies": { - "name": "Configuración de proxy", - "description": "Configure proxies HTTP/HTTPS/SOCKS para solicitudes de proveedores ascendentes. Establezca reglas de proxy globales o por proveedor, pruebe la conectividad y gestione la rotación de proxies." + "name": "Proxy Configuration", + "description": "Configure HTTP/HTTPS/SOCKS proxies for upstream provider requests. Set per-provider or global proxy rules, test connectivity, and manage proxy rotation." }, "omni-cache": { - "name": "Caché", - "description": "Gestione la caché de respuestas de LLM. Vea estadísticas de caché, borre entradas, configure políticas de TTL y controle los umbrales de almacenamiento en caché por similitud semántica." + "name": "Cache", + "description": "Manage the LLM response cache. View cache statistics, clear entries, configure TTL policies, and control semantic-similarity caching thresholds." }, "omni-compression": { - "name": "Compresión", - "description": "Configure los modos de compresión RTK (salida de comandos), Caveman (prosa) y apilada. Gestione paquetes de idiomas, reglas personalizadas y pruebe la compresión de prompts reduciendo los tokens entre un 60 y un 90 %." + "name": "Compression", + "description": "Configure RTK (command output), Caveman (prose), and stacked compression modes. Manage language packs, custom rules, and test prompt compression reducing tokens by 60–90%." }, "omni-context-rtk": { - "name": "Contexto y RTK", - "description": "Configure filtros RTK, reglas de ingeniería de contexto y ajustes de retransmisión de contexto. Pruebe la compresión con muestras de prompts reales y gestione las canalizaciones de transformación de contexto." + "name": "Context & RTK", + "description": "Configure RTK filters, context engineering rules, and context relay settings. Test compression with real prompt samples and manage context transformation pipelines." }, "omni-resilience": { - "name": "Resiliencia y monitoreo", - "description": "Monitoree el estado del proveedor, los estados del disyuntor, las métricas de latencia p50/p95/p99 y las alertas de protección de presupuesto. Inspeccione los tiempos de enfriamiento de las conexiones y los bloqueos de modelos en tiempo real." + "name": "Resilience & Monitoring", + "description": "Monitor provider health, circuit-breaker states, p50/p95/p99 latency metrics, and budget guard alerts. Inspect connection cooldowns and model lockouts in real time." }, "omni-cli-tools": { - "name": "Herramientas de CLI", - "description": "Administre las integraciones de herramientas de CLI expuestas a través de la API. Enumere, configure e invoque complementos de herramientas de CLI que extienden la superficie de automatización de OmniRoute." + "name": "CLI Tools", + "description": "Manage CLI tool integrations exposed via the API. List, configure, and invoke CLI tool plugins that extend OmniRoute's automation surface." }, "omni-tunnels": { - "name": "Túneles", - "description": "Cree y administre túneles seguros (ngrok, Cloudflare Tunnel, personalizados) para exponer OmniRoute a Internet o compartir el acceso con agentes remotos y pipelines de CI." + "name": "Tunnels", + "description": "Create and manage secure tunnels (ngrok, Cloudflare Tunnel, custom) to expose OmniRoute to the internet or share access with remote agents and CI pipelines." }, "omni-sync-cloud": { - "name": "Sincronización en la nube", - "description": "Sincronice la configuración de OmniRoute, las conexiones de proveedores y los ajustes hacia y desde el almacenamiento en la nube. Administre la autenticación de trabajadores en la nube y los destinos de copia de seguridad remotos." + "name": "Cloud Sync", + "description": "Synchronise OmniRoute configuration, provider connections, and settings to/from cloud storage. Manage cloud worker authentication and remote backup targets." }, "omni-db-backups": { - "name": "Base de datos y copias de seguridad", - "description": "Active copias de seguridad del sistema, restaure a partir de archivos de copia de seguridad y administre el ciclo de vida de la base de datos SQLite. Admite estrategias de exportación, importación e instantáneas incrementales." + "name": "Database & Backups", + "description": "Trigger system backups, restore from backup files, and manage the SQLite database lifecycle. Supports export, import, and incremental snapshot strategies." }, "omni-webhooks": { "name": "Webhooks", - "description": "Registre, enumere, pruebe y elimine endpoints de webhook. Configure suscripciones a eventos (request.completed, provider.error, budget.exceeded, etc.) y administre los reintentos de entrega." + "description": "Register, list, test, and remove webhook endpoints. Configure event subscriptions (request.completed, provider.error, budget.exceeded, etc.) and manage delivery retries." }, "omni-mcp": { - "name": "Servidor MCP", - "description": "Conéctese al servidor MCP de OmniRoute (37 herramientas, 3 transportes: SSE/stdio/HTTP). Cubre herramientas de enrutamiento, caché, compresión, memoria, habilidades, proveedores y auditoría en 16 ámbitos de permisos." + "name": "MCP Server", + "description": "Connect to the OmniRoute MCP server (37 tools, 3 transports: SSE/stdio/HTTP). Covers routing, cache, compression, memory, skills, providers, and audit tools across 16 permission scopes." }, "omni-agents-a2a": { - "name": "Agentes y protocolo A2A", - "description": "Interactúe con OmniRoute a través del protocolo de agente a agente JSON-RPC 2.0. 6 habilidades A2A integradas: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities." + "name": "Agents & A2A Protocol", + "description": "Interact with OmniRoute via JSON-RPC 2.0 agent-to-agent protocol. 6 built-in A2A skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities." }, "omni-version-manager": { - "name": "Administrador de versiones", - "description": "Instale, inicie, detenga, reinicie y actualice servicios integrados (9Router, CLIProxyAPI). Supervise el estado del servicio, recupere registros y configure el inicio automático para endpoints de servicio solo locales." + "name": "Version Manager", + "description": "Install, start, stop, restart, and update embedded services (9Router, CLIProxyAPI). Monitor service status, retrieve logs, and configure auto-start for local-only service endpoints." }, "omni-inference": { - "name": "Inferencia (compatible con OpenAI)", - "description": "Los endpoints de inferencia principales compatibles con OpenAI: chat completions, embeddings, images, audio (TTS/STT), moderations, rerank y la Responses API. La superficie de integración principal para agentes de IA." + "name": "Inference (OpenAI-compatible)", + "description": "The core OpenAI-compatible inference endpoints: chat completions, embeddings, images, audio (TTS/STT), moderations, rerank, and the Responses API. The primary integration surface for AI agents." }, "cli-serve": { "name": "CLI: Serve", - "description": "Inicie, detenga y reinicie el servidor OmniRoute desde la CLI. Administre el modo demonio, la configuración de puertos, la recuperación automática, la integración con la bandeja del sistema y el acceso directo para abrir el panel de control." + "description": "Start, stop, and restart the OmniRoute server from the CLI. Manage daemon mode, port configuration, auto-recovery, system tray integration, and the dashboard open shortcut." }, "cli-health": { "name": "CLI: Health", - "description": "Compruebe el estado del servidor, el estado de los componentes y las métricas en tiempo real desde la CLI. Ejecute `health`, `health components` y `health watch` para ver un panel en tiempo real de los disyuntores y el estado de los proveedores." + "description": "Check server health, component status, and live metrics from the CLI. Run `health`, `health components`, and `health watch` for a real-time dashboard of circuit breakers and provider status." }, "cli-providers": { "name": "CLI: Providers", - "description": "Administre las conexiones de proveedores desde la CLI: enumere los proveedores disponibles/configurados, agregue, pruebe, test-all, valide, rote claves de API y vea métricas por proveedor." + "description": "Manage provider connections from the CLI: list available/configured providers, add, test, test-all, validate, rotate API keys, and view per-provider metrics." }, "cli-keys": { "name": "CLI: API Keys", - "description": "Cree, enumere, rote y revoque claves de API de OmniRoute desde la CLI. Administre flujos de OAuth para la autenticación de proveedores e inspeccione los ámbitos y la expiración de las claves." + "description": "Create, list, rotate, and revoke OmniRoute API keys from the CLI. Manage OAuth flows for provider authentication and inspect key scopes and expiration." }, "cli-models": { "name": "CLI: Models", - "description": "Consulte los modelos de IA disponibles, enumere los alias de los modelos y explore el catálogo completo de modelos desde la CLI. Filtre por proveedor, busque por capacidad y resuelva variantes de nombres de modelos." + "description": "Query available AI models, list model aliases, and browse the full model catalog from the CLI. Filter by provider, search by capability, and resolve model name variants." }, "cli-chat": { "name": "CLI: Chat", - "description": "Envíe completados de chat, transmita respuestas en tiempo real e inicie una sesión REPL interactiva desde la CLI. Admite todos los proveedores de OmniRoute, enrutamiento combinado y configuración de prompts del sistema." + "description": "Send chat completions, stream responses, and start an interactive REPL session from the CLI. Supports all OmniRoute providers, combo routing, and system prompt configuration." }, "cli-routing": { "name": "CLI: Routing & Combos", - "description": "Cree, enumere, actualice y elimine combos de enrutamiento desde la CLI. Pruebe estrategias de enrutamiento, inspeccione métricas de combos y configure cadenas de respaldo de forma interactiva." + "description": "Create, list, update, and delete routing combos from the CLI. Test routing strategies, inspect combo metrics, and configure fallback chains interactively." }, "cli-resilience": { "name": "CLI: Resilience & Quotas", - "description": "Inspeccione y administre estados de disyuntores, tiempos de enfriamiento de conexión, límites de cuota y niveles de backoff desde la CLI. Restablezca proveedores bloqueados y configure umbrales de resiliencia." + "description": "Inspect and manage circuit-breaker states, connection cooldowns, quota limits, and backoff levels from the CLI. Reset stuck providers and configure resilience thresholds." }, "cli-compression": { "name": "CLI: Compression", - "description": "Configure y pruebe la compresión de prompts desde la CLI. Administre filtros RTK, reglas Caveman, modos de compresión apilados y obtenga una vista previa del resultado de la compresión con prompts reales." + "description": "Configure and test prompt compression from the CLI. Manage RTK filters, Caveman rules, stacked compression modes, and preview compression output with real prompts." }, "cli-contexts": { "name": "CLI: Contexts & Sessions", - "description": "Administre configuraciones de ingeniería de contexto, conjuntos de filtros RTK y sesiones de conversación desde la CLI. Aplique la configuración de transmisión de contexto (context-relay) e inspeccione los pipelines de contexto activos." + "description": "Manage context engineering configurations, RTK filter sets, and conversation sessions from the CLI. Apply context-relay settings and inspect active context pipelines." }, "cli-cost-usage": { "name": "CLI: Cost & Usage", - "description": "Vea desgloses de costos, uso de tokens y registros de llamadas desde la CLI. Filtre por proveedor, modelo o rango de fechas. Exporte informes de uso e inspeccione el gasto por conexión." + "description": "View cost breakdowns, token usage, and call logs from the CLI. Filter by provider, model, or date range. Export usage reports and inspect per-connection spending." }, "cli-mcp": { "name": "CLI: MCP", - "description": "Inspeccionar el estado del servidor MCP, enumerar las herramientas y ámbitos registrados, ejecutar invocaciones de herramientas y administrar los registros de auditoría de MCP desde la CLI." + "description": "Inspect the MCP server status, list registered tools and scopes, run tool invocations, and manage MCP audit logs from the CLI." }, "cli-a2a": { - "name": "CLI: Protocolo A2A", - "description": "Interactuar con el servidor A2A de OmniRoute desde la CLI. Enviar tareas, inspeccionar el historial de ejecución de habilidades y probar el protocolo de agente a agente JSON-RPC 2.0 de forma interactiva." + "name": "CLI: A2A Protocol", + "description": "Interact with the OmniRoute A2A server from the CLI. Send tasks, inspect skill execution history, and test the JSON-RPC 2.0 agent-to-agent protocol interactively." }, "cli-tunnel": { - "name": "CLI: Túneles", - "description": "Iniciar y detener conexiones de túnel (ngrok, Cloudflare, personalizadas) desde la CLI. Inspeccionar las URL de túneles activos, configurar la autenticación y probar la accesibilidad externa." + "name": "CLI: Tunnels", + "description": "Start and stop tunnel connections (ngrok, Cloudflare, custom) from the CLI. Inspect active tunnel URLs, configure authentication, and test external reachability." }, "cli-backup-sync": { - "name": "CLI: Copia de seguridad y sincronización", - "description": "Realizar copias de seguridad y restaurar datos de OmniRoute desde la CLI. Desencadenar instantáneas incrementales, sincronizar con el almacenamiento en la nube, administrar programaciones de copias de seguridad y restaurar desde archivos de almacenamiento." + "name": "CLI: Backup & Sync", + "description": "Backup and restore OmniRoute data from the CLI. Trigger incremental snapshots, sync to cloud storage, manage backup schedules, and restore from archive files." }, "cli-policy-audit": { - "name": "CLI: Políticas y auditoría", - "description": "Inspeccionar los registros de auditoría, administrar las políticas de acceso, ver los datos de telemetría y revisar el historial de solicitudes desde la CLI. Filtrar por tipo de evento, usuario o rango de tiempo para flujos de trabajo de cumplimiento." + "name": "CLI: Policy & Audit", + "description": "Inspect audit logs, manage access policies, view telemetry data, and review request history from the CLI. Filter by event type, user, or time range for compliance workflows." }, "cli-batches": { - "name": "CLI: Lotes y archivos", - "description": "Enviar y supervisar trabajos de inferencia por lotes desde la CLI. Cargar y administrar archivos para el procesamiento por lotes, recuperar resultados e integrar canalizaciones por lotes con flujos de trabajo de CI/CD." + "name": "CLI: Batches & Files", + "description": "Submit and monitor batch inference jobs from the CLI. Upload and manage files for batch processing, retrieve results, and integrate batch pipelines with CI/CD workflows." }, "cli-eval": { - "name": "CLI: Evaluaciones", - "description": "Crear y ejecutar conjuntos de evaluación, ver el progreso de las pruebas de rendimiento en vivo, ver tarjetas de puntuación, comparar el rendimiento de los modelos e integrar ejecuciones de evaluación con flujos de trabajo de CI desde la CLI." + "name": "CLI: Evals", + "description": "Create and run evaluation suites, watch live benchmark progress, view scorecards, compare model performance, and integrate eval runs with CI workflows from the CLI." }, "cli-plugins-skills": { - "name": "CLI: Plugins, habilidades y memoria", - "description": "Administrar Omni Skills (enumerar, instalar, probar, eliminar), plugins (crear, configurar) y memoria persistente (buscar, agregar, borrar) desde la CLI." + "name": "CLI: Plugins, Skills & Memory", + "description": "Manage Omni Skills (list, install, test, remove), plugins (create, configure), and persistent memory (search, add, clear) from the CLI." }, "cli-setup": { - "name": "CLI: Configuración y ajustes", - "description": "Ejecutar la configuración inicial, configurar los ajustes globales de la CLI, administrar las variables de entorno, buscar actualizaciones y configurar el inicio automático a través de los comandos de configuración y ajuste de la CLI." + "name": "CLI: Setup & Config", + "description": "Run initial setup, configure global CLI settings, manage environment variables, check for updates, and configure autostart via the CLI setup and config commands." }, "cli-skill-collector": { - "name": "CLI: Recolector de habilidades de agentes", - "description": "Detectar herramientas de codificación de CLI instaladas (Claude Code, Codex, Cursor, Copilot, Cline y más), buscar en GitHub habilidades de agentes coincidentes e instalarlas en las herramientas detectadas a través de las API integradas de OmniRoute." + "name": "CLI: Agent Skill Collector", + "description": "Detect installed CLI coding tools (Claude Code, Codex, Cursor, Copilot, Cline and more), search GitHub for matching agent skills, and install them to the detected tools via OmniRoute's built-in APIs." }, "config-codex-cli": { - "name": "Configuración: Codex CLI", - "description": "Flujo de trabajo de agente paso a paso para configurar la CLI de OpenAI Codex en cualquier máquina (Linux, macOS, Windows) para usar OmniRoute como un backend compatible con OpenAI. Detecta el sistema operativo y el shell, escribe config.toml y 7 perfiles con nombre, establece variables de entorno y verifica la configuración." + "name": "Config: Codex CLI", + "description": "Step-by-step agent workflow to configure the OpenAI Codex CLI on any machine (Linux, macOS, Windows) to use OmniRoute as an OpenAI-compatible backend. Detects OS and shell, writes config.toml and 7 named profiles, sets environment variables, and verifies the setup." }, "omni-github-skills": { - "name": "Descubrimiento de habilidades de GitHub", - "description": "Buscar, puntuar, escanear e importar habilidades de agentes desde repositorios de GitHub que contengan SKILL.md, CLAUDE.md, .cursorrules y archivos de habilidades de agentes similares. Descubrir habilidades de la comunidad en más de 160 categorías de proveedores, evaluar la relevancia con puntuación heurística, buscar malware o secretos codificados e instalar en los directorios de agentes de Hermes, Claude Code, Gemini CLI o OpenCode." + "name": "GitHub Skill Discovery", + "description": "Search, score, scan, and import agent skills from GitHub repositories that contain SKILL.md, CLAUDE.md, .cursorrules, and similar agent skill files. Discover community skills across 160+ provider categories, evaluate relevance with heuristic scoring, check for malware or hardcoded secrets, and install into Hermes, Claude Code, Gemini CLI, or OpenCode agent directories." } }, - "pageTitle": "Habilidades de agentes", - "pageSubtitle": "Enseña a tu agente a operar OmniRoute: 23 áreas de API + 21 familias de CLI", + "pageTitle": "Agent Skills", + "pageSubtitle": "Teach your agent to operate OmniRoute — 23 API areas + 21 CLI families", "conceptCard": { "agent": { - "title": "Habilidades de agentes — Salientes", - "description": "Las habilidades de agentes son documentos SKILL.md legibles por máquina que los agentes de IA externos (Claude Code, Cursor, Copilot…) obtienen de GitHub para aprender a operar OmniRoute a través de REST o CLI. Son leídos por el agente, no ejecutados por OmniRoute.", - "crossLinkLabel": "Entender la diferencia →" + "title": "Agent Skills — Outbound", + "description": "Agent Skills are machine-readable SKILL.md documents that external AI agents (Claude Code, Cursor, Copilot…) fetch from GitHub to learn how to operate OmniRoute via REST or CLI. They are read by the agent, not executed by OmniRoute.", + "crossLinkLabel": "Understand the difference →" }, "omni": { - "title": "Omni Skills — Entrantes", - "description": "Las Omni Skills son herramientas de entorno aislado (sandbox) que OmniRoute inyecta en el contexto del modelo en cada solicitud. Son ejecutadas por OmniRoute, no leídas por el agente.", - "crossLinkLabel": "Entender la diferencia →" + "title": "Omni Skills — Inbound", + "description": "Omni Skills are sandbox tools that OmniRoute injects into the model's context on every request. They are executed by OmniRoute, not read by the agent.", + "crossLinkLabel": "Understand the difference →" }, "comparison": { - "colAgent": "Habilidades de agentes", + "colAgent": "Agent Skills", "colOmni": "Omni Skills", "whatIs": { - "label": "Qué es", - "agent": "SKILL.md legible por máquina que enseña a un agente externo a operar OmniRoute", - "omni": "Herramientas ejecutables que OmniRoute inyecta como herramientas en las solicitudes de LLM" + "label": "What it is", + "agent": "Machine-readable SKILL.md that teaches an external agent to operate OmniRoute", + "omni": "Executable tools that OmniRoute injects as tools into LLM requests" }, "direction": { - "label": "Dirección", - "agent": "Saliente: el agente externo aprende a controlar OmniRoute", - "omni": "Entrante: OmniRoute proporciona herramientas a los modelos que pasan a través de él" + "label": "Direction", + "agent": "Outbound — external agent learns to control OmniRoute", + "omni": "Inbound — OmniRoute gives tools to models passing through it" }, "executor": { - "label": "Ejecutor", - "agent": "Agente externo (lee markdown → actúa a través de API/CLI)", - "omni": "El propio OmniRoute (intercepta tool_calls, sandbox de Docker)" + "label": "Executor", + "agent": "External agent (reads markdown → acts via API/CLI)", + "omni": "OmniRoute itself (intercepts tool_calls, Docker sandbox)" }, "storage": { - "label": "Almacenamiento", - "agent": "Catálogo dinámico (/api/agent-skills) → SKILL.md en GitHub", + "label": "Storage", + "agent": "Dynamic catalog (/api/agent-skills) → SKILL.md on GitHub", "omni": "SQLite (SkillsMP / skills.sh / local)" }, "tagline": { - "label": "Lema", - "agent": "Enseña a tu agente a usar OmniRoute", - "omni": "Proporciona herramientas ejecutables a los modelos de OmniRoute" + "label": "Tagline", + "agent": "Teach your agent to use OmniRoute", + "omni": "Give executable tools to OmniRoute models" } } }, "filters": { - "category": "Categoría", - "area": "Área", - "searchPlaceholder": "Buscar habilidades…" + "category": "Category", + "area": "Area", + "searchPlaceholder": "Search skills…" }, "categoryApi": "API", "categoryCli": "CLI", "categoryConfig": "Config", - "filterAll": "Todo", - "coverageLabel": "Cobertura", - "mcpUrl": "URL de MCP", + "filterAll": "All", + "coverageLabel": "Coverage", + "mcpUrl": "MCP URL", "a2aLink": "A2A", - "mcpPrompt": "Añade este endpoint de MCP a tu agente para darle 37 herramientas de OmniRoute.", - "a2aPrompt": "Registra esta Tarjeta de Agente con tu orquestador para habilitar la delegación de tareas A2A.", - "refresh": "Actualizar", - "copyUrl": "Copiar URL", - "viewOnGithub": "Ver en GitHub", - "previewLoading": "Cargando documentación de la habilidad…", - "previewError": "Error al cargar la documentación de la habilidad.", - "previewEmpty": "Selecciona una habilidad para previsualizar su documentación.", - "generateButton": "Generar habilidades faltantes", + "mcpPrompt": "Add this MCP endpoint to your agent to give it 37 OmniRoute tools.", + "a2aPrompt": "Register this Agent Card with your orchestrator to enable A2A task delegation.", + "refresh": "Refresh", + "copyUrl": "Copy URL", + "viewOnGithub": "View on GitHub", + "previewLoading": "Loading skill documentation…", + "previewError": "Failed to load skill documentation.", + "previewEmpty": "Select a skill to preview its documentation.", + "generateButton": "Generate missing skills", "coverageBar": { - "complete": "Completo", - "partial": "Parcial" + "complete": "Complete", + "partial": "Partial" }, - "noSkillsFound": "No se encontraron habilidades que coincidan con tus filtros.", - "regenerateConfirm": "Esto regenerará todos los archivos SKILL.md faltantes. ¿Continuar?", - "regenerateRunning": "Regenerando habilidades…", - "regenerateSuccess": "Habilidades regeneradas con éxito.", - "regenerateError": "Error al regenerar las habilidades." + "noSkillsFound": "No skills found matching your filters.", + "regenerateConfirm": "This will regenerate all missing SKILL.md files. Continue?", + "regenerateRunning": "Regenerating skills…", + "regenerateSuccess": "Skills regenerated successfully.", + "regenerateError": "Failed to regenerate skills." }, "freeProviderRankingsPage": { - "title": "Clasificación de proveedores gratuitos", - "subtitle": "Los mejores proveedores gratuitos clasificados por las puntuaciones ELO de sus modelos en las tablas de clasificación de Arena AI", - "loading": "Cargando clasificaciones...", - "errorLoading": "Error al cargar las clasificaciones", - "emptyState": "Aún no hay clasificaciones disponibles. Los datos de Arena ELO se sincronizan al iniciar (diariamente); vuelve a consultar pronto o inicia una sincronización manual. Desactiva Arena ELO Sync en Feature Flags o establece ARENA_ELO_SYNC_ENABLED=false para excluirte.", - "bestModel": "Mejor", - "allCategories": "Todas las categorías", - "categoryDefault": "Predeterminado", - "categoryCoding": "Programación", - "categoryReview": "Revisión", - "categoryDocumentation": "Documentación", - "categoryDebugging": "Depuración", - "colRank": "Clasificación", - "colProvider": "Proveedor", - "colTopModel": "Mejor modelo", - "colScore": "Puntuación", - "colAvgScore": "Puntuación promedio", - "colModels": "Modelos", - "colType": "Tipo", - "filterConfiguredOnly": "Solo configurados", - "filterAvailableOnly": "Solo disponibles", - "filterAvailableOnlyHelp": "Ocultar proveedores cuyas conexiones estén todas limitadas por velocidad o sin cuota.", - "configuredOnly": "Solo configurados", - "configuredOnlyHint": "Mostrar solo proveedores con conexiones activas", - "noConfiguredProviders": "No se encontraron proveedores configurados. Agregue una conexión de proveedor primero.", - "colConfigured": "Estado", + "title": "Free Provider Rankings", + "subtitle": "Best free providers ranked by model ELO scores from Arena AI leaderboards", + "loading": "Loading rankings...", + "errorLoading": "Failed to load rankings", + "emptyState": "No rankings available yet. Arena ELO data syncs on startup (daily) — check back shortly, or trigger a manual sync. Disable Arena ELO Sync in Feature Flags or set ARENA_ELO_SYNC_ENABLED=false to opt out.", + "bestModel": "Best", + "allCategories": "All Categories", + "categoryDefault": "Default", + "categoryCoding": "Coding", + "categoryReview": "Review", + "categoryDocumentation": "Documentation", + "categoryDebugging": "Debugging", + "colRank": "Rank", + "colProvider": "Provider", + "colTopModel": "Top Model", + "colScore": "Score", + "colAvgScore": "Avg Score", + "colModels": "Models", + "colType": "Type", + "filterConfiguredOnly": "Configured only", + "filterAvailableOnly": "Available only", + "filterAvailableOnlyHelp": "Hide providers whose connections are all rate-limited or out of quota.", + "configuredOnly": "Configured Only", + "configuredOnlyHint": "Show only providers with active connections", + "noConfiguredProviders": "No configured providers found. Add a provider connection first.", + "colConfigured": "Status", "typeAll": "Todos los tipos", "typeNoauth": "Sin registro", "typeOauth": "Inicio de sesión OAuth", "typeApikey": "Clave API", - "sortTypeFirst": "Más fácil primero", - "sortTypeFirstHelp": "Agrupar por esfuerzo de registro (Sin registro → Inicio de sesión OAuth → Clave API), manteniendo el orden de calidad dentro de cada grupo", - "typeLegend": "Sin registro = configuración cero · Inicio de sesión OAuth = iniciar sesión con su propia cuenta · Clave API = use su propia clave o el nivel gratuito de ese proveedor" + "sortTypeFirst": "Más sencillos primero", + "sortTypeFirstHelp": "Group by signup effort (No Signup → OAuth Login → API Key), keeping quality order within each group", + "typeLegend": "No Signup = zero setup · OAuth Login = sign in with your own account · API Key = bring your own key or that provider's free tier" }, "discovery": { - "title": "Descubrimiento de proveedores", - "subtitle": "Escanear proveedores en busca de métodos de acceso gratuitos/ilimitados y revisar los hallazgos. De participación voluntaria, solo local.", - "scanLabel": "Proveedor a escanear", - "scanPlaceholder": "p. ej., huggingchat", - "scan": "Escanear", - "scanning": "Escaneando…", - "scanQueued": "Escaneo completado para {provider}.", - "scanFailed": "Error en el escaneo.", - "loadFailed": "Error al cargar los resultados del descubrimiento.", - "localOnlyNote": "Esta herramienta es solo local (loopback). Los escaneos se ejecutan desde esta máquina y nunca se puede acceder a ellos de forma remota.", - "verify": "Verificar", - "verifyFailed": "Error al verificar el hallazgo.", - "delete": "Eliminar", - "deleteFailed": "No se pudo eliminar el hallazgo.", - "deleteTitle": "Eliminar resultado de descubrimiento", - "deleteConfirm": "¿Eliminar el hallazgo de descubrimiento para {provider}? Esto no se puede deshacer.", - "emptyTitle": "Aún no hay resultados de descubrimiento", - "emptyDescription": "Ejecute un escaneo arriba para buscar métodos de acceso gratuitos en un proveedor.", - "risk": "Riesgo", - "method": "Método", - "auth": "Autenticación", - "feasibility": "Viabilidad", - "models": "Modelos" + "title": "Provider Discovery", + "subtitle": "Scan providers for free/unlimited access methods and review findings. Opt-in, local-only.", + "scanLabel": "Provider to scan", + "scanPlaceholder": "e.g. huggingchat", + "scan": "Scan", + "scanning": "Scanning…", + "scanQueued": "Scan complete for {provider}.", + "scanFailed": "Scan failed.", + "loadFailed": "Failed to load discovery results.", + "localOnlyNote": "This tool is local-only (loopback). Scans run from this machine and are never reachable remotely.", + "verify": "Verify", + "verifyFailed": "Failed to verify finding.", + "delete": "Delete", + "deleteFailed": "Failed to delete finding.", + "deleteTitle": "Delete discovery result", + "deleteConfirm": "Delete the discovery finding for {provider}? This cannot be undone.", + "emptyTitle": "No discovery results yet", + "emptyDescription": "Run a scan above to look for free access methods on a provider.", + "risk": "Risk", + "method": "Method", + "auth": "Auth", + "feasibility": "Feasibility", + "models": "Models" }, "noAuthProvider": { - "title": "No requiere autenticación", - "description": "Este proveedor está listo para usarse de inmediato — no se necesita registro ni clave API.", - "accountDescription": "Listo para usar — no se necesita registro. Añada cuentas para la rotación de límite de velocidad.", - "addAccount": "Añadir cuenta", - "accountName": "Cuenta {number} de {provider}", - "accounts": "Cuentas ({count})", - "adding": "Añadiendo...", - "autoGeneratedAccount": "Usando una cuenta generada automáticamente. Seleccione “{addLabel}” para la rotación de límite de velocidad.", - "configureProxy": "Configurar proxy", - "proxyConfigured": "Proxy configurado: {host}", - "removeAccount": "Eliminar cuenta", - "proxyForAccount": "Proxy para la cuenta {number}", - "saved": "Guardado", - "custom": "Personalizado", - "noSavedProxies": "No hay proxies guardados — añada uno en Configuración → Proxy", - "directConnection": "Directo (sin proxy)", + "title": "No authentication required", + "description": "This provider is ready to use immediately — no signup or API key needed.", + "accountDescription": "Ready to use — no signup needed. Add accounts for rate-limit rotation.", + "addAccount": "Add Account", + "accountName": "{provider} Account {number}", + "accounts": "Accounts ({count})", + "adding": "Adding...", + "autoGeneratedAccount": "Using an auto-generated account. Select “{addLabel}” for rate-limit rotation.", + "configureProxy": "Configure proxy", + "proxyConfigured": "Proxy configured: {host}", + "removeAccount": "Remove account", + "proxyForAccount": "Proxy for Account {number}", + "saved": "Saved", + "custom": "Custom", + "noSavedProxies": "No saved proxies — add one in Settings → Proxy", + "directConnection": "Direct (no proxy)", "host": "Host", - "port": "Puerto", - "usernameOptional": "Nombre de usuario (opcional)", - "passwordOptional": "Contraseña (opcional)", - "cancel": "Cancelar", - "saving": "Guardando...", - "save": "Guardar", - "createConnectionFailed": "No se pudo crear la conexión", - "updateConnectionFailed": "No se pudo actualizar la conexión", - "fetchProxiesFailed": "No se pudieron obtener los proxies", - "noSavedProxiesError": "No se encontraron proxies guardados. Añada proxies en Configuración → Proxy primero.", - "updateProviderFailed": "No se pudo actualizar el proveedor", - "providerEnabled": "{provider} habilitado", - "providerDisabled": "{provider} deshabilitado" + "port": "Port", + "usernameOptional": "Username (optional)", + "passwordOptional": "Password (optional)", + "cancel": "Cancel", + "saving": "Saving...", + "save": "Save", + "createConnectionFailed": "Failed to create connection", + "updateConnectionFailed": "Failed to update connection", + "fetchProxiesFailed": "Failed to fetch proxies", + "noSavedProxiesError": "No saved proxies found. Add proxies in Settings → Proxy first.", + "updateProviderFailed": "Failed to update provider", + "providerEnabled": "{provider} enabled", + "providerDisabled": "{provider} disabled" }, "gamification": { "leaderboardScopes": { - "allTime": "Histórico", - "weekly": "Semanal", - "monthly": "Mensual", - "tokensShared": "Tokens compartidos" + "allTime": "All Time", + "weekly": "Weekly", + "monthly": "Monthly", + "tokensShared": "Tokens Shared" }, - "leaderboardLoadFailed": "Error al cargar la tabla de clasificación (HTTP {status})", - "scope": "Ámbito", - "tokensShared": "tokens compartidos", - "points": "puntos", - "rank": "Posición", - "name": "Nombre", - "score": "Puntuación", - "leaderboardEmpty": "Aún no hay entradas para este ámbito. ¡Empieza a usar OmniRoute para aparecer en la tabla de clasificación!", - "profileLoadFailed": "Error al cargar los datos del perfil", + "leaderboardLoadFailed": "Failed to load leaderboard (HTTP {status})", + "scope": "Scope", + "tokensShared": "tokens shared", + "points": "points", + "rank": "Rank", + "name": "Name", + "score": "Score", + "leaderboardEmpty": "No entries yet for this scope. Start using OmniRoute to appear on the leaderboard!", + "profileLoadFailed": "Failed to load profile data", "levelTitles": { - "beginner": "Principiante", - "explorer": "Explorador", - "expert": "Experto", - "master": "Maestro", - "legend": "Leyenda" + "beginner": "Beginner", + "explorer": "Explorer", + "expert": "Expert", + "master": "Master", + "legend": "Legend" }, "tiers": { - "bronze": "Bronce", - "silver": "Plata", - "gold": "Oro", - "platinum": "Platino", - "diamond": "Diamante" + "bronze": "Bronze", + "silver": "Silver", + "gold": "Gold", + "platinum": "Platinum", + "diamond": "Diamond" }, - "tierLabel": "Nivel: {tier}", - "dayStreak": "Racha de {count} días", - "levelProgress": "Nivel {current} → {next}", - "totalXpEarned": "{count} XP totales obtenidos", - "maintainStreak": "¡Sigue usando OmniRoute todos los días para mantener tu racha!", - "badgesTitle": "Insignias ({earned}/{total})", - "noBadges": "Aún no hay insignias disponibles.", - "hiddenBadge": "Logro oculto", - "earnedDate": "Obtenido el {date}", - "earnedOn": "Obtenido el {date}", - "category": "Categoría", + "tierLabel": "Tier: {tier}", + "dayStreak": "{count}-day streak", + "levelProgress": "Level {current} → {next}", + "totalXpEarned": "{count} total XP earned", + "maintainStreak": "Keep using OmniRoute every day to maintain your streak!", + "badgesTitle": "Badges ({earned}/{total})", + "noBadges": "No badges are available yet.", + "hiddenBadge": "Hidden achievement", + "earnedDate": "Earned {date}", + "earnedOn": "Earned on {date}", + "category": "Category", "rarities": { - "common": "Común", - "uncommon": "Poco común", - "rare": "Raro", - "epic": "Épico", - "legendary": "Legendario" + "common": "Common", + "uncommon": "Uncommon", + "rare": "Rare", + "epic": "Epic", + "legendary": "Legendary" }, "categories": { - "usage": "Uso", - "sharing": "Compartir", - "contribution": "Contribución", - "streak": "Racha", - "rare": "Logros raros" + "usage": "Usage", + "sharing": "Sharing", + "contribution": "Contribution", + "streak": "Streak", + "rare": "Rare achievements" }, "badges": { "first-token": { - "name": "Primer token", - "description": "Realizaste tu primera solicitud de API", - "criteria": "Completa tu primera solicitud de API a través de OmniRoute." + "name": "First Token", + "description": "Made your first API request", + "criteria": "Complete your first API request through OmniRoute." }, "token-consumer": { - "name": "Consumidor de tokens", - "description": "Realizaste 1,000 solicitudes de API", - "criteria": "Completa 1,000 solicitudes de API a través de OmniRoute." + "name": "Token Consumer", + "description": "Made 1,000 API requests", + "criteria": "Complete 1,000 API requests through OmniRoute." }, "token-machine": { - "name": "Máquina de tokens", - "description": "Realizaste 10,000 solicitudes de API", - "criteria": "Completa 10,000 solicitudes de API a través de OmniRoute." + "name": "Token Machine", + "description": "Made 10,000 API requests", + "criteria": "Complete 10,000 API requests through OmniRoute." }, "token-whale": { - "name": "Ballena de tokens", - "description": "Realizaste 100,000 solicitudes de API", - "criteria": "Completa 100,000 solicitudes de API a través de OmniRoute." + "name": "Token Whale", + "description": "Made 100,000 API requests", + "criteria": "Complete 100,000 API requests through OmniRoute." }, "generous": { - "name": "Generoso", - "description": "Compartiste 1,000 tokens con otros", - "criteria": "Comparte un total de 1,000 tokens con otros usuarios." + "name": "Generous", + "description": "Shared 1,000 tokens with others", + "criteria": "Share a total of 1,000 tokens with other users." }, "philanthropist": { - "name": "Filántropo", - "description": "Compartiste 10,000 tokens con otros", - "criteria": "Comparte un total de 10,000 tokens con otros usuarios." + "name": "Philanthropist", + "description": "Shared 10,000 tokens with others", + "criteria": "Share a total of 10,000 tokens with other users." }, "token-santa": { - "name": "Santa de los tokens", - "description": "Compartiste 100,000 tokens con otros", - "criteria": "Comparte un total de 100,000 tokens con otros usuarios." + "name": "Token Santa", + "description": "Shared 100,000 tokens with others", + "criteria": "Share a total of 100,000 tokens with other users." }, "community-hero": { - "name": "Héroe de la comunidad", - "description": "Compartiste 1,000,000 de tokens con otros", - "criteria": "Comparte un total de 1,000,000 de tokens con otros usuarios." + "name": "Community Hero", + "description": "Shared 1,000,000 tokens with others", + "criteria": "Share a total of 1,000,000 tokens with other users." }, "explorer": { - "name": "Explorador", - "description": "Utilizaste 5 proveedores diferentes", - "criteria": "Utiliza al menos 5 proveedores de IA diferentes." + "name": "Explorer", + "description": "Used 5 different providers", + "criteria": "Use at least 5 different AI providers." }, "polyglot": { - "name": "Políglota", - "description": "Utilizaste 10 modelos diferentes", - "criteria": "Utiliza al menos 10 modelos de IA diferentes." + "name": "Polyglot", + "description": "Used 10 different models", + "criteria": "Use at least 10 different AI models." }, "architect": { - "name": "Arquitecto", - "description": "Creaste 3 rutas combinadas", - "criteria": "Crea 3 rutas combinadas." + "name": "Architect", + "description": "Created 3 combo routes", + "criteria": "Create 3 combo routes." }, "speedster": { - "name": "Velocista", - "description": "Mantuviste una latencia promedio inferior a 500 ms en 100 solicitudes", - "criteria": "Mantén la latencia promedio por debajo de 500 ms en 100 solicitudes." + "name": "Speedster", + "description": "Maintained under 500 ms average latency for 100 requests", + "criteria": "Keep average latency below 500 ms across 100 requests." }, "resilient": { - "name": "Resiliente", - "description": "Mantuvo un 100% de tiempo de actividad durante 7 días", - "criteria": "Mantener un 100% de tiempo de actividad durante 7 días consecutivos." + "name": "Resilient", + "description": "Maintained 100% uptime for 7 days", + "criteria": "Maintain 100% uptime for 7 consecutive days." }, "daily-user": { - "name": "Usuario diario", - "description": "Activo durante 3 días consecutivos", - "criteria": "Usar OmniRoute durante 3 días consecutivos." + "name": "Daily User", + "description": "Active for 3 consecutive days", + "criteria": "Use OmniRoute for 3 consecutive days." }, "weekly-warrior": { - "name": "Guerrero semanal", - "description": "Activo durante 7 días consecutivos", - "criteria": "Usar OmniRoute durante 7 días consecutivos." + "name": "Weekly Warrior", + "description": "Active for 7 consecutive days", + "criteria": "Use OmniRoute for 7 consecutive days." }, "monthly-master": { - "name": "Maestro mensual", - "description": "Activo durante 30 días consecutivos", - "criteria": "Usar OmniRoute durante 30 días consecutivos." + "name": "Monthly Master", + "description": "Active for 30 consecutive days", + "criteria": "Use OmniRoute for 30 consecutive days." }, "unstoppable": { - "name": "Imparable", - "description": "Activo durante 365 días consecutivos", - "criteria": "Usar OmniRoute durante 365 días consecutivos." + "name": "Unstoppable", + "description": "Active for 365 consecutive days", + "criteria": "Use OmniRoute for 365 consecutive days." }, "early-adopter": { - "name": "Pionero", - "description": "Se unió dentro del primer mes de la gamificación", - "criteria": "Unirse dentro del primer mes tras el lanzamiento de la gamificación." + "name": "Early Adopter", + "description": "Joined within the first month of gamification", + "criteria": "Join within the first month after gamification launches." }, "bug-hunter": { - "name": "Cazador de errores", - "description": "Reportó 5 problemas", - "criteria": "Reportar 5 problemas válidos." + "name": "Bug Hunter", + "description": "Reported 5 issues", + "criteria": "Report 5 valid issues." }, "contributor": { - "name": "Colaborador", - "description": "Fusionó 1 pull request", - "criteria": "Tener 1 pull request fusionado en OmniRoute." + "name": "Contributor", + "description": "Merged 1 pull request", + "criteria": "Have 1 pull request merged into OmniRoute." }, "community-leader": { - "name": "Líder de la comunidad", - "description": "Alcanzó el top 10 en cualquier tabla de clasificación", - "criteria": "Alcanzar el top 10 en cualquier tabla de clasificación." + "name": "Community Leader", + "description": "Reached the top 10 on any leaderboard", + "criteria": "Reach the top 10 on any leaderboard." }, "secret-badge": { "name": "???", - "description": "Un logro oculto te espera...", - "criteria": "Completa el logro oculto para revelar esta insignia." + "description": "A hidden achievement awaits...", + "criteria": "Complete the hidden achievement to reveal this badge." } } }, "featureFlags": { "title": "Feature Flags", - "activeCount": "{count} activos", - "inactiveCount": "{count} inactivos", - "dbOverrideCount": "{count} sobreescrituras de BD", - "searchPlaceholder": "Buscar flags...", + "activeCount": "{count} active", + "inactiveCount": "{count} inactive", + "dbOverrideCount": "{count} DB overrides", + "searchPlaceholder": "Search flags...", "categories": { - "all": "Todos", - "security": "Seguridad", - "network": "Red", - "policies": "Políticas", - "runtime": "Tiempo de ejecución", + "all": "All", + "security": "Security", + "network": "Network", + "policies": "Policies", + "runtime": "Runtime", "cli": "CLI", - "health": "Salud", - "requiresRestart": "Requiere reinicio" + "health": "Health", + "requiresRestart": "Requires Restart" }, - "categoryLabel": "Categoría: {category}", - "caution": "Precaución", - "danger": "Peligro", - "requiresRestart": "Requiere reinicio", - "source": "Origen", - "resetFlag": "Restablecer {label} al valor predeterminado", - "reset": "Restablecer", - "loadFailed": "Error al cargar los indicadores de función", - "updateFailedHttp": "Error al actualizar el indicador: HTTP {status}", - "updateFailed": "Error al actualizar el indicador", - "restartFailedHttp": "Error al reiniciar: HTTP {status}", - "restartFailed": "Error al reiniciar", - "resetOverridesFailedHttp": "Error al restablecer las anulaciones: HTTP {status}", - "resetOverridesFailed": "Error al restablecer las anulaciones", - "restartRequiredCount": "{count, plural, one {# cambio requiere} other {# cambios requieren}} un reinicio del servidor para surtir efecto.", - "restartRequiredDescription": "Estos indicadores solo se aplican después de que se recargue el proceso. Reinicie ahora o continúe editando — los indicadores pendientes permanecerán en cola hasta que confirme.", - "restartServer": "Reiniciar servidor", - "cancel": "Cancelar", - "restarting": "Reiniciando…", - "confirmRestart": "Confirmar reinicio", - "restartViewDescription": "Estos indicadores solo surten efecto después de reiniciar el servidor. Actívelos o desactívelos como cualquier otro indicador — el cambio se guarda inmediatamente, pero el nuevo valor solo se lee al iniciar el proceso. Use el banner Reiniciar servidor de arriba para aplicarlo.", - "retry": "Reintentar", - "noSearchResults": "Ningún indicador coincide con su búsqueda", - "resetAllOverrides": "Restablecer todas las anulaciones", - "confirmResetOverrides": "¿Restablecer las {count} anulaciones de la base de datos?", - "resetting": "Restableciendo...", - "confirmReset": "Confirmar restablecimiento", + "categoryLabel": "Category: {category}", + "caution": "Caution", + "danger": "Danger", + "requiresRestart": "Requires restart", + "source": "Source", + "resetFlag": "Reset {label} to default", + "reset": "Reset", + "loadFailed": "Failed to load feature flags", + "updateFailedHttp": "Failed to update flag: HTTP {status}", + "updateFailed": "Failed to update flag", + "restartFailedHttp": "Restart failed: HTTP {status}", + "restartFailed": "Restart failed", + "resetOverridesFailedHttp": "Failed to reset overrides: HTTP {status}", + "resetOverridesFailed": "Failed to reset overrides", + "restartRequiredCount": "{count, plural, one {# change requires} other {# changes require}} a server restart to take effect.", + "restartRequiredDescription": "These flags only apply after the process reloads. Restart now or continue editing — pending flags stay queued until you confirm.", + "restartServer": "Restart Server", + "cancel": "Cancel", + "restarting": "Restarting…", + "confirmRestart": "Confirm Restart", + "restartViewDescription": "These flags only take effect after the server restarts. Toggle them like any other flag — the change is persisted immediately, but the new value is only read at process startup. Use the Restart Server banner above to apply.", + "retry": "Retry", + "noSearchResults": "No flags match your search", + "resetAllOverrides": "Reset All Overrides", + "confirmResetOverrides": "Reset all {count} DB override(s)?", + "resetting": "Resetting...", + "confirmReset": "Confirm Reset", "enumValues": { - "off": "Desactivado", - "warn": "Advertir", - "block": "Bloquear", - "redact": "Censurar", - "disabled": "Deshabilitado", + "off": "Off", + "warn": "Warn", + "block": "Block", + "redact": "Redact", + "disabled": "Disabled", "dual": "Dual", "alias": "Alias", - "canonical": "Canónico" + "canonical": "Canonical" }, "definitions": { "REQUIRE_API_KEY": { - "description": "Requerir una clave de API para todas las solicitudes entrantes." + "description": "Require an API key for all incoming requests." }, "INPUT_SANITIZER_ENABLED": { - "description": "Habilitar la desinfección de entradas para todas las solicitudes." + "description": "Enable input sanitization for all requests." }, "INJECTION_GUARD_MODE": { - "description": "Establecer el modo de protección contra inyección de prompts." + "description": "Set the prompt-injection guard mode." }, "PII_REDACTION_ENABLED": { - "description": "Ocultar información de identificación personal de las solicitudes." + "description": "Redact personally identifiable information from requests." }, "PII_RESPONSE_SANITIZATION": { - "description": "Sanear la información de identificación personal en las respuestas del proveedor." + "description": "Sanitize personally identifiable information in provider responses." }, "PII_RESPONSE_SANITIZATION_MODE": { - "description": "Elegir cómo se gestiona la PII de las respuestas: redact la reemplaza, warn solo la registra, block rechaza la respuesta y off desactiva el saneamiento." + "description": "Choose how response PII is handled: redact replaces it, warn only logs it, block rejects the response, and off disables sanitization." }, "OUTBOUND_SSRF_GUARD_ENABLED": { - "description": "Bloquear solicitudes salientes a rangos de IP privados o internos." + "description": "Block outbound requests to private or internal IP ranges." }, "ALLOW_API_KEY_REVEAL": { - "description": "Permitir que los usuarios autenticados del panel revelen las claves de API almacenadas en lugar de ver solo valores enmascarados." + "description": "Allow authenticated dashboard users to reveal stored API keys instead of seeing masked values only." }, "ENABLE_TLS_FINGERPRINT": { - "description": "Habilitar el modo sigiloso de huella digital TLS." + "description": "Enable TLS fingerprint stealth mode." }, "ONEPROXY_ENABLED": { - "description": "Habilitar el proxy de solicitudes a través de 1proxy." + "description": "Enable request proxying through 1proxy." }, "PROXY_AUTO_SELECT_ENABLED": { - "description": "Cuando no hay ningún proxy asignado a una conexión, seleccionar automáticamente el primer proxy de registro que funcione. Desactivado de forma predeterminada porque, de lo contrario, un proxy de registro se convierte en una alternativa global para todo el tráfico (#3332)." + "description": "When no proxy is assigned to a connection, automatically select the first working registry proxy. Off by default because otherwise one registry proxy becomes a global fallback for all traffic (#3332)." }, "OMNIROUTE_CONTROL_PLANE_PROXY_DIRECT_FALLBACK": { - "description": "Permitir que los flujos de OAuth y validación de proveedores omitan un proxy fijado cuando fallen las comprobaciones de accesibilidad del proxy. Desactivado de forma predeterminada porque esto puede cambiar la IP de salida de la cuenta." + "description": "Allow OAuth and provider-validation flows to bypass a pinned proxy when proxy reachability checks fail. Off by default because this can change the account egress IP." }, "MITM_DISABLE_TLS_VERIFY": { - "description": "Deshabilitar la verificación de certificados TLS para el proxy MITM." + "description": "Disable TLS certificate verification for the MITM proxy." }, "OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS": { - "description": "Permitir URL de proveedores que apunten a redes privadas o internas." + "description": "Allow provider URLs that point to private or internal networks." }, "OMNIROUTE_ALLOW_LOCAL_PROVIDER_URLS": { - "description": "Permitir proveedores en localhost, LAN y rangos de IP privados. Esto es necesario para modelos locales compatibles con OpenAI y está habilitado de forma predeterminada. Los endpoints de metadatos en la nube como 169.254.169.254 permanecen bloqueados." + "description": "Allow providers on localhost, LAN, and private IP ranges. This is required for local OpenAI-compatible models and enabled by default. Cloud-metadata endpoints such as 169.254.169.254 remain blocked." }, "ENABLE_CC_COMPATIBLE_PROVIDER": { - "description": "Habilitar el modo de proveedor compatible con Claude Code." + "description": "Enable Claude Code-compatible provider mode." }, "TOOL_POLICY_MODE": { - "description": "Establecer el modo de aplicación de la directiva de uso de herramientas." + "description": "Set the tool-use policy enforcement mode." }, "RATE_LIMIT_AUTO_ENABLE": { - "description": "Habilitar automáticamente la limitación de velocidad según los patrones de uso." + "description": "Automatically enable rate limiting based on usage patterns." }, "ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE": { - "description": "Permitir múltiples conexiones para cada nodo de compatibilidad." + "description": "Allow multiple connections for each compatibility node." }, "RESPONSES_PASSTHROUGH_DROP_COMMENTARY": { - "description": "Eliminar los elementos de salida de la fase de comentarios internos de los flujos de paso a través de Responses API antes de reenviarlos a los clientes. Deshabilite este indicador para recibir comentarios sin procesar del flujo ascendente." + "description": "Remove internal commentary-phase output items from Responses API passthrough streams before forwarding them to clients. Disable this flag to receive raw upstream commentary." }, "OMNIROUTE_MCP_ENFORCE_SCOPES": { - "description": "Aplicar restricciones de ámbito para el acceso a herramientas MCP." + "description": "Enforce scope restrictions for MCP tool access." }, "OMNIROUTE_MCP_COMPRESS_DESCRIPTIONS": { - "description": "Comprimir las descripciones de las herramientas MCP para reducir el uso de tokens." + "description": "Compress MCP tool descriptions to reduce token usage." }, "OMNIROUTE_ENABLE_RUNTIME_BACKGROUND_TASKS": { - "description": "Habilitar el procesamiento de tareas en segundo plano en tiempo de ejecución." + "description": "Enable background-task processing at runtime." }, "OMNIROUTE_DISABLE_BACKGROUND_SERVICES": { - "description": "Deshabilitar todos los servicios en segundo plano, incluida la actualización de cuotas y la sincronización." + "description": "Disable all background services, including quota refresh and synchronization." }, "OMNIROUTE_RTK_TRUST_PROJECT_FILTERS": { - "description": "Confiar en los filtros RTK a nivel de proyecto sin validación." + "description": "Trust project-level RTK filters without validation." }, "OMNIROUTE_ENABLE_LIVE_WS": { - "description": "Iniciar el servidor WebSocket del panel en tiempo real al importar en el puerto de bucle invertido 20132. Establezca el indicador en 0 o false para deshabilitarlo. La exposición a la LAN también requiere LIVE_WS_HOST=0.0.0.0 y LIVE_WS_ALLOWED_ORIGINS." + "description": "Start the real-time dashboard WebSocket server on import at loopback port 20132. Set the flag to 0 or false to disable it. LAN exposure also requires LIVE_WS_HOST=0.0.0.0 and LIVE_WS_ALLOWED_ORIGINS." }, "OMNIROUTE_CODEX_WS_ENABLED": { - "description": "Permitir que Codex use Responses a través de WebSocket. Cuando está deshabilitado, Codex recurre a HTTP Responses." + "description": "Allow Codex to use Responses over WebSocket. When disabled, Codex falls back to HTTP Responses." }, "OMNIROUTE_EMERGENCY_FALLBACK": { - "description": "Enrutar las solicitudes con presupuesto agotado al proveedor y modelo de respaldo gratuito de emergencia." + "description": "Route budget-exhausted requests to the emergency free fallback provider and model." }, "STREAM_RECOVERY_ENABLED": { - "description": "Reintentar de forma transparente los flujos SSE ascendentes truncados antes de que los bytes de respuesta lleguen al cliente." + "description": "Retry truncated upstream SSE streams transparently before any response bytes reach the client." }, "STREAM_RECOVERY_MIDSTREAM_ENABLED": { - "description": "Permitir que la recuperación de flujo vuelva a solicitar la respuesta y la una después de que los bytes ya hayan llegado al cliente." + "description": "Allow stream recovery to request the response again and stitch it after bytes have already reached the client." }, "MODEL_CATALOG_INCLUDE_NAMES": { - "description": "Incluir campos de nombres descriptivos en las respuestas de /v1/models. Deshabilite esto para clientes que solo aceptan ID de modelos." + "description": "Include display-friendly name fields in /v1/models responses. Disable this for clients that accept model IDs only." }, "MODELS_CATALOG_PREFIX_MODE": { - "description": "Controlar los prefijos de ID de modelo en /v1/models: dual emite prefijos canónicos y de alias, alias emite solo prefijos cortos y canonical emite solo ID de proveedor completos." + "description": "Control model-ID prefixes in /v1/models: dual emits alias and canonical prefixes, alias emits short prefixes only, and canonical emits full provider IDs only." }, "ARENA_ELO_SYNC_ENABLED": { - "description": "Sincronizar periódicamente los datos ELO de la tabla de clasificación de Arena AI para las clasificaciones de inteligencia de modelos." + "description": "Periodically synchronize Arena AI leaderboard ELO data for model-intelligence rankings." }, "CLI_COMPAT_ALL": { - "description": "Habilitar el modo de compatibilidad para todos los clientes de CLI." + "description": "Enable compatibility mode for all CLI clients." }, "MODEL_ALIAS_COMPAT_ENABLED": { - "description": "Habilitar la capa de compatibilidad de alias de modelos." + "description": "Enable the model-alias compatibility layer." }, "PRICING_SYNC_ENABLED": { - "description": "Sincronizar los datos de precios automáticamente. La variable de entorno PRICING_SYNC_ENABLED también debe ser true." + "description": "Synchronize pricing data automatically. The PRICING_SYNC_ENABLED environment variable must also be true." }, "OMNIROUTE_AUTO_SYNC_CODEX_PROFILES": { - "description": "Después de la sincronización de modelos de proveedores, regenerar los perfiles ~/.codex/*.config.toml a partir del catálogo en vivo. Esto nunca cambia la configuración activa o predeterminada de Codex y está desactivado de forma predeterminada." + "description": "After provider-model synchronization, regenerate ~/.codex/*.config.toml profiles from the live catalog. This never changes the active or default Codex configuration and is off by default." }, "OMNIROUTE_AUTO_SYNC_CLAUDE_PROFILES": { - "description": "Después de la sincronización de modelos de proveedores, regenerar los perfiles ~/.claude/profiles//settings.json a partir del catálogo en vivo. Esto nunca cambia la configuración activa o predeterminada de Claude y está desactivado de forma predeterminada." + "description": "After provider-model synchronization, regenerate ~/.claude/profiles//settings.json profiles from the live catalog. This never changes the active or default Claude configuration and is off by default." }, "OMNIROUTE_DISABLE_LOCAL_HEALTHCHECK": { - "description": "Deshabilitar el endpoint de comprobación de estado de la instancia local." + "description": "Disable the local instance health-check endpoint." }, "OMNIROUTE_DISABLE_TOKEN_HEALTHCHECK": { - "description": "Deshabilitar la comprobación de estado de validación de tokens." + "description": "Disable the token-validation health check." }, "SKILLS_SANDBOX_NETWORK_ENABLED": { - "description": "Habilitar el acceso a la red en el sandbox de habilidades." + "description": "Enable network access in the skills sandbox." } } }, "comboControl": { - "title": "Centro de control Combo", + "title": "Combo Control Center", "unavailable": "Combo Control Center unavailable", "backToCombos": "Back to Combos", "loadFailed": "Failed to load combo control center", @@ -11774,206 +11794,206 @@ "success": "Success", "latency": "Latency", "quota": "Quota", - "rangeWindow": "Ventana de {range}", - "runtimeHealthBlend": "combinación de tiempo de ejecución/salud", - "averageResponseTime": "tiempo de respuesta promedio", - "worstQuota": "Peor cuota", - "providerAccountTelemetry": "telemetría de proveedor/cuenta", - "overview": "Información general", - "overviewDescription": "Estrategia, estado de tiempo de ejecución y enlaces de control para este combo.", - "strategy": "Estrategia", - "targets": "Objetivos", - "providers": "Proveedores", - "targetCounts": "{configured} configurados · {resolved} resueltos", - "healthReasons": "Motivos de salud", + "rangeWindow": "{range} window", + "runtimeHealthBlend": "runtime/health blend", + "averageResponseTime": "average response time", + "worstQuota": "Worst quota", + "providerAccountTelemetry": "provider/account telemetry", + "overview": "Overview", + "overviewDescription": "Strategy, runtime status and control links for this combo.", + "strategy": "Strategy", + "targets": "Targets", + "providers": "Providers", + "targetCounts": "{configured} configured · {resolved} resolved", + "healthReasons": "Health reasons", "healthReason": { - "noRecentTraffic": "Sin tráfico reciente del combo", - "lowSuccessRate": "Tasa de éxito baja", - "successBelowTarget": "Tasa de éxito por debajo del objetivo", - "highFallbackRate": "Tasa de fallback alta", - "elevatedFallbackRate": "Tasa de fallback elevada", - "quotaExhausted": "Al menos una cuota está agotada", - "quotaNearlyExhausted": "La cuota está casi agotada", - "quotaGettingLow": "La cuota se está agotando", - "trafficHighlySkewed": "La distribución del tráfico está muy sesgada", - "comboHealthy": "El combo parece saludable" + "noRecentTraffic": "No recent combo traffic", + "lowSuccessRate": "Low success rate", + "successBelowTarget": "Success rate below target", + "highFallbackRate": "High fallback rate", + "elevatedFallbackRate": "Elevated fallback rate", + "quotaExhausted": "At least one quota is exhausted", + "quotaNearlyExhausted": "Quota is nearly exhausted", + "quotaGettingLow": "Quota is getting low", + "trafficHighlySkewed": "Traffic distribution is highly skewed", + "comboHealthy": "Combo looks healthy" }, - "configuredTargets": "Objetivos configurados", - "configuredTargetsDescription": "Los pasos del combo guardados, enriquecidos con datos de salud coincidentes cuando estén disponibles.", - "noConfiguredTargets": "No hay destinos configurados.", - "runtimeConfig": "Configuración de runtime", - "runtimeConfigDescription": "Configuración avanzada seleccionada para este combo.", - "noRuntimeConfig": "Sin configuración de runtime personalizada.", - "resolvedTargets": "Destinos de runtime resueltos", - "resolvedTargetsDescription": "Destinos aplanados después de la resolución de combos anidados y métricas a nivel de destino.", - "noResolvedTargetHealth": "Aún no hay estado de salud de destino resuelto.", - "quotaDistribution": "Cuota y distribución", - "noQuotaSnapshots": "No hay capturas de cuota para esta ventana de combo.", - "usageSkew": "Desviación de uso", - "recentDecisions": "Decisiones de enrutamiento recientes", - "recentDecisionsDescription": "Registros de llamadas recientes filtrados por este nombre de combo. Abra Analytics para una explicabilidad completa.", - "noRecentLogs": "No se encontraron registros de llamadas de combo recientes.", - "quickLinks": "Enlaces rápidos", - "comboHealth": "Salud del combo", - "callLogs": "Registros de llamadas", - "costs": "Costos", + "configuredTargets": "Configured targets", + "configuredTargetsDescription": "The saved combo steps, enriched with matching health data when available.", + "noConfiguredTargets": "No targets configured.", + "runtimeConfig": "Runtime config", + "runtimeConfigDescription": "Selected advanced settings for this combo.", + "noRuntimeConfig": "No custom runtime config.", + "resolvedTargets": "Resolved runtime targets", + "resolvedTargetsDescription": "Flattened targets after nested combo resolution and target-level metrics.", + "noResolvedTargetHealth": "No resolved target health yet.", + "quotaDistribution": "Quota and distribution", + "noQuotaSnapshots": "No quota snapshots for this combo window.", + "usageSkew": "Usage skew", + "recentDecisions": "Recent routing decisions", + "recentDecisionsDescription": "Recent call logs filtered by this combo name. Open Analytics for full explainability.", + "noRecentLogs": "No recent combo call logs found.", + "quickLinks": "Quick links", + "comboHealth": "Combo Health", + "callLogs": "Call Logs", + "costs": "Costs", "playground": "Playground", - "nestedCombo": "Combo anidado", - "modelTarget": "Destino del modelo", - "weight": "{value}% de peso", - "comboReference": "Referencia de combo", - "accountShort": "cuenta {id}", - "keyShort": "clave {id}", - "stepShort": "paso {id}", - "dynamic": "dinámico", - "unknown": "desconocido", - "unknownProvider": "proveedor desconocido", - "unknownModel": "modelo desconocido", - "resolvedTargetMetrics": "{requests} req · {success} exitosas · {latency} · cuota {quota}" + "nestedCombo": "Nested combo", + "modelTarget": "Model target", + "weight": "{value}% weight", + "comboReference": "Combo reference", + "accountShort": "account {id}", + "keyShort": "key {id}", + "stepShort": "step {id}", + "dynamic": "dynamic", + "unknown": "unknown", + "unknownProvider": "unknown provider", + "unknownModel": "unknown model", + "resolvedTargetMetrics": "{requests} req · {success} success · {latency} · quota {quota}" }, "usageLimits": { - "usdUsageQuota": "Cuota de uso en USD", - "usdUsageQuotaDescription": "Bloquea esta clave con un error de API 400 después de que su gasto local en USD alcance la cuota diaria o semanal configurada.", - "dailyQuotaUsd": "Cuota diaria (USD)", - "weeklyQuotaUsd": "Cuota semanal (USD)", - "quotaWindowDescription": "La cuota semanal sigue el restablecimiento semanal almacenado en caché de Claude cuando está disponible; de lo contrario, recurre a una ventana móvil de 7 días. La cuota diaria utiliza el día calendario de Fortaleza.", - "apiKeyUsdQuota": "Cuota en USD de la clave de API", - "apiKeyUsdQuotaDescription": "Cuando está habilitado, @@om-usage devuelve la cuota diaria, la cuota semanal, el gasto diario y el gasto semanal en USD. El semanal sigue el restablecimiento de Claude almacenado en caché cuando está disponible.", - "enabled": "Habilitado", - "disabled": "Deshabilitado", - "dailySpend": "Gasto diario", - "weeklySpend": "Gasto semanal", - "dailyQuota": "Cuota diaria", - "weeklyQuota": "Cuota semanal", - "fallbackRollingDays": "alternativa: {days} días móviles", - "fallbackRollingDaysShort": "Alternativa móvil {days}d", - "resetDueNow": "reinicio ahora", - "resetsInHours": "se reinicia en {count}h", - "resetsInDays": "se reinicia en {count}d", - "saveFailed": "Error al guardar los límites de uso", - "saving": "Guardando...", - "saveQuota": "Guardar cuota", - "loadUsdCostsFailed": "Error al cargar los costos en USD", - "usdCost": "Costo en USD", - "close": "Cerrar", - "loadingUsdCosts": "Cargando costos en USD", - "used": "Usado", - "quotaUsed": "Cuota usada", + "usdUsageQuota": "USD usage quota", + "usdUsageQuotaDescription": "Blocks this key with a 400 API error after its local USD spend reaches the configured daily or weekly quota.", + "dailyQuotaUsd": "Daily quota (USD)", + "weeklyQuotaUsd": "Weekly quota (USD)", + "quotaWindowDescription": "Weekly quota follows the cached Claude weekly reset when available; otherwise it falls back to a rolling 7 day window. Daily quota uses the Fortaleza calendar day.", + "apiKeyUsdQuota": "API key USD quota", + "apiKeyUsdQuotaDescription": "When enabled, @@om-usage returns daily quota, weekly quota, daily spend, and weekly spend in USD. Weekly follows the cached Claude reset when available.", + "enabled": "Enabled", + "disabled": "Disabled", + "dailySpend": "Daily spend", + "weeklySpend": "Weekly spend", + "dailyQuota": "Daily quota", + "weeklyQuota": "Weekly quota", + "fallbackRollingDays": "fallback: rolling {days} days", + "fallbackRollingDaysShort": "Fallback rolling {days}d", + "resetDueNow": "reset due now", + "resetsInHours": "resets in {count}h", + "resetsInDays": "resets in {count}d", + "saveFailed": "Failed to save usage limits", + "saving": "Saving...", + "saveQuota": "Save quota", + "loadUsdCostsFailed": "Failed to load USD costs", + "usdCost": "USD Cost", + "close": "Close", + "loadingUsdCosts": "Loading USD costs", + "used": "Used", + "quotaUsed": "Quota used", "estimatedFullQuota": "Est. 100%", - "rows": "Filas", - "window": "Ventana", - "unknown": "desconocido", - "fromRecordedReset": "Desde el reinicio registrado de {quota}", - "fromObservedReset": "Desde el reinicio observado de {quota}", - "fromReset": "Desde el reinicio de {quota}", - "quotaEstimator": "Estimador de cuota", - "noApiKeyUsage": "Sin uso de clave API en esta ventana del proveedor.", - "requestTokenCounts": "{requests} solicitudes · {tokens} tokens", - "noUsdLimit": "Sin límite de USD" + "rows": "Rows", + "window": "Window", + "unknown": "unknown", + "fromRecordedReset": "From recorded {quota} reset", + "fromObservedReset": "From observed {quota} reset", + "fromReset": "From {quota} reset", + "quotaEstimator": "Quota estimator", + "noApiKeyUsage": "No API key usage in this provider window.", + "requestTokenCounts": "{requests} requests · {tokens} tokens", + "noUsdLimit": "No USD limit" }, "freeBudget": { - "title": "Presupuesto de tokens gratuitos", - "remaining": "{remaining} restantes · {percent}% de {total}", - "steadyMonth": "Estable / mes", - "firstMonth": "Primer mes (+ créditos)", - "usedThisMonth": "Usado este mes", - "segmentHint": "Cada segmento = un grupo gratuito · deduplicado por grupo, conteo honesto (sin límites de tasa inflados).", - "boost": "Desbloquea ~{tokens} más al mes con una recarga única de $10 en OpenRouter (50 → 1000 solicitudes/día)", - "uncapped": "Permanentemente gratis, sin límite publicado (con límite de tasa) — acceso real, no contabilizado en el titular:", - "tosRestricted": "{count, plural, one {# modelo marcado} other {# modelos marcados}} como restringidos por ToS — tú decides", - "provider": "Proveedor", - "model": "Modelo", - "modelName": "Nombre del modelo", - "type": "Tipo", - "tokensMonth": "Tokens/mes", - "credit": "{tokens} de crédito", - "hideTosRestricted": "Ocultar restringidos por ToS", - "sort": "Ordenar", + "title": "Free-token budget", + "remaining": "{remaining} remaining · {percent}% of {total}", + "steadyMonth": "Steady / month", + "firstMonth": "First month (+ credits)", + "usedThisMonth": "Used this month", + "segmentHint": "Each segment = one free pool · pool-deduped, honest counting (no inflated rate-limit ceilings).", + "boost": "Unlock ~{tokens} more/mo with a one-time $10 OpenRouter top-up (50 → 1000 req/day)", + "uncapped": "Permanently free, no published cap (rate-limited) — real access, not counted in the headline:", + "tosRestricted": "{count, plural, one {# model} other {# models}} flagged as ToS-restricted — you decide", + "provider": "Provider", + "model": "Model", + "modelName": "Model name", + "type": "Type", + "tokensMonth": "Tokens/mo", + "credit": "{tokens} credit", + "hideTosRestricted": "Hide ToS-restricted", + "sort": "Sort", "freeType": { - "daily": "diario", - "monthly": "mensual", - "creditMonthly": "crédito/mes", - "uncapped": "sin límite", - "signupCredit": "crédito de registro", - "keyless": "sin clave", - "discontinued": "descontinuado" + "daily": "daily", + "monthly": "monthly", + "creditMonthly": "credit/mo", + "uncapped": "uncapped", + "signupCredit": "signup credit", + "keyless": "keyless", + "discontinued": "discontinued" }, "tosTitle": { - "avoid": "Restringido por ToS — revisar términos", - "caution": "Precaución — cláusulas de uso personal / proxy", - "ok": "Generalmente permisivo" + "avoid": "ToS-restricted — review terms", + "caution": "Caution — personal-use / proxy clauses", + "ok": "Generally permissive" } }, "providerHealthAutopilot": { - "title": "Piloto automático de estado del proveedor", - "description": "Busca proveedores inestables, tiempos de espera de cuentas, errores obsoletos y soluciones manuales seguras.", - "loadFailed": "Error al cargar el informe del piloto automático", - "actionApplied": "{action} aplicado.", - "actionFailed": "Error en la acción del piloto automático", - "refresh": "Actualizar", - "status": "Estado", - "issues": "Problemas", - "actions": "Acciones", - "connections": "Conexiones", + "title": "Provider Health Autopilot", + "description": "Finds unstable providers, account cooldowns, stale errors, and safe manual fixes.", + "loadFailed": "Failed to load autopilot report", + "actionApplied": "{action} applied.", + "actionFailed": "Autopilot action failed", + "refresh": "Refresh", + "status": "Status", + "issues": "Issues", + "actions": "Actions", + "connections": "Connections", "state": { - "healthy": "saludable", - "warning": "advertencia", - "critical": "crítico", - "loading": "cargando" + "healthy": "healthy", + "warning": "warning", + "critical": "critical", + "loading": "loading" }, - "loadingRecommendations": "Cargando recomendaciones del proveedor...", - "noRecommendations": "No hay recomendaciones sobre el estado del proveedor en este momento.", - "providerMetrics": "puntuación {score}% · activos {active}/{total} · tiempo de espera {cooldown} · bloqueos de modelo {lockouts}", + "loadingRecommendations": "Loading provider recommendations...", + "noRecommendations": "No provider health recommendations right now.", + "providerMetrics": "score {score}% · active {active}/{total} · cooldown {cooldown} · model lockouts {lockouts}", "providerState": { - "healthy": "saludable", - "degraded": "degradado", - "down": "caído" + "healthy": "healthy", + "degraded": "degraded", + "down": "down" }, "severity": { "info": "info", - "warning": "advertencia", - "critical": "crítico" + "warning": "warning", + "critical": "critical" }, - "remainingSeconds": "restante {seconds}s", - "errorCode": "código {code}", - "applying": "Aplicando...", + "remainingSeconds": "remaining {seconds}s", + "errorCode": "code {code}", + "applying": "Applying...", "issue": { - "circuitOpenTitle": "El disyuntor del proveedor está abierto", - "circuitOpenRecommendation": "Verifique la recuperación upstream, luego restablezca el disyuntor del proveedor o espere a la ventana de reintento.", - "circuitRecoveryTitle": "El proveedor está probando la recuperación", - "circuitRecoveryRecommendation": "Deje que se complete la siguiente prueba o restablezca el disyuntor después de la verificación manual.", - "terminalTitle": "{label} tiene un estado de cuenta terminal", - "terminalRecommendation": "Verifique la facturación, vuelva a autenticarse o reemplace la credencial antes de reactivarla.", - "cooldownTitle": "{label} está en enfriamiento temporal", - "cooldownRecommendation": "Espere a la ventana de reintento upstream o borre el enfriamiento después de validar la recuperación.", - "staleErrorTitle": "{label} tiene un estado de error obsoleto", - "staleErrorRecommendation": "Limpie los campos de error obsoletos para que la conexión sea elegible para el enrutamiento normal nuevamente.", - "inactiveTitle": "{label} está desactivado", - "inactiveRecommendation": "Reactive solo si esto no se desactivó intencionadamente.", - "modelLockoutTitle": "{model} está bloqueado para una conexión", - "modelLockoutRecommendation": "Resuelva el estado de la conexión o confirme que la cuota/disponibilidad del modelo se ha recuperado antes de borrar el bloqueo.", - "quotaTitle": "El monitor de cuota informa {status}", - "quotaRecommendation": "Revise el uso de la cuota y rote el tráfico a otra conexión en buen estado si es necesario." + "circuitOpenTitle": "Provider circuit breaker is open", + "circuitOpenRecommendation": "Verify upstream recovery, then reset the provider circuit breaker or wait for the retry window.", + "circuitRecoveryTitle": "Provider is probing recovery", + "circuitRecoveryRecommendation": "Let the next probe complete or reset the breaker after manual verification.", + "terminalTitle": "{label} has a terminal account state", + "terminalRecommendation": "Check billing, re-authenticate, or replace the credential before reactivating it.", + "cooldownTitle": "{label} is in temporary cooldown", + "cooldownRecommendation": "Wait for the upstream retry window or clear the cooldown after validating recovery.", + "staleErrorTitle": "{label} has stale error state", + "staleErrorRecommendation": "Clear stale error fields so the connection is eligible for normal routing again.", + "inactiveTitle": "{label} is disabled", + "inactiveRecommendation": "Reactivate only if this was not intentionally disabled.", + "modelLockoutTitle": "{model} is locked out for one connection", + "modelLockoutRecommendation": "Resolve the connection state or confirm model quota/availability has recovered before clearing the lockout.", + "quotaTitle": "Quota monitor reports {status}", + "quotaRecommendation": "Review quota usage and rotate traffic to another healthy connection if needed." }, "action": { - "resetProviderBreaker": "Restablecer disyuntor del proveedor", - "clearConnectionCooldown": "Borrar enfriamiento de la conexión", - "disableConnection": "Desactivar esta conexión", - "clearStaleError": "Borrar estado de error obsoleto", - "reactivateConnection": "Reactivar conexión", - "clearModelLockout": "Borrar bloqueo del modelo" + "resetProviderBreaker": "Reset provider breaker", + "clearConnectionCooldown": "Clear connection cooldown", + "disableConnection": "Disable this connection", + "clearStaleError": "Clear stale error state", + "reactivateConnection": "Reactivate connection", + "clearModelLockout": "Clear model lockout" } }, "changelogPage": { - "newsTab": "Novedades", - "changelogTab": "Historial de cambios", - "loading": "Cargando historial de cambios...", - "announcementsLoadFailed": "No se pudieron cargar los anuncios. Inténtelo de nuevo más tarde.", - "noAnnouncements": "No hay anuncios nuevos en este momento.", - "learnMore": "Más información", - "changelogLoadFailed": "No se pudo cargar el historial de cambios. Inténtelo de nuevo más tarde.", - "retry": "Reintentar", - "viewFullHistory": "Ver el historial completo en GitHub" + "newsTab": "News", + "changelogTab": "Changelog", + "loading": "Loading changelog...", + "announcementsLoadFailed": "Could not load announcements. Please try again later.", + "noAnnouncements": "No new announcements at this time.", + "learnMore": "Learn more", + "changelogLoadFailed": "Could not load the changelog. Please try again later.", + "retry": "Retry", + "viewFullHistory": "View full history on GitHub" }, "reasoningRouting": { "title": "Reasoning routing policies", @@ -12026,78 +12046,78 @@ "saveChanges": "Save changes", "add": "Add rule", "cancel": "Cancel", - "simulateTitle": "Simulate rule", - "model": "Model", - "effort": "Effort", - "transport": "Transport", - "simulate": "Simulate without upstream", - "extendedComboWarning": "Max/Ultra is validated separately for every combo target during routing.", - "extendedUnknownWarning": "Enter a target model to verify Max/Ultra support.", - "extendedUnsupportedWarning": "Max/Ultra is only known to be supported by suitable Codex GPT-5.6 models. Unknown custom models are accepted by the server with a warning.", + "simulateTitle": "Simular regla", + "model": "Modelo", + "effort": "Nivel de esfuerzo", + "transport": "Transporte", + "simulate": "Simular sin proveedor superior", + "extendedComboWarning": "Max/Ultra se valida por separado para cada objetivo del combo durante el enrutamiento.", + "extendedUnknownWarning": "Introduce un modelo objetivo para verificar la compatibilidad con Max/Ultra.", + "extendedUnsupportedWarning": "Max/Ultra solo es compatible de forma confirmada con modelos Codex GPT-5.6 adecuados. El servidor acepta modelos personalizados desconocidos con una advertencia.", "scope": { "global": "Global", - "apiKey": "API key", + "apiKey": "Clave API", "combo": "Combo", - "model": "Model", - "connection": "Connection" + "model": "Modelo", + "connection": "Conexión" }, "mode": { - "inherit": "Inherit client", - "default": "Use default", - "force": "Force" + "inherit": "Heredar del cliente", + "default": "Usar predeterminado", + "force": "Forzar" }, "budget": { - "preserve": "Preserve", - "remove": "Remove", - "set": "Set fixed value" + "preserve": "Conservar", + "remove": "Eliminar", + "set": "Establecer valor fijo" } }, "chaosConfig": { "pageTitle": "Modo Caos", - "pageSubtitle": "Ejecute múltiples modelos de IA en paralelo o de forma colaborativa en la misma tarea", - "enableChaos": "Activar Modo Caos", - "enableChaosDesc": "Permitir que las claves de API con el modo caos activado usen esta función", + "pageSubtitle": "Ejecuta múltiples modelos de IA en paralelo o de forma colaborativa en la misma tarea", + "enableChaos": "Habilitar Modo Caos", + "enableChaosDesc": "Permitir que las claves API con modo caos habilitado utilicen esta función", "mode": "Modo predeterminado", "modeParallel": "Paralelo", "modeCollaborative": "Colaborativo", - "modeParallelDesc": "Todos los modelos se ejecutan simultáneamente — resultados más rápidos", - "modeCollaborativeDesc": "Los modelos encadenan salidas — cada uno ve el resultado anterior", + "modeParallelDesc": "Todos los modelos se ejecutan simultáneamente: los resultados más rápidos", + "modeCollaborativeDesc": "Los modelos encadenan las salidas: cada uno ve el resultado anterior", "timeout": "Tiempo de espera (ms)", - "timeoutDesc": "Tiempo máximo por llamada al modelo (5000-600000ms)", - "systemPrompt": "Prompt del sistema (opcional)", - "systemPromptDesc": "Instrucciones personalizadas para todas las instancias del modelo en modo caos", - "providerOverrides": "Anulaciones de proveedor", - "providerOverridesDesc": "Seleccionar modelos específicos por proveedor para el modo caos", + "timeoutDesc": "Tiempo máximo por llamada al modelo (5000-600000 ms)", + "systemPrompt": "Prompt de sistema (opcional)", + "systemPromptDesc": "Instrucciones personalizadas para todas las instancias de modelos en modo caos", + "providerOverrides": "Ajustes específicos por proveedor", + "providerOverridesDesc": "Selecciona modelos específicos por proveedor para el modo caos", "providerId": "Proveedor", "modelId": "Modelo", "addProvider": "Añadir proveedor", "removeProvider": "Eliminar", "saveConfig": "Guardar configuración", - "configSaved": "Configuración de caos guardada correctamente", - "configError": "Error al guardar la configuración de caos", - "configReset": "Restablecer valores predeterminados", - "keyPermission": "Acceso al modo caos", - "keyPermissionDesc": "Permitir que esta clave API use el modo caos (ejecución paralela multimodelo)", - "testButton": "Probar modo caos", + "configSaved": "Configuración del modo caos guardada correctamente", + "configError": "Error al guardar la configuración del modo caos", + "configReset": "Restablecer a valores predeterminados", + "keyPermission": "Acceso al Modo Caos", + "keyPermissionDesc": "Permitir que esta clave API utilice el Modo Caos (ejecución paralela multimodelo)", + "testButton": "Probar Modo Caos", "testTask": "Escribe un poema corto sobre la inteligencia artificial", "loadingProviderModels": "Cargando proveedores...", - "systemPromptPlaceholder": "Opcional: anular el prompt del sistema predeterminado del modo caos...", + "systemPromptPlaceholder": "Opcional: anular el prompt de sistema predeterminado del modo caos...", "enabled": "Habilitado", "disabled": "Deshabilitado", - "maxTokens": "Tokens máximos", - "maxTokensDesc": "Número máximo de tokens por respuesta del modelo. Los valores más altos cuestan más y tardan más tiempo.", - "providerIdPlaceholder": "ID del proveedor (escriba o seleccione)", - "modelIdPlaceholder": "ID del modelo (opcional)", - "on": "ACTIVADO", - "off": "DESACTIVADO", + "maxTokens": "Límite de tokens", + "maxTokensDesc": "Límite máximo de tokens por respuesta del modelo. Valores más altos conllevan un mayor coste y tiempo de procesamiento.", + "providerIdPlaceholder": "ID de proveedor (escribe o selecciona)", + "modelIdPlaceholder": "ID de modelo (opcional)", + "on": "Activado", + "off": "Desactivado", "availableProviders": "Proveedores disponibles ({count})", - "noProviderOverrides": "Sin anulaciones — todos los proveedores activos participarán con sus modelos predeterminados" + "noProviderOverrides": "Sin ajustes específicos: todos los proveedores activos participarán con sus modelos predeterminados" }, "kimiSponsorBanner": { - "title": "Kimi (Moonshot AI) es el amigo fundador de código abierto de OmniRoute", - "description": "Kimi K3 aporta una ventana de contexto de 1M-token y un rendimiento de programación de vanguardia a OmniRoute por una fracción del costo.", + "title": "Kimi (Moonshot AI) is now an official sponsor of OmniRoute", + "description": "Kimi K3 aporta una ventana de contexto de 1M de tokens y un rendimiento de código de vanguardia a OmniRoute por una fracción del coste.", "cta": "Obtener Kimi Code", - "partnerLinkNote": "Enlace de afiliado", + "partnerLinkNote": "Enlace de socio", "dismissAriaLabel": "Descartar" } }