From d69efffd5451c81de80a8e97558cb6ac6ae54797 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alcib=C3=ADades=20Cabral=20D=C3=ADaz?=
<62911544+alcibiadesc@users.noreply.github.com>
Date: Mon, 22 Sep 2025 18:21:05 +0100
Subject: [PATCH] Add Spanish (ES) language support to i18n system (#795)
* Add Spanish (ES) language support to i18n system
- Added Es variant to UiLanguage enum in Rust backend
- Regenerated TypeScript types to include Spanish support
- Created complete Spanish translation files for all UI components
- Updated i18n configuration to include Spanish resources
- Added Spanish option to language selector in settings
- Updated existing language files to include Spanish in options
All major UI areas now support Spanish including navigation,
settings, project management, and status messages.
* Fix formatting for Spanish translation files
Run Prettier to ensure consistent JSON formatting
---
.../src/services/config/versions/v6.rs | 1 +
frontend/src/i18n/config.ts | 8 +
frontend/src/i18n/locales/en/common.json | 1 +
frontend/src/i18n/locales/es/common.json | 26 +++
frontend/src/i18n/locales/es/projects.json | 14 ++
frontend/src/i18n/locales/es/settings.json | 171 ++++++++++++++++++
frontend/src/i18n/locales/ja/common.json | 1 +
.../src/pages/settings/GeneralSettings.tsx | 3 +
shared/types.ts | 2 +-
9 files changed, 226 insertions(+), 1 deletion(-)
create mode 100644 frontend/src/i18n/locales/es/common.json
create mode 100644 frontend/src/i18n/locales/es/projects.json
create mode 100644 frontend/src/i18n/locales/es/settings.json
diff --git a/crates/services/src/services/config/versions/v6.rs b/crates/services/src/services/config/versions/v6.rs
index 72f74943..ec9aea5c 100644
--- a/crates/services/src/services/config/versions/v6.rs
+++ b/crates/services/src/services/config/versions/v6.rs
@@ -17,6 +17,7 @@ pub enum UiLanguage {
Browser, // Detect from browser
En, // Force English
Ja, // Force Japanese
+ Es, // Force Spanish
}
#[derive(Clone, Debug, Serialize, Deserialize, TS)]
diff --git a/frontend/src/i18n/config.ts b/frontend/src/i18n/config.ts
index be79668b..a47777d8 100644
--- a/frontend/src/i18n/config.ts
+++ b/frontend/src/i18n/config.ts
@@ -9,6 +9,9 @@ import enProjects from './locales/en/projects.json';
import jaCommon from './locales/ja/common.json';
import jaSettings from './locales/ja/settings.json';
import jaProjects from './locales/ja/projects.json';
+import esCommon from './locales/es/common.json';
+import esSettings from './locales/es/settings.json';
+import esProjects from './locales/es/projects.json';
const resources = {
en: {
@@ -21,6 +24,11 @@ const resources = {
settings: jaSettings,
projects: jaProjects,
},
+ es: {
+ common: esCommon,
+ settings: esSettings,
+ projects: esProjects,
+ },
};
i18n
diff --git a/frontend/src/i18n/locales/en/common.json b/frontend/src/i18n/locales/en/common.json
index 4c1efd5a..08786a32 100644
--- a/frontend/src/i18n/locales/en/common.json
+++ b/frontend/src/i18n/locales/en/common.json
@@ -20,6 +20,7 @@
"language": {
"en": "English",
"ja": "日本語",
+ "es": "Español",
"browserDefault": "Browser Default"
},
"conversation": {
diff --git a/frontend/src/i18n/locales/es/common.json b/frontend/src/i18n/locales/es/common.json
new file mode 100644
index 00000000..e10a07ac
--- /dev/null
+++ b/frontend/src/i18n/locales/es/common.json
@@ -0,0 +1,26 @@
+{
+ "buttons": {
+ "save": "Guardar",
+ "cancel": "Cancelar",
+ "delete": "Eliminar",
+ "edit": "Editar",
+ "create": "Crear",
+ "continue": "Continuar",
+ "reset": "Restablecer",
+ "manage": "Gestionar",
+ "connect": "Conectar",
+ "disconnect": "Desconectar"
+ },
+ "states": {
+ "loading": "Cargando...",
+ "saving": "Guardando...",
+ "error": "Error",
+ "success": "Éxito"
+ },
+ "language": {
+ "en": "English",
+ "ja": "日本語",
+ "es": "Español",
+ "browserDefault": "Predeterminado del navegador"
+ }
+}
diff --git a/frontend/src/i18n/locales/es/projects.json b/frontend/src/i18n/locales/es/projects.json
new file mode 100644
index 00000000..f07209fa
--- /dev/null
+++ b/frontend/src/i18n/locales/es/projects.json
@@ -0,0 +1,14 @@
+{
+ "title": "Proyectos",
+ "subtitle": "Gestiona tus proyectos y sigue su progreso",
+ "createProject": "Crear Proyecto",
+ "loading": "Cargando proyectos...",
+ "errors": {
+ "fetchFailed": "Error al cargar proyectos"
+ },
+ "empty": {
+ "title": "Aún no hay proyectos",
+ "description": "Comienza creando tu primer proyecto.",
+ "createFirst": "Crear tu primer proyecto"
+ }
+}
diff --git a/frontend/src/i18n/locales/es/settings.json b/frontend/src/i18n/locales/es/settings.json
new file mode 100644
index 00000000..893ee960
--- /dev/null
+++ b/frontend/src/i18n/locales/es/settings.json
@@ -0,0 +1,171 @@
+{
+ "settings": {
+ "layout": {
+ "nav": {
+ "title": "Configuración",
+ "general": "General",
+ "generalDesc": "Tema, notificaciones y preferencias",
+ "agents": "Agentes",
+ "agentsDesc": "Configuraciones de agentes",
+ "mcp": "Servidores MCP",
+ "mcpDesc": "Servidores de Protocolo de Contexto de Modelo (MCP)"
+ }
+ },
+ "general": {
+ "loading": "Cargando configuración...",
+ "loadError": "Error al cargar la configuración.",
+ "save": {
+ "button": "Guardar Configuración",
+ "success": "✓ ¡Configuración guardada!",
+ "error": "Error al guardar la configuración"
+ },
+ "appearance": {
+ "title": "Apariencia",
+ "description": "Personaliza cómo se ve la aplicación.",
+ "theme": {
+ "label": "Tema",
+ "placeholder": "Seleccionar tema",
+ "helper": "Elige tus colores preferidos."
+ },
+ "language": {
+ "label": "Idioma",
+ "placeholder": "Selecciona tu idioma",
+ "helper": "Elige tu idioma preferido. El predeterminado del navegador sigue el idioma de tu sistema."
+ }
+ },
+ "taskExecution": {
+ "title": "Ejecución de Tareas",
+ "description": "Configura cómo se ejecutan y procesan las tareas.",
+ "executor": {
+ "label": "Configuración predeterminada del Agente",
+ "placeholder": "Seleccionar perfil",
+ "helper": "Define la configuración predeterminada del agente que se usará al iniciar una tarea."
+ },
+ "variant": "PREDETERMINADO"
+ },
+ "editor": {
+ "title": "Editor",
+ "description": "Configura cómo quieres editar tu código.",
+ "type": {
+ "label": "Tipo de Editor",
+ "placeholder": "Seleccionar editor",
+ "helper": "Elige tu editor de código preferido."
+ }
+ },
+ "github": {
+ "title": "Integración con GitHub",
+ "connected": "Conectado como {{username}}",
+ "connectButton": "Conectar Cuenta de GitHub",
+ "manage": "Gestionar",
+ "disconnect": "Desconectar",
+ "helper": "Conecta tu cuenta de GitHub para acceder a repositorios privados y habilitar acciones avanzadas de Git."
+ },
+ "notifications": {
+ "title": "Notificaciones",
+ "description": "Controla cuándo y cómo recibes notificaciones.",
+ "sound": {
+ "label": "Notificaciones de Sonido",
+ "helper": "Reproduce un sonido cuando una tarea termina de ejecutarse.",
+ "fileLabel": "Sonido",
+ "filePlaceholder": "Seleccionar sonido",
+ "fileHelper": "Elige el sonido que se reproducirá al completar las tareas. Haz clic en el botón de volumen para escucharlo."
+ },
+ "push": {
+ "label": "Notificaciones Push",
+ "helper": "Muestra notificaciones del sistema cuando las tareas terminan de ejecutarse."
+ }
+ },
+ "privacy": {
+ "title": "Privacidad",
+ "description": "Ayuda a mejorar Vibe-Kanban compartiendo datos de uso anónimos.",
+ "telemetry": {
+ "label": "Habilitar Telemetría",
+ "helper": "Habilita el seguimiento anónimo para ayudar a mejorar la aplicación. No se recopilan prompts ni información del proyecto."
+ }
+ },
+ "taskTemplates": {
+ "title": "Plantillas de Tareas",
+ "description": "Gestiona las plantillas globales que se pueden usar en todos los proyectos."
+ },
+ "safety": {
+ "title": "Avisos legales y de seguridad",
+ "description": "Reinicia las confirmaciones de seguridad y de introducción.",
+ "disclaimer": {
+ "title": "Confirmación de Descargo",
+ "description": "Restablecer el aviso de seguridad.",
+ "button": "Restablecer"
+ },
+ "onboarding": {
+ "title": "Introducción",
+ "description": "Restablece el flujo de Introducción.",
+ "button": "Restablecer"
+ }
+ }
+ },
+ "agents": {
+ "title": "Configuraciones de Agentes de Código",
+ "description": "Personaliza el comportamiento de los agentes con diferentes configuraciones.",
+ "loading": "Cargando configuraciones de agentes...",
+ "save": {
+ "button": "Guardar Configuraciones de Agentes",
+ "success": "✓ ¡Configuración guardada con éxito”!"
+ },
+ "editor": {
+ "formLabel": "Editar JSON",
+ "agentLabel": "Agente",
+ "agentPlaceholder": "Seleccionar tipo",
+ "configLabel": "Configuración",
+ "configPlaceholder": "Seleccionar configuración",
+ "createNew": "Crear nuevo...",
+ "deleteTitle": "No se puede eliminar la última configuración",
+ "deleteButton": "Eliminar {{name}}",
+ "deleteText": "Eliminar",
+ "jsonLabel": "Configuración de Agente (JSON)",
+ "jsonPlaceholder": "Cargando perfiles...",
+ "jsonLoading": "Cargando...",
+ "pathLabel": "Ubicación del archivo de configuración:"
+ },
+ "errors": {
+ "deleteFailed": "Error al eliminar la configuración. Por favor, inténtalo de nuevo.",
+ "saveFailed": "Error al guardar la configuración de los agentes. Por favor, inténtalo de nuevo.",
+ "saveConfigFailed": "Error al guardar la configuración. Por favor, inténtalo de nuevo."
+ }
+ },
+ "mcp": {
+ "title": "Configuración de Servidor MCP",
+ "description": "Configura los servidores del Protocolo de Contexto de Modelos (MCP) para ampliar las capacidades del agente de codificación con herramientas y recursos personalizados.",
+ "loading": "Cargando configuración MCP...",
+ "applying": "Aplicando configuración...",
+ "labels": {
+ "agent": "Agente",
+ "agentPlaceholder": "Seleccionar",
+ "agentHelper": "Elige para qué agente configurar los servidores MCP.",
+ "serverConfig": "Configuración de Servidor (JSON)",
+ "popularServers": "Servidores populares",
+ "serverHelper": "Haz clic en una tarjeta para insertar ese Servidor MCP en el JSON de arriba.",
+ "saveLocation": "Los cambios se guardarán en:"
+ },
+ "loading": {
+ "jsonEditor": "Cargando...",
+ "configuration": "Cargando configuración actual del servidor MCP..."
+ },
+ "errors": {
+ "loadFailed": "Error al cargar la configuración.",
+ "invalidJson": "Formato JSON inválido",
+ "validationError": "Error de validación",
+ "saveFailed": "Error al guardar servidores MCP",
+ "applyFailed": "Error al aplicar la configuración del servidor MCP",
+ "addServerFailed": "Error al agregar servidor preconfigurado",
+ "mcpError": "Error de Configuración MCP: {{error}}",
+ "notSupported": "MCP No Soportado",
+ "supportMessage": "Para usar servidores MCP, por favor selecciona un agente diferente que soporte MCP (Claude, Amp, Gemini, Codex, o Opencode) arriba."
+ },
+ "save": {
+ "button": "Guardar Configuración MCP",
+ "success": "¡Configuración Guardada!",
+ "successMessage": "✓ ¡Configuración MCP guardada exitosamente!",
+ "loading": "Cargando configuración actual del servidor MCP..."
+ }
+ }
+ }
+}
diff --git a/frontend/src/i18n/locales/ja/common.json b/frontend/src/i18n/locales/ja/common.json
index 06418603..9a6b1580 100644
--- a/frontend/src/i18n/locales/ja/common.json
+++ b/frontend/src/i18n/locales/ja/common.json
@@ -20,6 +20,7 @@
"language": {
"en": "English",
"ja": "日本語",
+ "es": "Español",
"browserDefault": "ブラウザ設定"
},
"conversation": {
diff --git a/frontend/src/pages/settings/GeneralSettings.tsx b/frontend/src/pages/settings/GeneralSettings.tsx
index adf019b6..52d47f93 100644
--- a/frontend/src/pages/settings/GeneralSettings.tsx
+++ b/frontend/src/pages/settings/GeneralSettings.tsx
@@ -218,6 +218,9 @@ export function GeneralSettings() {
diff --git a/shared/types.ts b/shared/types.ts index b1768ecd..6b595546 100644 --- a/shared/types.ts +++ b/shared/types.ts @@ -100,7 +100,7 @@ export type GitHubConfig = { pat: string | null, oauth_token: string | null, use export enum SoundFile { ABSTRACT_SOUND1 = "ABSTRACT_SOUND1", ABSTRACT_SOUND2 = "ABSTRACT_SOUND2", ABSTRACT_SOUND3 = "ABSTRACT_SOUND3", ABSTRACT_SOUND4 = "ABSTRACT_SOUND4", COW_MOOING = "COW_MOOING", PHONE_VIBRATION = "PHONE_VIBRATION", ROOSTER = "ROOSTER" } -export type UiLanguage = "BROWSER" | "EN" | "JA"; +export type UiLanguage = "BROWSER" | "EN" | "JA" | "ES"; export type DeviceFlowStartResponse = { user_code: string, verification_uri: string, expires_in: number, interval: number, };