localization: ship es-ES

Complete Spanish catalog across all three namespaces, 1129 keys,
machine-translated then reviewed for terminology and plurals.

Fixed on review: an awkward literal fragment in settings.accounts.description
("Quién tiene acceso, y como qué") reworded to use the established
role → "función" glossary term instead of an ad-hoc phrase. Everything
else held up — "compositor" for the chat composer avoided the same
Editor-collision German needed fixing for, Minesweeper stayed
untranslated matching pt-PT/fr-FR/de-DE precedent, and the impersonal
"se" constructions used for the file-operation plurals (Se copió /
Se copiaron) read correctly at both n=1 and n=0 — Spanish's plural
rule is one/other like English, count=0 takes the plural branch.

All 17 plural entries verified at count 0/1/2.

This closes out the three-locale rollout: es-ES, de-DE and fr-FR all
now in SHIPPED_LOCALES and all three parity tests, each shipped in
its own commit only after passing review. pt-BR stays out per the
owner's call — European Portuguese first, Brazilian is a separate
decision.
This commit is contained in:
2026-08-23 17:21:37 +00:00
parent d6a3bea7c9
commit d7a4a18ce8
7 changed files with 1444 additions and 4 deletions
@@ -0,0 +1,81 @@
{
"button": {
"cancel": "Cancelar",
"confirm": "Confirmar",
"ok": "Aceptar",
"close": "Cerrar"
},
"search": {
"placeholder": "Buscar",
"open": "Abrir búsqueda",
"close": "Cerrar búsqueda",
"clear": "Borrar búsqueda"
},
"select": {
"placeholder": "Seleccionar..."
},
"tabs": {
"filterPlaceholder": "Filtrar"
},
"commandBlock": {
"run": "Ejecutar en el terminal",
"copy": "Copiar comando"
},
"colorPicker": {
"placeholder": "Color hexadecimal"
},
"state": {
"loading": "Cargando…"
},
"dataTable": {
"empty": "No se encontraron datos.",
"pagination": {
"showingPage": "Mostrando página {{current}} de {{total}}",
"showingPageShort": "p {{current}}/{{total}}",
"rowsPerPage": "Filas por página",
"perPage": "{{size}} / página",
"perPageShort": "{{size}}/p",
"first": "Primera",
"prev": "Anterior",
"next": "Siguiente",
"last": "Última"
}
},
"pagination": {
"label": "Paginación",
"previous": "Anterior",
"next": "Siguiente",
"morePages": "Más páginas",
"goToPrevious": "Ir a la página anterior",
"goToNext": "Ir a la página siguiente"
},
"carousel": {
"previous": "Diapositiva anterior",
"next": "Diapositiva siguiente"
},
"breadcrumb": {
"more": "Más"
},
"theme": {
"toggle": "Alternar modo de color"
},
"error": {
"forbidden": {
"title": "Acceso no autorizado",
"description": "No tienes autorización para realizar esta acción.",
"hint": "Si crees que esto es un error, contacta con tu responsable."
},
"unauthorized": {
"title": "Credenciales no válidas",
"description": "Tu token de acceso ha caducado",
"hint": "Inicia sesión de nuevo"
},
"server": {
"title": "Error del servidor"
}
},
"logo": {
"icon": "Icono de Officer",
"logo": "Logotipo de Officer"
}
}
@@ -4,11 +4,12 @@ import en from './en-GB.json';
import ptPT from './pt-PT.json';
import frFR from './fr-FR.json';
import deDE from './de-DE.json';
import esES from './es-ES.json';
// D2: every shipped locale ships a COMPLETE catalog. A key en-GB has and another locale lacks is a red
// build, not a warning — there is no regional fallback to paper over the gap.
describe('shared components (ui.*) locale catalogs', () => {
test('every shipped locale has every key en-GB has', () => {
expect(findMissingKeys(en, { 'pt-PT': ptPT, 'fr-FR': frFR, 'de-DE': deDE })).toEqual([]);
expect(findMissingKeys(en, { 'pt-PT': ptPT, 'fr-FR': frFR, 'de-DE': deDE, 'es-ES': esES })).toEqual([]);
});
});
@@ -0,0 +1,652 @@
{
"common": {
"save": "Guardar",
"delete": "Eliminar"
},
"minesweeper": {
"notInstalled": "Minesweeper no está instalado en este servidor.",
"needs": "Necesita wine, un prefijo de 32 bits y este paquete junto a la plataforma:",
"notRunning": "La sesión de Minesweeper no está en ejecución.",
"error": {
"connectionFailed": "La conexión a la sesión de Minesweeper falló.",
"refused": "El servidor VNC rechazó la conexión.",
"authUnsupported": "El servidor VNC pide autenticación, que este cliente no implementa.",
"handshakeRejected": "El servidor VNC rechazó el handshake.",
"unknownMessage": "El servidor VNC envió un tipo de mensaje desconocido ({{type}}).",
"unknownEncoding": "El servidor VNC usó la codificación {{encoding}}, que este cliente no solicitó."
}
},
"qrTransfer": {
"chooseFile": "Elige un archivo para enviar",
"startScanning": "Empezar a escanear",
"receiveAnother": "Recibir otro",
"stop": "Detener"
},
"dav": {
"empty": "Aquí no hay nada todavía. Añade uno desde un cliente de móvil o de escritorio mediante CalDAV/CardDAV.",
"calendar": "Calendario",
"contacts": "Contactos",
"readFailed": "No se pudo leer {{name}}: {{reason}}"
},
"terminal": {
"title": "Terminal",
"find": "Buscar",
"runningShells": "Shells en ejecución",
"loading": "Cargando…",
"noShells": "No hay ninguna shell en ejecución.",
"refresh": "Actualizar",
"kill": "Terminar esta shell"
},
"appStore": {
"loading": "Cargando",
"loadFailed": "No se pudo cargar la tienda de aplicaciones.",
"installed": "Instaladas",
"available": "Disponibles",
"needsYou": "Te necesita",
"needsYouShort": "te necesita",
"selectApp": "Selecciona una aplicación",
"installFailed": "La instalación falló",
"uninstall": "Desinstalar",
"enable": "Activar",
"disable": "Desactivar",
"enabled": "activada",
"disabled": "desactivada",
"removalNote": "Desactivar detiene el sidecar y su contenedor. Desinstalar también elimina los contenedores — tus datos, la configuración y las tablas de esta aplicación se conservan en cualquier caso.",
"installing": "instalando",
"failed": "falló",
"installedIcon": "instalada"
},
"systemMonitor": {
"cpuPackage": "Paquete de CPU",
"user": "Usuario",
"cpuPct": "CPU%",
"memPct": "MEM%",
"command": "Comando",
"memory": "Memoria",
"disks": "Discos",
"temperature": "Temperatura",
"network": "Red",
"power": "Energía",
"topProcesses": "Procesos principales",
"filterPlaceholder": "filtrar por nombre o imagen…",
"name": "Nombre",
"status": "Estado",
"mem": "Mem",
"uptime": "Tiempo activo",
"scopeDockers": "dockers"
},
"codeEditor": {
"closeFile": "Cerrar {{name}}",
"loading": "Cargando…",
"noFiles": "Sin archivos",
"explorer": "Explorador",
"openAFile": "Abre un archivo desde el explorador para empezar a editar",
"refresh": "Actualizar el árbol y recargar los archivos abiertos sin modificar",
"readFailed": "No se pudo leer el archivo",
"saved": "Archivo guardado",
"saveFailed": "No se pudo guardar el archivo",
"title": "Editor de código"
},
"widgets": {
"resync": "Resincronizar widgets (recarga para incluir los widgets recién implementados)"
},
"preview": {
"title": "Vista previa",
"reload": "Recargar",
"changeUrl": "Cambiar URL",
"openNewTab": "Abrir en una pestaña nueva",
"pointAtApp": "Apunta este panel a una aplicación en ejecución",
"open": "Abrir",
"hint": "Cualquier cosa que el navegador pueda alcanzar. Se queda en este panel y sobrevive a una recarga.",
"connecting": "Conectando…"
},
"sendOff": {
"files": "Archivos",
"where": "Dónde",
"loading": "Cargando…",
"landsIn": "Llega a su",
"landedIn": "Llegó a",
"whoMaySend": "Quién puede enviarme",
"allowedLandIn": "Los archivos de quien autorices llegan a",
"removeFile": "Eliminar {{name}}",
"sendTo": "Enviar a {{name}}",
"turningOff": "Desactivar a alguien detiene los envíos futuros y deja intacto lo que ya envió."
},
"panelName": {
"appStore": "Tienda de aplicaciones",
"appDetail": "Detalle de la aplicación",
"calendar": "Calendario",
"contacts": "Contactos",
"categories": "Categorías",
"chat": "Chat",
"chatSessions": "Sesiones",
"codeEditor": "Editor de código",
"commander": "Commander",
"commanders": "Commanders",
"dashboardPreview": "Vista previa del Dashboard",
"dashboards": "Dashboards",
"fileBrowser": "Explorador de archivos",
"pluginDetail": "Detalle del plugin",
"plugins": "Plugins",
"preview": "Vista previa",
"qrReceive": "Recibir por QR",
"qrSend": "Enviar por QR",
"scope": "Ámbito",
"systemMonitor": "Monitor del sistema",
"widgets": "Widgets",
"terminal": "Terminal",
"hostTerminal": "Terminal del host",
"runningShells": "Shells en ejecución",
"pm2Processes": "procesos pm2"
},
"dashboards": {
"title": "Dashboards",
"new": "Nuevo Dashboard",
"delete": "Eliminar dashboard",
"confirmDelete": "¿Seguro que quieres eliminar",
"search": "Buscar dashboards",
"name": "Nombre",
"description": "Descripción",
"open": "Abrir Dashboard",
"selectOne": "Selecciona un dashboard o crea uno nuevo",
"namePlaceholder": "Mi Dashboard",
"descriptionPlaceholder": "¿Para qué es este dashboard?",
"template": "Plantilla",
"create": "Crear",
"templates": {
"single": "Único",
"twoColumns": "2 columnas",
"mainSide": "Principal + lateral",
"sidebar": "Barra lateral",
"grid": "Cuadrícula 2x2",
"colsBottom": "Columnas + inferior"
}
},
"fileViewer": {
"readAloud": "Leer en voz alta",
"ocr": "Extraer texto (OCR)",
"transcribe": "Transcribir",
"extractAudio": "Extraer audio",
"extract": "Extraer",
"saveNextTo": "Guardar junto al original",
"download": "Descargar",
"pdfViewer": "Visor de PDF",
"videoFailed": "No se pudo cargar el vídeo",
"imageFailed": "No se pudo cargar la imagen",
"audioFailed": "No se pudo cargar el archivo de audio",
"audioTrack": "Pista de audio",
"subtitles": "Subtítulos",
"track": "Pista {{n}}",
"saved": "Archivo guardado",
"saveFailed": "No se pudo guardar el archivo",
"scrollTop": "Ir arriba",
"speechFailed": "No se pudo generar el audio de voz",
"ocrFailed": "No se pudo extraer el texto de la imagen",
"transcribeFailed": "No se pudo transcribir el audio",
"extractAudioFailed": "No se pudo extraer el audio del vídeo",
"extractFailed": "No se pudo extraer el archivo comprimido",
"savedAs": "Guardado como “{{name}}”",
"extractedTo": "Extraído en “{{name}}”",
"downloadInstead": "Descargar en su lugar",
"archiveFile": "Archivo comprimido"
},
"plugins": {
"loading": "Cargando…",
"onThisMachine": "En esta máquina",
"noPluginsIn": "No hay plugins en",
"available": "Disponibles",
"needsOnThisMachine": "Requisitos en esta máquina",
"install": "Instalar",
"clonesInto": "Clona el repositorio en",
"deleteData": "Eliminar también todos sus datos",
"noTables": "Este plugin no declara tablas, por lo que no hay datos que conservar.",
"selectOne": "Selecciona un plugin.",
"disable": "Desactivar",
"enable": "Activar",
"publisher": "Editor",
"version": "Versión",
"needsPlatform": "Requiere la plataforma",
"wouldMount": "Se montaría en",
"ships": "Incluye",
"permissions": "Permisos",
"source": "Origen",
"mountsAt": "Se monta en",
"sidecar": "Sidecar",
"deleteNamed": "Eliminar {{name}}",
"updateTo": "Actualizar a {{version}}"
},
"commandHq": {
"selectOne": "Selecciona un commander, o inicia uno nuevo.",
"startConversation": "Iniciar la conversación",
"name": "Nombre",
"nameHint": "Se aplica a la conversación al iniciarse, en lugar de que el harness la nombre a partir de tu primer mensaje.",
"workingDirectory": "Directorio de trabajo",
"cwdHint": "Desde donde se resuelve cada comando que ejecuta, y donde se guarda su historial. No se puede mover después.",
"new": "Nuevo commander",
"spawned": "Iniciado",
"deleteQ": "¿Eliminar?",
"uncategorised": "Sin categoría",
"loading": "Cargando…",
"platformDeploys": "Despliegues de la plataforma",
"endSession": "Terminar sesión — la libera para que pueda reanudarse en otro lugar",
"confirmDeleteHint": "Confirmar eliminación — elimina también la conversación, no solo la entrada de Command HQ",
"confirmDelete": "Confirmar eliminación",
"cancelDelete": "Cancelar eliminación",
"deleteCommander": "Eliminar commander",
"none": "Todavía no hay commanders aquí.",
"startOne": "Inicia uno",
"confirmDeleteNamed": "Confirmar la eliminación de {{name}}",
"deleteNamed": "Eliminar {{name}}",
"categories": "Categorías",
"noCategories": "Todavía no hay categorías",
"newCategory": "Nueva categoría",
"allCommanders": "Todos los commanders",
"categoryName": "Nombre de la categoría",
"guide": {
"whatIsIt": "Qué es un commander",
"starting": "Cómo iniciar uno",
"examples": "Ejemplos de un primer mensaje",
"whileRunning": "Mientras se ejecuta",
"whatIsItBody1": "Un agente que sigue trabajando cuando no estás — espera a que ocurra algo, actúa en consecuencia y te informa.",
"whatIsItBody2": "Es una conversación normal. Empiezas diciéndole qué vigilar y qué hacer al respecto, con tus propias palabras.",
"startingBody1": "Describe aquí el trabajo, como se lo dirías a cualquiera. Di qué debe vigilar, dónde, y qué hacer cuando se dispare.",
"startingBody2": "TODO: los pasos concretos, cuando el flujo de creación esté definido. Esto sustituye a “abrir el diálogo de trabajo en segundo plano y armar un vigilante”, que nadie podría adivinar.",
"examplesBody1": "TODO: dos o tres ejemplos de mensajes iniciales, cuando el flujo de creación esté definido. Son lo que convierte “describe el trabajo” de una instrucción en algo sobre lo que un usuario novato puede actuar.",
"whileRunningBody1": "TODO: lo que ve el propietario — dónde aparece su coste, cómo leer lo que están haciendo los agentes que ha iniciado, y cómo detenerlo.",
"draft": "borrador"
},
"startHint": "Explorará este directorio y luego te preguntará qué debe vigilar.",
"startBlocked": "{{missing}} — y entonces esto lo inicia.",
"confirmDeletingNamed": "Confirmar la eliminación de {{name}}"
},
"chatHistory": {
"newChat": "Nuevo chat",
"tryAgain": "Reintentar",
"refresh": "Actualizar",
"refreshSessions": "Actualizar sesiones",
"newChatInDir": "Nuevo chat en un directorio…",
"loadFailed": "No se pudieron cargar las sesiones",
"reading": "Leyendo transcripciones…",
"noSessions": "Todavía no hay sesiones",
"liveFailed": "No se pudieron leer las sesiones activas",
"asking": "Preguntando al agente…",
"tabs": {
"tree": "Árbol",
"latest": "Recientes",
"live": "Activas",
"agents": "Agentes",
"commanders": "Commanders"
},
"notifyPreference": "Preferencia de notificaciones",
"notify": {
"everyTurn": "Al final de cada turno",
"inputNeeded": "Solo cuando se necesita una respuesta",
"none": "Ninguna"
},
"notificationsLabel": "Notificaciones: {{choice}}",
"chooseDir": "Elige un directorio de trabajo",
"create": "Crear",
"newFolder": "Nueva carpeta",
"selectFolder": "Seleccionar esta carpeta",
"newFolderName": "Nombre de la nueva carpeta",
"noSubfolders": {
"one": "Sin subcarpetas visibles — se ha filtrado {{count}} oculta",
"other": "Sin subcarpetas visibles — se han filtrado {{count}} ocultas"
},
"showHidden": "Mostrar ocultas",
"showHiddenCount": "Mostrar ocultas ({{count}})",
"selectSession": "Selecciona una sesión para verla",
"endSession": "Terminar sesión — detiene cualquier turno en curso y la libera para que pueda reanudarse en otro lugar",
"noReadable": "No hay conversaciones legibles aquí.",
"noConversations": "Todavía no hay conversaciones",
"newChatIn": "Nuevo chat en {{path}}",
"sessionTitle": "Título de la sesión",
"saveTitle": "Guardar título",
"cancelRename": "Cancelar cambio de nombre",
"confirmDelete": "Confirmar eliminación",
"cancelDelete": "Cancelar eliminación",
"rename": "Renombrar",
"deleteSession": "Eliminar sesión",
"renameFailed": "No se pudo renombrar la sesión: {{reason}}",
"deleteFailed": "No se pudo eliminar la sesión: {{reason}}",
"deleteAll": "¿Eliminar las {{count}}?",
"confirmDeletingNamed": "Confirmar la eliminación de {{name}}",
"renameNamed": "Renombrar {{name}}",
"deleteNamed": "Eliminar {{name}}",
"newChatTitle": "Nuevo chat",
"renameHint": "Haz clic para renombrar este chat",
"hideHidden": "Ocultar ocultas"
},
"chat": {
"newChat": "Nuevo chat",
"rename": "Renombrar",
"deleteQ": "¿Eliminar “{{title}}”?",
"duplicateAgent": "Ya existe un agente llamado “{{name}}” en este dashboard",
"composerPlaceholder": "¿En qué quieres trabajar ahora?",
"turnFinished": "Turno terminado · sin mensaje de cierre",
"job": {
"title": "Trabajo en segundo plano",
"runsIn": "Se ejecuta en",
"command": "Comando — ejecutar exactamente esto",
"prompt": "Prompt — descríbelo y el agente lo resuelve",
"watch": "Vigilar algo",
"watchHint": "En texto libre. El agente preguntará antes de armar si algo no queda claro.",
"handBack": "Salir y devolver el control al agente, luego rearmar",
"keepGoing": "Continuar — actuar cada vez y seguir",
"stopAfter": "Detener después de",
"start": "Iniciar",
"watchExample": "vigila nuestros repositorios de Gitea; con cada nuevo push, tráelo y envíalo al espejo de GitHub",
"startJob": "Iniciar un trabajo en segundo plano o un vigilante"
},
"tasks": {
"restart": "Reiniciar",
"pinned": "Fijado",
"clearFinished": "Limpiar todos los terminados",
"clearFinishedTasks": "Limpiar todas las tareas terminadas",
"stopJob": "Detener este trabajo",
"dismiss": "Descartar",
"rerun": "Detenerlo y ejecutar el mismo comando de nuevo",
"collapse": "Contraer",
"collapseDetail": "Contraer el detalle de la tarea",
"stopNamed": "Detener {{label}}",
"dismissNamed": "Descartar {{label}}",
"status": "Tarea {{status}}."
},
"usage": {
"noSignIn": "No hay ninguna sesión guardada — ejecuta /login para usar esta",
"updating": "Actualizando…",
"unreadable": "No se pudo leer el consumo en esta máquina.",
"loading": "Cargando…",
"limits": "Límites",
"byDay": "Tokens por día",
"byModel": "Tokens por modelo",
"title": "Consumo y límites",
"modelBreakdown": "Entrada {{input}} · salida {{output}} · lectura de caché {{cacheRead}} · escritura de caché {{cacheWrite}}",
"switchTo": "Cambiar a {{account}}",
"switchToOrg": "Cambiar a {{account}} ({{org}})",
"signInExpired": "{{account}} — sesión caducada, ejecuta /login"
},
"attach": {
"image": "Imagen",
"textFile": "Archivo de texto",
"webpageUrl": "URL de página web",
"attach": "Adjuntar",
"readFailed": "No se pudo leer {{name}}: {{reason}}",
"unknownError": "error desconocido",
"webpageTitle": "Adjuntar página web",
"webpageHint": "Introduce una URL para extraerla y adjuntarla como contexto.",
"scrapeFailed": "No se pudo extraer la página web",
"uploadFailed": "No se pudo subir la imagen",
"dropImages": "Suelta imágenes para adjuntarlas"
},
"signIn": {
"title": "Iniciar sesión en Claude",
"done": "Sesión iniciada. Los turnos nuevos usan estas credenciales — no hace falta reiniciar.",
"asking": "Pidiendo a la CLI un enlace de inicio de sesión…",
"openHint": "Ábrelo, autoriza y pega aquí el código que te dé.",
"authorise": "Autorizar en claude.com",
"copyLink": "Copia el enlace, para abrirlo en otro navegador o en tu teléfono",
"pasteCode": "pega el código"
},
"message": {
"copyCode": "Copiar el código",
"copyMarkdown": "Copiar como bloque markdown",
"showMore": "Mostrar más ({{count}} líneas más)",
"subagent": "Subagente",
"outputError": "Salida — error",
"contextCleared": "Contexto borrado — nada de lo anterior está en memoria",
"interrupted": "Interrumpido por el usuario",
"agentRestarted": "Agente reiniciado — turno interrumpido",
"retry": "Reintentar",
"planUnchanged": "Modo de plan sin cambios",
"approve": "Aprobar",
"frontmatter": "Frontmatter",
"systemPrompt": "Prompt de sistema",
"reviseHint": "¿Qué debería cambiar? El agente revisa el plan a partir de esto.",
"waiting": "Esperando una respuesta",
"narrationFailed": "La narración se generó pero no se pudo reproducir.",
"readAloudFailed": "No se pudo leer este mensaje en voz alta: {{reason}}",
"compacted": "Contexto compactado",
"compactedAuto": "Contexto compactado automáticamente",
"answerSent": "Respuesta enviada — esperando al agente",
"other": "Otro..."
},
"composer": {
"stop": "Detener",
"sendIntoTurn": "Enviar esto al turno que ya está en curso",
"removeFromQueue": "Quitar de la cola",
"send": "Enviar",
"startHint": "Envía un mensaje para empezar",
"jumpToLatest": "Ir al último mensaje",
"noAudio": "No se captó ningún audio"
},
"agent": {
"gone": "El agente de este panel ya no existe.",
"forget": "Olvidarlo",
"name": "Nombra este agente",
"peers": "Pares: {{names}}"
},
"copy": "Copiar"
},
"files": {
"folderGone": "Esa carpeta ya no existe — de vuelta al inicio",
"searchFailed": "La búsqueda falló",
"createFolderFailed": "No se pudo crear la carpeta",
"createFileFailed": "No se pudo crear el archivo",
"uploadFailed": "No se pudieron subir los archivos",
"renameFailed": "No se pudo renombrar",
"deleteFailed": "No se pudo eliminar",
"deleteSomeFailed": "No se pudieron eliminar algunos elementos",
"downloadFailed": "No se pudo descargar",
"pathCopied": "Ruta copiada",
"generatingSpeech": "Generando audio de voz…",
"speechFailed": "No se pudo generar el audio de voz",
"extracting": "Extrayendo el archivo comprimido…",
"extractFailed": "No se pudo extraer el archivo comprimido",
"cloned": "Repositorio clonado",
"cloneFailed": "No se pudo clonar el repositorio",
"cloning": "Clonando…",
"duplicateFailed": "No se pudo duplicar",
"compressing": "Comprimiendo…",
"compressFailed": "No se pudo comprimir",
"pasteFailed": "No se pudo pegar",
"pasteNeedsSecure": "Pegar desde el portapapeles necesita un contexto seguro (https). Arrastra el archivo en su lugar.",
"copiedItems": {
"one": "Se copió {{count}} elemento",
"other": "Se copiaron {{count}} elementos"
},
"cutItems": {
"one": "Se cortó {{count}} elemento",
"other": "Se cortaron {{count}} elementos"
},
"pastedItems": {
"one": "Se pegó {{count}} elemento",
"other": "Se pegaron {{count}} elementos"
},
"uploadedFiles": {
"one": "Se subió {{count}} archivo",
"other": "Se subieron {{count}} archivos"
},
"deleteItemsQ": {
"one": "¿Eliminar {{count}} elemento?",
"other": "¿Eliminar {{count}} elementos?"
},
"deletedItems": {
"one": "Se eliminó {{count}} elemento",
"other": "Se eliminaron {{count}} elementos"
},
"createdFolder": "Carpeta “{{name}}” creada",
"created": "“{{name}}” creado",
"renamedTo": "Renombrado a “{{name}}”",
"deleteQ": "¿Eliminar “{{name}}”?",
"deleted": "“{{name}}” eliminado",
"extractedTo": "Extraído en “{{name}}”",
"duplicated": "“{{name}}” duplicado",
"pastedInto": "Pegado en “{{name}}”",
"unpinned": "“{{name}}” quitado de fijados",
"pinned": "“{{name}}” fijado",
"menu": {
"copyPath": "Copiar ruta",
"chatAboutThis": "Chatear sobre esto",
"paste": "Pegar",
"newFile": "Nuevo archivo",
"newFolder": "Nueva carpeta",
"uploadFiles": "Subir archivos",
"uploadFolder": "Subir carpeta",
"cloneRepository": "Clonar repositorio",
"hideHiddenFiles": "Ocultar archivos ocultos",
"showHiddenFiles": "Mostrar archivos ocultos",
"createDashboardHere": "Crear Dashboard aquí",
"downloadVideo": "Descargar vídeo",
"dictate": "Dictar",
"dropToUpload": "Suelta archivos para subirlos",
"openFolder": "Abrir carpeta",
"showLocation": "Mostrar ubicación",
"download": "Descargar",
"noResults": "No se encontraron resultados",
"open": "Abrir",
"openInEditor": "Abrir en el editor",
"openInEditorTooLarge": "Abrir en el editor (demasiado grande)",
"pasteIntoFolder": "Pegar en la carpeta",
"readAloud": "Leer en voz alta",
"extract": "Extraer",
"runTask": "Ejecutar tarea",
"runAgent": "Ejecutar agente",
"cut": "Cortar",
"copy": "Copiar",
"duplicate": "Duplicar",
"rename": "Renombrar",
"compress": "Comprimir",
"compressSelection": "Comprimir selección",
"unpin": "Quitar de fijados",
"pin": "Fijar",
"chat": "Chat...",
"delete": "Eliminar",
"gitClone": "Clonar con Git",
"searchFiles": "Buscar archivos...",
"clearSelection": "Limpiar selección",
"selected": "seleccionados",
"refresh": "Actualizar"
},
"grid": {
"empty": "Esta carpeta está vacía",
"sort": "Ordenar:",
"name": "Nombre",
"type": "Tipo",
"size": "Tamaño",
"date": "Fecha"
}
},
"taskRunner": {
"stop": "Detener",
"taskFailed": "La tarea falló",
"taskComplete": "Tarea completada",
"noSubtitles": "Sin subtítulos",
"none": "Ninguno",
"noVideos": "No se encontraron vídeos en esta carpeta.",
"differentLayout": "Disposición diferente — ejecuta estos por separado:",
"skipped": "Omitidos (convertir por separado):",
"analyzing": "Analizando archivos…",
"close": "Cerrar",
"runningOn": "Ejecutándose en",
"queue": "Cola",
"concurrency": "Concurrencia",
"model": "Modelo",
"steps": "Pasos",
"stopPipeline": "Detener el pipeline",
"pipelineFailed": "El pipeline falló",
"pipelineComplete": "Pipeline completado",
"viewInJobs": "Ver en Trabajos",
"copyOutput": "Copiar salida",
"track": "Pista {{n}}",
"runFromStep": "Ejecutar desde el paso {{n}}"
},
"newEntry": {
"nameReserved": "Ese nombre está reservado",
"nameSlash": "El nombre no puede contener \"/\"",
"nameExists": "\"{{name}}\" ya existe aquí",
"urlSpaces": "Una URL no puede contener espacios",
"cancel": "Cancelar",
"file": {
"title": "Nuevo archivo",
"description": "Incluye la extensión — es lo que el editor usa para elegir un lenguaje. Se abre en cuanto se crea.",
"label": "Nombre del archivo",
"placeholder": "notas.txt",
"submit": "Crear y abrir"
},
"folder": {
"title": "Nueva carpeta",
"description": "Se crea en la carpeta que estás viendo.",
"label": "Nombre de la carpeta",
"placeholder": "documentos",
"submit": "Crear carpeta"
},
"clone": {
"title": "Clonar repositorio",
"description": "Se clona en la carpeta que estás viendo, con su propio nombre.",
"label": "URL del repositorio",
"placeholder": "https://github.com/owner/repo.git",
"submit": "Clonar"
}
},
"videoDownload": {
"title": "Descargar vídeo",
"descriptionInput": "Pega la URL de un vídeo o lista de reproducción — se obtienen los detalles antes de descargar.",
"descriptionPreview": "Revisa y descarga.",
"urlPlaceholder": "https://www.youtube.com/watch?v=… o …/playlist?list=…",
"audioOnly": "Extraer solo el audio (mp3)",
"fetch": "Obtener",
"back": "Volver",
"audioOnlyLabel": "Solo audio",
"video": "Vídeo",
"itemCount": {
"one": "{{count}} elemento",
"other": "{{count}} elementos"
},
"subfolderPlaceholder": "Subcarpeta (opcional) — déjalo en blanco para esta carpeta",
"downloadAll": "Descargar todo",
"couldNotFetch": "No se pudo obtener",
"downloading": "Descargando…",
"saving": "Guardando…",
"saved": "Guardado",
"retry": "Reintentar",
"download": "Descargar",
"couldNotFetchInfo": "No se pudo obtener la información",
"timedOut": "Tiempo agotado",
"downloadFailed": "La descarga falló",
"couldNotStart": "No se pudo iniciar la descarga"
},
"fileBrowserWidget": {
"title": "Explorador de archivos",
"search": "Buscar...",
"browse": "Explorar",
"recent": "Recientes",
"pinned": "Fijados",
"noResults": "Sin resultados",
"emptyDirectory": "Directorio vacío",
"noPinnedFiles": "Sin archivos fijados",
"noRecentFiles": "Sin archivos recientes",
"uploading": "Subiendo...",
"empty": "Esta carpeta está vacía",
"sort": "Ordenar:"
},
"agentRunner": {
"agentRunning": "Agente en ejecución",
"keepsGoing": "Sigue ejecutándose tanto si esto se queda abierto como si no. Síguelo en el chat — la sesión más reciente aparece arriba.",
"openChat": "Abrir chat",
"target": "Objetivo",
"starting": "Iniciando…",
"runAgent": "Ejecutar agente",
"startFailed": "No se pudo iniciar el agente"
},
"dictate": {
"title": "Dictar",
"description": "Grabando audio. Pulsa Intro o haz clic en Detener para guardar.",
"recording": "Grabando...",
"startingStatus": "Iniciando...",
"stopSave": "Detener y guardar",
"noAudioCaptured": "No se captó ningún audio",
"micAccessFailed": "No se pudo acceder al micrófono",
"recordingFailed": "La grabación falló"
}
}
@@ -4,11 +4,12 @@ import en from './en-GB.json';
import ptPT from './pt-PT.json';
import frFR from './fr-FR.json';
import deDE from './de-DE.json';
import esES from './es-ES.json';
// D2: every shipped locale ships a COMPLETE catalog. A key en-GB has and another locale lacks is a red
// build, not a warning — there is no regional fallback to paper over the gap.
describe('officerdev (panel.*) locale catalogs', () => {
test('every shipped locale has every key en-GB has', () => {
expect(findMissingKeys(en, { 'pt-PT': ptPT, 'fr-FR': frFR, 'de-DE': deDE })).toEqual([]);
expect(findMissingKeys(en, { 'pt-PT': ptPT, 'fr-FR': frFR, 'de-DE': deDE, 'es-ES': esES })).toEqual([]);
});
});