From cbf56f0707f99ae3928be6abd8ed76c760adb567 Mon Sep 17 00:00:00 2001 From: Diego Ospina Date: Sat, 10 Oct 2026 22:36:49 -0500 Subject: [PATCH] i18n: Spanish interface translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Language::Es was registered and switches formulas to Spanish (SUMA, decimal comma, semicolon arguments), but every interface label still fell back to English. This adds es.rs with all 266 labels in Excel's Spanish wording (Combinar y centrar, Inmovilizar paneles, Análisis de hipótesis, Buscar objetivo, Rastrear precedentes…) and covers Spanish in the i18n tests. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012JC2QZ1Qc5KQMBswS38GKy --- crates/ui-egui/src/i18n.rs | 8 +- crates/ui-egui/src/i18n/es.rs | 275 +++++++++++++++++++++++++ crates/ui-egui/tests/formula_locale.rs | 2 +- 3 files changed, 283 insertions(+), 2 deletions(-) create mode 100644 crates/ui-egui/src/i18n/es.rs diff --git a/crates/ui-egui/src/i18n.rs b/crates/ui-egui/src/i18n.rs index 1e7b212..e44a032 100644 --- a/crates/ui-egui/src/i18n.rs +++ b/crates/ui-egui/src/i18n.rs @@ -9,6 +9,7 @@ use serde::{Deserialize, Serialize}; +mod es; mod ko; mod pt; mod ru; @@ -97,7 +98,8 @@ impl Language { /// "Orientation") is keyed `context|label`: English shows only the part after the `|`. pub fn tr(self, text: &str) -> &str { let translated = match self { - Self::En | Self::Es => None, + Self::En => None, + Self::Es => es::translate(text), Self::Ja => JAPANESE.iter().find(|(english, _)| *english == text).map(|(_, translated)| *translated), Self::Zh => zh::translate(text), Self::Ko => ko::translate(text), @@ -434,12 +436,16 @@ mod tests { assert!(ko::translate(english).is_some_and(|text| !text.is_empty()), "missing Korean: {english}"); assert!(ru::translate(english).is_some_and(|text| !text.is_empty()), "missing Russian: {english}"); assert!(pt::translate(english).is_some_and(|text| !text.is_empty()), "missing Portuguese: {english}"); + assert!(es::translate(english).is_some_and(|text| !text.is_empty()), "missing Spanish: {english}"); } assert_eq!(Language::Ja.tr("Data"), "データ"); assert_eq!(Language::Zh.tr("Data"), "数据"); assert_eq!(Language::Ko.tr("Data"), "데이터"); assert_eq!(Language::Ru.tr("Data"), "Данные"); assert_eq!(Language::PtBr.tr("Data"), "Dados"); + assert_eq!(Language::Es.tr("Data"), "Datos"); + assert_eq!(Language::Es.tr("Freeze Panes"), "Inmovilizar paneles"); + assert_eq!(Language::Es.tr("Sheet1!A1"), "Sheet1!A1"); assert_eq!(Language::PtBr.tr("Date"), "Data"); assert_eq!(Language::PtBr.tr("Sheet1!A1"), "Sheet1!A1"); assert_eq!(Language::Ja.tr("Sheet1!A1"), "Sheet1!A1"); diff --git a/crates/ui-egui/src/i18n/es.rs b/crates/ui-egui/src/i18n/es.rs new file mode 100644 index 0000000..fe201cc --- /dev/null +++ b/crates/ui-egui/src/i18n/es.rs @@ -0,0 +1,275 @@ +//! Spanish translations for the interface strings in i18n.rs. Labels follow Excel's Spanish +//! wording (sentence case, «Inmovilizar paneles», «Combinar y centrar»); anything absent falls back +//! to English. Formula names and separators are localized separately (`formula_locale`). + +pub(super) fn translate(text: &str) -> Option<&'static str> { + Some(match text { + "Paste" => "Pegar", + "Paste Values" => "Pegar valores", + "Paste Formulas" => "Pegar fórmulas", + "Paste Formatting" => "Pegar formato", + "Transpose" => "Transponer", + "Paste Link" => "Pegar vínculo", + "Paste Special…" => "Pegado especial…", + "Cut (⌘X)" => "Cortar (⌘X)", + "Copy (⌘C)" => "Copiar (⌘C)", + "Format Painter (double-click to keep it on)" => "Copiar formato (doble clic para mantenerlo activo)", + "Bold (⌘B)" => "Negrita (⌘B)", + "Italic (⌘I)" => "Cursiva (⌘I)", + "Underline (⌘U)" => "Subrayado (⌘U)", + "Double Underline" => "Subrayado doble", + "Strikethrough" => "Tachado", + "Underline" => "Subrayado", + "Increase Font Size" => "Aumentar tamaño de fuente", + "Decrease Font Size" => "Disminuir tamaño de fuente", + "Wrap Text" => "Ajustar texto", + "Merge & Center" => "Combinar y centrar", + "Merge Cells" => "Combinar celdas", + "Merge Across" => "Combinar horizontalmente", + "Unmerge Cells" => "Separar celdas", + "Fill Color" => "Color de relleno", + "Font Color" => "Color de fuente", + "Borders" => "Bordes", + "Top\nAlign" => "Alinear en la\nparte superior", + "Middle\nAlign" => "Alinear en\nel medio", + "Bottom\nAlign" => "Alinear en la\nparte inferior", + "Left" => "Izquierda", + "Right" => "Derecha", + "Center" => "Centro", + "Horizontal" => "Horizontal", + "Vertical Text" => "Texto vertical", + "Decrease Indent" => "Disminuir sangría", + "Increase Indent" => "Aumentar sangría", + "Orientation" => "Orientación", + "Angle Counterclockwise" => "Ángulo ascendente", + "Angle Clockwise" => "Ángulo descendente", + "Rotate Text Up" => "Girar texto hacia arriba", + "Rotate Text Down" => "Girar texto hacia abajo", + "Accounting Number Format" => "Formato de número de contabilidad", + "Percent Style" => "Estilo porcentual", + "Comma Style" => "Estilo de millares", + "Increase Decimal" => "Aumentar decimales", + "Decrease Decimal" => "Disminuir decimales", + "More Accounting Formats…" => "Más formatos de contabilidad…", + "Conditional\nFormatting" => "Formato\ncondicional", + "Conditional Formatting" => "Formato condicional", + "Format\nas Table" => "Dar formato\ncomo tabla", + "Cell\nStyles" => "Estilos\nde celda", + "Format Cells…" => "Formato de celdas…", + "Format Cell Alignment…" => "Alineación de celdas…", + "Format\nPane" => "Panel\nde formato", + "Format" => "Formato", + "Insert" => "Insertar", + "Insert Cells…" => "Insertar celdas…", + "Delete" => "Eliminar", + "Delete Cells…" => "Eliminar celdas…", + "Insert Sheet Rows" => "Insertar filas de hoja", + "Insert Sheet Columns" => "Insertar columnas de hoja", + "Delete Sheet Rows" => "Eliminar filas de hoja", + "Delete Sheet Columns" => "Eliminar columnas de hoja", + "Row Height…" => "Alto de fila…", + "AutoFit Row Height" => "Autoajustar alto de fila", + "Column Width…" => "Ancho de columna…", + "AutoFit Column Width" => "Autoajustar ancho de columna", + "Default Width…" => "Ancho predeterminado…", + "Hide Rows" => "Ocultar filas", + "Unhide Rows" => "Mostrar filas", + "Hide Columns" => "Ocultar columnas", + "Unhide Columns" => "Mostrar columnas", + "Lock Cell" => "Bloquear celda", + "Clear" => "Borrar", + "Clear All" => "Borrar todo", + "Clear Formats" => "Borrar formatos", + "Clear Contents" => "Borrar contenido", + "Clear Comments and Notes" => "Borrar comentarios y notas", + "Clear Hyperlinks" => "Borrar hipervínculos", + "AutoSum" => "Autosuma", + "AutoSum (⌘⇧T)" => "Autosuma (⌘⇧T)", + "Flash\nFill" => "Relleno\nrápido", + "Flash Fill" => "Relleno rápido", + "Fill" => "Rellenar", + "Clear Print Area" => "Borrar área de impresión", + "Find &\nSelect" => "Buscar y\nseleccionar", + "Find…" => "Buscar…", + "Replace…" => "Reemplazar…", + "Go To…" => "Ir a…", + "Go To Special…" => "Ir a Especial…", + "PivotTable" => "Tabla dinámica", + "Recommended\nCharts" => "Gráficos\nrecomendados", + "Table" => "Tabla", + "Pictures" => "Imágenes", + "Shapes" => "Formas", + "Icons" => "Iconos", + "Text\nBox" => "Cuadro\nde texto", + "Comment" => "Comentario", + "New\nComment" => "Nuevo\ncomentario", + "New Note" => "Nueva nota", + "Show/Hide Note" => "Mostrar u ocultar nota", + "Header &\nFooter" => "Encabezado y\npie de página", + "Text to\nColumns" => "Texto en\ncolumnas", + "Link" => "Vínculo", + "Symbol" => "Símbolo", + "Sparklines" => "Minigráficos", + "Header & Footer" => "Encabezado y pie de página", + "Draw with ink" => "Dibujar con lápiz", + "Eraser" => "Borrador", + "Ink to\nShape" => "Entrada de lápiz\na forma", + "Select\nObjects" => "Seleccionar\nobjetos", + "Themes" => "Temas", + "Margins" => "Márgenes", + "Size" => "Tamaño", + "Print\nArea" => "Área de\nimpresión", + "Set Print Area" => "Establecer área de impresión", + "Breaks" => "Saltos", + "Insert Page Break" => "Insertar salto de página", + "Remove Page Break" => "Quitar salto de página", + "Reset All Page Breaks" => "Restablecer todos los saltos de página", + "Print\nTitles" => "Imprimir\ntítulos", + "Narrow" => "Estrecho", + "Wide" => "Ancho", + "Normal" => "Normal", + "Portrait" => "Vertical", + "Landscape" => "Horizontal", + "Custom Margins…" => "Márgenes personalizados…", + "Insert\nFunction" => "Insertar\nfunción", + "Name\nManager" => "Administrador\nde nombres", + "Define Name" => "Definir nombre", + "Use in Formula" => "Utilizar en la fórmula", + "Create from Selection" => "Crear desde la selección", + "Trace Precedents" => "Rastrear precedentes", + "Trace Dependents" => "Rastrear dependientes", + "Remove Arrows" => "Quitar flechas", + "Show Formulas" => "Mostrar fórmulas", + "Error Checking" => "Comprobación de errores", + "Evaluate Formula" => "Evaluar fórmula", + "Watch Window" => "Ventana Inspección", + "Calculation\nOptions" => "Opciones\nde cálculo", + "Calculate Now" => "Calcular ahora", + "Calculate Sheet" => "Calcular hoja", + "Automatic" => "Automático", + "Automatic Except for Data Tables" => "Automático excepto en las tablas de datos", + "Manual" => "Manual", + "Sort &\nFilter" => "Ordenar\ny filtrar", + "Sort" => "Ordenar", + "Sort A to Z" => "Ordenar de A a Z", + "Sort Z to A" => "Ordenar de Z a A", + "Custom Sort…" => "Orden personalizado…", + "Filter" => "Filtro", + "Reapply" => "Volver a aplicar", + "Get Data\n(Text/CSV)" => "Obtener datos\n(texto/CSV)", + "Remove\nDuplicates" => "Quitar\nduplicados", + "Data\nValidation" => "Validación\nde datos", + "Data Validation" => "Validación de datos", + "Data Validation…" => "Validación de datos…", + "Circle Invalid Data" => "Rodear con un círculo datos no válidos", + "Clear Validation" => "Borrar círculos de validación", + "Group" => "Agrupar", + "Ungroup" => "Desagrupar", + "Subtotal" => "Subtotal", + "What-If\nAnalysis" => "Análisis de\nhipótesis", + "Data Table…" => "Tabla de datos…", + "Scenario Manager…" => "Administrador de escenarios…", + "Goal Seek…" => "Buscar objetivo…", + "Spelling" => "Ortografía", + "Check\nAccessibility" => "Comprobar\naccesibilidad", + "Threaded Comments" => "Comentarios en conversación", + "Show\nComments" => "Mostrar\ncomentarios", + "Protect\nWorkbook" => "Proteger\nlibro", + "Unprotect\nSheet" => "Desproteger\nhoja", + "Protect Sheet…" => "Proteger hoja…", + "Comments" => "Comentarios", + "Notes" => "Notas", + "Page Break\nPreview" => "Vista previa de\nsalto de página", + "Page\nLayout" => "Diseño\nde página", + "Formula Bar" => "Barra de fórmulas", + "Gridlines" => "Líneas de cuadrícula", + "Headings" => "Encabezados", + "Zoom" => "Zoom", + "100%" => "100%", + "Zoom to\nSelection" => "Ampliar\nselección", + "Freeze\nPanes" => "Inmovilizar\npaneles", + "Freeze Panes" => "Inmovilizar paneles", + "Freeze Top Row" => "Inmovilizar fila superior", + "Freeze First Column" => "Inmovilizar primera columna", + "Unfreeze Panes" => "Movilizar paneles", + "Dark Mode" => "Modo oscuro", + "Interface language" => "Idioma de la interfaz", + "Command\nPalette" => "Paleta de\ncomandos", + "Agent\nControl" => "Control\ndel agente", + "Action\nJournal" => "Registro\nde acciones", + "About\nGridCraft" => "Acerca de\nGridCraft", + "Share" => "Compartir", + "Add Chart\nElement" => "Agregar elemento\nde gráfico", + "Change\nChart Type" => "Cambiar tipo\nde gráfico", + "Switch\nRow/Column" => "Cambiar entre\nfilas y columnas", + "Data Labels: None" => "Etiquetas de datos: ninguna", + "Data Labels: Show" => "Etiquetas de datos: mostrar", + "Legend: None" => "Leyenda: ninguna", + "Legend: Bottom" => "Leyenda: abajo", + "Legend: Top" => "Leyenda: arriba", + "Legend: Right" => "Leyenda: derecha", + "Gridlines: None" => "Líneas de cuadrícula: ninguna", + "Gridlines: Show" => "Líneas de cuadrícula: mostrar", + "Chart\nTitle" => "Título\ndel gráfico", + "Delete\nChart" => "Eliminar\ngráfico", + "Convert\nto Range" => "Convertir\nen rango", + "Table\nStyles" => "Estilos\nde tabla", + "Top 10 Items" => "10 superiores", + "Top 10%" => "10% superior", + "Bottom 10 Items" => "10 inferiores", + "Bottom 10%" => "10% inferior", + "Above Average" => "Por encima del promedio", + "Below Average" => "Por debajo del promedio", + "Clear Rules from Entire Sheet" => "Borrar reglas de toda la hoja", + "Clear Rules from Selected Cells" => "Borrar reglas de las celdas seleccionadas", + "Constants" => "Constantes", + "Data Bars" => "Barras de datos", + "Color Scales" => "Escalas de color", + "Icon Sets" => "Conjuntos de iconos", + "Home" => "Inicio", + "Draw" => "Dibujar", + "Page Layout" => "Disposición de página", + "Formulas" => "Fórmulas", + "Data" => "Datos", + "Review" => "Revisar", + "View" => "Vista", + "Automate" => "Automatizar", + "Table Design" => "Diseño de tabla", + "Chart Design" => "Diseño de gráfico", + "Ready" => "Listo", + "Enter" => "Introducir", + "Edit" => "Modificar", + "Point" => "Señalar", + "Calculate" => "Calcular", + "Select destination and press Enter or choose Paste" => "Seleccione el destino y presione Entrar o elija Pegar", + "General" => "General", + "Number" => "Número", + "Currency" => "Moneda", + "Accounting" => "Contabilidad", + "Date" => "Fecha", + "Time" => "Hora", + "Percentage" => "Porcentaje", + "Fraction" => "Fracción", + "Scientific" => "Científica", + "Text" => "Texto", + "Special" => "Especial", + "Custom" => "Personalizada", + "Short Date" => "Fecha corta", + "Long Date" => "Fecha larga", + "More Number Formats…" => "Más formatos de número…", + "Financial" => "Financieras", + "Logical" => "Lógicas", + "Date &\nTime" => "Fecha\ny hora", + "Lookup &\nReference" => "Búsqueda y\nreferencia", + "Math &\nTrig" => "Matemáticas y\ntrigonométricas", + "More\nFunctions" => "Más\nfunciones", + "Page Layout|Orientation" => "Orientación", + "Display theme" => "Tema de la interfaz", + "System" => "Sistema", + "Light" => "Claro", + "Dark" => "Oscuro", + "Sheet Options|View" => "Ver", + "Print" => "Imprimir", + _ => return None, + }) +} diff --git a/crates/ui-egui/tests/formula_locale.rs b/crates/ui-egui/tests/formula_locale.rs index a92ab13..9dcb65d 100644 --- a/crates/ui-egui/tests/formula_locale.rs +++ b/crates/ui-egui/tests/formula_locale.rs @@ -183,5 +183,5 @@ fn portuguese_interface_retains_its_canonical_formula_fallback() { assert!(!enter(&mut app, "=SUMA(1;2)")); let restored: UiState = serde_json::from_str(&serde_json::to_string(&app.ui).unwrap()).unwrap(); assert_eq!(restored.language, Language::PtBr); - assert_eq!(Language::Es.tr("Page Layout|Orientation"), "Orientation"); + assert_eq!(Language::Es.tr("Page Layout|Orientation"), "Orientación"); }