feat(i18n): add Spanish localization and improve locale switching (#212)

* feat(i18n): add Spanish localization and improve locale switching

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Marcos Leandro Bonilla Borges 2026-05-11 00:09:13 -04:00 committed by GitHub
parent 7c72a09b59
commit 3c0dbb3e30
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 939 additions and 4 deletions

View File

@ -28,7 +28,7 @@ import { useDialogSources } from "@/composables/useDialogSources";
import { useNavigationTargets } from "@/composables/useNavigationTargets";
import { useDataGridActions } from "@/composables/useDataGridActions";
import { useTauriEvents } from "@/composables/useTauriEvents";
import { setLocale, currentLocale } from "@/i18n";
import { setLocale, currentLocale, nextLocale } from "@/i18n";
import * as api from "@/lib/api";
import { resolveDefaultDatabase } from "@/lib/defaultDatabase";
import { resolveExecutableSql } from "@/lib/sqlExecutionTarget";
@ -377,7 +377,7 @@ function changeActiveSchema(schema: string | undefined) {
}
function toggleLocale() {
setLocale(currentLocale() === "zh-CN" ? "en" : "zh-CN");
setLocale(nextLocale(currentLocale()));
}
function openGitHub() {
openUrl("https://github.com/t8y2/dbx");

View File

@ -1,10 +1,21 @@
import { createI18n } from "vue-i18n";
import en from "./locales/en";
import es from "./locales/es";
import zhCN from "./locales/zh-CN";
export type Locale = "en" | "zh-CN";
export type Locale = "en" | "es" | "zh-CN";
const savedLocale = (localStorage.getItem("dbx-locale") as Locale) || "zh-CN";
const supportedLocales: Locale[] = ["en", "es", "zh-CN"];
const defaultLocale: Locale = "zh-CN";
function normalizeLocale(value: string | null): Locale {
if (value && supportedLocales.includes(value as Locale)) {
return value as Locale;
}
return defaultLocale;
}
const savedLocale = normalizeLocale(localStorage.getItem("dbx-locale"));
const i18n = createI18n({
legacy: false,
@ -12,6 +23,7 @@ const i18n = createI18n({
fallbackLocale: "en",
messages: {
en,
es,
"zh-CN": zhCN,
},
});
@ -25,4 +37,10 @@ export function currentLocale(): Locale {
return i18n.global.locale.value as Locale;
}
export function nextLocale(current: Locale): Locale {
const index = supportedLocales.indexOf(current);
const nextIndex = index === -1 ? 0 : (index + 1) % supportedLocales.length;
return supportedLocales[nextIndex];
}
export default i18n;

917
src/i18n/locales/es.ts Normal file
View File

@ -0,0 +1,917 @@
export default {
app: {
name: "DBX",
},
auth: {
setupTitle: "Configurar contraseña de acceso",
setupDescription: "Establece una contraseña para proteger tu instancia",
loginDescription: "Herramienta de administración de bases de datos",
newPassword: "Ingresa la nueva contraseña",
confirmPassword: "Confirmar contraseña",
enterPassword: "Ingresa la contraseña de acceso",
passwordMismatch: "Las contraseñas no coinciden",
setPassword: "Establecer contraseña",
login: "Iniciar sesión",
processing: "Procesando...",
loginFailed: "Contraseña incorrecta",
connectFailed: "Error de conexión",
changePassword: "Cambiar contraseña",
oldPassword: "Contraseña actual",
oldPasswordWrong: "La contraseña actual es incorrecta",
passwordChanged: "Contraseña cambiada exitosamente",
changePasswordFailed: "Error al cambiar la contraseña",
changePasswordDescription: "Ingresa tu contraseña actual y elige una nueva",
},
toolbar: {
newConnection: "Nueva conexión",
newQuery: "Nueva consulta",
execute: "Ejecutar",
executeShortcut: "Ejecutar selección/consulta (Cmd+Enter)",
stopQuery: "Detener consulta",
explainPlan: "Plan de ejecución",
stopExplain: "Detener análisis",
formatSql: "Formatear SQL",
formatSqlFailed: "Error al formatear el SQL",
saveSql: "Guardar en biblioteca SQL",
openSql: "Abrir archivo SQL",
sqlSaved: "SQL guardado",
sqlOpenFailed: "Error al abrir el archivo: {message}",
sqlSaveFailed: "Error al guardar el archivo: {message}",
},
updates: {
title: "Actualizaciones",
check: "Buscar actualizaciones",
availableTitle: "Actualización disponible",
availableMessage: "DBX {latest} está disponible. Estás usando la versión {current}.",
upToDate: "DBX está actualizado ({version}).",
failed: "Error al buscar actualizaciones: {error}",
rateLimited:
"Las verificaciones de actualizaciones de GitHub están temporalmente limitadas. Puedes abrir la página de lanzamientos para verificar manualmente.",
openRelease: "Abrir lanzamiento",
downloadAndInstall: "Descargar e instalar",
downloading: "Descargando {progress}%",
downloadFailed: "Error al descargar la actualización: {error}",
restart: "Salir y reiniciar",
restartFailed: "Error al reiniciar la aplicación: {error}",
exitAndUpdate: "Salir y actualizar",
reopenHint: "La aplicación se reiniciará para completar la actualización",
},
sidebar: {
connections: "CONEXIONES",
noConnections: "Sin conexiones",
import: "Importar conexiones",
importDbx: "Importar configuración DBX",
importNavicat: "Importar Navicat NCX",
importDbeaver: "Importar DBeaver",
export: "Exportar conexiones",
showMore: "Mostrar {count} más...",
filterByType: "Filtrar por tipo",
clearFilter: "Limpiar filtro",
},
savedSql: {
saveToLibrary: "Guardar en biblioteca SQL",
save: "Guardar",
saved: "SQL guardado",
saveFailed: "Error al guardar el SQL: {message}",
fileName: "Nombre de archivo",
folder: "Carpeta",
rootFolder: "Biblioteca SQL",
newFolder: "Nueva carpeta SQL",
newFolderDefault: "Nueva carpeta",
renameFolder: "Renombrar carpeta",
deleteFolder: "Eliminar carpeta",
deleteFolderConfirm: "¿Eliminar “{name}” y los archivos SQL que contiene?",
open: "Abrir SQL",
renameFile: "Renombrar SQL",
deleteFile: "Eliminar SQL",
deleteFileConfirm: "¿Eliminar “{name}”?",
},
connection: {
title: "Nueva conexión",
name: "Nombre",
namePlaceholder: "Mi base de datos",
type: "Tipo",
host: "Host",
filePath: "Ruta del archivo",
user: "Usuario",
password: "Contraseña",
database: "Base de datos",
databasePlaceholder: "Opcional",
databasePlaceholderWithDefault: "Opcional, por defecto {database}",
serviceName: "Servicio/SID",
driverName: "Nombre del driver",
driverNamePlaceholder: "Nombre del proveedor o entorno",
urlParams: "Parámetros de URL",
connectionUrlOptional: "URL (opcional)",
connectionUrlPlaceholder: "postgresql://usuario:contraseña{'@'}host:5432/db?sslmode=require",
parseConnectionUrl: "Analizar URL de conexión",
parseConnectionUrlApplied: "URL de conexión aplicada",
parseConnectionUrlFailed: "Error al analizar la URL de conexión: {message}",
mode: "Modo de conexión",
modeForm: "Formulario",
searchDatabasePlaceholder: "Buscar tipos de bases de datos",
iconView: "Vista de íconos",
listView: "Vista de lista",
selectedDatabase: "Seleccionada",
noDatabaseMatches: "Sin bases de datos coincidentes",
next: "Siguiente",
back: "Anterior",
basicTab: "Conexión",
test: "Probar",
testing: "Probando...",
copyTestResult: "Copiar resultado de prueba",
saveAndConnect: "Guardar y conectar",
save: "Guardar",
editTitle: "Editar conexión",
testSuccess: "Conexión exitosa",
connecting: "Conectando a {name}...",
connectSuccess: "Conectado a {name}",
connectFailed: "Error de conexión: {message}",
lastError: "Error de conexión",
clearError: "Limpiar error de conexión",
saveFailed: "Error al guardar la conexión: {message}",
loadFailed: "Error al cargar las conexiones guardadas: {message}",
sshTunnel: "Túnel SSH",
sshEnable: "Conectar mediante túnel SSH",
sshHost: "Host SSH",
sshUser: "Usuario SSH",
sshPassword: "Contraseña SSH",
sshPasswordPlaceholder: "Dejar vacío para usar clave",
sshKeyPath: "Ruta de clave",
sshKeyPassphrase: "Frase de clave",
sshKeyPassphrasePlaceholder: "Dejar vacío si la clave no está cifrada",
sshKeyPathBrowse: "Examinar",
sshExposeLan: "Exponer túnel a la red local",
sshConnectTimeout: "Tiempo de espera SSH (segundos)",
jdbcUrl: "URL JDBC",
jdbcUrlPlaceholder: "jdbc:postgresql://localhost:5432/base_de_datos",
jdbcDriverClass: "Clase del driver (opcional)",
jdbcDriverClassPlaceholder: "La mayoría de los drivers se registran automáticamente; usa com.vendor.jdbc.Driver si es necesario",
jdbcDriverPaths: "JARs del driver JDBC",
jdbcDriverSelectPlaceholder: "Seleccionar driver importado",
jdbcDriverPathsPlaceholder: "/ruta/al/driver.jar\n/ruta/a/otro-driver.jar",
jdbcDriverBrowse: "Seleccionar JAR del driver JDBC",
jdbcDocs: "Ver documentación JDBC",
jdbcPluginHint: "Instala primero el plugin JDBC de DBX y luego importa el JAR del driver JDBC del proveedor.",
dmCompatHint: "Requiere el driver ODBC DM8 instalado en el sistema.",
dmDownload: "Descargar desde Dameng",
mongoLegacyHint:
"Para servidores MongoDB más antiguos, ingresa authSource=admin&authMechanism=SCRAM-SHA-1 aquí; agrega directConnection=true solo cuando sea necesario para conexiones directas a instancias independientes.",
compatible: "Compatible",
mainstream: "Popular",
color: "Color",
colorNone: "Sin color",
colorGreen: "Verde",
colorYellow: "Amarillo",
colorOrange: "Naranja",
colorRed: "Rojo",
colorBlue: "Azul",
colorPurple: "Morado",
},
editor: {
pressToExecute: "Presiona {mod}+Enter para ejecutar",
pressToSaveSql: "Presiona {mod}+S para guardar el SQL",
noDatabase: "Sin base de datos seleccionada",
selectConnection: "Seleccionar conexión",
selectDatabase: "Seleccionar base de datos",
selectSchema: "Seleccionar esquema",
setDefaultDatabase: "Establecer como predeterminada",
defaultDatabase: "Predeterminada",
},
tabs: {
sql: "SQL",
table: "Tabla",
tableData: "Datos de tabla",
redis: "Redis",
mongo: "Mongo",
objects: "Objetos",
tooltipConnection: "Conexión:",
tooltipDatabase: "Base de datos:",
tooltipTable: "Tabla:",
tooltipCollection: "Colección:",
tooltipSchema: "Esquema:",
resultN: "Resultado {n}",
scrollLeft: "Desplazar pestañas a la izquierda",
scrollRight: "Desplazar pestañas a la derecha",
},
chart: {
title: "Gráfico",
type: "Tipo",
line: "Línea",
bar: "Barras",
pie: "Circular",
noNumericData: "No hay datos numéricos disponibles para graficar",
},
grid: {
rows: "{count} filas",
totalRows: "Total {count} filas",
rowsAffected: "{count} filas afectadas",
querySuccess: "Consulta ejecutada exitosamente",
noRows: "Sin datos",
noRowsDescription: "Este conjunto de resultados no tiene registros.",
noSearchResults: "Sin coincidencias",
noSearchResultsDescription: "Intenta con otra palabra clave.",
noFilteredRows: "Ninguna fila coincide con el filtro",
noFilteredRowsDescription: "Ajusta el texto de búsqueda o el filtro de estado de filas.",
copy: "Copiar",
copyCell: "Copiar celda",
copyRow: "Copiar fila (JSON)",
copyRowInsert: "Copiar como INSERT",
copyAll: "Copiar todo (TSV)",
selection: "Selección",
copySelectionTsv: "Copiar selección (TSV)",
copySelectionCsv: "Copiar selección (CSV)",
copySelectionJson: "Copiar selección (JSON)",
copySelectionSql: "Copiar selección como lista SQL IN",
clearSelection: "Limpiar selección",
export: "Exportar",
exportCsv: "Exportar CSV",
exportXlsx: "Exportar XLSX",
exportJson: "Exportar JSON",
exportMarkdown: "Exportar Markdown",
exported: "Exportado",
exportFailed: "Error al exportar: {message}",
filter: "Filtrar",
localFilter: "Filtro local de columna",
localFilterFor: "Filtro local para '{column}'",
searchValues: "Buscar valores...",
value: "Valor",
count: "Conteo",
applyFilter: "Aplicar filtro",
clearLocalFilters: "Limpiar filtros locales de columnas",
moreValues: "{count} valores más, sigue escribiendo para acotar los resultados",
filterByValue: "Filtrar por este valor",
filterExcludeValue: "Excluir este valor",
filterIsNull: "Mostrar valores NULL",
filterIsNotNull: "Mostrar valores no NULL",
clearFilter: "Limpiar filtro",
sort: "Ordenar",
sortAscending: "Orden ascendente",
sortDescending: "Orden descendente",
clearSort: "Limpiar orden",
copied: "¡Copiado!",
pasted: "¡Pegado!",
search: "Buscar...",
searchOrWhere: "Buscar, o ingresar una cláusula WHERE...",
applyWhere: "Aplicar WHERE",
filterRows: "Filtrar filas",
filterAllRows: "Todas las filas",
filterChangedRows: "Modificadas",
page: "Página {page}",
rowsPerPage: "Filas por página",
save: "Guardar",
discard: "Descartar",
dismiss: "Cerrar",
addRow: "Agregar fila",
deleteRow: "Eliminar fila",
restoreRow: "Restaurar fila",
statusClean: "Sin cambios",
statusNew: "Elementos nuevos",
statusEdited: "Elementos modificados",
statusDeleted: "Elementos eliminados",
pendingChanges: "{count} pendientes",
selectedCells: "{count} seleccionadas",
cellDetails: "Detalles de celda",
cellValue: "Valor",
columnName: "Columna",
columnType: "Tipo",
columnComment: "Comentario",
rowNumber: "Fila",
valueLength: "Longitud",
nullValue: "NULL",
noComment: "Sin comentario",
formattedJson: "JSON formateado",
copyValue: "Copiar valor",
editValue: "Editar valor",
setNull: "Establecer NULL",
copyColumnName: "Copiar nombre de columna",
copySqlCondition: "Copiar condición SQL",
transpose: "Transponer fila",
rowsPerPageShort: " filas",
columnDetails: "Detalles de columna",
queryError: "Error de consulta",
refresh: "Actualizar",
commit: "Confirmar",
rollback: "Revertir",
transactionActive: "Editando",
sortUnsupported: "Este SQL no admite ordenamiento del resultado completo. Intenta con una consulta SELECT simple.",
truncatedHint: "Los resultados están limitados a 10.000 filas. Usa LIMIT/OFFSET en tu consulta para paginar.",
},
welcome: {
title: "Espacio de trabajo de base de datos",
subtitle: "Selecciona una conexión a la izquierda para explorar el esquema, o abre una pestaña de consulta directamente.",
connections: "Conexiones",
connected: "Conectado",
databaseTypes: "Tipos de bases de datos",
quickConnections: "Inicio rápido",
quickConnectionsHint: "Haz clic en una conexión para abrir una pestaña de consulta.",
shortcuts: "Atajos",
shortcutsHint: "Inicia la siguiente acción desde aquí.",
tip: "También puedes expandir las conexiones a la izquierda y hacer clic derecho en bases de datos o tablas para más opciones.",
tipSidebar: "Haz clic en una tabla a la izquierda para ver los datos",
tipExecute: "para ejecutar la consulta",
fileOpened: "Abierto {name}",
mcpTitle: "Integración con agentes de IA",
mcpDescription:
"Además del asistente de IA integrado, puedes usar Claude Code, Cursor y otros agentes de programación para consultar tus bases de datos mediante MCP.",
mcpLearnMore: "Más información",
},
common: {
language: "Idioma",
loading: "Cargando...",
stopping: "Deteniendo...",
close: "Cerrar",
},
explain: {
title: "Plan de ejecución",
tree: "Árbol",
summary: "Resumen",
running: "Leyendo plan de ejecución...",
empty: "Sin plan de ejecución",
nodeCount: "{count} nodos",
node: "Nodo",
relation: "Tabla",
index: "Índice",
cost: "Costo",
rows: "Filas",
details: "Detalles",
unsupported: "El plan de ejecución aún no está disponible para esta base de datos",
emptySql: "No hay SQL para analizar",
unsafe: "Esta versión solo analiza sentencias SELECT / WITH / TABLE / VALUES",
},
lineage: {
title: "Linaje de campo",
open: "Ver linaje de campo",
loading: "Leyendo metadatos {done}/{total}",
empty: "Sin linaje relacionado",
noFiltered: "Ningún resultado coincide con los filtros actuales",
targetField: "Campo actual",
searchPlaceholder: "Buscar tablas, campos, vistas o fragmentos SQL...",
showing: "Mostrando {shown}/{total} resultados",
all: "Todos",
certain: "Confirmado",
likely: "Probable",
possible: "Posible",
queryHistory: "Historial de consultas",
openTable: "Abrir tabla",
copy: "Copiar nombre",
copied: "Copiado",
kind: {
foreignKey: "Clave foránea",
viewReference: "Vista",
historyReference: "Historial SQL",
sameName: "Mismo nombre",
},
description: {
foreignKeyIncoming: "{target} apunta al campo actual mediante una clave foránea. Esta es una dependencia verificada.",
foreignKeyOutgoing: "El campo actual referencia a {target} mediante una clave foránea. Esta es una dependencia verificada.",
viewLikely: "La definición de la vista menciona tanto la tabla como el campo destino, lo que generalmente indica una dependencia de consulta.",
viewPossible:
"La definición de la vista menciona un campo con el mismo nombre pero no la tabla destino, por lo que requiere confirmación.",
historyLikely:
"Una sentencia SQL del historial menciona tanto la tabla como el campo destino. Úsala como contexto de análisis de impacto.",
historyPossible: "Una sentencia SQL del historial menciona un campo con el mismo nombre. Puede estar relacionado pero requiere verificación.",
sameName:
"Otra tabla tiene un campo con el mismo nombre. Puede compartir significado de negocio, pero no es una dependencia verificada en la base de datos.",
},
cancel: "Cancelar",
refresh: "Analizar de nuevo",
},
connectionGroup: {
createGroup: "Nuevo grupo",
groupNamePlaceholder: "Nombre del grupo",
renameGroup: "Renombrar grupo",
deleteGroup: "Eliminar grupo",
moveToGroup: "Mover al grupo",
moveToNewGroup: "Mover a nuevo grupo",
ungrouped: "Sin grupo",
newGroup: "Nuevo grupo...",
newGroupDefault: "Nuevo grupo",
deleteGroupConfirmTitle: "Eliminar grupo",
deleteGroupConfirmMessage: '¿Eliminar el grupo "{name}"? Las conexiones dentro serán movidas al nivel superior.',
},
databaseSearch: {
title: "Buscar en base de datos",
open: "Buscar en base de datos",
keyword: "Palabra clave",
keywordPlaceholder: "Ingresa un ID de usuario, correo, número de orden...",
limitPerTable: "Por tabla",
search: "Buscar",
searching: "Buscando",
stop: "Detener",
hint: "Analiza las tablas regulares de la base de datos o esquema actual. Se omiten las columnas binarias y cada tabla tiene un límite para evitar cargar demasiados datos a la vez.",
loadingTables: "Leyendo lista de tablas...",
progress: "Analizadas {done}/{total} tablas",
resultCount: "{count} coincidencias",
limitedTables: "Esquema grande detectado; solo se analizan las primeras {count} tablas",
results: "Resultados",
openResult: "Abrir",
waiting: "Esperando coincidencias...",
noResults: "Sin coincidencias aún",
errors: "Algunas tablas fallaron",
},
configExport: {
passphraseTitle: "Cifrar y exportar",
passphraseImportTitle: "Descifrar e importar",
passphraseExportHint:
"Para incluir las contraseñas de conexión en la exportación, define una frase de paso para el cifrado. Necesitarás la misma frase para importar.",
passphraseImportHint: "Este archivo está cifrado. Ingresa la frase de paso para descifrarlo e importarlo.",
passphrase: "Frase de paso",
passphraseConfirm: "Confirmar frase de paso",
passphrasePlaceholder: "Ingresa la frase de paso",
passphraseConfirmPlaceholder: "Vuelve a ingresar la frase de paso",
passphraseRequired: "La frase de paso es obligatoria",
passphraseMismatch: "Las frases de paso no coinciden",
passphraseTooShort: "La frase de paso debe tener al menos 4 caracteres",
exportEncrypted: "Exportar",
decryptImport: "Descifrar e importar",
wrongPassphrase: "Frase de paso incorrecta o archivo corrupto",
exportSuccess: "Conexiones exportadas exitosamente",
importSuccess: "Se importaron {count} conexión(es)",
importNavicatSuccess:
"Se importaron {count} conexión(es) de Navicat. Completa la contraseña de las conexiones que aún la tengan vacía antes de probarlas.",
importDbeaverSuccess:
"Se importaron {count} conexión(es) de DBeaver. Completa la contraseña de las conexiones que aún la tengan vacía antes de probarlas.",
importNone: "No hay nuevas conexiones para importar",
importLayoutConfirm: "El archivo importado contiene grupos de conexiones. ¿Deseas aplicarlos?",
importLayoutTitle: "Importar grupos",
importLayoutApply: "Aplicar",
},
ai: {
placeholder: "Describe tu consulta en lenguaje natural...",
settings: "Configuración de IA",
provider: "Proveedor",
run: "Ejecutar",
readingSchema: "Leyendo esquema",
noConnection: "No hay una conexión disponible para esta pestaña",
noSql: "No hay SQL para procesar",
sqlPreview: "Vista previa de SQL",
copySql: "Copiar SQL",
executeSql: "Ejecutar SQL",
copyAll: "Copiar todo",
copied: "Copiado",
replace: "Reemplazar en el editor",
append: "Agregar al editor",
apply: "Aplicar al editor",
clear: "Limpiar chat",
welcome: "Dime qué quieres consultar y escribiré el SQL",
newChat: "Nuevo chat",
thinking: "Procesando...",
reasoningProcess: "Proceso de razonamiento",
stopGenerating: "Detener generación",
fixWithAi: "Corregir con IA",
truncated: "Contexto truncado",
contextSummary: "{database} · {tables} tablas",
autoSqlBlocked: "El SQL generado por la IA parecía demasiado riesgoso para ejecutarse automáticamente. Revísalo manualmente antes de ejecutar.",
settingsHint:
"La configuración se almacena en el directorio de datos local de la aplicación. Las solicitudes son enviadas por el backend de Tauri en lugar de directamente desde el frontend.",
actions: {
generate: "Generar SQL",
explain: "Explicar SQL",
optimize: "Optimizar SQL",
fix: "Corregir error",
convert: "Convertir dialecto",
sampleData: "Datos de ejemplo",
},
placeholders: {
generate: "Describe lo que quieres consultar, p. ej. pedidos por usuario en los últimos 7 días",
explain: "Opcional: indica qué quieres entender",
optimize: "Opcional: indica un objetivo, p. ej. reducir los escaneos completos de tabla",
fix: "Pega el error o describe el resultado esperado",
convert: "P. ej. convertir a PostgreSQL / MySQL / SQL Server",
sampleData: "Describe los datos de ejemplo o sentencias de prueba a generar",
},
},
contextMenu: {
openConnection: "Abrir conexión",
closeConnection: "Cerrar conexión",
deleteConnection: "Eliminar conexión",
confirmDeleteTitle: "Eliminar conexión",
confirmDeleteMessage: '¿Estás seguro de que deseas eliminar "{name}"? Esta acción no se puede deshacer.',
editConnection: "Editar conexión",
duplicateConnection: "Duplicar conexión",
newQuery: "Nueva consulta",
openObjectBrowser: "Explorar objetos",
viewData: "Ver datos",
editStructure: "Editar estructura",
refreshChildren: "Actualizar",
pin: "Fijar",
unpin: "Desfijar",
refreshTab: "Actualizar datos",
closeTab: "Cerrar pestaña",
closeOtherTabs: "Cerrar otras pestañas",
closeAllTabs: "Cerrar todas las pestañas",
copyName: "Copiar nombre",
setDefaultDatabase: "Establecer como base de datos predeterminada",
clearDefaultDatabase: "Limpiar base de datos predeterminada",
exportDatabase: "Exportar base de datos",
exportDatabaseSuccess: "Se exportaron {count} tablas, hasta {limit} filas cada una",
exportDatabaseFailed: "Error al exportar la base de datos: {message}",
importData: "Importar datos",
exportData: "Exportar datos",
exportStructure: "Exportar estructura",
createTable: "Crear tabla",
dropTable: "Eliminar tabla",
emptyTable: "Vaciar tabla",
truncateTable: "Truncar tabla",
duplicateStructure: "Duplicar estructura",
confirmDropTableTitle: "Eliminar tabla",
confirmDropTableMessage:
'¿Estás seguro de que deseas eliminar "{name}"? Esto borrará permanentemente la tabla y todos sus datos.',
confirmEmptyTableTitle: "Vaciar tabla",
confirmEmptyTableMessage: '¿Estás seguro de que deseas eliminar todos los datos de "{name}"?',
confirmTruncateTableTitle: "Truncar tabla",
confirmTruncateTableMessage: '¿Estás seguro de que deseas truncar "{name}"? Esto eliminará todas las filas.',
dropTableSuccess: 'Tabla "{name}" eliminada',
emptyTableSuccess: 'Todos los datos eliminados de "{name}"',
truncateTableSuccess: 'Tabla "{name}" truncada',
duplicateStructureSuccess: 'Estructura de tabla duplicada como "{name}"',
tableOperationFailed: "Error en la operación: {message}",
duplicateNameTitle: "Duplicar estructura",
duplicateNamePlaceholder: "Nombre de la nueva tabla",
createDatabase: "Crear base de datos",
dropDatabase: "Eliminar base de datos",
confirmDropDatabaseTitle: "Eliminar base de datos",
confirmDropDatabaseMessage:
'¿Estás seguro de que deseas eliminar la base de datos "{name}"? Esto borrará permanentemente la base de datos y todos sus datos.',
createDatabaseSuccess: 'Base de datos "{name}" creada',
dropDatabaseSuccess: 'Base de datos "{name}" eliminada',
createDatabaseNamePlaceholder: "Nombre de la base de datos",
createSchema: "Crear esquema",
dropSchema: "Eliminar esquema",
confirmDropSchemaTitle: "Eliminar esquema",
confirmDropSchemaMessage:
'¿Estás seguro de que deseas eliminar el esquema "{name}"? Esto borrará permanentemente el esquema y todos sus objetos.',
createSchemaSuccess: 'Esquema "{name}" creado',
dropSchemaSuccess: 'Esquema "{name}" eliminado',
createSchemaNamePlaceholder: "Nombre del esquema",
},
tree: {
savedSql: "Biblioteca SQL",
columns: "Columnas",
indexes: "Índices",
foreignKeys: "Claves foráneas",
triggers: "Disparadores",
objectBrowser: "Explorar en el navegador de objetos ({count})",
},
objects: {
all: "Todos",
tables: "Tablas",
views: "Vistas",
procedures: "Procedimientos",
functions: "Funciones",
table: "Tabla",
view: "Vista",
procedure: "Procedimiento",
function: "Función",
name: "Nombre",
type: "Tipo",
schemaColumn: "Esquema",
comment: "Comentario",
loadingSchemas: "Cargando esquemas...",
schema: "Esquema",
search: "Buscar tablas, vistas, funciones o procedimientos...",
loading: "Cargando objetos...",
empty: "No se encontraron objetos",
},
structureEditor: {
title: "Editar estructura de tabla",
createTitle: "Crear tabla",
tableName: "Nombre de tabla",
refresh: "Actualizar estructura",
columns: "Columnas",
indexes: "Índices",
foreignKeys: "Claves foráneas",
triggers: "Disparadores",
addColumn: "Agregar columna",
addIndex: "Agregar índice",
columnName: "Columna",
dataType: "Tipo",
nullable: "Admite nulos",
defaultValue: "Valor por defecto",
comment: "Comentario",
actions: "Acciones",
indexName: "Índice",
indexColumns: "Columnas",
indexColumnsPlaceholder: "Seleccionar columnas...",
unique: "Único",
indexType: "Tipo",
includedColumns: "Incluidas",
includedColumnsPlaceholder: "Seleccionar columnas...",
filter: "Filtro",
primary: "Primaria",
drop: "Eliminar",
restore: "Restaurar",
remove: "Quitar",
yes: "Sí",
no: "No",
emptyReadonly: "Sin registros",
sqlPreview: "Vista previa de SQL",
noChanges: "Sin cambios",
apply: "Aplicar cambios",
ready: "Listo",
saved: "Estructura de tabla actualizada",
},
diagram: {
title: "Diagrama de relaciones",
open: "Ver diagrama",
selectConnection: "Seleccionar conexión",
selectDatabase: "Seleccionar base de datos",
selectSchema: "Seleccionar esquema",
searchTables: "Buscar tablas, columnas, claves...",
refresh: "Actualizar diagrama",
loading: "Leyendo relaciones...",
loadingProgress: "Leyendo relaciones... {loaded}/{total}",
partialError: "Se omitieron los metadatos de {count} tablas que no pudieron cargarse",
selectTarget: "Selecciona una conexión y base de datos",
empty: "No hay tablas para mostrar",
noMatches: "No hay tablas coincidentes",
tablesCount: "{count} tablas",
relationshipsCount: "{count} relaciones",
tableMode: "Vista de tabla",
engineeringMode: "ER de ingeniería",
allTables: "Todas las tablas",
relatedTables: "Tablas relacionadas",
moreColumns: "+ {count} columnas",
exportSvg: "Exportar SVG",
exportedSvg: "SVG exportado",
exportSvgFailed: "Error al exportar SVG: {message}",
zoomIn: "Acercar",
zoomOut: "Alejar",
resetLayout: "Restablecer diseño",
},
redis: {
selectKey: "Selecciona una clave para ver su valor",
noKeys: "No se encontraron claves",
pattern: "patrón (p. ej. usuario:*)",
keys: "{count} claves",
loadingKeys: "Cargando claves...",
loadMoreKeys: "Cargar más claves",
items: "{count} elementos",
fields: "{count} campos",
members: "{count} miembros",
entries: "{count} entradas",
noExpiry: "sin expiración",
binaryStringReadonlyHint:
"Los valores de cadena binaria se muestran como texto escapado en modo de solo lectura; la edición de bytes sin procesar no está disponible.",
},
mongo: {
documents: "{count} documentos",
addField: "Agregar campo",
deleteField: "Eliminar campo",
field: "Campo",
value: "Valor",
fieldPlaceholder: "Nombre del campo",
emptyCollection: "Colección vacía",
selectDocument: "Selecciona un documento",
readonlyId: "_id es de solo lectura",
invalidJsonValue: "Esta celda no contiene un valor JSON válido",
duplicateField: "Nombre de campo duplicado: {field}",
edit: "Editar",
documentView: "Vista de documento",
tableView: "Vista de tabla",
},
history: {
title: "Historial",
search: "Buscar en historial...",
empty: "Sin historial aún",
failed: "Fallida",
success: "Exitosa",
restore: "Restaurar en el editor",
copy: "Copiar SQL",
delete: "Eliminar",
viewDetails: "Ver detalles",
rollback: "Revertir",
rollbackSql: "SQL de reversión",
rollbackConfirm: "¿Ejecutar el SQL de reversión generado para esta entrada del historial?",
rollbackSuccess: "Reversión ejecutada",
rollbackFailed: "Error al revertir: {message}",
confirmDelete: "¿Eliminar esta entrada del historial?",
confirmClear: "¿Limpiar todo el historial?",
filters: {
all: "Todas",
query: "Consultas",
data_change: "Cambios de datos",
schema_change: "Cambios de esquema",
failed: "Fallidas",
},
kinds: {
query: "Consulta",
data_change: "Cambio de datos",
schema_change: "Cambio de esquema",
import: "Importación",
transfer: "Transferencia",
},
kindShort: {
query: "SQL",
data_change: "Datos",
schema_change: "DDL",
import: "Import",
transfer: "Mover",
},
detail: {
kind: "Tipo",
operation: "Operación",
connection: "Conexión",
database: "Base de datos",
target: "Destino",
time: "Hora",
duration: "Duración",
affectedRows: "Filas afectadas",
status: "Estado",
error: "Error",
},
},
dangerDialog: {
title: "Operación peligrosa",
message: "Esta sentencia SQL puede modificar o eliminar datos de forma irreversible. ¿Estás seguro de que deseas ejecutarla?",
deleteMessage: "Esta operación de eliminación puede ser irreversible. ¿Continuar?",
deleteConfirm: "Confirmar eliminación",
deleteRowMessage: "Esta fila quedará marcada para eliminación y se borrará de la base de datos al guardar. ¿Continuar?",
deleteRowDetails: "Tabla: {table}",
deleteRowDetailsNoTable: "Fila actual del resultado",
redisKeyDetails: "Clave Redis: {key}",
redisHashFieldDetails: "Hash Redis: {key}\nCampo: {field}",
redisListItemDetails: "Lista Redis: {key}\nÍndice: {index}",
redisSetMemberDetails: "Conjunto Redis: {key}\nMiembro: {member}",
mongoDocumentDetails: "Colección MongoDB: {collection}\nDocumento _id: {id}",
mongoFieldDetails: "Campo: {field}",
mongoArrayItemDetails: "Índice del elemento del arreglo: {index}",
cancel: "Cancelar",
confirm: "Ejecutar",
},
transfer: {
title: "Transferencia de datos",
source: "Origen",
target: "Destino",
sourceConnection: "Conexión de origen",
sourceDatabase: "Base de datos de origen",
targetConnection: "Conexión de destino",
targetDatabase: "Base de datos de destino",
tables: "Tablas",
selectAll: "Seleccionar todas",
deselectAll: "Deseleccionar todas",
createTable: "Crear tabla si no existe",
transferMode: "Modo de transferencia",
modeAppend: "Agregar (INSERT)",
modeOverwrite: "Sobrescribir (TRUNCATE + INSERT)",
modeUpsert: "Upsert (INSERT o UPDATE por PK)",
batchSize: "Tamaño de lote",
start: "Iniciar transferencia",
cancel: "Cancelar",
progress: "Transfiriendo...",
transferring: "Transfiriendo {table}...",
completed: "Transferencia completada",
failed: "Error en la transferencia",
cancelled: "Transferencia cancelada",
rowsTransferred: "{count} filas transferidas",
tableProgress: "{current} / {total} tablas",
noSqlConnections: "No hay conexiones SQL disponibles",
selectTables: "Selecciona las tablas a transferir",
searchTables: "Buscar tablas...",
noTables: "Sin tablas",
selectSourceFirst: "Selecciona primero la conexión y base de datos de origen",
tableError: "Error en tabla {table}: {error}",
overallProgress: "Progreso general",
dataTransfer: "Transferencia de datos",
},
tableImport: {
title: "Importar datos a tabla",
target: "Tabla destino",
selectFile: "Seleccionar archivo",
file: "Archivo",
rows: "Filas",
mapped: "Mapeadas",
mapping: "Mapeo de columnas",
skipColumn: "Omitir",
preview: "Vista previa",
mode: "Modo de importación",
append: "Agregar datos",
truncate: "Truncar e importar",
progress: "Progreso",
start: "Iniciar importación",
success: "Se importaron {count} filas",
},
sqlFile: {
title: "Ejecutar archivo SQL",
file: "Archivo",
selectSqlFile: "Seleccionar archivo SQL",
browse: "Examinar",
target: "Destino",
connection: "Conexión",
selectConnection: "Seleccionar conexión",
database: "Base de datos",
selectDatabase: "Seleccionar base de datos",
databasePlaceholder: "Nombre de la base de datos",
options: "Opciones",
continueOnError: "Continuar en caso de error",
cancelling: "Cancelando...",
cancel: "Cancelar",
execute: "Ejecutar",
statement: "Sentencia",
succeeded: "Exitosa",
failed: "Fallida",
affectedRows: "Filas afectadas",
currentStatement: "Sentencia actual",
status: {
idle: "Inactivo",
started: "Iniciado",
running: "En ejecución",
statementDone: "Sentencia completada",
statementFailed: "Sentencia fallida",
done: "Completado",
error: "Error",
cancelled: "Cancelado",
},
},
diff: {
title: "Comparar bases de datos",
source: "Origen",
target: "Destino",
selectConnection: "Seleccionar conexión",
selectDatabase: "Seleccionar base de datos",
selectSchema: "Seleccionar esquema",
compare: "Comparar",
comparing: "Comparando esquemas...",
noDifferences: "No se encontraron diferencias",
table: "Tabla",
status: "Estado",
details: "Detalles",
added: "Agregada",
removed: "Eliminada",
modified: "Modificada",
indexes: "Índices",
foreignKeys: "Claves foráneas",
triggers: "Disparadores",
newTable: "Nueva tabla",
dropTable: "Eliminar tabla",
generatedSql: "SQL de sincronización",
copySql: "Copiar SQL",
executeSync: "Ejecutar sincronización",
syncSuccess: "Sincronización ejecutada exitosamente",
},
dataCompare: {
title: "Comparar datos",
selectTable: "Seleccionar tabla",
keyColumns: "Columnas clave",
keyColumnsPlaceholder: "Columnas primarias o únicas separadas por comas",
rowLimit: "Límite de filas a comparar",
rowLimitOption: "{count} filas",
rowCounts: "Origen {source} filas, destino {target} filas; se comparan hasta las primeras {limit} filas",
truncatedWarning:
"La tabla supera este límite de comparación, por lo que los resultados solo cubren las filas cargadas. Aumenta el límite o usa comparación por fragmentos más adelante.",
compare: "Comparar datos",
summary: "Agregadas {added}, eliminadas {removed}, modificadas {modified}",
noKeyColumns: "Selecciona al menos una columna clave",
missingKeyColumns: "Las columnas clave deben existir en las tablas de origen y destino: {columns}",
noCommonColumns: "Las tablas de origen y destino no tienen columnas en común para comparar",
noDifferences: "Los datos son idénticos, no se necesita SQL de sincronización",
syncSuccess: "Sincronización de datos ejecutada exitosamente",
},
settings: {
title: "Configuración",
editorTab: "Editor",
appearanceTab: "Apariencia",
jdbcTab: "Drivers JDBC",
securityTab: "Seguridad",
aboutTab: "Acerca de",
fontFamily: "Familia tipográfica",
selectFont: "Seleccionar fuente...",
fontSize: "Tamaño de fuente",
theme: "Tema",
selectTheme: "Seleccionar tema...",
appLayout: "Diseño de la interfaz",
appLayoutSeparated: "Moderno separado",
appLayoutSeparatedDescription: "Separación clara de paneles con pestañas en bloque.",
appLayoutClassic: "Clásico compacto",
appLayoutClassicDescription: "Barra de pestañas continua con encabezados de panel compactos.",
apply: "Aplicar",
resetDefaults: "Restablecer valores por defecto",
executeMode: "Modo de ejecución (Cmd+Enter)",
executeModeAll: "Ejecutar todo el SQL",
executeModeCurrent: "Ejecutar sentencia en el cursor",
wordWrap: "Ajuste de línea",
wordWrapDescription: "Ajustar las líneas largas de SQL al ancho del editor",
preview: "Vista previa en tiempo real",
jdbcPlugin: "Plugin JDBC de DBX",
jdbcPluginInstall: "Instalar plugin JDBC",
jdbcPluginInstallSuccess: "Plugin JDBC instalado",
jdbcPluginUninstall: "Desinstalar",
jdbcPluginUninstallSuccess: "Plugin JDBC desinstalado",
jdbcPluginInstalled: "Instalado: v{version}",
jdbcPluginIncompatible: "Protocolo incompatible",
jdbcPluginNotInstalled: "No instalado",
jdbcDrivers: "JARs de drivers JDBC",
jdbcImport: "Importar JAR",
jdbcImportPath: "Ruta de importación",
jdbcDriverPathPlaceholder: "/ruta/al/driver.jar",
jdbcImportSuccess: "Se importaron {count} archivo(s) de driver",
jdbcDeleteSuccess: "Driver eliminado",
jdbcNoDrivers: "Aún no se han importado drivers JDBC.",
aboutDescription: "Una herramienta de administración de bases de datos liviana y de código abierto.",
community: "Comunidad",
qqGroup: "Grupo QQ",
project: "Proyecto",
openSource: "Repositorio de código abierto",
},
};