diff --git a/CHANGELOG.md b/CHANGELOG.md
index e4ce0300..28e2d251 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -254,7 +254,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Refactor ER diagram to single TB layout with Record position tracking
- Replace ER diagram SVG rendering with pure HTML for better performance
-- Adopt DBX-style compact toolbar layout
+- Adopt compact toolbar layout
- Refactor sidebar: move ER diagram button to database actions dropdown
## [0.7.4] - 2026-07-01
diff --git a/README.md b/README.md
index b3f69aef..6a561233 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@
[Download](https://www.geekfun.club/download) · [Docs](docs/DISTRIBUTION.md) · [Website](https://www.geekfun.club) · [Releases](https://github.com/geek-fun/sqlkit/releases)
-English · [简体中文](README_zh.md)
+English · [简体中文](README_zh.md) · [Português (BR)](README_pt-BR.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Español](README_es.md)
diff --git a/README_es.md b/README_es.md
new file mode 100644
index 00000000..0427ffda
--- /dev/null
+++ b/README_es.md
@@ -0,0 +1,309 @@
+
+
+
+
+# SqlKit
+
+**Cliente GUI de bases de datos SQL agéntico y multiplataforma — tu agente de bases de datos para más de 70 bases de datos.**
+
+**Privacidad primero. Tus datos, tus llaves. Código abierto.**
+
+[](https://github.com/geek-fun/sqlkit/releases)
+[](https://github.com/geek-fun/sqlkit/releases)
+[](LICENSE)
+[](https://github.com/geek-fun/sqlkit/stargazers)
+[](https://github.com/geek-fun/sqlkit/actions/workflows/node.yml)
+[](https://mcptoplist.com/server/io.github.geek-fun%2Fdata-studio)
+
+
+
+
+
+
+
+
+
+[Descargar](https://www.geekfun.club/download) · [Documentación](docs/DISTRIBUTION.md) · [Sitio web](https://www.geekfun.club) · [Versiones](https://github.com/geek-fun/sqlkit/releases)
+
+[English](README.md) · [简体中文](README_zh.md) · [Português (BR)](README_pt-BR.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · Español
+
+
+
+---
+
+SqlKit es un **cliente de bases de datos agéntico** — no solo ejecuta SQL, sino que entiende tus bases de datos y actúa en tu nombre. Describe lo que necesitas en lenguaje natural y el agente escribe consultas, inspecciona esquemas, optimiza SQL y devuelve resultados. Construido con Tauri (Rust), no con Electron, reemplaza a clientes pesados como DBeaver, Navicat y DataGrip con una única app de escritorio nativa.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Instalación
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Características
+
+### Estudio de Datos Agéntico
+
+Describe lo que necesitas en lenguaje natural — el agente lee tu esquema, escribe consultas, optimiza el SQL lento, explica los planes de ejecución visualmente y corrige errores al instante. Compatible con OpenAI, Anthropic, DeepSeek y Ollama. Trae tu propia clave.
+
+- **Generación de consultas con IA** — de lenguaje natural a SQL con contexto consciente del esquema
+- **Optimización de SQL** — reescribe consultas lentas y visualiza planes de ejecución
+- **Corrección de errores** — el agente diagnostica y corrige errores de SQL automáticamente
+- **Seguridad** — las operaciones destructivas requieren confirmación; las credenciales nunca se exponen al LLM
+
+### Ligero y con rendimiento nativo
+
+Construido con Rust + Tauri v2 — sin Electron, sin JRE, sin Chromium incluido. Se distribuye como un pequeño binario nativo, con rendimiento nativo en macOS, Windows y Linux. Lo que otras apps necesitan un runtime de Java o una licencia de JetBrains para hacer, SqlKit lo hace con una sola descarga.
+
+### Todas tus bases de datos, una sola app
+
+SqlKit es compatible con **más de 70 bases de datos** mediante cuatro estrategias de adaptador:
+
+| Estrategia | Bases de datos |
+|----------|-----------|
+| **Nativo** (Rust) | PostgreSQL, MySQL, SQL Server, SQLite |
+| **Compatible con protocolo PG** | CockroachDB, Redshift, YugabyteDB, TimescaleDB, QuestDB, Vastbase, YashanDB, KingbaseES, GaussDB, HighGo, UXDB, OpenGauss, GBase8c, Greenplum, EnterpriseDB, CrateDB, Materialize, AlloyDB, CloudSQLPG, FujitsuPG |
+| **Compatible con protocolo MySQL** | MariaDB, TiDB, OceanBase, TDSQL, PolarDB, Doris, SelectDB, StarRocks, Databend, GoldenDB, ManticoreSearch, SingleStore, CloudSQLMySQL |
+| **Puente JDBC** | Oracle, DuckDB, Firebird, DB2, H2, Snowflake, TDengine, Derby, Hive, Databricks, Hana, Teradata, Vertica, Exasol, BigQuery, Informix, Kylin, Cassandra, Iris, Access, Dameng, XuguDB, GBase8a |
+| **Puente HTTP** | ClickHouse, Trino, Presto, RQLite, Turso |
+
+### Editor de calidad profesional
+
+Impulsado por Monaco (el motor de VS Code), ofrece resaltado de sintaxis SQL completo, autocompletado y soporte para múltiples pestañas. Explora esquemas visualmente, inspecciona el DDL y busca objetos en todas las bases de datos.
+
+- **Editor Monaco** — edición de SQL de nivel VS Code con resaltado de sintaxis y autocompletado
+- **Múltiples pestañas** — trabaja en varias consultas a la vez con gestión de pestañas
+- **Explorador de esquemas** — vista de árbol de bases de datos, esquemas, tablas, columnas e índices
+- **Historial de consultas** — se guarda automáticamente, se puede buscar y repetir
+- **Cuadrícula de resultados** — paginada, ordenable, con edición en línea y exportación a CSV/JSON/Markdown
+- **Visor de DDL** — consulta las sentencias CREATE de cualquier objeto
+- **Búsqueda de objetos** — encuentra rápidamente tablas, vistas y procedimientos en los esquemas
+
+### Transferencia de grandes volúmenes de datos
+
+Mueve datos entre cualquier motor compatible — de PostgreSQL a ClickHouse, de Oracle a SQL Server o de MySQL a BigQuery. Sin archivos intermedios.
+
+- **Transferencia entre motores** — migra datos entre diferentes tipos de bases de datos con mapeo automático de tipos
+- **Importación / Exportación** — formatos CSV, JSON y JSONL
+- **Operaciones masivas** — procesa millones de registros con procesamiento por lotes
+
+### Seguridad y conectividad
+
+- **Túnel SSH** — conéctate a través de SSH con autenticación por clave o contraseña
+- **Almacenamiento cifrado** — credenciales protegidas por el llavero del sistema operativo (macOS Keychain, Windows Credential Manager, Linux Secret Service)
+- **SSL/TLS** — conexiones cifradas a las bases de datos compatibles
+- **Reconexión automática** — gestión de conexiones resiliente
+
+### Multiplataforma
+
+- **macOS** (Apple Silicon e Intel) — instalador nativo `.dmg`
+- **Windows** — instalador `.exe`
+- **Linux** — paquetes `.AppImage` y `.deb`
+
+## Desarrollo
+
+### Requisitos previos
+
+- [Node.js](https://nodejs.org/) >= 18
+- [Toolchain de Rust](https://www.rust-lang.org/tools/install)
+
+**Linux (Ubuntu/Debian):**
+
+```bash
+sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev libssl-dev
+```
+
+**macOS:**
+
+```bash
+xcode-select --install
+```
+
+**Windows:** Instala [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
+
+### Inicio rápido
+
+```bash
+npm install
+npm run tauri dev
+```
+
+### Scripts
+
+| Comando | Descripción |
+|---------|-------------|
+| `npm run dev` | Inicia el servidor de desarrollo de Vite |
+| `npm run build` | Compila el frontend para producción |
+| `npm run lint:check` | Ejecuta ESLint |
+| `npm run lint:fix` | Corrige automáticamente los problemas de lint |
+| `npm test` | Ejecuta las pruebas del frontend |
+| `npm run tauri dev` | Inicia el desarrollo con Tauri |
+| `npm run tauri build` | Compila la aplicación Tauri |
+
+### Instrucciones de compilación
+
+Consulta [BUILD.md](BUILD.md) para ver los requisitos de compilación específicos de cada plataforma y la solución de problemas.
+
+## Stack tecnológico
+
+| Capa | Tecnología |
+|-------|------------|
+| Framework | [Tauri v2](https://tauri.app/) (Rust) |
+| Frontend | [Vue 3](https://vuejs.org/) + [TypeScript](https://www.typescriptlang.org/) |
+| UI | [shadcn-vue](https://www.shadcn-vue.com/) + [UnoCSS](https://unocss.dev/) |
+| Editor | [Monaco Editor](https://microsoft.github.io/monaco-editor/) |
+| Base de datos | [sqlx](https://github.com/launchbadge/sqlx) + drivers específicos de cada motor |
+
+## Preguntas frecuentes
+
+
+¿Es SqlKit gratuito?
+
+Sí — la **edición Community** es gratuita y de código abierto bajo la licencia Apache 2.0. Las conexiones, la edición de SQL, la exploración de esquemas, la edición de datos, el historial de consultas y la exportación de resultados son gratuitos, sin límites artificiales.
+
+Las capacidades avanzadas — agente de IA (con tu propio LLM), servidor MCP, diagramas ER, importación/exportación masiva y transferencia de datos entre motores — forman parte de la suscripción de pago **GEEKFUN Data Studio Ultimate** (9,9 USD/mes o 99 USD/año, con 7 días de prueba gratuita). Todas las versiones publicadas mientras tu suscripción esté activa quedan tuyas para siempre, incluso si cancelas más adelante.
+
+[Ver precios →](https://www.geekfun.club/pricing)
+
+
+
+¿SqlKit envía datos a servidores externos?
+No. SqlKit no recopila telemetría. La función de actualización automática consulta GitHub Releases en busca de nuevas versiones — puedes desactivarla en la configuración. Tus credenciales y consultas permanecen en tu equipo.
+
+
+
+¿Puedo usar SqlKit sin conexión a internet?
+Sí. La app de escritorio funciona completamente sin conexión. Las funciones de IA requieren acceso de red al endpoint del modelo (o un modelo local mediante Ollama).
+
+
+
+¿En qué se diferencia SqlKit de DBeaver / TablePlus / DataGrip?
+SqlKit es una app nativa de Tauri (Rust) — sin Java JRE, sin la sobrecarga de Electron. Incluye IA de forma nativa (no como plugin), es compatible con más de 70 bases de datos y funciona en macOS, Windows y Linux desde un único binario. Privacidad primero, con almacenamiento local cifrado de credenciales.
+
+
+
+¿Qué bases de datos son compatibles?
+PostgreSQL, MySQL, Oracle, SQL Server, SQLite, DuckDB, ClickHouse, Firebird, MariaDB, CockroachDB, TiDB, OceanBase, Snowflake, DB2, H2, Trino, Greenplum, CrateDB, SingleStore y más de 60 adicionales. Consulta la sección Soporte de múltiples bases de datos para ver la lista completa.
+
+
+
+¿Cómo puedo reportar un error o solicitar una nueva función?
+Abre un issue en GitHub Issues .
+
+
+## Comunidad
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Patrocinio
+
+
+
+
+
+
+
+## Licencia
+
+[Apache 2.0](LICENSE) © GEEKFUN
diff --git a/README_ja.md b/README_ja.md
new file mode 100644
index 00000000..be1087bf
--- /dev/null
+++ b/README_ja.md
@@ -0,0 +1,309 @@
+
+
+
+
+# SqlKit
+
+**Agentic なクロスプラットフォーム SQL データベース GUI クライアント — 70 以上のデータベースに対応する、あなたのデータベースエージェント。**
+
+**プライバシー第一。あなたのデータ、あなたのキー。オープンソース。**
+
+[](https://github.com/geek-fun/sqlkit/releases)
+[](https://github.com/geek-fun/sqlkit/releases)
+[](LICENSE)
+[](https://github.com/geek-fun/sqlkit/stargazers)
+[](https://github.com/geek-fun/sqlkit/actions/workflows/node.yml)
+[](https://mcptoplist.com/server/io.github.geek-fun%2Fdata-studio)
+
+
+
+
+
+
+
+
+
+[ダウンロード](https://www.geekfun.club/download) · [ドキュメント](docs/DISTRIBUTION.md) · [ウェブサイト](https://www.geekfun.club) · [リリース](https://github.com/geek-fun/sqlkit/releases)
+
+[English](README.md) · [简体中文](README_zh.md) · [Português (BR)](README_pt-BR.md) · 日本語 · [한국어](README_ko.md) · [Español](README_es.md)
+
+
+
+---
+
+SqlKit は **Agentic なデータベースクライアント** です — 単に SQL を実行するだけではなく、あなたのデータベースを理解し、あなたに代わって操作します。必要なことを自然言語で伝えれば、エージェントがクエリを書き、スキーマを調査し、SQL を最適化して結果を返します。Electron ではなく Tauri(Rust)で構築されており、DBeaver、Navicat、DataGrip といった重厚なクライアントを 1 つのネイティブデスクトップアプリに置き換えます。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## インストール
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## 機能
+
+### Agentic データスタジオ
+
+必要なことを自然言語で記述するだけです — エージェントがスキーマを読み取り、クエリを書き、遅い SQL を最適化し、実行プランをわかりやすく可視化し、エラーをその場で修正します。OpenAI、Anthropic、DeepSeek、Ollama に対応。API キーはご自身のものをご利用ください。
+
+- **AI クエリ生成** — スキーマを把握したコンテキストで自然言語から SQL を生成
+- **SQL 最適化** — 遅いクエリを書き換え、実行プランを可視化
+- **エラー修正** — エージェントが SQL エラーを自動で診断・修正
+- **安全性** — 破壊的な操作には確認が必要。認証情報が LLM に渡されることはありません
+
+### 軽量でネイティブなパフォーマンス
+
+Rust + Tauri v2 で構築 — Electron も JRE もバンドルされた Chromium もありません。小さなネイティブバイナリとして提供され、macOS、Windows、Linux でネイティブのパフォーマンスを発揮します。他のアプリなら Java ランタイムや JetBrains ライセンスを必要とする処理も、SqlKit なら 1 回のダウンロードで実現します。
+
+### すべてのデータベースを 1 つのアプリで
+
+SqlKit は 4 つのアダプタ戦略によって **70 以上のデータベース** に対応しています:
+
+| 戦略 | データベース |
+|----------|-----------|
+| **ネイティブ** (Rust) | PostgreSQL, MySQL, SQL Server, SQLite |
+| **PG プロトコル互換** | CockroachDB, Redshift, YugabyteDB, TimescaleDB, QuestDB, Vastbase, YashanDB, KingbaseES, GaussDB, HighGo, UXDB, OpenGauss, GBase8c, Greenplum, EnterpriseDB, CrateDB, Materialize, AlloyDB, CloudSQLPG, FujitsuPG |
+| **MySQL プロトコル互換** | MariaDB, TiDB, OceanBase, TDSQL, PolarDB, Doris, SelectDB, StarRocks, Databend, GoldenDB, ManticoreSearch, SingleStore, CloudSQLMySQL |
+| **JDBC ブリッジ** | Oracle, DuckDB, Firebird, DB2, H2, Snowflake, TDengine, Derby, Hive, Databricks, Hana, Teradata, Vertica, Exasol, BigQuery, Informix, Kylin, Cassandra, Iris, Access, Dameng, XuguDB, GBase8a |
+| **HTTP ブリッジ** | ClickHouse, Trino, Presto, RQLite, Turso |
+
+### プロダクトグレードのエディター
+
+Monaco(VS Code エンジン)を搭載し、完全な SQL シンタックスハイライト、自動補完、マルチタブをサポートします。スキーマを視覚的に閲覧し、DDL を確認し、データベースを横断してオブジェクトを検索できます。
+
+- **Monaco Editor** — シンタックスハイライトと自動補完を備えた VS Code グレードの SQL 編集
+- **マルチタブ** — タブ管理で複数のクエリを同時に処理
+- **スキーマブラウザー** — データベース、スキーマ、テーブル、カラム、インデックスのツリービュー
+- **クエリ履歴** — 自動保存、検索可能、再実行可能
+- **結果グリッド** — ページネーション、ソート、インライン編集、CSV/JSON/Markdown エクスポートに対応
+- **DDL ビューアー** — 任意のオブジェクトの CREATE 文を表示
+- **オブジェクト検索** — スキーマを横断してテーブル、ビュー、プロシージャをすばやく検索
+
+### 大量データ転送
+
+対応する任意のエンジン間でデータを移動できます — PostgreSQL から ClickHouse へ、Oracle から SQL Server へ、MySQL から BigQuery へ。中間ファイルは不要です。
+
+- **クロスエンジン転送** — 異なる種類のデータベース間でデータを移行、型のマッピングは自動
+- **インポート / エクスポート** — CSV、JSON、JSONL 形式に対応
+- **バルク操作** — バッチ処理で数百万件のレコードを処理
+
+### セキュリティと接続
+
+- **SSH トンネル** — 鍵またはパスワード認証による SSH 接続
+- **暗号化ストレージ** — 認証情報は OS のキーチェーンで保護(macOS Keychain、Windows Credential Manager、Linux Secret Service)
+- **SSL/TLS** — 対応データベースへの暗号化接続
+- **自動再接続** — 堅牢な接続管理
+
+### クロスプラットフォーム
+
+- **macOS**(Apple Silicon と Intel)— ネイティブの `.dmg` インストーラー
+- **Windows** — `.exe` インストーラー
+- **Linux** — `.AppImage` と `.deb` パッケージ
+
+## 開発
+
+### 前提条件
+
+- [Node.js](https://nodejs.org/) >= 18
+- [Rust ツールチェーン](https://www.rust-lang.org/tools/install)
+
+**Linux (Ubuntu/Debian):**
+
+```bash
+sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev libssl-dev
+```
+
+**macOS:**
+
+```bash
+xcode-select --install
+```
+
+**Windows:** [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) をインストールしてください
+
+### クイックスタート
+
+```bash
+npm install
+npm run tauri dev
+```
+
+### スクリプト
+
+| コマンド | 説明 |
+|---------|-------------|
+| `npm run dev` | Vite 開発サーバーを起動 |
+| `npm run build` | フロントエンドの本番用ビルド |
+| `npm run lint:check` | ESLint を実行 |
+| `npm run lint:fix` | Lint の問題を自動修正 |
+| `npm test` | フロントエンドのテストを実行 |
+| `npm run tauri dev` | Tauri 開発モードを起動 |
+| `npm run tauri build` | Tauri アプリケーションをビルド |
+
+### ビルド手順
+
+プラットフォームごとのビルド要件とトラブルシューティングの詳細は [BUILD.md](BUILD.md) を参照してください。
+
+## 技術スタック
+
+| レイヤー | 技術 |
+|-------|------------|
+| フレームワーク | [Tauri v2](https://tauri.app/) (Rust) |
+| フロントエンド | [Vue 3](https://vuejs.org/) + [TypeScript](https://www.typescriptlang.org/) |
+| UI | [shadcn-vue](https://www.shadcn-vue.com/) + [UnoCSS](https://unocss.dev/) |
+| エディター | [Monaco Editor](https://microsoft.github.io/monaco-editor/) |
+| データベース | [sqlx](https://github.com/launchbadge/sqlx) + エンジン固有のドライバー |
+
+## よくある質問
+
+
+SqlKit は無料ですか?
+
+はい — **Community エディション**は Apache 2.0 ライセンスの下で無料かつオープンソースです。接続、SQL 編集、スキーマ閲覧、データ編集、クエリ履歴、結果のエクスポートはすべて無料で、人為的な制限はありません。
+
+高度な機能 — AI エージェント(お使いの LLM を利用)、MCP サーバー、ER 図、一括インポート/エクスポート、クロスエンジンデータ転送 — は、有料の **GEEKFUN Data Studio Ultimate** サブスクリプション(月額 $9.9 または年額 $99、7 日間の無料トライアル付き)の一部です。サブスクリプション期間中にリリースされたバージョンは、後で解約しても永久にあなたのものです。
+
+[料金を見る →](https://www.geekfun.club/pricing)
+
+
+
+SqlKit はデータを外部に送信しますか?
+いいえ。SqlKit はテレメトリーを収集しません。自動更新機能は GitHub Releases で新しいバージョンを確認します — 設定から無効化できます。認証情報とクエリはあなたのマシンから出ることはありません。
+
+
+
+インターネット接続なしで SqlKit を使えますか?
+はい。デスクトップアプリは完全にオフラインで動作します。AI 機能にはモデルエンドポイントへのネットワークアクセス(または Ollama によるローカルモデル)が必要です。
+
+
+
+SqlKit は DBeaver / TablePlus / DataGrip と何が違いますか?
+SqlKit はネイティブの Tauri アプリ(Rust)です — Java JRE も Electron のオーバーヘッドもありません。AI をプラグインではなくネイティブに搭載し、70 以上のデータベースに対応し、1 つのバイナリで macOS、Windows、Linux 上で動作します。プライバシー第一、認証情報はローカルで暗号化して保存されます。
+
+
+
+対応しているデータベースは何ですか?
+PostgreSQL、MySQL、Oracle、SQL Server、SQLite、DuckDB、ClickHouse、Firebird、MariaDB、CockroachDB、TiDB、OceanBase、Snowflake、DB2、H2、Trino、Greenplum、CrateDB、SingleStore、その他 60 以上。完全なリストはマルチデータベース対応 のセクションを参照してください。
+
+
+
+バグの報告や機能のリクエストはどのように行えばよいですか?
+GitHub Issues で issue をオープンしてください。
+
+
+## コミュニティ
+
+
+
+
+
+
+
+
+
+
+
+
+
+## スポンサー
+
+
+
+
+
+
+
+## ライセンス
+
+[Apache 2.0](LICENSE) © GEEKFUN
diff --git a/README_ko.md b/README_ko.md
new file mode 100644
index 00000000..9ef92202
--- /dev/null
+++ b/README_ko.md
@@ -0,0 +1,309 @@
+
+
+
+
+# SqlKit
+
+**Agentic 크로스플랫폼 SQL 데이터베이스 GUI 클라이언트 — 70개 이상의 데이터베이스를 지원하는 여러분의 데이터베이스 에이전트.**
+
+**프라이버시 최우선. 여러분의 데이터, 여러분의 키. 오픈 소스.**
+
+[](https://github.com/geek-fun/sqlkit/releases)
+[](https://github.com/geek-fun/sqlkit/releases)
+[](LICENSE)
+[](https://github.com/geek-fun/sqlkit/stargazers)
+[](https://github.com/geek-fun/sqlkit/actions/workflows/node.yml)
+[](https://mcptoplist.com/server/io.github.geek-fun%2Fdata-studio)
+
+
+
+
+
+
+
+
+
+[다운로드](https://www.geekfun.club/download) · [문서](docs/DISTRIBUTION.md) · [웹사이트](https://www.geekfun.club) · [릴리스](https://github.com/geek-fun/sqlkit/releases)
+
+[English](README.md) · [简体中文](README_zh.md) · [Português (BR)](README_pt-BR.md) · [日本語](README_ja.md) · 한국어 · [Español](README_es.md)
+
+
+
+---
+
+SqlKit은 **Agentic 데이터베이스 클라이언트**입니다 — 단순히 SQL을 실행하는 데 그치지 않고, 여러분의 데이터베이스를 이해하고 대신 작업을 수행합니다. 필요한 것을 자연어로 설명하면 에이전트가 쿼리를 작성하고, 스키마를 검사하고, SQL을 최적화하여 결과를 반환합니다. Electron이 아닌 Tauri(Rust) 기반으로 구축되어 DBeaver, Navicat, DataGrip 같은 무거운 클라이언트를 하나의 네이티브 데스크톱 앱으로 대체합니다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## 설치
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## 주요 기능
+
+### Agentic 데이터 스튜디오
+
+필요한 것을 자연어로 설명하기만 하면 됩니다 — 에이전트가 스키마를 읽고, 쿼리를 작성하고, 느린 SQL을 최적화하고, 실행 계획을 시각적으로 설명하며, 오류를 그 자리에서 수정합니다. OpenAI, Anthropic, DeepSeek, Ollama를 지원합니다. API 키는 직접 준비해서 사용하세요.
+
+- **AI 쿼리 생성** — 스키마를 인식하는 컨텍스트로 자연어를 SQL로 변환
+- **SQL 최적화** — 느린 쿼리를 재작성하고 실행 계획을 시각화
+- **오류 수정** — 에이전트가 SQL 오류를 자동으로 진단하고 수정
+- **안전성** — 파괴적인 작업은 확인 필요; 자격 증명은 LLM에 노출되지 않음
+
+### 가볍고 네이티브한 성능
+
+Rust + Tauri v2로 구축 — Electron도, JRE도, 번들된 Chromium도 없습니다. 작은 네이티브 바이너리로 배포되며 macOS, Windows, Linux에서 네이티브 성능을 발휘합니다. 다른 앱이 Java 런타임이나 JetBrains 라이선스를 필요로 하는 작업도 SqlKit은 한 번의 다운로드로 처리합니다.
+
+### 모든 데이터베이스를 하나의 앱으로
+
+SqlKit은 네 가지 어댑터 전략으로 **70개 이상의 데이터베이스**를 지원합니다:
+
+| 전략 | 데이터베이스 |
+|----------|-----------|
+| **네이티브** (Rust) | PostgreSQL, MySQL, SQL Server, SQLite |
+| **PG 프로토콜 호환** | CockroachDB, Redshift, YugabyteDB, TimescaleDB, QuestDB, Vastbase, YashanDB, KingbaseES, GaussDB, HighGo, UXDB, OpenGauss, GBase8c, Greenplum, EnterpriseDB, CrateDB, Materialize, AlloyDB, CloudSQLPG, FujitsuPG |
+| **MySQL 프로토콜 호환** | MariaDB, TiDB, OceanBase, TDSQL, PolarDB, Doris, SelectDB, StarRocks, Databend, GoldenDB, ManticoreSearch, SingleStore, CloudSQLMySQL |
+| **JDBC 브리지** | Oracle, DuckDB, Firebird, DB2, H2, Snowflake, TDengine, Derby, Hive, Databricks, Hana, Teradata, Vertica, Exasol, BigQuery, Informix, Kylin, Cassandra, Iris, Access, Dameng, XuguDB, GBase8a |
+| **HTTP 브리지** | ClickHouse, Trino, Presto, RQLite, Turso |
+
+### 프로덕트급 에디터
+
+Monaco(VS Code 엔진) 기반으로 완전한 SQL 구문 강조, 자동 완성, 멀티 탭을 지원합니다. 스키마를 시각적으로 탐색하고, DDL을 확인하고, 데이터베이스 전체에서 객체를 검색할 수 있습니다.
+
+- **Monaco Editor** — 구문 강조와 자동 완성을 갖춘 VS Code급 SQL 편집
+- **멀티 탭** — 탭 관리로 여러 쿼리를 동시에 처리
+- **스키마 브라우저** — 데이터베이스, 스키마, 테이블, 컬럼, 인덱스의 트리 뷰
+- **쿼리 히스토리** — 자동 저장, 검색 가능, 재실행 가능
+- **결과 그리드** — 페이지네이션, 정렬, 인라인 편집, CSV/JSON/Markdown 내보내기 지원
+- **DDL 뷰어** — 모든 객체의 CREATE 문 조회
+- **객체 검색** — 스키마 전체에서 테이블, 뷰, 프로시저를 빠르게 검색
+
+### 대용량 데이터 전송
+
+지원되는 어떤 엔진 간에도 데이터를 이동할 수 있습니다 — PostgreSQL에서 ClickHouse로, Oracle에서 SQL Server로, MySQL에서 BigQuery로. 중간 파일이 필요하지 않습니다.
+
+- **크로스 엔진 전송** — 서로 다른 데이터베이스 유형 간 데이터 마이그레이션, 타입 매핑은 자동
+- **가져오기 / 내보내기** — CSV, JSON, JSONL 형식
+- **벌크 작업** — 배치 처리로 수백만 건의 레코드 처리
+
+### 보안 및 연결
+
+- **SSH 터널** — 키 또는 비밀번호 인증을 통한 SSH 연결
+- **암호화 저장소** — OS 키체인으로 보호되는 자격 증명 (macOS Keychain, Windows Credential Manager, Linux Secret Service)
+- **SSL/TLS** — 지원되는 데이터베이스에 대한 암호화 연결
+- **자동 재연결** — 안정적인 연결 처리
+
+### 크로스플랫폼
+
+- **macOS** (Apple Silicon 및 Intel) — 네이티브 `.dmg` 설치 프로그램
+- **Windows** — `.exe` 설치 프로그램
+- **Linux** — `.AppImage` 및 `.deb` 패키지
+
+## 개발
+
+### 사전 요구 사항
+
+- [Node.js](https://nodejs.org/) >= 18
+- [Rust 툴체인](https://www.rust-lang.org/tools/install)
+
+**Linux (Ubuntu/Debian):**
+
+```bash
+sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev libssl-dev
+```
+
+**macOS:**
+
+```bash
+xcode-select --install
+```
+
+**Windows:** [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) 설치
+
+### 빠른 시작
+
+```bash
+npm install
+npm run tauri dev
+```
+
+### 스크립트
+
+| 명령 | 설명 |
+|---------|-------------|
+| `npm run dev` | Vite 개발 서버 시작 |
+| `npm run build` | 프론트엔드 프로덕션 빌드 |
+| `npm run lint:check` | ESLint 실행 |
+| `npm run lint:fix` | 린트 문제 자동 수정 |
+| `npm test` | 프론트엔드 테스트 실행 |
+| `npm run tauri dev` | Tauri 개발 모드 시작 |
+| `npm run tauri build` | Tauri 애플리케이션 빌드 |
+
+### 빌드 안내
+
+플랫폼별 빌드 요구 사항과 문제 해결에 대한 자세한 내용은 [BUILD.md](BUILD.md)를 참고하세요.
+
+## 기술 스택
+
+| 레이어 | 기술 |
+|-------|------------|
+| 프레임워크 | [Tauri v2](https://tauri.app/) (Rust) |
+| 프론트엔드 | [Vue 3](https://vuejs.org/) + [TypeScript](https://www.typescriptlang.org/) |
+| UI | [shadcn-vue](https://www.shadcn-vue.com/) + [UnoCSS](https://unocss.dev/) |
+| 에디터 | [Monaco Editor](https://microsoft.github.io/monaco-editor/) |
+| 데이터베이스 | [sqlx](https://github.com/launchbadge/sqlx) + 엔진별 드라이버 |
+
+## 자주 묻는 질문
+
+
+SqlKit은 무료인가요?
+
+네 — **Community 에디션**은 Apache 2.0 라이선스 아래 무료이며 오픈 소스입니다. 연결, SQL 편집, 스키마 탐색, 데이터 편집, 쿼리 히스토리, 결과 내보내기는 모두 무료이며 인위적인 제한이 없습니다.
+
+고급 기능은 — AI 에이전트(직접 준비한 LLM 사용), MCP 서버, ER 다이어그램, 대량 가져오기/내보내기, 크로스 엔진 데이터 전송 — 유료 **GEEKFUN Data Studio Ultimate** 구독(월 $9.9 또는 연 $99, 7일 무료 체험 제공)에 포함되어 있습니다. 구독 중에 출시된 모든 버전은 해지한 뒤에도 영구적으로 여러분의 것입니다.
+
+[요금제 보기 →](https://www.geekfun.club/pricing)
+
+
+
+SqlKit은 데이터를 외부로 전송하나요?
+아니요. SqlKit은 텔레메트리를 수집하지 않습니다. 자동 업데이트 기능은 GitHub Releases에서 새 버전을 확인합니다 — 설정에서 비활성화할 수 있습니다. 자격 증명과 쿼리는 여러분의 머신에 머무릅니다.
+
+
+
+인터넷 연결 없이 SqlKit을 사용할 수 있나요?
+네. 데스크톱 앱은 완전히 오프라인에서 작동합니다. AI 기능에는 모델 엔드포인트에 대한 네트워크 접근(또는 Ollama를 통한 로컬 모델)이 필요합니다.
+
+
+
+SqlKit은 DBeaver / TablePlus / DataGrip과 어떻게 다른가요?
+SqlKit은 네이티브 Tauri 앱(Rust)입니다 — Java JRE도, Electron 오버헤드도 없습니다. AI를 플러그인이 아닌 네이티브로 내장했고, 70개 이상의 데이터베이스를 지원하며, 하나의 바이너리로 macOS, Windows, Linux에서 실행됩니다. 프라이버시 최우선, 자격 증명은 로컬에서 암호화하여 저장합니다.
+
+
+
+어떤 데이터베이스가 지원되나요?
+PostgreSQL, MySQL, Oracle, SQL Server, SQLite, DuckDB, ClickHouse, Firebird, MariaDB, CockroachDB, TiDB, OceanBase, Snowflake, DB2, H2, Trino, Greenplum, CrateDB, SingleStore 외 60개 이상을 지원합니다. 전체 목록은 멀티 데이터베이스 지원 섹션을 참고하세요.
+
+
+
+버그를 신고하거나 기능을 요청하려면 어떻게 해야 하나요?
+GitHub Issues 에서 이슈를 열어주세요.
+
+
+## 커뮤니티
+
+
+
+
+
+
+
+
+
+
+
+
+
+## 스폰서
+
+
+
+
+
+
+
+## 라이선스
+
+[Apache 2.0](LICENSE) © GEEKFUN
diff --git a/README_pt-BR.md b/README_pt-BR.md
new file mode 100644
index 00000000..0027f6e0
--- /dev/null
+++ b/README_pt-BR.md
@@ -0,0 +1,309 @@
+
+
+
+
+# SqlKit
+
+**Cliente GUI de banco de dados SQL agêntico e multiplataforma — seu agente de banco de dados para mais de 70 bancos de dados.**
+
+**Privacidade em primeiro lugar. Seus dados, suas chaves. Código aberto.**
+
+[](https://github.com/geek-fun/sqlkit/releases)
+[](https://github.com/geek-fun/sqlkit/releases)
+[](LICENSE)
+[](https://github.com/geek-fun/sqlkit/stargazers)
+[](https://github.com/geek-fun/sqlkit/actions/workflows/node.yml)
+[](https://mcptoplist.com/server/io.github.geek-fun%2Fdata-studio)
+
+
+
+
+
+
+
+
+
+[Baixar](https://www.geekfun.club/download) · [Documentação](docs/DISTRIBUTION.md) · [Site](https://www.geekfun.club) · [Versões](https://github.com/geek-fun/sqlkit/releases)
+
+[English](README.md) · [简体中文](README_zh.md) · Português (BR) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Español](README_es.md)
+
+
+
+---
+
+SqlKit é um **cliente de banco de dados agêntico** — ele não apenas executa SQL, ele entende seus bancos de dados e age em seu nome. Descreva o que você precisa em linguagem natural e o agente escreve consultas, inspeciona esquemas, otimiza SQL e retorna resultados. Construído com Tauri (Rust), e não com Electron, ele substitui clientes pesados como DBeaver, Navicat e DataGrip por um único aplicativo desktop nativo.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Instalação
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Funcionalidades
+
+### Estúdio de Dados Agêntico
+
+Descreva o que você precisa em linguagem natural — o agente lê seu esquema, escreve consultas, otimiza SQL lentas, explica planos de execução visualmente e corrige erros na hora. Compatível com OpenAI, Anthropic, DeepSeek e Ollama. Traga sua própria chave.
+
+- **Geração de consultas com IA** — de linguagem natural para SQL com contexto ciente do esquema
+- **Otimização de SQL** — reescreve consultas lentas e visualiza planos de execução
+- **Correção de erros** — o agente diagnostica e corrige erros de SQL automaticamente
+- **Segurança** — operações destrutivas exigem confirmação; credenciais nunca expostas ao LLM
+
+### Leve e com desempenho nativo
+
+Construído com Rust + Tauri v2 — sem Electron, sem JRE, sem Chromium embutido. Distribuído como um pequeno binário nativo, com desempenho nativo no macOS, Windows e Linux. O que outros aplicativos precisam de um runtime Java ou de uma licença JetBrains para fazer, o SqlKit faz com um único download.
+
+### Todos os seus bancos de dados, um só aplicativo
+
+O SqlKit suporta **mais de 70 bancos de dados** por meio de quatro estratégias de adaptador:
+
+| Estratégia | Bancos de dados |
+|----------|-----------|
+| **Nativo** (Rust) | PostgreSQL, MySQL, SQL Server, SQLite |
+| **Compatível com protocolo PG** | CockroachDB, Redshift, YugabyteDB, TimescaleDB, QuestDB, Vastbase, YashanDB, KingbaseES, GaussDB, HighGo, UXDB, OpenGauss, GBase8c, Greenplum, EnterpriseDB, CrateDB, Materialize, AlloyDB, CloudSQLPG, FujitsuPG |
+| **Compatível com protocolo MySQL** | MariaDB, TiDB, OceanBase, TDSQL, PolarDB, Doris, SelectDB, StarRocks, Databend, GoldenDB, ManticoreSearch, SingleStore, CloudSQLMySQL |
+| **Ponte JDBC** | Oracle, DuckDB, Firebird, DB2, H2, Snowflake, TDengine, Derby, Hive, Databricks, Hana, Teradata, Vertica, Exasol, BigQuery, Informix, Kylin, Cassandra, Iris, Access, Dameng, XuguDB, GBase8a |
+| **Ponte HTTP** | ClickHouse, Trino, Presto, RQLite, Turso |
+
+### Editor de nível profissional
+
+Baseado no Monaco (motor do VS Code), oferece destaque de sintaxe SQL completo, autocompletar e suporte a múltiplas abas. Navegue pelos esquemas visualmente, inspecione o DDL e pesquise objetos em todos os bancos de dados.
+
+- **Editor Monaco** — edição de SQL de nível VS Code com destaque de sintaxe e autocompletar
+- **Múltiplas abas** — trabalhe em várias consultas ao mesmo tempo com gerenciamento de abas
+- **Navegador de esquemas** — visualização em árvore de bancos de dados, esquemas, tabelas, colunas e índices
+- **Histórico de consultas** — salvo automaticamente, pesquisável e reproduzível
+- **Grade de resultados** — paginada, ordenável, com edição em linha e exportação em CSV/JSON/Markdown
+- **Visualizador de DDL** — veja as instruções CREATE de qualquer objeto
+- **Busca de objetos** — encontre rapidamente tabelas, views e procedures nos esquemas
+
+### Transferência de grandes volumes de dados
+
+Mova dados entre quaisquer engines suportados — PostgreSQL para ClickHouse, Oracle para SQL Server, ou MySQL para BigQuery. Nenhum arquivo intermediário é necessário.
+
+- **Transferência entre engines** — migre dados entre diferentes tipos de banco de dados com mapeamento automático de tipos
+- **Importação / Exportação** — formatos CSV, JSON e JSONL
+- **Operações em lote** — processe milhões de registros com processamento em lote
+
+### Segurança e conectividade
+
+- **Túnel SSH** — conecte-se via SSH com autenticação por chave ou senha
+- **Armazenamento criptografado** — credenciais protegidas pelo chaveiro do sistema operacional (macOS Keychain, Windows Credential Manager, Linux Secret Service)
+- **SSL/TLS** — conexões criptografadas para bancos de dados suportados
+- **Reconexão automática** — gerenciamento de conexões resiliente
+
+### Multiplataforma
+
+- **macOS** (Apple Silicon e Intel) — instalador nativo `.dmg`
+- **Windows** — instalador `.exe`
+- **Linux** — pacotes `.AppImage` e `.deb`
+
+## Desenvolvimento
+
+### Pré-requisitos
+
+- [Node.js](https://nodejs.org/) >= 18
+- [Toolchain do Rust](https://www.rust-lang.org/tools/install)
+
+**Linux (Ubuntu/Debian):**
+
+```bash
+sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev libssl-dev
+```
+
+**macOS:**
+
+```bash
+xcode-select --install
+```
+
+**Windows:** Instale o [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
+
+### Início rápido
+
+```bash
+npm install
+npm run tauri dev
+```
+
+### Scripts
+
+| Comando | Descrição |
+|---------|-------------|
+| `npm run dev` | Inicia o servidor de desenvolvimento Vite |
+| `npm run build` | Compila o frontend para produção |
+| `npm run lint:check` | Executa o ESLint |
+| `npm run lint:fix` | Corrige automaticamente os problemas de lint |
+| `npm test` | Executa os testes do frontend |
+| `npm run tauri dev` | Inicia o desenvolvimento com Tauri |
+| `npm run tauri build` | Compila o aplicativo Tauri |
+
+### Instruções de build
+
+Consulte o [BUILD.md](BUILD.md) para ver os requisitos de build específicos de cada plataforma e a solução de problemas.
+
+## Stack tecnológica
+
+| Camada | Tecnologia |
+|-------|------------|
+| Framework | [Tauri v2](https://tauri.app/) (Rust) |
+| Frontend | [Vue 3](https://vuejs.org/) + [TypeScript](https://www.typescriptlang.org/) |
+| UI | [shadcn-vue](https://www.shadcn-vue.com/) + [UnoCSS](https://unocss.dev/) |
+| Editor | [Monaco Editor](https://microsoft.github.io/monaco-editor/) |
+| Banco de dados | [sqlx](https://github.com/launchbadge/sqlx) + drivers específicos de cada engine |
+
+## Perguntas frequentes
+
+
+O SqlKit é gratuito?
+
+Sim — a **edição Community** é gratuita e de código aberto sob a licença Apache 2.0. Conexões, edição de SQL, navegação de esquemas, edição de dados, histórico de consultas e exportação de resultados são todos gratuitos, sem limites artificiais.
+
+Recursos avançados — agente de IA (traga seu próprio LLM), servidor MCP, diagramas ER, importação/exportação em massa e transferência de dados entre engines — fazem parte da assinatura paga **GEEKFUN Data Studio Ultimate** (US$ 9,90/mês ou US$ 99/ano, com 7 dias de teste gratuito). Todas as versões lançadas enquanto sua assinatura estiver ativa permanecem suas para sempre, mesmo que você cancele depois.
+
+[Ver preços →](https://www.geekfun.club/pricing)
+
+
+
+O SqlKit envia dados para servidores externos?
+Não. O SqlKit não coleta telemetria. O recurso de atualização automática verifica novas versões no GitHub Releases — você pode desativá-lo nas configurações. Suas credenciais e consultas ficam na sua máquina.
+
+
+
+Posso usar o SqlKit sem conexão com a internet?
+Sim. O aplicativo desktop funciona totalmente offline. Os recursos de IA exigem acesso à rede ao endpoint do modelo (ou um modelo local via Ollama).
+
+
+
+Qual é a diferença entre o SqlKit e o DBeaver / TablePlus / DataGrip?
+O SqlKit é um aplicativo Tauri nativo (Rust) — sem Java JRE, sem a sobrecarga do Electron. Inclui IA nativamente (não como plugin), suporta mais de 70 bancos de dados e roda no macOS, Windows e Linux a partir de um único binário. Privacidade em primeiro lugar, com armazenamento local e criptografado das credenciais.
+
+
+
+Quais bancos de dados são suportados?
+PostgreSQL, MySQL, Oracle, SQL Server, SQLite, DuckDB, ClickHouse, Firebird, MariaDB, CockroachDB, TiDB, OceanBase, Snowflake, DB2, H2, Trino, Greenplum, CrateDB, SingleStore e mais de 60 outros. Consulte a seção Suporte a múltiplos bancos de dados para ver a lista completa.
+
+
+
+Como reporto um bug ou solicito um recurso?
+Abra uma issue no GitHub Issues .
+
+
+## Comunidade
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Patrocínio
+
+
+
+
+
+
+
+## Licença
+
+[Apache 2.0](LICENSE) © GEEKFUN
diff --git a/docs/I18N.md b/docs/I18N.md
index 11f8dafc..3fea3f75 100644
--- a/docs/I18N.md
+++ b/docs/I18N.md
@@ -1,6 +1,6 @@
# Multi-Language Support Implementation
-This document describes the internationalization (i18n) implementation in SQLKit, which supports both English and Chinese (Simplified) languages.
+This document describes the internationalization (i18n) implementation in SQLKit, which supports English, Simplified Chinese, Traditional Chinese (Taiwan), Brazilian Portuguese, Japanese, Korean, and Spanish.
## Overview
@@ -12,9 +12,14 @@ The multi-language support is implemented using [vue-i18n](https://vue-i18n.intl
All language files are located in `src/lang/`:
-- **`index.ts`**: Main i18n configuration and initialization
-- **`enUS.ts`**: English (US) translations
+- **`index.ts`**: Main i18n configuration, locale detection, and initialization
+- **`enUS.ts`**: English (US) translations — the key source of truth
- **`zhCN.ts`**: Chinese Simplified translations
+- **`zhTW.ts`**: Traditional Chinese (Taiwan) translations
+- **`ptBR.ts`**: Brazilian Portuguese translations
+- **`jaJP.ts`**: Japanese translations
+- **`koKR.ts`**: Korean translations
+- **`esES.ts`**: Spanish translations
### Translation Keys Organization
@@ -43,9 +48,13 @@ const _translations = {
The language preference is:
1. **Stored in localStorage** with key `'lang'`
-2. **Auto-detection**: If set to `'auto'`, follows system language (`navigator.language`)
- - If system language is `'zh-CN'`, uses Chinese
- - Otherwise, defaults to English
+2. **Auto-detection**: If set to `'auto'` (the default), follows the system language (`navigator.language`):
+ - `zh-TW` / `zh-HK` / `zh-MO` / `zh-Hant` → `zhTW`
+ - other `zh-*` → `zhCN`
+ - `pt-*` → `ptBR`, `ja*` → `jaJP`, `ko*` → `koKR`, `es*` → `esES`
+ - anything else → `enUS`
+
+Invalid stored values fall back to auto-detection, and `fallbackLocale` is `enUS`, so a missing key in any locale renders the English string instead of a raw key.
## Usage in Components
@@ -78,105 +87,33 @@ For dynamic content, use interpolation:
```
-## Language Switcher
-
-Users can change the language in **Settings** page under **Appearance** section. The language selector offers three options:
-
-1. **Auto (Follow System)** - `'auto'`
-2. **English** - `'enUS'`
-3. **简体中文** - `'zhCN'`
-
-When changed, the preference is saved to `localStorage` and the UI updates immediately.
-
-## Translated Pages and Components
-
-### Pages
-- ✅ ConnectionsPage
-- ✅ SettingsPage
-- ✅ HistoryPage
-- ✅ ImportExportPage
-- ✅ QueriesPage
-- ✅ DataStudioPage
-
-### Components
-- ✅ ServerFormDialog
-- ✅ ServerCard
-- ✅ AppHeader (displays app name "SQLKit" - no translation needed)
-
## Adding New Translations
To add translations for a new feature:
-1. **Add keys to both `enUS.ts` and `zhCN.ts`**:
-
-```typescript
-// In enUS.ts
-export const enUS = {
- // ... existing translations
- pages: {
- myNewPage: {
- title: 'My New Page',
- description: 'This is a new page',
- }
- }
-}
-
-// In zhCN.ts
-export const zhCN = {
- // ... existing translations
- pages: {
- myNewPage: {
- title: '我的新页面',
- description: '这是一个新页面',
- }
- }
-}
-```
+1. **Add keys to ALL language files in `src/lang/`** — `enUS.ts` first, then the same keys in every other locale file. The parity test (see below) fails the build if a locale file is missing keys.
2. **Use in component**:
```vue
-
-
{{ t('pages.myNewPage.title') }}
- {{ t('pages.myNewPage.description') }}
```
-## Key Translation Examples
+## Adding a New Language
-### Common Buttons
-- `common.buttons.create` → "Create" / "创建"
-- `common.buttons.save` → "Save" / "保存"
-- `common.buttons.cancel` → "Cancel" / "取消"
-- `common.buttons.delete` → "Delete" / "删除"
-
-### Connection Status
-- `common.status.connected` → "Connected" / "已连接"
-- `common.status.connecting` → "Connecting..." / "连接中..."
-- `common.status.disconnected` → "Disconnected" / "未连接"
-- `common.status.error` → "Connection Error" / "连接错误"
-
-### Server Form
-- `components.serverForm.labels.connectionName` → "Connection Name" / "连接名称"
-- `components.serverForm.labels.host` → "Host" / "主机地址"
-- `components.serverForm.labels.port` → "Port" / "端口"
-- `components.serverForm.labels.database` → "Database" / "数据库"
+1. Copy `src/lang/enUS.ts` to `src/lang/{locale}.ts` (locale codes follow the `zhCN` / `ptBR` style, e.g. `frFR`).
+2. Translate the values. Keep brand names, SQL keywords, code identifiers, keyboard key names, and interpolation placeholders (`{name}`) exactly as they are. Keep language-name keys (if any) as native names.
+3. Register the file in `src/lang/index.ts`: import it, add the locale code to the `AppLocale` type and `AVAILABLE_LOCALES`, add it to the `messages` object, and extend `detectFromNavigator()` so the system language maps to it.
+4. Add the locale to `src/__tests__/i18nParity.test.ts`.
+5. Run `npm test` — the parity test and the key-usage test must both pass.
## Testing
-To test translations:
-
-1. Run the application: `npm run tauri dev`
-2. Navigate to **Settings** page
-3. Change the **Language** dropdown to test different languages
-4. Navigate through different pages to verify translations
-5. Try creating/editing connections to test form translations
+- `src/__tests__/i18nParity.test.ts` asserts every locale file carries exactly the `enUS` key set; CI fails on drift, and missing keys fall back to English at runtime rather than showing raw keys.
+- `src/__tests__/i18nKeys.test.ts` asserts every literal `t('key')` used in source files resolves in `enUS` and `zhCN`.
+- To verify translations manually: run `npm run tauri dev`, switch the system language (or set `localStorage.lang`), and walk through the main pages.
## Implementation Reference
diff --git a/src/__tests__/i18nParity.test.ts b/src/__tests__/i18nParity.test.ts
new file mode 100644
index 00000000..a18a50bb
--- /dev/null
+++ b/src/__tests__/i18nParity.test.ts
@@ -0,0 +1,32 @@
+import { enUS } from '@/lang/enUS'
+import { esES } from '@/lang/esES'
+import { jaJP } from '@/lang/jaJP'
+import { koKR } from '@/lang/koKR'
+import { ptBR } from '@/lang/ptBR'
+import { zhCN } from '@/lang/zhCN'
+import { zhTW } from '@/lang/zhTW'
+
+type Messages = Record
+
+const flatten = (messages: Messages, prefix = ''): string[] =>
+ Object.entries(messages).flatMap(([key, value]) =>
+ value && typeof value === 'object'
+ ? flatten(value as Messages, `${prefix}${key}.`)
+ : [`${prefix}${key}`],
+ )
+
+// Guards against locale drift: every language file must carry exactly the same
+// key set as enUS, otherwise missing keys silently fall back to English at runtime.
+describe('i18n locale parity', () => {
+ const locales: Record = { zhCN, zhTW, ptBR, jaJP, koKR, esES }
+
+ it.each(Object.entries(locales))('%s has exactly the enUS key set', (_name, messages) => {
+ const baseKeys = flatten(enUS as unknown as Messages).sort()
+ const localeKeys = flatten(messages).sort()
+ const missing = baseKeys.filter(key => !localeKeys.includes(key))
+ const extra = localeKeys.filter(key => !baseKeys.includes(key))
+
+ expect(missing).toEqual([])
+ expect(extra).toEqual([])
+ })
+})
diff --git a/src/lang/esES.ts b/src/lang/esES.ts
new file mode 100644
index 00000000..281bc431
--- /dev/null
+++ b/src/lang/esES.ts
@@ -0,0 +1,2050 @@
+export const esES = {
+ aiPermissions: {
+ ultimateOnly: 'La configuración de IA por conexión requiere Ultimate',
+ accessLevel: 'Nivel de acceso',
+ unavailable: 'No disponible',
+ loadError: 'No se pudieron cargar los permisos',
+ saving: 'Guardando…',
+ deniedByConnection: 'Denegado por los permisos de la conexión',
+ conversationReadOnly: 'Solo lectura para esta conversación',
+ title: 'Permisos de IA',
+ help: 'Se aplica a Data Studio y a clientes MCP externos. Usa los valores predeterminados del sistema o establece permisos para esta conexión.',
+ loading: 'Cargando permisos…',
+ loadFailed: 'No se pudieron cargar los permisos. Reintenta antes de guardar esta conexión.',
+ retry: 'Reintentar',
+ inherit: 'Usar el valor predeterminado del sistema',
+ none: 'Sin acceso',
+ read: 'Lectura',
+ data: 'Leer y modificar datos',
+ full: 'Acceso total',
+ custom: 'Personalizado',
+ effective: 'Acceso efectivo',
+ create: 'Crear datos',
+ update: 'Actualizar datos',
+ delete: 'Eliminar datos',
+ manage: 'Administrar estructura y administración',
+ allow: 'Permitir',
+ deny: 'Denegar',
+ fromConnection: 'Esta conexión',
+ defaults: 'Permisos de IA predeterminados',
+ defaultsHelp: 'Se aplica a Data Studio y a clientes MCP externos. Las conexiones siguen estos valores predeterminados, salvo que una acción se configure en la conexión.',
+ save: 'Guardar valores predeterminados',
+ saved: 'Permisos guardados',
+ saveFailed: 'No se pudo guardar los permisos',
+ inheritHelp: 'Sigue los valores predeterminados del sistema, incluidos los cambios futuros.',
+ noneHelp: 'Sin acceso a datos ni acciones administrativas.',
+ readHelp: 'Lee datos e inspecciona la estructura; sin cambios.',
+ dataHelp: 'Cambios de datos, incluida la eliminación. Sin cambios de estructura ni de administración.',
+ fullHelp: 'Todas las acciones sobre datos, cambios de estructura y administración.',
+ customHelp: 'Elige qué acciones individuales puede realizar la IA.',
+ defaultDecision: 'Usar el valor predeterminado ({decision})',
+ readPreset: 'Solo lectura',
+ },
+
+ device: {
+ replaceTitle: 'Límite de dispositivos alcanzado',
+ replaceDescription:
+ 'Tu suscripción puede permanecer activada en hasta {limit} dispositivos. Elige abajo un dispositivo para reemplazarlo por este; el dispositivo reemplazado pierde el acceso de inmediato.',
+ slotUsage: '{used}/{limit} dispositivos en uso',
+ thisDevice: 'Este dispositivo',
+ lastActive: 'Última actividad',
+ neverActive: 'Nunca',
+ replaceConfirm: 'Reemplazar y activar',
+ replaceFailed: 'No se pudo reemplazar el dispositivo. Elige otro e inténtalo de nuevo.',
+ },
+ plan: {
+ tab: 'Cuenta y plan',
+ pricing: 'Ultimate $9.9/mes · $99/año · Prueba gratis de 7 días',
+ state: {
+ ultimate: 'Ultimate',
+ community: 'Community',
+ unknown: 'Desconocido',
+ checking: 'Comprobando…',
+ },
+ gate: {
+ additive: 'Todo lo de Community, además:',
+ recommended: 'Recomendado',
+ currentFeature: 'Esta función',
+ trustLine: 'El bloqueo de versión mantiene tus versiones pagadas · Cancela cuando quieras',
+ headline: {
+ ai: 'Pregunta a tus datos en lenguaje natural',
+ transfer: 'Mueve datos en volumen: rápido y seguro',
+ er_diagram: 'Ve tu esquema como un mapa',
+ ssh_tunnel: 'Accede a bases de datos remotas por SSH',
+ mcp_bridge: 'Integra SQLKit en tu stack de agentes',
+ },
+ tiles: {
+ aiQueryT: 'Consultas en lenguaje natural',
+ aiQueryD: 'Pregunta en lenguaje natural y obtén SQL editable',
+ aiAgentT: 'Explicación y corrección con agente',
+ aiAgentD: 'Un clic para optimizar consultas lentas',
+ mcpServerT: 'Servidor MCP integrado',
+ mcpServerD: 'Se ejecuta localmente: cero configuración',
+ mcpClientsT: 'Cualquier cliente MCP',
+ mcpClientsD: 'Claude Desktop, Cursor y más',
+ },
+ groups: {
+ cloud: 'Nube',
+ local: 'Local',
+ custom: 'Personalizado',
+ clients: 'Clientes',
+ },
+ detail: {
+ ai: 'Funciona con cualquier modelo: nube, local o personalizado',
+ mcp: 'Se conecta a tus clientes MCP favoritos',
+ },
+ price: {
+ yearly: '$99 / año',
+ save: 'Ahorra 17%',
+ monthly: '$9.9 / mes',
+ },
+ trust: {
+ versionLock: 'Las versiones publicadas durante tu suscripción quedan tuyas, incluso sin conexión',
+ byok: 'Usa tu propia clave de LLM: sin recargo en tokens',
+ cancel: 'Cancela cuando quieras',
+ },
+ cta: {
+ unlock: 'Desbloquea con Ultimate',
+ unlockSub: 'Prueba gratis de 7 días · $9.9/mes · $99/año',
+ },
+ },
+ poster: {
+ mcp: {
+ clients: 'Compatible con',
+ config: 'Configuración del cliente',
+ },
+ ai: {
+ question: 'Encuentra los pagos fallidos de los últimos 7 días',
+ loop: 'Bucle 1',
+ thinking: 'Pensando',
+ toolVerb: 'Consultó public.orders',
+ answer: 'Se encontraron 3 pagos fallidos. Consulta generada:',
+ },
+ transfer: {
+ scopeDatabase: 'Base de datos completa',
+ },
+ },
+ compare: {
+ ai: 'Asistente de IA y NL2SQL',
+ er_diagram: 'Diagramas ER',
+ transfer: 'Importación / exportación masiva y migración',
+ ssh: 'Túnel SSH',
+ mcp: 'Puente MCP',
+ versionLock: 'Bloqueo de versión',
+ },
+ upgrade: {
+ title: 'Actualiza a Ultimate',
+ cta: 'Actualizar',
+ refresh: 'Actualizar beneficios',
+ startFree: 'Empieza gratis',
+ versionPermanent: 'Las versiones obtenidas con la suscripción se usan de forma permanente, incluso sin conexión.',
+ versionLockedOut: 'Esta versión requiere una suscripción activa para desbloquearse. Renuévala para desbloquearla de forma permanente.',
+ },
+ section: {
+ title: 'Cuenta y plan',
+ desc: 'Beneficios de la suscripción y estado del bloqueo de versión de esta instalación.',
+ versionPermanent: 'La versión actual se usa de forma permanente (cubierto por tu bloqueo de versión).',
+ subscriptionActive: 'Ultimate está activo: todas las funciones desbloqueadas mientras dure la suscripción.',
+ versionLockedOut: 'Esta versión ({date}) no está cubierta por un bloqueo de versión; se muestra el modo Community.',
+ expiresAt: 'Activo hasta {time}',
+ cancelScheduled: 'La suscripción está programada para finalizar al cierre del período de facturación actual.',
+ checkFailed: 'No se pudieron verificar los beneficios; se muestra el estado en caché. Revisa tu red y actualiza.',
+ sessionExpired: 'La sesión expiró; inicia sesión de nuevo para verificar tu plan.',
+ sessionLostSignedOut: 'Tu sesión ya no se puede renovar: se cerró tu sesión. Inicia sesión de nuevo cuando quieras.',
+ deviceActivationFailed: 'Falló el registro del dispositivo: la renovación automática de sesión no está disponible.',
+ notLoggedIn: 'No has iniciado sesión.',
+ loginLink: 'Inicia sesión con Geekfun',
+ refresh: 'Actualizar',
+ logout: 'Cerrar sesión',
+ manage: 'Administrar suscripción',
+ },
+ },
+ aside: {
+ aiAssistant: 'Asistente de IA',
+ tasks: 'Tareas',
+ },
+ connection: {
+ prompt: {
+ title: 'Prompt de agente',
+ label: 'Prompt de agente',
+ description: 'Agrega contexto sobre esta conexión para el agente de IA.',
+ help: 'Se envía al agente cada vez que se adjunta esta conexión, después del prompt de sistema global.',
+ placeholder: 'Describe el significado de negocio de los datos, las convenciones de nombres o las consultas habituales.',
+ configured: 'Configurado',
+ add: 'Agregar',
+ edit: 'Editar',
+ clear: 'Limpiar',
+ cancel: 'Cancelar',
+ confirm: 'Confirmar',
+ },
+ },
+ connectionsPage: {
+ addSshProfile: 'Agregar perfil SSH',
+ copySuffix: ' (Copia)',
+ sshProfilesSection: 'Perfiles SSH',
+ sshProfile: 'Perfil SSH',
+ },
+ common: {
+
+ copy: 'Copiar',
+ copied: '¡Copiado!',
+ browse: 'Examinar',
+ settings: 'Configuración',
+ loading: 'Cargando...',
+ notifications: {
+ codeCopied: 'Código copiado',
+ },
+ buttons: {
+ create: 'Crear',
+ save: 'Guardar',
+ cancel: 'Cancelar',
+ delete: 'Eliminar',
+ edit: 'Editar',
+ confirm: 'Confirmar',
+ test: 'Probar',
+ connect: 'Conectar',
+ disconnect: 'Desconectar',
+ duplicate: 'Duplicar',
+ saveChanges: 'Guardar cambios',
+ createConnection: 'Crear conexión',
+ testConnection: 'Probar conexión',
+ dismiss: 'Descartar',
+ close: 'Cerrar',
+ browse: 'Examinar',
+ retry: 'Reintentar',
+ continue: 'Continuar',
+ refresh: 'Actualizar',
+ },
+ status: {
+ connected: 'Conectado',
+ disconnected: 'Desconectado',
+ connecting: 'Conectando...',
+ error: 'Error de conexión',
+ testing: 'Probando conexión...',
+ success: '¡Conexión exitosa!',
+ failed: 'Conexión fallida',
+ },
+ },
+ ssl: {
+ errors: {
+ invalidMode: 'Modo SSL no válido',
+ caCertRequired: 'La ruta del certificado CA es obligatoria para los modos verify-ca/verify-full',
+ invalidCaPath: 'Ruta del certificado CA no válida',
+ invalidCertPath: 'Ruta del certificado de cliente no válida',
+ invalidKeyPath: 'Ruta de la clave privada del cliente no válida',
+ },
+ mode: {
+ label: 'Modo SSL/TLS',
+ disable: 'Deshabilitar',
+ prefer: 'Preferir',
+ require: 'Requerir',
+ verifyca: 'Verificar CA',
+ verifyfull: 'Verificación completa',
+ },
+ modeDesc: {
+ disable: 'Sin cifrado',
+ prefer: 'Intenta cifrar y recurre a texto plano',
+ require: 'Siempre cifra, omite la validación del certificado',
+ verifyca: 'Cifra + verifica el certificado CA',
+ verifyfull: 'Cifra + verifica CA y host',
+ },
+ certSettings: {
+ title: 'Configuración de certificados',
+ caCert: 'Certificado CA',
+ caCertPlaceholder: 'Ruta al certificado CA',
+ clientCert: 'Certificado de cliente',
+ clientCertPlaceholder: 'Ruta al certificado de cliente',
+ clientKey: 'Clave privada del cliente',
+ clientKeyPlaceholder: 'Ruta a la clave privada del cliente',
+ },
+ sqlServer: {
+ trustServerCert: 'Confiar en el certificado del servidor',
+ trustServerCertHint: 'Aceptar certificados autofirmados',
+ },
+ },
+ transfer: {
+ title: 'Transferencia',
+ subtitle: 'Importa, exporta y migra tus datos',
+ tabs: {
+ export: 'Exportar',
+ import: 'Importar',
+ migration: 'Migración',
+ structure: 'Estructura',
+ },
+ export: {
+ step: {
+ source: 'Origen',
+ format: 'Formato',
+ output: 'Salida',
+ formatOutput: 'Formato y salida',
+ preview: 'Vista previa',
+ execute: 'Iniciar exportación',
+ },
+ selectTablesFirst: 'Selecciona tablas arriba para configurar las columnas',
+ tables: {
+ label: 'Tablas',
+ loadFailed: 'No se pudieron cargar las tablas',
+ },
+ columns: {
+ label: 'Columnas',
+ selectAll: 'Seleccionar todas',
+ deselectAll: 'Desmarcar todas',
+ loadFailed: 'No se pudieron cargar las columnas',
+ },
+ whereClause: 'Cláusula WHERE (opcional)',
+ where: 'Cláusula WHERE (opcional)',
+ whereClausePlaceholder: 'status = "active"',
+ orderBy: 'ORDER BY (opcional)',
+ orderByPlaceholder: 'created_at DESC',
+ limit: 'LIMIT (opcional)',
+ limitPlaceholder: '1000',
+ scope: 'Alcance',
+ delimiter: 'Delimitador',
+ delimiterOptions: {
+ comma: 'Coma (,)',
+ semicolon: 'Punto y coma (;)',
+ tab: 'Tabulación',
+ },
+ includeHeader: 'Incluir encabezado',
+ dateFormat: 'Formato de fecha',
+ dateFormatOptions: {
+ iso8601: 'ISO 8601',
+ unix: 'Unix',
+ },
+ rowsPerBatch: 'Filas/lote',
+ createTable: 'CREATE TABLE',
+ dropTable: 'DROP TABLE',
+ worksheet: 'Hoja',
+ freeze: 'Inmovilizar',
+ autoFit: 'Ajuste automático',
+ outputPath: 'Ruta de salida',
+ selectFormat: 'Seleccionar formato',
+ showAdvanced: 'Mostrar opciones avanzadas',
+ hideAdvanced: 'Ocultar opciones avanzadas',
+ encoding: 'Codificación',
+ preview: 'Vista previa',
+ outputFile: 'Archivo de salida',
+ },
+ connection: {
+ connectFailed: 'No se pudo conectar',
+ databasesFailed: 'No se pudieron cargar las bases de datos',
+ schemasFailed: 'No se pudieron cargar los esquemas',
+ label: 'Conexión',
+ placeholder: 'Seleccionar conexión',
+ noConnections: 'No hay conexiones disponibles. Agrega primero una conexión.',
+ connected: 'Conectado',
+ offline: 'Sin conexión',
+ databaseLabel: 'Base de datos',
+ databasePlaceholder: 'Seleccionar base de datos',
+ system: 'Sistema',
+ loadingDatabases: 'Cargando bases de datos...',
+ schemaLabel: 'Esquema',
+ schemaPlaceholder: 'Seleccionar esquema',
+ loadingSchemas: 'Cargando esquemas...',
+ tableLabel: 'Tabla',
+ tablePlaceholder: 'Seleccionar tabla',
+ },
+ import: {
+ step: {
+ file: 'Seleccionar archivo',
+ mapping: 'Destino y mapeo',
+ options: 'Opciones y vista previa',
+ execute: 'Importar',
+ },
+ dropzone: {
+ title: 'Arrastra y suelta un archivo aquí',
+ subtitle: 'o haz clic para explorar',
+ supported: 'Compatible con: CSV, JSONL, SQL, Excel (.xlsx)',
+ instruction: 'o haz clic para explorar en tu equipo',
+ },
+ detected: {
+ format: 'Formato detectado',
+ encoding: 'Codificación detectada',
+ rows: 'Filas (estimadas)',
+ },
+ autoMap: 'Asignación automática por nombre',
+ clearAll: 'Borrar todo',
+ conflict: {
+ label: 'En conflicto',
+ skip: 'Omitir duplicados',
+ replace: 'Reemplazar existentes',
+ upsert: 'Actualizar existentes (upsert)',
+ abort: 'Abortar ante errores',
+ },
+ truncateBefore: 'Truncar la tabla antes de importar',
+ dryRun: 'Simulación (validar sin insertar)',
+ browseFiles: 'Explorar archivos',
+ fileSize: 'Tamaño del archivo',
+ detectedColumns: 'Columnas detectadas',
+ createDbIfNotExists: 'Crear la base de datos si no existe',
+ tablesAutoCreated: 'Las tablas se crearán automáticamente',
+ skipPlaceholder: 'Omitir',
+ skip: '(Omitir)',
+ importData: 'Importar datos',
+ dataPreview: 'VISTA PREVIA DE DATOS',
+ previewRows: '10 filas',
+ selectFileToPreview: 'Selecciona un archivo para previsualizar los datos',
+ importSettings: 'CONFIGURACIÓN DE IMPORTACIÓN',
+ batchSize: 'Tamaño del lote',
+ loadingPreview: 'Cargando vista previa...',
+ noPreviewData: 'Sin datos de vista previa',
+ fileDetails: 'DETALLES DEL ARCHIVO',
+ },
+ structure: {
+ title: 'Estructura',
+ subtitle: 'Genera DDL y ejecuta archivos SQL',
+ generateDdl: 'Generar DDL',
+ runSqlFile: 'Ejecutar archivo SQL',
+ objects: 'Objetos de base de datos',
+ selectAll: 'Seleccionar todas',
+ deselectAll: 'Desmarcar todas',
+ loadingObjects: 'Cargando objetos...',
+ noObjects: 'No se encontraron objetos. Selecciona una conexión y una base de datos.',
+ objectsSelected: 'objetos seleccionados',
+ options: 'Opciones de DDL',
+ includeCreateTable: 'Sentencias CREATE TABLE',
+ includePrimaryKeys: 'Claves primarias',
+ includeForeignKeys: 'Claves foráneas',
+ includeIndexes: 'Índices',
+ includeDropIfExists: 'DROP IF EXISTS antes de CREATE',
+ includeIfNotExists: 'IF NOT EXISTS en CREATE',
+ generate: 'Generar DDL',
+ preview: 'Vista previa del DDL',
+ copyToClipboard: 'Copiar al portapapeles',
+ saveToFile: 'Guardar en archivo...',
+ sqlFile: 'Archivo SQL',
+ errorHandling: 'Manejo de errores',
+ onErrorStop: 'Detener en el primer error',
+ onErrorSkip: 'Omitir y continuar',
+ onErrorRollback: 'Revertir (mejor esfuerzo; aborta en el primer error)',
+ reset: 'Restablecer',
+ execute: 'Ejecutar',
+ },
+ migration: {
+ title: 'Migración',
+ subtitle: 'Migración de datos entre motores',
+ step: {
+ source: 'Origen',
+ target: 'Destino',
+ mapping: 'Mapeo',
+ configure: 'Configurar',
+ execute: 'Ejecutar',
+ },
+ sourceConnection: 'Conexión de origen',
+ targetConnection: 'Conexión de destino',
+ availableTables: 'Tablas disponibles',
+ loadingTables: 'Cargando tablas...',
+ noTables: 'No se encontraron tablas',
+ selectAll: 'Seleccionar todas',
+ deselectAll: 'Desmarcar todas',
+ tablesSelected: 'tablas seleccionadas',
+ direction: 'Dirección de migración',
+ createTables: 'Crear las tablas de destino si no existen',
+ dropTables: 'Eliminar las tablas de destino antes de la migración',
+ loadingMapping: 'Generando conversiones de tipos...',
+ typeConversions: 'columnas requieren conversión de tipo',
+ batchSize: 'Tamaño del lote',
+ onError: 'Ante errores',
+ onErrorSkipRow: 'Omitir la fila y continuar',
+ onErrorSkipTable: 'Omitir la tabla y continuar',
+ onErrorAbort: 'Abortar la migración',
+ migrateIndexes: 'Migrar índices',
+ migrateForeignKeys: 'Migrar claves foráneas',
+ migrateConstraints: 'Migrar restricciones',
+ summary: 'Resumen de la migración',
+ tables: 'Tablas',
+ totalRows: 'Total de filas',
+ conversions: 'Conversiones de tipos',
+ executing: 'Ejecutando migración...',
+ pleaseWait: 'Espera mientras se transfieren los datos',
+ startMigration: 'Iniciar migración',
+ migrateAgain: 'Migrar de nuevo',
+ back: 'Atrás',
+ next: 'Siguiente',
+ },
+ format: {
+ label: 'Formato',
+ csv: 'CSV (.csv)',
+ jsonl: 'JSONL (.jsonl)',
+ sql: 'SQL (.sql)',
+ excel: 'Excel (.xlsx)',
+ defaults: {
+ csv: 'Delimitador de coma, comillas dobles, UTF-8, incluir encabezado',
+ jsonl: 'Un objeto JSON por línea, compacto, UTF-8, fechas ISO 8601',
+ sql: 'Tabla de destino autocompletada, tamaño de lote 1000, incluir CREATE TABLE',
+ excel: 'Incluir encabezado, ajustar columnas automáticamente, inmovilizar fila de encabezado',
+ },
+ advancedOptions: 'Opciones avanzadas',
+ },
+ progress: {
+ preparing: 'Preparando',
+ exporting: 'Exportando...',
+ importing: 'Importando...',
+ elapsed: 'Transcurrido',
+ remaining: 'Restante estimado',
+ rows: 'Filas',
+ exported: 'exportadas',
+ imported: 'importadas',
+ skipped: 'omitidas',
+ errors: 'errores',
+ cancel: 'Cancelar',
+ runInBackground: 'Ejecutar en segundo plano',
+ },
+ result: {
+ success: 'completado con éxito',
+ partial: 'completado con errores',
+ failed: 'falló',
+ duration: 'Duración',
+ file: 'Archivo',
+ openFile: 'Abrir archivo',
+ openFolder: 'Abrir carpeta',
+ exportAgain: 'Exportar de nuevo',
+ importAgain: 'Importar de nuevo',
+ viewTable: 'Ver tabla',
+ processed: 'Procesadas',
+ skipped: 'Omitidas',
+ errorCount: 'Errores',
+ },
+ tasks: {
+ title: 'Tareas',
+ clearCompleted: 'Borrar completadas',
+ goToTask: 'Ir a la tarea',
+ dismiss: 'Descartar',
+ noTasks: 'No hay tareas de transferencia',
+ rows: 'filas',
+ emptyDescription: 'Los trabajos de exportación, importación y migración aparecerán aquí',
+ status: {
+ pending: 'Pendiente',
+ running: 'En ejecución',
+ completed: 'Completada',
+ failed: 'Fallida',
+ },
+ startedAgo: 'Iniciada hace {time}',
+ },
+ common: {
+
+ connection: 'Conexión',
+ database: 'Base de datos',
+ schema: 'Esquema',
+ table: 'Tabla',
+ back: 'Atrás',
+ next: 'Siguiente',
+ browse: 'Examinar...',
+ error: 'Error',
+ cancel: 'Cancelar',
+ save: 'Guardar',
+ close: 'Cerrar',
+ tableName: 'Nombre de la tabla',
+ rows: 'Filas',
+ type: 'Tipo',
+ noTablesFound: 'No se encontraron tablas',
+ columns: 'Columnas',
+ deselectAll: 'Desmarcar todas',
+ scopeServer: 'Servidor',
+ scopeDatabase: 'Base de datos',
+ scopeTables: 'Tablas',
+ },
+ },
+ pages: {
+ connections: {
+ title: 'Conexiones',
+ subtitle: 'Administra tus conexiones de base de datos',
+ search: 'Buscar conexiones...',
+ stats: {
+ totalConnections: 'Conexiones totales',
+ activeSessions: 'Sesiones activas',
+ sshProfiles: 'Perfiles SSH',
+ ago: 'hace {time}',
+ },
+ saved: 'Conexiones guardadas',
+ addNew: 'Agregar nueva conexión',
+ addNewHint: 'PostgreSQL, MySQL, SQLite...',
+ empty: {
+ title: 'No se encontraron conexiones',
+ message: 'Ninguna conexión coincide con tu búsqueda "{query}"',
+ },
+ delete: {
+ title: 'Eliminar conexión',
+ message: '¿Seguro que quieres eliminar "{name}"? Esta acción no se puede deshacer.',
+ },
+ error: {
+ title: 'Error de conexión',
+ },
+ saveFailed: 'No se pudo guardar la conexión',
+ },
+ settings: {
+ title: 'Configuración',
+ subtitle: 'Configura tus preferencias de la aplicación',
+ general: {
+ title: 'General',
+ description: 'Administra tu cuenta, plan, tema y actualizaciones de la aplicación',
+ theme: 'Tema',
+ themeSelect: 'Seleccionar tema',
+ themeHelp: 'Elige entre tema claro, oscuro o del sistema',
+ themes: {
+ light: 'Claro',
+ dark: 'Oscuro',
+ system: 'Sistema',
+ },
+ language: 'Idioma',
+ languageSelect: 'Seleccionar idioma',
+ languageHelp: 'Elige tu idioma preferido',
+ languages: {
+ enUS: 'Inglés',
+ zhCN: '简体中文',
+ auto: 'Automático (según el sistema)',
+ },
+ },
+ mcp: {
+ title: 'Puente MCP',
+ status: 'Estado',
+ running: 'Ejecutándose en el puerto {port}',
+ stopped: 'Detenido',
+ port: 'Puerto',
+ portDesc: 'Puerto del servidor del puente MCP (déjalo vacío para automático)',
+ restart: 'Reiniciar puente',
+ restartSuccess: 'Puente MCP reiniciado correctamente',
+ restartFailed: 'No se pudo reiniciar',
+ restartFailedDetail: 'No se pudo reiniciar el puente MCP',
+ restartTimeout: 'El puente MCP no se inició en 60 segundos',
+ shuttingDown: 'Apagando...',
+ starting: 'Iniciando...',
+ autoStart: 'Inicio automático',
+ autoStartDesc: 'Iniciar el puente MCP automáticamente al abrir la aplicación',
+ saveFailed: 'No se pudo guardar la configuración de MCP',
+ },
+ about: {
+ title: 'Acerca de',
+ version: 'Versión',
+ license: 'Licencia',
+ licenseName: 'Apache 2.0',
+ repository: 'Repositorio',
+ website: 'Sitio web',
+ copyright: '© {year} GEEKFUN. Todos los derechos reservados.',
+ description: 'SqlKit es un cliente GUI multiplataforma para bases de datos SQL basado en agentes de IA. Construido con Rust + Tauri.',
+ },
+ feedback: {
+ preparing: 'Preparando descarga…',
+ downloading: 'Descargando…',
+ installing: 'Instalando y verificando…',
+ complete: 'Instalación completada',
+ failed: 'La acción falló',
+ checking: 'Buscando actualizaciones…',
+ removing: 'Eliminando…',
+ removed: 'Eliminado correctamente',
+ refreshing: 'Actualizando estado…',
+ refreshed: 'Estado actualizado',
+ loading: 'Cargando configuración…',
+ loadFailed: 'No se pudo cargar esta sección',
+ retry: 'Reintentar',
+ saved: 'Cambios guardados',
+ saving: 'Guardando cambios…',
+ testing: 'Probando conexión…',
+ syncing: 'Sincronizando modelos…',
+ synced: 'Modelos sincronizados',
+ opening: 'Abriendo en tu navegador…',
+ opened: 'Abierto en tu navegador',
+ signedOut: 'Sesión cerrada',
+ },
+ jre: {
+ title: 'JRE y controladores',
+ description: 'Administra el Java Runtime y los controladores JDBC para las conexiones de base de datos',
+ jreCard: {
+ title: 'Java Runtime',
+ description: 'Necesario para conexiones mediante puente JDBC (Oracle, DB2, H2, Derby)',
+ status: {
+ installed: 'Instalado',
+ notInstalled: 'No instalado',
+ checking: 'Comprobando...',
+ managed: 'Administrado',
+ system: 'Sistema',
+ versionUnknown: 'Desconocida',
+ systemWarning: 'La versión de Java del sistema es desconocida o incompatible. Descarga el JRE administrado para garantizar la compatibilidad.',
+ systemInvalid: 'No hay un JRE válido',
+ managedRecommended: 'Usar JRE administrado',
+ },
+ actions: {
+ download: 'Descargar JRE',
+ remove: 'Eliminar JRE',
+ redownload: 'Volver a descargar',
+ checkUpdates: 'Buscar actualizaciones',
+ },
+ notifications: {
+ upToDate: 'El JRE está actualizado',
+ updateAvailable: 'Actualización de JRE disponible',
+ newVersion: 'La versión {version} está disponible',
+ checkUpdatesFailed: 'No se pudo buscar actualizaciones de JRE',
+ downloadFailed: 'No se pudo descargar el JRE',
+ downloadSuccess: 'JRE descargado correctamente',
+ removeFailed: 'No se pudo eliminar el JRE',
+ },
+ },
+ bridgeCard: {
+ title: 'JAR del puente',
+ description: 'Componente de puente JDBC para conexiones de base de datos',
+ status: {
+ installed: 'Instalado',
+ notInstalled: 'No instalado',
+ checking: 'Comprobando...',
+ },
+ actions: {
+ download: 'Descargar puente',
+ remove: 'Eliminar puente',
+ },
+ notifications: {
+ downloadFailed: 'No se pudo descargar el JAR del puente',
+ downloadSuccess: 'JAR del puente descargado correctamente',
+ removeFailed: 'No se pudo eliminar el JAR del puente',
+ },
+ },
+ jdbcToggle: {
+ title: 'Conexiones JDBC',
+ description: 'Habilitar compatibilidad con bases de datos JDBC (JRE + puente + controladores)',
+ label: 'JDBC no necesario',
+ },
+ actions: {
+ refresh: 'Actualizar',
+ },
+ driversCard: {
+ title: 'Controladores JDBC',
+ description: 'Archivos de controladores JDBC específicos por base de datos',
+ label: {
+ versions: 'versiones',
+ },
+ status: {
+ installed: 'Instalado',
+ notInstalled: 'No instalado',
+ loading: 'Cargando controladores...',
+ },
+ actions: {
+ download: 'Descargar',
+ remove: 'Eliminar',
+ checkUpdates: 'Buscar actualizaciones',
+ },
+ notifications: {
+ upToDate: 'El controlador está actualizado',
+ updateAvailable: 'Actualización de controlador disponible',
+ newVersion: 'La versión {version} está disponible',
+ checkUpdatesFailed: 'No se pudo buscar actualizaciones del controlador',
+ downloadFailed: 'No se pudo descargar el controlador',
+ downloadSuccess: 'Controlador descargado correctamente',
+ removeFailed: 'No se pudo eliminar el controlador',
+ installBridgeFirst: 'Instala primero el JAR del puente y luego intenta descargar los controladores',
+ },
+ empty: {
+ title: 'No hay controladores configurados',
+ message: 'Se descargarán automáticamente al conectarte a una base de datos JDBC.',
+ },
+ },
+ },
+ editor: {
+ title: 'Editor',
+ description: 'Configura el comportamiento y la apariencia del editor SQL',
+ fontSize: 'Tamaño de fuente',
+ fontSizeHelp: 'Tamaño de fuente del editor en píxeles (8–32)',
+ fontSizeError: 'El tamaño de fuente debe estar entre 8 y 32',
+ tabSize: 'Tamaño de tabulación',
+ tabSizeHelp: 'Número de espacios por tabulación (1–8)',
+ tabSizeError: 'El tamaño de tabulación debe estar entre 1 y 8',
+ wordWrap: 'Ajuste de línea',
+ wordWrapHelp: 'Ajusta las líneas largas en el editor',
+ showLineNumbers: 'Mostrar números de línea',
+ showLineNumbersHelp: 'Muestra los números de línea en el margen del editor',
+ showMinimap: 'Mostrar minimapa',
+ showMinimapHelp: 'Muestra una vista de minimapa al lado derecho',
+ indentWidth: 'Ancho de sangría',
+ indentWidthHelp: 'Espacios por nivel de sangría en el SQL formateado (1–8)',
+ indentWidthError: 'El ancho de sangría debe estar entre 1 y 8',
+ lineWidth: 'Ancho de línea',
+ lineWidthHelp: 'Ancho de línea objetivo en caracteres para el SQL formateado (40–200)',
+ lineWidthError: 'El ancho de línea debe estar entre 40 y 200',
+ },
+ query: {
+ title: 'Consulta',
+ description: 'Configura los valores predeterminados de ejecución de consultas',
+ defaultLimit: 'Límite de filas predeterminado',
+ defaultLimitHelp: 'Máximo de filas devueltas por consulta (10–10000)',
+ defaultLimitError: 'El límite de filas debe estar entre 10 y 10000',
+ queryTimeout: 'Tiempo de espera de consulta (s)',
+ queryTimeoutHelp: 'Tiempo máximo de ejecución de la consulta en segundos (1–300)',
+ queryTimeoutError: 'El tiempo de espera debe estar entre 1 y 300 segundos',
+ autoSave: 'Autoguardado',
+ autoSaveHelp: 'Guarda automáticamente los cambios de la consulta',
+ },
+ ai: {
+ title: 'Configuración de IA',
+ tabLabel: 'LLMs',
+ description: 'Configura los proveedores de modelos de IA y el comportamiento del chat',
+ missing: 'No hay ningún modelo de IA configurado. Agrega un proveedor y selecciona un modelo en Configuración.',
+ providerList: {
+ title: 'Proveedores',
+ description: 'Administra tus proveedores de modelos de IA',
+ addProvider: 'Agregar proveedor',
+ empty: 'No hay proveedores configurados. Agrega uno para habilitar las funciones de IA.',
+ emptyAction: 'Agrega tu primer proveedor',
+ deleteConfirm: '¿Seguro que quieres eliminar "{name}"?',
+ deleteConfirmTitle: 'Eliminar proveedor',
+ sync: 'Sincronizar modelos',
+ syncing: 'Sincronizando...',
+ syncSuccess: '{count} modelos sincronizados',
+ syncFailed: 'No se pudo sincronizar los modelos',
+ modelCount: '{count} modelos',
+ testConnection: 'Probar',
+ testing: 'Probando...',
+ testSuccess: 'Conexión exitosa',
+ testFailed: 'La prueba de conexión falló',
+ },
+ form: {
+ addTitle: 'Agregar proveedor',
+ editTitle: 'Editar proveedor',
+ providerType: 'Tipo de proveedor',
+ providerTypeHelp: 'Selecciona un preajuste o elige Personalizado para otros proveedores',
+ presetOpenai: 'OpenAI',
+ presetAnthropic: 'Anthropic',
+ presetAzure: 'Azure OpenAI',
+ presetCustom: 'Personalizado',
+ name: 'Nombre visible',
+ namePlaceholder: 'Mi proveedor',
+ nameHelp: 'Un nombre fácil de recordar para este proveedor',
+ apiCompatibility: 'Compatibilidad de API',
+ apiCompatibilityPlaceholder: 'openai, anthropic, azure',
+ apiCompatibilityHelp: 'Tipo de protocolo de API. Usa "openai" para servicios compatibles como Ollama o DeepSeek.',
+ apiKey: 'Clave de API',
+ apiKeyPlaceholder: 'sk-...',
+ apiKeyHelp: 'Tu clave de API del proveedor. Se guarda localmente y nunca se envía a nuestros servidores.',
+ baseUrl: 'URL base',
+ baseUrlPlaceholder: 'https://api.openai.com/v1',
+ baseUrlHelp: 'URL del endpoint de la API. Deja el valor predeterminado para proveedores oficiales.',
+ proxy: 'Proxy',
+ proxyPlaceholder: 'http://proxy:8080',
+ proxyHelp: 'Proxy HTTP/SOCKS5 opcional para las solicitudes de API',
+ proxyMode: 'Modo de proxy',
+ contextWindow: 'Anular ventana de contexto',
+ contextWindowHelp: 'Anula el tamaño predeterminado de la ventana de contexto (opcional)',
+ showKey: 'Mostrar',
+ hideKey: 'Ocultar',
+ save: 'Guardar proveedor',
+ models: 'Modelos',
+ modelsPlaceholder: 'gpt-4o, gpt-4o-mini',
+ modelsHelp: 'IDs de modelos separados por comas. Se sincronizan automáticamente desde la API del proveedor si está disponible.',
+ validation: {
+ nameRequired: 'El nombre visible es obligatorio',
+ apiCompatibilityRequired: 'La compatibilidad de API es obligatoria',
+ invalidApiCompatibility: 'La compatibilidad de API debe ser "openai", "anthropic" o "azure"',
+ baseUrlInvalid: 'La URL base debe comenzar con http:// o https://',
+ },
+ },
+ chat: {
+ title: 'Agente',
+ description: 'Configura el comportamiento del agente en tiempo de ejecución',
+ autoCompactLabel: 'Compactar mensajes automáticamente',
+ autoCompactDescription: 'Resume automáticamente los mensajes antiguos para ahorrar tokens al acercarse al límite de contexto',
+ maxIterationsLabel: 'Iteraciones máximas',
+ maxIterationsDescription: 'Número máximo de iteraciones de llamadas a herramientas antes de que el agente se detenga (1–1000)',
+ wallClockBudgetLabel: 'Tiempo máximo (min)',
+ wallClockBudgetDescription: 'Tiempo máximo de reloj en minutos antes de que el agente se detenga (1–240)',
+ tokenBudgetLabel: 'Presupuesto de tokens',
+ tokenBudgetDescription: 'Máximo de tokens consumidos antes de que el agente se detenga',
+ systemPromptLabel: 'Prompt del sistema',
+ systemPromptDescription: 'Prompt de sistema global que se envía al agente cuando se adjunta una conexión de base de datos. Describe tu uso, terminología o contexto de negocio.',
+ systemPromptAdd: 'Agregar prompt del sistema',
+ systemPromptEdit: 'Editar prompt del sistema',
+ systemPromptDelete: 'Eliminar prompt del sistema',
+ systemPromptEmpty: 'No hay prompt del sistema configurado.',
+ systemPromptSave: 'Guardar',
+ systemPromptCancel: 'Cancelar',
+ systemPromptSaveFailed: 'No se pudo guardar el prompt del sistema.',
+ systemPromptUltimateOnly: 'El prompt de agente es una función de Ultimate',
+ },
+ },
+ updates: {
+ title: 'Actualizaciones',
+ description: 'Busca actualizaciones de la aplicación',
+ checkForUpdates: 'Buscar actualizaciones',
+ checkForUpdatesHelp: 'Se busca automáticamente al abrir General. Las actualizaciones se instalan solo cuando eliges Actualizar ahora.',
+ check: 'Comprobar ahora',
+ checking: 'Comprobando...',
+ downloading: 'Descargando...',
+ installing: 'Instalando...',
+ updateAvailable: 'Actualización disponible',
+ upToDate: 'Tienes la versión más reciente',
+ checkFailed: 'No se pudo buscar actualizaciones',
+ downloadFailed: 'No se pudo descargar la actualización',
+ installFailed: 'No se pudo instalar la actualización',
+ installed: 'Actualización instalada. Reiniciando...',
+ newVersion: 'La versión {version} está disponible',
+ },
+ },
+ history: {
+ title: 'Historial',
+ subtitle: 'Consulta y administra tu historial de consultas',
+ recent: 'Consultas recientes',
+ recentDescription: 'Tus consultas ejecutadas recientemente',
+ empty: 'Aún no hay historial de consultas.',
+ search: 'Buscar consultas...',
+ filterAll: 'Todas',
+ filterSuccess: 'Éxito',
+ filterError: 'Error',
+ clearAll: 'Borrar todo',
+ clearNonFavorites: 'Borrar no favoritas',
+ clearAllConfirm: '¿Seguro que quieres borrar todas las entradas del historial?',
+ clearNonFavoritesConfirm: '¿Seguro que quieres borrar todas las entradas del historial que no son favoritas?',
+ columns: {
+ sql: 'SQL',
+ connection: 'Conexión',
+ database: 'Base de datos',
+ status: 'Estado',
+ time: 'Hora',
+ executionTime: 'Duración',
+ actions: 'Acciones',
+ },
+ status: {
+ success: 'Éxito',
+ error: 'Error',
+ },
+ actions: {
+ rerun: 'Ejecutar de nuevo en el editor',
+ favorite: 'Agregar a favoritas',
+ unfavorite: 'Quitar de favoritas',
+ delete: 'Eliminar',
+ },
+ notifications: {
+ cleared: 'Historial borrado',
+ deleted: 'Entrada eliminada',
+ rerun: 'Consulta cargada en el editor',
+ },
+ },
+ importExport: {
+ title: 'Importar / Exportar',
+ subtitle: 'Importa y exporta tus datos',
+ card: {
+ title: 'Importación / Exportación de datos',
+ description: 'Importa y exporta esquemas y datos de bases de datos',
+ comingSoon: 'La función de importación y exportación estará disponible en una actualización futura.',
+ },
+ },
+ queries: {
+ title: 'Consultas',
+ subtitle: 'Escribe y ejecuta consultas SQL',
+ selectConnection: 'Selecciona una conexión',
+ selectDatabase: 'Selecciona una base de datos',
+ noTab: 'No hay pestañas de consulta abiertas',
+ newTab: 'Nueva consulta',
+ landing: {
+ ready: 'Listo para escribir consultas',
+ connectedAs: 'Conectado como',
+ currentDatabase: 'Base de datos',
+ selectConnection: 'Selecciona una conexión',
+ tip: 'Consejo: haz doble clic en una tabla de la barra lateral para ver sus datos',
+ },
+ editor: {
+ title: 'Editor SQL',
+ description: 'Escribe aquí tus consultas SQL',
+ execute: 'Ejecutar',
+ explain: 'Explicar',
+ format: 'Formatear SQL',
+ },
+ shortcuts: {
+ execute: 'Ejecutar consulta ({key}Enter)',
+ explain: 'Explicar consulta (F6)',
+ format: 'Formatear SQL (Shift+Alt+F)',
+ save: 'Guardar ({key}S)',
+ saveAs: 'Guardar como archivo .sql',
+ comment: 'Alternar comentario ({key}/)',
+ },
+ status: {
+ connection: 'Conexión',
+ database: 'Base de datos',
+ rows: 'Filas',
+ time: 'Tiempo',
+ executing: 'Ejecutando...',
+ connectionLost: 'Se perdió la conexión. La conexión a la base de datos se cerró.',
+ reconnecting: 'Reconectando...',
+ },
+ notifications: {
+ querySaved: 'Consulta guardada',
+ saveFailed: 'No se pudo guardar',
+ loadFailed: 'No se pudo cargar la consulta',
+ noStatementFound: 'No se encontró ninguna sentencia SQL en la posición del cursor',
+ formatFailed: 'No se pudo formatear el SQL',
+ noActiveConnection: 'No hay conexión activa',
+ selectConnectionFirst: 'Selecciona una conexión y una base de datos antes de ejecutar una consulta',
+ tableActionSuccess: 'Tabla {table} {action} con éxito',
+ tableActionFailed: 'No se pudo {action} la tabla: {error}',
+ },
+ orphanDialog: {
+ title: 'Pestaña huérfana',
+ message: 'Esta pestaña pertenece a otra conexión y no puede ejecutar consultas. Aún puedes editar y guardar su contenido.',
+ acknowledge: 'Mantener como huérfana',
+ close: 'Cerrar pestaña',
+ },
+ executeOrphanDialog: {
+ title: 'Conexión cambiada',
+ message: 'La conexión original de esta pestaña de consulta cambió: {from} → {to}. ¿Revincular con la conexión activa actual y ejecutar?',
+ cancel: 'Cancelar',
+ close: 'Cerrar pestaña',
+ rebindAndExecute: 'Revincular y ejecutar',
+ },
+ explain: {
+ title: 'Plan EXPLAIN',
+ treeView: 'Árbol',
+ summaryView: 'Resumen',
+ rawView: 'Sin formato',
+ analyze: 'EXPLAIN ANALYZE',
+ running: 'Generando el plan de ejecución...',
+ empty: 'Sin datos del plan de ejecución',
+ nodeCount: '{count} nodos',
+ summary: {
+ totalCost: 'Costo total estimado: {cost}',
+ mostExpensive: 'Más costoso: {node}',
+ noCostData: 'Sin datos de costo',
+ },
+ node: {
+ rowEstimate: 'e:{rows}',
+ actualRows: 'a:{rows}',
+ discrepancyWarning: 'Las filas reales superan significativamente la estimación ({actual} vs. {estimated}, {ratio}x)',
+ },
+ error: {
+ parseFailed: 'No se pudo analizar el plan de ejecución',
+ noPlan: 'La base de datos no devolvió ningún plan de ejecución',
+ },
+ tabLabels: {
+ results: 'Resultados',
+ explain: 'Explicar',
+ },
+ analyzeToggle: 'Alternar el modo EXPLAIN ANALYZE (actualmente: {mode})',
+ columnHeaders: {
+ nodeType: 'Tipo de nodo',
+ relation: 'Relación',
+ index: 'Índice',
+ cost: 'Costo',
+ rows: 'Filas',
+ details: 'Detalles',
+ },
+ },
+ },
+ },
+ dataStudio: {
+ title: 'DATA STUDIO BETA',
+ subtitle: 'Análisis de datos SQL con IA',
+ inputPlaceholder: 'Haz una pregunta sobre tus datos...',
+ modelUnavailable: 'El modelo seleccionado no está disponible',
+ history: {
+ title: 'Historial',
+ newSession: 'Nueva sesión',
+ justNow: 'Justo ahora',
+ minutesAgo: 'hace {count} min',
+ hoursAgo: 'hace {count} h',
+ yesterday: 'Ayer',
+ noSessions: 'No hay sesiones anteriores',
+ messages: 'mensajes',
+ sources: 'fuentes',
+ delete: 'Eliminar sesión',
+ sessionFallback: 'Chat',
+ empty: 'Aún no hay sesiones',
+ },
+ agent: {
+ emptyState: 'Haz una pregunta o describe la consulta que quieres ejecutar.',
+ noSource: 'Adjunta una fuente de datos para comenzar.',
+ stop: 'Detener',
+ continue: 'Continuar',
+ continueHint: 'El agente se pausó. Haz clic en Continuar para reanudar o en Detener para finalizar la sesión.',
+ clearChat: 'Limpiar chat',
+ riskSafe: 'Operación segura',
+ riskElevated: 'Riesgo elevado',
+ riskDestructive: 'Operación destructiva',
+ allowOnce: 'Permitir una vez',
+ allowAlways: 'Permitir siempre',
+ deny: 'Denegar',
+ denyAlways: 'Denegar siempre',
+ cancelRun: 'Cancelar',
+ preparing: 'Preparando...',
+ thinking: 'Pensando',
+ iteration: 'Paso',
+ waitingModel: 'Esperando el modelo...',
+ compacting: 'Compactando el contexto...',
+ viewFullResult: 'Ver resultado completo',
+ viewMore: 'más',
+ message: {
+ toolBlocked: 'Bloqueado',
+ toolRejected: 'Rechazado',
+ blockedNotice: 'Bloqueado por permisos: acción no ejecutada',
+ historicalBlockedNotice: 'Intento anterior bloqueado: acción no ejecutada',
+ rejectedNotice: 'Rechazado por ti: acción no ejecutada',
+ interruptedNotice: 'Resultado de la ejecución no disponible',
+ unavailableNotice: 'Acción no disponible: acción no ejecutada',
+ connectionLabel: 'Conexión: {name}',
+ requiredAction: 'Requerido: {action}',
+ reviewPermissions: 'Revisar permisos',
+ reviewHelp: 'Guardar los cambios de permisos no ejecuta la acción bloqueada. Vuelve al chat y elige Reintentar solicitud cuando estés listo.',
+ reviewConnectionHelp: 'Los cambios se aplican solo a esta conexión. Los valores predeterminados del sistema no cambian. Guarda y vuelve al chat para reintentar la solicitud.',
+ connectionUnavailable: 'No se pudo identificar la conexión guardada. Vuelve a adjuntar la conexión en el chat antes de revisar sus permisos.',
+ backToChat: 'Volver al chat',
+ retryRequest: 'Reintentar solicitud',
+ retryPrompt: 'Reintenta la solicitud bloqueada o rechazada anteriormente usando {tool} con estos argumentos originales:\n{args}\nVerifica de nuevo los permisos actuales y solicita la aprobación necesaria. No repitas las acciones ya completadas.',
+ awaitingPermissionDecision: 'En pausa. Revisa la acción bloqueada y luego reintenta o envía una nueva solicitud.',
+ removeDenyRule: 'Quitar la regla de denegar siempre',
+ ruleRemoved: 'Regla eliminada. Reintenta la solicitud para verificar el acceso actual y los requisitos de confirmación.',
+ sourceUnavailable: 'La fuente original ya no está disponible en esta conversación. Adjúntala antes de reintentar.',
+ denialSource: {
+ system: 'Denegado por los valores predeterminados de IA del sistema.',
+ connection: 'Denegado por los permisos de IA de esta conexión.',
+ conversation: 'Denegado por las restricciones de fuentes de esta conversación.',
+ rule: 'Una regla de denegar siempre bloquea esta herramienta en esta conversación.',
+ unknown: 'Los permisos de IA bloquearon esta acción. Revisa el acceso antes de reintentar.',
+ },
+ toolDenied: 'Ejecución de herramienta denegada',
+ toolError: 'Falló la ejecución de la herramienta',
+ waitingForModel: 'Esperando el modelo',
+ compactionInProgress: 'Compactando conversación',
+ preparingInProgress: 'Preparando',
+ thinkingInProgress: 'Pensando…',
+ thinkingDone: 'Pensamiento completado',
+ thinkingDuration: '{s}s',
+ generating: 'Generando…',
+ awaitingConfirm: 'Esperando aprobación para {tool}…',
+ executingTool: 'Ejecutando {tool}…',
+ toolWrote: 'Escribió',
+ toolRead: 'Leyó',
+ toolExecuted: 'Ejecutó',
+ toolSearched: 'Buscó',
+ toolDeleted: 'Eliminó',
+ toolUpdated: 'Actualizó',
+ iterationLabel: 'Bucle {n}',
+ compactionLabel: 'Conversación compactada ({trigger})',
+ compactionSummary: 'Mostrar resumen',
+ compactionTrigger: {
+ auto: 'automática',
+ manual: 'manual',
+ },
+ },
+ },
+ contextIndicator: {
+ offBadgeTitle: 'La compactación automática está DESACTIVADA: el contexto no se reducirá automáticamente',
+ popoverTitle: 'Ventana de contexto',
+ warningText: 'La compactación automática está DESACTIVADA y el contexto supera el umbral. Compacta ahora o la próxima solicitud podría fallar.',
+ labelUsed: 'Usado',
+ labelCapacity: 'Capacidad',
+ labelWindow: 'Ventana',
+ labelReservedOut: 'Reservado para salida',
+ labelAutoCompactAt: 'Compactación automática en',
+ labelStatus: 'Estado',
+ compactNow: 'Compactar ahora',
+ compacting: 'Compactando…',
+ compactSuccess: 'Contexto compactado',
+ compactFailed: 'Error al compactar: {error}',
+ statusIdle: 'Inactivo',
+ statusOverThresholdOff: 'Sobre el umbral (compactación automática DESACTIVADA)',
+ statusAutoCompactOff: 'Compactación automática DESACTIVADA',
+ statusWillAutoCompact: 'Se compactará automáticamente',
+ statusHealthy: 'Saludable',
+ tooltipIdle: 'Uso del contexto',
+ tooltipAutoCompactOff: 'Compactación automática desactivada',
+ },
+ addSource: {
+ title: 'Agregar fuente de datos',
+ selectConnection: 'Seleccionar conexión',
+ searchPlaceholder: 'Buscar conexiones...',
+ noConnections: 'No se encontraron conexiones compatibles',
+ allAttached: 'Todas las conexiones compatibles ya están adjuntadas',
+ connectionsFound: 'Se encontraron {count} conexiones',
+ connectSource: 'Conectar',
+ },
+ modifySource: {
+ title: 'Modificar fuente de datos',
+ accessPermissions: 'Permisos de acceso',
+ inheritTitle: 'Usar permisos de la conexión',
+ saveChanges: 'Guardar cambios',
+ modeDefault: 'Preguntar',
+ modeFull: 'Automático',
+ },
+ detachSource: {
+ title: 'Desadjuntar fuente',
+ message: '¿Seguro que quieres desadjuntar esta fuente de datos? Se quitará la conexión de Data Studio.',
+ confirm: 'Desadjuntar',
+ },
+ },
+ components: {
+ serverForm: {
+ basicTab: 'Básico',
+ advancedTab: 'Avanzado',
+ title: {
+ edit: 'Editar conexión',
+ new: 'Nueva conexión',
+ },
+ description: {
+ edit: 'Actualiza la configuración de tu conexión de base de datos.',
+ new: 'Configura una nueva conexión de base de datos.',
+ },
+ labels: {
+ connectionName: 'Nombre de la conexión',
+ databaseType: 'Tipo de base de datos',
+ host: 'Host',
+ databaseFilePath: 'Ruta del archivo de base de datos',
+ encryptionKey: 'Clave de cifrado',
+ port: 'Puerto',
+ database: 'Base de datos',
+ username: 'Usuario',
+ password: 'Contraseña',
+ ssl: 'Usar cifrado SSL/TLS',
+ sqliteMode: 'Modo SQLite',
+ recentDatabases: 'Bases de datos recientes',
+ },
+ placeholders: {
+ connectionName: 'Mi base de datos',
+ selectType: 'Selecciona el tipo de base de datos',
+ host: 'localhost',
+ filePath: '/path/to/database.db',
+ duckdbFilePath: '/path/to/database.duckdb or :memory:',
+ encryptionKey: 'Introduce la frase de contraseña de cifrado',
+ database: 'database_name',
+ username: 'username',
+ password: '••••••••',
+ },
+ databaseTypes: {
+ 'postgresql': 'PostgreSQL',
+ 'sqlserver': 'SQL Server',
+ 'mysql': 'MySQL',
+ 'mariadb': 'MariaDB',
+ 'sqlite': 'SQLite',
+ 'sqlcipher': 'SQLCipher',
+ 'duckdb': 'DuckDB',
+ 'clickhouse': 'ClickHouse',
+ 'cockroachdb': 'CockroachDB',
+ 'redshift': 'Amazon Redshift',
+ 'yugabytedb': 'YugabyteDB',
+ 'timescaledb': 'TimescaleDB',
+ 'kingbasees': '人大金仓 (KingbaseES)',
+ 'gaussdb': '华为 GaussDB',
+ 'highgo': '瀚高数据库 (HighGo DB)',
+ 'uxdb': '优炫数据库 (UXDB)',
+ 'opengauss': 'openGauss',
+ 'gbase8c': '南大通用 GBase 8c',
+ 'questdb': 'QuestDB',
+ 'vastbase': 'Vastbase (海量数据库)',
+ 'yashandb': 'YashanDB (崖山数据库)',
+ 'tidb': 'TiDB',
+ 'oceanbase': 'OceanBase',
+ 'oceanbase-oracle': 'OceanBase Oracle',
+ 'tdsql': 'TDSQL',
+ 'polardb': 'PolarDB',
+ 'dameng': '达梦 Dameng',
+ 'doris': 'Apache Doris',
+ 'selectdb': 'SelectDB',
+ 'starrocks': 'StarRocks',
+ 'databend': 'Databend',
+ 'goldendb': 'GoldenDB',
+ 'manticore': 'Manticore Search',
+ 'oracle': 'Oracle',
+ 'db2': 'IBM Db2',
+ 'h2': 'H2',
+ 'snowflake': 'Snowflake',
+ 'xugudb': '虚谷数据库 (XuguDB)',
+ 'gbase8a': '南大通用 GBase 8a',
+ 'trino': 'Trino',
+ 'presto': 'Presto',
+ 'derby': 'Apache Derby',
+ 'hive': 'Apache Hive',
+ 'databricks': 'Databricks SQL',
+ 'hana': 'SAP HANA',
+ 'teradata': 'Teradata',
+ 'vertica': 'Vertica',
+ 'exasol': 'Exasol',
+ 'bigquery': 'Google BigQuery',
+ 'informix': 'IBM Informix',
+ 'kylin': 'Apache Kylin',
+ 'cassandra': 'Apache Cassandra',
+ 'iris': 'InterSystems IRIS',
+ 'access': 'Microsoft Access',
+ 'firebird': 'Firebird',
+ 'rqlite': 'RQLite',
+ 'turso': 'Turso (libSQL)',
+ 'tdengine': 'TDengine',
+ },
+ oracle: {
+ connectionMethod: 'Método de conexión',
+ methods: {
+ basic: 'Básico (Host:Puerto)',
+ tns: 'TNS (tnsnames.ora)',
+ cloudWallet: 'Cloud Wallet (ATP/ADW)',
+ },
+ identifyBy: 'Identificar por',
+ sid: 'SID',
+ serviceName: 'Nombre del servicio',
+ role: 'Rol',
+ roles: {
+ normal: 'NORMAL',
+ sysdba: 'SYSDBA',
+ sysoper: 'SYSOPER',
+ },
+ tnsAdminDir: 'Directorio TNS_ADMIN',
+ tnsAlias: 'Alias de TNS',
+ walletDir: 'Directorio del wallet',
+ walletPassword: 'Contraseña del wallet',
+ serviceLevel: 'Nivel de servicio',
+ serviceLevels: {
+ low: 'Bajo (lote)',
+ medium: 'Medio (estándar)',
+ high: 'Alto (crítico)',
+ tp: 'TP (transacción)',
+ tpurgent: 'TP_URGENT (prioridad)',
+ },
+ browse: 'Examinar...',
+ noAliases: 'No se encontraron alias de TNS',
+ tnsSelectDir: 'Selecciona un directorio TNS para cargar los alias',
+ walletSelectDir: 'Selecciona un directorio de wallet para cargar los alias',
+ loadingAliases: 'Cargando alias...',
+ },
+ buttons: {
+ create: 'Nuevo...',
+ open: 'Abrir...',
+ },
+ fileStatus: {
+ willCreate: 'El archivo aún no existe: {engine} lo crea al conectarte.',
+ missingParent: 'La carpeta contenedora aún no existe.',
+ createDirectory: 'Crear carpeta',
+ createDirectoryFailed: 'No se pudo crear la carpeta',
+ unwritable: 'Sin permiso de escritura en esta ruta.',
+ directory: 'Esta ruta es una carpeta. Elige un archivo de base de datos.',
+ empty: 'El archivo está vacío (0 bytes).',
+ ready: 'El archivo existe ({size})',
+ storageVersion: 'Formato de almacenamiento {storage} (se abre con DuckDB {version} o superior)',
+ storageVersionUnknown: 'Formato de almacenamiento {storage}: más reciente de lo que esta versión conoce; probablemente fue escrito por un DuckDB más nuevo.',
+ writeAheadLog: 'Hay un registro de escritura anticipada (.wal); se reproduce al conectar.',
+ unsupportedPath: 'DuckDB no puede abrir una ruta que contenga \';\'. Renombra el archivo e inténtalo de nuevo.',
+ wrongFormat: 'Parece un archivo {format}, no una base de datos {engine}.',
+ unknownFormat: 'otro',
+ reveal: 'Mostrar en la carpeta',
+ revealFailed: 'No se pudo mostrar el archivo',
+ removeRecent: 'Quitar de la lista de recientes',
+ },
+ duckdb: {
+ accessMode: 'Modo de acceso',
+ readWrite: 'Lectura y escritura',
+ readWriteHint: 'DuckDB mantiene un bloqueo exclusivo del archivo: solo un proceso puede escribir en él.',
+ readOnly: 'Solo lectura',
+ readOnlyHint: 'Permite que otros procesos de DuckDB lean el mismo archivo al mismo tiempo.',
+ conflictingConnection: '"{name}" ya abre este archivo con otro modo de acceso, y DuckDB rechaza una segunda conexión con una configuración diferente.',
+ openReadOnly: 'Abrir en solo lectura',
+ switchToConnection: 'Cambiar a esa conexión',
+ sharedConnection: '"{name}" usa el mismo archivo y la misma configuración; ambas conexiones comparten una instancia de DuckDB.',
+ engineVersion: 'Versión del motor {version}',
+ retryReadOnly: 'Reintentar en solo lectura',
+ retryReadWrite: 'Reintentar en lectura y escritura',
+ inMemoryHint: 'Las bases de datos en memoria son temporales y se pierden al cerrar la conexión. Útil para explorar datos antes de guardarlos en un archivo.',
+ inMemoryInstance: 'Instancia',
+ inMemorySharedHint: 'La instancia en memoria con nombre la comparten todas las conexiones del pool, por lo que las tablas creadas en una consulta siguen visibles en la siguiente.',
+ },
+ duckdbFailures: {
+ 'read-only-unsupported': 'El puente JDBC instalado aún no puede abrir una base de datos en solo lectura (DuckDB rechaza los cambios de modo por conexión). Reintenta en modo de lectura y escritura, o actualiza el puente en Configuración.',
+ 'storage-version': 'Este archivo fue escrito por un DuckDB más reciente que el motor en uso, por lo que no se puede abrir. Expórtalo con la versión más reciente (EXPORT DATABASE) e impórtalo de nuevo, o actualiza el controlador de DuckDB.',
+ 'config-conflict': 'Otra conexión ya abrió este archivo con una configuración diferente (solo lectura vs. lectura y escritura, o inicialización distinta). DuckDB rechaza la segunda configuración.',
+ 'lock-conflict': 'Otro proceso mantiene el bloqueo de escritura de este archivo (CLI de duckdb, Python u otra conexión de SQLKit). Ábrelo en solo lectura o cierra el otro programa.',
+ 'unsupported-url': 'Esta ruta no se puede pasar al controlador JDBC de DuckDB. Renombra el archivo e inténtalo de nuevo.',
+ 'extension': 'No se pudo cargar ni descargar una extensión de DuckDB. Revisa la conexión de red o instala la extensión de antemano.',
+ 'read-only-file': 'El archivo de base de datos o su carpeta es de solo lectura, por lo que DuckDB no puede escribir en él. Cambia los permisos del archivo o ábrelo en solo lectura.',
+ 'missing-file': 'El archivo de base de datos no existe y no se pudo crear. Revisa la ruta y los permisos de la carpeta.',
+ },
+ sqlite: {
+ modes: {
+ file: 'Archivo',
+ inMemory: 'En memoria',
+ },
+ recentEmpty: 'No hay bases de datos recientes',
+ ago: 'hace {time}',
+ inMemoryHint: 'Las bases de datos en memoria son temporales y se perderán al cerrar la conexión. Útil para pruebas y datos temporales.',
+ pathStatus: {
+ valid: 'El archivo existe',
+ notFound: 'Archivo no encontrado',
+ noPermission: 'Sin permiso de escritura',
+ },
+ },
+ errors: {
+ nameRequired: 'El nombre de la conexión es obligatorio',
+ hostRequired: 'El host es obligatorio',
+ databaseRequired: 'SID / Nombre del servicio es obligatorio',
+ databaseNameRequired: 'El nombre de la base de datos es obligatorio',
+ filePathRequired: 'La ruta del archivo de base de datos es obligatoria',
+ portInvalid: 'El puerto debe ser un número positivo',
+ filePickerFailed: 'No se pudo abrir el selector de archivos',
+ tnsAdminDirRequired: 'El directorio de administración TNS es obligatorio',
+ tnsAliasRequired: 'El alias de TNS es obligatorio',
+ },
+ ssh: {
+ newProfile: 'Nuevo perfil',
+ hopOrderHint: 'Los saltos se prueban en orden: el último salto reenvía a la base de datos. El proxy del sistema se aplica solo al primer salto.',
+ importFromConfig: 'Importar de ~/.ssh/config',
+ profileName: 'Nombre del perfil',
+ profileNamePlaceholder: 'p. ej., bastión de producción',
+ editProfile: 'Editar perfil SSH',
+ useSshTunnel: 'Túnel SSH',
+ ultimateOnly: 'El túnel SSH es una función de Ultimate',
+ tunnelSkippedHint: 'El túnel SSH es una función de Ultimate: las sesiones Community o sin sesión iniciada omiten el túnel guardado en esta conexión, por lo que esta prueba se realizó contra una conexión directa.',
+ systemProxy: 'Proxy del sistema',
+ systemProxyDetected: 'Proxy del sistema detectado: {url}',
+ systemProxyAdd: 'Agregar',
+ systemProxyDetach: 'Desvincular proxy del sistema',
+ systemProxyNotDetected: 'El proxy del sistema está habilitado pero no se detectó ninguno. Conectando directamente.',
+ detachAction: 'Quitar de la cadena',
+ moveUp: 'Subir salto',
+ moveDown: 'Bajar salto',
+ hops: 'salto | saltos',
+ addProfilePlaceholder: 'Agregar perfil…',
+ searchProfilePlaceholder: 'Buscar perfiles…',
+ testChain: 'Probar conectividad del túnel',
+ testFirstHop: 'Probar el primer salto (los saltos posteriores no se prueban)',
+ testDisabledHint: 'Faltan campos obligatorios o la configuración no es válida',
+ testReturnedNotConnected: 'La conexión devolvió no conectado',
+ jreBroken: 'El JRE falta o está dañado',
+ stepFailed: 'Falló',
+ testTimedOut: 'La prueba excedió el tiempo de espera (30 s): puede que el bastión no sea accesible o que el protocolo de enlace SSH se colgara',
+ testSuccess: 'Conectado a {user}{\'@\'}{host}:{port}',
+ notConfigured: 'Túnel SSH sin configurar: agrega un perfil para empezar',
+ editTunnel: 'Editar túnel SSH',
+ connectionOnly: 'Los cambios se aplican solo a esta conexión.',
+ convertHint: 'Conviértelo en un perfil reutilizable para agregar y reordenar saltos.',
+ noConfigHosts: 'No se encontraron hosts SSH en ~/.ssh/config.',
+ convertToProfile: 'Convertir en perfil',
+ convertedProfileName: 'Manual ({host})',
+ sshHost: 'Host SSH',
+ sshPort: 'Puerto SSH',
+ username: 'Usuario',
+ authMethod: 'Método de autenticación',
+ password: 'Contraseña',
+ privateKey: 'Clave privada',
+ sshAgent: 'Agente SSH',
+ sshPassword: 'Contraseña SSH',
+ privateKeyPath: 'Ruta de la clave privada',
+ passphraseOptional: 'Frase de contraseña (opcional)',
+ agentSockPath: 'Ruta del socket del agente',
+ agentHelpText: 'Usa el agente SSH del sistema; no se necesita configuración adicional.',
+ },
+ },
+ serverCard: {
+ actions: {
+ connect: 'Conectar',
+ openEditor: 'Abrir en el editor',
+ closeConnection: 'Cerrar conexión',
+ edit: 'Editar',
+ duplicate: 'Duplicar',
+ delete: 'Eliminar',
+ },
+ strategy: {
+ nativeTooltip: 'Conexión directa mediante controlador Rust nativo: el mejor rendimiento, sin dependencias externas',
+ jdbcBridgeTooltip: 'Conecta mediante controlador JDBC a través de un Java runtime integrado: la mayor compatibilidad de bases de datos',
+ httpBridgeTooltip: 'Conecta mediante el protocolo SQL sobre HTTP: para bases de datos basadas en REST',
+ },
+ },
+ connectingModal: {
+ connecting: 'Conectando a {name}...',
+ connectingSubtext: 'Espera mientras se establece la conexión',
+ connectionError: 'Error de conexión',
+ sshTunnelSkipped: 'El túnel SSH es una función de Ultimate: las sesiones Community o sin sesión iniciada omiten el túnel guardado en esta conexión y conectan directamente (la configuración se conserva).',
+ sshTunnelStripped: 'El túnel guardado en esta conexión se omitió para este intento (es una función de Ultimate y estás en Community o sin sesión iniciada). Si la base de datos solo es accesible a través de ese túnel, actualiza a Ultimate.',
+ },
+ databaseBrowser: {
+ title: 'Explorador de bases de datos',
+ search: 'Buscar tablas...',
+ refresh: 'Actualizar',
+ newQuery: 'Nueva consulta',
+ loading: 'Cargando...',
+ empty: 'No se encontraron bases de datos. Conéctate primero a un servidor.',
+ selectDatabase: 'Seleccionar base de datos',
+ selectSchema: 'Seleccionar esquema',
+ databases: 'Bases de datos',
+ current: 'Actual',
+ userDatabases: 'Bases de datos de usuario',
+ systemDatabases: 'Bases de datos del sistema',
+ noTables: 'No se encontraron tablas',
+ noViews: 'No se encontraron vistas',
+ noProcedures: 'No se encontraron procedimientos',
+ noFunctions: 'No se encontraron funciones',
+ noSavedQueries: 'Aún no hay consultas guardadas',
+ comingSoon: 'Próximamente',
+ sections: {
+ tables: 'Tablas',
+ views: 'Vistas',
+ procedures: 'Procedimientos',
+ functions: 'Funciones',
+ savedQueries: 'Consultas guardadas',
+ },
+ errors: {
+ fetchDatabases: 'No se pudieron obtener las bases de datos',
+ fetchSchemas: 'No se pudieron obtener los esquemas',
+ fetchTables: 'No se pudieron obtener las tablas',
+ invalidResponse: 'Respuesta inválida del servidor',
+ },
+ contextMenu: {
+ viewData: 'Ver datos',
+ selectTopN: 'Seleccionar los primeros 100',
+ viewStructure: 'Ver estructura',
+ createScript: 'Script CREATE',
+ exportData: 'Exportar datos',
+ showErDiagram: 'Mostrar diagrama ER',
+ dropTable: 'Eliminar tabla',
+ truncateTable: 'Truncar',
+ newQuery: 'Nueva consulta',
+ refresh: 'Actualizar',
+ },
+ savedQueryActions: {
+ open: 'Abrir',
+ delete: 'Eliminar',
+ reveal: 'Mostrar en Finder',
+ },
+ erDiagram: {
+ title: 'Diagrama ER',
+ viewMode: 'Ver',
+ zoom: '{percentage}%',
+ zoomIn: 'Acercar',
+ zoomOut: 'Alejar',
+ allSchemas: 'Todos los esquemas',
+ engineeringView: 'Vista de ingeniería',
+ fitToScreen: 'Ajustar a la pantalla',
+ searchPlaceholder: 'Filtrar tablas...',
+ tablesCountBadge: '{count} tablas',
+ tableView: 'Vista de tabla',
+ relationshipsCountBadge: '{count} relaciones',
+ resetLayout: 'Restablecer diseño',
+ largeSchemaWarning: 'Este esquema tiene {count} tablas. Mostrar todas puede ser muy denso. ¿Continuar?',
+ showAllColumns: 'Mostrar todas las columnas ({count})',
+ hideExtraColumns: 'Mostrar menos',
+ noForeignKeys: 'No se encontraron relaciones de clave foránea',
+ openTable: 'Abrir datos de la tabla',
+ layoutDirection: 'Disposición',
+ layoutTopBottom: 'Arriba → Abajo',
+ layoutLeftRight: 'Izquierda → Derecha',
+ loading: 'Cargando relaciones del esquema...',
+ },
+ },
+ listingTab: {
+ views: 'Vistas',
+ procedures: 'Procedimientos',
+ functions: 'Funciones',
+ searchPlaceholder: 'Buscar por nombre...',
+ name: 'Nombre',
+ detail: 'Detalle',
+ ddl: 'DDL',
+ actions: 'Acciones',
+ viewDdl: 'Ver DDL',
+ drop: 'Eliminar',
+ rename: 'Renombrar',
+ copyName: 'Copiar nombre',
+ copyDdl: 'Copiar DDL',
+ dropDialogTitle: 'Eliminar objeto',
+ dropDialogDescription: '¿Seguro que quieres eliminar {name}?',
+ confirmDrop: 'Eliminar',
+ renameDialogTitle: 'Renombrar objeto',
+ renameDialogDescription: 'Introduce un nuevo nombre para {name}:',
+ newNamePlaceholder: 'Nuevo nombre',
+ confirmRename: 'Renombrar',
+ noResults: 'Ningún objeto coincide con tu búsqueda',
+ empty: 'No se encontraron objetos',
+ },
+ schemaTab: {
+ column: 'Columna',
+ type: 'Tipo',
+ nullable: 'Admite nulos',
+ default: 'Predeterminado',
+ key: 'Clave',
+ autoIncrement: 'Autoincremental',
+ yes: 'SÍ',
+ no: 'NO',
+ pk: 'PK',
+ },
+ indexesTab: {
+ name: 'Nombre',
+ columns: 'Columnas',
+ type: 'Tipo',
+ unique: 'Único',
+ primary: 'Primario',
+ empty: 'No se encontraron índices',
+ yes: 'SÍ',
+ no: 'NO',
+ },
+ foreignKeysTab: {
+ constraint: 'Restricción',
+ columns: 'Columnas',
+ references: 'Referencias',
+ onUpdate: 'ON UPDATE',
+ onDelete: 'ON DELETE',
+ empty: 'No se encontraron claves foráneas',
+ },
+ triggersTab: {
+ name: 'Nombre',
+ timing: 'Momento',
+ event: 'Evento',
+ ddl: 'DDL',
+ viewDdl: 'Ver DDL',
+ empty: 'No se encontraron disparadores',
+ },
+ queryResult: {
+ title: 'Resultados',
+ selectResult: 'Seleccionar conjunto de resultados',
+ resultSet: 'Resultado {index} de {count}',
+ exportActions: 'Copiar y exportar el resultado',
+ scriptReadOnly: 'Los resultados de script son de solo lectura; la ordenación se aplica a las filas devueltas.',
+ rows: '{count} filas',
+ rowsAffected: '{count} fila(s) afectada(s)',
+ time: '{time}',
+ close: 'Cerrar',
+ executing: 'Ejecutando consulta...',
+ error: 'Error de consulta',
+ success: 'Consulta ejecutada con éxito',
+ noData: 'No se devolvieron datos',
+ commandCompleted: 'Comando completado',
+ noResults: 'Ejecuta una consulta para ver resultados',
+ },
+ dataTableView: {
+ searchPlaceholder: 'Buscar en todas las columnas...',
+ clearSearch: 'Limpiar búsqueda',
+ filterPlaceholder: 'Filtro (cláusula WHERE de SQL, p. ej. age > 18 AND status = \'active\')',
+ clearFilter: 'Limpiar filtro',
+ refresh: 'Actualizar',
+ columns: 'Columnas',
+ exportCsv: 'Exportar página actual (CSV)',
+ applyFilters: 'Aplicar filtros',
+ loading: 'Cargando datos de la tabla...',
+ error: 'No se pudieron cargar los datos de la tabla',
+ connectionLost: 'Se perdió la conexión. La conexión a la base de datos se cerró.',
+ reconnecting: 'Reconectando...',
+ reconnect: 'Reconectar',
+ noRows: 'No se encontraron filas',
+ rows: 'filas',
+ columnsCount: '{count} columnas',
+ indexesCount: '{count} índices',
+ foreignKeysCount: '{count} claves foráneas',
+ triggersCount: '{count} disparadores',
+ page: 'Página {page} de {total}',
+ rowsPerPage: 'Filas por página:',
+ actions: 'Acciones',
+ editRow: 'Editar fila',
+ deleteRow: 'Eliminar fila',
+ notifications: {
+ csvExported: 'CSV exportado',
+ exportFailed: 'No se pudo exportar',
+ rowDeleted: 'Fila eliminada',
+ deleteFailed: 'No se pudo eliminar la fila',
+ rowUpdated: 'Fila actualizada',
+ updateFailed: 'No se pudo actualizar la fila',
+ noPrimaryKey: 'No se detectó clave primaria',
+ noPrimaryKeyDesc: 'Esta tabla no tiene clave primaria. La fila se identificará por todas las columnas.',
+ fallbackAllColumns: 'Sin clave primaria: se usan todas las columnas para identificar la fila. Edita con precaución.',
+ },
+ deleteDialog: {
+ title: 'Eliminar fila',
+ message: '¿Seguro que quieres eliminar esta fila? Esta acción no se puede deshacer.',
+ confirm: 'Eliminar',
+ },
+ editDialog: {
+ title: 'Editar fila',
+ },
+ validation: {
+ required: 'Este campo es obligatorio',
+ invalidNumber: 'Introduce un número válido',
+ invalidBoolean: 'Introduce true o false',
+ },
+ },
+ queryTabs: {
+ unsaved: 'Cambios sin guardar',
+ orphan: 'Esta pestaña pertenece a otra conexión',
+ new: 'Nueva consulta',
+ closeDialog: {
+ title: 'Cambios sin guardar',
+ message: 'La consulta "{name}" tiene cambios sin guardar. ¿Quieres descartarlos?',
+ discard: 'Descartar',
+ },
+ },
+ header: {
+ appName: 'SQLKit',
+ },
+ sqlEditor: {
+ execute: 'Ejecutar',
+ format: 'Formatear',
+ copy: 'Copiar',
+ },
+ destructiveDialog: {
+ deleteRow: {
+ title: 'Confirmar eliminación',
+ message: '¿Eliminar {count} fila(s) de la tabla "{table}"?',
+ detail: 'Esta acción no se puede deshacer.',
+ confirm: 'Eliminar',
+ },
+ dropTable: {
+ title: 'Eliminar tabla',
+ message: '¿Eliminar la tabla "{table}"?',
+ detail: 'Esto eliminará permanentemente la tabla y todos sus datos. Esta acción no se puede deshacer.',
+ confirm: 'Eliminar',
+ },
+ truncateTable: {
+ title: 'Truncar tabla',
+ message: '¿Truncar la tabla "{table}"?',
+ detail: 'Esto eliminará todas las {count} filas. Esta acción no se puede deshacer.',
+ confirm: 'Truncar',
+ },
+ deleteConnection: {
+ title: 'Eliminar conexión',
+ message: '¿Eliminar la conexión "{name}"?',
+ detail: 'Esto quitará la configuración de conexión guardada. Las conexiones activas se desconectarán.',
+ confirm: 'Eliminar',
+ },
+ deleteProfile: {
+ title: 'Eliminar perfil SSH',
+ message: '¿Eliminar el perfil "{name}"?',
+ detail: 'El perfil se quita de la biblioteca de perfiles compartida. Las conexiones que saltan a través de él perderán este bastión.',
+ inUse: 'Lo usan {count} conexión(es): {names}. Esas conexiones se desvincularán de este perfil.',
+ confirm: 'Eliminar',
+ },
+ },
+ pagination: {
+ label: 'Paginación',
+ showingWithoutTotal: 'Mostrando filas {start}–{end} · total no disponible',
+ rowsPerPage: 'Filas por página',
+ pageSize: '{count} filas/página',
+ customSize: 'Filas/página personalizadas',
+ apply: 'Aplicar',
+ showAll: 'Mostrar todas las filas devueltas',
+ allRows: 'Todas las filas devueltas',
+ firstPage: 'Primera página',
+ previousPage: 'Página anterior',
+ nextPage: 'Página siguiente',
+ lastPage: 'Última página',
+ goToPage: 'Ir a la página',
+ pageCount: 'de {count}',
+ sortScope: 'La ordenación se aplica a la página actual',
+ },
+ dataGrid: {
+ sort: {
+ asc: 'Ordenar ascendentemente',
+ desc: 'Ordenar descendentemente',
+ clear: 'Quitar orden',
+ unsortable: 'Este tipo de columna no se puede ordenar',
+ },
+ filter: {
+ byValue: 'Filtrar por valor',
+ byLike: 'Filtrar por LIKE',
+ greaterThan: 'Filtrar >=',
+ lessThan: 'Filtrar <=',
+ between: 'Filtrar entre',
+ excludeValue: 'Excluir valor',
+ clearFilter: 'Limpiar filtro',
+ clearAll: 'Limpiar todos los filtros',
+ activeFilters: 'Filtros',
+ },
+ row: {
+ edit: 'Editar fila',
+ delete: 'Eliminar fila',
+ duplicate: 'Duplicar fila',
+ details: 'Detalles de la fila',
+ copyAsCsv: 'Copiar fila como CSV',
+ copyAsJson: 'Copiar fila como JSON',
+ copyAsInsert: 'Copiar fila como INSERT',
+ actions: 'Acciones',
+ noTableContext: 'El resultado de la consulta no está vinculado a una tabla, por lo que no se pueden editar ni eliminar filas',
+ editUnsupported: {
+ 'not-select': 'Esta sentencia no es una consulta SELECT; las filas del resultado no se pueden editar ni eliminar',
+ 'cte': 'La consulta usa WITH (CTE); las filas no se pueden mapear a una tabla, por lo que la edición no es compatible',
+ 'set-operation': 'La consulta usa UNION/INTERSECT/EXCEPT; las filas provienen de varias sentencias, por lo que la edición no es compatible',
+ 'aggregation': 'La consulta está agregada (GROUP BY/DISTINCT/funciones de agregación); las filas no se pueden mapear a filas base, por lo que la edición no es compatible',
+ 'multiple-sources': 'La consulta une varias tablas; las filas no se pueden editar ni eliminar',
+ 'no-table': 'La consulta no tiene tabla FROM; las filas no se pueden editar ni eliminar',
+ 'complex-source': 'El origen de la consulta es una subconsulta o una expresión compleja; las filas no se pueden editar ni eliminar',
+ },
+ },
+ cell: {
+ copyValue: 'Copiar valor de la celda',
+ copyRow: 'Copiar fila',
+ filterByValue: 'Filtrar por este valor',
+ excludeValue: 'Excluir este valor',
+ },
+ selection: {
+ selected: '{count} fila(s) seleccionada(s)',
+ editSelected: 'Editar selección',
+ deleteSelected: 'Eliminar selección',
+ exportSelected: 'Exportar selección',
+ },
+ status: {
+ showing: 'Mostrando {start}–{end} de {total} filas',
+ showingLimited: 'Mostrando {start}–{end} de {loaded} filas (limitado)',
+ time: '· {time}',
+ },
+ empty: 'Sin resultados',
+ error: {
+ title: 'Error al cargar los datos',
+ retry: 'Reintentar',
+ },
+ loading: 'Cargando datos...',
+ edit: {
+ title: 'Editar fila',
+ duplicateTitle: 'Duplicar fila',
+ nullToggle: 'Establecer NULL',
+ pkReadonly: 'Clave primaria (solo lectura)',
+ save: 'Guardar',
+ cancel: 'Cancelar',
+ saving: 'Guardando...',
+ confirmCancel: '¿Descartar cambios?',
+ confirmCancelMessage: 'Tienes cambios sin guardar. ¿Seguro que quieres cerrar?',
+ discard: 'Descartar',
+ validation: {
+ required: 'Este campo es obligatorio',
+ invalidNumber: 'Introduce un número válido',
+ invalidBoolean: 'Introduce true o false',
+ },
+ },
+ details: {
+ title: 'Detalles de la fila',
+ },
+ delete: {
+ title: 'Eliminar fila',
+ message: '¿Seguro que quieres eliminar esta fila?',
+ detail: 'Esta acción no se puede deshacer.',
+ confirm: 'Eliminar',
+ batchTitle: 'Eliminar filas seleccionadas',
+ batchMessage: '¿Seguro que quieres eliminar {count} fila(s) seleccionada(s)?',
+ batchDetail: 'Esta acción no se puede deshacer.',
+ },
+ export: {
+ copyAllCsv: 'Copiar todo como CSV',
+ copyAllJson: 'Copiar todo como JSON',
+ copyAllInsert: 'Copiar todo como INSERT',
+ exportCsv: 'Exportar CSV',
+ exportJson: 'Exportar JSON',
+ exportInsert: 'Exportar INSERT',
+ copied: 'Copiado al portapapeles',
+ exported: 'Archivo exportado',
+ formatLabels: {
+ csv: 'CSV',
+ json: 'JSON',
+ insert: 'INSERT',
+ },
+ },
+ json: {
+ expand: 'Expandir',
+ title: 'Visor JSON',
+ copy: 'Copiar JSON',
+ },
+ blob: {
+ label: '[BLOB {size}]',
+ },
+ null: '(NULL)',
+ rowNumber: '#',
+ },
+ },
+ updater: {
+ updateAvailable: 'Actualización disponible',
+ newVersion: 'La versión {version} está disponible',
+ upToDate: 'Tienes la versión más reciente',
+ checkFailed: 'No se pudo buscar actualizaciones',
+ downloading: 'Descargando actualización...',
+ installing: 'Instalando actualización...',
+ installFailed: 'No se pudo instalar la actualización',
+ skip: 'Omitir esta versión',
+ later: 'Más tarde',
+ updateNow: 'Actualizar ahora',
+ restarting: 'Reiniciando...',
+ downloadingPercent: 'Descargando {percent}%',
+ relaunchFailed: 'No se pudo reiniciar después de la actualización',
+ retry: 'Reintentar',
+ installFailedHelp: 'Pulsa F12 para abrir las herramientas de desarrollo y ver los detalles del error.',
+ },
+ errors: {
+ unexpected: 'Error inesperado: {error}',
+ codes: {
+ // Connection errors
+ CONNECTION_FAILED: 'No se pudo conectar a la base de datos',
+ CONNECTION_TIMEOUT: 'Tiempo de espera de conexión agotado',
+ CONNECTION_REFUSED: 'Conexión rechazada',
+ AUTHENTICATION_FAILED: 'Error de autenticación',
+
+ // Query errors
+ QUERY_SYNTAX_ERROR: 'Error de sintaxis SQL',
+ QUERY_EXECUTION_ERROR: 'Falló la ejecución de la consulta',
+ QUERY_TIMEOUT: 'Tiempo de espera de ejecución de la consulta agotado',
+
+ // Resource errors
+ DATABASE_NOT_FOUND: 'Base de datos no encontrada',
+ TABLE_NOT_FOUND: 'La tabla no existe',
+ COLUMN_NOT_FOUND: 'La columna no existe',
+
+ // Permission errors
+ PERMISSION_DENIED: 'Permiso denegado',
+ INSUFFICIENT_PRIVILEGES: 'Privilegios insuficientes',
+
+ // Data errors
+ CONSTRAINT_VIOLATION: 'Violación de restricción',
+ FOREIGN_KEY_VIOLATION: 'Se violó la restricción de clave foránea',
+ UNIQUE_VIOLATION: 'Se violó la restricción de unicidad',
+ NOT_NULL_VIOLATION: 'Se violó la restricción NOT NULL',
+ CHECK_VIOLATION: 'Se violó la restricción CHECK',
+
+ // System errors
+ INTERNAL_ERROR: 'Error interno',
+ UNSUPPORTED_OPERATION: 'Operación no compatible',
+ INVALID_CONFIGURATION: 'Configuración no válida',
+ },
+ titles: {
+ CONNECTION_FAILED: 'Error de conexión',
+ AUTHENTICATION_FAILED: 'Error de autenticación',
+ QUERY_SYNTAX_ERROR: 'Error de sintaxis SQL',
+ QUERY_EXECUTION_ERROR: 'Error de ejecución de la consulta',
+ TABLE_NOT_FOUND: 'Tabla no encontrada',
+ COLUMN_NOT_FOUND: 'Columna no encontrada',
+ PERMISSION_DENIED: 'Permiso denegado',
+ FOREIGN_KEY_VIOLATION: 'Restricción de clave foránea violada',
+ UNIQUE_VIOLATION: 'Restricción de unicidad violada',
+ NOT_NULL_VIOLATION: 'Restricción NOT NULL violada',
+ },
+ hints: {
+ CONNECTION_FAILED: 'Revisa tu configuración de conexión y asegúrate de que el servidor de base de datos esté en ejecución',
+ AUTHENTICATION_FAILED: 'Verifica tu usuario y contraseña',
+ QUERY_SYNTAX_ERROR: 'Revisa tu sintaxis SQL e inténtalo de nuevo',
+ QUERY_TIMEOUT: 'Intenta optimizar tu consulta o aumentar el límite de tiempo de espera',
+ DATABASE_NOT_FOUND: 'Asegúrate de que la base de datos exista y de que tengas acceso a ella',
+ TABLE_NOT_FOUND: 'Revisa el nombre de la tabla y asegúrate de que exista en la base de datos',
+ COLUMN_NOT_FOUND: 'Verifica que el nombre de la columna coincida con el esquema de la tabla',
+ FOREIGN_KEY_VIOLATION: 'Asegúrate de que los registros referenciados existan en la tabla padre',
+ UNIQUE_VIOLATION: 'Ya existe un registro con este valor',
+ NOT_NULL_VIOLATION: 'Este campo requiere un valor',
+ CHECK_VIOLATION: 'El valor no cumple las restricciones de la tabla',
+ PERMISSION_DENIED: 'No tienes privilegios suficientes para esta operación',
+ },
+ },
+ sidebar: {
+ connection: {
+ placeholder: 'Seleccionar conexión',
+ connected: 'Conectado',
+ lost: 'Conexión perdida',
+ disconnected: 'Desconectado',
+ connecting: 'Conectando...',
+ },
+ database: {
+ placeholder: 'Todas las bases de datos',
+ selectDatabase: 'Seleccionar base de datos',
+ refresh: 'Actualizar',
+ refreshTooltip: 'Volver a cargar la lista de bases de datos',
+ },
+ databases: {
+ actions: {
+ createObject: {
+ title: 'Crear {type}',
+ placeholder: 'Introduce el nombre de {type}',
+ cancel: 'Cancelar',
+ confirm: 'Crear',
+ created: 'Se creó {type} "{name}" correctamente',
+ error: 'No se pudo crear: {error}',
+ types: {
+ database: 'Base de datos',
+ schema: 'Esquema',
+ },
+ },
+ createDatabase: {
+ title: 'Crear base de datos',
+ name: 'Nombre de la base de datos',
+ namePlaceholder: 'Introduce el nombre de la base de datos',
+ charset: 'Juego de caracteres',
+ collation: 'Intercalación',
+ collationPlaceholder: 'p. ej. utf8mb4_unicode_ci',
+ encoding: 'Codificación',
+ locale: 'Locale / LC_COLLATE',
+ localePlaceholder: 'p. ej. en_US.UTF-8',
+ optional: 'opcional',
+ cancel: 'Cancelar',
+ confirm: 'Crear',
+ },
+ dropDatabase: {
+ title: 'Eliminar base de datos',
+ message: '¿Seguro que quieres eliminar "{name}"? Esta acción no se puede deshacer.',
+ typeToConfirm: 'Escribe el nombre de la base de datos para confirmar:',
+ cancel: 'Cancelar',
+ confirm: 'Eliminar',
+ success: 'Base de datos "{name}" eliminada correctamente',
+ error: 'No se pudo eliminar la base de datos: {error}',
+ },
+ createTable: {
+ title: 'Crear tabla',
+ tableName: 'Nombre de la tabla',
+ tableNamePlaceholder: 'Introduce el nombre de la tabla',
+ engine: 'Motor',
+ columns: 'Columnas',
+ addColumn: 'Agregar columna',
+ colName: 'Nombre',
+ colType: 'Tipo',
+ colLength: 'Longitud',
+ colAutoInc: 'AI',
+ colDefault: 'Predeterminado',
+ lengthPlaceholder: '255',
+ defaultPlaceholder: 'NULL',
+ preview: 'Vista previa SQL',
+ cancel: 'Cancelar',
+ create: 'Crear',
+ opened: 'El SQL de la tabla se abrió en el editor. Ejecútalo para crear la tabla.',
+ },
+ templateOpened: 'Se abrió la plantilla de {type} en el editor.',
+ },
+ },
+ actionMenu: {
+ label: 'Acciones de base de datos',
+ createScript: 'Script de creación',
+ newDatabase: 'Nueva base de datos',
+ newSchema: 'Nuevo esquema',
+ newTable: 'Nueva tabla',
+ newView: 'Nueva vista',
+ newFunction: 'Nueva función',
+ newProcedure: 'Nuevo procedimiento',
+ showErDiagram: 'Diagrama ER',
+ backupDatabase: 'Copia de seguridad de la base de datos',
+ exportDatabase: 'Exportar base de datos',
+ dropDatabase: 'Eliminar base de datos',
+ },
+ groups: {
+ tables: 'TABLAS',
+ views: 'VISTAS',
+ procedures: 'PROCEDIMIENTOS',
+ functions: 'FUNCIONES',
+ },
+ loading: 'Cargando...',
+ empty: 'No hay base de datos seleccionada. Elige una para explorar.',
+ noObjects: 'No se encontraron objetos',
+ noDatabases: 'No se encontraron bases de datos. Conéctate primero a un servidor.',
+ search: 'Buscar tablas, vistas...',
+ savedQueries: {
+ header: 'Consultas guardadas',
+ expand: 'Expandir consultas guardadas',
+ collapse: 'Contraer consultas guardadas',
+ newQuery: 'Nueva consulta',
+ empty: 'Aún no hay consultas guardadas',
+ created: 'Creada',
+ modified: 'Modificada',
+ connectionNone: 'Sin conexión de destino',
+ actions: {
+ open: 'Abrir',
+ rename: 'Renombrar',
+ changeConnection: 'Cambiar conexión de destino',
+ reveal: 'Mostrar en el explorador de archivos',
+ delete: 'Eliminar',
+ },
+ delete: {
+ title: '¿Eliminar la consulta guardada?',
+ description: '¿Seguro que quieres eliminar "{name}"? Esta acción no se puede deshacer.',
+ cancel: 'Cancelar',
+ confirm: 'Eliminar',
+ target: 'Destino',
+ created: 'Creada',
+ },
+ renameDialog: {
+ title: 'Renombrar consulta guardada',
+ label: 'Nuevo nombre',
+ placeholder: 'Introduce el nuevo nombre de archivo',
+ cancel: 'Cancelar',
+ confirm: 'Renombrar',
+ },
+ connectionDialog: {
+ title: 'Cambiar conexión de destino',
+ label: 'Seleccionar conexión',
+ none: 'Sin conexión',
+ cancel: 'Cancelar',
+ confirm: 'Guardar',
+ },
+ },
+ notImplemented: 'Esta función aún no está implementada',
+ },
+}
diff --git a/src/lang/index.ts b/src/lang/index.ts
index 8d1d9454..4dad178a 100644
--- a/src/lang/index.ts
+++ b/src/lang/index.ts
@@ -1,8 +1,13 @@
import { createI18n, useI18n } from 'vue-i18n'
import { enUS } from './enUS'
+import { esES } from './esES'
+import { jaJP } from './jaJP'
+import { koKR } from './koKR'
+import { ptBR } from './ptBR'
import { zhCN } from './zhCN'
+import { zhTW } from './zhTW'
-type AppLocale = 'zhCN' | 'enUS'
+type AppLocale = 'zhCN' | 'zhTW' | 'enUS' | 'ptBR' | 'jaJP' | 'koKR' | 'esES'
function getStoredLocale(): AppLocale | 'auto' {
if (typeof localStorage === 'undefined')
@@ -10,16 +15,33 @@ function getStoredLocale(): AppLocale | 'auto' {
return (localStorage.getItem('lang') as AppLocale | 'auto') || 'auto'
}
-const AVAILABLE_LOCALES: AppLocale[] = ['enUS', 'zhCN']
+const AVAILABLE_LOCALES: AppLocale[] = ['enUS', 'zhCN', 'zhTW', 'ptBR', 'jaJP', 'koKR', 'esES']
+
+function detectFromNavigator(): AppLocale {
+ if (typeof navigator === 'undefined')
+ return 'enUS'
+ const tag = (navigator.language || '').toLowerCase()
+ if (/^zh-(?:tw|hk|mo|hant)/.test(tag))
+ return 'zhTW'
+ if (tag === 'zh-cn')
+ return 'zhCN'
+ if (tag.startsWith('pt'))
+ return 'ptBR'
+ if (tag.startsWith('ja'))
+ return 'jaJP'
+ if (tag.startsWith('ko'))
+ return 'koKR'
+ if (tag.startsWith('es'))
+ return 'esES'
+ return 'enUS'
+}
function resolveLocale(): AppLocale {
const stored = getStoredLocale()
- if (stored === 'auto')
- return typeof navigator !== 'undefined' && navigator.language === 'zh-CN' ? 'zhCN' : 'enUS'
// Validate stored locale against available locales; fall back to auto if invalid
- if (AVAILABLE_LOCALES.includes(stored as AppLocale))
+ if (stored !== 'auto' && AVAILABLE_LOCALES.includes(stored))
return stored
- return typeof navigator !== 'undefined' && navigator.language === 'zh-CN' ? 'zhCN' : 'enUS'
+ return detectFromNavigator()
}
const lang = createI18n({
@@ -31,10 +53,15 @@ const lang = createI18n({
fallbackWarn: false,
messages: {
zhCN,
+ zhTW,
enUS,
+ ptBR,
+ jaJP,
+ koKR,
+ esES,
},
})
const useLang = useI18n
-export { lang, useLang }
+export { detectFromNavigator, lang, useLang }
diff --git a/src/lang/jaJP.ts b/src/lang/jaJP.ts
new file mode 100644
index 00000000..f91ae7ee
--- /dev/null
+++ b/src/lang/jaJP.ts
@@ -0,0 +1,2049 @@
+export const jaJP = {
+ aiPermissions: {
+ ultimateOnly: '接続ごとの AI 設定には Ultimate が必要です',
+ accessLevel: 'アクセスレベル',
+ unavailable: '利用不可',
+ loadError: '権限を読み込めませんでした',
+ saving: '保存中…',
+ deniedByConnection: '接続の権限により拒否されています',
+ conversationReadOnly: 'この会話では読み取り専用',
+ title: 'AI 権限',
+ help: 'Data Studio と外部 MCP クライアントに適用されます。システムのデフォルトを使用するか、この接続の権限を設定してください。',
+ loading: '権限を読み込み中…',
+ loadFailed: '権限を読み込めませんでした。この接続を保存する前に再試行してください。',
+ retry: '再試行',
+ inherit: 'システムのデフォルトを使用',
+ none: 'アクセスなし',
+ read: '読み取り',
+ data: 'データの読み取りと変更',
+ full: 'フルアクセス',
+ custom: 'カスタム',
+ effective: '実効アクセス',
+ create: 'データの作成',
+ update: 'データの更新',
+ delete: 'データの削除',
+ manage: '構造と管理の操作',
+ allow: '許可',
+ deny: '拒否',
+ fromConnection: 'この接続',
+ defaults: 'デフォルトの AI 権限',
+ defaultsHelp: 'Data Studio と外部 MCP クライアントに適用されます。接続で個別に設定しない限り、接続はこれらのデフォルトに従います。',
+ save: 'デフォルトを保存',
+ saved: '権限を保存しました',
+ saveFailed: '権限を保存できませんでした',
+ inheritHelp: '将来の変更を含め、システムのデフォルトに従います。',
+ noneHelp: 'データアクセスも管理操作もありません。',
+ readHelp: 'データの読み取りと構造の確認のみ。変更はできません。',
+ dataHelp: '削除を含むデータの変更。構造や管理の変更はできません。',
+ fullHelp: 'すべてのデータ操作、構造変更、管理操作。',
+ customHelp: 'AI が実行できる個々の操作を選択します。',
+ defaultDecision: 'デフォルトを使用 ({decision})',
+ readPreset: '読み取り専用',
+ },
+
+ device: {
+ replaceTitle: 'デバイス数の上限に達しました',
+ replaceDescription: 'サブスクリプションは最大 {limit} 台のデバイスで有効化できます。置き換えるデバイスを以下から選択してください — 置き換えられたデバイスは直ちにアクセスできなくなります。',
+ slotUsage: '{used}/{limit} 台のデバイスが使用中',
+ thisDevice: 'このデバイス',
+ lastActive: '最終アクティブ',
+ neverActive: '未使用',
+ replaceConfirm: '置き換えて有効化',
+ replaceFailed: 'デバイスの置き換えに失敗しました。別のデバイスを選択して再試行してください。',
+ },
+ plan: {
+ tab: 'アカウントとプラン',
+ pricing: 'Ultimate $9.9/月 · $99/年 · 7日間無料トライアル',
+ state: {
+ ultimate: 'Ultimate',
+ community: 'Community',
+ unknown: '不明',
+ checking: '確認中…',
+ },
+ gate: {
+ additive: 'Community の全機能に加えて:',
+ recommended: 'おすすめ',
+ currentFeature: 'この機能',
+ trustLine: 'バージョンロックで購入済みリリースをずっと利用可能 · いつでもキャンセルできます',
+ headline: {
+ ai: '自然言語でデータに質問する',
+ transfer: '大量のデータを高速かつ安全に移動',
+ er_diagram: 'スキーマをマップとして可視化',
+ ssh_tunnel: 'SSH 経由でリモートデータベースに接続',
+ mcp_bridge: 'SQLKit をエージェントスタックに組み込む',
+ },
+ tiles: {
+ aiQueryT: '自然言語クエリ',
+ aiQueryD: '自然言語で質問すると、編集可能な SQL を取得できます',
+ aiAgentT: 'エージェントによる説明と修正',
+ aiAgentD: 'ワンクリックで遅いクエリを最適化',
+ mcpServerT: '内蔵 MCP サーバー',
+ mcpServerD: 'ローカルで動作 — セットアップ不要',
+ mcpClientsT: '任意の MCP クライアント',
+ mcpClientsD: 'Claude Desktop、Cursor など',
+ },
+ groups: {
+ cloud: 'クラウド',
+ local: 'ローカル',
+ custom: 'カスタム',
+ clients: 'クライアント',
+ },
+ detail: {
+ ai: 'クラウド、ローカル、カスタムを問わず任意のモデルで動作',
+ mcp: 'お気に入りの MCP クライアントに接続できます',
+ },
+ price: {
+ yearly: '$99 / 年',
+ save: '17% お得',
+ monthly: '$9.9 / 月',
+ },
+ trust: {
+ versionLock: 'サブスクライブ中にリリースされたバージョンは、オフラインでもずっと利用できます',
+ byok: '独自の LLM キーを利用可能 — トークンの上乗せ料金なし',
+ cancel: 'いつでもキャンセルできます',
+ },
+ cta: {
+ unlock: 'Ultimate でアンロック',
+ unlockSub: '7日間無料トライアル · $9.9/月 · $99/年',
+ },
+ },
+ poster: {
+ mcp: {
+ clients: '対応クライアント',
+ config: 'クライアント設定',
+ },
+ ai: {
+ question: '過去 7 日間の失敗した支払いを探して',
+ loop: 'ループ 1',
+ thinking: '思考中',
+ toolVerb: 'public.orders をクエリしました',
+ answer: '3 件の失敗した支払いが見つかりました。生成されたクエリ:',
+ },
+ transfer: {
+ scopeDatabase: 'データベース全体',
+ },
+ },
+ compare: {
+ ai: 'AI アシスタント & NL2SQL',
+ er_diagram: 'ER 図',
+ transfer: '一括インポート / エクスポート & 移行',
+ ssh: 'SSH トンネル',
+ mcp: 'MCP ブリッジ',
+ versionLock: 'バージョンロック',
+ },
+ upgrade: {
+ title: 'Ultimate にアップグレード',
+ cta: 'アップグレード',
+ refresh: 'エンタイトルメントを更新',
+ startFree: '無料で始める',
+ versionPermanent: 'サブスクライブ中のバージョンは、オフラインでも永久に使用できます。',
+ versionLockedOut: 'このリリースのアンロックには有効なサブスクリプションが必要です。更新すると永久にアンロックされます。',
+ },
+ section: {
+ title: 'アカウントとプラン',
+ desc: 'このインストールのサブスクリプションエンタイトルメントとバージョンロックの状態。',
+ versionPermanent: '現在のバージョンは永久に使用できます (バージョンロックの対象です)。',
+ subscriptionActive: 'Ultimate が有効です — サブスクライブ中はすべての機能が利用できます。',
+ versionLockedOut: 'このバージョン ({date}) はバージョンロックの対象外のため、Community モードで表示しています。',
+ expiresAt: '{time} まで有効',
+ cancelScheduled: 'サブスクリプションは現在の請求期間の終了時に終了する予定です。',
+ checkFailed: 'エンタイトルメントを確認できませんでした — キャッシュされた状態を表示しています。ネットワークを確認して更新してください。',
+ sessionExpired: 'セッションが期限切れです — プランを確認するには再度ログインしてください。',
+ sessionLostSignedOut: 'セッションを更新できなくなったため、ログアウトされました。いつでも再度ログインできます。',
+ deviceActivationFailed: 'デバイスの登録に失敗しました — セッションの自動更新は利用できません。',
+ notLoggedIn: 'ログインしていません。',
+ loginLink: 'Geekfun でログイン',
+ refresh: '更新',
+ logout: 'ログアウト',
+ manage: 'サブスクリプションを管理',
+ },
+ },
+ aside: {
+ aiAssistant: 'AI アシスタント',
+ tasks: 'タスク',
+ },
+ connection: {
+ prompt: {
+ title: 'エージェントプロンプト',
+ label: 'エージェントプロンプト',
+ description: 'この接続に関するコンテキストを AI エージェントに追加します。',
+ help: 'この接続がアタッチされると、グローバルシステムプロンプトの後にエージェントへ送信されます。',
+ placeholder: 'データの業務上の意味、命名規則、よく使うクエリなどを記述してください。',
+ configured: '設定済み',
+ add: '追加',
+ edit: '編集',
+ clear: 'クリア',
+ cancel: 'キャンセル',
+ confirm: '確認',
+ },
+ },
+ connectionsPage: {
+ addSshProfile: 'SSH プロファイルを追加',
+ copySuffix: ' (コピー)',
+ sshProfilesSection: 'SSH プロファイル',
+ sshProfile: 'SSH プロファイル',
+ },
+ common: {
+
+ copy: 'コピー',
+ copied: 'コピーしました!',
+ browse: '参照',
+ settings: '設定',
+ loading: '読み込み中...',
+ notifications: {
+ codeCopied: 'コードをコピーしました',
+ },
+ buttons: {
+ create: '作成',
+ save: '保存',
+ cancel: 'キャンセル',
+ delete: '削除',
+ edit: '編集',
+ confirm: '確認',
+ test: 'テスト',
+ connect: '接続',
+ disconnect: '切断',
+ duplicate: '複製',
+ saveChanges: '変更を保存',
+ createConnection: '接続を作成',
+ testConnection: '接続テスト',
+ dismiss: '閉じる',
+ close: '閉じる',
+ browse: '参照',
+ retry: '再試行',
+ continue: '続行',
+ refresh: '更新',
+ },
+ status: {
+ connected: '接続済み',
+ disconnected: '切断されました',
+ connecting: '接続中...',
+ error: '接続エラー',
+ testing: '接続をテスト中...',
+ success: '接続に成功しました!',
+ failed: '接続に失敗しました',
+ },
+ },
+ ssl: {
+ errors: {
+ invalidMode: '無効な SSL モードです',
+ caCertRequired: 'verify-ca/verify-full モードでは CA 証明書のパスが必要です',
+ invalidCaPath: 'CA 証明書のパスが無効です',
+ invalidCertPath: 'クライアント証明書のパスが無効です',
+ invalidKeyPath: 'クライアント秘密鍵のパスが無効です',
+ },
+ mode: {
+ label: 'SSL/TLS モード',
+ disable: 'Disable',
+ prefer: 'Prefer',
+ require: 'Require',
+ verifyca: 'Verify CA',
+ verifyfull: 'Verify Full',
+ },
+ modeDesc: {
+ disable: '暗号化なし',
+ prefer: '暗号化を試み、失敗時は平文で接続します',
+ require: '常に暗号化しますが、証明書は検証しません',
+ verifyca: '暗号化 + CA 証明書の検証',
+ verifyfull: '暗号化 + CA とホストの検証',
+ },
+ certSettings: {
+ title: '証明書設定',
+ caCert: 'CA 証明書',
+ caCertPlaceholder: 'CA 証明書のパス',
+ clientCert: 'クライアント証明書',
+ clientCertPlaceholder: 'クライアント証明書のパス',
+ clientKey: 'クライアント秘密鍵',
+ clientKeyPlaceholder: 'クライアント秘密鍵のパス',
+ },
+ sqlServer: {
+ trustServerCert: 'サーバー証明書を信頼',
+ trustServerCertHint: '自己署名証明書を受け入れます',
+ },
+ },
+ transfer: {
+ title: '転送',
+ subtitle: 'データのインポート、エクスポート、移行',
+ tabs: {
+ export: 'エクスポート',
+ import: 'インポート',
+ migration: '移行',
+ structure: '構造',
+ },
+ export: {
+ step: {
+ source: 'ソース',
+ format: 'フォーマット',
+ output: '出力',
+ formatOutput: 'フォーマットと出力',
+ preview: 'プレビュー',
+ execute: 'エクスポート開始',
+ },
+ selectTablesFirst: '上でテーブルを選択すると列を設定できます',
+ tables: {
+ label: 'テーブル',
+ loadFailed: 'テーブルの読み込みに失敗しました',
+ },
+ columns: {
+ label: '列',
+ selectAll: 'すべて選択',
+ deselectAll: 'すべて選択解除',
+ loadFailed: '列の読み込みに失敗しました',
+ },
+ whereClause: 'WHERE 句 (任意)',
+ where: 'WHERE 句 (任意)',
+ whereClausePlaceholder: 'status = "active"',
+ orderBy: 'ORDER BY (任意)',
+ orderByPlaceholder: 'created_at DESC',
+ limit: 'LIMIT (任意)',
+ limitPlaceholder: '1000',
+ scope: 'スコープ',
+ delimiter: '区切り文字',
+ delimiterOptions: {
+ comma: 'カンマ (,)',
+ semicolon: 'セミコロン (;)',
+ tab: 'タブ',
+ },
+ includeHeader: 'ヘッダーを含める',
+ dateFormat: '日付フォーマット',
+ dateFormatOptions: {
+ iso8601: 'ISO 8601',
+ unix: 'Unix',
+ },
+ rowsPerBatch: 'バッチあたりの行数',
+ createTable: 'CREATE TABLE',
+ dropTable: 'DROP TABLE',
+ worksheet: 'ワークシート',
+ freeze: '固定',
+ autoFit: '自動調整',
+ outputPath: '出力パス',
+ selectFormat: 'フォーマットを選択',
+ showAdvanced: '詳細オプションを表示',
+ hideAdvanced: '詳細オプションを非表示',
+ encoding: 'エンコーディング',
+ preview: 'プレビュー',
+ outputFile: '出力ファイル',
+ },
+ connection: {
+ connectFailed: '接続に失敗しました',
+ databasesFailed: 'データベースの読み込みに失敗しました',
+ schemasFailed: 'スキーマの読み込みに失敗しました',
+ label: '接続',
+ placeholder: '接続を選択',
+ noConnections: '利用可能な接続がありません。先に接続を追加してください。',
+ connected: '接続済み',
+ offline: 'オフライン',
+ databaseLabel: 'データベース',
+ databasePlaceholder: 'データベースを選択',
+ system: 'システム',
+ loadingDatabases: 'データベースを読み込み中...',
+ schemaLabel: 'スキーマ',
+ schemaPlaceholder: 'スキーマを選択',
+ loadingSchemas: 'スキーマを読み込み中...',
+ tableLabel: 'テーブル',
+ tablePlaceholder: 'テーブルを選択',
+ },
+ import: {
+ step: {
+ file: 'ファイルを選択',
+ mapping: 'ターゲットとマッピング',
+ options: 'オプションとプレビュー',
+ execute: 'インポート',
+ },
+ dropzone: {
+ title: 'ここにファイルをドラッグ&ドロップ',
+ subtitle: 'またはクリックして参照',
+ supported: '対応形式: CSV, JSONL, SQL, Excel (.xlsx)',
+ instruction: 'またはクリックしてコンピューターから選択',
+ },
+ detected: {
+ format: '検出されたフォーマット',
+ encoding: '検出されたエンコーディング',
+ rows: '行数 (推定)',
+ },
+ autoMap: '名前で自動マッピング',
+ clearAll: 'すべてクリア',
+ conflict: {
+ label: '競合時の処理',
+ skip: '重複をスキップ',
+ replace: '既存データを置き換え',
+ upsert: '既存データを更新 (upsert)',
+ abort: 'エラー時に中止',
+ },
+ truncateBefore: 'インポート前にテーブルを TRUNCATE',
+ dryRun: 'ドライラン (挿入せず検証のみ)',
+ browseFiles: 'ファイルを参照',
+ fileSize: 'ファイルサイズ',
+ detectedColumns: '検出された列',
+ createDbIfNotExists: 'データベースが存在しない場合は作成',
+ tablesAutoCreated: 'テーブルは自動作成されます',
+ skipPlaceholder: 'スキップ',
+ skip: '(スキップ)',
+ importData: 'データをインポート',
+ dataPreview: 'データプレビュー',
+ previewRows: '10 行',
+ selectFileToPreview: 'プレビューするファイルを選択してください',
+ importSettings: 'インポート設定',
+ batchSize: 'バッチサイズ',
+ loadingPreview: 'プレビューを読み込み中...',
+ noPreviewData: 'プレビューデータがありません',
+ fileDetails: 'ファイル詳細',
+ },
+ structure: {
+ title: '構造',
+ subtitle: 'DDL の生成と SQL ファイルの実行',
+ generateDdl: 'DDL を生成',
+ runSqlFile: 'SQL ファイルを実行',
+ objects: 'データベースオブジェクト',
+ selectAll: 'すべて選択',
+ deselectAll: 'すべて選択解除',
+ loadingObjects: 'オブジェクトを読み込み中...',
+ noObjects: 'オブジェクトが見つかりません。接続とデータベースを選択してください。',
+ objectsSelected: '個のオブジェクトを選択中',
+ options: 'DDL オプション',
+ includeCreateTable: 'CREATE TABLE 文',
+ includePrimaryKeys: '主キー',
+ includeForeignKeys: '外部キー',
+ includeIndexes: 'インデックス',
+ includeDropIfExists: 'CREATE の前に DROP IF EXISTS を含める',
+ includeIfNotExists: 'CREATE に IF NOT EXISTS を含める',
+ generate: 'DDL を生成',
+ preview: 'DDL プレビュー',
+ copyToClipboard: 'クリップボードにコピー',
+ saveToFile: 'ファイルに保存...',
+ sqlFile: 'SQL ファイル',
+ errorHandling: 'エラー処理',
+ onErrorStop: '最初のエラーで停止',
+ onErrorSkip: 'スキップして続行',
+ onErrorRollback: 'ロールバック (ベストエフォート、最初のエラーで中止)',
+ reset: 'リセット',
+ execute: '実行',
+ },
+ migration: {
+ title: '移行',
+ subtitle: '異種エンジン間のデータ移行',
+ step: {
+ source: 'ソース',
+ target: 'ターゲット',
+ mapping: 'マッピング',
+ configure: '設定',
+ execute: '実行',
+ },
+ sourceConnection: 'ソース接続',
+ targetConnection: 'ターゲット接続',
+ availableTables: '利用可能なテーブル',
+ loadingTables: 'テーブルを読み込み中...',
+ noTables: 'テーブルが見つかりません',
+ selectAll: 'すべて選択',
+ deselectAll: 'すべて選択解除',
+ tablesSelected: '個のテーブルを選択中',
+ direction: '移行方向',
+ createTables: 'ターゲットテーブルが存在しない場合は作成',
+ dropTables: '移行前にターゲットテーブルを DROP',
+ loadingMapping: '型マッピングを生成中...',
+ typeConversions: '個の列で型変換が必要',
+ batchSize: 'バッチサイズ',
+ onError: 'エラー時の処理',
+ onErrorSkipRow: '行をスキップして続行',
+ onErrorSkipTable: 'テーブルをスキップして続行',
+ onErrorAbort: '移行を中止',
+ migrateIndexes: 'インデックスを移行',
+ migrateForeignKeys: '外部キーを移行',
+ migrateConstraints: '制約を移行',
+ summary: '移行サマリー',
+ tables: 'テーブル',
+ totalRows: '合計行数',
+ conversions: '型変換',
+ executing: '移行を実行中...',
+ pleaseWait: 'データを転送しています。しばらくお待ちください',
+ startMigration: '移行を開始',
+ migrateAgain: '再移行',
+ back: '戻る',
+ next: '次へ',
+ },
+ format: {
+ label: 'フォーマット',
+ csv: 'CSV (.csv)',
+ jsonl: 'JSONL (.jsonl)',
+ sql: 'SQL (.sql)',
+ excel: 'Excel (.xlsx)',
+ defaults: {
+ csv: 'カンマ区切り、ダブルクォート、UTF-8、ヘッダー付き',
+ jsonl: '1 行に 1 つの JSON オブジェクト、コンパクト、UTF-8、ISO 8601 日付',
+ sql: 'ターゲットテーブル自動入力、バッチサイズ 1000、CREATE TABLE 付き',
+ excel: 'ヘッダー付き、列幅自動調整、ヘッダー行を固定',
+ },
+ advancedOptions: '詳細オプション',
+ },
+ progress: {
+ preparing: '準備中',
+ exporting: 'エクスポート中...',
+ importing: 'インポート中...',
+ elapsed: '経過時間',
+ remaining: '残り時間 (推定)',
+ rows: '行',
+ exported: 'エクスポート済み',
+ imported: 'インポート済み',
+ skipped: 'スキップ済み',
+ errors: 'エラー',
+ cancel: 'キャンセル',
+ runInBackground: 'バックグラウンドで実行',
+ },
+ result: {
+ success: '正常に完了しました',
+ partial: 'エラーありで完了しました',
+ failed: '失敗しました',
+ duration: '所要時間',
+ file: 'ファイル',
+ openFile: 'ファイルを開く',
+ openFolder: 'フォルダを開く',
+ exportAgain: '再エクスポート',
+ importAgain: '再インポート',
+ viewTable: 'テーブルを表示',
+ processed: '処理済み',
+ skipped: 'スキップ',
+ errorCount: 'エラー',
+ },
+ tasks: {
+ title: 'タスク',
+ clearCompleted: '完了済みをクリア',
+ goToTask: 'タスクへ移動',
+ dismiss: '閉じる',
+ noTasks: '転送タスクはありません',
+ rows: '行',
+ emptyDescription: 'エクスポート、インポート、移行のジョブがここに表示されます',
+ status: {
+ pending: '待機中',
+ running: '実行中',
+ completed: '完了',
+ failed: '失敗',
+ },
+ startedAgo: '{time}前に開始',
+ },
+ common: {
+
+ connection: '接続',
+ database: 'データベース',
+ schema: 'スキーマ',
+ table: 'テーブル',
+ back: '戻る',
+ next: '次へ',
+ browse: '参照...',
+ error: 'エラー',
+ cancel: 'キャンセル',
+ save: '保存',
+ close: '閉じる',
+ tableName: 'テーブル名',
+ rows: '行',
+ type: '型',
+ noTablesFound: 'テーブルが見つかりません',
+ columns: '列',
+ deselectAll: 'すべて選択解除',
+ scopeServer: 'サーバー',
+ scopeDatabase: 'データベース',
+ scopeTables: 'テーブル',
+ },
+ },
+ pages: {
+ connections: {
+ title: '接続',
+ subtitle: 'データベース接続の管理',
+ search: '接続を検索...',
+ stats: {
+ totalConnections: '接続の総数',
+ activeSessions: 'アクティブなセッション',
+ sshProfiles: 'SSH プロファイル',
+ ago: '{time}前',
+ },
+ saved: '保存された接続',
+ addNew: '新規接続を追加',
+ addNewHint: 'PostgreSQL、MySQL、SQLite...',
+ empty: {
+ title: '接続が見つかりません',
+ message: '"{query}" に一致する接続はありません',
+ },
+ delete: {
+ title: '接続の削除',
+ message: '"{name}" を削除してもよろしいですか?この操作は元に戻せません。',
+ },
+ error: {
+ title: '接続エラー',
+ },
+ saveFailed: '接続の保存に失敗しました',
+ },
+ settings: {
+ title: '設定',
+ subtitle: 'アプリケーションの環境設定を行います',
+ general: {
+ title: '一般',
+ description: 'アカウント、プラン、テーマ、アプリケーションの更新を管理します',
+ theme: 'テーマ',
+ themeSelect: 'テーマを選択',
+ themeHelp: 'ライト、ダーク、またはシステムテーマを選択してください',
+ themes: {
+ light: 'ライト',
+ dark: 'ダーク',
+ system: 'システム',
+ },
+ language: '言語',
+ languageSelect: '言語を選択',
+ languageHelp: 'お好みの言語を選択してください',
+ languages: {
+ enUS: 'English',
+ zhCN: '简体中文',
+ auto: '自動 (システムに従う)',
+ },
+ },
+ mcp: {
+ title: 'MCP ブリッジ',
+ status: 'ステータス',
+ running: 'ポート {port} で実行中',
+ stopped: '停止中',
+ port: 'ポート',
+ portDesc: 'MCP ブリッジサーバーのポート (空欄の場合は自動)',
+ restart: 'ブリッジを再起動',
+ restartSuccess: 'MCP ブリッジを正常に再起動しました',
+ restartFailed: '再起動に失敗しました',
+ restartFailedDetail: 'MCP ブリッジの再起動に失敗しました',
+ restartTimeout: 'MCP ブリッジが 60 秒以内に起動しませんでした',
+ shuttingDown: 'シャットダウン中...',
+ starting: '起動中...',
+ autoStart: '自動起動',
+ autoStartDesc: 'アプリの起動時に MCP ブリッジを自動的に開始します',
+ saveFailed: 'MCP 設定の保存に失敗しました',
+ },
+ about: {
+ title: '情報',
+ version: 'バージョン',
+ license: 'ライセンス',
+ licenseName: 'Apache 2.0',
+ repository: 'リポジトリ',
+ website: 'ウェブサイト',
+ copyright: '© {year} GEEKFUN. All rights reserved.',
+ description: 'SqlKit はエージェント機能を備えたクロスプラットフォームの SQL データベース GUI クライアントです。Rust + Tauri で構築されています。',
+ },
+ feedback: {
+ preparing: 'ダウンロードを準備中…',
+ downloading: 'ダウンロード中…',
+ installing: 'インストールと検証中…',
+ complete: 'インストールが完了しました',
+ failed: '操作に失敗しました',
+ checking: 'アップデートを確認中…',
+ removing: '削除中…',
+ removed: '削除しました',
+ refreshing: 'ステータスを更新中…',
+ refreshed: 'ステータスを更新しました',
+ loading: '設定を読み込み中…',
+ loadFailed: 'このセクションを読み込めませんでした',
+ retry: '再試行',
+ saved: '変更を保存しました',
+ saving: '変更を保存中…',
+ testing: '接続をテスト中…',
+ syncing: 'モデルを同期中…',
+ synced: 'モデルを同期しました',
+ opening: 'ブラウザーで開いています…',
+ opened: 'ブラウザーで開きました',
+ signedOut: 'ログアウトしました',
+ },
+ jre: {
+ title: 'JRE とドライバー',
+ description: 'データベース接続用の Java ランタイムと JDBC ドライバーを管理します',
+ jreCard: {
+ title: 'Java ランタイム',
+ description: 'JDBC ブリッジ接続 (Oracle、DB2、H2、Derby) に必要です',
+ status: {
+ installed: 'インストール済み',
+ notInstalled: '未インストール',
+ checking: '確認中...',
+ managed: '管理',
+ system: 'システム',
+ versionUnknown: '不明',
+ systemWarning: 'システムの Java バージョンが不明または互換性がありません。互換性を保証するには管理 JRE をダウンロードしてください。',
+ systemInvalid: '有効な JRE がありません',
+ managedRecommended: '管理 JRE を使用',
+ },
+ actions: {
+ download: 'JRE をダウンロード',
+ remove: 'JRE を削除',
+ redownload: '再ダウンロード',
+ checkUpdates: 'アップデートを確認',
+ },
+ notifications: {
+ upToDate: 'JRE は最新です',
+ updateAvailable: 'JRE のアップデートが利用可能です',
+ newVersion: 'バージョン {version} が利用可能です',
+ checkUpdatesFailed: 'JRE のアップデート確認に失敗しました',
+ downloadFailed: 'JRE のダウンロードに失敗しました',
+ downloadSuccess: 'JRE を正常にダウンロードしました',
+ removeFailed: 'JRE の削除に失敗しました',
+ },
+ },
+ bridgeCard: {
+ title: 'ブリッジ JAR',
+ description: 'データベース接続用の JDBC ブリッジコンポーネント',
+ status: {
+ installed: 'インストール済み',
+ notInstalled: '未インストール',
+ checking: '確認中...',
+ },
+ actions: {
+ download: 'ブリッジをダウンロード',
+ remove: 'ブリッジを削除',
+ },
+ notifications: {
+ downloadFailed: 'ブリッジ JAR のダウンロードに失敗しました',
+ downloadSuccess: 'ブリッジ JAR を正常にダウンロードしました',
+ removeFailed: 'ブリッジ JAR の削除に失敗しました',
+ },
+ },
+ jdbcToggle: {
+ title: 'JDBC 接続',
+ description: 'JDBC データベースのサポートを有効にします (JRE + ブリッジ + ドライバー)',
+ label: 'JDBC は不要です',
+ },
+ actions: {
+ refresh: '更新',
+ },
+ driversCard: {
+ title: 'JDBC ドライバー',
+ description: 'データベース固有の JDBC ドライバーファイル',
+ label: {
+ versions: '個のバージョン',
+ },
+ status: {
+ installed: 'インストール済み',
+ notInstalled: '未インストール',
+ loading: 'ドライバーを読み込み中...',
+ },
+ actions: {
+ download: 'ダウンロード',
+ remove: '削除',
+ checkUpdates: 'アップデートを確認',
+ },
+ notifications: {
+ upToDate: 'ドライバーは最新です',
+ updateAvailable: 'ドライバーのアップデートが利用可能です',
+ newVersion: 'バージョン {version} が利用可能です',
+ checkUpdatesFailed: 'ドライバーのアップデート確認に失敗しました',
+ downloadFailed: 'ドライバーのダウンロードに失敗しました',
+ downloadSuccess: 'ドライバーを正常にダウンロードしました',
+ removeFailed: 'ドライバーの削除に失敗しました',
+ installBridgeFirst: '先にブリッジ JAR をインストールしてから、ドライバーのダウンロードを試してください',
+ },
+ empty: {
+ title: 'ドライバーが設定されていません',
+ message: 'JDBC データベースに接続すると自動的にダウンロードされます。',
+ },
+ },
+ },
+ editor: {
+ title: 'エディター',
+ description: 'SQL エディターの動作と外観を設定します',
+ fontSize: 'フォントサイズ',
+ fontSizeHelp: 'エディターのフォントサイズ (ピクセル、8–32)',
+ fontSizeError: 'フォントサイズは 8 から 32 の間で指定してください',
+ tabSize: 'タブサイズ',
+ tabSizeHelp: 'タブあたりのスペース数 (1–8)',
+ tabSizeError: 'タブサイズは 1 から 8 の間で指定してください',
+ wordWrap: '折り返し',
+ wordWrapHelp: 'エディターで長い行を折り返します',
+ showLineNumbers: '行番号を表示',
+ showLineNumbersHelp: 'エディターのガターに行番号を表示します',
+ showMinimap: 'ミニマップを表示',
+ showMinimapHelp: '右側にミニマップの概要を表示します',
+ indentWidth: 'インデント幅',
+ indentWidthHelp: 'フォーマット済み SQL のインデントレベルごとのスペース数 (1–8)',
+ indentWidthError: 'インデント幅は 1 から 8 の間で指定してください',
+ lineWidth: '行幅',
+ lineWidthHelp: 'フォーマット済み SQL の目標行幅 (文字数、40–200)',
+ lineWidthError: '行幅は 40 から 200 の間で指定してください',
+ },
+ query: {
+ title: 'クエリ',
+ description: 'クエリ実行のデフォルト設定を行います',
+ defaultLimit: 'デフォルトの行数上限',
+ defaultLimitHelp: 'クエリごとに返される最大行数 (10–10000)',
+ defaultLimitError: '行数上限は 10 から 10000 の間で指定してください',
+ queryTimeout: 'クエリタイムアウト (秒)',
+ queryTimeoutHelp: 'クエリ実行の最大時間 (秒、1–300)',
+ queryTimeoutError: 'タイムアウトは 1 から 300 秒の間で指定してください',
+ autoSave: '自動保存',
+ autoSaveHelp: 'クエリの変更を自動的に保存します',
+ },
+ ai: {
+ title: 'AI 設定',
+ tabLabel: 'LLM',
+ description: 'AI モデルプロバイダーとチャットの動作を設定します',
+ missing: 'AI モデルが設定されていません。設定でプロバイダーを追加し、モデルを選択してください。',
+ providerList: {
+ title: 'プロバイダー',
+ description: 'AI モデルプロバイダーを管理します',
+ addProvider: 'プロバイダーを追加',
+ empty: 'プロバイダーが設定されていません。追加すると AI 機能が有効になります。',
+ emptyAction: '最初のプロバイダーを追加',
+ deleteConfirm: '"{name}" を削除してもよろしいですか?',
+ deleteConfirmTitle: 'プロバイダーの削除',
+ sync: 'モデルを同期',
+ syncing: '同期中...',
+ syncSuccess: '{count} 個のモデルを同期しました',
+ syncFailed: 'モデルの同期に失敗しました',
+ modelCount: '{count} 個のモデル',
+ testConnection: 'テスト',
+ testing: 'テスト中...',
+ testSuccess: '接続に成功しました',
+ testFailed: '接続テストに失敗しました',
+ },
+ form: {
+ addTitle: 'プロバイダーを追加',
+ editTitle: 'プロバイダーを編集',
+ providerType: 'プロバイダーの種類',
+ providerTypeHelp: 'プリセットを選択するか、その他のプロバイダーにはカスタムを選択してください',
+ presetOpenai: 'OpenAI',
+ presetAnthropic: 'Anthropic',
+ presetAzure: 'Azure OpenAI',
+ presetCustom: 'カスタム',
+ name: '表示名',
+ namePlaceholder: 'マイプロバイダー',
+ nameHelp: 'このプロバイダーの分かりやすい名前',
+ apiCompatibility: 'API 互換性',
+ apiCompatibilityPlaceholder: 'openai, anthropic, azure',
+ apiCompatibilityHelp: 'API プロトコルの種類。Ollama や DeepSeek などの互換サービスには "openai" を使用してください。',
+ apiKey: 'API キー',
+ apiKeyPlaceholder: 'sk-...',
+ apiKeyHelp: 'プロバイダーの API キー。ローカルに保存され、当社のサーバーには送信されません。',
+ baseUrl: 'ベース URL',
+ baseUrlPlaceholder: 'https://api.openai.com/v1',
+ baseUrlHelp: 'API エンドポイントの URL。公式プロバイダーの場合はデフォルトのままにしてください。',
+ proxy: 'プロキシ',
+ proxyPlaceholder: 'http://proxy:8080',
+ proxyHelp: 'API リクエスト用のオプションの HTTP/SOCKS5 プロキシ',
+ proxyMode: 'プロキシモード',
+ contextWindow: 'コンテキストウィンドウの上書き',
+ contextWindowHelp: 'デフォルトのコンテキストウィンドウサイズを上書きします (任意)',
+ showKey: '表示',
+ hideKey: '非表示',
+ save: 'プロバイダーを保存',
+ models: 'モデル',
+ modelsPlaceholder: 'gpt-4o, gpt-4o-mini',
+ modelsHelp: 'カンマ区切りのモデル ID。利用可能な場合はプロバイダー API から自動同期されます。',
+ validation: {
+ nameRequired: '表示名は必須です',
+ apiCompatibilityRequired: 'API 互換性は必須です',
+ invalidApiCompatibility: 'API 互換性は "openai"、"anthropic"、"azure" のいずれかである必要があります',
+ baseUrlInvalid: 'ベース URL は http:// または https:// で始まる必要があります',
+ },
+ },
+ chat: {
+ title: 'エージェント',
+ description: 'エージェントの実行時の動作を設定します',
+ autoCompactLabel: 'メッセージの自動圧縮',
+ autoCompactDescription: 'コンテキスト上限に近づくと、古いメッセージを自動的に要約してトークンを節約します',
+ maxIterationsLabel: '最大反復回数',
+ maxIterationsDescription: 'エージェントが停止するまでのツール呼び出し反復の最大数 (1–1000)',
+ wallClockBudgetLabel: '実行時間の上限 (分)',
+ wallClockBudgetDescription: 'エージェントが停止するまでの最大実時間 (分、1–240)',
+ tokenBudgetLabel: 'トークン上限',
+ tokenBudgetDescription: 'エージェントが停止するまでの最大トークン消費量',
+ systemPromptLabel: 'システムプロンプト',
+ systemPromptDescription: 'データベース接続がアタッチされたときにエージェントへ送信されるグローバルシステムプロンプト。使い方、用語、業務コンテキストなどを記述してください。',
+ systemPromptAdd: 'システムプロンプトを追加',
+ systemPromptEdit: 'システムプロンプトを編集',
+ systemPromptDelete: 'システムプロンプトを削除',
+ systemPromptEmpty: 'システムプロンプトが設定されていません。',
+ systemPromptSave: '保存',
+ systemPromptCancel: 'キャンセル',
+ systemPromptSaveFailed: 'システムプロンプトを保存できませんでした。',
+ systemPromptUltimateOnly: 'エージェントプロンプトは Ultimate 機能です',
+ },
+ },
+ updates: {
+ title: 'アップデート',
+ description: 'アプリケーションのアップデートを確認します',
+ checkForUpdates: 'アップデートを確認',
+ checkForUpdatesHelp: '一般を開くと自動的に確認します。アップデートは「今すぐアップデート」を選択したときにのみインストールされます。',
+ check: '今すぐ確認',
+ checking: '確認中...',
+ downloading: 'ダウンロード中...',
+ installing: 'インストール中...',
+ updateAvailable: 'アップデートが利用可能です',
+ upToDate: '最新バージョンを使用しています',
+ checkFailed: 'アップデートの確認に失敗しました',
+ downloadFailed: 'アップデートのダウンロードに失敗しました',
+ installFailed: 'アップデートのインストールに失敗しました',
+ installed: 'アップデートをインストールしました。再起動中...',
+ newVersion: 'バージョン {version} が利用可能です',
+ },
+ },
+ history: {
+ title: '履歴',
+ subtitle: 'クエリ履歴の表示と管理',
+ recent: '最近のクエリ',
+ recentDescription: '最近実行したクエリ',
+ empty: 'クエリ履歴はまだありません。',
+ search: 'クエリを検索...',
+ filterAll: 'すべて',
+ filterSuccess: '成功',
+ filterError: 'エラー',
+ clearAll: 'すべてクリア',
+ clearNonFavorites: 'お気に入り以外をクリア',
+ clearAllConfirm: 'すべての履歴エントリを削除してもよろしいですか?',
+ clearNonFavoritesConfirm: 'お気に入り以外の履歴エントリをすべて削除してもよろしいですか?',
+ columns: {
+ sql: 'SQL',
+ connection: '接続',
+ database: 'データベース',
+ status: 'ステータス',
+ time: '時刻',
+ executionTime: '所要時間',
+ actions: '操作',
+ },
+ status: {
+ success: '成功',
+ error: 'エラー',
+ },
+ actions: {
+ rerun: 'エディターで再実行',
+ favorite: 'お気に入りに追加',
+ unfavorite: 'お気に入りから削除',
+ delete: '削除',
+ },
+ notifications: {
+ cleared: '履歴を削除しました',
+ deleted: 'エントリを削除しました',
+ rerun: 'クエリをエディターに読み込みました',
+ },
+ },
+ importExport: {
+ title: 'インポート / エクスポート',
+ subtitle: 'データのインポートとエクスポート',
+ card: {
+ title: 'データインポート / エクスポート',
+ description: 'データベースのスキーマとデータをインポート・エクスポートします',
+ comingSoon: 'インポート・エクスポート機能は今後のアップデートで提供予定です。',
+ },
+ },
+ queries: {
+ title: 'クエリ',
+ subtitle: 'SQL クエリの作成と実行',
+ selectConnection: '接続を選択',
+ selectDatabase: 'データベースを選択',
+ noTab: '開いているクエリタブはありません',
+ newTab: '新規クエリ',
+ landing: {
+ ready: 'クエリを書く準備ができました',
+ connectedAs: '接続ユーザー',
+ currentDatabase: 'データベース',
+ selectConnection: '接続を選択',
+ tip: 'ヒント: サイドバーのテーブルをダブルクリックするとデータを表示できます',
+ },
+ editor: {
+ title: 'SQL エディター',
+ description: 'ここに SQL クエリを入力します',
+ execute: '実行',
+ explain: 'Explain',
+ format: 'SQL をフォーマット',
+ },
+ shortcuts: {
+ execute: 'クエリを実行 ({key}Enter)',
+ explain: 'クエリを Explain (F6)',
+ format: 'SQL をフォーマット (Shift+Alt+F)',
+ save: '保存 ({key}S)',
+ saveAs: '.sql ファイルとして保存',
+ comment: 'コメントを切り替え ({key}/)',
+ },
+ status: {
+ connection: '接続',
+ database: 'データベース',
+ rows: '行',
+ time: '時間',
+ executing: '実行中...',
+ connectionLost: '接続が切断されました。データベースへの接続が閉じられました。',
+ reconnecting: '再接続中...',
+ },
+ notifications: {
+ querySaved: 'クエリを保存しました',
+ saveFailed: '保存に失敗しました',
+ loadFailed: 'クエリの読み込みに失敗しました',
+ noStatementFound: 'カーソル位置に SQL ステートメントが見つかりません',
+ formatFailed: 'SQL のフォーマットに失敗しました',
+ noActiveConnection: 'アクティブな接続がありません',
+ selectConnectionFirst: 'クエリを実行する前に、接続とデータベースを選択してください',
+ tableActionSuccess: 'テーブル {table} が{action}されました',
+ tableActionFailed: 'テーブルの{action}に失敗しました: {error}',
+ },
+ orphanDialog: {
+ title: '孤立タブ',
+ message: 'このタブは別の接続に属しているため、クエリを実行できません。内容の編集と保存は可能です。',
+ acknowledge: '孤立タブとして保持',
+ close: 'タブを閉じる',
+ },
+ executeOrphanDialog: {
+ title: '接続が変更されました',
+ message: 'このクエリタブの元の接続が変更されました: {from} → {to}。現在のアクティブな接続に再バインドして実行しますか?',
+ cancel: 'キャンセル',
+ close: 'タブを閉じる',
+ rebindAndExecute: '再バインドして実行',
+ },
+ explain: {
+ title: '実行計画',
+ treeView: 'ツリー',
+ summaryView: 'サマリー',
+ rawView: 'RAW',
+ analyze: 'Explain Analyze',
+ running: '実行計画を生成中...',
+ empty: '実行計画データがありません',
+ nodeCount: '{count} ノード',
+ summary: {
+ totalCost: '推定総コスト: {cost}',
+ mostExpensive: '最もコストが高いノード: {node}',
+ noCostData: 'コストデータなし',
+ },
+ node: {
+ rowEstimate: 'e:{rows}',
+ actualRows: 'a:{rows}',
+ discrepancyWarning: '実際の行数が推定を大幅に上回っています ({actual} 対 {estimated}、{ratio} 倍)',
+ },
+ error: {
+ parseFailed: '実行計画の解析に失敗しました',
+ noPlan: 'データベースから実行計画が返されませんでした',
+ },
+ tabLabels: {
+ results: '結果',
+ explain: 'Explain',
+ },
+ analyzeToggle: 'EXPLAIN ANALYZE モードを切り替え (現在: {mode})',
+ columnHeaders: {
+ nodeType: 'ノードタイプ',
+ relation: 'リレーション',
+ index: 'インデックス',
+ cost: 'コスト',
+ rows: '行',
+ details: '詳細',
+ },
+ },
+ },
+ },
+ dataStudio: {
+ title: 'DATA STUDIO BETA',
+ subtitle: 'AI 搭載の SQL データ分析',
+ inputPlaceholder: 'データについて質問してください...',
+ modelUnavailable: '選択されたモデルは利用できません',
+ history: {
+ title: '履歴',
+ newSession: '新規セッション',
+ justNow: 'たった今',
+ minutesAgo: '{count}分前',
+ hoursAgo: '{count}時間前',
+ yesterday: '昨日',
+ noSessions: '以前のセッションはありません',
+ messages: '件のメッセージ',
+ sources: '件のソース',
+ delete: 'セッションを削除',
+ sessionFallback: 'チャット',
+ empty: 'セッションはまだありません',
+ },
+ agent: {
+ emptyState: '質問するか、実行したいクエリを説明してください。',
+ noSource: '開始するにはデータソースをアタッチしてください。',
+ stop: '停止',
+ continue: '続行',
+ continueHint: 'エージェントが一時停止しました。「続行」をクリックして再開するか、「停止」でセッションを終了してください。',
+ clearChat: 'チャットをクリア',
+ riskSafe: '安全な操作',
+ riskElevated: '中程度のリスク',
+ riskDestructive: '破壊的な操作',
+ allowOnce: '今回のみ許可',
+ allowAlways: '常に許可',
+ deny: '拒否',
+ denyAlways: '常に拒否',
+ cancelRun: 'キャンセル',
+ preparing: '準備中...',
+ thinking: '思考中',
+ iteration: 'ステップ',
+ waitingModel: 'モデルを待機中...',
+ compacting: 'コンテキストを圧縮中...',
+ viewFullResult: '完全な結果を表示',
+ viewMore: 'さらに表示',
+ message: {
+ toolBlocked: 'ブロックされました',
+ toolRejected: '拒否されました',
+ blockedNotice: '権限によりブロックされました — 操作は実行されませんでした',
+ historicalBlockedNotice: '以前の試行がブロックされました — 操作は実行されませんでした',
+ rejectedNotice: 'ユーザーにより拒否されました — 操作は実行されませんでした',
+ interruptedNotice: '実行結果を取得できません',
+ unavailableNotice: '操作が利用できないため実行されませんでした',
+ connectionLabel: '接続: {name}',
+ requiredAction: '必要な操作: {action}',
+ reviewPermissions: '権限を確認',
+ reviewHelp: '権限の変更を保存しても、ブロックされた操作は実行されません。チャットに戻り、準備ができたら「リクエストを再試行」を選択してください。',
+ reviewConnectionHelp: '変更はこの接続にのみ適用されます。システムのデフォルトは変更されません。保存してからチャットに戻り、リクエストを再試行してください。',
+ connectionUnavailable: '保存された接続を特定できませんでした。権限を確認する前に、チャットで接続を再アタッチしてください。',
+ backToChat: 'チャットに戻る',
+ retryRequest: 'リクエストを再試行',
+ retryPrompt: '以前ブロックまたは拒否されたリクエストを、{tool} を使って元の引数のまま再試行してください:\n{args}\n現在の権限を再確認し、必要な承認があれば要求してください。以前成功した操作は繰り返さないでください。',
+ awaitingPermissionDecision: '一時停止中。ブロックされた操作を確認し、再試行するか新しいリクエストを送信してください。',
+ removeDenyRule: '「常に拒否」ルールを削除',
+ ruleRemoved: 'ルールを削除しました。リクエストを再試行して、現在のアクセス権と承認要件を確認してください。',
+ sourceUnavailable: '元のデータソースはこの会話ではもう利用できません。再試行する前にアタッチしてください。',
+ denialSource: {
+ system: 'システムの AI デフォルトにより拒否されました。',
+ connection: 'この接続の AI 権限により拒否されました。',
+ conversation: 'この会話のソース制限により拒否されました。',
+ rule: '「常に拒否」ルールにより、この会話ではこのツールがブロックされています。',
+ unknown: 'AI 権限によりこの操作はブロックされました。再試行する前にアクセス権を確認してください。',
+ },
+ toolDenied: 'ツールの実行が拒否されました',
+ toolError: 'ツールの実行に失敗しました',
+ waitingForModel: 'モデルを待機中',
+ compactionInProgress: '会話を圧縮中',
+ preparingInProgress: '準備中',
+ thinkingInProgress: '思考中…',
+ thinkingDone: '思考完了',
+ thinkingDuration: '{s}秒',
+ generating: '生成中…',
+ awaitingConfirm: '{tool} の承認を待機中…',
+ executingTool: '{tool} を実行中…',
+ toolWrote: '書き込み',
+ toolRead: '読み取り',
+ toolExecuted: '実行',
+ toolSearched: '検索',
+ toolDeleted: '削除',
+ toolUpdated: '更新',
+ iterationLabel: 'ループ {n}',
+ compactionLabel: '会話を圧縮しました ({trigger})',
+ compactionSummary: 'サマリーを表示',
+ compactionTrigger: {
+ auto: '自動',
+ manual: '手動',
+ },
+ },
+ },
+ contextIndicator: {
+ offBadgeTitle: '自動圧縮はオフです — コンテキストは自動的に縮小されません',
+ popoverTitle: 'コンテキストウィンドウ',
+ warningText: '自動圧縮がオフのままコンテキストがしきい値を超えています。今すぐ圧縮しないと、次のリクエストが失敗する可能性があります。',
+ labelUsed: '使用済み',
+ labelCapacity: '容量',
+ labelWindow: 'ウィンドウ',
+ labelReservedOut: '出力予約',
+ labelAutoCompactAt: '自動圧縮のしきい値',
+ labelStatus: 'ステータス',
+ compactNow: '今すぐ圧縮',
+ compacting: '圧縮中…',
+ compactSuccess: 'コンテキストを圧縮しました',
+ compactFailed: '圧縮に失敗しました: {error}',
+ statusIdle: 'アイドル',
+ statusOverThresholdOff: 'しきい値超過 (自動圧縮オフ)',
+ statusAutoCompactOff: '自動圧縮オフ',
+ statusWillAutoCompact: '自動圧縮予定',
+ statusHealthy: '正常',
+ tooltipIdle: 'コンテキスト使用量',
+ tooltipAutoCompactOff: '自動圧縮オフ',
+ },
+ addSource: {
+ title: 'データソースを追加',
+ selectConnection: '接続を選択',
+ searchPlaceholder: '接続を検索...',
+ noConnections: '互換性のある接続が見つかりません',
+ allAttached: '互換性のある接続はすべてアタッチ済みです',
+ connectionsFound: '{count} 件の接続が見つかりました',
+ connectSource: '接続',
+ },
+ modifySource: {
+ title: 'データソースの変更',
+ accessPermissions: 'アクセス権限',
+ inheritTitle: '接続の権限を使用',
+ saveChanges: '変更を保存',
+ modeDefault: '確認',
+ modeFull: '自動',
+ },
+ detachSource: {
+ title: 'データソースの切断',
+ message: 'このデータソースを切断してもよろしいですか?Data Studio からこの接続が削除されます。',
+ confirm: '切断',
+ },
+ },
+ components: {
+ serverForm: {
+ basicTab: '基本',
+ advancedTab: '詳細',
+ title: {
+ edit: '接続を編集',
+ new: '新規接続',
+ },
+ description: {
+ edit: 'データベース接続の設定を更新します。',
+ new: '新しいデータベース接続を設定します。',
+ },
+ labels: {
+ connectionName: '接続名',
+ databaseType: 'データベースの種類',
+ host: 'ホスト',
+ databaseFilePath: 'データベースファイルのパス',
+ encryptionKey: '暗号化キー',
+ port: 'ポート',
+ database: 'データベース',
+ username: 'ユーザー名',
+ password: 'パスワード',
+ ssl: 'SSL/TLS 暗号化を使用',
+ sqliteMode: 'SQLite モード',
+ recentDatabases: '最近のデータベース',
+ },
+ placeholders: {
+ connectionName: 'マイデータベース',
+ selectType: 'データベースの種類を選択',
+ host: 'localhost',
+ filePath: '/path/to/database.db',
+ duckdbFilePath: '/path/to/database.duckdb or :memory:',
+ encryptionKey: '暗号化パスフレーズを入力',
+ database: 'database_name',
+ username: 'username',
+ password: '••••••••',
+ },
+ databaseTypes: {
+ 'postgresql': 'PostgreSQL',
+ 'sqlserver': 'SQL Server',
+ 'mysql': 'MySQL',
+ 'mariadb': 'MariaDB',
+ 'sqlite': 'SQLite',
+ 'sqlcipher': 'SQLCipher',
+ 'duckdb': 'DuckDB',
+ 'clickhouse': 'ClickHouse',
+ 'cockroachdb': 'CockroachDB',
+ 'redshift': 'Amazon Redshift',
+ 'yugabytedb': 'YugabyteDB',
+ 'timescaledb': 'TimescaleDB',
+ 'kingbasees': '人大金仓 (KingbaseES)',
+ 'gaussdb': '华为 GaussDB',
+ 'highgo': '瀚高数据库 (HighGo DB)',
+ 'uxdb': '优炫数据库 (UXDB)',
+ 'opengauss': 'openGauss',
+ 'gbase8c': '南大通用 GBase 8c',
+ 'questdb': 'QuestDB',
+ 'vastbase': 'Vastbase (海量数据库)',
+ 'yashandb': 'YashanDB (崖山数据库)',
+ 'tidb': 'TiDB',
+ 'oceanbase': 'OceanBase',
+ 'oceanbase-oracle': 'OceanBase Oracle',
+ 'tdsql': 'TDSQL',
+ 'polardb': 'PolarDB',
+ 'dameng': '达梦 Dameng',
+ 'doris': 'Apache Doris',
+ 'selectdb': 'SelectDB',
+ 'starrocks': 'StarRocks',
+ 'databend': 'Databend',
+ 'goldendb': 'GoldenDB',
+ 'manticore': 'Manticore Search',
+ 'oracle': 'Oracle',
+ 'db2': 'IBM Db2',
+ 'h2': 'H2',
+ 'snowflake': 'Snowflake',
+ 'xugudb': '虚谷数据库 (XuguDB)',
+ 'gbase8a': '南大通用 GBase 8a',
+ 'trino': 'Trino',
+ 'presto': 'Presto',
+ 'derby': 'Apache Derby',
+ 'hive': 'Apache Hive',
+ 'databricks': 'Databricks SQL',
+ 'hana': 'SAP HANA',
+ 'teradata': 'Teradata',
+ 'vertica': 'Vertica',
+ 'exasol': 'Exasol',
+ 'bigquery': 'Google BigQuery',
+ 'informix': 'IBM Informix',
+ 'kylin': 'Apache Kylin',
+ 'cassandra': 'Apache Cassandra',
+ 'iris': 'InterSystems IRIS',
+ 'access': 'Microsoft Access',
+ 'firebird': 'Firebird',
+ 'rqlite': 'RQLite',
+ 'turso': 'Turso (libSQL)',
+ 'tdengine': 'TDengine',
+ },
+ oracle: {
+ connectionMethod: '接続方法',
+ methods: {
+ basic: 'Basic (Host:Port)',
+ tns: 'TNS (tnsnames.ora)',
+ cloudWallet: 'Cloud Wallet (ATP/ADW)',
+ },
+ identifyBy: '識別方式',
+ sid: 'SID',
+ serviceName: 'サービス名',
+ role: 'ロール',
+ roles: {
+ normal: 'NORMAL',
+ sysdba: 'SYSDBA',
+ sysoper: 'SYSOPER',
+ },
+ tnsAdminDir: 'TNS_ADMIN ディレクトリ',
+ tnsAlias: 'TNS エイリアス',
+ walletDir: 'ウォレットディレクトリ',
+ walletPassword: 'ウォレットパスワード',
+ serviceLevel: 'サービスレベル',
+ serviceLevels: {
+ low: 'Low (バッチ)',
+ medium: 'Medium (標準)',
+ high: 'High (クリティカル)',
+ tp: 'TP (トランザクション)',
+ tpurgent: 'TP_URGENT (優先)',
+ },
+ browse: '参照...',
+ noAliases: 'TNS エイリアスが見つかりません',
+ tnsSelectDir: 'エイリアスを読み込む TNS ディレクトリを選択してください',
+ walletSelectDir: 'エイリアスを読み込むウォレットディレクトリを選択してください',
+ loadingAliases: 'エイリアスを読み込み中...',
+ },
+ buttons: {
+ create: '新規...',
+ open: '開く...',
+ },
+ fileStatus: {
+ willCreate: 'ファイルはまだ存在しません — 接続時に {engine} が作成します。',
+ missingParent: '親フォルダが存在しません。',
+ createDirectory: 'フォルダを作成',
+ createDirectoryFailed: 'フォルダの作成に失敗しました',
+ unwritable: 'このパスへの書き込み権限がありません。',
+ directory: 'このパスはフォルダです。データベースファイルを選択してください。',
+ empty: 'ファイルが空です (0 バイト)。',
+ ready: 'ファイルが存在します ({size})',
+ storageVersion: 'ストレージフォーマット {storage} (DuckDB {version} 以降で開きます)',
+ storageVersionUnknown: 'ストレージフォーマット {storage} — このビルドが認識しているより新しいため、おそらくより新しい DuckDB によって書かれています。',
+ writeAheadLog: 'ライトアヘッドログ (.wal) が存在します。接続時に再生されます。',
+ unsupportedPath: 'DuckDB は \';\' を含むパスを開けません。ファイル名を変更して再試行してください。',
+ wrongFormat: 'これは {format} ファイルのようです。{engine} データベースではありません。',
+ unknownFormat: 'その他の形式',
+ reveal: 'フォルダで表示',
+ revealFailed: 'ファイルを表示できませんでした',
+ removeRecent: '最近のリストから削除',
+ },
+ duckdb: {
+ accessMode: 'アクセスモード',
+ readWrite: '読み書き',
+ readWriteHint: 'DuckDB はファイルに対して排他ロックを保持します。書き込めるプロセスは 1 つだけです。',
+ readOnly: '読み取り専用',
+ readOnlyHint: '他の DuckDB プロセスが同じファイルを同時に読み取ることを許可します。',
+ conflictingConnection: '"{name}" が既に異なるアクセスモードでこのファイルを開いているため、DuckDB は異なる設定での 2 つ目の接続を拒否します。',
+ openReadOnly: '読み取り専用で開く',
+ switchToConnection: 'その接続に切り替える',
+ sharedConnection: '"{name}" は同じファイルと設定を使用しているため、両方の接続が 1 つの DuckDB インスタンスを共有します。',
+ engineVersion: 'エンジンバージョン {version}',
+ retryReadOnly: '読み取り専用で再試行',
+ retryReadWrite: '読み書きで再試行',
+ inMemoryHint: 'インメモリデータベースは一時的なもので、接続を閉じると失われます。ファイルに保存する前にデータを調べるのに便利です。',
+ inMemoryInstance: 'インスタンス',
+ inMemorySharedHint: '名前付きインメモリインスタンスはすべてのプールされた接続で共有されるため、あるクエリで作成したテーブルは次のクエリでも表示されます。',
+ },
+ duckdbFailures: {
+ 'read-only-unsupported': 'インストール済みの JDBC ブリッジはまだ読み取り専用でデータベースを開けません (DuckDB は接続ごとのモード変更を拒否します)。読み書きモードで再試行するか、設定でブリッジを更新してください。',
+ 'storage-version': 'このファイルは使用中のエンジンより新しい DuckDB によって書かれたため、開けません。新しいバージョンでエクスポート (EXPORT DATABASE) して再度インポートするか、DuckDB ドライバーを更新してください。',
+ 'config-conflict': '別の接続が既に異なる設定 (読み取り専用 vs 読み書き、または異なる初期化) でこのファイルを開いています。DuckDB は 2 つ目の設定を拒否します。',
+ 'lock-conflict': '別のプロセスがこのファイルの書き込みロックを保持しています (duckdb CLI、Python、または別の SQLKit 接続)。読み取り専用で開くか、他のプログラムを閉じてください。',
+ 'unsupported-url': 'このパスは DuckDB の JDBC ドライバーに渡せません。ファイル名を変更して再試行してください。',
+ 'extension': 'DuckDB 拡張機能を読み込めなかったか、ダウンロードできませんでした。ネットワーク接続を確認するか、拡張機能を事前にインストールしてください。',
+ 'read-only-file': 'データベースファイルまたはそのフォルダが読み取り専用のため、DuckDB は書き込めません。ファイルの権限を変更するか、読み取り専用で開いてください。',
+ 'missing-file': 'データベースファイルが存在せず、作成もできませんでした。パスとフォルダの権限を確認してください。',
+ },
+ sqlite: {
+ modes: {
+ file: 'ファイル',
+ inMemory: 'インメモリ',
+ },
+ recentEmpty: '最近のデータベースはありません',
+ ago: '{time}前',
+ inMemoryHint: 'インメモリデータベースは一時的なもので、接続を閉じると失われます。テストや一時データに便利です。',
+ pathStatus: {
+ valid: 'ファイルが存在します',
+ notFound: 'ファイルが見つかりません',
+ noPermission: '書き込み権限がありません',
+ },
+ },
+ errors: {
+ nameRequired: '接続名は必須です',
+ hostRequired: 'ホストは必須です',
+ databaseRequired: 'SID / サービス名は必須です',
+ databaseNameRequired: 'データベース名は必須です',
+ filePathRequired: 'データベースファイルのパスは必須です',
+ portInvalid: 'ポートは正の数である必要があります',
+ filePickerFailed: 'ファイルピッカーを開けませんでした',
+ tnsAdminDirRequired: 'TNS_ADMIN ディレクトリは必須です',
+ tnsAliasRequired: 'TNS エイリアスは必須です',
+ },
+ ssh: {
+ newProfile: '新規プロファイル',
+ hopOrderHint: 'ホップは順に試行されます — 最後のホップがデータベースへフォワードします。システムプロキシは最初のホップにのみ適用されます。',
+ importFromConfig: '~/.ssh/config からインポート',
+ profileName: 'プロファイル名',
+ profileNamePlaceholder: '例: 本番バスティオン',
+ editProfile: 'SSH プロファイルを編集',
+ useSshTunnel: 'SSH トンネル',
+ ultimateOnly: 'SSH トンネルは Ultimate 機能です',
+ tunnelSkippedHint: 'SSH トンネルは Ultimate 機能です: Community または未ログインのセッションでは、この接続に保存されたトンネルがスキップされるため、このテストは直接接続に対して実行されました。',
+ systemProxy: 'システムプロキシ',
+ systemProxyDetected: 'システムプロキシを検出: {url}',
+ systemProxyAdd: '追加',
+ systemProxyDetach: 'システムプロキシを切り離す',
+ systemProxyNotDetected: 'システムプロキシが有効ですが、検出されませんでした。直接接続します。',
+ detachAction: 'チェーンから切り離す',
+ moveUp: 'ホップを上へ移動',
+ moveDown: 'ホップを下へ移動',
+ hops: 'ホップ | ホップ',
+ addProfilePlaceholder: 'プロファイルを追加…',
+ searchProfilePlaceholder: 'プロファイルを検索…',
+ testChain: 'トンネルの接続をテスト',
+ testFirstHop: '最初のホップをテスト (後続のホップは検証されません)',
+ testDisabledHint: '必須フィールドが不足しているか、設定が無効です',
+ testReturnedNotConnected: '接続結果が「未接続」でした',
+ jreBroken: 'JRE が存在しないか破損しています',
+ stepFailed: '失敗',
+ testTimedOut: 'テストがタイムアウトしました (30秒) — バスティオンに到達できないか、SSH ハンドシェイクが停止しています',
+ testSuccess: '{user}{\'@\'}{host}:{port} に接続しました',
+ notConfigured: 'SSH トンネルが未設定です — 開始するにはプロファイルを追加してください',
+ editTunnel: 'SSH トンネルを編集',
+ connectionOnly: '変更はこの接続にのみ適用されます。',
+ convertHint: 'ホップの追加や並べ替えを行うには、再利用可能なプロファイルに変換してください。',
+ noConfigHosts: '~/.ssh/config に SSH ホストが見つかりません。',
+ convertToProfile: 'プロファイルに変換',
+ convertedProfileName: '手動 ({host})',
+ sshHost: 'SSH ホスト',
+ sshPort: 'SSH ポート',
+ username: 'ユーザー名',
+ authMethod: '認証方式',
+ password: 'パスワード',
+ privateKey: '秘密鍵',
+ sshAgent: 'SSH エージェント',
+ sshPassword: 'SSH パスワード',
+ privateKeyPath: '秘密鍵のパス',
+ passphraseOptional: 'パスフレーズ (任意)',
+ agentSockPath: 'エージェントソケットパス',
+ agentHelpText: 'システムの SSH エージェントを使用します - 追加設定は不要です。',
+ },
+ },
+ serverCard: {
+ actions: {
+ connect: '接続',
+ openEditor: 'エディターで開く',
+ closeConnection: '接続を閉じる',
+ edit: '編集',
+ duplicate: '複製',
+ delete: '削除',
+ },
+ strategy: {
+ nativeTooltip: 'ネイティブ Rust ドライバーによる直接接続 — 最高のパフォーマンス、外部依存なし',
+ jdbcBridgeTooltip: '組み込み Java ランタイム経由で JDBC ドライバーに接続 — 最も幅広いデータベース互換性',
+ httpBridgeTooltip: 'HTTP SQL プロトコル経由で接続 — REST ベースのデータベース向け',
+ },
+ },
+ connectingModal: {
+ connecting: '{name} に接続中...',
+ connectingSubtext: '接続を確立しています。しばらくお待ちください',
+ connectionError: '接続エラー',
+ sshTunnelSkipped: 'SSH トンネルは Ultimate 機能です: Community または未ログインのセッションでは、この接続に保存されたトンネルをスキップして直接接続します (設定自体は保持されます)。',
+ sshTunnelStripped: 'この接続に保存されたトンネルは今回の試行ではスキップされました (Ultimate 機能であり、Community または未ログインのため)。データベースへの到達がそのトンネル経由に限られる場合は、Ultimate にアップグレードしてください。',
+ },
+ databaseBrowser: {
+ title: 'データベースブラウザー',
+ search: 'テーブルを検索...',
+ refresh: '更新',
+ newQuery: '新規クエリ',
+ loading: '読み込み中...',
+ empty: 'データベースが見つかりません。先にサーバーに接続してください。',
+ selectDatabase: 'データベースを選択',
+ selectSchema: 'スキーマを選択',
+ databases: 'データベース',
+ current: '現在',
+ userDatabases: 'ユーザーデータベース',
+ systemDatabases: 'システムデータベース',
+ noTables: 'テーブルが見つかりません',
+ noViews: 'ビューが見つかりません',
+ noProcedures: 'プロシージャが見つかりません',
+ noFunctions: '関数が見つかりません',
+ noSavedQueries: '保存されたクエリはまだありません',
+ comingSoon: '近日提供予定',
+ sections: {
+ tables: 'テーブル',
+ views: 'ビュー',
+ procedures: 'プロシージャ',
+ functions: '関数',
+ savedQueries: '保存されたクエリ',
+ },
+ errors: {
+ fetchDatabases: 'データベースの取得に失敗しました',
+ fetchSchemas: 'スキーマの取得に失敗しました',
+ fetchTables: 'テーブルの取得に失敗しました',
+ invalidResponse: 'サーバーから無効なレスポンスが返されました',
+ },
+ contextMenu: {
+ viewData: 'データを表示',
+ selectTopN: '先頭 100 件を取得',
+ viewStructure: '構造を表示',
+ createScript: 'CREATE スクリプト',
+ exportData: 'データをエクスポート',
+ showErDiagram: 'ER 図を表示',
+ dropTable: 'テーブルを DROP',
+ truncateTable: 'TRUNCATE',
+ newQuery: '新規クエリ',
+ refresh: '更新',
+ },
+ savedQueryActions: {
+ open: '開く',
+ delete: '削除',
+ reveal: 'Finder で表示',
+ },
+ erDiagram: {
+ title: 'ER 図',
+ viewMode: '表示',
+ zoom: '{percentage}%',
+ zoomIn: 'ズームイン',
+ zoomOut: 'ズームアウト',
+ allSchemas: 'すべてのスキーマ',
+ engineeringView: 'エンジニアリングビュー',
+ fitToScreen: '画面に合わせる',
+ searchPlaceholder: 'テーブルを絞り込み...',
+ tablesCountBadge: '{count} テーブル',
+ tableView: 'テーブルビュー',
+ relationshipsCountBadge: '{count} リレーションシップ',
+ resetLayout: 'レイアウトをリセット',
+ largeSchemaWarning: 'このスキーマには {count} 個のテーブルがあります。すべて表示すると表示が混雑する可能性があります。続行しますか?',
+ showAllColumns: 'すべての列を表示 ({count})',
+ hideExtraColumns: '表示を減らす',
+ noForeignKeys: '外部キーリレーションシップが見つかりません',
+ openTable: 'テーブルデータを開く',
+ layoutDirection: 'レイアウト',
+ layoutTopBottom: '上 → 下',
+ layoutLeftRight: '左 → 右',
+ loading: 'スキーマリレーションを読み込み中...',
+ },
+ },
+ listingTab: {
+ views: 'ビュー',
+ procedures: 'プロシージャ',
+ functions: '関数',
+ searchPlaceholder: '名前で検索...',
+ name: '名前',
+ detail: '詳細',
+ ddl: 'DDL',
+ actions: '操作',
+ viewDdl: 'DDL を表示',
+ drop: 'DROP',
+ rename: '名前を変更',
+ copyName: '名前をコピー',
+ copyDdl: 'DDL をコピー',
+ dropDialogTitle: 'オブジェクトを DROP',
+ dropDialogDescription: '{name} を DROP してもよろしいですか?',
+ confirmDrop: 'DROP',
+ renameDialogTitle: 'オブジェクトの名前を変更',
+ renameDialogDescription: '{name} の新しい名前を入力してください:',
+ newNamePlaceholder: '新しい名前',
+ confirmRename: '名前を変更',
+ noResults: '検索に一致するオブジェクトはありません',
+ empty: 'オブジェクトが見つかりません',
+ },
+ schemaTab: {
+ column: '列',
+ type: '型',
+ nullable: 'NULL 許可',
+ default: 'デフォルト',
+ key: 'キー',
+ autoIncrement: '自動採番',
+ yes: 'YES',
+ no: 'NO',
+ pk: 'PK',
+ },
+ indexesTab: {
+ name: '名前',
+ columns: '列',
+ type: '型',
+ unique: 'ユニーク',
+ primary: 'プライマリ',
+ empty: 'インデックスが見つかりません',
+ yes: 'YES',
+ no: 'NO',
+ },
+ foreignKeysTab: {
+ constraint: '制約',
+ columns: '列',
+ references: '参照先',
+ onUpdate: 'ON UPDATE',
+ onDelete: 'ON DELETE',
+ empty: '外部キーが見つかりません',
+ },
+ triggersTab: {
+ name: '名前',
+ timing: 'タイミング',
+ event: 'イベント',
+ ddl: 'DDL',
+ viewDdl: 'DDL を表示',
+ empty: 'トリガーが見つかりません',
+ },
+ queryResult: {
+ title: '結果',
+ selectResult: '結果セットを選択',
+ resultSet: '結果 {index} / {count}',
+ exportActions: '結果のコピーとエクスポート',
+ scriptReadOnly: 'スクリプトの結果は読み取り専用です。ソートは返された行に適用されます。',
+ rows: '{count} 行',
+ rowsAffected: '{count} 行が影響を受けました',
+ time: '{time}',
+ close: '閉じる',
+ executing: 'クエリを実行中...',
+ error: 'クエリエラー',
+ success: 'クエリが正常に実行されました',
+ noData: 'データが返されませんでした',
+ commandCompleted: 'コマンドが完了しました',
+ noResults: 'クエリを実行すると結果が表示されます',
+ },
+ dataTableView: {
+ searchPlaceholder: 'すべての列を検索...',
+ clearSearch: '検索をクリア',
+ filterPlaceholder: 'フィルター (SQL WHERE 句、例: age > 18 AND status = \'active\')',
+ clearFilter: 'フィルターをクリア',
+ refresh: '更新',
+ columns: '列',
+ exportCsv: '現在のページをエクスポート (CSV)',
+ applyFilters: 'フィルターを適用',
+ loading: 'テーブルデータを読み込み中...',
+ error: 'テーブルデータの読み込みに失敗しました',
+ connectionLost: '接続が切断されました。データベースへの接続が閉じられました。',
+ reconnecting: '再接続中...',
+ reconnect: '再接続',
+ noRows: '行が見つかりません',
+ rows: '行',
+ columnsCount: '{count} 列',
+ indexesCount: '{count} インデックス',
+ foreignKeysCount: '{count} 外部キー',
+ triggersCount: '{count} トリガー',
+ page: '{total} ページ中 {page} ページ目',
+ rowsPerPage: '1 ページあたりの行数:',
+ actions: '操作',
+ editRow: '行を編集',
+ deleteRow: '行を削除',
+ notifications: {
+ csvExported: 'CSV をエクスポートしました',
+ exportFailed: 'エクスポートに失敗しました',
+ rowDeleted: '行を削除しました',
+ deleteFailed: '行の削除に失敗しました',
+ rowUpdated: '行を更新しました',
+ updateFailed: '行の更新に失敗しました',
+ noPrimaryKey: '主キーが検出されません',
+ noPrimaryKeyDesc: 'このテーブルには主キーがありません。すべての列で行を特定します。',
+ fallbackAllColumns: '主キーがないため、すべての列で行を特定します。注意して編集してください。',
+ },
+ deleteDialog: {
+ title: '行の削除',
+ message: 'この行を削除してもよろしいですか?この操作は元に戻せません。',
+ confirm: '削除',
+ },
+ editDialog: {
+ title: '行を編集',
+ },
+ validation: {
+ required: 'この項目は必須です',
+ invalidNumber: '有効な数値を入力してください',
+ invalidBoolean: 'true または false を入力してください',
+ },
+ },
+ queryTabs: {
+ unsaved: '未保存の変更',
+ orphan: 'このタブは別の接続に属しています',
+ new: '新規クエリ',
+ closeDialog: {
+ title: '未保存の変更',
+ message: 'クエリ "{name}" には未保存の変更があります。破棄しますか?',
+ discard: '破棄',
+ },
+ },
+ header: {
+ appName: 'SQLKit',
+ },
+ sqlEditor: {
+ execute: '実行',
+ format: 'フォーマット',
+ copy: 'コピー',
+ },
+ destructiveDialog: {
+ deleteRow: {
+ title: '削除の確認',
+ message: 'テーブル "{table}" から {count} 行を削除しますか?',
+ detail: 'この操作は元に戻せません。',
+ confirm: '削除',
+ },
+ dropTable: {
+ title: 'テーブルを DROP',
+ message: 'テーブル "{table}" を DROP しますか?',
+ detail: 'テーブルとそのすべてのデータが完全に削除されます。この操作は元に戻せません。',
+ confirm: 'DROP',
+ },
+ truncateTable: {
+ title: 'テーブルを TRUNCATE',
+ message: 'テーブル "{table}" を TRUNCATE しますか?',
+ detail: '{count} 行すべてが削除されます。この操作は元に戻せません。',
+ confirm: 'TRUNCATE',
+ },
+ deleteConnection: {
+ title: '接続の削除',
+ message: '接続 "{name}" を削除しますか?',
+ detail: '保存された接続設定が削除されます。アクティブな接続は切断されます。',
+ confirm: '削除',
+ },
+ deleteProfile: {
+ title: 'SSH プロファイルの削除',
+ message: 'プロファイル "{name}" を削除しますか?',
+ detail: 'プロファイルは共有プロファイルライブラリから削除されます。このバスティオン経由で接続している接続は、このバスティオンを利用できなくなります。',
+ inUse: 'このプロファイルは {count} 個の接続で使用されています: {names}。それらの接続はこのプロファイルから切り離されます。',
+ confirm: '削除',
+ },
+ },
+ pagination: {
+ label: 'ページネーション',
+ showingWithoutTotal: '{start}–{end} 行を表示 · 合計は利用できません',
+ rowsPerPage: '1 ページあたりの行数',
+ pageSize: '{count} 行/ページ',
+ customSize: 'カスタム行数/ページ',
+ apply: '適用',
+ showAll: '返されたすべての行を表示',
+ allRows: '返されたすべての行',
+ firstPage: '最初のページ',
+ previousPage: '前のページ',
+ nextPage: '次のページ',
+ lastPage: '最後のページ',
+ goToPage: 'ページへ移動',
+ pageCount: '{count} ページ中',
+ sortScope: 'ソートは現在のページに適用されます',
+ },
+ dataGrid: {
+ sort: {
+ asc: '昇順でソート',
+ desc: '降順でソート',
+ clear: 'ソートをクリア',
+ unsortable: 'この列の型はソートできません',
+ },
+ filter: {
+ byValue: '値でフィルター',
+ byLike: 'Like でフィルター',
+ greaterThan: 'フィルター >=',
+ lessThan: 'フィルター <=',
+ between: '範囲でフィルター',
+ excludeValue: '値を除外',
+ clearFilter: 'フィルターをクリア',
+ clearAll: 'すべてのフィルターをクリア',
+ activeFilters: 'フィルター',
+ },
+ row: {
+ edit: '行を編集',
+ delete: '行を削除',
+ duplicate: '行を複製',
+ details: '行の詳細',
+ copyAsCsv: '行を CSV としてコピー',
+ copyAsJson: '行を JSON としてコピー',
+ copyAsInsert: '行を INSERT としてコピー',
+ actions: '操作',
+ noTableContext: 'クエリ結果がテーブルに紐付いていないため、行の編集や削除はできません',
+ editUnsupported: {
+ 'not-select': 'このステートメントは SELECT クエリではないため、結果の行は編集・削除できません',
+ 'cte': 'クエリが WITH (CTE) を使用しているため、行をテーブルにマッピングできず、編集はサポートされません',
+ 'set-operation': 'クエリが UNION/INTERSECT/EXCEPT を使用しているため、行は複数のステートメントに由来し、編集はサポートされません',
+ 'aggregation': 'クエリが集計 (GROUP BY/DISTINCT/集計関数) を使用しているため、行をベースの行にマッピングできず、編集はサポートされません',
+ 'multiple-sources': 'クエリが複数のテーブルを結合しているため、行の編集や削除はできません',
+ 'no-table': 'クエリに FROM テーブルがないため、行の編集や削除はできません',
+ 'complex-source': 'クエリのソースがサブクエリまたは複雑な式のため、行の編集や削除はできません',
+ },
+ },
+ cell: {
+ copyValue: 'セルの値をコピー',
+ copyRow: '行をコピー',
+ filterByValue: 'この値でフィルター',
+ excludeValue: 'この値を除外',
+ },
+ selection: {
+ selected: '{count} 行を選択中',
+ editSelected: '選択した行を編集',
+ deleteSelected: '選択した行を削除',
+ exportSelected: '選択した行をエクスポート',
+ },
+ status: {
+ showing: '{total} 行中 {start}–{end} 行を表示',
+ showingLimited: '{loaded} 行中 {start}–{end} 行を表示 (制限あり)',
+ time: '· {time}',
+ },
+ empty: '結果がありません',
+ error: {
+ title: 'データの読み込みエラー',
+ retry: '再試行',
+ },
+ loading: 'データを読み込み中...',
+ edit: {
+ title: '行を編集',
+ duplicateTitle: '行を複製',
+ nullToggle: 'NULL に設定',
+ pkReadonly: '主キー (読み取り専用)',
+ save: '保存',
+ cancel: 'キャンセル',
+ saving: '保存中...',
+ confirmCancel: '変更を破棄しますか?',
+ confirmCancelMessage: '未保存の変更があります。閉じてもよろしいですか?',
+ discard: '破棄',
+ validation: {
+ required: 'この項目は必須です',
+ invalidNumber: '有効な数値を入力してください',
+ invalidBoolean: 'true または false を入力してください',
+ },
+ },
+ details: {
+ title: '行の詳細',
+ },
+ delete: {
+ title: '行の削除',
+ message: 'この行を削除してもよろしいですか?',
+ detail: 'この操作は元に戻せません。',
+ confirm: '削除',
+ batchTitle: '選択した行の削除',
+ batchMessage: '選択した {count} 行を削除してもよろしいですか?',
+ batchDetail: 'この操作は元に戻せません。',
+ },
+ export: {
+ copyAllCsv: 'すべてを CSV としてコピー',
+ copyAllJson: 'すべてを JSON としてコピー',
+ copyAllInsert: 'すべてを INSERT としてコピー',
+ exportCsv: 'CSV をエクスポート',
+ exportJson: 'JSON をエクスポート',
+ exportInsert: 'INSERT をエクスポート',
+ copied: 'クリップボードにコピーしました',
+ exported: 'ファイルをエクスポートしました',
+ formatLabels: {
+ csv: 'CSV',
+ json: 'JSON',
+ insert: 'INSERT',
+ },
+ },
+ json: {
+ expand: '展開',
+ title: 'JSON ビューアー',
+ copy: 'JSON をコピー',
+ },
+ blob: {
+ label: '[BLOB {size}]',
+ },
+ null: '(NULL)',
+ rowNumber: '#',
+ },
+ },
+ updater: {
+ updateAvailable: 'アップデートが利用可能です',
+ newVersion: 'バージョン {version} が利用可能です',
+ upToDate: '最新バージョンを使用しています',
+ checkFailed: 'アップデートの確認に失敗しました',
+ downloading: 'アップデートをダウンロード中...',
+ installing: 'アップデートをインストール中...',
+ installFailed: 'アップデートのインストールに失敗しました',
+ skip: 'このバージョンをスキップ',
+ later: '後で',
+ updateNow: '今すぐアップデート',
+ restarting: '再起動中...',
+ downloadingPercent: '{percent}% をダウンロード中',
+ relaunchFailed: 'アップデート後の再起動に失敗しました',
+ retry: '再試行',
+ installFailedHelp: 'F12 キーを押してデベロッパーツールを開き、エラーの詳細を確認してください。',
+ },
+ errors: {
+ unexpected: '予期しないエラー: {error}',
+ codes: {
+ // Connection errors
+ CONNECTION_FAILED: 'データベースに接続できませんでした',
+ CONNECTION_TIMEOUT: '接続タイムアウト',
+ CONNECTION_REFUSED: '接続が拒否されました',
+ AUTHENTICATION_FAILED: '認証に失敗しました',
+
+ // Query errors
+ QUERY_SYNTAX_ERROR: 'SQL 構文エラー',
+ QUERY_EXECUTION_ERROR: 'クエリの実行に失敗しました',
+ QUERY_TIMEOUT: 'クエリの実行がタイムアウトしました',
+
+ // Resource errors
+ DATABASE_NOT_FOUND: 'データベースが見つかりません',
+ TABLE_NOT_FOUND: 'テーブルが存在しません',
+ COLUMN_NOT_FOUND: '列が存在しません',
+
+ // Permission errors
+ PERMISSION_DENIED: '権限が拒否されました',
+ INSUFFICIENT_PRIVILEGES: '十分な権限がありません',
+
+ // Data errors
+ CONSTRAINT_VIOLATION: '制約違反です',
+ FOREIGN_KEY_VIOLATION: '外部キー制約に違反しています',
+ UNIQUE_VIOLATION: '一意制約に違反しています',
+ NOT_NULL_VIOLATION: 'NOT NULL 制約に違反しています',
+ CHECK_VIOLATION: 'CHECK 制約に違反しています',
+
+ // System errors
+ INTERNAL_ERROR: '内部エラー',
+ UNSUPPORTED_OPERATION: 'サポートされていない操作です',
+ INVALID_CONFIGURATION: '設定が無効です',
+ },
+ titles: {
+ CONNECTION_FAILED: '接続に失敗しました',
+ AUTHENTICATION_FAILED: '認証に失敗しました',
+ QUERY_SYNTAX_ERROR: 'SQL 構文エラー',
+ QUERY_EXECUTION_ERROR: 'クエリ実行エラー',
+ TABLE_NOT_FOUND: 'テーブルが見つかりません',
+ COLUMN_NOT_FOUND: '列が見つかりません',
+ PERMISSION_DENIED: '権限が拒否されました',
+ FOREIGN_KEY_VIOLATION: '外部キー制約違反',
+ UNIQUE_VIOLATION: '一意制約違反',
+ NOT_NULL_VIOLATION: 'NOT NULL 制約違反',
+ },
+ hints: {
+ CONNECTION_FAILED: '接続設定を確認し、データベースサーバーが起動していることを確認してください',
+ AUTHENTICATION_FAILED: 'ユーザー名とパスワードを確認してください',
+ QUERY_SYNTAX_ERROR: 'SQL 構文を確認して再試行してください',
+ QUERY_TIMEOUT: 'クエリの最適化を試みるか、タイムアウト上限を増やしてください',
+ DATABASE_NOT_FOUND: 'データベースが存在し、アクセス権があることを確認してください',
+ TABLE_NOT_FOUND: 'テーブル名を確認し、データベースに存在することを確認してください',
+ COLUMN_NOT_FOUND: '列名がテーブルのスキーマと一致していることを確認してください',
+ FOREIGN_KEY_VIOLATION: '参照されるレコードが親テーブルに存在することを確認してください',
+ UNIQUE_VIOLATION: 'この値を持つレコードは既に存在します',
+ NOT_NULL_VIOLATION: 'この項目には値が必要です',
+ CHECK_VIOLATION: '値がテーブルの制約を満たしていません',
+ PERMISSION_DENIED: 'この操作に必要な権限がありません',
+ },
+ },
+ sidebar: {
+ connection: {
+ placeholder: '接続を選択',
+ connected: '接続済み',
+ lost: '接続が切断されました',
+ disconnected: '切断されました',
+ connecting: '接続中...',
+ },
+ database: {
+ placeholder: 'すべてのデータベース',
+ selectDatabase: 'データベースを選択',
+ refresh: '更新',
+ refreshTooltip: 'データベース一覧を再読み込み',
+ },
+ databases: {
+ actions: {
+ createObject: {
+ title: '{type} を作成',
+ placeholder: '{type} 名を入力',
+ cancel: 'キャンセル',
+ confirm: '作成',
+ created: '{type} "{name}" を作成しました',
+ error: '作成に失敗しました: {error}',
+ types: {
+ database: 'データベース',
+ schema: 'スキーマ',
+ },
+ },
+ createDatabase: {
+ title: 'データベースを作成',
+ name: 'データベース名',
+ namePlaceholder: 'データベース名を入力',
+ charset: '文字セット',
+ collation: '照合順序',
+ collationPlaceholder: '例: utf8mb4_unicode_ci',
+ encoding: 'エンコーディング',
+ locale: 'ロケール / LC_COLLATE',
+ localePlaceholder: '例: en_US.UTF-8',
+ optional: '任意',
+ cancel: 'キャンセル',
+ confirm: '作成',
+ },
+ dropDatabase: {
+ title: 'データベースを DROP',
+ message: '"{name}" を DROP してもよろしいですか?この操作は元に戻せません。',
+ typeToConfirm: '確認のためデータベース名を入力してください:',
+ cancel: 'キャンセル',
+ confirm: 'DROP',
+ success: 'データベース "{name}" を DROP しました',
+ error: 'データベースの DROP に失敗しました: {error}',
+ },
+ createTable: {
+ title: 'テーブルを作成',
+ tableName: 'テーブル名',
+ tableNamePlaceholder: 'テーブル名を入力',
+ engine: 'エンジン',
+ columns: '列',
+ addColumn: '列を追加',
+ colName: '名前',
+ colType: '型',
+ colLength: '長さ',
+ colAutoInc: 'AI',
+ colDefault: 'デフォルト',
+ lengthPlaceholder: '255',
+ defaultPlaceholder: 'NULL',
+ preview: 'SQL プレビュー',
+ cancel: 'キャンセル',
+ create: '作成',
+ opened: 'テーブルの SQL がエディターで開かれました。実行するとテーブルが作成されます。',
+ },
+ templateOpened: '{type} の新規テンプレートがエディターで開かれました。',
+ },
+ },
+ actionMenu: {
+ label: 'データベース操作',
+ createScript: 'CREATE スクリプト',
+ newDatabase: '新規データベース',
+ newSchema: '新規スキーマ',
+ newTable: '新規テーブル',
+ newView: '新規ビュー',
+ newFunction: '新規関数',
+ newProcedure: '新規プロシージャ',
+ showErDiagram: 'ER 図',
+ backupDatabase: 'データベースをバックアップ',
+ exportDatabase: 'データベースをエクスポート',
+ dropDatabase: 'データベースを DROP',
+ },
+ groups: {
+ tables: 'テーブル',
+ views: 'ビュー',
+ procedures: 'プロシージャ',
+ functions: '関数',
+ },
+ loading: '読み込み中...',
+ empty: 'データベースが選択されていません。参照するには選択してください。',
+ noObjects: 'オブジェクトが見つかりません',
+ noDatabases: 'データベースが見つかりません。先にサーバーに接続してください。',
+ search: 'テーブルやビューを検索...',
+ savedQueries: {
+ header: '保存されたクエリ',
+ expand: '保存されたクエリを展開',
+ collapse: '保存されたクエリを折りたたむ',
+ newQuery: '新規クエリ',
+ empty: '保存されたクエリはまだありません',
+ created: '作成日時',
+ modified: '更新日時',
+ connectionNone: 'ターゲット接続なし',
+ actions: {
+ open: '開く',
+ rename: '名前を変更',
+ changeConnection: 'ターゲット接続を変更',
+ reveal: 'ファイルマネージャーで表示',
+ delete: '削除',
+ },
+ delete: {
+ title: '保存されたクエリを削除しますか?',
+ description: '"{name}" を削除してもよろしいですか?この操作は元に戻せません。',
+ cancel: 'キャンセル',
+ confirm: '削除',
+ target: 'ターゲット',
+ created: '作成日時',
+ },
+ renameDialog: {
+ title: '保存されたクエリの名前を変更',
+ label: '新しい名前',
+ placeholder: '新しいファイル名を入力',
+ cancel: 'キャンセル',
+ confirm: '名前を変更',
+ },
+ connectionDialog: {
+ title: 'ターゲット接続を変更',
+ label: '接続を選択',
+ none: '接続なし',
+ cancel: 'キャンセル',
+ confirm: '保存',
+ },
+ },
+ notImplemented: 'この機能はまだ実装されていません',
+ },
+}
diff --git a/src/lang/koKR.ts b/src/lang/koKR.ts
new file mode 100644
index 00000000..64972132
--- /dev/null
+++ b/src/lang/koKR.ts
@@ -0,0 +1,2050 @@
+export const koKR = {
+ aiPermissions: {
+ ultimateOnly: '연결별 AI 설정은 Ultimate 전용입니다',
+ accessLevel: '접근 수준',
+ unavailable: '사용 불가',
+ loadError: '권한을 불러올 수 없습니다',
+ saving: '저장 중…',
+ deniedByConnection: '연결 권한에 의해 거부됨',
+ conversationReadOnly: '이 대화에서는 읽기 전용',
+ title: 'AI 권한',
+ help: 'Data Studio 및 외부 MCP 클라이언트에 적용됩니다. 시스템 기본값을 사용하거나 이 연결에 대한 권한을 설정하세요.',
+ loading: '권한을 불러오는 중…',
+ loadFailed: '권한을 불러올 수 없습니다. 이 연결을 저장하기 전에 다시 시도하세요.',
+ retry: '다시 시도',
+ inherit: '시스템 기본값 사용',
+ none: '접근 없음',
+ read: '읽기',
+ data: '데이터 읽기 및 수정',
+ full: '전체 접근',
+ custom: '사용자 지정',
+ effective: '적용되는 접근 권한',
+ create: '데이터 생성',
+ update: '데이터 수정',
+ delete: '데이터 삭제',
+ manage: '구조 및 관리 작업',
+ allow: '허용',
+ deny: '거부',
+ fromConnection: '이 연결',
+ defaults: '기본 AI 권한',
+ defaultsHelp: 'Data Studio 및 외부 MCP 클라이언트에 적용됩니다. 연결에서 개별 동작을 설정하지 않으면 이 기본값을 따릅니다.',
+ save: '기본값 저장',
+ saved: '권한이 저장되었습니다',
+ saveFailed: '권한을 저장할 수 없습니다',
+ inheritHelp: '이후 변경 사항을 포함해 시스템 기본값을 따릅니다.',
+ noneHelp: '데이터 접근과 관리 작업이 모두 차단됩니다.',
+ readHelp: '데이터를 읽고 구조를 확인할 수 있지만 변경은 불가합니다.',
+ dataHelp: '삭제를 포함한 데이터 변경이 가능합니다. 구조 및 관리 변경은 불가합니다.',
+ fullHelp: '모든 데이터 작업, 구조 변경 및 관리 작업이 가능합니다.',
+ customHelp: 'AI가 수행할 수 있는 개별 동작을 선택합니다.',
+ defaultDecision: '기본값 사용 ({decision})',
+ readPreset: '읽기 전용',
+ },
+
+ device: {
+ replaceTitle: '기기 제한에 도달했습니다',
+ replaceDescription:
+ '구독은 최대 {limit}대의 기기에서 활성화 상태를 유지할 수 있습니다. 아래에서 기기를 선택해 이 기기로 교체하세요 — 교체된 기기는 즉시 접근이 해제됩니다.',
+ slotUsage: '{used}/{limit}대 기기 사용 중',
+ thisDevice: '이 기기',
+ lastActive: '마지막 활동',
+ neverActive: '사용한 적 없음',
+ replaceConfirm: '교체 및 활성화',
+ replaceFailed: '기기 교체에 실패했습니다. 다른 기기를 선택한 후 다시 시도하세요.',
+ },
+ plan: {
+ tab: '계정 및 플랜',
+ pricing: 'Ultimate 월 $9.9 · 연 $99 · 7일 무료 체험',
+ state: {
+ ultimate: 'Ultimate',
+ community: 'Community',
+ unknown: '알 수 없음',
+ checking: '확인 중…',
+ },
+ gate: {
+ additive: 'Community의 모든 기능에 더해:',
+ recommended: '추천',
+ currentFeature: '이 기능',
+ trustLine: '버전 잠금으로 유료 릴리스를 계속 사용 · 언제든 해지 가능',
+ headline: {
+ ai: '일상 언어로 데이터에 질문하세요',
+ transfer: '대량 데이터 이동 — 빠르고 안전하게',
+ er_diagram: '스키마를 지도처럼 한눈에',
+ ssh_tunnel: 'SSH로 원격 데이터베이스에 접속',
+ mcp_bridge: 'SQLKit을 에이전트 스택에 연결',
+ },
+ tiles: {
+ aiQueryT: '자연어 쿼리',
+ aiQueryD: '일상 언어로 질문하면 편집 가능한 SQL을 받습니다',
+ aiAgentT: '에이전트 기반 설명 및 수정',
+ aiAgentD: '클릭 한 번으로 느린 쿼리 최적화',
+ mcpServerT: '내장 MCP 서버',
+ mcpServerD: '로컬에서 실행 — 설정 불필요',
+ mcpClientsT: '모든 MCP 클라이언트',
+ mcpClientsD: 'Claude Desktop, Cursor 등',
+ },
+ groups: {
+ cloud: '클라우드',
+ local: '로컬',
+ custom: '사용자 지정',
+ clients: '클라이언트',
+ },
+ detail: {
+ ai: '모든 모델과 연동 — 클라우드, 로컬 또는 사용자 지정',
+ mcp: '선호하는 MCP 클라이언트와 연결됩니다',
+ },
+ price: {
+ yearly: '$99 / 연',
+ save: '17% 절약',
+ monthly: '$9.9 / 월',
+ },
+ trust: {
+ versionLock: '구독 중 릴리스된 버전은 오프라인에서도 계속 사용할 수 있습니다',
+ byok: '직접 발급한 LLM 키 사용 — 토큰 추가 요금 없음',
+ cancel: '언제든 해지 가능',
+ },
+ cta: {
+ unlock: 'Ultimate으로 잠금 해제',
+ unlockSub: '7일 무료 체험 · 월 $9.9 · 연 $99',
+ },
+ },
+ poster: {
+ mcp: {
+ clients: '지원 클라이언트',
+ config: '클라이언트 설정',
+ },
+ ai: {
+ question: '최근 7일간 실패한 결제를 찾아줘',
+ loop: '루프 1',
+ thinking: '생각 중',
+ toolVerb: 'public.orders 조회함',
+ answer: '실패한 결제 3건을 찾았습니다 — 생성된 쿼리:',
+ },
+ transfer: {
+ scopeDatabase: '데이터베이스 전체',
+ },
+ },
+ compare: {
+ ai: 'AI 어시스턴트 & NL2SQL',
+ er_diagram: 'ER 다이어그램',
+ transfer: '대량 가져오기 / 내보내기 및 마이그레이션',
+ ssh: 'SSH 터널',
+ mcp: 'MCP 브리지',
+ versionLock: '버전 잠금',
+ },
+ upgrade: {
+ title: 'Ultimate으로 업그레이드',
+ cta: '업그레이드',
+ refresh: '권한 새로 고침',
+ startFree: '무료로 시작',
+ versionPermanent: '구독한 버전은 오프라인에서도 영구적으로 사용할 수 있습니다.',
+ versionLockedOut: '이 릴리스를 잠금 해제하려면 활성 구독이 필요합니다. 갱신하면 영구적으로 사용할 수 있습니다.',
+ },
+ section: {
+ title: '계정 및 플랜',
+ desc: '이 설치 버전의 구독 권한과 버전 잠금 상태입니다.',
+ versionPermanent: '현재 버전은 영구적으로 사용할 수 있습니다 (버전 잠금에 포함됨).',
+ subscriptionActive: 'Ultimate이 활성화되어 있습니다 — 구독 중에는 모든 기능이 잠금 해제됩니다.',
+ versionLockedOut: '이 버전({date})은 버전 잠금에 포함되지 않습니다 — Community 모드로 표시됩니다.',
+ expiresAt: '{time}까지 사용 가능',
+ cancelScheduled: '구독은 현재 결제 주기가 끝나면 종료되도록 예약되어 있습니다.',
+ checkFailed: '권한을 확인할 수 없습니다 — 캐시된 상태를 표시합니다. 네트워크를 확인한 후 새로 고침하세요.',
+ sessionExpired: '세션이 만료되었습니다 — 플랜을 확인하려면 다시 로그인하세요.',
+ sessionLostSignedOut: '세션을 더 이상 갱신할 수 없어 로그아웃되었습니다. 언제든 다시 로그인할 수 있습니다.',
+ deviceActivationFailed: '기기 등록에 실패했습니다 — 세션 자동 갱신을 사용할 수 없습니다.',
+ notLoggedIn: '로그인되어 있지 않습니다.',
+ loginLink: 'Geekfun으로 로그인',
+ refresh: '새로 고침',
+ logout: '로그아웃',
+ manage: '구독 관리',
+ },
+ },
+ aside: {
+ aiAssistant: 'AI 어시스턴트',
+ tasks: '작업',
+ },
+ connection: {
+ prompt: {
+ title: '에이전트 프롬프트',
+ label: '에이전트 프롬프트',
+ description: 'AI 에이전트에게 이 연결에 대한 맥락을 추가합니다.',
+ help: '이 연결이 연결될 때마다 전역 시스템 프롬프트 뒤에 에이전트에게 전송됩니다.',
+ placeholder: '데이터의 비즈니스 의미, 명명 규칙, 자주 사용하는 쿼리 등을 설명하세요.',
+ configured: '구성됨',
+ add: '추가',
+ edit: '편집',
+ clear: '지우기',
+ cancel: '취소',
+ confirm: '확인',
+ },
+ },
+ connectionsPage: {
+ addSshProfile: 'SSH 프로필 추가',
+ copySuffix: ' (복사본)',
+ sshProfilesSection: 'SSH 프로필',
+ sshProfile: 'SSH 프로필',
+ },
+ common: {
+
+ copy: '복사',
+ copied: '복사되었습니다!',
+ browse: '찾아보기',
+ settings: '설정',
+ loading: '불러오는 중...',
+ notifications: {
+ codeCopied: '코드가 복사되었습니다',
+ },
+ buttons: {
+ create: '생성',
+ save: '저장',
+ cancel: '취소',
+ delete: '삭제',
+ edit: '편집',
+ confirm: '확인',
+ test: '테스트',
+ connect: '연결',
+ disconnect: '연결 해제',
+ duplicate: '복제',
+ saveChanges: '변경 사항 저장',
+ createConnection: '연결 만들기',
+ testConnection: '연결 테스트',
+ dismiss: '닫기',
+ close: '닫기',
+ browse: '찾아보기',
+ retry: '다시 시도',
+ continue: '계속',
+ refresh: '새로 고침',
+ },
+ status: {
+ connected: '연결됨',
+ disconnected: '연결 해제됨',
+ connecting: '연결 중...',
+ error: '연결 오류',
+ testing: '연결 테스트 중...',
+ success: '연결에 성공했습니다!',
+ failed: '연결에 실패했습니다',
+ },
+ },
+ ssl: {
+ errors: {
+ invalidMode: '잘못된 SSL 모드입니다',
+ caCertRequired: 'verify-ca/verify-full 모드에는 CA 인증서 경로가 필요합니다',
+ invalidCaPath: 'CA 인증서 경로가 올바르지 않습니다',
+ invalidCertPath: '클라이언트 인증서 경로가 올바르지 않습니다',
+ invalidKeyPath: '클라이언트 개인 키 경로가 올바르지 않습니다',
+ },
+ mode: {
+ label: 'SSL/TLS 모드',
+ disable: '사용 안 함',
+ prefer: '선호',
+ require: '필수',
+ verifyca: 'CA 검증',
+ verifyfull: '전체 검증',
+ },
+ modeDesc: {
+ disable: '암호화 없음',
+ prefer: '암호화를 시도하고 실패 시 평문으로 연결',
+ require: '항상 암호화하되 인증서 검증은 생략',
+ verifyca: '암호화 + CA 인증서 검증',
+ verifyfull: '암호화 + CA 및 호스트 검증',
+ },
+ certSettings: {
+ title: '인증서 설정',
+ caCert: 'CA 인증서',
+ caCertPlaceholder: 'CA 인증서 경로',
+ clientCert: '클라이언트 인증서',
+ clientCertPlaceholder: '클라이언트 인증서 경로',
+ clientKey: '클라이언트 개인 키',
+ clientKeyPlaceholder: '클라이언트 개인 키 경로',
+ },
+ sqlServer: {
+ trustServerCert: '서버 인증서 신뢰',
+ trustServerCertHint: '자체 서명된 인증서를 허용합니다',
+ },
+ },
+ transfer: {
+ title: '전송',
+ subtitle: '데이터 가져오기, 내보내기, 마이그레이션',
+ tabs: {
+ export: '내보내기',
+ import: '가져오기',
+ migration: '마이그레이션',
+ structure: '구조',
+ },
+ export: {
+ step: {
+ source: '원본',
+ format: '형식',
+ output: '출력',
+ formatOutput: '형식 및 출력',
+ preview: '미리 보기',
+ execute: '내보내기 시작',
+ },
+ selectTablesFirst: '열을 구성하려면 위에서 테이블을 선택하세요',
+ tables: {
+ label: '테이블',
+ loadFailed: '테이블을 불러오지 못했습니다',
+ },
+ columns: {
+ label: '열',
+ selectAll: '모두 선택',
+ deselectAll: '모두 선택 해제',
+ loadFailed: '열을 불러오지 못했습니다',
+ },
+ whereClause: 'WHERE 절 (선택)',
+ where: 'WHERE 절 (선택)',
+ whereClausePlaceholder: 'status = "active"',
+ orderBy: 'ORDER BY (선택)',
+ orderByPlaceholder: 'created_at DESC',
+ limit: 'LIMIT (선택)',
+ limitPlaceholder: '1000',
+ scope: '범위',
+ delimiter: '구분자',
+ delimiterOptions: {
+ comma: '쉼표 (,)',
+ semicolon: '세미콜론 (;)',
+ tab: '탭',
+ },
+ includeHeader: '헤더 포함',
+ dateFormat: '날짜 형식',
+ dateFormatOptions: {
+ iso8601: 'ISO 8601',
+ unix: 'Unix',
+ },
+ rowsPerBatch: '행/배치',
+ createTable: 'CREATE TABLE',
+ dropTable: 'DROP TABLE',
+ worksheet: '워크시트',
+ freeze: '틀 고정',
+ autoFit: '열 너비 자동 맞춤',
+ outputPath: '출력 경로',
+ selectFormat: '형식 선택',
+ showAdvanced: '고급 옵션 표시',
+ hideAdvanced: '고급 옵션 숨기기',
+ encoding: '인코딩',
+ preview: '미리 보기',
+ outputFile: '출력 파일',
+ },
+ connection: {
+ connectFailed: '연결에 실패했습니다',
+ databasesFailed: '데이터베이스를 불러오지 못했습니다',
+ schemasFailed: '스키마를 불러오지 못했습니다',
+ label: '연결',
+ placeholder: '연결 선택',
+ noConnections: '사용 가능한 연결이 없습니다. 먼저 연결을 추가하세요.',
+ connected: '연결됨',
+ offline: '오프라인',
+ databaseLabel: '데이터베이스',
+ databasePlaceholder: '데이터베이스 선택',
+ system: '시스템',
+ loadingDatabases: '데이터베이스를 불러오는 중...',
+ schemaLabel: '스키마',
+ schemaPlaceholder: '스키마 선택',
+ loadingSchemas: '스키마를 불러오는 중...',
+ tableLabel: '테이블',
+ tablePlaceholder: '테이블 선택',
+ },
+ import: {
+ step: {
+ file: '파일 선택',
+ mapping: '대상 및 매핑',
+ options: '옵션 및 미리 보기',
+ execute: '가져오기',
+ },
+ dropzone: {
+ title: '여기에 파일을 끌어다 놓으세요',
+ subtitle: '또는 클릭하여 찾아보기',
+ supported: '지원 형식: CSV, JSONL, SQL, Excel (.xlsx)',
+ instruction: '또는 클릭하여 컴퓨터에서 파일 찾기',
+ },
+ detected: {
+ format: '감지된 형식',
+ encoding: '감지된 인코딩',
+ rows: '행 수 (추정)',
+ },
+ autoMap: '이름 기준 자동 매핑',
+ clearAll: '모두 지우기',
+ conflict: {
+ label: '충돌 시 처리',
+ skip: '중복 건너뛰기',
+ replace: '기존 행 대체',
+ upsert: '기존 행 업데이트 (upsert)',
+ abort: '오류 시 중단',
+ },
+ truncateBefore: '가져오기 전에 테이블 비우기',
+ dryRun: '드라이 런 (삽입하지 않고 검증만 수행)',
+ browseFiles: '파일 찾아보기',
+ fileSize: '파일 크기',
+ detectedColumns: '감지된 열',
+ createDbIfNotExists: '데이터베이스가 없으면 생성',
+ tablesAutoCreated: '테이블은 자동으로 생성됩니다',
+ skipPlaceholder: '건너뛰기',
+ skip: '(건너뛰기)',
+ importData: '데이터 가져오기',
+ dataPreview: '데이터 미리 보기',
+ previewRows: '10행',
+ selectFileToPreview: '데이터를 미리 보려면 파일을 선택하세요',
+ importSettings: '가져오기 설정',
+ batchSize: '배치 크기',
+ loadingPreview: '미리 보기를 불러오는 중...',
+ noPreviewData: '미리 볼 데이터가 없습니다',
+ fileDetails: '파일 정보',
+ },
+ structure: {
+ title: '구조',
+ subtitle: 'DDL 생성 및 SQL 파일 실행',
+ generateDdl: 'DDL 생성',
+ runSqlFile: 'SQL 파일 실행',
+ objects: '데이터베이스 객체',
+ selectAll: '모두 선택',
+ deselectAll: '모두 선택 해제',
+ loadingObjects: '객체를 불러오는 중...',
+ noObjects: '객체를 찾을 수 없습니다. 연결과 데이터베이스를 선택하세요.',
+ objectsSelected: '개 객체 선택됨',
+ options: 'DDL 옵션',
+ includeCreateTable: 'CREATE TABLE 문 포함',
+ includePrimaryKeys: '기본 키',
+ includeForeignKeys: '외래 키',
+ includeIndexes: '인덱스',
+ includeDropIfExists: 'CREATE 앞에 DROP IF EXISTS 포함',
+ includeIfNotExists: 'CREATE에 IF NOT EXISTS 포함',
+ generate: 'DDL 생성',
+ preview: 'DDL 미리 보기',
+ copyToClipboard: '클립보드로 복사',
+ saveToFile: '파일로 저장...',
+ sqlFile: 'SQL 파일',
+ errorHandling: '오류 처리',
+ onErrorStop: '첫 오류에서 중지',
+ onErrorSkip: '건너뛰고 계속',
+ onErrorRollback: '롤백 (최선 노력; 첫 오류에서 중단)',
+ reset: '초기화',
+ execute: '실행',
+ },
+ migration: {
+ title: '마이그레이션',
+ subtitle: '크로스 엔진 데이터 마이그레이션',
+ step: {
+ source: '원본',
+ target: '대상',
+ mapping: '매핑',
+ configure: '구성',
+ execute: '실행',
+ },
+ sourceConnection: '원본 연결',
+ targetConnection: '대상 연결',
+ availableTables: '사용 가능한 테이블',
+ loadingTables: '테이블을 불러오는 중...',
+ noTables: '테이블을 찾을 수 없습니다',
+ selectAll: '모두 선택',
+ deselectAll: '모두 선택 해제',
+ tablesSelected: '개 테이블 선택됨',
+ direction: '마이그레이션 방향',
+ createTables: '대상 테이블이 없으면 생성',
+ dropTables: '마이그레이션 전에 대상 테이블 DROP',
+ loadingMapping: '타입 매핑을 생성하는 중...',
+ typeConversions: '개 열에 타입 변환 필요',
+ batchSize: '배치 크기',
+ onError: '오류 시',
+ onErrorSkipRow: '행 건너뛰고 계속',
+ onErrorSkipTable: '테이블 건너뛰고 계속',
+ onErrorAbort: '마이그레이션 중단',
+ migrateIndexes: '인덱스 마이그레이션',
+ migrateForeignKeys: '외래 키 마이그레이션',
+ migrateConstraints: '제약 조건 마이그레이션',
+ summary: '마이그레이션 요약',
+ tables: '테이블',
+ totalRows: '총 행 수',
+ conversions: '타입 변환',
+ executing: '마이그레이션 실행 중...',
+ pleaseWait: '데이터 전송이 완료될 때까지 기다려 주세요',
+ startMigration: '마이그레이션 시작',
+ migrateAgain: '다시 마이그레이션',
+ back: '뒤로',
+ next: '다음',
+ },
+ format: {
+ label: '형식',
+ csv: 'CSV (.csv)',
+ jsonl: 'JSONL (.jsonl)',
+ sql: 'SQL (.sql)',
+ excel: 'Excel (.xlsx)',
+ defaults: {
+ csv: '쉼표 구분자, 큰따옴표, UTF-8, 헤더 포함',
+ jsonl: '줄당 JSON 객체 하나, 압축 형식, UTF-8, ISO 8601 날짜',
+ sql: '대상 테이블 자동 입력, 배치 크기 1000, CREATE TABLE 포함',
+ excel: '헤더 포함, 열 너비 자동 맞춤, 헤더 행 틀 고정',
+ },
+ advancedOptions: '고급 옵션',
+ },
+ progress: {
+ preparing: '준비 중',
+ exporting: '내보내는 중...',
+ importing: '가져오는 중...',
+ elapsed: '경과 시간',
+ remaining: '예상 남은 시간',
+ rows: '행',
+ exported: '내보냄',
+ imported: '가져옴',
+ skipped: '건너뜀',
+ errors: '오류',
+ cancel: '취소',
+ runInBackground: '백그라운드에서 실행',
+ },
+ result: {
+ success: '성공적으로 완료되었습니다',
+ partial: '오류와 함께 완료되었습니다',
+ failed: '실패했습니다',
+ duration: '소요 시간',
+ file: '파일',
+ openFile: '파일 열기',
+ openFolder: '폴더 열기',
+ exportAgain: '다시 내보내기',
+ importAgain: '다시 가져오기',
+ viewTable: '테이블 보기',
+ processed: '처리됨',
+ skipped: '건너뜀',
+ errorCount: '오류',
+ },
+ tasks: {
+ title: '작업',
+ clearCompleted: '완료된 작업 지우기',
+ goToTask: '작업으로 이동',
+ dismiss: '닫기',
+ noTasks: '전송 작업이 없습니다',
+ rows: '행',
+ emptyDescription: '내보내기, 가져오기, 마이그레이션 작업이 여기에 표시됩니다',
+ status: {
+ pending: '대기 중',
+ running: '실행 중',
+ completed: '완료됨',
+ failed: '실패',
+ },
+ startedAgo: '{time} 전에 시작',
+ },
+ common: {
+
+ connection: '연결',
+ database: '데이터베이스',
+ schema: '스키마',
+ table: '테이블',
+ back: '뒤로',
+ next: '다음',
+ browse: '찾아보기...',
+ error: '오류',
+ cancel: '취소',
+ save: '저장',
+ close: '닫기',
+ tableName: '테이블 이름',
+ rows: '행',
+ type: '타입',
+ noTablesFound: '테이블을 찾을 수 없습니다',
+ columns: '열',
+ deselectAll: '모두 선택 해제',
+ scopeServer: '서버',
+ scopeDatabase: '데이터베이스',
+ scopeTables: '테이블',
+ },
+ },
+ pages: {
+ connections: {
+ title: '연결',
+ subtitle: '데이터베이스 연결을 관리합니다',
+ search: '연결 검색...',
+ stats: {
+ totalConnections: '전체 연결',
+ activeSessions: '활성 세션',
+ sshProfiles: 'SSH 프로필',
+ ago: '{time} 전',
+ },
+ saved: '저장된 연결',
+ addNew: '새 연결 추가',
+ addNewHint: 'PostgreSQL, MySQL, SQLite...',
+ empty: {
+ title: '연결을 찾을 수 없습니다',
+ message: '"{query}"(으)로 검색된 연결이 없습니다',
+ },
+ delete: {
+ title: '연결 삭제',
+ message: '"{name}"을(를) 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.',
+ },
+ error: {
+ title: '연결 오류',
+ },
+ saveFailed: '연결을 저장하지 못했습니다',
+ },
+ settings: {
+ title: '설정',
+ subtitle: '애플리케이션 환경설정을 구성합니다',
+ general: {
+ title: '일반',
+ description: '계정, 플랜, 테마, 앱 업데이트를 관리합니다',
+ theme: '테마',
+ themeSelect: '테마 선택',
+ themeHelp: '라이트, 다크, 시스템 테마 중에서 선택하세요',
+ themes: {
+ light: '라이트',
+ dark: '다크',
+ system: '시스템',
+ },
+ language: '언어',
+ languageSelect: '언어 선택',
+ languageHelp: '선호하는 언어를 선택하세요',
+ languages: {
+ enUS: 'English',
+ zhCN: '简体中文',
+ auto: '자동 (시스템 따름)',
+ },
+ },
+ mcp: {
+ title: 'MCP 브리지',
+ status: '상태',
+ running: '포트 {port}에서 실행 중',
+ stopped: '중지됨',
+ port: '포트',
+ portDesc: 'MCP 브리지 서버 포트 (비워두면 자동)',
+ restart: '브리지 재시작',
+ restartSuccess: 'MCP 브리지가 성공적으로 재시작되었습니다',
+ restartFailed: '재시작에 실패했습니다',
+ restartFailedDetail: 'MCP 브리지를 재시작하지 못했습니다',
+ restartTimeout: 'MCP 브리지가 60초 안에 시작하지 못했습니다',
+ shuttingDown: '종료하는 중...',
+ starting: '시작하는 중...',
+ autoStart: '자동 시작',
+ autoStartDesc: '앱 실행 시 MCP 브리지를 자동으로 시작합니다',
+ saveFailed: 'MCP 설정을 저장하지 못했습니다',
+ },
+ about: {
+ title: '정보',
+ version: '버전',
+ license: '라이선스',
+ licenseName: 'Apache 2.0',
+ repository: '저장소',
+ website: '웹사이트',
+ copyright: '© {year} GEEKFUN. 모든 권리 보유.',
+ description: 'SqlKit은 에이전트 기능을 갖춘 크로스 플랫폼 SQL 데이터베이스 GUI 클라이언트입니다. Rust + Tauri로 개발되었습니다.',
+ },
+ feedback: {
+ preparing: '다운로드 준비 중…',
+ downloading: '다운로드 중…',
+ installing: '설치 및 검증 중…',
+ complete: '설치 완료',
+ failed: '작업에 실패했습니다',
+ checking: '업데이트 확인 중…',
+ removing: '제거 중…',
+ removed: '제거되었습니다',
+ refreshing: '상태를 새로 고치는 중…',
+ refreshed: '상태가 새로 고쳐졌습니다',
+ loading: '설정을 불러오는 중…',
+ loadFailed: '이 섹션을 불러올 수 없습니다',
+ retry: '다시 시도',
+ saved: '변경 사항이 저장되었습니다',
+ saving: '변경 사항 저장 중…',
+ testing: '연결 테스트 중…',
+ syncing: '모델 동기화 중…',
+ synced: '모델 동기화 완료',
+ opening: '브라우저에서 여는 중…',
+ opened: '브라우저에서 열렸습니다',
+ signedOut: '로그아웃되었습니다',
+ },
+ jre: {
+ title: 'JRE 및 드라이버',
+ description: '데이터베이스 연결용 Java 런타임 및 JDBC 드라이버를 관리합니다',
+ jreCard: {
+ title: 'Java 런타임',
+ description: 'JDBC 브리지 연결에 필요합니다 (Oracle, DB2, H2, Derby)',
+ status: {
+ installed: '설치됨',
+ notInstalled: '설치되지 않음',
+ checking: '확인 중...',
+ managed: '관리형',
+ system: '시스템',
+ versionUnknown: '알 수 없음',
+ systemWarning: '시스템 Java 버전을 확인할 수 없거나 호환되지 않습니다. 호환성을 보장하려면 관리형 JRE를 다운로드하세요.',
+ systemInvalid: '유효한 JRE 없음',
+ managedRecommended: '관리형 JRE 사용',
+ },
+ actions: {
+ download: 'JRE 다운로드',
+ remove: 'JRE 제거',
+ redownload: '다시 다운로드',
+ checkUpdates: '업데이트 확인',
+ },
+ notifications: {
+ upToDate: 'JRE가 최신 상태입니다',
+ updateAvailable: 'JRE 업데이트가 있습니다',
+ newVersion: '버전 {version}을(를) 사용할 수 있습니다',
+ checkUpdatesFailed: 'JRE 업데이트를 확인하지 못했습니다',
+ downloadFailed: 'JRE를 다운로드하지 못했습니다',
+ downloadSuccess: 'JRE를 다운로드했습니다',
+ removeFailed: 'JRE를 제거하지 못했습니다',
+ },
+ },
+ bridgeCard: {
+ title: '브리지 JAR',
+ description: '데이터베이스 연결용 JDBC 브리지 구성 요소',
+ status: {
+ installed: '설치됨',
+ notInstalled: '설치되지 않음',
+ checking: '확인 중...',
+ },
+ actions: {
+ download: '브리지 다운로드',
+ remove: '브리지 제거',
+ },
+ notifications: {
+ downloadFailed: '브리지 JAR를 다운로드하지 못했습니다',
+ downloadSuccess: '브리지 JAR를 다운로드했습니다',
+ removeFailed: '브리지 JAR를 제거하지 못했습니다',
+ },
+ },
+ jdbcToggle: {
+ title: 'JDBC 연결',
+ description: 'JDBC 데이터베이스 지원을 활성화합니다 (JRE + 브리지 + 드라이버)',
+ label: 'JDBC 불필요',
+ },
+ actions: {
+ refresh: '새로 고침',
+ },
+ driversCard: {
+ title: 'JDBC 드라이버',
+ description: '데이터베이스별 JDBC 드라이버 파일',
+ label: {
+ versions: '버전',
+ },
+ status: {
+ installed: '설치됨',
+ notInstalled: '설치되지 않음',
+ loading: '드라이버를 불러오는 중...',
+ },
+ actions: {
+ download: '다운로드',
+ remove: '제거',
+ checkUpdates: '업데이트 확인',
+ },
+ notifications: {
+ upToDate: '드라이버가 최신 상태입니다',
+ updateAvailable: '드라이버 업데이트가 있습니다',
+ newVersion: '버전 {version}을(를) 사용할 수 있습니다',
+ checkUpdatesFailed: '드라이버 업데이트를 확인하지 못했습니다',
+ downloadFailed: '드라이버를 다운로드하지 못했습니다',
+ downloadSuccess: '드라이버를 다운로드했습니다',
+ removeFailed: '드라이버를 제거하지 못했습니다',
+ installBridgeFirst: '먼저 브리지 JAR를 설치한 후 드라이버를 다운로드하세요',
+ },
+ empty: {
+ title: '구성된 드라이버가 없습니다',
+ message: 'JDBC 데이터베이스에 연결하면 자동으로 다운로드됩니다.',
+ },
+ },
+ },
+ editor: {
+ title: '편집기',
+ description: 'SQL 편집기의 동작과 모양을 구성합니다',
+ fontSize: '글꼴 크기',
+ fontSizeHelp: '편집기 글꼴 크기 (픽셀, 8–32)',
+ fontSizeError: '글꼴 크기는 8에서 32 사이여야 합니다',
+ tabSize: '탭 크기',
+ tabSizeHelp: '탭당 공백 수 (1–8)',
+ tabSizeError: '탭 크기는 1에서 8 사이여야 합니다',
+ wordWrap: '자동 줄 바꿈',
+ wordWrapHelp: '편집기에서 긴 줄을 자동으로 줄 바꿈합니다',
+ showLineNumbers: '줄 번호 표시',
+ showLineNumbersHelp: '편집기 거터에 줄 번호를 표시합니다',
+ showMinimap: '미니맵 표시',
+ showMinimapHelp: '오른쪽에 미니맵 개요를 표시합니다',
+ indentWidth: '들여쓰기 너비',
+ indentWidthHelp: '서식이 지정된 SQL의 들여쓰기 수준당 공백 수 (1–8)',
+ indentWidthError: '들여쓰기 너비는 1에서 8 사이여야 합니다',
+ lineWidth: '줄 너비',
+ lineWidthHelp: '서식이 지정된 SQL의 목표 줄 너비 (문자 수, 40–200)',
+ lineWidthError: '줄 너비는 40에서 200 사이여야 합니다',
+ },
+ query: {
+ title: '쿼리',
+ description: '쿼리 실행 기본값을 구성합니다',
+ defaultLimit: '기본 행 제한',
+ defaultLimitHelp: '쿼리당 최대 반환 행 수 (10–10000)',
+ defaultLimitError: '행 제한은 10에서 10000 사이여야 합니다',
+ queryTimeout: '쿼리 제한 시간 (초)',
+ queryTimeoutHelp: '최대 쿼리 실행 시간 (초, 1–300)',
+ queryTimeoutError: '제한 시간은 1초에서 300초 사이여야 합니다',
+ autoSave: '자동 저장',
+ autoSaveHelp: '쿼리 변경 사항을 자동으로 저장합니다',
+ },
+ ai: {
+ title: 'AI 설정',
+ tabLabel: 'LLM',
+ description: 'AI 모델 공급자와 채팅 동작을 구성합니다',
+ missing: '구성된 AI 모델이 없습니다. 설정에서 공급자를 추가하고 모델을 선택하세요.',
+ providerList: {
+ title: '공급자',
+ description: 'AI 모델 공급자를 관리합니다',
+ addProvider: '공급자 추가',
+ empty: '구성된 공급자가 없습니다. 추가하면 AI 기능을 사용할 수 있습니다.',
+ emptyAction: '첫 공급자 추가',
+ deleteConfirm: '"{name}"을(를) 삭제하시겠습니까?',
+ deleteConfirmTitle: '공급자 삭제',
+ sync: '모델 동기화',
+ syncing: '동기화 중...',
+ syncSuccess: '{count}개 모델 동기화됨',
+ syncFailed: '모델을 동기화하지 못했습니다',
+ modelCount: '모델 {count}개',
+ testConnection: '테스트',
+ testing: '테스트 중...',
+ testSuccess: '연결 성공',
+ testFailed: '연결 테스트에 실패했습니다',
+ },
+ form: {
+ addTitle: '공급자 추가',
+ editTitle: '공급자 편집',
+ providerType: '공급자 유형',
+ providerTypeHelp: '프리셋을 선택하거나 다른 공급자는 사용자 지정을 선택하세요',
+ presetOpenai: 'OpenAI',
+ presetAnthropic: 'Anthropic',
+ presetAzure: 'Azure OpenAI',
+ presetCustom: '사용자 지정',
+ name: '표시 이름',
+ namePlaceholder: '내 공급자',
+ nameHelp: '이 공급자를 식별하기 쉬운 이름',
+ apiCompatibility: 'API 호환성',
+ apiCompatibilityPlaceholder: 'openai, anthropic, azure',
+ apiCompatibilityHelp: 'API 프로토콜 유형입니다. Ollama나 DeepSeek 같은 호환 서비스에는 "openai"를 사용하세요.',
+ apiKey: 'API 키',
+ apiKeyPlaceholder: 'sk-...',
+ apiKeyHelp: '공급자의 API 키입니다. 로컬에만 저장되며 서버로 전송되지 않습니다.',
+ baseUrl: '기본 URL',
+ baseUrlPlaceholder: 'https://api.openai.com/v1',
+ baseUrlHelp: 'API 엔드포인트 URL입니다. 공식 공급자는 기본값을 유지하세요.',
+ proxy: '프록시',
+ proxyPlaceholder: 'http://proxy:8080',
+ proxyHelp: 'API 요청에 사용할 선택적 HTTP/SOCKS5 프록시',
+ proxyMode: '프록시 모드',
+ contextWindow: '컨텍스트 윈도우 재정의',
+ contextWindowHelp: '기본 컨텍스트 윈도우 크기를 재정의합니다 (선택)',
+ showKey: '표시',
+ hideKey: '숨기기',
+ save: '공급자 저장',
+ models: '모델',
+ modelsPlaceholder: 'gpt-4o, gpt-4o-mini',
+ modelsHelp: '쉼표로 구분된 모델 ID입니다. 가능하면 공급자 API에서 자동 동기화됩니다.',
+ validation: {
+ nameRequired: '표시 이름은 필수입니다',
+ apiCompatibilityRequired: 'API 호환성은 필수입니다',
+ invalidApiCompatibility: 'API 호환성은 "openai", "anthropic", "azure" 중 하나여야 합니다',
+ baseUrlInvalid: '기본 URL은 http:// 또는 https://로 시작해야 합니다',
+ },
+ },
+ chat: {
+ title: '에이전트',
+ description: '에이전트 실행 동작을 구성합니다',
+ autoCompactLabel: '메시지 자동 압축',
+ autoCompactDescription: '컨텍스트 한도에 가까워지면 이전 메시지를 자동으로 요약해 토큰을 절약합니다',
+ maxIterationsLabel: '최대 반복 횟수',
+ maxIterationsDescription: '에이전트가 중지하기 전까지의 최대 도구 호출 반복 횟수 (1–1000)',
+ wallClockBudgetLabel: '실행 시간 예산 (분)',
+ wallClockBudgetDescription: '에이전트가 중지하기 전까지의 최대 실제 실행 시간 (분, 1–240)',
+ tokenBudgetLabel: '토큰 예산',
+ tokenBudgetDescription: '에이전트가 중지하기 전까지 소비할 수 있는 최대 토큰 수',
+ systemPromptLabel: '시스템 프롬프트',
+ systemPromptDescription: '데이터베이스 연결이 연결될 때 에이전트에게 전송되는 전역 시스템 프롬프트입니다. 사용 용도, 용어, 비즈니스 맥락 등을 설명하세요.',
+ systemPromptAdd: '시스템 프롬프트 추가',
+ systemPromptEdit: '시스템 프롬프트 편집',
+ systemPromptDelete: '시스템 프롬프트 삭제',
+ systemPromptEmpty: '구성된 시스템 프롬프트가 없습니다.',
+ systemPromptSave: '저장',
+ systemPromptCancel: '취소',
+ systemPromptSaveFailed: '시스템 프롬프트를 저장할 수 없습니다.',
+ systemPromptUltimateOnly: '에이전트 프롬프트는 Ultimate 전용 기능입니다',
+ },
+ },
+ updates: {
+ title: '업데이트',
+ description: '앱 업데이트를 확인합니다',
+ checkForUpdates: '업데이트 확인',
+ checkForUpdatesHelp: '일반을 열 때 자동으로 확인합니다. 업데이트는 지금 업데이트를 선택할 때만 설치됩니다.',
+ check: '지금 확인',
+ checking: '확인 중...',
+ downloading: '다운로드 중...',
+ installing: '설치 중...',
+ updateAvailable: '업데이트 있음',
+ upToDate: '최신 버전을 사용 중입니다',
+ checkFailed: '업데이트를 확인하지 못했습니다',
+ downloadFailed: '업데이트를 다운로드하지 못했습니다',
+ installFailed: '업데이트를 설치하지 못했습니다',
+ installed: '업데이트가 설치되었습니다. 재시작하는 중...',
+ newVersion: '버전 {version}을(를) 사용할 수 있습니다',
+ },
+ },
+ history: {
+ title: '기록',
+ subtitle: '쿼리 기록을 확인하고 관리합니다',
+ recent: '최근 쿼리',
+ recentDescription: '최근에 실행한 쿼리',
+ empty: '아직 쿼리 기록이 없습니다.',
+ search: '쿼리 검색...',
+ filterAll: '전체',
+ filterSuccess: '성공',
+ filterError: '오류',
+ clearAll: '모두 지우기',
+ clearNonFavorites: '즐겨찾기 아닌 항목 지우기',
+ clearAllConfirm: '모든 기록 항목을 지우시겠습니까?',
+ clearNonFavoritesConfirm: '즐겨찾기가 아닌 모든 기록 항목을 지우시겠습니까?',
+ columns: {
+ sql: 'SQL',
+ connection: '연결',
+ database: '데이터베이스',
+ status: '상태',
+ time: '시간',
+ executionTime: '소요 시간',
+ actions: '동작',
+ },
+ status: {
+ success: '성공',
+ error: '오류',
+ },
+ actions: {
+ rerun: '편집기에서 다시 실행',
+ favorite: '즐겨찾기에 추가',
+ unfavorite: '즐겨찾기에서 제거',
+ delete: '삭제',
+ },
+ notifications: {
+ cleared: '기록이 지워졌습니다',
+ deleted: '항목이 삭제되었습니다',
+ rerun: '쿼리가 편집기에 불러와졌습니다',
+ },
+ },
+ importExport: {
+ title: '가져오기 / 내보내기',
+ subtitle: '데이터를 가져오고 내보냅니다',
+ card: {
+ title: '데이터 가져오기 / 내보내기',
+ description: '데이터베이스 스키마와 데이터를 가져오고 내보냅니다',
+ comingSoon: '가져오기 및 내보내기 기능은 추후 업데이트에서 제공될 예정입니다.',
+ },
+ },
+ queries: {
+ title: '쿼리',
+ subtitle: 'SQL 쿼리를 작성하고 실행합니다',
+ selectConnection: '연결 선택',
+ selectDatabase: '데이터베이스 선택',
+ noTab: '열려 있는 쿼리 탭이 없습니다',
+ newTab: '새 쿼리',
+ landing: {
+ ready: '쿼리를 작성할 준비가 되었습니다',
+ connectedAs: '다음 계정으로 연결됨',
+ currentDatabase: '데이터베이스',
+ selectConnection: '연결 선택',
+ tip: '팁: 사이드바에서 테이블을 두 번 클릭하면 데이터를 볼 수 있습니다',
+ },
+ editor: {
+ title: 'SQL 편집기',
+ description: '여기에 SQL 쿼리를 작성하세요',
+ execute: '실행',
+ explain: 'Explain',
+ format: 'SQL 포맷팅',
+ },
+ shortcuts: {
+ execute: '쿼리 실행 ({key}Enter)',
+ explain: '쿼리 Explain (F6)',
+ format: 'SQL 포맷팅 (Shift+Alt+F)',
+ save: '저장 ({key}S)',
+ saveAs: '.sql 파일로 저장',
+ comment: '주석 전환 ({key}/)',
+ },
+ status: {
+ connection: '연결',
+ database: '데이터베이스',
+ rows: '행',
+ time: '시간',
+ executing: '실행 중...',
+ connectionLost: '연결이 끊겼습니다. 데이터베이스 연결이 종료되었습니다.',
+ reconnecting: '다시 연결하는 중...',
+ },
+ notifications: {
+ querySaved: '쿼리가 저장되었습니다',
+ saveFailed: '저장에 실패했습니다',
+ loadFailed: '쿼리를 불러오지 못했습니다',
+ noStatementFound: '커서 위치에서 SQL 문을 찾을 수 없습니다',
+ formatFailed: 'SQL 포맷팅에 실패했습니다',
+ noActiveConnection: '활성 연결이 없습니다',
+ selectConnectionFirst: '쿼리를 실행하기 전에 연결과 데이터베이스를 선택하세요',
+ tableActionSuccess: '테이블 {table} {action} 완료',
+ tableActionFailed: '테이블 {action} 실패: {error}',
+ },
+ orphanDialog: {
+ title: '고립된 탭',
+ message: '이 탭은 다른 연결에 속해 있어 쿼리를 실행할 수 없습니다. 내용은 계속 편집하고 저장할 수 있습니다.',
+ acknowledge: '고립 상태로 유지',
+ close: '탭 닫기',
+ },
+ executeOrphanDialog: {
+ title: '연결 변경됨',
+ message: '이 쿼리 탭의 원래 연결이 변경되었습니다: {from} → {to}. 현재 활성 연결에 다시 바인딩하고 실행하시겠습니까?',
+ cancel: '취소',
+ close: '탭 닫기',
+ rebindAndExecute: '다시 바인딩 후 실행',
+ },
+ explain: {
+ title: '실행 계획',
+ treeView: '트리',
+ summaryView: '요약',
+ rawView: '원본',
+ analyze: 'Explain Analyze',
+ running: '실행 계획을 생성하는 중...',
+ empty: '실행 계획 데이터가 없습니다',
+ nodeCount: '노드 {count}개',
+ summary: {
+ totalCost: '예상 총 비용: {cost}',
+ mostExpensive: '가장 비용이 큰 노드: {node}',
+ noCostData: '비용 데이터 없음',
+ },
+ node: {
+ rowEstimate: 'e:{rows}',
+ actualRows: 'a:{rows}',
+ discrepancyWarning: '실제 행 수가 예상을 크게 초과합니다 ({actual} 대 {estimated}, {ratio}배)',
+ },
+ error: {
+ parseFailed: '실행 계획을 해석하지 못했습니다',
+ noPlan: '데이터베이스에서 실행 계획을 반환하지 않았습니다',
+ },
+ tabLabels: {
+ results: '결과',
+ explain: 'Explain',
+ },
+ analyzeToggle: 'EXPLAIN ANALYZE 모드 전환 (현재: {mode})',
+ columnHeaders: {
+ nodeType: '노드 유형',
+ relation: '관계',
+ index: '인덱스',
+ cost: '비용',
+ rows: '행',
+ details: '상세',
+ },
+ },
+ },
+ },
+ dataStudio: {
+ title: 'DATA STUDIO BETA',
+ subtitle: 'AI 기반 SQL 데이터 분석',
+ inputPlaceholder: '데이터에 대해 궁금한 점을 물어보세요...',
+ modelUnavailable: '선택한 모델을 사용할 수 없습니다',
+ history: {
+ title: '기록',
+ newSession: '새 세션',
+ justNow: '방금 전',
+ minutesAgo: '{count}분 전',
+ hoursAgo: '{count}시간 전',
+ yesterday: '어제',
+ noSessions: '이전 세션이 없습니다',
+ messages: '메시지',
+ sources: '소스',
+ delete: '세션 삭제',
+ sessionFallback: '채팅',
+ empty: '아직 세션이 없습니다',
+ },
+ agent: {
+ emptyState: '질문하거나 실행할 쿼리를 설명하세요.',
+ noSource: '시작하려면 데이터 소스를 연결하세요.',
+ stop: '중지',
+ continue: '계속',
+ continueHint: '에이전트가 일시 중지되었습니다. 계속을 눌러 재개하거나 중지로 세션을 끝내세요.',
+ clearChat: '채팅 지우기',
+ riskSafe: '안전 작업',
+ riskElevated: '주의 필요 작업',
+ riskDestructive: '파괴적 작업',
+ allowOnce: '한 번만 허용',
+ allowAlways: '항상 허용',
+ deny: '거부',
+ denyAlways: '항상 거부',
+ cancelRun: '취소',
+ preparing: '준비 중...',
+ thinking: '생각 중',
+ iteration: '단계',
+ waitingModel: '모델 대기 중...',
+ compacting: '컨텍스트 압축 중...',
+ viewFullResult: '전체 결과 보기',
+ viewMore: '더 보기',
+ message: {
+ toolBlocked: '차단됨',
+ toolRejected: '거부됨',
+ blockedNotice: '권한에 의해 차단됨 — 작업이 실행되지 않았습니다',
+ historicalBlockedNotice: '이전 시도가 차단됨 — 작업이 실행되지 않았습니다',
+ rejectedNotice: '사용자가 거부함 — 작업이 실행되지 않았습니다',
+ interruptedNotice: '실행 결과를 확인할 수 없습니다',
+ unavailableNotice: '작업을 사용할 수 없음 — 작업이 실행되지 않았습니다',
+ connectionLabel: '연결: {name}',
+ requiredAction: '필요한 작업: {action}',
+ reviewPermissions: '권한 검토',
+ reviewHelp: '권한 변경을 저장해도 차단된 작업이 실행되지는 않습니다. 채팅으로 돌아와 준비가 되면 요청 재시도를 선택하세요.',
+ reviewConnectionHelp: '변경 사항은 이 연결에만 적용되며 시스템 기본값은 그대로 유지됩니다. 저장한 후 채팅으로 돌아가 요청을 다시 시도하세요.',
+ connectionUnavailable: '저장된 연결을 식별할 수 없습니다. 권한을 검토하기 전에 채팅에서 연결을 다시 붙이세요.',
+ backToChat: '채팅으로 돌아가기',
+ retryRequest: '요청 재시도',
+ retryPrompt: '차단되었거나 거부된 이전 요청을 다음 원래 인수로 {tool} 도구를 사용해 다시 시도하세요:\n{args}\n현재 권한을 다시 확인하고 필요한 승인을 요청하세요. 이전에 성공한 작업은 반복하지 마세요.',
+ awaitingPermissionDecision: '일시 중지되었습니다. 차단된 작업을 검토한 후 다시 시도하거나 새 요청을 보내세요.',
+ removeDenyRule: '항상 거부 규칙 제거',
+ ruleRemoved: '규칙이 제거되었습니다. 요청을 다시 시도해 현재 접근 권한과 확인 요건을 확인하세요.',
+ sourceUnavailable: '원래 소스가 이 대화에서 더 이상 사용할 수 없습니다. 다시 시도하기 전에 소스를 연결하세요.',
+ denialSource: {
+ system: '시스템 AI 기본값에 의해 거부되었습니다.',
+ connection: '이 연결의 AI 권한에 의해 거부되었습니다.',
+ conversation: '이 대화의 소스 제한에 의해 거부되었습니다.',
+ rule: '항상 거부 규칙이 이 대화에서 이 도구를 차단합니다.',
+ unknown: 'AI 권한이 이 작업을 차단했습니다. 다시 시도하기 전에 접근 권한을 검토하세요.',
+ },
+ toolDenied: '도구 실행이 거부되었습니다',
+ toolError: '도구 실행에 실패했습니다',
+ waitingForModel: '모델 대기 중',
+ compactionInProgress: '대화 압축 중',
+ preparingInProgress: '준비 중',
+ thinkingInProgress: '생각 중…',
+ thinkingDone: '생각 완료',
+ thinkingDuration: '{s}초',
+ generating: '생성 중…',
+ awaitingConfirm: '{tool} 승인 대기 중…',
+ executingTool: '{tool} 실행 중…',
+ toolWrote: '작성함',
+ toolRead: '읽음',
+ toolExecuted: '실행함',
+ toolSearched: '검색함',
+ toolDeleted: '삭제함',
+ toolUpdated: '업데이트함',
+ iterationLabel: '루프 {n}',
+ compactionLabel: '대화 압축됨 ({trigger})',
+ compactionSummary: '요약 보기',
+ compactionTrigger: {
+ auto: '자동',
+ manual: '수동',
+ },
+ },
+ },
+ contextIndicator: {
+ offBadgeTitle: '자동 압축이 꺼져 있음 — 컨텍스트가 자동으로 줄어들지 않습니다',
+ popoverTitle: '컨텍스트 윈도우',
+ warningText: '자동 압축이 꺼져 있고 컨텍스트가 임계값을 초과했습니다. 지금 압축하지 않으면 다음 요청이 실패할 수 있습니다.',
+ labelUsed: '사용량',
+ labelCapacity: '용량',
+ labelWindow: '윈도우',
+ labelReservedOut: '출력 예약분',
+ labelAutoCompactAt: '자동 압축 시점',
+ labelStatus: '상태',
+ compactNow: '지금 압축',
+ compacting: '압축 중…',
+ compactSuccess: '컨텍스트가 압축되었습니다',
+ compactFailed: '압축 실패: {error}',
+ statusIdle: '대기',
+ statusOverThresholdOff: '임계값 초과 (자동 압축 꺼짐)',
+ statusAutoCompactOff: '자동 압축 꺼짐',
+ statusWillAutoCompact: '자동 압축 예정',
+ statusHealthy: '정상',
+ tooltipIdle: '컨텍스트 사용량',
+ tooltipAutoCompactOff: '자동 압축 꺼짐',
+ },
+ addSource: {
+ title: '데이터 소스 추가',
+ selectConnection: '연결 선택',
+ searchPlaceholder: '연결 검색...',
+ noConnections: '호환되는 연결이 없습니다',
+ allAttached: '호환되는 모든 연결이 이미 연결되어 있습니다',
+ connectionsFound: '연결 {count}개를 찾았습니다',
+ connectSource: '연결',
+ },
+ modifySource: {
+ title: '데이터 소스 수정',
+ accessPermissions: '접근 권한',
+ inheritTitle: '연결 권한 사용',
+ saveChanges: '변경 사항 저장',
+ modeDefault: '묻기',
+ modeFull: '자동',
+ },
+ detachSource: {
+ title: '소스 분리',
+ message: '이 데이터 소스를 분리하시겠습니까? Data Studio에서 연결이 제거됩니다.',
+ confirm: '분리',
+ },
+ },
+ components: {
+ serverForm: {
+ basicTab: '기본',
+ advancedTab: '고급',
+ title: {
+ edit: '연결 편집',
+ new: '새 연결',
+ },
+ description: {
+ edit: '데이터베이스 연결 설정을 수정합니다.',
+ new: '새 데이터베이스 연결을 구성합니다.',
+ },
+ labels: {
+ connectionName: '연결 이름',
+ databaseType: '데이터베이스 유형',
+ host: '호스트',
+ databaseFilePath: '데이터베이스 파일 경로',
+ encryptionKey: '암호화 키',
+ port: '포트',
+ database: '데이터베이스',
+ username: '사용자 이름',
+ password: '비밀번호',
+ ssl: 'SSL/TLS 암호화 사용',
+ sqliteMode: 'SQLite 모드',
+ recentDatabases: '최근 데이터베이스',
+ },
+ placeholders: {
+ connectionName: '내 데이터베이스',
+ selectType: '데이터베이스 유형 선택',
+ host: 'localhost',
+ filePath: '/path/to/database.db',
+ duckdbFilePath: '/path/to/database.duckdb 또는 :memory:',
+ encryptionKey: '암호화 패스프레이즈 입력',
+ database: 'database_name',
+ username: 'username',
+ password: '••••••••',
+ },
+ databaseTypes: {
+ 'postgresql': 'PostgreSQL',
+ 'sqlserver': 'SQL Server',
+ 'mysql': 'MySQL',
+ 'mariadb': 'MariaDB',
+ 'sqlite': 'SQLite',
+ 'sqlcipher': 'SQLCipher',
+ 'duckdb': 'DuckDB',
+ 'clickhouse': 'ClickHouse',
+ 'cockroachdb': 'CockroachDB',
+ 'redshift': 'Amazon Redshift',
+ 'yugabytedb': 'YugabyteDB',
+ 'timescaledb': 'TimescaleDB',
+ 'kingbasees': '人大金仓 (KingbaseES)',
+ 'gaussdb': '华为 GaussDB',
+ 'highgo': '瀚高数据库 (HighGo DB)',
+ 'uxdb': '优炫数据库 (UXDB)',
+ 'opengauss': 'openGauss',
+ 'gbase8c': '南大通用 GBase 8c',
+ 'questdb': 'QuestDB',
+ 'vastbase': 'Vastbase (海量数据库)',
+ 'yashandb': 'YashanDB (崖山数据库)',
+ 'tidb': 'TiDB',
+ 'oceanbase': 'OceanBase',
+ 'oceanbase-oracle': 'OceanBase Oracle',
+ 'tdsql': 'TDSQL',
+ 'polardb': 'PolarDB',
+ 'dameng': '达梦 Dameng',
+ 'doris': 'Apache Doris',
+ 'selectdb': 'SelectDB',
+ 'starrocks': 'StarRocks',
+ 'databend': 'Databend',
+ 'goldendb': 'GoldenDB',
+ 'manticore': 'Manticore Search',
+ 'oracle': 'Oracle',
+ 'db2': 'IBM Db2',
+ 'h2': 'H2',
+ 'snowflake': 'Snowflake',
+ 'xugudb': '虚谷数据库 (XuguDB)',
+ 'gbase8a': '南大通用 GBase 8a',
+ 'trino': 'Trino',
+ 'presto': 'Presto',
+ 'derby': 'Apache Derby',
+ 'hive': 'Apache Hive',
+ 'databricks': 'Databricks SQL',
+ 'hana': 'SAP HANA',
+ 'teradata': 'Teradata',
+ 'vertica': 'Vertica',
+ 'exasol': 'Exasol',
+ 'bigquery': 'Google BigQuery',
+ 'informix': 'IBM Informix',
+ 'kylin': 'Apache Kylin',
+ 'cassandra': 'Apache Cassandra',
+ 'iris': 'InterSystems IRIS',
+ 'access': 'Microsoft Access',
+ 'firebird': 'Firebird',
+ 'rqlite': 'RQLite',
+ 'turso': 'Turso (libSQL)',
+ 'tdengine': 'TDengine',
+ },
+ oracle: {
+ connectionMethod: '연결 방식',
+ methods: {
+ basic: '기본 (호스트:포트)',
+ tns: 'TNS (tnsnames.ora)',
+ cloudWallet: 'Cloud Wallet (ATP/ADW)',
+ },
+ identifyBy: '식별 방식',
+ sid: 'SID',
+ serviceName: '서비스 이름',
+ role: '역할',
+ roles: {
+ normal: 'NORMAL',
+ sysdba: 'SYSDBA',
+ sysoper: 'SYSOPER',
+ },
+ tnsAdminDir: 'TNS_ADMIN 디렉터리',
+ tnsAlias: 'TNS 별칭',
+ walletDir: 'Wallet 디렉터리',
+ walletPassword: 'Wallet 비밀번호',
+ serviceLevel: '서비스 수준',
+ serviceLevels: {
+ low: '낮음 (배치)',
+ medium: '중간 (표준)',
+ high: '높음 (중요)',
+ tp: 'TP (트랜잭션)',
+ tpurgent: 'TP_URGENT (우선순위)',
+ },
+ browse: '찾아보기...',
+ noAliases: 'TNS 별칭을 찾을 수 없습니다',
+ tnsSelectDir: '별칭을 불러올 TNS 디렉터리를 선택하세요',
+ walletSelectDir: '별칭을 불러올 wallet 디렉터리를 선택하세요',
+ loadingAliases: '별칭을 불러오는 중...',
+ },
+ buttons: {
+ create: '새로 만들기...',
+ open: '열기...',
+ },
+ fileStatus: {
+ willCreate: '파일이 아직 없습니다 — 연결 시 {engine}이(가) 생성합니다.',
+ missingParent: '상위 폴더가 아직 없습니다.',
+ createDirectory: '폴더 생성',
+ createDirectoryFailed: '폴더를 생성하지 못했습니다',
+ unwritable: '이 경로에 쓰기 권한이 없습니다.',
+ directory: '이 경로는 폴더입니다. 데이터베이스 파일을 선택하세요.',
+ empty: '파일이 비어 있습니다 (0바이트).',
+ ready: '파일이 있습니다 ({size})',
+ storageVersion: '저장 형식 {storage} (DuckDB {version} 이상에서 열림)',
+ storageVersionUnknown: '저장 형식 {storage} — 이 빌드가 인식하는 것보다 새 형식으로, 최신 DuckDB에서 작성된 것으로 보입니다.',
+ writeAheadLog: '쓰기 전 로그(.wal)가 있습니다. 연결 시 재생됩니다.',
+ unsupportedPath: 'DuckDB는 \';\'가 포함된 경로를 열 수 없습니다. 파일 이름을 변경한 후 다시 시도하세요.',
+ wrongFormat: '이 파일은 {engine} 데이터베이스가 아니라 {format} 파일로 보입니다.',
+ unknownFormat: '다른 형식',
+ reveal: '폴더에서 보기',
+ revealFailed: '파일을 표시하지 못했습니다',
+ removeRecent: '최근 목록에서 제거',
+ },
+ duckdb: {
+ accessMode: '접근 모드',
+ readWrite: '읽기 및 쓰기',
+ readWriteHint: 'DuckDB는 파일에 배타적 잠금을 유지합니다. 한 번에 하나의 프로세스만 쓸 수 있습니다.',
+ readOnly: '읽기 전용',
+ readOnlyHint: '다른 DuckDB 프로세스도 같은 파일을 동시에 읽을 수 있습니다.',
+ conflictingConnection: '"{name}"이(가) 이미 다른 접근 모드로 이 파일을 열고 있으며, DuckDB는 구성이 다른 두 번째 연결을 거부합니다.',
+ openReadOnly: '읽기 전용으로 열기',
+ switchToConnection: '해당 연결로 전환',
+ sharedConnection: '"{name}"은(는) 같은 파일과 구성을 사용합니다 — 두 연결이 하나의 DuckDB 인스턴스를 공유합니다.',
+ engineVersion: '엔진 버전 {version}',
+ retryReadOnly: '읽기 전용으로 재시도',
+ retryReadWrite: '읽기/쓰기로 재시도',
+ inMemoryHint: '인메모리 데이터베이스는 임시적이며 연결을 닫으면 사라집니다. 파일로 저장하기 전에 데이터를 탐색할 때 유용합니다.',
+ inMemoryInstance: '인스턴스',
+ inMemorySharedHint: '이름이 지정된 인메모리 인스턴스는 풀링된 모든 연결이 공유하므로 한 쿼리에서 만든 테이블이 다음 쿼리에서도 유지됩니다.',
+ },
+ duckdbFailures: {
+ 'read-only-unsupported': '설치된 JDBC 브리지는 아직 데이터베이스를 읽기 전용으로 열 수 없습니다 (DuckDB는 연결별 모드 변경을 거부합니다). 읽기/쓰기 모드로 재시도하거나 설정에서 브리지를 업데이트하세요.',
+ 'storage-version': '이 파일은 사용 중인 엔진보다 새로운 DuckDB에서 작성되어 열 수 없습니다. 최신 버전으로 내보낸 후(EXPORT DATABASE) 다시 가져오거나 DuckDB 드라이버를 업데이트하세요.',
+ 'config-conflict': '다른 연결이 이미 다른 구성(읽기 전용 vs 읽기/쓰기, 또는 다른 초기화)으로 이 파일을 열고 있습니다. DuckDB는 두 번째 구성을 거부합니다.',
+ 'lock-conflict': '다른 프로세스가 이 파일의 쓰기 잠금을 보유하고 있습니다 (duckdb CLI, Python 또는 다른 SQLKit 연결). 읽기 전용으로 열거나 다른 프로그램을 종료하세요.',
+ 'unsupported-url': '이 경로는 DuckDB의 JDBC 드라이버에 전달할 수 없습니다. 파일 이름을 변경한 후 다시 시도하세요.',
+ 'extension': 'DuckDB 확장을 불러오거나 다운로드하지 못했습니다. 네트워크 연결을 확인하거나 확장을 미리 설치하세요.',
+ 'read-only-file': '데이터베이스 파일이나 폴더가 읽기 전용이라 DuckDB가 쓸 수 없습니다. 파일 권한을 변경하거나 읽기 전용으로 여세요.',
+ 'missing-file': '데이터베이스 파일이 없으며 생성할 수도 없습니다. 경로와 폴더 권한을 확인하세요.',
+ },
+ sqlite: {
+ modes: {
+ file: '파일',
+ inMemory: '인메모리',
+ },
+ recentEmpty: '최근 데이터베이스가 없습니다',
+ ago: '{time} 전',
+ inMemoryHint: '인메모리 데이터베이스는 임시적이며 연결을 닫으면 사라집니다. 테스트와 임시 데이터에 유용합니다.',
+ pathStatus: {
+ valid: '파일 있음',
+ notFound: '파일 없음',
+ noPermission: '쓰기 권한 없음',
+ },
+ },
+ errors: {
+ nameRequired: '연결 이름은 필수입니다',
+ hostRequired: '호스트는 필수입니다',
+ databaseRequired: 'SID / 서비스 이름은 필수입니다',
+ databaseNameRequired: '데이터베이스 이름은 필수입니다',
+ filePathRequired: '데이터베이스 파일 경로는 필수입니다',
+ portInvalid: '포트는 양수여야 합니다',
+ filePickerFailed: '파일 선택기를 열지 못했습니다',
+ tnsAdminDirRequired: 'TNS 관리 디렉터리는 필수입니다',
+ tnsAliasRequired: 'TNS 별칭은 필수입니다',
+ },
+ ssh: {
+ newProfile: '새 프로필',
+ hopOrderHint: '홉은 순서대로 시도되며 마지막 홉이 데이터베이스로 전달합니다. 시스템 프록시는 첫 번째 홉에만 적용됩니다.',
+ importFromConfig: '~/.ssh/config에서 가져오기',
+ profileName: '프로필 이름',
+ profileNamePlaceholder: '예: 운영 배스천',
+ editProfile: 'SSH 프로필 편집',
+ useSshTunnel: 'SSH 터널',
+ ultimateOnly: 'SSH 터널은 Ultimate 전용 기능입니다',
+ tunnelSkippedHint: 'SSH 터널은 Ultimate 전용 기능입니다. Community 또는 로그아웃 상태의 세션에서는 이 연결에 저장된 터널을 건너뛰므로 이 테스트는 직접 연결로 실행되었습니다.',
+ systemProxy: '시스템 프록시',
+ systemProxyDetected: '시스템 프록시 감지됨: {url}',
+ systemProxyAdd: '추가',
+ systemProxyDetach: '시스템 프록시 분리',
+ systemProxyNotDetected: '시스템 프록시가 활성화되어 있지만 감지되지 않았습니다. 직접 연결합니다.',
+ detachAction: '체인에서 분리',
+ moveUp: '홉 위로 이동',
+ moveDown: '홉 아래로 이동',
+ hops: '홉 | 홉',
+ addProfilePlaceholder: '프로필 추가…',
+ searchProfilePlaceholder: '프로필 검색…',
+ testChain: '터널 연결 테스트',
+ testFirstHop: '첫 홉 테스트 (이후 홉은 테스트되지 않음)',
+ testDisabledHint: '필수 입력이 누락되었거나 구성이 잘못되었습니다',
+ testReturnedNotConnected: '연결 결과가 연결되지 않음으로 반환되었습니다',
+ jreBroken: 'JRE가 없거나 손상되었습니다',
+ stepFailed: '실패',
+ testTimedOut: '테스트 시간 초과 (30초) — 배스천에 접근할 수 없거나 SSH 핸드셰이크가 멈췄습니다',
+ testSuccess: '{user}{\'@\'}{host}:{port}에 연결되었습니다',
+ notConfigured: 'SSH 터널이 구성되지 않았습니다 — 프로필을 추가해 시작하세요',
+ editTunnel: 'SSH 터널 편집',
+ connectionOnly: '변경 사항은 이 연결에만 적용됩니다.',
+ convertHint: '재사용 가능한 프로필로 변환하면 홉을 추가하고 순서를 바꿀 수 있습니다.',
+ noConfigHosts: '~/.ssh/config에서 SSH 호스트를 찾을 수 없습니다.',
+ convertToProfile: '프로필로 변환',
+ convertedProfileName: '수동 ({host})',
+ sshHost: 'SSH 호스트',
+ sshPort: 'SSH 포트',
+ username: '사용자 이름',
+ authMethod: '인증 방식',
+ password: '비밀번호',
+ privateKey: '개인 키',
+ sshAgent: 'SSH 에이전트',
+ sshPassword: 'SSH 비밀번호',
+ privateKeyPath: '개인 키 경로',
+ passphraseOptional: '패스프레이즈 (선택)',
+ agentSockPath: '에이전트 소켓 경로',
+ agentHelpText: '시스템 SSH 에이전트를 사용합니다 - 추가 구성이 필요하지 않습니다.',
+ },
+ },
+ serverCard: {
+ actions: {
+ connect: '연결',
+ openEditor: '편집기에서 열기',
+ closeConnection: '연결 닫기',
+ edit: '편집',
+ duplicate: '복제',
+ delete: '삭제',
+ },
+ strategy: {
+ nativeTooltip: '네이티브 Rust 드라이버를 통한 직접 연결 — 최고 성능, 외부 의존성 없음',
+ jdbcBridgeTooltip: '내장 Java 런타임을 통해 JDBC 드라이버로 연결 — 가장 넓은 데이터베이스 호환성',
+ httpBridgeTooltip: 'HTTP SQL 프로토콜로 연결 — REST 기반 데이터베이스용',
+ },
+ },
+ connectingModal: {
+ connecting: '{name}에 연결하는 중...',
+ connectingSubtext: '연결을 수립하는 동안 잠시만 기다려 주세요',
+ connectionError: '연결 오류',
+ sshTunnelSkipped: 'SSH 터널은 Ultimate 전용 기능입니다. Community 또는 로그아웃 상태의 세션에서는 이 연결에 저장된 터널을 건너뛰고 직접 연결합니다 (구성 자체는 유지됩니다).',
+ sshTunnelStripped: '이번 시도에서는 이 연결에 저장된 터널이 건너뛰어졌습니다 (Ultimate 전용 기능이며 현재 Community 또는 로그아웃 상태입니다). 데이터베이스가 그 터널을 통해서만 접근 가능하다면 Ultimate으로 업그레이드하세요.',
+ },
+ databaseBrowser: {
+ title: '데이터베이스 브라우저',
+ search: '테이블 검색...',
+ refresh: '새로 고침',
+ newQuery: '새 쿼리',
+ loading: '불러오는 중...',
+ empty: '데이터베이스를 찾을 수 없습니다. 먼저 서버에 연결하세요.',
+ selectDatabase: '데이터베이스 선택',
+ selectSchema: '스키마 선택',
+ databases: '데이터베이스',
+ current: '현재',
+ userDatabases: '사용자 데이터베이스',
+ systemDatabases: '시스템 데이터베이스',
+ noTables: '테이블을 찾을 수 없습니다',
+ noViews: '뷰를 찾을 수 없습니다',
+ noProcedures: '프로시저를 찾을 수 없습니다',
+ noFunctions: '함수를 찾을 수 없습니다',
+ noSavedQueries: '아직 저장된 쿼리가 없습니다',
+ comingSoon: '곧 제공 예정',
+ sections: {
+ tables: '테이블',
+ views: '뷰',
+ procedures: '프로시저',
+ functions: '함수',
+ savedQueries: '저장된 쿼리',
+ },
+ errors: {
+ fetchDatabases: '데이터베이스를 가져오지 못했습니다',
+ fetchSchemas: '스키마를 가져오지 못했습니다',
+ fetchTables: '테이블을 가져오지 못했습니다',
+ invalidResponse: '서버 응답이 올바르지 않습니다',
+ },
+ contextMenu: {
+ viewData: '데이터 보기',
+ selectTopN: '상위 100개 조회',
+ viewStructure: '구조 보기',
+ createScript: 'CREATE 스크립트',
+ exportData: '데이터 내보내기',
+ showErDiagram: 'ER 다이어그램 보기',
+ dropTable: '테이블 DROP',
+ truncateTable: '비우기 (TRUNCATE)',
+ newQuery: '새 쿼리',
+ refresh: '새로 고침',
+ },
+ savedQueryActions: {
+ open: '열기',
+ delete: '삭제',
+ reveal: 'Finder에서 보기',
+ },
+ erDiagram: {
+ title: 'ER 다이어그램',
+ viewMode: '보기',
+ zoom: '{percentage}%',
+ zoomIn: '확대',
+ zoomOut: '축소',
+ allSchemas: '모든 스키마',
+ engineeringView: '엔지니어링 뷰',
+ fitToScreen: '화면에 맞추기',
+ searchPlaceholder: '테이블 필터링...',
+ tablesCountBadge: '테이블 {count}개',
+ tableView: '테이블 뷰',
+ relationshipsCountBadge: '관계 {count}개',
+ resetLayout: '레이아웃 초기화',
+ largeSchemaWarning: '이 스키마에는 테이블 {count}개가 있습니다. 모두 표시하면 복잡할 수 있습니다. 계속하시겠습니까?',
+ showAllColumns: '모든 열 표시 ({count})',
+ hideExtraColumns: '간략히 보기',
+ noForeignKeys: '외래 키 관계를 찾을 수 없습니다',
+ openTable: '테이블 데이터 열기',
+ layoutDirection: '레이아웃',
+ layoutTopBottom: '위 → 아래',
+ layoutLeftRight: '왼쪽 → 오른쪽',
+ loading: '스키마 관계를 불러오는 중...',
+ },
+ },
+ listingTab: {
+ views: '뷰',
+ procedures: '프로시저',
+ functions: '함수',
+ searchPlaceholder: '이름으로 검색...',
+ name: '이름',
+ detail: '상세',
+ ddl: 'DDL',
+ actions: '동작',
+ viewDdl: 'DDL 보기',
+ drop: 'DROP',
+ rename: '이름 변경',
+ copyName: '이름 복사',
+ copyDdl: 'DDL 복사',
+ dropDialogTitle: '객체 DROP',
+ dropDialogDescription: '{name}을(를) DROP하시겠습니까?',
+ confirmDrop: 'DROP',
+ renameDialogTitle: '객체 이름 변경',
+ renameDialogDescription: '{name}의 새 이름을 입력하세요:',
+ newNamePlaceholder: '새 이름',
+ confirmRename: '이름 변경',
+ noResults: '검색과 일치하는 객체가 없습니다',
+ empty: '객체를 찾을 수 없습니다',
+ },
+ schemaTab: {
+ column: '열',
+ type: '타입',
+ nullable: 'NULL 허용',
+ default: '기본값',
+ key: '키',
+ autoIncrement: '자동 증가',
+ yes: '예',
+ no: '아니오',
+ pk: 'PK',
+ },
+ indexesTab: {
+ name: '이름',
+ columns: '열',
+ type: '타입',
+ unique: '고유',
+ primary: '기본',
+ empty: '인덱스를 찾을 수 없습니다',
+ yes: '예',
+ no: '아니오',
+ },
+ foreignKeysTab: {
+ constraint: '제약 조건',
+ columns: '열',
+ references: '참조',
+ onUpdate: 'ON UPDATE',
+ onDelete: 'ON DELETE',
+ empty: '외래 키를 찾을 수 없습니다',
+ },
+ triggersTab: {
+ name: '이름',
+ timing: '시점',
+ event: '이벤트',
+ ddl: 'DDL',
+ viewDdl: 'DDL 보기',
+ empty: '트리거를 찾을 수 없습니다',
+ },
+ queryResult: {
+ title: '결과',
+ selectResult: '결과 집합 선택',
+ resultSet: '결과 {index}/{count}',
+ exportActions: '결과 복사 및 내보내기',
+ scriptReadOnly: '스크립트 결과는 읽기 전용입니다. 정렬은 반환된 행에만 적용됩니다.',
+ rows: '{count}행',
+ rowsAffected: '{count}행이 영향을 받았습니다',
+ time: '{time}',
+ close: '닫기',
+ executing: '쿼리 실행 중...',
+ error: '쿼리 오류',
+ success: '쿼리가 성공적으로 실행되었습니다',
+ noData: '반환된 데이터가 없습니다',
+ commandCompleted: '명령이 완료되었습니다',
+ noResults: '쿼리를 실행하면 결과가 표시됩니다',
+ },
+ dataTableView: {
+ searchPlaceholder: '모든 열에서 검색...',
+ clearSearch: '검색 지우기',
+ filterPlaceholder: '필터 (SQL WHERE 절, 예: age > 18 AND status = \'active\')',
+ clearFilter: '필터 지우기',
+ refresh: '새로 고침',
+ columns: '열',
+ exportCsv: '현재 페이지 내보내기 (CSV)',
+ applyFilters: '필터 적용',
+ loading: '테이블 데이터를 불러오는 중...',
+ error: '테이블 데이터를 불러오지 못했습니다',
+ connectionLost: '연결이 끊겼습니다. 데이터베이스 연결이 종료되었습니다.',
+ reconnecting: '다시 연결하는 중...',
+ reconnect: '다시 연결',
+ noRows: '행이 없습니다',
+ rows: '행',
+ columnsCount: '열 {count}개',
+ indexesCount: '인덱스 {count}개',
+ foreignKeysCount: '외래 키 {count}개',
+ triggersCount: '트리거 {count}개',
+ page: '페이지 {page} / {total}',
+ rowsPerPage: '페이지당 행 수:',
+ actions: '동작',
+ editRow: '행 편집',
+ deleteRow: '행 삭제',
+ notifications: {
+ csvExported: 'CSV를 내보냈습니다',
+ exportFailed: '내보내기에 실패했습니다',
+ rowDeleted: '행이 삭제되었습니다',
+ deleteFailed: '행을 삭제하지 못했습니다',
+ rowUpdated: '행이 업데이트되었습니다',
+ updateFailed: '행을 업데이트하지 못했습니다',
+ noPrimaryKey: '기본 키가 감지되지 않았습니다',
+ noPrimaryKeyDesc: '이 테이블에는 기본 키가 없습니다. 행은 모든 열로 식별됩니다.',
+ fallbackAllColumns: '기본 키가 없어 모든 열로 행을 식별합니다. 주의해서 편집하세요.',
+ },
+ deleteDialog: {
+ title: '행 삭제',
+ message: '이 행을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.',
+ confirm: '삭제',
+ },
+ editDialog: {
+ title: '행 편집',
+ },
+ validation: {
+ required: '이 필드는 필수입니다',
+ invalidNumber: '올바른 숫자를 입력하세요',
+ invalidBoolean: 'true 또는 false를 입력하세요',
+ },
+ },
+ queryTabs: {
+ unsaved: '저장되지 않은 변경 사항',
+ orphan: '이 탭은 다른 연결에 속해 있습니다',
+ new: '새 쿼리',
+ closeDialog: {
+ title: '저장되지 않은 변경 사항',
+ message: '쿼리 "{name}"에 저장되지 않은 변경 사항이 있습니다. 변경 사항을 버리시겠습니까?',
+ discard: '버리기',
+ },
+ },
+ header: {
+ appName: 'SQLKit',
+ },
+ sqlEditor: {
+ execute: '실행',
+ format: '포맷',
+ copy: '복사',
+ },
+ destructiveDialog: {
+ deleteRow: {
+ title: '삭제 확인',
+ message: '테이블 "{table}"에서 {count}행을 삭제하시겠습니까?',
+ detail: '이 작업은 되돌릴 수 없습니다.',
+ confirm: '삭제',
+ },
+ dropTable: {
+ title: '테이블 DROP',
+ message: '테이블 "{table}"을(를) DROP하시겠습니까?',
+ detail: '테이블과 모든 데이터가 영구적으로 삭제됩니다. 이 작업은 되돌릴 수 없습니다.',
+ confirm: 'DROP',
+ },
+ truncateTable: {
+ title: '테이블 비우기 (TRUNCATE)',
+ message: '테이블 "{table}"을(를) 비우시겠습니까?',
+ detail: '전체 {count}행이 제거됩니다. 이 작업은 되돌릴 수 없습니다.',
+ confirm: '비우기',
+ },
+ deleteConnection: {
+ title: '연결 삭제',
+ message: '연결 "{name}"을(를) 삭제하시겠습니까?',
+ detail: '저장된 연결 구성이 제거됩니다. 활성 연결은 연결 해제됩니다.',
+ confirm: '삭제',
+ },
+ deleteProfile: {
+ title: 'SSH 프로필 삭제',
+ message: '프로필 "{name}"을(를) 삭제하시겠습니까?',
+ detail: '프로필이 공유 프로필 라이브러리에서 제거됩니다. 이 프로필을 경유하던 연결은 이 배스천을 사용할 수 없게 됩니다.',
+ inUse: '{count}개 연결이 사용 중입니다: {names}. 해당 연결은 이 프로필에서 분리됩니다.',
+ confirm: '삭제',
+ },
+ },
+ pagination: {
+ label: '페이지 매기기',
+ showingWithoutTotal: '{start}–{end}행 표시 중 · 전체 수 없음',
+ rowsPerPage: '페이지당 행 수',
+ pageSize: '페이지당 {count}행',
+ customSize: '사용자 지정 행 수',
+ apply: '적용',
+ showAll: '반환된 모든 행 표시',
+ allRows: '반환된 모든 행',
+ firstPage: '첫 페이지',
+ previousPage: '이전 페이지',
+ nextPage: '다음 페이지',
+ lastPage: '마지막 페이지',
+ goToPage: '페이지 이동',
+ pageCount: '/ {count}',
+ sortScope: '정렬은 현재 페이지에만 적용됩니다',
+ },
+ dataGrid: {
+ sort: {
+ asc: '오름차순 정렬',
+ desc: '내림차순 정렬',
+ clear: '정렬 지우기',
+ unsortable: '이 열 유형은 정렬할 수 없습니다',
+ },
+ filter: {
+ byValue: '값으로 필터',
+ byLike: 'LIKE로 필터',
+ greaterThan: '>= 필터',
+ lessThan: '<= 필터',
+ between: 'BETWEEN 필터',
+ excludeValue: '값 제외',
+ clearFilter: '필터 지우기',
+ clearAll: '모든 필터 지우기',
+ activeFilters: '필터',
+ },
+ row: {
+ edit: '행 편집',
+ delete: '행 삭제',
+ duplicate: '행 복제',
+ details: '행 상세',
+ copyAsCsv: '행을 CSV로 복사',
+ copyAsJson: '행을 JSON으로 복사',
+ copyAsInsert: '행을 INSERT로 복사',
+ actions: '동작',
+ noTableContext: '쿼리 결과가 테이블과 연결되어 있지 않아 행을 편집하거나 삭제할 수 없습니다',
+ editUnsupported: {
+ 'not-select': '이 문은 SELECT 쿼리가 아닙니다. 결과 행을 편집하거나 삭제할 수 없습니다',
+ 'cte': '쿼리가 WITH (CTE)를 사용합니다. 행을 테이블에 다시 매핑할 수 없어 편집이 지원되지 않습니다',
+ 'set-operation': '쿼리가 UNION/INTERSECT/EXCEPT를 사용합니다. 행이 여러 문에서 오므로 편집이 지원되지 않습니다',
+ 'aggregation': '쿼리가 집계됩니다 (GROUP BY/DISTINCT/집계 함수). 행을 기본 행에 매핑할 수 없어 편집이 지원되지 않습니다',
+ 'multiple-sources': '쿼리가 여러 테이블을 조인합니다. 행을 편집하거나 삭제할 수 없습니다',
+ 'no-table': '쿼리에 FROM 테이블이 없습니다. 행을 편집하거나 삭제할 수 없습니다',
+ 'complex-source': '쿼리 원본이 서브쿼리 또는 복잡한 식입니다. 행을 편집하거나 삭제할 수 없습니다',
+ },
+ },
+ cell: {
+ copyValue: '셀 값 복사',
+ copyRow: '행 복사',
+ filterByValue: '이 값으로 필터',
+ excludeValue: '이 값 제외',
+ },
+ selection: {
+ selected: '{count}행 선택됨',
+ editSelected: '선택 항목 편집',
+ deleteSelected: '선택 항목 삭제',
+ exportSelected: '선택 항목 내보내기',
+ },
+ status: {
+ showing: '전체 {total}행 중 {start}–{end}행 표시 중',
+ showingLimited: '전체 {loaded}행 중 {start}–{end}행 표시 중 (제한됨)',
+ time: '· {time}',
+ },
+ empty: '결과 없음',
+ error: {
+ title: '데이터를 불러오는 중 오류가 발생했습니다',
+ retry: '다시 시도',
+ },
+ loading: '데이터를 불러오는 중...',
+ edit: {
+ title: '행 편집',
+ duplicateTitle: '행 복제',
+ nullToggle: 'NULL 설정',
+ pkReadonly: '기본 키 (읽기 전용)',
+ save: '저장',
+ cancel: '취소',
+ saving: '저장 중...',
+ confirmCancel: '변경 사항을 버리시겠습니까?',
+ confirmCancelMessage: '저장되지 않은 변경 사항이 있습니다. 닫으시겠습니까?',
+ discard: '버리기',
+ validation: {
+ required: '이 필드는 필수입니다',
+ invalidNumber: '올바른 숫자를 입력하세요',
+ invalidBoolean: 'true 또는 false를 입력하세요',
+ },
+ },
+ details: {
+ title: '행 상세',
+ },
+ delete: {
+ title: '행 삭제',
+ message: '이 행을 삭제하시겠습니까?',
+ detail: '이 작업은 되돌릴 수 없습니다.',
+ confirm: '삭제',
+ batchTitle: '선택한 행 삭제',
+ batchMessage: '선택한 {count}행을 삭제하시겠습니까?',
+ batchDetail: '이 작업은 되돌릴 수 없습니다.',
+ },
+ export: {
+ copyAllCsv: '전체를 CSV로 복사',
+ copyAllJson: '전체를 JSON으로 복사',
+ copyAllInsert: '전체를 INSERT로 복사',
+ exportCsv: 'CSV 내보내기',
+ exportJson: 'JSON 내보내기',
+ exportInsert: 'INSERT 내보내기',
+ copied: '클립보드에 복사되었습니다',
+ exported: '파일을 내보냈습니다',
+ formatLabels: {
+ csv: 'CSV',
+ json: 'JSON',
+ insert: 'INSERT',
+ },
+ },
+ json: {
+ expand: '펼치기',
+ title: 'JSON 뷰어',
+ copy: 'JSON 복사',
+ },
+ blob: {
+ label: '[BLOB {size}]',
+ },
+ null: '(NULL)',
+ rowNumber: '#',
+ },
+ },
+ updater: {
+ updateAvailable: '업데이트 있음',
+ newVersion: '버전 {version}을(를) 사용할 수 있습니다',
+ upToDate: '최신 버전을 사용 중입니다',
+ checkFailed: '업데이트를 확인하지 못했습니다',
+ downloading: '업데이트를 다운로드하는 중...',
+ installing: '업데이트를 설치하는 중...',
+ installFailed: '업데이트를 설치하지 못했습니다',
+ skip: '이 버전 건너뛰기',
+ later: '나중에',
+ updateNow: '지금 업데이트',
+ restarting: '재시작하는 중...',
+ downloadingPercent: '{percent}% 다운로드 중',
+ relaunchFailed: '업데이트 후 재시작에 실패했습니다',
+ retry: '다시 시도',
+ installFailedHelp: 'F12를 눌러 개발자 도구를 열고 오류 세부 정보를 확인하세요.',
+ },
+ errors: {
+ unexpected: '예기치 않은 오류: {error}',
+ codes: {
+ // Connection errors
+ CONNECTION_FAILED: '데이터베이스에 연결하지 못했습니다',
+ CONNECTION_TIMEOUT: '연결 시간 초과',
+ CONNECTION_REFUSED: '연결이 거부되었습니다',
+ AUTHENTICATION_FAILED: '인증에 실패했습니다',
+
+ // Query errors
+ QUERY_SYNTAX_ERROR: 'SQL 구문 오류',
+ QUERY_EXECUTION_ERROR: '쿼리 실행에 실패했습니다',
+ QUERY_TIMEOUT: '쿼리 실행 시간이 초과되었습니다',
+
+ // Resource errors
+ DATABASE_NOT_FOUND: '데이터베이스를 찾을 수 없습니다',
+ TABLE_NOT_FOUND: '테이블이 존재하지 않습니다',
+ COLUMN_NOT_FOUND: '열이 존재하지 않습니다',
+
+ // Permission errors
+ PERMISSION_DENIED: '권한이 거부되었습니다',
+ INSUFFICIENT_PRIVILEGES: '권한이 부족합니다',
+
+ // Data errors
+ CONSTRAINT_VIOLATION: '제약 조건 위반',
+ FOREIGN_KEY_VIOLATION: '외래 키 제약 조건 위반',
+ UNIQUE_VIOLATION: '고유 제약 조건 위반',
+ NOT_NULL_VIOLATION: 'NOT NULL 제약 조건 위반',
+ CHECK_VIOLATION: 'CHECK 제약 조건 위반',
+
+ // System errors
+ INTERNAL_ERROR: '내부 오류',
+ UNSUPPORTED_OPERATION: '지원되지 않는 작업입니다',
+ INVALID_CONFIGURATION: '구성이 올바르지 않습니다',
+ },
+ titles: {
+ CONNECTION_FAILED: '연결 실패',
+ AUTHENTICATION_FAILED: '인증 실패',
+ QUERY_SYNTAX_ERROR: 'SQL 구문 오류',
+ QUERY_EXECUTION_ERROR: '쿼리 실행 오류',
+ TABLE_NOT_FOUND: '테이블 없음',
+ COLUMN_NOT_FOUND: '열 없음',
+ PERMISSION_DENIED: '권한 거부',
+ FOREIGN_KEY_VIOLATION: '외래 키 제약 조건 위반',
+ UNIQUE_VIOLATION: '고유 제약 조건 위반',
+ NOT_NULL_VIOLATION: 'NOT NULL 제약 조건 위반',
+ },
+ hints: {
+ CONNECTION_FAILED: '연결 설정을 확인하고 데이터베이스 서버가 실행 중인지 확인하세요',
+ AUTHENTICATION_FAILED: '사용자 이름과 비밀번호를 확인하세요',
+ QUERY_SYNTAX_ERROR: 'SQL 구문을 확인한 후 다시 시도하세요',
+ QUERY_TIMEOUT: '쿼리를 최적화하거나 제한 시간을 늘려 보세요',
+ DATABASE_NOT_FOUND: '데이터베이스가 존재하고 접근 권한이 있는지 확인하세요',
+ TABLE_NOT_FOUND: '테이블 이름을 확인하고 데이터베이스에 존재하는지 확인하세요',
+ COLUMN_NOT_FOUND: '열 이름이 테이블 스키마와 일치하는지 확인하세요',
+ FOREIGN_KEY_VIOLATION: '참조된 레코드가 부모 테이블에 있는지 확인하세요',
+ UNIQUE_VIOLATION: '이 값을 가진 레코드가 이미 존재합니다',
+ NOT_NULL_VIOLATION: '이 필드에는 값이 필요합니다',
+ CHECK_VIOLATION: '값이 테이블 제약 조건을 충족하지 않습니다',
+ PERMISSION_DENIED: '이 작업에 필요한 권한이 부족합니다',
+ },
+ },
+ sidebar: {
+ connection: {
+ placeholder: '연결 선택',
+ connected: '연결됨',
+ lost: '연결 끊김',
+ disconnected: '연결 해제됨',
+ connecting: '연결 중...',
+ },
+ database: {
+ placeholder: '모든 데이터베이스',
+ selectDatabase: '데이터베이스 선택',
+ refresh: '새로 고침',
+ refreshTooltip: '데이터베이스 목록 다시 불러오기',
+ },
+ databases: {
+ actions: {
+ createObject: {
+ title: '{type} 생성',
+ placeholder: '{type} 이름 입력',
+ cancel: '취소',
+ confirm: '생성',
+ created: '{type} "{name}"이(가) 생성되었습니다',
+ error: '생성 실패: {error}',
+ types: {
+ database: '데이터베이스',
+ schema: '스키마',
+ },
+ },
+ createDatabase: {
+ title: '데이터베이스 생성',
+ name: '데이터베이스 이름',
+ namePlaceholder: '데이터베이스 이름 입력',
+ charset: '문자셋',
+ collation: '콜레이션',
+ collationPlaceholder: '예: utf8mb4_unicode_ci',
+ encoding: '인코딩',
+ locale: '로케일 / LC_COLLATE',
+ localePlaceholder: '예: en_US.UTF-8',
+ optional: '선택 사항',
+ cancel: '취소',
+ confirm: '생성',
+ },
+ dropDatabase: {
+ title: '데이터베이스 DROP',
+ message: '"{name}"을(를) DROP하시겠습니까? 이 작업은 되돌릴 수 없습니다.',
+ typeToConfirm: '확인하려면 데이터베이스 이름을 입력하세요:',
+ cancel: '취소',
+ confirm: 'DROP',
+ success: '데이터베이스 "{name}"을(를) DROP했습니다',
+ error: '데이터베이스 DROP 실패: {error}',
+ },
+ createTable: {
+ title: '테이블 생성',
+ tableName: '테이블 이름',
+ tableNamePlaceholder: '테이블 이름 입력',
+ engine: '엔진',
+ columns: '열',
+ addColumn: '열 추가',
+ colName: '이름',
+ colType: '타입',
+ colLength: '길이',
+ colAutoInc: 'AI',
+ colDefault: '기본값',
+ lengthPlaceholder: '255',
+ defaultPlaceholder: 'NULL',
+ preview: 'SQL 미리 보기',
+ cancel: '취소',
+ create: '생성',
+ opened: '테이블 SQL이 편집기에서 열렸습니다. 실행하면 테이블이 생성됩니다.',
+ },
+ templateOpened: '새 {type} 템플릿이 편집기에서 열렸습니다.',
+ },
+ },
+ actionMenu: {
+ label: '데이터베이스 작업',
+ createScript: '생성 스크립트',
+ newDatabase: '새 데이터베이스',
+ newSchema: '새 스키마',
+ newTable: '새 테이블',
+ newView: '새 뷰',
+ newFunction: '새 함수',
+ newProcedure: '새 프로시저',
+ showErDiagram: 'ER 다이어그램',
+ backupDatabase: '데이터베이스 백업',
+ exportDatabase: '데이터베이스 내보내기',
+ dropDatabase: '데이터베이스 DROP',
+ },
+ groups: {
+ tables: '테이블',
+ views: '뷰',
+ procedures: '프로시저',
+ functions: '함수',
+ },
+ loading: '불러오는 중...',
+ empty: '선택된 데이터베이스가 없습니다. 탐색할 데이터베이스를 선택하세요.',
+ noObjects: '객체를 찾을 수 없습니다',
+ noDatabases: '데이터베이스를 찾을 수 없습니다. 먼저 서버에 연결하세요.',
+ search: '테이블, 뷰 검색...',
+ savedQueries: {
+ header: '저장된 쿼리',
+ expand: '저장된 쿼리 펼치기',
+ collapse: '저장된 쿼리 접기',
+ newQuery: '새 쿼리',
+ empty: '아직 저장된 쿼리가 없습니다',
+ created: '생성됨',
+ modified: '수정됨',
+ connectionNone: '대상 연결 없음',
+ actions: {
+ open: '열기',
+ rename: '이름 변경',
+ changeConnection: '대상 연결 변경',
+ reveal: '파일 탐색기에서 보기',
+ delete: '삭제',
+ },
+ delete: {
+ title: '저장된 쿼리를 삭제하시겠습니까?',
+ description: '"{name}"을(를) 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.',
+ cancel: '취소',
+ confirm: '삭제',
+ target: '대상',
+ created: '생성됨',
+ },
+ renameDialog: {
+ title: '저장된 쿼리 이름 변경',
+ label: '새 이름',
+ placeholder: '새 파일 이름 입력',
+ cancel: '취소',
+ confirm: '이름 변경',
+ },
+ connectionDialog: {
+ title: '대상 연결 변경',
+ label: '연결 선택',
+ none: '연결 없음',
+ cancel: '취소',
+ confirm: '저장',
+ },
+ },
+ notImplemented: '이 기능은 아직 구현되지 않았습니다',
+ },
+}
diff --git a/src/lang/ptBR.ts b/src/lang/ptBR.ts
new file mode 100644
index 00000000..ae0433e7
--- /dev/null
+++ b/src/lang/ptBR.ts
@@ -0,0 +1,2050 @@
+export const ptBR = {
+ aiPermissions: {
+ ultimateOnly: 'As configurações de IA por conexão exigem o Ultimate',
+ accessLevel: 'Nível de acesso',
+ unavailable: 'Indisponível',
+ loadError: 'Não foi possível carregar as permissões',
+ saving: 'Salvando…',
+ deniedByConnection: 'Negado pelas permissões da conexão',
+ conversationReadOnly: 'Somente leitura nesta conversa',
+ title: 'Permissões de IA',
+ help: 'Aplica-se ao Data Studio e a clientes MCP externos. Use os padrões do sistema ou defina permissões para esta conexão.',
+ loading: 'Carregando permissões…',
+ loadFailed: 'Não foi possível carregar as permissões. Tente novamente antes de salvar esta conexão.',
+ retry: 'Tentar novamente',
+ inherit: 'Usar padrão do sistema',
+ none: 'Sem acesso',
+ read: 'Leitura',
+ data: 'Ler e modificar dados',
+ full: 'Acesso completo',
+ custom: 'Personalizado',
+ effective: 'Acesso efetivo',
+ create: 'Criar dados',
+ update: 'Atualizar dados',
+ delete: 'Excluir dados',
+ manage: 'Gerenciar estrutura e administração',
+ allow: 'Permitir',
+ deny: 'Negar',
+ fromConnection: 'Esta conexão',
+ defaults: 'Permissões padrão de IA',
+ defaultsHelp: 'Aplica-se ao Data Studio e a clientes MCP externos. As conexões seguem estes padrões, a menos que uma ação seja definida na conexão.',
+ save: 'Salvar padrões',
+ saved: 'Permissões salvas',
+ saveFailed: 'Não foi possível salvar as permissões',
+ inheritHelp: 'Segue os padrões do sistema, incluindo alterações futuras.',
+ noneHelp: 'Sem acesso a dados ou ações administrativas.',
+ readHelp: 'Lê dados e inspeciona a estrutura; sem alterações.',
+ dataHelp: 'Alterações de dados, incluindo exclusão. Sem alterações de estrutura ou administrativas.',
+ fullHelp: 'Todas as ações de dados, alterações de estrutura e administração.',
+ customHelp: 'Escolha quais ações individuais a IA pode executar.',
+ defaultDecision: 'Usar padrão ({decision})',
+ readPreset: 'Somente leitura',
+ },
+
+ device: {
+ replaceTitle: 'Limite de dispositivos atingido',
+ replaceDescription:
+ 'Sua assinatura pode permanecer ativada em até {limit} dispositivos. Escolha um dispositivo abaixo para substituí-lo por este — o dispositivo substituído perde o acesso imediatamente.',
+ slotUsage: '{used}/{limit} dispositivos em uso',
+ thisDevice: 'Este dispositivo',
+ lastActive: 'Última atividade',
+ neverActive: 'Nunca',
+ replaceConfirm: 'Substituir e ativar',
+ replaceFailed: 'Falha ao substituir o dispositivo. Escolha outro e tente novamente.',
+ },
+ plan: {
+ tab: 'Conta e plano',
+ pricing: 'Ultimate $9,9/mês · $99/ano · 7 dias de teste gratuito',
+ state: {
+ ultimate: 'Ultimate',
+ community: 'Community',
+ unknown: 'Desconhecido',
+ checking: 'Verificando…',
+ },
+ gate: {
+ additive: 'Tudo do Community, além de:',
+ recommended: 'Recomendado',
+ currentFeature: 'Este recurso',
+ trustLine: 'O bloqueio de versão mantém as versões pagas suas · Cancele quando quiser',
+ headline: {
+ ai: 'Pergunte aos seus dados em linguagem natural',
+ transfer: 'Mova dados em massa — rápido e seguro',
+ er_diagram: 'Veja seu schema como um mapa',
+ ssh_tunnel: 'Acesse bancos de dados remotos via SSH',
+ mcp_bridge: 'Traga o SQLKit para a sua stack de agentes',
+ },
+ tiles: {
+ aiQueryT: 'Consultas em linguagem natural',
+ aiQueryD: 'Pergunte em linguagem natural e receba SQL editável',
+ aiAgentT: 'Explain e correção com agente',
+ aiAgentD: 'Um clique para otimizar consultas lentas',
+ mcpServerT: 'Servidor MCP integrado',
+ mcpServerD: 'Executa localmente — zero configuração',
+ mcpClientsT: 'Qualquer cliente MCP',
+ mcpClientsD: 'Claude Desktop, Cursor e mais',
+ },
+ groups: {
+ cloud: 'Nuvem',
+ local: 'Local',
+ custom: 'Personalizado',
+ clients: 'Clientes',
+ },
+ detail: {
+ ai: 'Funciona com qualquer modelo — nuvem, local ou personalizado',
+ mcp: 'Conecta-se aos seus clientes MCP favoritos',
+ },
+ price: {
+ yearly: '$99 / ano',
+ save: 'Economize 17%',
+ monthly: '$9,9 / mês',
+ },
+ trust: {
+ versionLock: 'Versões lançadas durante a assinatura continuam suas, mesmo offline',
+ byok: 'Traga sua própria chave de LLM — sem marcação nos tokens',
+ cancel: 'Cancele quando quiser',
+ },
+ cta: {
+ unlock: 'Desbloqueie com o Ultimate',
+ unlockSub: 'Teste gratuito de 7 dias · $9,9/mês · $99/ano',
+ },
+ },
+ poster: {
+ mcp: {
+ clients: 'Funciona com',
+ config: 'Configuração do cliente',
+ },
+ ai: {
+ question: 'Encontre pagamentos com falha dos últimos 7 dias',
+ loop: 'Loop 1',
+ thinking: 'Pensando',
+ toolVerb: 'Consultou public.orders',
+ answer: 'Encontrados 3 pagamentos com falha — a consulta gerada:',
+ },
+ transfer: {
+ scopeDatabase: 'Banco de dados inteiro',
+ },
+ },
+ compare: {
+ ai: 'Assistente de IA e NL2SQL',
+ er_diagram: 'Diagramas ER',
+ transfer: 'Importação/exportação em massa e migração',
+ ssh: 'Túnel SSH',
+ mcp: 'Ponte MCP',
+ versionLock: 'Bloqueio de versão',
+ },
+ upgrade: {
+ title: 'Faça upgrade para o Ultimate',
+ cta: 'Fazer upgrade',
+ refresh: 'Atualizar benefícios',
+ startFree: 'Começar grátis',
+ versionPermanent: 'As versões assinadas podem ser usadas para sempre, mesmo offline.',
+ versionLockedOut: 'Esta versão exige uma assinatura ativa para desbloquear. Renove para desbloqueá-la permanentemente.',
+ },
+ section: {
+ title: 'Conta e plano',
+ desc: 'Benefícios da assinatura e estado do bloqueio de versão desta instalação.',
+ versionPermanent: 'A versão atual pode ser usada para sempre (coberta pelo seu bloqueio de versão).',
+ subscriptionActive: 'O Ultimate está ativo — todos os recursos ficam desbloqueados durante a assinatura.',
+ versionLockedOut: 'Esta versão ({date}) não está coberta por um bloqueio de versão — exibindo o modo Community.',
+ expiresAt: 'Ativo até {time}',
+ cancelScheduled: 'A assinatura está programada para terminar no encerramento do ciclo de faturamento atual.',
+ checkFailed: 'Não foi possível verificar os benefícios — exibindo o estado em cache. Verifique sua rede e atualize.',
+ sessionExpired: 'Sessão expirada — entre novamente para verificar seu plano.',
+ sessionLostSignedOut: 'Sua sessão não pode mais ser renovada — você foi desconectado. Entre novamente quando quiser.',
+ deviceActivationFailed: 'Falha no registro do dispositivo — a renovação automática de sessão está indisponível.',
+ notLoggedIn: 'Você não está conectado.',
+ loginLink: 'Entrar com Geekfun',
+ refresh: 'Atualizar',
+ logout: 'Sair',
+ manage: 'Gerenciar assinatura',
+ },
+ },
+ aside: {
+ aiAssistant: 'Assistente de IA',
+ tasks: 'Tarefas',
+ },
+ connection: {
+ prompt: {
+ title: 'Prompt do agente',
+ label: 'Prompt do agente',
+ description: 'Adicione contexto sobre esta conexão para o agente de IA.',
+ help: 'Enviado ao agente sempre que esta conexão é anexada, após o prompt de sistema global.',
+ placeholder: 'Descreva o significado de negócio dos dados, convenções de nomenclatura ou consultas comuns.',
+ configured: 'Configurado',
+ add: 'Adicionar',
+ edit: 'Editar',
+ clear: 'Limpar',
+ cancel: 'Cancelar',
+ confirm: 'Confirmar',
+ },
+ },
+ connectionsPage: {
+ addSshProfile: 'Adicionar perfil SSH',
+ copySuffix: ' (Cópia)',
+ sshProfilesSection: 'Perfis SSH',
+ sshProfile: 'Perfil SSH',
+ },
+ common: {
+
+ copy: 'Copiar',
+ copied: 'Copiado!',
+ browse: 'Procurar',
+ settings: 'Configurações',
+ loading: 'Carregando...',
+ notifications: {
+ codeCopied: 'Código copiado',
+ },
+ buttons: {
+ create: 'Criar',
+ save: 'Salvar',
+ cancel: 'Cancelar',
+ delete: 'Excluir',
+ edit: 'Editar',
+ confirm: 'Confirmar',
+ test: 'Testar',
+ connect: 'Conectar',
+ disconnect: 'Desconectar',
+ duplicate: 'Duplicar',
+ saveChanges: 'Salvar alterações',
+ createConnection: 'Criar conexão',
+ testConnection: 'Testar conexão',
+ dismiss: 'Dispensar',
+ close: 'Fechar',
+ browse: 'Procurar',
+ retry: 'Tentar novamente',
+ continue: 'Continuar',
+ refresh: 'Atualizar',
+ },
+ status: {
+ connected: 'Conectado',
+ disconnected: 'Desconectado',
+ connecting: 'Conectando...',
+ error: 'Erro de conexão',
+ testing: 'Testando conexão...',
+ success: 'Conexão bem-sucedida!',
+ failed: 'Falha na conexão',
+ },
+ },
+ ssl: {
+ errors: {
+ invalidMode: 'Modo SSL inválido',
+ caCertRequired: 'O caminho do certificado CA é obrigatório para os modos verify-ca/verify-full',
+ invalidCaPath: 'Caminho do certificado CA inválido',
+ invalidCertPath: 'Caminho do certificado do cliente inválido',
+ invalidKeyPath: 'Caminho da chave privada do cliente inválido',
+ },
+ mode: {
+ label: 'Modo SSL/TLS',
+ disable: 'Desativar',
+ prefer: 'Preferir',
+ require: 'Exigir',
+ verifyca: 'Verificar CA',
+ verifyfull: 'Verificação completa',
+ },
+ modeDesc: {
+ disable: 'Sem criptografia',
+ prefer: 'Tenta criptografia, com retorno para texto simples',
+ require: 'Sempre criptografa, sem validação de certificado',
+ verifyca: 'Criptografa + verifica o certificado CA',
+ verifyfull: 'Criptografa + verifica CA e host',
+ },
+ certSettings: {
+ title: 'Configurações de certificado',
+ caCert: 'Certificado CA',
+ caCertPlaceholder: 'Caminho do certificado CA',
+ clientCert: 'Certificado do cliente',
+ clientCertPlaceholder: 'Caminho do certificado do cliente',
+ clientKey: 'Chave privada do cliente',
+ clientKeyPlaceholder: 'Caminho da chave privada do cliente',
+ },
+ sqlServer: {
+ trustServerCert: 'Confiar no certificado do servidor',
+ trustServerCertHint: 'Aceita certificados autoassinados',
+ },
+ },
+ transfer: {
+ title: 'Transferência',
+ subtitle: 'Importe, exporte e migre seus dados',
+ tabs: {
+ export: 'Exportar',
+ import: 'Importar',
+ migration: 'Migração',
+ structure: 'Estrutura',
+ },
+ export: {
+ step: {
+ source: 'Origem',
+ format: 'Formato',
+ output: 'Saída',
+ formatOutput: 'Formato e saída',
+ preview: 'Pré-visualização',
+ execute: 'Iniciar exportação',
+ },
+ selectTablesFirst: 'Selecione tabelas acima para configurar as colunas',
+ tables: {
+ label: 'Tabelas',
+ loadFailed: 'Falha ao carregar as tabelas',
+ },
+ columns: {
+ label: 'Colunas',
+ selectAll: 'Selecionar tudo',
+ deselectAll: 'Desmarcar tudo',
+ loadFailed: 'Falha ao carregar as colunas',
+ },
+ whereClause: 'Cláusula WHERE (opcional)',
+ where: 'Cláusula WHERE (opcional)',
+ whereClausePlaceholder: 'status = "active"',
+ orderBy: 'ORDER BY (opcional)',
+ orderByPlaceholder: 'created_at DESC',
+ limit: 'LIMIT (opcional)',
+ limitPlaceholder: '1000',
+ scope: 'Escopo',
+ delimiter: 'Delimitador',
+ delimiterOptions: {
+ comma: 'Vírgula (,)',
+ semicolon: 'Ponto e vírgula (;)',
+ tab: 'Tabulação',
+ },
+ includeHeader: 'Incluir cabeçalho',
+ dateFormat: 'Formato de data',
+ dateFormatOptions: {
+ iso8601: 'ISO 8601',
+ unix: 'Unix',
+ },
+ rowsPerBatch: 'Linhas/lote',
+ createTable: 'CREATE TABLE',
+ dropTable: 'DROP TABLE',
+ worksheet: 'Planilha',
+ freeze: 'Congelar',
+ autoFit: 'Ajuste automático',
+ outputPath: 'Caminho de saída',
+ selectFormat: 'Selecionar formato',
+ showAdvanced: 'Mostrar opções avançadas',
+ hideAdvanced: 'Ocultar opções avançadas',
+ encoding: 'Codificação',
+ preview: 'Pré-visualização',
+ outputFile: 'Arquivo de saída',
+ },
+ connection: {
+ connectFailed: 'Falha ao conectar',
+ databasesFailed: 'Falha ao carregar os bancos de dados',
+ schemasFailed: 'Falha ao carregar os schemas',
+ label: 'Conexão',
+ placeholder: 'Selecionar conexão',
+ noConnections: 'Nenhuma conexão disponível. Adicione uma conexão primeiro.',
+ connected: 'Conectado',
+ offline: 'Offline',
+ databaseLabel: 'Banco de dados',
+ databasePlaceholder: 'Selecionar banco de dados',
+ system: 'Sistema',
+ loadingDatabases: 'Carregando bancos de dados...',
+ schemaLabel: 'Schema',
+ schemaPlaceholder: 'Selecionar schema',
+ loadingSchemas: 'Carregando schemas...',
+ tableLabel: 'Tabela',
+ tablePlaceholder: 'Selecionar tabela',
+ },
+ import: {
+ step: {
+ file: 'Selecionar arquivo',
+ mapping: 'Destino e mapeamento',
+ options: 'Opções e pré-visualização',
+ execute: 'Importar',
+ },
+ dropzone: {
+ title: 'Arraste e solte um arquivo aqui',
+ subtitle: 'ou clique para procurar',
+ supported: 'Suportados: CSV, JSONL, SQL, Excel (.xlsx)',
+ instruction: 'ou clique para procurar no seu computador',
+ },
+ detected: {
+ format: 'Formato detectado',
+ encoding: 'Codificação detectada',
+ rows: 'Linhas (estimado)',
+ },
+ autoMap: 'Mapear automaticamente por nome',
+ clearAll: 'Limpar tudo',
+ conflict: {
+ label: 'Em caso de conflito',
+ skip: 'Ignorar duplicadas',
+ replace: 'Substituir existentes',
+ upsert: 'Atualizar existentes (upsert)',
+ abort: 'Abortar em caso de erro',
+ },
+ truncateBefore: 'Truncar a tabela antes de importar',
+ dryRun: 'Simulação (validar sem inserir)',
+ browseFiles: 'Procurar arquivos',
+ fileSize: 'Tamanho do arquivo',
+ detectedColumns: 'Colunas detectadas',
+ createDbIfNotExists: 'Criar banco de dados se não existir',
+ tablesAutoCreated: 'As tabelas serão criadas automaticamente',
+ skipPlaceholder: 'Ignorar',
+ skip: '(Ignorar)',
+ importData: 'Importar dados',
+ dataPreview: 'PRÉ-VISUALIZAÇÃO DOS DADOS',
+ previewRows: '10 linhas',
+ selectFileToPreview: 'Selecione um arquivo para pré-visualizar os dados',
+ importSettings: 'CONFIGURAÇÕES DE IMPORTAÇÃO',
+ batchSize: 'Tamanho do lote',
+ loadingPreview: 'Carregando pré-visualização...',
+ noPreviewData: 'Sem dados de pré-visualização',
+ fileDetails: 'DETALHES DO ARQUIVO',
+ },
+ structure: {
+ title: 'Estrutura',
+ subtitle: 'Gere DDL e execute arquivos SQL',
+ generateDdl: 'Gerar DDL',
+ runSqlFile: 'Executar arquivo SQL',
+ objects: 'Objetos do banco de dados',
+ selectAll: 'Selecionar tudo',
+ deselectAll: 'Desmarcar tudo',
+ loadingObjects: 'Carregando objetos...',
+ noObjects: 'Nenhum objeto encontrado. Selecione uma conexão e um banco de dados.',
+ objectsSelected: 'objetos selecionados',
+ options: 'Opções de DDL',
+ includeCreateTable: 'Instruções CREATE TABLE',
+ includePrimaryKeys: 'Chaves primárias',
+ includeForeignKeys: 'Chaves estrangeiras',
+ includeIndexes: 'Índices',
+ includeDropIfExists: 'DROP IF EXISTS antes de CREATE',
+ includeIfNotExists: 'IF NOT EXISTS no CREATE',
+ generate: 'Gerar DDL',
+ preview: 'Pré-visualização do DDL',
+ copyToClipboard: 'Copiar para a área de transferência',
+ saveToFile: 'Salvar em arquivo...',
+ sqlFile: 'Arquivo SQL',
+ errorHandling: 'Tratamento de erros',
+ onErrorStop: 'Parar no primeiro erro',
+ onErrorSkip: 'Ignorar e continuar',
+ onErrorRollback: 'Rollback (melhor esforço; aborta no primeiro erro)',
+ reset: 'Redefinir',
+ execute: 'Executar',
+ },
+ migration: {
+ title: 'Migração',
+ subtitle: 'Migração de dados entre mecanismos',
+ step: {
+ source: 'Origem',
+ target: 'Destino',
+ mapping: 'Mapeamento',
+ configure: 'Configurar',
+ execute: 'Executar',
+ },
+ sourceConnection: 'Conexão de origem',
+ targetConnection: 'Conexão de destino',
+ availableTables: 'Tabelas disponíveis',
+ loadingTables: 'Carregando tabelas...',
+ noTables: 'Nenhuma tabela encontrada',
+ selectAll: 'Selecionar tudo',
+ deselectAll: 'Desmarcar tudo',
+ tablesSelected: 'tabelas selecionadas',
+ direction: 'Direção da migração',
+ createTables: 'Criar as tabelas de destino se não existirem',
+ dropTables: 'Excluir as tabelas de destino antes da migração',
+ loadingMapping: 'Gerando mapeamentos de tipos...',
+ typeConversions: 'colunas exigem conversão de tipo',
+ batchSize: 'Tamanho do lote',
+ onError: 'Em caso de erro',
+ onErrorSkipRow: 'Ignorar linha e continuar',
+ onErrorSkipTable: 'Ignorar tabela e continuar',
+ onErrorAbort: 'Abortar migração',
+ migrateIndexes: 'Migrar índices',
+ migrateForeignKeys: 'Migrar chaves estrangeiras',
+ migrateConstraints: 'Migrar restrições',
+ summary: 'Resumo da migração',
+ tables: 'Tabelas',
+ totalRows: 'Total de linhas',
+ conversions: 'Conversões de tipo',
+ executing: 'Executando migração...',
+ pleaseWait: 'Aguarde enquanto os dados são transferidos',
+ startMigration: 'Iniciar migração',
+ migrateAgain: 'Migrar novamente',
+ back: 'Voltar',
+ next: 'Avançar',
+ },
+ format: {
+ label: 'Formato',
+ csv: 'CSV (.csv)',
+ jsonl: 'JSONL (.jsonl)',
+ sql: 'SQL (.sql)',
+ excel: 'Excel (.xlsx)',
+ defaults: {
+ csv: 'Delimitador vírgula, aspas duplas, UTF-8, incluir cabeçalho',
+ jsonl: 'Um objeto JSON por linha, compacto, UTF-8, datas ISO 8601',
+ sql: 'Tabela de destino preenchida automaticamente, tamanho de lote 1000, incluir CREATE TABLE',
+ excel: 'Incluir cabeçalho, ajustar colunas automaticamente, congelar linha de cabeçalho',
+ },
+ advancedOptions: 'Opções avançadas',
+ },
+ progress: {
+ preparing: 'Preparando',
+ exporting: 'Exportando...',
+ importing: 'Importando...',
+ elapsed: 'Decorrido',
+ remaining: 'Restante estimado',
+ rows: 'Linhas',
+ exported: 'exportadas',
+ imported: 'importadas',
+ skipped: 'ignoradas',
+ errors: 'erros',
+ cancel: 'Cancelar',
+ runInBackground: 'Executar em segundo plano',
+ },
+ result: {
+ success: 'concluído com sucesso',
+ partial: 'concluído com erros',
+ failed: 'falhou',
+ duration: 'Duração',
+ file: 'Arquivo',
+ openFile: 'Abrir arquivo',
+ openFolder: 'Abrir pasta',
+ exportAgain: 'Exportar novamente',
+ importAgain: 'Importar novamente',
+ viewTable: 'Ver tabela',
+ processed: 'Processadas',
+ skipped: 'Ignoradas',
+ errorCount: 'Erros',
+ },
+ tasks: {
+ title: 'Tarefas',
+ clearCompleted: 'Limpar concluídas',
+ goToTask: 'Ir para a tarefa',
+ dismiss: 'Dispensar',
+ noTasks: 'Nenhuma tarefa de transferência',
+ rows: 'linhas',
+ emptyDescription: 'Trabalhos de exportação, importação e migração aparecerão aqui',
+ status: {
+ pending: 'Pendente',
+ running: 'Em execução',
+ completed: 'Concluída',
+ failed: 'Falhou',
+ },
+ startedAgo: 'Iniciada há {time}',
+ },
+ common: {
+
+ connection: 'Conexão',
+ database: 'Banco de dados',
+ schema: 'Schema',
+ table: 'Tabela',
+ back: 'Voltar',
+ next: 'Avançar',
+ browse: 'Procurar...',
+ error: 'Erro',
+ cancel: 'Cancelar',
+ save: 'Salvar',
+ close: 'Fechar',
+ tableName: 'Nome da tabela',
+ rows: 'Linhas',
+ type: 'Tipo',
+ noTablesFound: 'Nenhuma tabela encontrada',
+ columns: 'Colunas',
+ deselectAll: 'Desmarcar tudo',
+ scopeServer: 'Servidor',
+ scopeDatabase: 'Banco de dados',
+ scopeTables: 'Tabelas',
+ },
+ },
+ pages: {
+ connections: {
+ title: 'Conexões',
+ subtitle: 'Gerencie suas conexões de banco de dados',
+ search: 'Pesquisar conexões...',
+ stats: {
+ totalConnections: 'Total de conexões',
+ activeSessions: 'Sessões ativas',
+ sshProfiles: 'Perfis SSH',
+ ago: 'há {time}',
+ },
+ saved: 'Conexões salvas',
+ addNew: 'Adicionar nova conexão',
+ addNewHint: 'PostgreSQL, MySQL, SQLite...',
+ empty: {
+ title: 'Nenhuma conexão encontrada',
+ message: 'Nenhuma conexão corresponde à sua pesquisa por "{query}"',
+ },
+ delete: {
+ title: 'Excluir conexão',
+ message: 'Tem certeza de que deseja excluir "{name}"? Esta ação não pode ser desfeita.',
+ },
+ error: {
+ title: 'Erro de conexão',
+ },
+ saveFailed: 'Falha ao salvar a conexão',
+ },
+ settings: {
+ title: 'Configurações',
+ subtitle: 'Configure as preferências do aplicativo',
+ general: {
+ title: 'Geral',
+ description: 'Gerencie sua conta, plano, tema e atualizações do aplicativo',
+ theme: 'Tema',
+ themeSelect: 'Selecionar tema',
+ themeHelp: 'Escolha entre tema claro, escuro ou do sistema',
+ themes: {
+ light: 'Claro',
+ dark: 'Escuro',
+ system: 'Sistema',
+ },
+ language: 'Idioma',
+ languageSelect: 'Selecionar idioma',
+ languageHelp: 'Escolha seu idioma preferido',
+ languages: {
+ enUS: 'English',
+ zhCN: '简体中文',
+ auto: 'Automático (seguir o sistema)',
+ },
+ },
+ mcp: {
+ title: 'Ponte MCP',
+ status: 'Status',
+ running: 'Em execução na porta {port}',
+ stopped: 'Parado',
+ port: 'Porta',
+ portDesc: 'Porta do servidor da ponte MCP (deixe vazio para automática)',
+ restart: 'Reiniciar ponte',
+ restartSuccess: 'Ponte MCP reiniciada com sucesso',
+ restartFailed: 'Falha ao reiniciar',
+ restartFailedDetail: 'Falha ao reiniciar a ponte MCP',
+ restartTimeout: 'A ponte MCP não iniciou em 60 segundos',
+ shuttingDown: 'Desligando...',
+ starting: 'Iniciando...',
+ autoStart: 'Início automático',
+ autoStartDesc: 'Inicia a ponte MCP automaticamente ao abrir o aplicativo',
+ saveFailed: 'Falha ao salvar as configurações de MCP',
+ },
+ about: {
+ title: 'Sobre',
+ version: 'Versão',
+ license: 'Licença',
+ licenseName: 'Apache 2.0',
+ repository: 'Repositório',
+ website: 'Site',
+ copyright: '© {year} GEEKFUN. Todos os direitos reservados.',
+ description: 'SqlKit é um cliente GUI multiplataforma e agêntico para bancos de dados SQL. Construído com Rust + Tauri.',
+ },
+ feedback: {
+ preparing: 'Preparando download…',
+ downloading: 'Baixando…',
+ installing: 'Instalando e verificando…',
+ complete: 'Instalação concluída',
+ failed: 'Falha na ação',
+ checking: 'Verificando atualizações…',
+ removing: 'Removendo…',
+ removed: 'Removido com sucesso',
+ refreshing: 'Atualizando status…',
+ refreshed: 'Status atualizado',
+ loading: 'Carregando configurações…',
+ loadFailed: 'Não foi possível carregar esta seção',
+ retry: 'Tentar novamente',
+ saved: 'Alterações salvas',
+ saving: 'Salvando alterações…',
+ testing: 'Testando conexão…',
+ syncing: 'Sincronizando modelos…',
+ synced: 'Modelos sincronizados',
+ opening: 'Abrindo no seu navegador…',
+ opened: 'Aberto no seu navegador',
+ signedOut: 'Sessão encerrada',
+ },
+ jre: {
+ title: 'JRE e drivers',
+ description: 'Gerencie o Java Runtime e os drivers JDBC para conexões de banco de dados',
+ jreCard: {
+ title: 'Java Runtime',
+ description: 'Necessário para conexões via ponte JDBC (Oracle, DB2, H2, Derby)',
+ status: {
+ installed: 'Instalado',
+ notInstalled: 'Não instalado',
+ checking: 'Verificando...',
+ managed: 'Gerenciado',
+ system: 'Sistema',
+ versionUnknown: 'Desconhecida',
+ systemWarning: 'A versão do Java do sistema é desconhecida ou incompatível. Baixe o JRE gerenciado para garantir compatibilidade.',
+ systemInvalid: 'Sem JRE válido',
+ managedRecommended: 'Usar JRE gerenciado',
+ },
+ actions: {
+ download: 'Baixar JRE',
+ remove: 'Remover JRE',
+ redownload: 'Baixar novamente',
+ checkUpdates: 'Verificar atualizações',
+ },
+ notifications: {
+ upToDate: 'O JRE está atualizado',
+ updateAvailable: 'Atualização do JRE disponível',
+ newVersion: 'Versão {version} disponível',
+ checkUpdatesFailed: 'Falha ao verificar atualizações do JRE',
+ downloadFailed: 'Falha ao baixar o JRE',
+ downloadSuccess: 'JRE baixado com sucesso',
+ removeFailed: 'Falha ao remover o JRE',
+ },
+ },
+ bridgeCard: {
+ title: 'JAR da ponte',
+ description: 'Componente da ponte JDBC para conexões de banco de dados',
+ status: {
+ installed: 'Instalado',
+ notInstalled: 'Não instalado',
+ checking: 'Verificando...',
+ },
+ actions: {
+ download: 'Baixar ponte',
+ remove: 'Remover ponte',
+ },
+ notifications: {
+ downloadFailed: 'Falha ao baixar o JAR da ponte',
+ downloadSuccess: 'JAR da ponte baixado com sucesso',
+ removeFailed: 'Falha ao remover o JAR da ponte',
+ },
+ },
+ jdbcToggle: {
+ title: 'Conexões JDBC',
+ description: 'Ativa o suporte a bancos de dados JDBC (JRE + ponte + drivers)',
+ label: 'JDBC não necessário',
+ },
+ actions: {
+ refresh: 'Atualizar',
+ },
+ driversCard: {
+ title: 'Drivers JDBC',
+ description: 'Arquivos de driver JDBC específicos por banco de dados',
+ label: {
+ versions: 'versões',
+ },
+ status: {
+ installed: 'Instalado',
+ notInstalled: 'Não instalado',
+ loading: 'Carregando drivers...',
+ },
+ actions: {
+ download: 'Baixar',
+ remove: 'Remover',
+ checkUpdates: 'Verificar atualizações',
+ },
+ notifications: {
+ upToDate: 'O driver está atualizado',
+ updateAvailable: 'Atualização do driver disponível',
+ newVersion: 'Versão {version} disponível',
+ checkUpdatesFailed: 'Falha ao verificar atualizações do driver',
+ downloadFailed: 'Falha ao baixar o driver',
+ downloadSuccess: 'Driver baixado com sucesso',
+ removeFailed: 'Falha ao remover o driver',
+ installBridgeFirst: 'Instale o JAR da ponte primeiro e tente baixar os drivers',
+ },
+ empty: {
+ title: 'Nenhum driver configurado',
+ message: 'Eles serão baixados automaticamente quando você se conectar a um banco de dados JDBC.',
+ },
+ },
+ },
+ editor: {
+ title: 'Editor',
+ description: 'Configure o comportamento e a aparência do editor SQL',
+ fontSize: 'Tamanho da fonte',
+ fontSizeHelp: 'Tamanho da fonte do editor em pixels (8–32)',
+ fontSizeError: 'O tamanho da fonte deve estar entre 8 e 32',
+ tabSize: 'Tamanho da tabulação',
+ tabSizeHelp: 'Número de espaços por tabulação (1–8)',
+ tabSizeError: 'O tamanho da tabulação deve estar entre 1 e 8',
+ wordWrap: 'Quebra de linha',
+ wordWrapHelp: 'Quebra linhas longas no editor',
+ showLineNumbers: 'Mostrar números de linha',
+ showLineNumbersHelp: 'Exibe números de linha na margem do editor',
+ showMinimap: 'Mostrar minimapa',
+ showMinimapHelp: 'Mostra uma visão geral em minimapa à direita',
+ indentWidth: 'Largura do recuo',
+ indentWidthHelp: 'Espaços por nível de recuo no SQL formatado (1–8)',
+ indentWidthError: 'A largura do recuo deve estar entre 1 e 8',
+ lineWidth: 'Largura da linha',
+ lineWidthHelp: 'Largura alvo da linha em caracteres para o SQL formatado (40–200)',
+ lineWidthError: 'A largura da linha deve estar entre 40 e 200',
+ },
+ query: {
+ title: 'Consulta',
+ description: 'Configure os padrões de execução de consultas',
+ defaultLimit: 'Limite padrão de linhas',
+ defaultLimitHelp: 'Máximo de linhas retornadas por consulta (10–10000)',
+ defaultLimitError: 'O limite de linhas deve estar entre 10 e 10000',
+ queryTimeout: 'Tempo limite da consulta (s)',
+ queryTimeoutHelp: 'Tempo máximo de execução da consulta em segundos (1–300)',
+ queryTimeoutError: 'O tempo limite deve estar entre 1 e 300 segundos',
+ autoSave: 'Salvamento automático',
+ autoSaveHelp: 'Salva automaticamente as alterações da consulta',
+ },
+ ai: {
+ title: 'Configurações de IA',
+ tabLabel: 'LLMs',
+ description: 'Configure provedores de modelos de IA e o comportamento do chat',
+ missing: 'Nenhum modelo de IA configurado. Adicione um provedor e selecione um modelo nas Configurações.',
+ providerList: {
+ title: 'Provedores',
+ description: 'Gerencie seus provedores de modelos de IA',
+ addProvider: 'Adicionar provedor',
+ empty: 'Nenhum provedor configurado. Adicione um para ativar os recursos de IA.',
+ emptyAction: 'Adicionar seu primeiro provedor',
+ deleteConfirm: 'Tem certeza de que deseja excluir "{name}"?',
+ deleteConfirmTitle: 'Excluir provedor',
+ sync: 'Sincronizar modelos',
+ syncing: 'Sincronizando...',
+ syncSuccess: '{count} modelos sincronizados',
+ syncFailed: 'Falha ao sincronizar os modelos',
+ modelCount: '{count} modelos',
+ testConnection: 'Testar',
+ testing: 'Testando...',
+ testSuccess: 'Conexão bem-sucedida',
+ testFailed: 'Falha no teste de conexão',
+ },
+ form: {
+ addTitle: 'Adicionar provedor',
+ editTitle: 'Editar provedor',
+ providerType: 'Tipo de provedor',
+ providerTypeHelp: 'Selecione uma opção predefinida ou escolha Personalizado para outros provedores',
+ presetOpenai: 'OpenAI',
+ presetAnthropic: 'Anthropic',
+ presetAzure: 'Azure OpenAI',
+ presetCustom: 'Personalizado',
+ name: 'Nome de exibição',
+ namePlaceholder: 'Meu provedor',
+ nameHelp: 'Um nome fácil de lembrar para este provedor',
+ apiCompatibility: 'Compatibilidade de API',
+ apiCompatibilityPlaceholder: 'openai, anthropic, azure',
+ apiCompatibilityHelp: 'Tipo de protocolo da API. Use "openai" para serviços compatíveis como Ollama ou DeepSeek.',
+ apiKey: 'Chave de API',
+ apiKeyPlaceholder: 'sk-...',
+ apiKeyHelp: 'Sua chave de API do provedor. Armazenada localmente e nunca enviada aos nossos servidores.',
+ baseUrl: 'URL base',
+ baseUrlPlaceholder: 'https://api.openai.com/v1',
+ baseUrlHelp: 'URL do endpoint da API. Mantenha o padrão para provedores oficiais.',
+ proxy: 'Proxy',
+ proxyPlaceholder: 'http://proxy:8080',
+ proxyHelp: 'Proxy HTTP/SOCKS5 opcional para solicitações de API',
+ proxyMode: 'Modo de proxy',
+ contextWindow: 'Substituir janela de contexto',
+ contextWindowHelp: 'Substitui o tamanho padrão da janela de contexto (opcional)',
+ showKey: 'Mostrar',
+ hideKey: 'Ocultar',
+ save: 'Salvar provedor',
+ models: 'Modelos',
+ modelsPlaceholder: 'gpt-4o, gpt-4o-mini',
+ modelsHelp: 'IDs de modelos separados por vírgula. Sincronizados automaticamente da API do provedor, se disponível.',
+ validation: {
+ nameRequired: 'O nome de exibição é obrigatório',
+ apiCompatibilityRequired: 'A compatibilidade de API é obrigatória',
+ invalidApiCompatibility: 'A compatibilidade de API deve ser "openai", "anthropic" ou "azure"',
+ baseUrlInvalid: 'A URL base deve começar com http:// ou https://',
+ },
+ },
+ chat: {
+ title: 'Agente',
+ description: 'Configure o comportamento de execução do agente',
+ autoCompactLabel: 'Compactar mensagens automaticamente',
+ autoCompactDescription: 'Resume mensagens antigas automaticamente para economizar tokens ao se aproximar dos limites de contexto',
+ maxIterationsLabel: 'Máx. de iterações',
+ maxIterationsDescription: 'Número máximo de iterações de chamadas de ferramenta antes de o agente parar (1–1000)',
+ wallClockBudgetLabel: 'Limite de tempo total (min)',
+ wallClockBudgetDescription: 'Tempo máximo total em minutos antes de o agente parar (1–240)',
+ tokenBudgetLabel: 'Orçamento de tokens',
+ tokenBudgetDescription: 'Máximo de tokens consumidos antes de o agente parar',
+ systemPromptLabel: 'Prompt de sistema',
+ systemPromptDescription: 'Prompt de sistema global enviado ao agente quando uma conexão de banco de dados é anexada. Descreva seu uso, terminologia ou contexto de negócio.',
+ systemPromptAdd: 'Adicionar prompt de sistema',
+ systemPromptEdit: 'Editar prompt de sistema',
+ systemPromptDelete: 'Excluir prompt de sistema',
+ systemPromptEmpty: 'Nenhum prompt de sistema configurado.',
+ systemPromptSave: 'Salvar',
+ systemPromptCancel: 'Cancelar',
+ systemPromptSaveFailed: 'Não foi possível salvar o prompt de sistema.',
+ systemPromptUltimateOnly: 'O Prompt do agente é um recurso do Ultimate',
+ },
+ },
+ updates: {
+ title: 'Atualizações',
+ description: 'Verifique atualizações do aplicativo',
+ checkForUpdates: 'Verificar atualizações',
+ checkForUpdatesHelp: 'Verifica automaticamente ao abrir o Geral. As atualizações são instaladas apenas quando você escolhe Atualizar agora.',
+ check: 'Verificar agora',
+ checking: 'Verificando...',
+ downloading: 'Baixando...',
+ installing: 'Instalando...',
+ updateAvailable: 'Atualização disponível',
+ upToDate: 'Você já tem a versão mais recente',
+ checkFailed: 'Falha ao verificar atualizações',
+ downloadFailed: 'Falha ao baixar a atualização',
+ installFailed: 'Falha ao instalar a atualização',
+ installed: 'Atualização instalada. Reiniciando...',
+ newVersion: 'Versão {version} disponível',
+ },
+ },
+ history: {
+ title: 'Histórico',
+ subtitle: 'Veja e gerencie seu histórico de consultas',
+ recent: 'Consultas recentes',
+ recentDescription: 'Suas consultas executadas recentemente',
+ empty: 'Ainda não há histórico de consultas.',
+ search: 'Pesquisar consultas...',
+ filterAll: 'Todas',
+ filterSuccess: 'Sucesso',
+ filterError: 'Erro',
+ clearAll: 'Limpar tudo',
+ clearNonFavorites: 'Limpar não favoritas',
+ clearAllConfirm: 'Tem certeza de que deseja limpar todas as entradas do histórico?',
+ clearNonFavoritesConfirm: 'Tem certeza de que deseja limpar todas as entradas não favoritas do histórico?',
+ columns: {
+ sql: 'SQL',
+ connection: 'Conexão',
+ database: 'Banco de dados',
+ status: 'Status',
+ time: 'Hora',
+ executionTime: 'Duração',
+ actions: 'Ações',
+ },
+ status: {
+ success: 'Sucesso',
+ error: 'Erro',
+ },
+ actions: {
+ rerun: 'Reexecutar no editor',
+ favorite: 'Adicionar aos favoritos',
+ unfavorite: 'Remover dos favoritos',
+ delete: 'Excluir',
+ },
+ notifications: {
+ cleared: 'Histórico limpo',
+ deleted: 'Entrada excluída',
+ rerun: 'Consulta carregada no editor',
+ },
+ },
+ importExport: {
+ title: 'Importar / Exportar',
+ subtitle: 'Importe e exporte seus dados',
+ card: {
+ title: 'Importação / exportação de dados',
+ description: 'Importe e exporte schemas e dados do banco de dados',
+ comingSoon: 'A funcionalidade de importação e exportação estará disponível em uma atualização futura.',
+ },
+ },
+ queries: {
+ title: 'Consultas',
+ subtitle: 'Escreva e execute consultas SQL',
+ selectConnection: 'Selecione uma conexão',
+ selectDatabase: 'Selecione um banco de dados',
+ noTab: 'Nenhuma aba de consulta aberta',
+ newTab: 'Nova consulta',
+ landing: {
+ ready: 'Pronto para escrever consultas',
+ connectedAs: 'Conectado como',
+ currentDatabase: 'Banco de dados',
+ selectConnection: 'Selecionar uma conexão',
+ tip: 'Dica: clique duas vezes em uma tabela na barra lateral para ver os dados',
+ },
+ editor: {
+ title: 'Editor SQL',
+ description: 'Escreva suas consultas SQL aqui',
+ execute: 'Executar',
+ explain: 'Explicar',
+ format: 'Formatar SQL',
+ },
+ shortcuts: {
+ execute: 'Executar consulta ({key}Enter)',
+ explain: 'Explicar consulta (F6)',
+ format: 'Formatar SQL (Shift+Alt+F)',
+ save: 'Salvar ({key}S)',
+ saveAs: 'Salvar como arquivo .sql',
+ comment: 'Alternar comentário ({key}/)',
+ },
+ status: {
+ connection: 'Conexão',
+ database: 'Banco de dados',
+ rows: 'Linhas',
+ time: 'Tempo',
+ executing: 'Executando...',
+ connectionLost: 'Conexão perdida. A conexão com o banco de dados foi encerrada.',
+ reconnecting: 'Reconectando...',
+ },
+ notifications: {
+ querySaved: 'Consulta salva',
+ saveFailed: 'Falha ao salvar',
+ loadFailed: 'Falha ao carregar a consulta',
+ noStatementFound: 'Nenhuma instrução SQL encontrada na posição do cursor',
+ formatFailed: 'Falha ao formatar o SQL',
+ noActiveConnection: 'Nenhuma conexão ativa',
+ selectConnectionFirst: 'Selecione uma conexão e um banco de dados antes de executar uma consulta',
+ tableActionSuccess: 'Tabela {table} {action} com sucesso',
+ tableActionFailed: 'Falha ao {action} a tabela: {error}',
+ },
+ orphanDialog: {
+ title: 'Aba órfã',
+ message: 'Esta aba pertence a outra conexão e não pode executar consultas. Você ainda pode editar e salvar o conteúdo dela.',
+ acknowledge: 'Manter como órfã',
+ close: 'Fechar aba',
+ },
+ executeOrphanDialog: {
+ title: 'Conexão alterada',
+ message: 'A conexão original desta aba de consulta mudou: {from} → {to}. Reconectar à conexão ativa atual e executar?',
+ cancel: 'Cancelar',
+ close: 'Fechar aba',
+ rebindAndExecute: 'Reconectar e executar',
+ },
+ explain: {
+ title: 'Plano de execução',
+ treeView: 'Árvore',
+ summaryView: 'Resumo',
+ rawView: 'Bruto',
+ analyze: 'Explain Analyze',
+ running: 'Gerando o plano de execução...',
+ empty: 'Sem dados do plano de execução',
+ nodeCount: '{count} nós',
+ summary: {
+ totalCost: 'Custo total estimado: {cost}',
+ mostExpensive: 'Mais caro: {node}',
+ noCostData: 'Sem dados de custo',
+ },
+ node: {
+ rowEstimate: 'e:{rows}',
+ actualRows: 'a:{rows}',
+ discrepancyWarning: 'As linhas reais excedem significativamente a estimativa ({actual} vs {estimated}, {ratio}x)',
+ },
+ error: {
+ parseFailed: 'Falha ao analisar o plano de execução',
+ noPlan: 'Nenhum plano de execução retornado pelo banco de dados',
+ },
+ tabLabels: {
+ results: 'Resultados',
+ explain: 'Explicar',
+ },
+ analyzeToggle: 'Alternar o modo EXPLAIN ANALYZE (atualmente: {mode})',
+ columnHeaders: {
+ nodeType: 'Tipo de nó',
+ relation: 'Relação',
+ index: 'Índice',
+ cost: 'Custo',
+ rows: 'Linhas',
+ details: 'Detalhes',
+ },
+ },
+ },
+ },
+ dataStudio: {
+ title: 'DATA STUDIO BETA',
+ subtitle: 'Análise de dados SQL com IA',
+ inputPlaceholder: 'Faça uma pergunta sobre seus dados...',
+ modelUnavailable: 'O modelo selecionado não está disponível',
+ history: {
+ title: 'Histórico',
+ newSession: 'Nova sessão',
+ justNow: 'Agora mesmo',
+ minutesAgo: 'há {count} min',
+ hoursAgo: 'há {count} h',
+ yesterday: 'Ontem',
+ noSessions: 'Nenhuma sessão anterior',
+ messages: 'mensagens',
+ sources: 'fontes',
+ delete: 'Excluir sessão',
+ sessionFallback: 'Chat',
+ empty: 'Nenhuma sessão ainda',
+ },
+ agent: {
+ emptyState: 'Faça uma pergunta ou descreva a consulta que deseja executar.',
+ noSource: 'Anexe uma fonte de dados para começar.',
+ stop: 'Parar',
+ continue: 'Continuar',
+ continueHint: 'O agente foi pausado. Clique em Continuar para retomar ou em Parar para encerrar a sessão.',
+ clearChat: 'Limpar chat',
+ riskSafe: 'Operação segura',
+ riskElevated: 'Risco elevado',
+ riskDestructive: 'Operação destrutiva',
+ allowOnce: 'Permitir uma vez',
+ allowAlways: 'Sempre permitir',
+ deny: 'Negar',
+ denyAlways: 'Sempre negar',
+ cancelRun: 'Cancelar',
+ preparing: 'Preparando...',
+ thinking: 'Pensando',
+ iteration: 'Etapa',
+ waitingModel: 'Aguardando o modelo...',
+ compacting: 'Compactando o contexto...',
+ viewFullResult: 'Ver resultado completo',
+ viewMore: 'mais',
+ message: {
+ toolBlocked: 'Bloqueado',
+ toolRejected: 'Rejeitado',
+ blockedNotice: 'Bloqueado pelas permissões — ação não executada',
+ historicalBlockedNotice: 'Tentativa anterior bloqueada — ação não executada',
+ rejectedNotice: 'Rejeitado por você — ação não executada',
+ interruptedNotice: 'Resultado da execução indisponível',
+ unavailableNotice: 'Ação indisponível — ação não executada',
+ connectionLabel: 'Conexão: {name}',
+ requiredAction: 'Necessário: {action}',
+ reviewPermissions: 'Revisar permissões',
+ reviewHelp: 'Salvar as alterações de permissões não executa a ação bloqueada. Volte ao chat e escolha Repetir solicitação quando estiver pronto.',
+ reviewConnectionHelp: 'As alterações se aplicam apenas a esta conexão. Os padrões do sistema permanecem inalterados. Salve e volte ao chat para repetir a solicitação.',
+ connectionUnavailable: 'Não foi possível identificar a conexão salva. Anexe novamente a conexão no chat antes de revisar as permissões dela.',
+ backToChat: 'Voltar ao chat',
+ retryRequest: 'Repetir solicitação',
+ retryPrompt: 'Repita a solicitação anteriormente bloqueada ou rejeitada usando {tool} com estes argumentos originais:\n{args}\nVerifique novamente as permissões atuais e solicite as aprovações necessárias. Não repita ações anteriormente concluídas com sucesso.',
+ awaitingPermissionDecision: 'Pausado. Revise a ação bloqueada e repita ou envie uma nova solicitação.',
+ removeDenyRule: 'Remover regra de Sempre negar',
+ ruleRemoved: 'Regra removida. Repita a solicitação para verificar o acesso atual e os requisitos de confirmação.',
+ sourceUnavailable: 'A fonte original não está mais disponível nesta conversa. Anexe-a antes de repetir.',
+ denialSource: {
+ system: 'Negado pelos padrões de IA do sistema.',
+ connection: 'Negado pelas permissões de IA desta conexão.',
+ conversation: 'Negado pelas restrições de fonte desta conversa.',
+ rule: 'Uma regra de Sempre negar bloqueia esta ferramenta nesta conversa.',
+ unknown: 'As permissões de IA bloquearam esta ação. Revise o acesso antes de repetir.',
+ },
+ toolDenied: 'Execução da ferramenta negada',
+ toolError: 'Falha na execução da ferramenta',
+ waitingForModel: 'Aguardando o modelo',
+ compactionInProgress: 'Compactando conversa',
+ preparingInProgress: 'Preparando',
+ thinkingInProgress: 'Pensando…',
+ thinkingDone: 'Pensamento concluído',
+ thinkingDuration: '{s}s',
+ generating: 'Gerando…',
+ awaitingConfirm: 'Aguardando aprovação para {tool}…',
+ executingTool: 'Executando {tool}…',
+ toolWrote: 'Escreveu',
+ toolRead: 'Leu',
+ toolExecuted: 'Executou',
+ toolSearched: 'Pesquisou',
+ toolDeleted: 'Excluiu',
+ toolUpdated: 'Atualizou',
+ iterationLabel: 'Loop {n}',
+ compactionLabel: 'Conversa compactada ({trigger})',
+ compactionSummary: 'Mostrar resumo',
+ compactionTrigger: {
+ auto: 'automática',
+ manual: 'manual',
+ },
+ },
+ },
+ contextIndicator: {
+ offBadgeTitle: 'A compactação automática está DESATIVADA — o contexto não será reduzido automaticamente',
+ popoverTitle: 'Janela de contexto',
+ warningText: 'A compactação automática está DESATIVADA e o contexto está acima do limite. Compacte agora ou a próxima solicitação pode falhar.',
+ labelUsed: 'Usado',
+ labelCapacity: 'Capacidade',
+ labelWindow: 'Janela',
+ labelReservedOut: 'Reservado para saída',
+ labelAutoCompactAt: 'Compactar automaticamente em',
+ labelStatus: 'Status',
+ compactNow: 'Compactar agora',
+ compacting: 'Compactando…',
+ compactSuccess: 'Contexto compactado',
+ compactFailed: 'Falha ao compactar: {error}',
+ statusIdle: 'Ocioso',
+ statusOverThresholdOff: 'Acima do limite (compactação automática DESATIVADA)',
+ statusAutoCompactOff: 'Compactação automática DESATIVADA',
+ statusWillAutoCompact: 'Compactará automaticamente',
+ statusHealthy: 'Saudável',
+ tooltipIdle: 'Uso do contexto',
+ tooltipAutoCompactOff: 'Compactação automática desativada',
+ },
+ addSource: {
+ title: 'Adicionar fonte de dados',
+ selectConnection: 'Selecionar conexão',
+ searchPlaceholder: 'Pesquisar conexões...',
+ noConnections: 'Nenhuma conexão compatível encontrada',
+ allAttached: 'Todas as conexões compatíveis já estão anexadas',
+ connectionsFound: '{count} conexões encontradas',
+ connectSource: 'Conectar',
+ },
+ modifySource: {
+ title: 'Modificar fonte de dados',
+ accessPermissions: 'Permissões de acesso',
+ inheritTitle: 'Usar permissões da conexão',
+ saveChanges: 'Salvar alterações',
+ modeDefault: 'Perguntar',
+ modeFull: 'Automático',
+ },
+ detachSource: {
+ title: 'Desanexar fonte',
+ message: 'Tem certeza de que deseja desanexar esta fonte de dados? Isso removerá a conexão do Data Studio.',
+ confirm: 'Desanexar',
+ },
+ },
+ components: {
+ serverForm: {
+ basicTab: 'Básico',
+ advancedTab: 'Avançado',
+ title: {
+ edit: 'Editar conexão',
+ new: 'Nova conexão',
+ },
+ description: {
+ edit: 'Atualize as configurações da sua conexão de banco de dados.',
+ new: 'Configure uma nova conexão de banco de dados.',
+ },
+ labels: {
+ connectionName: 'Nome da conexão',
+ databaseType: 'Tipo de banco de dados',
+ host: 'Host',
+ databaseFilePath: 'Caminho do arquivo do banco de dados',
+ encryptionKey: 'Chave de criptografia',
+ port: 'Porta',
+ database: 'Banco de dados',
+ username: 'Usuário',
+ password: 'Senha',
+ ssl: 'Usar criptografia SSL/TLS',
+ sqliteMode: 'Modo SQLite',
+ recentDatabases: 'Bancos de dados recentes',
+ },
+ placeholders: {
+ connectionName: 'Meu banco de dados',
+ selectType: 'Selecionar tipo de banco de dados',
+ host: 'localhost',
+ filePath: '/path/to/database.db',
+ duckdbFilePath: '/path/to/database.duckdb or :memory:',
+ encryptionKey: 'Digite a frase secreta de criptografia',
+ database: 'database_name',
+ username: 'username',
+ password: '••••••••',
+ },
+ databaseTypes: {
+ 'postgresql': 'PostgreSQL',
+ 'sqlserver': 'SQL Server',
+ 'mysql': 'MySQL',
+ 'mariadb': 'MariaDB',
+ 'sqlite': 'SQLite',
+ 'sqlcipher': 'SQLCipher',
+ 'duckdb': 'DuckDB',
+ 'clickhouse': 'ClickHouse',
+ 'cockroachdb': 'CockroachDB',
+ 'redshift': 'Amazon Redshift',
+ 'yugabytedb': 'YugabyteDB',
+ 'timescaledb': 'TimescaleDB',
+ 'kingbasees': '人大金仓 (KingbaseES)',
+ 'gaussdb': '华为 GaussDB',
+ 'highgo': '瀚高数据库 (HighGo DB)',
+ 'uxdb': '优炫数据库 (UXDB)',
+ 'opengauss': 'openGauss',
+ 'gbase8c': '南大通用 GBase 8c',
+ 'questdb': 'QuestDB',
+ 'vastbase': 'Vastbase (海量数据库)',
+ 'yashandb': 'YashanDB (崖山数据库)',
+ 'tidb': 'TiDB',
+ 'oceanbase': 'OceanBase',
+ 'oceanbase-oracle': 'OceanBase Oracle',
+ 'tdsql': 'TDSQL',
+ 'polardb': 'PolarDB',
+ 'dameng': '达梦 Dameng',
+ 'doris': 'Apache Doris',
+ 'selectdb': 'SelectDB',
+ 'starrocks': 'StarRocks',
+ 'databend': 'Databend',
+ 'goldendb': 'GoldenDB',
+ 'manticore': 'Manticore Search',
+ 'oracle': 'Oracle',
+ 'db2': 'IBM Db2',
+ 'h2': 'H2',
+ 'snowflake': 'Snowflake',
+ 'xugudb': '虚谷数据库 (XuguDB)',
+ 'gbase8a': '南大通用 GBase 8a',
+ 'trino': 'Trino',
+ 'presto': 'Presto',
+ 'derby': 'Apache Derby',
+ 'hive': 'Apache Hive',
+ 'databricks': 'Databricks SQL',
+ 'hana': 'SAP HANA',
+ 'teradata': 'Teradata',
+ 'vertica': 'Vertica',
+ 'exasol': 'Exasol',
+ 'bigquery': 'Google BigQuery',
+ 'informix': 'IBM Informix',
+ 'kylin': 'Apache Kylin',
+ 'cassandra': 'Apache Cassandra',
+ 'iris': 'InterSystems IRIS',
+ 'access': 'Microsoft Access',
+ 'firebird': 'Firebird',
+ 'rqlite': 'RQLite',
+ 'turso': 'Turso (libSQL)',
+ 'tdengine': 'TDengine',
+ },
+ oracle: {
+ connectionMethod: 'Método de conexão',
+ methods: {
+ basic: 'Básico (Host:Port)',
+ tns: 'TNS (tnsnames.ora)',
+ cloudWallet: 'Cloud Wallet (ATP/ADW)',
+ },
+ identifyBy: 'Identificar por',
+ sid: 'SID',
+ serviceName: 'Nome do serviço',
+ role: 'Função',
+ roles: {
+ normal: 'NORMAL',
+ sysdba: 'SYSDBA',
+ sysoper: 'SYSOPER',
+ },
+ tnsAdminDir: 'Diretório TNS_ADMIN',
+ tnsAlias: 'Alias TNS',
+ walletDir: 'Diretório do Wallet',
+ walletPassword: 'Senha do Wallet',
+ serviceLevel: 'Nível de serviço',
+ serviceLevels: {
+ low: 'Baixo (lote)',
+ medium: 'Médio (padrão)',
+ high: 'Alto (crítico)',
+ tp: 'TP (transação)',
+ tpurgent: 'TP_URGENT (prioridade)',
+ },
+ browse: 'Procurar...',
+ noAliases: 'Nenhum alias TNS encontrado',
+ tnsSelectDir: 'Selecione um diretório TNS para carregar os aliases',
+ walletSelectDir: 'Selecione um diretório de wallet para carregar os aliases',
+ loadingAliases: 'Carregando aliases...',
+ },
+ buttons: {
+ create: 'Novo...',
+ open: 'Abrir...',
+ },
+ fileStatus: {
+ willCreate: 'O arquivo ainda não existe — o {engine} o cria quando você conecta.',
+ missingParent: 'A pasta pai ainda não existe.',
+ createDirectory: 'Criar pasta',
+ createDirectoryFailed: 'Falha ao criar a pasta',
+ unwritable: 'Sem permissão de escrita neste caminho.',
+ directory: 'Este caminho é uma pasta. Escolha um arquivo de banco de dados.',
+ empty: 'O arquivo está vazio (0 bytes).',
+ ready: 'O arquivo existe ({size})',
+ storageVersion: 'Formato de armazenamento {storage} (abre com DuckDB {version} ou mais recente)',
+ storageVersionUnknown: 'Formato de armazenamento {storage} — mais novo do que esta versão conhece, provavelmente gravado por um DuckDB mais recente.',
+ writeAheadLog: 'Há um write-ahead log (.wal) presente; ele é reproduzido ao conectar.',
+ unsupportedPath: 'O DuckDB não consegue abrir um caminho que contenha \';\'. Renomeie o arquivo e tente novamente.',
+ wrongFormat: 'Parece um arquivo {format}, não um banco de dados {engine}.',
+ unknownFormat: 'diferente',
+ reveal: 'Mostrar na pasta',
+ revealFailed: 'Falha ao mostrar o arquivo',
+ removeRecent: 'Remover da lista de recentes',
+ },
+ duckdb: {
+ accessMode: 'Modo de acesso',
+ readWrite: 'Leitura e escrita',
+ readWriteHint: 'O DuckDB mantém um bloqueio exclusivo no arquivo: apenas um processo pode gravar nele.',
+ readOnly: 'Somente leitura',
+ readOnlyHint: 'Permite que outros processos DuckDB leiam o mesmo arquivo ao mesmo tempo.',
+ conflictingConnection: '"{name}" já abre este arquivo com um modo de acesso diferente, e o DuckDB rejeita uma segunda conexão com uma configuração diferente.',
+ openReadOnly: 'Abrir somente leitura',
+ switchToConnection: 'Mudar para aquela conexão',
+ sharedConnection: '"{name}" usa o mesmo arquivo e configuração — ambas as conexões compartilham uma instância do DuckDB.',
+ engineVersion: 'Versão do mecanismo {version}',
+ retryReadOnly: 'Tentar novamente como somente leitura',
+ retryReadWrite: 'Tentar novamente como leitura e escrita',
+ inMemoryHint: 'Bancos de dados em memória são temporários e são perdidos quando a conexão é fechada. Útil para explorar dados antes de salvá-los em um arquivo.',
+ inMemoryInstance: 'Instância',
+ inMemorySharedHint: 'A instância em memória com nome é compartilhada por todas as conexões do pool, então as tabelas criadas em uma consulta permanecem visíveis para a próxima.',
+ },
+ duckdbFailures: {
+ 'read-only-unsupported': 'A ponte JDBC instalada ainda não consegue abrir um banco de dados somente leitura (o DuckDB recusa mudanças de modo por conexão). Tente novamente em modo leitura e escrita, ou atualize a ponte nas Configurações.',
+ 'storage-version': 'Este arquivo foi gravado por um DuckDB mais recente do que o mecanismo em uso e não pode ser aberto. Exporte-o com a versão mais recente (EXPORT DATABASE) e importe-o novamente, ou atualize o driver do DuckDB.',
+ 'config-conflict': 'Outra conexão já abriu este arquivo com uma configuração diferente (somente leitura vs. leitura e escrita, ou inicialização diferente). O DuckDB rejeita a segunda configuração.',
+ 'lock-conflict': 'Outro processo mantém o bloqueio de escrita deste arquivo (CLI do duckdb, Python ou outra conexão do SQLKit). Abra-o somente leitura ou feche o outro programa.',
+ 'unsupported-url': 'Este caminho não pode ser passado ao driver JDBC do DuckDB. Renomeie o arquivo e tente novamente.',
+ 'extension': 'Uma extensão do DuckDB não pôde ser carregada ou baixada. Verifique a conexão de rede ou instale a extensão antecipadamente.',
+ 'read-only-file': 'O arquivo do banco de dados ou sua pasta é somente leitura, então o DuckDB não pode gravar nele. Altere as permissões do arquivo ou abra-o somente leitura.',
+ 'missing-file': 'O arquivo do banco de dados não existe e não pôde ser criado. Verifique o caminho e as permissões da pasta.',
+ },
+ sqlite: {
+ modes: {
+ file: 'Arquivo',
+ inMemory: 'Em memória',
+ },
+ recentEmpty: 'Nenhum banco de dados recente',
+ ago: 'há {time}',
+ inMemoryHint: 'Bancos de dados em memória são temporários e serão perdidos quando a conexão for fechada. Útil para testes e dados temporários.',
+ pathStatus: {
+ valid: 'O arquivo existe',
+ notFound: 'Arquivo não encontrado',
+ noPermission: 'Sem permissão de escrita',
+ },
+ },
+ errors: {
+ nameRequired: 'O nome da conexão é obrigatório',
+ hostRequired: 'O host é obrigatório',
+ databaseRequired: 'SID / Nome do serviço é obrigatório',
+ databaseNameRequired: 'O nome do banco de dados é obrigatório',
+ filePathRequired: 'O caminho do arquivo do banco de dados é obrigatório',
+ portInvalid: 'A porta deve ser um número positivo',
+ filePickerFailed: 'Falha ao abrir o seletor de arquivos',
+ tnsAdminDirRequired: 'O diretório TNS admin é obrigatório',
+ tnsAliasRequired: 'O alias TNS é obrigatório',
+ },
+ ssh: {
+ newProfile: 'Novo perfil',
+ hopOrderHint: 'Os saltos são tentados em ordem — o último salto encaminha ao banco de dados. O proxy do sistema se aplica apenas ao primeiro salto.',
+ importFromConfig: 'Importar de ~/.ssh/config',
+ profileName: 'Nome do perfil',
+ profileNamePlaceholder: 'ex.: Bastião de produção',
+ editProfile: 'Editar perfil SSH',
+ useSshTunnel: 'Túnel SSH',
+ ultimateOnly: 'O túnel SSH é um recurso do Ultimate',
+ tunnelSkippedHint: 'O túnel SSH é um recurso do Ultimate: sessões Community ou desconectadas ignoram o túnel salvo nesta conexão, então este teste foi executado em uma conexão direta.',
+ systemProxy: 'Proxy do sistema',
+ systemProxyDetected: 'Proxy do sistema detectado: {url}',
+ systemProxyAdd: 'Adicionar',
+ systemProxyDetach: 'Desanexar proxy do sistema',
+ systemProxyNotDetected: 'O proxy do sistema está ativado, mas nenhum foi detectado. Conectando diretamente.',
+ detachAction: 'Desanexar da cadeia',
+ moveUp: 'Mover salto para cima',
+ moveDown: 'Mover salto para baixo',
+ hops: 'salto | saltos',
+ addProfilePlaceholder: 'Adicionar perfil…',
+ searchProfilePlaceholder: 'Pesquisar perfis…',
+ testChain: 'Testar conectividade do túnel',
+ testFirstHop: 'Testar o primeiro salto (os demais saltos não são testados)',
+ testDisabledHint: 'Campos obrigatórios ausentes ou configuração inválida',
+ testReturnedNotConnected: 'A conexão retornou não conectada',
+ jreBroken: 'O JRE está ausente ou quebrado',
+ stepFailed: 'Falhou',
+ testTimedOut: 'O teste expirou (30s) — o bastião pode estar inacessível ou o handshake SSH travou',
+ testSuccess: 'Conectado a {user}{\'@\'}{host}:{port}',
+ notConfigured: 'Túnel SSH não configurado — adicione um perfil para começar',
+ editTunnel: 'Editar túnel SSH',
+ connectionOnly: 'As alterações se aplicam apenas a esta conexão.',
+ convertHint: 'Converta em um perfil reutilizável para adicionar e reordenar saltos.',
+ noConfigHosts: 'Nenhum host SSH encontrado em ~/.ssh/config.',
+ convertToProfile: 'Converter em perfil',
+ convertedProfileName: 'Manual ({host})',
+ sshHost: 'Host SSH',
+ sshPort: 'Porta SSH',
+ username: 'Usuário',
+ authMethod: 'Método de autenticação',
+ password: 'Senha',
+ privateKey: 'Chave privada',
+ sshAgent: 'Agente SSH',
+ sshPassword: 'Senha SSH',
+ privateKeyPath: 'Caminho da chave privada',
+ passphraseOptional: 'Frase secreta (opcional)',
+ agentSockPath: 'Caminho do socket do agente',
+ agentHelpText: 'Usando o agente SSH do sistema — não é necessária configuração adicional.',
+ },
+ },
+ serverCard: {
+ actions: {
+ connect: 'Conectar',
+ openEditor: 'Abrir no editor',
+ closeConnection: 'Fechar conexão',
+ edit: 'Editar',
+ duplicate: 'Duplicar',
+ delete: 'Excluir',
+ },
+ strategy: {
+ nativeTooltip: 'Conexão direta via driver Rust nativo — melhor desempenho, sem dependências externas',
+ jdbcBridgeTooltip: 'Conecta por meio do driver JDBC com um Java runtime embutido — compatibilidade mais ampla com bancos de dados',
+ httpBridgeTooltip: 'Conecta via protocolo SQL HTTP — para bancos de dados baseados em REST',
+ },
+ },
+ connectingModal: {
+ connecting: 'Conectando a {name}...',
+ connectingSubtext: 'Aguarde enquanto a conexão é estabelecida',
+ connectionError: 'Erro de conexão',
+ sshTunnelSkipped: 'O túnel SSH é um recurso do Ultimate: sessões Community ou desconectadas ignoram o túnel salvo nesta conexão e conectam diretamente (a configuração em si é mantida).',
+ sshTunnelStripped: 'O túnel salvo nesta conexão foi ignorado nesta tentativa (recurso do Ultimate, e você está no Community ou desconectado). Se o banco de dados só for acessível por esse túnel, faça upgrade para o Ultimate.',
+ },
+ databaseBrowser: {
+ title: 'Navegador de banco de dados',
+ search: 'Pesquisar tabelas...',
+ refresh: 'Atualizar',
+ newQuery: 'Nova consulta',
+ loading: 'Carregando...',
+ empty: 'Nenhum banco de dados encontrado. Conecte-se a um servidor primeiro.',
+ selectDatabase: 'Selecionar banco de dados',
+ selectSchema: 'Selecionar schema',
+ databases: 'Bancos de dados',
+ current: 'Atual',
+ userDatabases: 'Bancos de dados de usuário',
+ systemDatabases: 'Bancos de dados do sistema',
+ noTables: 'Nenhuma tabela encontrada',
+ noViews: 'Nenhuma visão encontrada',
+ noProcedures: 'Nenhum procedimento encontrado',
+ noFunctions: 'Nenhuma função encontrada',
+ noSavedQueries: 'Ainda não há consultas salvas',
+ comingSoon: 'Em breve',
+ sections: {
+ tables: 'Tabelas',
+ views: 'Visões',
+ procedures: 'Procedimentos',
+ functions: 'Funções',
+ savedQueries: 'Consultas salvas',
+ },
+ errors: {
+ fetchDatabases: 'Falha ao buscar os bancos de dados',
+ fetchSchemas: 'Falha ao buscar os schemas',
+ fetchTables: 'Falha ao buscar as tabelas',
+ invalidResponse: 'Resposta inválida do servidor',
+ },
+ contextMenu: {
+ viewData: 'Ver dados',
+ selectTopN: 'Selecionar os 100 primeiros',
+ viewStructure: 'Ver estrutura',
+ createScript: 'Script CREATE',
+ exportData: 'Exportar dados',
+ showErDiagram: 'Mostrar diagrama ER',
+ dropTable: 'Excluir tabela',
+ truncateTable: 'Truncar',
+ newQuery: 'Nova consulta',
+ refresh: 'Atualizar',
+ },
+ savedQueryActions: {
+ open: 'Abrir',
+ delete: 'Excluir',
+ reveal: 'Revelar no Finder',
+ },
+ erDiagram: {
+ title: 'Diagrama ER',
+ viewMode: 'Visualização',
+ zoom: '{percentage}%',
+ zoomIn: 'Ampliar',
+ zoomOut: 'Reduzir',
+ allSchemas: 'Todos os schemas',
+ engineeringView: 'Visão de engenharia',
+ fitToScreen: 'Ajustar à tela',
+ searchPlaceholder: 'Filtrar tabelas...',
+ tablesCountBadge: '{count} tabelas',
+ tableView: 'Visualização de tabela',
+ relationshipsCountBadge: '{count} relacionamentos',
+ resetLayout: 'Redefinir layout',
+ largeSchemaWarning: 'Este schema tem {count} tabelas. Exibir todas pode ficar denso. Continuar?',
+ showAllColumns: 'Mostrar todas as colunas ({count})',
+ hideExtraColumns: 'Mostrar menos',
+ noForeignKeys: 'Nenhum relacionamento de chave estrangeira encontrado',
+ openTable: 'Abrir dados da tabela',
+ layoutDirection: 'Layout',
+ layoutTopBottom: 'De cima para baixo',
+ layoutLeftRight: 'Da esquerda para a direita',
+ loading: 'Carregando relações do schema...',
+ },
+ },
+ listingTab: {
+ views: 'Visões',
+ procedures: 'Procedimentos',
+ functions: 'Funções',
+ searchPlaceholder: 'Pesquisar por nome...',
+ name: 'Nome',
+ detail: 'Detalhe',
+ ddl: 'DDL',
+ actions: 'Ações',
+ viewDdl: 'Ver DDL',
+ drop: 'Excluir',
+ rename: 'Renomear',
+ copyName: 'Copiar nome',
+ copyDdl: 'Copiar DDL',
+ dropDialogTitle: 'Excluir objeto',
+ dropDialogDescription: 'Tem certeza de que deseja excluir {name}?',
+ confirmDrop: 'Excluir',
+ renameDialogTitle: 'Renomear objeto',
+ renameDialogDescription: 'Digite um novo nome para {name}:',
+ newNamePlaceholder: 'Novo nome',
+ confirmRename: 'Renomear',
+ noResults: 'Nenhum objeto corresponde à sua pesquisa',
+ empty: 'Nenhum objeto encontrado',
+ },
+ schemaTab: {
+ column: 'Coluna',
+ type: 'Tipo',
+ nullable: 'Permite nulo',
+ default: 'Padrão',
+ key: 'Chave',
+ autoIncrement: 'Auto incremento',
+ yes: 'SIM',
+ no: 'NÃO',
+ pk: 'PK',
+ },
+ indexesTab: {
+ name: 'Nome',
+ columns: 'Colunas',
+ type: 'Tipo',
+ unique: 'Único',
+ primary: 'Primário',
+ empty: 'Nenhum índice encontrado',
+ yes: 'SIM',
+ no: 'NÃO',
+ },
+ foreignKeysTab: {
+ constraint: 'Restrição',
+ columns: 'Colunas',
+ references: 'Referências',
+ onUpdate: 'ON UPDATE',
+ onDelete: 'ON DELETE',
+ empty: 'Nenhuma chave estrangeira encontrada',
+ },
+ triggersTab: {
+ name: 'Nome',
+ timing: 'Momento',
+ event: 'Evento',
+ ddl: 'DDL',
+ viewDdl: 'Ver DDL',
+ empty: 'Nenhum trigger encontrado',
+ },
+ queryResult: {
+ title: 'Resultados',
+ selectResult: 'Selecionar conjunto de resultados',
+ resultSet: 'Resultado {index} de {count}',
+ exportActions: 'Copiar e exportar resultado',
+ scriptReadOnly: 'Os resultados de script são somente leitura; a ordenação se aplica às linhas retornadas.',
+ rows: '{count} linhas',
+ rowsAffected: '{count} linha(s) afetada(s)',
+ time: '{time}',
+ close: 'Fechar',
+ executing: 'Executando consulta...',
+ error: 'Erro na consulta',
+ success: 'Consulta executada com sucesso',
+ noData: 'Nenhum dado retornado',
+ commandCompleted: 'Comando concluído',
+ noResults: 'Execute uma consulta para ver os resultados',
+ },
+ dataTableView: {
+ searchPlaceholder: 'Pesquisar em todas as colunas...',
+ clearSearch: 'Limpar pesquisa',
+ filterPlaceholder: 'Filtrar (cláusula WHERE SQL, ex.: age > 18 AND status = \'active\')',
+ clearFilter: 'Limpar filtro',
+ refresh: 'Atualizar',
+ columns: 'Colunas',
+ exportCsv: 'Exportar página atual (CSV)',
+ applyFilters: 'Aplicar filtros',
+ loading: 'Carregando dados da tabela...',
+ error: 'Falha ao carregar os dados da tabela',
+ connectionLost: 'Conexão perdida. A conexão com o banco de dados foi encerrada.',
+ reconnecting: 'Reconectando...',
+ reconnect: 'Reconectar',
+ noRows: 'Nenhuma linha encontrada',
+ rows: 'linhas',
+ columnsCount: '{count} colunas',
+ indexesCount: '{count} índices',
+ foreignKeysCount: '{count} chaves estrangeiras',
+ triggersCount: '{count} triggers',
+ page: 'Página {page} de {total}',
+ rowsPerPage: 'Linhas por página:',
+ actions: 'Ações',
+ editRow: 'Editar linha',
+ deleteRow: 'Excluir linha',
+ notifications: {
+ csvExported: 'CSV exportado',
+ exportFailed: 'Falha na exportação',
+ rowDeleted: 'Linha excluída',
+ deleteFailed: 'Falha ao excluir a linha',
+ rowUpdated: 'Linha atualizada',
+ updateFailed: 'Falha ao atualizar a linha',
+ noPrimaryKey: 'Nenhuma chave primária detectada',
+ noPrimaryKeyDesc: 'Esta tabela não tem chave primária. A linha será identificada por todas as colunas.',
+ fallbackAllColumns: 'Sem chave primária — usando todas as colunas para identificar a linha. Edite com cautela.',
+ },
+ deleteDialog: {
+ title: 'Excluir linha',
+ message: 'Tem certeza de que deseja excluir esta linha? Esta ação não pode ser desfeita.',
+ confirm: 'Excluir',
+ },
+ editDialog: {
+ title: 'Editar linha',
+ },
+ validation: {
+ required: 'Este campo é obrigatório',
+ invalidNumber: 'Digite um número válido',
+ invalidBoolean: 'Digite true ou false',
+ },
+ },
+ queryTabs: {
+ unsaved: 'Alterações não salvas',
+ orphan: 'Esta aba pertence a outra conexão',
+ new: 'Nova consulta',
+ closeDialog: {
+ title: 'Alterações não salvas',
+ message: 'A consulta "{name}" tem alterações não salvas. Deseja descartá-las?',
+ discard: 'Descartar',
+ },
+ },
+ header: {
+ appName: 'SQLKit',
+ },
+ sqlEditor: {
+ execute: 'Executar',
+ format: 'Formatar',
+ copy: 'Copiar',
+ },
+ destructiveDialog: {
+ deleteRow: {
+ title: 'Confirmar exclusão',
+ message: 'Excluir {count} linha(s) da tabela "{table}"?',
+ detail: 'Esta ação não pode ser desfeita.',
+ confirm: 'Excluir',
+ },
+ dropTable: {
+ title: 'Excluir tabela',
+ message: 'Excluir a tabela "{table}"?',
+ detail: 'Isso excluirá permanentemente a tabela e todos os dados dela. Esta ação não pode ser desfeita.',
+ confirm: 'Excluir',
+ },
+ truncateTable: {
+ title: 'Truncar tabela',
+ message: 'Truncar a tabela "{table}"?',
+ detail: 'Isso removerá todas as {count} linhas. Esta ação não pode ser desfeita.',
+ confirm: 'Truncar',
+ },
+ deleteConnection: {
+ title: 'Excluir conexão',
+ message: 'Excluir a conexão "{name}"?',
+ detail: 'Isso removerá a configuração da conexão salva. As conexões ativas serão desconectadas.',
+ confirm: 'Excluir',
+ },
+ deleteProfile: {
+ title: 'Excluir perfil SSH',
+ message: 'Excluir o perfil "{name}"?',
+ detail: 'O perfil será removido da biblioteca de perfis compartilhada. As conexões que passam por ele perderão este bastião.',
+ inUse: 'Ele é usado por {count} conexão(ões): {names}. Essas conexões serão desanexadas deste perfil.',
+ confirm: 'Excluir',
+ },
+ },
+ pagination: {
+ label: 'Paginação',
+ showingWithoutTotal: 'Mostrando linhas {start}–{end} · total indisponível',
+ rowsPerPage: 'Linhas por página',
+ pageSize: '{count} linhas/página',
+ customSize: 'Linhas por página personalizadas',
+ apply: 'Aplicar',
+ showAll: 'Mostrar todas as linhas retornadas',
+ allRows: 'Todas as linhas retornadas',
+ firstPage: 'Primeira página',
+ previousPage: 'Página anterior',
+ nextPage: 'Próxima página',
+ lastPage: 'Última página',
+ goToPage: 'Ir para a página',
+ pageCount: 'de {count}',
+ sortScope: 'A ordenação se aplica à página atual',
+ },
+ dataGrid: {
+ sort: {
+ asc: 'Ordenar em ordem crescente',
+ desc: 'Ordenar em ordem decrescente',
+ clear: 'Limpar ordenação',
+ unsortable: 'Este tipo de coluna não pode ser ordenado',
+ },
+ filter: {
+ byValue: 'Filtrar por valor',
+ byLike: 'Filtrar por LIKE',
+ greaterThan: 'Filtrar >=',
+ lessThan: 'Filtrar <=',
+ between: 'Filtrar entre',
+ excludeValue: 'Excluir valor',
+ clearFilter: 'Limpar filtro',
+ clearAll: 'Limpar todos os filtros',
+ activeFilters: 'Filtros',
+ },
+ row: {
+ edit: 'Editar linha',
+ delete: 'Excluir linha',
+ duplicate: 'Duplicar linha',
+ details: 'Detalhes da linha',
+ copyAsCsv: 'Copiar linha como CSV',
+ copyAsJson: 'Copiar linha como JSON',
+ copyAsInsert: 'Copiar linha como INSERT',
+ actions: 'Ações',
+ noTableContext: 'O resultado da consulta não está vinculado a uma tabela, então as linhas não podem ser editadas ou excluídas',
+ editUnsupported: {
+ 'not-select': 'Esta instrução não é uma consulta SELECT; as linhas do resultado não podem ser editadas ou excluídas',
+ 'cte': 'A consulta usa WITH (CTE); as linhas não podem ser mapeadas de volta a uma tabela, então a edição não é suportada',
+ 'set-operation': 'A consulta usa UNION/INTERSECT/EXCEPT; as linhas vêm de várias instruções, então a edição não é suportada',
+ 'aggregation': 'A consulta é agregada (GROUP BY/DISTINCT/funções de agregação); as linhas não podem ser mapeadas de volta às linhas base, então a edição não é suportada',
+ 'multiple-sources': 'A consulta junta várias tabelas; as linhas não podem ser editadas ou excluídas',
+ 'no-table': 'A consulta não tem tabela no FROM; as linhas não podem ser editadas ou excluídas',
+ 'complex-source': 'A origem da consulta é uma subconsulta ou expressão complexa; as linhas não podem ser editadas ou excluídas',
+ },
+ },
+ cell: {
+ copyValue: 'Copiar valor da célula',
+ copyRow: 'Copiar linha',
+ filterByValue: 'Filtrar por este valor',
+ excludeValue: 'Excluir este valor',
+ },
+ selection: {
+ selected: '{count} linha(s) selecionada(s)',
+ editSelected: 'Editar selecionadas',
+ deleteSelected: 'Excluir selecionadas',
+ exportSelected: 'Exportar selecionadas',
+ },
+ status: {
+ showing: 'Mostrando {start}–{end} de {total} linhas',
+ showingLimited: 'Mostrando {start}–{end} de {loaded} linhas (limitado)',
+ time: '· {time}',
+ },
+ empty: 'Nenhum resultado',
+ error: {
+ title: 'Erro ao carregar os dados',
+ retry: 'Tentar novamente',
+ },
+ loading: 'Carregando dados...',
+ edit: {
+ title: 'Editar linha',
+ duplicateTitle: 'Duplicar linha',
+ nullToggle: 'Definir NULL',
+ pkReadonly: 'Chave primária (somente leitura)',
+ save: 'Salvar',
+ cancel: 'Cancelar',
+ saving: 'Salvando...',
+ confirmCancel: 'Descartar alterações?',
+ confirmCancelMessage: 'Você tem alterações não salvas. Tem certeza de que deseja fechar?',
+ discard: 'Descartar',
+ validation: {
+ required: 'Este campo é obrigatório',
+ invalidNumber: 'Digite um número válido',
+ invalidBoolean: 'Digite true ou false',
+ },
+ },
+ details: {
+ title: 'Detalhes da linha',
+ },
+ delete: {
+ title: 'Excluir linha',
+ message: 'Tem certeza de que deseja excluir esta linha?',
+ detail: 'Esta ação não pode ser desfeita.',
+ confirm: 'Excluir',
+ batchTitle: 'Excluir linhas selecionadas',
+ batchMessage: 'Tem certeza de que deseja excluir {count} linha(s) selecionada(s)?',
+ batchDetail: 'Esta ação não pode ser desfeita.',
+ },
+ export: {
+ copyAllCsv: 'Copiar tudo como CSV',
+ copyAllJson: 'Copiar tudo como JSON',
+ copyAllInsert: 'Copiar tudo como INSERT',
+ exportCsv: 'Exportar CSV',
+ exportJson: 'Exportar JSON',
+ exportInsert: 'Exportar INSERT',
+ copied: 'Copiado para a área de transferência',
+ exported: 'Arquivo exportado',
+ formatLabels: {
+ csv: 'CSV',
+ json: 'JSON',
+ insert: 'INSERT',
+ },
+ },
+ json: {
+ expand: 'Expandir',
+ title: 'Visualizador de JSON',
+ copy: 'Copiar JSON',
+ },
+ blob: {
+ label: '[BLOB {size}]',
+ },
+ null: '(NULL)',
+ rowNumber: '#',
+ },
+ },
+ updater: {
+ updateAvailable: 'Atualização disponível',
+ newVersion: 'Versão {version} disponível',
+ upToDate: 'Você já tem a versão mais recente',
+ checkFailed: 'Falha ao verificar atualizações',
+ downloading: 'Baixando atualização...',
+ installing: 'Instalando atualização...',
+ installFailed: 'Falha ao instalar a atualização',
+ skip: 'Ignorar esta versão',
+ later: 'Mais tarde',
+ updateNow: 'Atualizar agora',
+ restarting: 'Reiniciando...',
+ downloadingPercent: 'Baixando {percent}%',
+ relaunchFailed: 'Falha ao reiniciar após a atualização',
+ retry: 'Tentar novamente',
+ installFailedHelp: 'Pressione F12 para abrir as ferramentas de desenvolvedor e verificar os detalhes do erro.',
+ },
+ errors: {
+ unexpected: 'Erro inesperado: {error}',
+ codes: {
+ // Connection errors
+ CONNECTION_FAILED: 'Falha ao conectar ao banco de dados',
+ CONNECTION_TIMEOUT: 'Tempo limite de conexão',
+ CONNECTION_REFUSED: 'Conexão recusada',
+ AUTHENTICATION_FAILED: 'Falha na autenticação',
+
+ // Query errors
+ QUERY_SYNTAX_ERROR: 'Erro de sintaxe SQL',
+ QUERY_EXECUTION_ERROR: 'Falha na execução da consulta',
+ QUERY_TIMEOUT: 'Tempo limite de execução da consulta esgotado',
+
+ // Resource errors
+ DATABASE_NOT_FOUND: 'Banco de dados não encontrado',
+ TABLE_NOT_FOUND: 'A tabela não existe',
+ COLUMN_NOT_FOUND: 'A coluna não existe',
+
+ // Permission errors
+ PERMISSION_DENIED: 'Permissão negada',
+ INSUFFICIENT_PRIVILEGES: 'Privilégios insuficientes',
+
+ // Data errors
+ CONSTRAINT_VIOLATION: 'Violação de restrição',
+ FOREIGN_KEY_VIOLATION: 'Restrição de chave estrangeira violada',
+ UNIQUE_VIOLATION: 'Restrição de exclusividade violada',
+ NOT_NULL_VIOLATION: 'Restrição NOT NULL violada',
+ CHECK_VIOLATION: 'Restrição CHECK violada',
+
+ // System errors
+ INTERNAL_ERROR: 'Erro interno',
+ UNSUPPORTED_OPERATION: 'Operação não suportada',
+ INVALID_CONFIGURATION: 'Configuração inválida',
+ },
+ titles: {
+ CONNECTION_FAILED: 'Falha na conexão',
+ AUTHENTICATION_FAILED: 'Falha na autenticação',
+ QUERY_SYNTAX_ERROR: 'Erro de sintaxe SQL',
+ QUERY_EXECUTION_ERROR: 'Erro de execução da consulta',
+ TABLE_NOT_FOUND: 'Tabela não encontrada',
+ COLUMN_NOT_FOUND: 'Coluna não encontrada',
+ PERMISSION_DENIED: 'Permissão negada',
+ FOREIGN_KEY_VIOLATION: 'Restrição de chave estrangeira violada',
+ UNIQUE_VIOLATION: 'Restrição de exclusividade violada',
+ NOT_NULL_VIOLATION: 'Restrição NOT NULL violada',
+ },
+ hints: {
+ CONNECTION_FAILED: 'Verifique suas configurações de conexão e certifique-se de que o servidor do banco de dados está em execução',
+ AUTHENTICATION_FAILED: 'Verifique seu usuário e senha',
+ QUERY_SYNTAX_ERROR: 'Verifique a sintaxe do SQL e tente novamente',
+ QUERY_TIMEOUT: 'Tente otimizar sua consulta ou aumentar o limite de tempo',
+ DATABASE_NOT_FOUND: 'Certifique-se de que o banco de dados existe e que você tem acesso a ele',
+ TABLE_NOT_FOUND: 'Verifique o nome da tabela e se ela existe no banco de dados',
+ COLUMN_NOT_FOUND: 'Verifique se o nome da coluna corresponde ao schema da tabela',
+ FOREIGN_KEY_VIOLATION: 'Certifique-se de que os registros referenciados existam na tabela pai',
+ UNIQUE_VIOLATION: 'Já existe um registro com este valor',
+ NOT_NULL_VIOLATION: 'Este campo exige um valor',
+ CHECK_VIOLATION: 'O valor não satisfaz as restrições da tabela',
+ PERMISSION_DENIED: 'Você não tem privilégios suficientes para esta operação',
+ },
+ },
+ sidebar: {
+ connection: {
+ placeholder: 'Selecionar conexão',
+ connected: 'Conectado',
+ lost: 'Conexão perdida',
+ disconnected: 'Desconectado',
+ connecting: 'Conectando...',
+ },
+ database: {
+ placeholder: 'Todos os bancos de dados',
+ selectDatabase: 'Selecionar banco de dados',
+ refresh: 'Atualizar',
+ refreshTooltip: 'Recarregar a lista de bancos de dados',
+ },
+ databases: {
+ actions: {
+ createObject: {
+ title: 'Criar {type}',
+ placeholder: 'Digite o nome do {type}',
+ cancel: 'Cancelar',
+ confirm: 'Criar',
+ created: '{type} "{name}" criado com sucesso',
+ error: 'Falha ao criar: {error}',
+ types: {
+ database: 'Banco de dados',
+ schema: 'Schema',
+ },
+ },
+ createDatabase: {
+ title: 'Criar banco de dados',
+ name: 'Nome do banco de dados',
+ namePlaceholder: 'Digite o nome do banco de dados',
+ charset: 'Conjunto de caracteres',
+ collation: 'Collation',
+ collationPlaceholder: 'ex.: utf8mb4_unicode_ci',
+ encoding: 'Codificação',
+ locale: 'Locale / LC_COLLATE',
+ localePlaceholder: 'ex.: en_US.UTF-8',
+ optional: 'opcional',
+ cancel: 'Cancelar',
+ confirm: 'Criar',
+ },
+ dropDatabase: {
+ title: 'Excluir banco de dados',
+ message: 'Tem certeza de que deseja excluir "{name}"? Esta ação não pode ser desfeita.',
+ typeToConfirm: 'Digite o nome do banco de dados para confirmar:',
+ cancel: 'Cancelar',
+ confirm: 'Excluir',
+ success: 'Banco de dados "{name}" excluído com sucesso',
+ error: 'Falha ao excluir o banco de dados: {error}',
+ },
+ createTable: {
+ title: 'Criar tabela',
+ tableName: 'Nome da tabela',
+ tableNamePlaceholder: 'Digite o nome da tabela',
+ engine: 'Mecanismo',
+ columns: 'Colunas',
+ addColumn: 'Adicionar coluna',
+ colName: 'Nome',
+ colType: 'Tipo',
+ colLength: 'Tamanho',
+ colAutoInc: 'AI',
+ colDefault: 'Padrão',
+ lengthPlaceholder: '255',
+ defaultPlaceholder: 'NULL',
+ preview: 'Pré-visualização do SQL',
+ cancel: 'Cancelar',
+ create: 'Criar',
+ opened: 'O SQL da tabela foi aberto no editor. Execute-o para criar a tabela.',
+ },
+ templateOpened: 'Novo modelo de {type} aberto no editor.',
+ },
+ },
+ actionMenu: {
+ label: 'Ações do banco de dados',
+ createScript: 'Criar script',
+ newDatabase: 'Novo banco de dados',
+ newSchema: 'Novo schema',
+ newTable: 'Nova tabela',
+ newView: 'Nova visão',
+ newFunction: 'Nova função',
+ newProcedure: 'Novo procedimento',
+ showErDiagram: 'Diagrama ER',
+ backupDatabase: 'Backup do banco de dados',
+ exportDatabase: 'Exportar banco de dados',
+ dropDatabase: 'Excluir banco de dados',
+ },
+ groups: {
+ tables: 'TABELAS',
+ views: 'VISÕES',
+ procedures: 'PROCEDIMENTOS',
+ functions: 'FUNÇÕES',
+ },
+ loading: 'Carregando...',
+ empty: 'Nenhum banco de dados selecionado. Escolha um para navegar.',
+ noObjects: 'Nenhum objeto encontrado',
+ noDatabases: 'Nenhum banco de dados encontrado. Conecte-se a um servidor primeiro.',
+ search: 'Pesquisar tabelas, visões...',
+ savedQueries: {
+ header: 'Consultas salvas',
+ expand: 'Expandir consultas salvas',
+ collapse: 'Recolher consultas salvas',
+ newQuery: 'Nova consulta',
+ empty: 'Ainda não há consultas salvas',
+ created: 'Criado',
+ modified: 'Modificado',
+ connectionNone: 'Sem conexão de destino',
+ actions: {
+ open: 'Abrir',
+ rename: 'Renomear',
+ changeConnection: 'Alterar conexão de destino',
+ reveal: 'Revelar no Explorador de Arquivos',
+ delete: 'Excluir',
+ },
+ delete: {
+ title: 'Excluir consulta salva?',
+ description: 'Tem certeza de que deseja excluir "{name}"? Esta ação não pode ser desfeita.',
+ cancel: 'Cancelar',
+ confirm: 'Excluir',
+ target: 'Destino',
+ created: 'Criado',
+ },
+ renameDialog: {
+ title: 'Renomear consulta salva',
+ label: 'Novo nome',
+ placeholder: 'Digite o novo nome do arquivo',
+ cancel: 'Cancelar',
+ confirm: 'Renomear',
+ },
+ connectionDialog: {
+ title: 'Alterar conexão de destino',
+ label: 'Selecionar conexão',
+ none: 'Sem conexão',
+ cancel: 'Cancelar',
+ confirm: 'Salvar',
+ },
+ },
+ notImplemented: 'Este recurso ainda não foi implementado',
+ },
+}
diff --git a/src/lang/zhTW.ts b/src/lang/zhTW.ts
new file mode 100644
index 00000000..ba3b6047
--- /dev/null
+++ b/src/lang/zhTW.ts
@@ -0,0 +1,2049 @@
+export const zhTW = {
+ aiPermissions: {
+ ultimateOnly: '個別連線的 AI 設定需要 Ultimate',
+ accessLevel: '存取等級',
+ unavailable: '無法使用',
+ loadError: '無法載入權限',
+ saving: '儲存中…',
+ deniedByConnection: '已被連線權限禁止',
+ conversationReadOnly: '此對話為唯讀',
+ title: 'AI 權限',
+ help: '適用於 Data Studio 與外部 MCP 用戶端。可使用系統預設值,或為此連線個別設定權限。',
+ loading: '正在載入權限…',
+ loadFailed: '無法載入權限。請重試後再儲存此連線。',
+ retry: '重試',
+ inherit: '使用系統預設值',
+ none: '禁止存取',
+ read: '讀取',
+ data: '讀取與修改資料',
+ full: '完整存取',
+ custom: '自訂',
+ effective: '實際存取權限',
+ create: '建立資料',
+ update: '更新資料',
+ delete: '刪除資料',
+ manage: '管理結構與系統管理',
+ allow: '允許',
+ deny: '拒絕',
+ fromConnection: '此連線',
+ defaults: '預設 AI 權限',
+ defaultsHelp: '適用於 Data Studio 與外部 MCP 用戶端。除非在連線中另行設定,否則各連線皆沿用這些預設值。',
+ save: '儲存預設值',
+ saved: '權限已儲存',
+ saveFailed: '無法儲存權限',
+ inheritHelp: '沿用系統預設值,包含日後的變更。',
+ noneHelp: '不可存取資料,也不可執行管理操作。',
+ readHelp: '讀取資料並檢視結構,不可進行變更。',
+ dataHelp: '可變更資料(包含刪除),不可變更結構或執行管理操作。',
+ fullHelp: '可執行所有資料操作、結構變更與系統管理。',
+ customHelp: '選擇 AI 可執行哪些個別操作。',
+ defaultDecision: '使用預設值({decision})',
+ readPreset: '唯讀',
+ },
+
+ device: {
+ replaceTitle: '已達裝置數量上限',
+ replaceDescription: '您的訂閱最多可在 {limit} 台裝置上啟用。請在下方選擇要以本裝置取代的裝置,被取代的裝置將立即失去存取權限。',
+ slotUsage: '已使用 {used}/{limit} 台裝置',
+ thisDevice: '本裝置',
+ lastActive: '上次使用',
+ neverActive: '從未使用',
+ replaceConfirm: '取代並啟用',
+ replaceFailed: '無法取代裝置,請選擇其他裝置後再試一次。',
+ },
+ plan: {
+ tab: '帳戶與方案',
+ pricing: 'Ultimate $9.9/月 · $99/年 · 7 天免費試用',
+ state: {
+ ultimate: 'Ultimate',
+ community: 'Community',
+ unknown: '未知',
+ checking: '檢查中…',
+ },
+ gate: {
+ additive: '包含 Community 的所有功能,另外還有:',
+ recommended: '推薦',
+ currentFeature: '此功能',
+ trustLine: '版本鎖定讓您購買期間發布的版本永久歸您所有 · 隨時可取消',
+ headline: {
+ ai: '用白話文詢問您的資料',
+ transfer: '大量搬移資料,快速又安全',
+ er_diagram: '把資料表關聯畫成一張圖',
+ ssh_tunnel: '透過 SSH 連線到遠端資料庫',
+ mcp_bridge: '把 SQLKit 帶進您的代理工具鏈',
+ },
+ tiles: {
+ aiQueryT: '自然語言查詢',
+ aiQueryD: '用白話文提問,取得可編輯的 SQL',
+ aiAgentT: '代理式解釋與修正',
+ aiAgentD: '一鍵最佳化慢查詢',
+ mcpServerT: '內建 MCP 伺服器',
+ mcpServerD: '在本機執行,無需設定',
+ mcpClientsT: '任何 MCP 用戶端',
+ mcpClientsD: 'Claude Desktop、Cursor 等',
+ },
+ groups: {
+ cloud: '雲端',
+ local: '本機',
+ custom: '自訂',
+ clients: '用戶端',
+ },
+ detail: {
+ ai: '支援任何模型:雲端、本機或自訂',
+ mcp: '可連接您慣用的 MCP 用戶端',
+ },
+ price: {
+ yearly: '$99 / 年',
+ save: '省 17%',
+ monthly: '$9.9 / 月',
+ },
+ trust: {
+ versionLock: '訂閱期間發布的版本永遠屬於您,離線也能使用',
+ byok: '自備 LLM 金鑰,不加收任何 Token 費用',
+ cancel: '隨時可取消',
+ },
+ cta: {
+ unlock: '升級 Ultimate 解鎖',
+ unlockSub: '7 天免費試用 · $9.9/月 · $99/年',
+ },
+ },
+ poster: {
+ mcp: {
+ clients: '支援',
+ config: '用戶端設定',
+ },
+ ai: {
+ question: '找出過去 7 天內失敗的付款',
+ loop: '第 1 輪',
+ thinking: '思考中',
+ toolVerb: '已查詢 public.orders',
+ answer: '找到 3 筆失敗的付款,產生的查詢如下:',
+ },
+ transfer: {
+ scopeDatabase: '整個資料庫',
+ },
+ },
+ compare: {
+ ai: 'AI 助理與 NL2SQL',
+ er_diagram: 'ER 圖',
+ transfer: '大量匯入 / 匯出與移轉',
+ ssh: 'SSH 通道',
+ mcp: 'MCP Bridge',
+ versionLock: '版本鎖定',
+ },
+ upgrade: {
+ title: '升級到 Ultimate',
+ cta: '升級',
+ refresh: '重新整理授權',
+ startFree: '免費開始',
+ versionPermanent: '訂閱期間的版本可永久使用,離線也沒問題。',
+ versionLockedOut: '此版本需要有效的訂閱才能解鎖。續訂即可永久解鎖。',
+ },
+ section: {
+ title: '帳戶與方案',
+ desc: '此安裝的訂閱授權與版本鎖定狀態。',
+ versionPermanent: '目前的版本可永久使用(受您的版本鎖定涵蓋)。',
+ subscriptionActive: 'Ultimate 已啟用,訂閱期間所有功能皆已解鎖。',
+ versionLockedOut: '此版本({date})不在版本鎖定涵蓋範圍內,目前顯示為 Community 模式。',
+ expiresAt: '有效期限至 {time}',
+ cancelScheduled: '訂閱將於目前的計費週期結束時終止。',
+ checkFailed: '無法驗證授權,目前顯示快取的狀態。請檢查網路後重新整理。',
+ sessionExpired: '工作階段已過期,請重新登入以驗證您的方案。',
+ sessionLostSignedOut: '您的工作階段已無法續期,已將您登出。隨時可以重新登入。',
+ deviceActivationFailed: '裝置註冊失敗,無法自動續期工作階段。',
+ notLoggedIn: '您尚未登入。',
+ loginLink: '使用 Geekfun 登入',
+ refresh: '重新整理',
+ logout: '登出',
+ manage: '管理訂閱',
+ },
+ },
+ aside: {
+ aiAssistant: 'AI 助理',
+ tasks: '工作',
+ },
+ connection: {
+ prompt: {
+ title: '代理提示詞',
+ label: '代理提示詞',
+ description: '為 AI 代理補充此連線的上下文。',
+ help: '此連線附加到代理時,會在全域系統提示詞之後傳送給代理。',
+ placeholder: '描述資料的業務意義、命名慣例或常用查詢。',
+ configured: '已設定',
+ add: '新增',
+ edit: '編輯',
+ clear: '清除',
+ cancel: '取消',
+ confirm: '確認',
+ },
+ },
+ connectionsPage: {
+ addSshProfile: '新增 SSH 設定檔',
+ copySuffix: '(副本)',
+ sshProfilesSection: 'SSH 設定檔',
+ sshProfile: 'SSH 設定檔',
+ },
+ common: {
+
+ copy: '複製',
+ copied: '已複製!',
+ browse: '瀏覽',
+ settings: '設定',
+ loading: '載入中...',
+ notifications: {
+ codeCopied: '已複製程式碼',
+ },
+ buttons: {
+ create: '建立',
+ save: '儲存',
+ cancel: '取消',
+ delete: '刪除',
+ edit: '編輯',
+ confirm: '確認',
+ test: '測試',
+ connect: '連線',
+ disconnect: '中斷連線',
+ duplicate: '複製',
+ saveChanges: '儲存變更',
+ createConnection: '建立連線',
+ testConnection: '測試連線',
+ dismiss: '關閉',
+ close: '關閉',
+ browse: '瀏覽',
+ retry: '重試',
+ continue: '繼續',
+ refresh: '重新整理',
+ },
+ status: {
+ connected: '已連線',
+ disconnected: '已中斷連線',
+ connecting: '連線中...',
+ error: '連線錯誤',
+ testing: '正在測試連線...',
+ success: '連線成功!',
+ failed: '連線失敗',
+ },
+ },
+ ssl: {
+ errors: {
+ invalidMode: '無效的 SSL 模式',
+ caCertRequired: 'verify-ca/verify-full 模式需要提供 CA 憑證路徑',
+ invalidCaPath: 'CA 憑證路徑無效',
+ invalidCertPath: '用戶端憑證路徑無效',
+ invalidKeyPath: '用戶端私密金鑰路徑無效',
+ },
+ mode: {
+ label: 'SSL/TLS 模式',
+ disable: '停用',
+ prefer: '優先',
+ require: '強制',
+ verifyca: '驗證 CA',
+ verifyfull: '完整驗證',
+ },
+ modeDesc: {
+ disable: '不加密',
+ prefer: '嘗試加密,失敗則退回明文',
+ require: '一律加密,略過憑證驗證',
+ verifyca: '加密 + 驗證 CA 憑證',
+ verifyfull: '加密 + 驗證 CA 與主機',
+ },
+ certSettings: {
+ title: '憑證設定',
+ caCert: 'CA 憑證',
+ caCertPlaceholder: 'CA 憑證路徑',
+ clientCert: '用戶端憑證',
+ clientCertPlaceholder: '用戶端憑證路徑',
+ clientKey: '用戶端私密金鑰',
+ clientKeyPlaceholder: '用戶端私密金鑰路徑',
+ },
+ sqlServer: {
+ trustServerCert: '信任伺服器憑證',
+ trustServerCertHint: '接受自我簽署憑證',
+ },
+ },
+ transfer: {
+ title: '傳輸',
+ subtitle: '匯入、匯出與移轉您的資料',
+ tabs: {
+ export: '匯出',
+ import: '匯入',
+ migration: '移轉',
+ structure: '結構',
+ },
+ export: {
+ step: {
+ source: '來源',
+ format: '格式',
+ output: '輸出',
+ formatOutput: '格式與輸出',
+ preview: '預覽',
+ execute: '開始匯出',
+ },
+ selectTablesFirst: '請先在上方選取資料表以設定欄位',
+ tables: {
+ label: '資料表',
+ loadFailed: '載入資料表失敗',
+ },
+ columns: {
+ label: '欄位',
+ selectAll: '全選',
+ deselectAll: '取消全選',
+ loadFailed: '載入欄位失敗',
+ },
+ whereClause: 'WHERE 子句(選填)',
+ where: 'WHERE 子句(選填)',
+ whereClausePlaceholder: 'status = "active"',
+ orderBy: 'ORDER BY(選填)',
+ orderByPlaceholder: 'created_at DESC',
+ limit: 'LIMIT(選填)',
+ limitPlaceholder: '1000',
+ scope: '範圍',
+ delimiter: '分隔符號',
+ delimiterOptions: {
+ comma: '逗號(,)',
+ semicolon: '分號(;)',
+ tab: '定位字元',
+ },
+ includeHeader: '包含標頭',
+ dateFormat: '日期格式',
+ dateFormatOptions: {
+ iso8601: 'ISO 8601',
+ unix: 'Unix',
+ },
+ rowsPerBatch: '列數/批次',
+ createTable: 'CREATE TABLE',
+ dropTable: 'DROP TABLE',
+ worksheet: '工作表',
+ freeze: '凍結',
+ autoFit: '自動調整',
+ outputPath: '輸出路徑',
+ selectFormat: '選擇格式',
+ showAdvanced: '顯示進階選項',
+ hideAdvanced: '隱藏進階選項',
+ encoding: '編碼',
+ preview: '預覽',
+ outputFile: '輸出檔案',
+ },
+ connection: {
+ connectFailed: '連線失敗',
+ databasesFailed: '載入資料庫清單失敗',
+ schemasFailed: '載入結構描述清單失敗',
+ label: '連線',
+ placeholder: '選擇連線',
+ noConnections: '沒有可用的連線,請先新增連線。',
+ connected: '已連線',
+ offline: '離線',
+ databaseLabel: '資料庫',
+ databasePlaceholder: '選擇資料庫',
+ system: '系統',
+ loadingDatabases: '正在載入資料庫...',
+ schemaLabel: '結構描述',
+ schemaPlaceholder: '選擇結構描述',
+ loadingSchemas: '正在載入結構描述...',
+ tableLabel: '資料表',
+ tablePlaceholder: '選擇資料表',
+ },
+ import: {
+ step: {
+ file: '選擇檔案',
+ mapping: '目標與對應',
+ options: '選項與預覽',
+ execute: '匯入',
+ },
+ dropzone: {
+ title: '將檔案拖放到這裡',
+ subtitle: '或點擊瀏覽',
+ supported: '支援格式:CSV、JSONL、SQL、Excel (.xlsx)',
+ instruction: '或點擊以從電腦瀏覽',
+ },
+ detected: {
+ format: '偵測到的格式',
+ encoding: '偵測到的編碼',
+ rows: '列數(估計)',
+ },
+ autoMap: '依名稱自動對應',
+ clearAll: '全部清除',
+ conflict: {
+ label: '衝突處理',
+ skip: '略過重複資料',
+ replace: '取代現有資料',
+ upsert: '更新現有資料(upsert)',
+ abort: '發生錯誤時中止',
+ },
+ truncateBefore: '匯入前清空資料表',
+ dryRun: '試跑(僅驗證,不插入資料)',
+ browseFiles: '瀏覽檔案',
+ fileSize: '檔案大小',
+ detectedColumns: '偵測到的欄位',
+ createDbIfNotExists: '資料庫不存在時建立',
+ tablesAutoCreated: '資料表將自動建立',
+ skipPlaceholder: '略過',
+ skip: '(略過)',
+ importData: '匯入資料',
+ dataPreview: '資料預覽',
+ previewRows: '10 列',
+ selectFileToPreview: '選擇檔案以預覽資料',
+ importSettings: '匯入設定',
+ batchSize: '批次大小',
+ loadingPreview: '正在載入預覽...',
+ noPreviewData: '沒有預覽資料',
+ fileDetails: '檔案詳細資訊',
+ },
+ structure: {
+ title: '結構',
+ subtitle: '產生 DDL 並執行 SQL 檔案',
+ generateDdl: '產生 DDL',
+ runSqlFile: '執行 SQL 檔案',
+ objects: '資料庫物件',
+ selectAll: '全選',
+ deselectAll: '取消全選',
+ loadingObjects: '正在載入物件...',
+ noObjects: '找不到任何物件。請選擇連線與資料庫。',
+ objectsSelected: '個物件已選取',
+ options: 'DDL 選項',
+ includeCreateTable: 'CREATE TABLE 陳述式',
+ includePrimaryKeys: '主索引鍵',
+ includeForeignKeys: '外部索引鍵',
+ includeIndexes: '索引',
+ includeDropIfExists: '在 CREATE 前加上 DROP IF EXISTS',
+ includeIfNotExists: 'CREATE 時加上 IF NOT EXISTS',
+ generate: '產生 DDL',
+ preview: 'DDL 預覽',
+ copyToClipboard: '複製到剪貼簿',
+ saveToFile: '儲存到檔案...',
+ sqlFile: 'SQL 檔案',
+ errorHandling: '錯誤處理',
+ onErrorStop: '遇到第一個錯誤即停止',
+ onErrorSkip: '略過並繼續',
+ onErrorRollback: '復原(盡力而為;遇到第一個錯誤即中止)',
+ reset: '重設',
+ execute: '執行',
+ },
+ migration: {
+ title: '移轉',
+ subtitle: '跨引擎資料移轉',
+ step: {
+ source: '來源',
+ target: '目標',
+ mapping: '對應',
+ configure: '設定',
+ execute: '執行',
+ },
+ sourceConnection: '來源連線',
+ targetConnection: '目標連線',
+ availableTables: '可用資料表',
+ loadingTables: '正在載入資料表...',
+ noTables: '找不到任何資料表',
+ selectAll: '全選',
+ deselectAll: '取消全選',
+ tablesSelected: '個資料表已選取',
+ direction: '移轉方向',
+ createTables: '目標資料表不存在時建立',
+ dropTables: '移轉前刪除目標資料表',
+ loadingMapping: '正在產生類型對應...',
+ typeConversions: '個欄位需要類型轉換',
+ batchSize: '批次大小',
+ onError: '錯誤處理',
+ onErrorSkipRow: '略過該列並繼續',
+ onErrorSkipTable: '略過該資料表並繼續',
+ onErrorAbort: '中止移轉',
+ migrateIndexes: '移轉索引',
+ migrateForeignKeys: '移轉外部索引鍵',
+ migrateConstraints: '移轉條件約束',
+ summary: '移轉摘要',
+ tables: '資料表',
+ totalRows: '總列數',
+ conversions: '類型轉換',
+ executing: '正在執行移轉...',
+ pleaseWait: '正在傳輸資料,請稍候',
+ startMigration: '開始移轉',
+ migrateAgain: '再次移轉',
+ back: '上一步',
+ next: '下一步',
+ },
+ format: {
+ label: '格式',
+ csv: 'CSV (.csv)',
+ jsonl: 'JSONL (.jsonl)',
+ sql: 'SQL (.sql)',
+ excel: 'Excel (.xlsx)',
+ defaults: {
+ csv: '逗號分隔、雙引號、UTF-8、包含標頭',
+ jsonl: '每行一個 JSON 物件、精簡、UTF-8、ISO 8601 日期',
+ sql: '自動填入目標資料表、批次大小 1000、包含 CREATE TABLE',
+ excel: '包含標頭、自動調整欄寬、凍結標頭列',
+ },
+ advancedOptions: '進階選項',
+ },
+ progress: {
+ preparing: '準備中',
+ exporting: '匯出中...',
+ importing: '匯入中...',
+ elapsed: '已耗時',
+ remaining: '預估剩餘',
+ rows: '列',
+ exported: '已匯出',
+ imported: '已匯入',
+ skipped: '已略過',
+ errors: '錯誤',
+ cancel: '取消',
+ runInBackground: '在背景執行',
+ },
+ result: {
+ success: '已成功完成',
+ partial: '已完成但有錯誤',
+ failed: '失敗',
+ duration: '耗時',
+ file: '檔案',
+ openFile: '開啟檔案',
+ openFolder: '開啟資料夾',
+ exportAgain: '再次匯出',
+ importAgain: '再次匯入',
+ viewTable: '檢視資料表',
+ processed: '已處理',
+ skipped: '已略過',
+ errorCount: '錯誤',
+ },
+ tasks: {
+ title: '工作',
+ clearCompleted: '清除已完成',
+ goToTask: '前往工作',
+ dismiss: '關閉',
+ noTasks: '目前沒有傳輸工作',
+ rows: '列',
+ emptyDescription: '匯出、匯入與移轉工作會顯示在這裡',
+ status: {
+ pending: '等待中',
+ running: '執行中',
+ completed: '已完成',
+ failed: '失敗',
+ },
+ startedAgo: '{time} 前開始',
+ },
+ common: {
+
+ connection: '連線',
+ database: '資料庫',
+ schema: '結構描述',
+ table: '資料表',
+ back: '返回',
+ next: '下一步',
+ browse: '瀏覽...',
+ error: '錯誤',
+ cancel: '取消',
+ save: '儲存',
+ close: '關閉',
+ tableName: '資料表名稱',
+ rows: '列數',
+ type: '類型',
+ noTablesFound: '找不到任何資料表',
+ columns: '欄位',
+ deselectAll: '取消全選',
+ scopeServer: '伺服器',
+ scopeDatabase: '資料庫',
+ scopeTables: '資料表',
+ },
+ },
+ pages: {
+ connections: {
+ title: '連線管理',
+ subtitle: '管理您的資料庫連線',
+ search: '搜尋連線...',
+ stats: {
+ totalConnections: '連線總數',
+ activeSessions: '作用中的工作階段',
+ sshProfiles: 'SSH 設定檔',
+ ago: '{time} 前',
+ },
+ saved: '已儲存的連線',
+ addNew: '新增連線',
+ addNewHint: 'PostgreSQL、MySQL、SQLite...',
+ empty: {
+ title: '找不到任何連線',
+ message: '沒有符合搜尋條件「{query}」的連線',
+ },
+ delete: {
+ title: '刪除連線',
+ message: '確定要刪除「{name}」嗎?此操作無法復原。',
+ },
+ error: {
+ title: '連線錯誤',
+ },
+ saveFailed: '儲存連線失敗',
+ },
+ settings: {
+ title: '設定',
+ subtitle: '設定應用程式偏好',
+ general: {
+ title: '一般',
+ description: '管理您的帳戶、方案、主題與應用程式更新',
+ theme: '主題',
+ themeSelect: '選擇主題',
+ themeHelp: '選擇淺色、深色或跟隨系統的主題',
+ themes: {
+ light: '淺色',
+ dark: '深色',
+ system: '跟隨系統',
+ },
+ language: '語言',
+ languageSelect: '選擇語言',
+ languageHelp: '選擇您偏好的語言',
+ languages: {
+ enUS: 'English',
+ zhCN: '简体中文',
+ auto: '自動(跟隨系統)',
+ },
+ },
+ mcp: {
+ title: 'MCP Bridge',
+ status: '狀態',
+ running: '正在連接埠 {port} 上執行',
+ stopped: '已停止',
+ port: '連接埠',
+ portDesc: 'MCP Bridge 伺服器使用的連接埠(留空則自動指定)',
+ restart: '重新啟動 Bridge',
+ restartSuccess: 'MCP Bridge 已成功重新啟動',
+ restartFailed: '重新啟動失敗',
+ restartFailedDetail: '無法重新啟動 MCP Bridge',
+ restartTimeout: 'MCP Bridge 未能在 60 秒內啟動',
+ shuttingDown: '正在關閉...',
+ starting: '正在啟動...',
+ autoStart: '自動啟動',
+ autoStartDesc: '應用程式啟動時自動啟動 MCP Bridge',
+ saveFailed: '無法儲存 MCP 設定',
+ },
+ about: {
+ title: '關於',
+ version: '版本',
+ license: '授權條款',
+ licenseName: 'Apache 2.0',
+ repository: '儲存庫',
+ website: '網站',
+ copyright: '© {year} GEEKFUN,保留一切權利。',
+ description: 'SqlKit 是一款具 AI 代理能力的跨平台 SQL 資料庫圖形化用戶端。以 Rust + Tauri 建構。',
+ },
+ feedback: {
+ preparing: '正在準備下載…',
+ downloading: '正在下載…',
+ installing: '正在安裝並驗證…',
+ complete: '安裝完成',
+ failed: '操作失敗',
+ checking: '正在檢查更新…',
+ removing: '正在移除…',
+ removed: '已成功移除',
+ refreshing: '正在重新整理狀態…',
+ refreshed: '狀態已重新整理',
+ loading: '正在載入設定…',
+ loadFailed: '無法載入此區塊',
+ retry: '重試',
+ saved: '變更已儲存',
+ saving: '正在儲存變更…',
+ testing: '正在測試連線…',
+ syncing: '正在同步模型…',
+ synced: '模型已同步',
+ opening: '正在瀏覽器中開啟…',
+ opened: '已在瀏覽器中開啟',
+ signedOut: '已登出',
+ },
+ jre: {
+ title: 'JRE 與驅動程式',
+ description: '管理資料庫連線所需的 Java 執行環境與 JDBC 驅動程式',
+ jreCard: {
+ title: 'Java 執行環境',
+ description: 'JDBC 橋接連線所需(Oracle、DB2、H2、Derby)',
+ status: {
+ installed: '已安裝',
+ notInstalled: '未安裝',
+ checking: '檢查中...',
+ managed: '受管理',
+ system: '系統',
+ versionUnknown: '未知',
+ systemWarning: '系統 Java 版本未知或不相容。請下載受管理的 JRE 以確保相容性。',
+ systemInvalid: '沒有有效的 JRE',
+ managedRecommended: '使用受管理的 JRE',
+ },
+ actions: {
+ download: '下載 JRE',
+ remove: '移除 JRE',
+ redownload: '重新下載',
+ checkUpdates: '檢查更新',
+ },
+ notifications: {
+ upToDate: 'JRE 已是最新版本',
+ updateAvailable: '有可用的 JRE 更新',
+ newVersion: '版本 {version} 可用',
+ checkUpdatesFailed: '檢查 JRE 更新失敗',
+ downloadFailed: '下載 JRE 失敗',
+ downloadSuccess: 'JRE 下載成功',
+ removeFailed: '移除 JRE 失敗',
+ },
+ },
+ bridgeCard: {
+ title: '橋接 JAR',
+ description: '用於資料庫連線的 JDBC 橋接元件',
+ status: {
+ installed: '已安裝',
+ notInstalled: '未安裝',
+ checking: '檢查中...',
+ },
+ actions: {
+ download: '下載橋接',
+ remove: '移除橋接',
+ },
+ notifications: {
+ downloadFailed: '下載橋接 JAR 失敗',
+ downloadSuccess: '橋接 JAR 下載成功',
+ removeFailed: '移除橋接 JAR 失敗',
+ },
+ },
+ jdbcToggle: {
+ title: 'JDBC 連線',
+ description: '啟用 JDBC 資料庫支援(JRE + 橋接 + 驅動程式)',
+ label: '不需要 JDBC',
+ },
+ actions: {
+ refresh: '重新整理',
+ },
+ driversCard: {
+ title: 'JDBC 驅動程式',
+ description: '各資料庫專用的 JDBC 驅動程式檔案',
+ label: {
+ versions: '個版本',
+ },
+ status: {
+ installed: '已安裝',
+ notInstalled: '未安裝',
+ loading: '正在載入驅動程式...',
+ },
+ actions: {
+ download: '下載',
+ remove: '移除',
+ checkUpdates: '檢查更新',
+ },
+ notifications: {
+ upToDate: '驅動程式已是最新版本',
+ updateAvailable: '有可用的驅動程式更新',
+ newVersion: '版本 {version} 可用',
+ checkUpdatesFailed: '檢查驅動程式更新失敗',
+ downloadFailed: '下載驅動程式失敗',
+ downloadSuccess: '驅動程式下載成功',
+ removeFailed: '移除驅動程式失敗',
+ installBridgeFirst: '請先安裝橋接 JAR,再嘗試下載驅動程式',
+ },
+ empty: {
+ title: '尚未設定任何驅動程式',
+ message: '連線至 JDBC 資料庫時會自動下載。',
+ },
+ },
+ },
+ editor: {
+ title: '編輯器',
+ description: '設定 SQL 編輯器的行為與外觀',
+ fontSize: '字型大小',
+ fontSizeHelp: '編輯器字型大小(像素,8–32)',
+ fontSizeError: '字型大小必須介於 8 到 32 之間',
+ tabSize: 'Tab 大小',
+ tabSizeHelp: '每個 Tab 的空格數(1–8)',
+ tabSizeError: 'Tab 大小必須介於 1 到 8 之間',
+ wordWrap: '自動換行',
+ wordWrapHelp: '在編輯器中換行顯示長行',
+ showLineNumbers: '顯示行號',
+ showLineNumbersHelp: '在編輯器邊欄顯示行號',
+ showMinimap: '顯示縮圖',
+ showMinimapHelp: '在右側顯示縮圖總覽',
+ indentWidth: '縮排寬度',
+ indentWidthHelp: '格式化 SQL 時每層縮排的空格數(1–8)',
+ indentWidthError: '縮排寬度必須介於 1 到 8 之間',
+ lineWidth: '行寬',
+ lineWidthHelp: '格式化 SQL 的目標行寬(字元數,40–200)',
+ lineWidthError: '行寬必須介於 40 到 200 之間',
+ },
+ query: {
+ title: '查詢',
+ description: '設定查詢執行的預設值',
+ defaultLimit: '預設列數上限',
+ defaultLimitHelp: '每次查詢傳回的最大列數(10–10000)',
+ defaultLimitError: '列數上限必須介於 10 到 10000 之間',
+ queryTimeout: '查詢逾時(秒)',
+ queryTimeoutHelp: '查詢執行時間上限(秒,1–300)',
+ queryTimeoutError: '逾時時間必須介於 1 到 300 秒之間',
+ autoSave: '自動儲存',
+ autoSaveHelp: '自動儲存查詢變更',
+ },
+ ai: {
+ title: 'AI 設定',
+ tabLabel: 'LLMs',
+ description: '設定 AI 模型供應商與對話行為',
+ missing: '尚未設定 AI 模型。請在設定中新增供應商並選擇模型。',
+ providerList: {
+ title: '供應商',
+ description: '管理您的 AI 模型供應商',
+ addProvider: '新增供應商',
+ empty: '尚未設定任何供應商。新增供應商即可啟用 AI 功能。',
+ emptyAction: '新增第一個供應商',
+ deleteConfirm: '確定要刪除「{name}」嗎?',
+ deleteConfirmTitle: '刪除供應商',
+ sync: '同步模型',
+ syncing: '同步中...',
+ syncSuccess: '已同步 {count} 個模型',
+ syncFailed: '同步模型失敗',
+ modelCount: '{count} 個模型',
+ testConnection: '測試',
+ testing: '測試中...',
+ testSuccess: '連線成功',
+ testFailed: '連線測試失敗',
+ },
+ form: {
+ addTitle: '新增供應商',
+ editTitle: '編輯供應商',
+ providerType: '供應商類型',
+ providerTypeHelp: '選擇預設項,或選擇「自訂」以使用其他供應商',
+ presetOpenai: 'OpenAI',
+ presetAnthropic: 'Anthropic',
+ presetAzure: 'Azure OpenAI',
+ presetCustom: '自訂',
+ name: '顯示名稱',
+ namePlaceholder: '我的供應商',
+ nameHelp: '為此供應商取一個易記的名稱',
+ apiCompatibility: 'API 相容性',
+ apiCompatibilityPlaceholder: 'openai, anthropic, azure',
+ apiCompatibilityHelp: 'API 協定類型。相容服務(如 Ollama 或 DeepSeek)請使用「openai」。',
+ apiKey: 'API 金鑰',
+ apiKeyPlaceholder: 'sk-...',
+ apiKeyHelp: '您的供應商 API 金鑰。僅儲存在本機,絕不會傳送到我們的伺服器。',
+ baseUrl: '基礎 URL',
+ baseUrlPlaceholder: 'https://api.openai.com/v1',
+ baseUrlHelp: 'API 端點 URL。使用官方供應商時請保持預設值。',
+ proxy: '代理',
+ proxyPlaceholder: 'http://proxy:8080',
+ proxyHelp: 'API 請求可選用的 HTTP/SOCKS5 代理',
+ proxyMode: '代理模式',
+ contextWindow: 'Context Window 覆寫',
+ contextWindowHelp: '覆寫預設的上下文視窗大小(選填)',
+ showKey: '顯示',
+ hideKey: '隱藏',
+ save: '儲存供應商',
+ models: '模型',
+ modelsPlaceholder: 'gpt-4o, gpt-4o-mini',
+ modelsHelp: '以逗號分隔的模型 ID。若供應商支援,將從其 API 自動同步。',
+ validation: {
+ nameRequired: '顯示名稱為必填欄位',
+ apiCompatibilityRequired: 'API 相容性為必填欄位',
+ invalidApiCompatibility: 'API 相容性必須是「openai」、「anthropic」或「azure」',
+ baseUrlInvalid: '基礎 URL 必須以 http:// 或 https:// 開頭',
+ },
+ },
+ chat: {
+ title: 'Agent',
+ description: '設定代理的執行階段行為',
+ autoCompactLabel: '自動壓縮訊息',
+ autoCompactDescription: '接近上下文上限時,自動摘要較舊的訊息以節省 Token',
+ maxIterationsLabel: '最大迭代次數',
+ maxIterationsDescription: '代理停止前的最大工具呼叫迭代次數(1–1000)',
+ wallClockBudgetLabel: '時間上限(分鐘)',
+ wallClockBudgetDescription: '代理停止前的最長實際時間(1–240 分鐘)',
+ tokenBudgetLabel: 'Token 預算',
+ tokenBudgetDescription: '代理停止前可消耗的最大 Token 數量',
+ systemPromptLabel: '系統提示詞',
+ systemPromptDescription: '附加資料庫連線時傳送給代理的全域系統提示詞。可描述您的使用情境、專有名詞或業務背景。',
+ systemPromptAdd: '新增系統提示詞',
+ systemPromptEdit: '編輯系統提示詞',
+ systemPromptDelete: '刪除系統提示詞',
+ systemPromptEmpty: '尚未設定系統提示詞。',
+ systemPromptSave: '儲存',
+ systemPromptCancel: '取消',
+ systemPromptSaveFailed: '無法儲存系統提示詞。',
+ systemPromptUltimateOnly: 'Agent Prompt 是 Ultimate 功能',
+ },
+ },
+ updates: {
+ title: '更新',
+ description: '檢查應用程式更新',
+ checkForUpdates: '檢查更新',
+ checkForUpdatesHelp: '開啟「一般」時會自動檢查。只有選擇「立即更新」時才會安裝更新。',
+ check: '立即檢查',
+ checking: '檢查中...',
+ downloading: '下載中...',
+ installing: '安裝中...',
+ updateAvailable: '有可用更新',
+ upToDate: '已是最新版本',
+ checkFailed: '檢查更新失敗',
+ downloadFailed: '下載更新失敗',
+ installFailed: '安裝更新失敗',
+ installed: '更新已安裝,正在重新啟動...',
+ newVersion: '版本 {version} 可用',
+ },
+ },
+ history: {
+ title: '歷史記錄',
+ subtitle: '檢視並管理您的查詢歷史記錄',
+ recent: '最近的查詢',
+ recentDescription: '您最近執行的查詢',
+ empty: '尚無查詢歷史記錄。',
+ search: '搜尋查詢...',
+ filterAll: '全部',
+ filterSuccess: '成功',
+ filterError: '錯誤',
+ clearAll: '全部清除',
+ clearNonFavorites: '清除非我的最愛',
+ clearAllConfirm: '確定要清除所有歷史記錄嗎?',
+ clearNonFavoritesConfirm: '確定要清除所有非我的最愛的歷史記錄嗎?',
+ columns: {
+ sql: 'SQL',
+ connection: '連線',
+ database: '資料庫',
+ status: '狀態',
+ time: '時間',
+ executionTime: '耗時',
+ actions: '操作',
+ },
+ status: {
+ success: '成功',
+ error: '錯誤',
+ },
+ actions: {
+ rerun: '在編輯器中重新執行',
+ favorite: '加入我的最愛',
+ unfavorite: '取消我的最愛',
+ delete: '刪除',
+ },
+ notifications: {
+ cleared: '歷史記錄已清除',
+ deleted: '記錄已刪除',
+ rerun: '查詢已載入編輯器',
+ },
+ },
+ importExport: {
+ title: '匯入 / 匯出',
+ subtitle: '匯入與匯出您的資料',
+ card: {
+ title: '資料匯入 / 匯出',
+ description: '匯入與匯出資料庫結構描述與資料',
+ comingSoon: '匯入與匯出功能將於未來的更新中提供。',
+ },
+ },
+ queries: {
+ title: '查詢',
+ subtitle: '撰寫並執行 SQL 查詢',
+ selectConnection: '選擇連線',
+ selectDatabase: '選擇資料庫',
+ noTab: '沒有開啟的查詢分頁',
+ newTab: '新增查詢',
+ landing: {
+ ready: '準備開始撰寫查詢',
+ connectedAs: '連線身分',
+ currentDatabase: '資料庫',
+ selectConnection: '選擇連線',
+ tip: '提示:在側邊欄雙擊資料表即可檢視其資料',
+ },
+ editor: {
+ title: 'SQL 編輯器',
+ description: '在此撰寫您的 SQL 查詢',
+ execute: '執行',
+ explain: '解釋',
+ format: '格式化 SQL',
+ },
+ shortcuts: {
+ execute: '執行查詢 ({key}Enter)',
+ explain: '解釋查詢 (F6)',
+ format: '格式化 SQL (Shift+Alt+F)',
+ save: '儲存 ({key}S)',
+ saveAs: '另存為 .sql 檔案',
+ comment: '切換註解 ({key}/)',
+ },
+ status: {
+ connection: '連線',
+ database: '資料庫',
+ rows: '列數',
+ time: '耗時',
+ executing: '執行中...',
+ connectionLost: '連線已中斷。資料庫連線已關閉。',
+ reconnecting: '正在重新連線...',
+ },
+ notifications: {
+ querySaved: '查詢已儲存',
+ saveFailed: '儲存失敗',
+ loadFailed: '載入查詢失敗',
+ noStatementFound: '游標位置找不到 SQL 陳述式',
+ formatFailed: 'SQL 格式化失敗',
+ noActiveConnection: '沒有作用中的連線',
+ selectConnectionFirst: '執行查詢前請先選擇連線與資料庫',
+ tableActionSuccess: '資料表 {table} {action} 成功',
+ tableActionFailed: '{action} 資料表失敗:{error}',
+ },
+ orphanDialog: {
+ title: '孤立分頁',
+ message: '此分頁屬於另一個連線,無法執行查詢。您仍可編輯並儲存其內容。',
+ acknowledge: '保留為孤立分頁',
+ close: '關閉分頁',
+ },
+ executeOrphanDialog: {
+ title: '連線已變更',
+ message: '此查詢分頁的原始連線已變更:{from} → {to}。要重新綁定至目前作用中的連線並執行嗎?',
+ cancel: '取消',
+ close: '關閉分頁',
+ rebindAndExecute: '重新綁定並執行',
+ },
+ explain: {
+ title: '執行計畫',
+ treeView: '樹狀',
+ summaryView: '摘要',
+ rawView: '原始',
+ analyze: 'Explain Analyze',
+ running: '正在產生執行計畫...',
+ empty: '沒有執行計畫資料',
+ nodeCount: '{count} 個節點',
+ summary: {
+ totalCost: '預估總成本:{cost}',
+ mostExpensive: '成本最高:{node}',
+ noCostData: '沒有成本資料',
+ },
+ node: {
+ rowEstimate: '估:{rows}',
+ actualRows: '實:{rows}',
+ discrepancyWarning: '實際列數明顯超過預估({actual} vs {estimated},{ratio} 倍)',
+ },
+ error: {
+ parseFailed: '執行計畫解析失敗',
+ noPlan: '資料庫未傳回執行計畫',
+ },
+ tabLabels: {
+ results: '結果',
+ explain: '解釋',
+ },
+ analyzeToggle: '切換 EXPLAIN ANALYZE 模式(目前:{mode})',
+ columnHeaders: {
+ nodeType: '節點類型',
+ relation: '關聯',
+ index: '索引',
+ cost: '成本',
+ rows: '列數',
+ details: '詳細資訊',
+ },
+ },
+ },
+ },
+ dataStudio: {
+ title: 'DATA STUDIO BETA',
+ subtitle: 'AI 驅動的 SQL 資料分析',
+ inputPlaceholder: '詢問關於您資料的問題...',
+ modelUnavailable: '所選模型無法使用',
+ history: {
+ title: '歷史記錄',
+ newSession: '新增工作階段',
+ justNow: '剛剛',
+ minutesAgo: '{count} 分鐘前',
+ hoursAgo: '{count} 小時前',
+ yesterday: '昨天',
+ noSessions: '沒有先前的工作階段',
+ messages: '則訊息',
+ sources: '個來源',
+ delete: '刪除工作階段',
+ sessionFallback: '對話',
+ empty: '尚無工作階段',
+ },
+ agent: {
+ emptyState: '提出問題,或描述您想執行的查詢。',
+ noSource: '請先附加資料來源以開始。',
+ stop: '停止',
+ continue: '繼續',
+ continueHint: '代理已暫停。點擊「繼續」以恢復,或點擊「停止」以結束此工作階段。',
+ clearChat: '清除對話',
+ riskSafe: '安全操作',
+ riskElevated: '較高風險',
+ riskDestructive: '破壞性操作',
+ allowOnce: '允許一次',
+ allowAlways: '一律允許',
+ deny: '拒絕',
+ denyAlways: '一律拒絕',
+ cancelRun: '取消',
+ preparing: '準備中...',
+ thinking: '思考中',
+ iteration: '步驟',
+ waitingModel: '正在等待模型...',
+ compacting: '正在壓縮上下文...',
+ viewFullResult: '檢視完整結果',
+ viewMore: '更多',
+ message: {
+ toolBlocked: '已封鎖',
+ toolRejected: '已拒絕',
+ blockedNotice: '已被權限封鎖,未執行此操作',
+ historicalBlockedNotice: '先前的嘗試已被封鎖,未執行此操作',
+ rejectedNotice: '已由您拒絕,未執行此操作',
+ interruptedNotice: '無法取得執行結果',
+ unavailableNotice: '操作無法使用,未執行此操作',
+ connectionLabel: '連線:{name}',
+ requiredAction: '需要:{action}',
+ reviewPermissions: '檢視權限',
+ reviewHelp: '儲存權限變更並不會執行被封鎖的操作。準備好後請回到對話,選擇「重試請求」。',
+ reviewConnectionHelp: '變更僅適用於此連線,系統預設值維持不變。請儲存後回到對話以重試請求。',
+ connectionUnavailable: '無法識別已儲存的連線。請先在對話中重新附加該連線,再檢視其權限。',
+ backToChat: '回到對話',
+ retryRequest: '重試請求',
+ retryPrompt: '請使用 {tool} 與下列原始參數,重試先前被封鎖或被拒絕的請求:\n{args}\n請重新檢查目前的權限,並在需要時請求核准。請勿重複先前已成功的操作。',
+ awaitingPermissionDecision: '已暫停。請檢視被封鎖的操作,然後重試或傳送新的請求。',
+ removeDenyRule: '移除「一律拒絕」規則',
+ ruleRemoved: '規則已移除。請重試請求,以檢查目前的存取權限與確認需求。',
+ sourceUnavailable: '原始來源已不在此對話中。請先重新附加,再重試。',
+ denialSource: {
+ system: '已被系統 AI 預設值拒絕。',
+ connection: '已被此連線的 AI 權限拒絕。',
+ conversation: '已被此對話的來源限制拒絕。',
+ rule: '「一律拒絕」規則在此對話中封鎖了此工具。',
+ unknown: 'AI 權限封鎖了此操作。重試前請先檢視存取權限。',
+ },
+ toolDenied: '工具執行已被拒絕',
+ toolError: '工具執行失敗',
+ waitingForModel: '正在等待模型',
+ compactionInProgress: '正在壓縮對話',
+ preparingInProgress: '準備中',
+ thinkingInProgress: '思考中…',
+ thinkingDone: '思考完成',
+ thinkingDuration: '{s} 秒',
+ generating: '產生中…',
+ awaitingConfirm: '正在等待 {tool} 的核准…',
+ executingTool: '正在執行 {tool}…',
+ toolWrote: '已寫入',
+ toolRead: '已讀取',
+ toolExecuted: '已執行',
+ toolSearched: '已搜尋',
+ toolDeleted: '已刪除',
+ toolUpdated: '已更新',
+ iterationLabel: '第 {n} 輪',
+ compactionLabel: '對話已壓縮({trigger})',
+ compactionSummary: '顯示摘要',
+ compactionTrigger: {
+ auto: '自動',
+ manual: '手動',
+ },
+ },
+ },
+ contextIndicator: {
+ offBadgeTitle: '自動壓縮已關閉 — 上下文不會自動縮減',
+ popoverTitle: 'Context window',
+ warningText: '自動壓縮已關閉,且上下文已超過門檻。請立即壓縮,否則下一次請求可能失敗。',
+ labelUsed: '已使用',
+ labelCapacity: '容量',
+ labelWindow: '視窗',
+ labelReservedOut: '保留輸出',
+ labelAutoCompactAt: '自動壓縮門檻',
+ labelStatus: '狀態',
+ compactNow: '立即壓縮',
+ compacting: '壓縮中…',
+ compactSuccess: '上下文已壓縮',
+ compactFailed: '壓縮失敗:{error}',
+ statusIdle: '閒置',
+ statusOverThresholdOff: '超過門檻(自動壓縮已關閉)',
+ statusAutoCompactOff: '自動壓縮已關閉',
+ statusWillAutoCompact: '將自動壓縮',
+ statusHealthy: '正常',
+ tooltipIdle: '上下文用量',
+ tooltipAutoCompactOff: '自動壓縮已關閉',
+ },
+ addSource: {
+ title: '新增資料來源',
+ selectConnection: '選擇連線',
+ searchPlaceholder: '搜尋連線...',
+ noConnections: '找不到相容的連線',
+ allAttached: '所有相容的連線皆已附加',
+ connectionsFound: '找到 {count} 個連線',
+ connectSource: '連線',
+ },
+ modifySource: {
+ title: '修改資料來源',
+ accessPermissions: '存取權限',
+ inheritTitle: '使用連線權限',
+ saveChanges: '儲存變更',
+ modeDefault: '詢問',
+ modeFull: '自動',
+ },
+ detachSource: {
+ title: '中斷資料來源',
+ message: '確定要中斷此資料來源嗎?這會將該連線從 Data Studio 中移除。',
+ confirm: '中斷',
+ },
+ },
+ components: {
+ serverForm: {
+ basicTab: '基本',
+ advancedTab: '進階',
+ title: {
+ edit: '編輯連線',
+ new: '新增連線',
+ },
+ description: {
+ edit: '更新您的資料庫連線設定。',
+ new: '設定新的資料庫連線。',
+ },
+ labels: {
+ connectionName: '連線名稱',
+ databaseType: '資料庫類型',
+ host: '主機',
+ databaseFilePath: '資料庫檔案路徑',
+ encryptionKey: '加密金鑰',
+ port: '連接埠',
+ database: '資料庫',
+ username: '使用者名稱',
+ password: '密碼',
+ ssl: '使用 SSL/TLS 加密',
+ sqliteMode: 'SQLite 模式',
+ recentDatabases: '最近的資料庫',
+ },
+ placeholders: {
+ connectionName: '我的資料庫',
+ selectType: '選擇資料庫類型',
+ host: 'localhost',
+ filePath: '/path/to/database.db',
+ duckdbFilePath: '/path/to/database.duckdb 或 :memory:',
+ encryptionKey: '輸入加密密碼短語',
+ database: 'database_name',
+ username: 'username',
+ password: '••••••••',
+ },
+ databaseTypes: {
+ 'postgresql': 'PostgreSQL',
+ 'sqlserver': 'SQL Server',
+ 'mysql': 'MySQL',
+ 'mariadb': 'MariaDB',
+ 'sqlite': 'SQLite',
+ 'sqlcipher': 'SQLCipher',
+ 'duckdb': 'DuckDB',
+ 'clickhouse': 'ClickHouse',
+ 'cockroachdb': 'CockroachDB',
+ 'redshift': 'Amazon Redshift',
+ 'yugabytedb': 'YugabyteDB',
+ 'timescaledb': 'TimescaleDB',
+ 'kingbasees': '人大金仓 (KingbaseES)',
+ 'gaussdb': '華為 GaussDB',
+ 'highgo': '瀚高資料庫 (HighGo DB)',
+ 'uxdb': '優炫資料庫 (UXDB)',
+ 'opengauss': 'openGauss',
+ 'gbase8c': '南大通用 GBase 8c',
+ 'questdb': 'QuestDB',
+ 'vastbase': 'Vastbase (海量資料庫)',
+ 'yashandb': 'YashanDB (崖山資料庫)',
+ 'tidb': 'TiDB',
+ 'oceanbase': 'OceanBase',
+ 'oceanbase-oracle': 'OceanBase Oracle',
+ 'tdsql': 'TDSQL',
+ 'polardb': 'PolarDB',
+ 'dameng': '達夢 Dameng',
+ 'doris': 'Apache Doris',
+ 'selectdb': 'SelectDB',
+ 'starrocks': 'StarRocks',
+ 'databend': 'Databend',
+ 'goldendb': 'GoldenDB',
+ 'manticore': 'Manticore Search',
+ 'oracle': 'Oracle',
+ 'db2': 'IBM Db2',
+ 'h2': 'H2',
+ 'snowflake': 'Snowflake',
+ 'xugudb': '虛谷資料庫 (XuguDB)',
+ 'gbase8a': '南大通用 GBase 8a',
+ 'trino': 'Trino',
+ 'presto': 'Presto',
+ 'derby': 'Apache Derby',
+ 'hive': 'Apache Hive',
+ 'databricks': 'Databricks SQL',
+ 'hana': 'SAP HANA',
+ 'teradata': 'Teradata',
+ 'vertica': 'Vertica',
+ 'exasol': 'Exasol',
+ 'bigquery': 'Google BigQuery',
+ 'informix': 'IBM Informix',
+ 'kylin': 'Apache Kylin',
+ 'cassandra': 'Apache Cassandra',
+ 'iris': 'InterSystems IRIS',
+ 'access': 'Microsoft Access',
+ 'firebird': 'Firebird',
+ 'rqlite': 'RQLite',
+ 'turso': 'Turso (libSQL)',
+ 'tdengine': 'TDengine',
+ },
+ oracle: {
+ connectionMethod: '連線方式',
+ methods: {
+ basic: '基本(主機:連接埠)',
+ tns: 'TNS (tnsnames.ora)',
+ cloudWallet: '雲端錢包 (ATP/ADW)',
+ },
+ identifyBy: '識別方式',
+ sid: 'SID',
+ serviceName: '服務名稱',
+ role: '角色',
+ roles: {
+ normal: 'NORMAL',
+ sysdba: 'SYSDBA',
+ sysoper: 'SYSOPER',
+ },
+ tnsAdminDir: 'TNS_ADMIN 目錄',
+ tnsAlias: 'TNS 別名',
+ walletDir: '錢包目錄',
+ walletPassword: '錢包密碼',
+ serviceLevel: '服務層級',
+ serviceLevels: {
+ low: '低(批次)',
+ medium: '中(標準)',
+ high: '高(關鍵)',
+ tp: 'TP(交易)',
+ tpurgent: 'TP_URGENT(優先)',
+ },
+ browse: '瀏覽...',
+ noAliases: '找不到 TNS 別名',
+ tnsSelectDir: '請選擇 TNS 目錄以載入別名',
+ walletSelectDir: '請選擇錢包目錄以載入別名',
+ loadingAliases: '正在載入別名...',
+ },
+ buttons: {
+ create: '新增...',
+ open: '開啟...',
+ },
+ fileStatus: {
+ willCreate: '檔案尚不存在 — 連線時 {engine} 會自動建立。',
+ missingParent: '上層資料夾尚不存在。',
+ createDirectory: '建立資料夾',
+ createDirectoryFailed: '建立資料夾失敗',
+ unwritable: '此路徑沒有寫入權限。',
+ directory: '此路徑是一個資料夾,請改為選擇資料庫檔案。',
+ empty: '檔案是空的(0 位元組)。',
+ ready: '檔案已存在({size})',
+ storageVersion: '儲存格式 {storage}(需 DuckDB {version} 或更新版本開啟)',
+ storageVersionUnknown: '儲存格式 {storage} — 比此版本已知的格式還新,可能是由較新的 DuckDB 寫入。',
+ writeAheadLog: '存在預寫日誌檔(.wal),連線時會自動重放。',
+ unsupportedPath: 'DuckDB 無法開啟包含 \';\' 的路徑。請重新命名檔案後再試。',
+ wrongFormat: '這看起來是 {format} 檔案,而非 {engine} 資料庫。',
+ unknownFormat: '其他格式',
+ reveal: '在資料夾中顯示',
+ revealFailed: '無法顯示檔案所在資料夾',
+ removeRecent: '從最近清單移除',
+ },
+ duckdb: {
+ accessMode: '存取模式',
+ readWrite: '讀寫',
+ readWriteHint: 'DuckDB 會對檔案持有獨佔鎖:同一時間只有一個處理程序可以寫入。',
+ readOnly: '唯讀',
+ readOnlyHint: '允許其他 DuckDB 處理程序同時讀取同一個檔案。',
+ conflictingConnection: '「{name}」已用不同的存取模式開啟此檔案,DuckDB 會拒絕設定不同的第二個連線。',
+ openReadOnly: '以唯讀開啟',
+ switchToConnection: '切換至該連線',
+ sharedConnection: '「{name}」使用相同的檔案與設定 — 兩個連線會共用同一個 DuckDB 執行個體。',
+ engineVersion: '引擎版本 {version}',
+ retryReadOnly: '以唯讀重試',
+ retryReadWrite: '以讀寫重試',
+ inMemoryHint: '記憶體內資料庫是暫時性的,連線關閉後就會遺失。適合在將資料存入檔案前先用於探索資料。',
+ inMemoryInstance: '執行個體',
+ inMemorySharedHint: '具名的記憶體內執行個體由所有共用的連線使用,因此在某次查詢中建立的資料表,在下一次查詢中仍可見。',
+ },
+ duckdbFailures: {
+ 'read-only-unsupported': '目前安裝的 JDBC 橋接尚無法以唯讀方式開啟資料庫(DuckDB 拒絕依連線變更模式)。請以讀寫模式重試,或在設定中更新橋接。',
+ 'storage-version': '此檔案是由比目前使用的引擎更新的 DuckDB 寫入,因此無法開啟。請用較新版本匯出(EXPORT DATABASE)後重新匯入,或更新 DuckDB 驅動程式。',
+ 'config-conflict': '另一個連線已用不同的設定(唯讀 vs 讀寫,或不同的初始化)開啟此檔案。DuckDB 會拒絕第二種設定。',
+ 'lock-conflict': '另一個處理程序持有此檔案的寫入鎖(duckdb CLI、Python 或另一個 SQLKit 連線)。請以唯讀開啟,或關閉其他程式。',
+ 'unsupported-url': '此路徑無法傳給 DuckDB 的 JDBC 驅動程式。請重新命名檔案後再試。',
+ 'extension': '無法載入或下載 DuckDB 擴充功能。請檢查網路連線,或預先安裝該擴充功能。',
+ 'read-only-file': '資料庫檔案或其資料夾是唯讀的,DuckDB 無法寫入。請變更檔案權限,或以唯讀方式開啟。',
+ 'missing-file': '資料庫檔案不存在且無法建立。請檢查路徑與資料夾權限。',
+ },
+ sqlite: {
+ modes: {
+ file: '檔案',
+ inMemory: '記憶體內',
+ },
+ recentEmpty: '沒有最近的資料庫',
+ ago: '{time} 前',
+ inMemoryHint: '記憶體內資料庫是暫時性的,連線關閉後就會遺失。適合用於測試與暫存資料。',
+ pathStatus: {
+ valid: '檔案存在',
+ notFound: '找不到檔案',
+ noPermission: '沒有寫入權限',
+ },
+ },
+ errors: {
+ nameRequired: '請輸入連線名稱',
+ hostRequired: '請輸入主機',
+ databaseRequired: '請輸入 SID / 服務名稱',
+ databaseNameRequired: '請輸入資料庫名稱',
+ filePathRequired: '請輸入資料庫檔案路徑',
+ portInvalid: '連接埠必須是正整數',
+ filePickerFailed: '無法開啟檔案選擇器',
+ tnsAdminDirRequired: '請輸入 TNS admin 目錄',
+ tnsAliasRequired: '請輸入 TNS 別名',
+ },
+ ssh: {
+ newProfile: '新增設定檔',
+ hopOrderHint: '跳板會依序嘗試 — 最後一跳轉送到資料庫。系統代理僅適用於第一跳。',
+ importFromConfig: '從 ~/.ssh/config 匯入',
+ profileName: '設定檔名稱',
+ profileNamePlaceholder: '例如:正式環境跳板主機',
+ editProfile: '編輯 SSH 設定檔',
+ useSshTunnel: 'SSH 通道',
+ ultimateOnly: 'SSH 通道為 Ultimate 功能',
+ tunnelSkippedHint: 'SSH 通道為 Ultimate 功能:Community 版或未登入的工作階段會略過此連線已儲存的通道,因此這次測試是對直接連線執行的。',
+ systemProxy: '系統代理',
+ systemProxyDetected: '偵測到系統代理:{url}',
+ systemProxyAdd: '新增',
+ systemProxyDetach: '移除系統代理',
+ systemProxyNotDetected: '已啟用系統代理,但未偵測到任何代理,將直接連線。',
+ detachAction: '從鏈路移除',
+ moveUp: '上移跳板',
+ moveDown: '下移跳板',
+ hops: '個跳板',
+ addProfilePlaceholder: '新增設定檔…',
+ searchProfilePlaceholder: '搜尋設定檔…',
+ testChain: '測試通道連通性',
+ testFirstHop: '測試第一跳(後續跳板不會被測試)',
+ testDisabledHint: '必填欄位缺少或設定無效',
+ testReturnedNotConnected: '連線回報未連線',
+ jreBroken: 'JRE 缺失或損毀',
+ stepFailed: '失敗',
+ testTimedOut: '測試逾時(30 秒)— 跳板主機可能無法連上,或 SSH 交握停滯',
+ testSuccess: '已連線到 {user}{\'@\'}{host}:{port}',
+ notConfigured: '尚未設定 SSH 通道 — 新增設定檔即可開始',
+ editTunnel: '編輯 SSH 通道',
+ connectionOnly: '變更僅套用於此連線。',
+ convertHint: '轉換為可重複使用的設定檔,即可新增跳板並調整順序。',
+ noConfigHosts: '~/.ssh/config 中找不到任何 SSH 主機。',
+ convertToProfile: '轉換為設定檔',
+ convertedProfileName: '手動設定({host})',
+ sshHost: 'SSH 主機',
+ sshPort: 'SSH 連接埠',
+ username: '使用者名稱',
+ authMethod: '驗證方式',
+ password: '密碼',
+ privateKey: '私密金鑰',
+ sshAgent: 'SSH Agent',
+ sshPassword: 'SSH 密碼',
+ privateKeyPath: '私密金鑰路徑',
+ passphraseOptional: '密碼短語(選填)',
+ agentSockPath: 'Agent Socket 路徑',
+ agentHelpText: '使用系統 SSH Agent,無需額外設定。',
+ },
+ },
+ serverCard: {
+ actions: {
+ connect: '連線',
+ openEditor: '在編輯器中開啟',
+ closeConnection: '關閉連線',
+ edit: '編輯',
+ duplicate: '複製',
+ delete: '刪除',
+ },
+ strategy: {
+ nativeTooltip: '透過原生 Rust 驅動程式直接連線 — 效能最佳,無外部相依性',
+ jdbcBridgeTooltip: '透過內嵌 Java 執行環境的 JDBC 驅動程式連線 — 資料庫相容性最廣',
+ httpBridgeTooltip: '透過 HTTP SQL 協定連線 — 適用於以 REST 為基礎的資料庫',
+ },
+ },
+ connectingModal: {
+ connecting: '正在連線到 {name}...',
+ connectingSubtext: '正在建立連線,請稍候',
+ connectionError: '連線錯誤',
+ sshTunnelSkipped: 'SSH 通道為 Ultimate 功能:Community 版或未登入的工作階段會略過此連線已儲存的通道並直接連線(設定本身會保留)。',
+ sshTunnelStripped: '此次連線已略過此連線儲存的通道(Ultimate 功能,而您目前使用 Community 版或未登入)。若此資料庫只能透過該通道連上,請升級至 Ultimate。',
+ },
+ databaseBrowser: {
+ title: '資料庫瀏覽器',
+ search: '搜尋資料表...',
+ refresh: '重新整理',
+ newQuery: '新增查詢',
+ loading: '載入中...',
+ empty: '找不到任何資料庫。請先連線到伺服器。',
+ selectDatabase: '選擇資料庫',
+ selectSchema: '選擇結構描述',
+ databases: '資料庫',
+ current: '目前',
+ userDatabases: '使用者資料庫',
+ systemDatabases: '系統資料庫',
+ noTables: '找不到任何資料表',
+ noViews: '找不到任何檢視',
+ noProcedures: '找不到任何預存程序',
+ noFunctions: '找不到任何函數',
+ noSavedQueries: '尚無已儲存的查詢',
+ comingSoon: '即將推出',
+ sections: {
+ tables: '資料表',
+ views: '檢視',
+ procedures: '預存程序',
+ functions: '函數',
+ savedQueries: '已儲存的查詢',
+ },
+ errors: {
+ fetchDatabases: '取得資料庫清單失敗',
+ fetchSchemas: '取得結構描述清單失敗',
+ fetchTables: '取得資料表清單失敗',
+ invalidResponse: '伺服器回應無效',
+ },
+ contextMenu: {
+ viewData: '檢視資料',
+ selectTopN: '選取前 100 筆',
+ viewStructure: '檢視結構',
+ createScript: 'CREATE 指令碼',
+ exportData: '匯出資料',
+ showErDiagram: '顯示 ER 圖',
+ dropTable: '刪除資料表',
+ truncateTable: '清空',
+ newQuery: '新增查詢',
+ refresh: '重新整理',
+ },
+ savedQueryActions: {
+ open: '開啟',
+ delete: '刪除',
+ reveal: '在 Finder 中顯示',
+ },
+ erDiagram: {
+ title: 'ER 圖',
+ viewMode: '檢視',
+ zoom: '{percentage}%',
+ zoomIn: '放大',
+ zoomOut: '縮小',
+ allSchemas: '所有結構描述',
+ engineeringView: '工程檢視',
+ fitToScreen: '符合螢幕大小',
+ searchPlaceholder: '篩選資料表...',
+ tablesCountBadge: '{count} 張資料表',
+ tableView: '資料表檢視',
+ relationshipsCountBadge: '{count} 個關聯',
+ resetLayout: '重設版面配置',
+ largeSchemaWarning: '此結構描述包含 {count} 張資料表,全部顯示可能會過於密集。要繼續嗎?',
+ showAllColumns: '顯示所有欄位({count})',
+ hideExtraColumns: '顯示更少',
+ noForeignKeys: '找不到外部索引鍵關聯',
+ openTable: '開啟資料表資料',
+ layoutDirection: '版面配置',
+ layoutTopBottom: '上 → 下',
+ layoutLeftRight: '左 → 右',
+ loading: '正在載入結構描述關聯...',
+ },
+ },
+ listingTab: {
+ views: '檢視',
+ procedures: '預存程序',
+ functions: '函數',
+ searchPlaceholder: '依名稱搜尋...',
+ name: '名稱',
+ detail: '詳細資訊',
+ ddl: 'DDL',
+ actions: '操作',
+ viewDdl: '檢視 DDL',
+ drop: '刪除',
+ rename: '重新命名',
+ copyName: '複製名稱',
+ copyDdl: '複製 DDL',
+ dropDialogTitle: '刪除物件',
+ dropDialogDescription: '確定要刪除 {name} 嗎?',
+ confirmDrop: '刪除',
+ renameDialogTitle: '重新命名物件',
+ renameDialogDescription: '輸入 {name} 的新名稱:',
+ newNamePlaceholder: '新名稱',
+ confirmRename: '重新命名',
+ noResults: '沒有符合搜尋條件的物件',
+ empty: '找不到任何物件',
+ },
+ schemaTab: {
+ column: '欄位',
+ type: '類型',
+ nullable: '允許 Null',
+ default: '預設值',
+ key: '索引鍵',
+ autoIncrement: '自動遞增',
+ yes: '是',
+ no: '否',
+ pk: '主鍵',
+ },
+ indexesTab: {
+ name: '名稱',
+ columns: '欄位',
+ type: '類型',
+ unique: '唯一',
+ primary: '主鍵',
+ empty: '找不到任何索引',
+ yes: '是',
+ no: '否',
+ },
+ foreignKeysTab: {
+ constraint: '條件約束',
+ columns: '欄位',
+ references: '參考',
+ onUpdate: 'ON UPDATE',
+ onDelete: 'ON DELETE',
+ empty: '找不到任何外部索引鍵',
+ },
+ triggersTab: {
+ name: '名稱',
+ timing: '時機',
+ event: '事件',
+ ddl: 'DDL',
+ viewDdl: '檢視 DDL',
+ empty: '找不到任何觸發程式',
+ },
+ queryResult: {
+ title: '結果',
+ selectResult: '選擇結果集',
+ resultSet: '結果 {index} / {count}',
+ exportActions: '複製與匯出結果',
+ scriptReadOnly: '指令碼結果為唯讀;排序僅套用於傳回的列。',
+ rows: '{count} 列',
+ rowsAffected: '已影響 {count} 列',
+ time: '{time}',
+ close: '關閉',
+ executing: '正在執行查詢...',
+ error: '查詢錯誤',
+ success: '查詢執行成功',
+ noData: '沒有傳回資料',
+ commandCompleted: '命令已完成',
+ noResults: '執行查詢以查看結果',
+ },
+ dataTableView: {
+ searchPlaceholder: '搜尋所有欄位...',
+ clearSearch: '清除搜尋',
+ filterPlaceholder: '篩選(SQL WHERE 子句,例如 age > 18 AND status = \'active\')',
+ clearFilter: '清除篩選',
+ refresh: '重新整理',
+ columns: '欄位',
+ exportCsv: '匯出目前頁面 (CSV)',
+ applyFilters: '套用篩選',
+ loading: '正在載入資料表資料...',
+ error: '載入資料表資料失敗',
+ connectionLost: '連線已中斷。資料庫連線已關閉。',
+ reconnecting: '正在重新連線...',
+ reconnect: '重新連線',
+ noRows: '找不到任何列',
+ rows: '列',
+ columnsCount: '{count} 個欄位',
+ indexesCount: '{count} 個索引',
+ foreignKeysCount: '{count} 個外部索引鍵',
+ triggersCount: '{count} 個觸發程式',
+ page: '第 {page} 頁,共 {total} 頁',
+ rowsPerPage: '每頁列數:',
+ actions: '操作',
+ editRow: '編輯列',
+ deleteRow: '刪除列',
+ notifications: {
+ csvExported: 'CSV 已匯出',
+ exportFailed: '匯出失敗',
+ rowDeleted: '列已刪除',
+ deleteFailed: '刪除列失敗',
+ rowUpdated: '列已更新',
+ updateFailed: '更新列失敗',
+ noPrimaryKey: '未偵測到主索引鍵',
+ noPrimaryKeyDesc: '此資料表沒有主索引鍵。將使用所有欄位來識別列。',
+ fallbackAllColumns: '沒有主索引鍵 — 將使用所有欄位識別列。編輯時請留意。',
+ },
+ deleteDialog: {
+ title: '刪除列',
+ message: '確定要刪除此列嗎?此操作無法復原。',
+ confirm: '刪除',
+ },
+ editDialog: {
+ title: '編輯列',
+ },
+ validation: {
+ required: '此欄位為必填',
+ invalidNumber: '請輸入有效的數字',
+ invalidBoolean: '請輸入 true 或 false',
+ },
+ },
+ queryTabs: {
+ unsaved: '有未儲存的變更',
+ orphan: '此分頁屬於另一個連線',
+ new: '新增查詢',
+ closeDialog: {
+ title: '未儲存的變更',
+ message: '查詢「{name}」有未儲存的變更,要捨棄嗎?',
+ discard: '捨棄',
+ },
+ },
+ header: {
+ appName: 'SQLKit',
+ },
+ sqlEditor: {
+ execute: '執行',
+ format: '格式化',
+ copy: '複製',
+ },
+ destructiveDialog: {
+ deleteRow: {
+ title: '確認刪除',
+ message: '要從資料表「{table}」刪除 {count} 列嗎?',
+ detail: '此操作無法復原。',
+ confirm: '刪除',
+ },
+ dropTable: {
+ title: '刪除資料表',
+ message: '要刪除資料表「{table}」嗎?',
+ detail: '這將永久刪除該資料表及其所有資料。此操作無法復原。',
+ confirm: '刪除',
+ },
+ truncateTable: {
+ title: '清空資料表',
+ message: '要清空資料表「{table}」嗎?',
+ detail: '這將移除全部 {count} 列。此操作無法復原。',
+ confirm: '清空',
+ },
+ deleteConnection: {
+ title: '刪除連線',
+ message: '要刪除連線「{name}」嗎?',
+ detail: '這將移除已儲存的連線設定。作用中的連線將會中斷。',
+ confirm: '刪除',
+ },
+ deleteProfile: {
+ title: '刪除 SSH 設定檔',
+ message: '要刪除設定檔「{name}」嗎?',
+ detail: '設定檔將從共用設定檔庫中移除,經由它跳轉的連線將失去此跳板。',
+ inUse: '此設定檔正被 {count} 個連線使用:{names}。這些連線將與此設定檔解除關聯。',
+ confirm: '刪除',
+ },
+ },
+ pagination: {
+ label: '分頁',
+ showingWithoutTotal: '顯示第 {start}–{end} 列 · 無法取得總列數',
+ rowsPerPage: '每頁列數',
+ pageSize: '{count} 列/頁',
+ customSize: '自訂每頁列數',
+ apply: '套用',
+ showAll: '顯示所有傳回的列',
+ allRows: '所有傳回的列',
+ firstPage: '第一頁',
+ previousPage: '上一頁',
+ nextPage: '下一頁',
+ lastPage: '最後一頁',
+ goToPage: '跳至頁面',
+ pageCount: '/ {count}',
+ sortScope: '排序僅套用於目前頁面',
+ },
+ dataGrid: {
+ sort: {
+ asc: '遞增排序',
+ desc: '遞減排序',
+ clear: '清除排序',
+ unsortable: '此欄位類型無法排序',
+ },
+ filter: {
+ byValue: '依值篩選',
+ byLike: '依 LIKE 篩選',
+ greaterThan: '篩選 >=',
+ lessThan: '篩選 <=',
+ between: '區間篩選',
+ excludeValue: '排除此值',
+ clearFilter: '清除篩選',
+ clearAll: '清除所有篩選',
+ activeFilters: '篩選條件',
+ },
+ row: {
+ edit: '編輯列',
+ delete: '刪除列',
+ duplicate: '複製列',
+ details: '列詳細資訊',
+ copyAsCsv: '複製列為 CSV',
+ copyAsJson: '複製列為 JSON',
+ copyAsInsert: '複製列為 INSERT',
+ actions: '操作',
+ noTableContext: '查詢結果未關聯至資料表,因此無法編輯或刪除列',
+ editUnsupported: {
+ 'not-select': '此陳述式不是 SELECT 查詢,因此無法編輯或刪除結果列',
+ 'cte': '查詢使用 WITH(CTE),列無法對應回資料表,因此不支援編輯',
+ 'set-operation': '查詢使用 UNION/INTERSECT/EXCEPT,列來自多個陳述式,因此不支援編輯',
+ 'aggregation': '查詢包含彙總(GROUP BY/DISTINCT/彙總函數),列無法對應回基底列,因此不支援編輯',
+ 'multiple-sources': '查詢聯結多張資料表,因此無法編輯或刪除列',
+ 'no-table': '查詢沒有 FROM 資料表,因此無法編輯或刪除列',
+ 'complex-source': '查詢來源是子查詢或複雜運算式,因此無法編輯或刪除列',
+ },
+ },
+ cell: {
+ copyValue: '複製儲存格值',
+ copyRow: '複製列',
+ filterByValue: '依此值篩選',
+ excludeValue: '排除此值',
+ },
+ selection: {
+ selected: '已選取 {count} 列',
+ editSelected: '編輯所選列',
+ deleteSelected: '刪除所選列',
+ exportSelected: '匯出所選列',
+ },
+ status: {
+ showing: '顯示第 {start}–{end} 列,共 {total} 列',
+ showingLimited: '顯示第 {start}–{end} 列,已載入 {loaded} 列(受限)',
+ time: '· {time}',
+ },
+ empty: '沒有結果',
+ error: {
+ title: '載入資料時發生錯誤',
+ retry: '重試',
+ },
+ loading: '正在載入資料...',
+ edit: {
+ title: '編輯列',
+ duplicateTitle: '複製列',
+ nullToggle: '設為 NULL',
+ pkReadonly: '主索引鍵(唯讀)',
+ save: '儲存',
+ cancel: '取消',
+ saving: '儲存中...',
+ confirmCancel: '捨棄變更?',
+ confirmCancelMessage: '您有未儲存的變更。確定要關閉嗎?',
+ discard: '捨棄',
+ validation: {
+ required: '此欄位為必填',
+ invalidNumber: '請輸入有效的數字',
+ invalidBoolean: '請輸入 true 或 false',
+ },
+ },
+ details: {
+ title: '列詳細資訊',
+ },
+ delete: {
+ title: '刪除列',
+ message: '確定要刪除此列嗎?',
+ detail: '此操作無法復原。',
+ confirm: '刪除',
+ batchTitle: '刪除所選列',
+ batchMessage: '確定要刪除所選的 {count} 列嗎?',
+ batchDetail: '此操作無法復原。',
+ },
+ export: {
+ copyAllCsv: '全部複製為 CSV',
+ copyAllJson: '全部複製為 JSON',
+ copyAllInsert: '全部複製為 INSERT',
+ exportCsv: '匯出 CSV',
+ exportJson: '匯出 JSON',
+ exportInsert: '匯出 INSERT',
+ copied: '已複製到剪貼簿',
+ exported: '檔案已匯出',
+ formatLabels: {
+ csv: 'CSV',
+ json: 'JSON',
+ insert: 'INSERT',
+ },
+ },
+ json: {
+ expand: '展開',
+ title: 'JSON 檢視器',
+ copy: '複製 JSON',
+ },
+ blob: {
+ label: '[BLOB {size}]',
+ },
+ null: '(NULL)',
+ rowNumber: '#',
+ },
+ },
+ updater: {
+ updateAvailable: '有可用更新',
+ newVersion: '版本 {version} 可用',
+ upToDate: '已是最新版本',
+ checkFailed: '檢查更新失敗',
+ downloading: '正在下載更新...',
+ installing: '正在安裝更新...',
+ installFailed: '安裝更新失敗',
+ skip: '略過此版本',
+ later: '稍後',
+ updateNow: '立即更新',
+ restarting: '正在重新啟動...',
+ downloadingPercent: '下載中 {percent}%',
+ relaunchFailed: '更新後重新啟動失敗',
+ retry: '重試',
+ installFailedHelp: '按 F12 開啟開發人員工具檢查錯誤詳細資訊。',
+ },
+ errors: {
+ unexpected: '發生未預期的錯誤:{error}',
+ codes: {
+ // Connection errors
+ CONNECTION_FAILED: '無法連線到資料庫',
+ CONNECTION_TIMEOUT: '連線逾時',
+ CONNECTION_REFUSED: '連線被拒絕',
+ AUTHENTICATION_FAILED: '驗證失敗',
+
+ // Query errors
+ QUERY_SYNTAX_ERROR: 'SQL 語法錯誤',
+ QUERY_EXECUTION_ERROR: '查詢執行失敗',
+ QUERY_TIMEOUT: '查詢執行逾時',
+
+ // Resource errors
+ DATABASE_NOT_FOUND: '找不到資料庫',
+ TABLE_NOT_FOUND: '資料表不存在',
+ COLUMN_NOT_FOUND: '欄位不存在',
+
+ // Permission errors
+ PERMISSION_DENIED: '權限被拒絕',
+ INSUFFICIENT_PRIVILEGES: '權限不足',
+
+ // Data errors
+ CONSTRAINT_VIOLATION: '條件約束違規',
+ FOREIGN_KEY_VIOLATION: '違反外部索引鍵條件約束',
+ UNIQUE_VIOLATION: '違反唯一條件約束',
+ NOT_NULL_VIOLATION: '違反 NOT NULL 條件約束',
+ CHECK_VIOLATION: '違反 CHECK 條件約束',
+
+ // System errors
+ INTERNAL_ERROR: '內部錯誤',
+ UNSUPPORTED_OPERATION: '不支援的操作',
+ INVALID_CONFIGURATION: '設定無效',
+ },
+ titles: {
+ CONNECTION_FAILED: '連線失敗',
+ AUTHENTICATION_FAILED: '驗證失敗',
+ QUERY_SYNTAX_ERROR: 'SQL 語法錯誤',
+ QUERY_EXECUTION_ERROR: '查詢執行錯誤',
+ TABLE_NOT_FOUND: '找不到資料表',
+ COLUMN_NOT_FOUND: '找不到欄位',
+ PERMISSION_DENIED: '權限被拒絕',
+ FOREIGN_KEY_VIOLATION: '違反外部索引鍵條件約束',
+ UNIQUE_VIOLATION: '違反唯一條件約束',
+ NOT_NULL_VIOLATION: '違反 NOT NULL 條件約束',
+ },
+ hints: {
+ CONNECTION_FAILED: '請檢查連線設定,並確認資料庫伺服器正在執行',
+ AUTHENTICATION_FAILED: '請確認您的使用者名稱與密碼',
+ QUERY_SYNTAX_ERROR: '請檢查 SQL 語法後再試一次',
+ QUERY_TIMEOUT: '請嘗試最佳化查詢,或提高逾時上限',
+ DATABASE_NOT_FOUND: '請確認資料庫存在且您有權存取',
+ TABLE_NOT_FOUND: '請檢查資料表名稱,並確認它存在於資料庫中',
+ COLUMN_NOT_FOUND: '請確認欄位名稱與資料表結構描述相符',
+ FOREIGN_KEY_VIOLATION: '請確認父資料表中存在被參考的記錄',
+ UNIQUE_VIOLATION: '具有此值的記錄已存在',
+ NOT_NULL_VIOLATION: '此欄位必須有值',
+ CHECK_VIOLATION: '該值不符合資料表的條件約束',
+ PERMISSION_DENIED: '您沒有足夠的權限執行此操作',
+ },
+ },
+ sidebar: {
+ connection: {
+ placeholder: '選擇連線',
+ connected: '已連線',
+ lost: '連線已中斷',
+ disconnected: '已中斷連線',
+ connecting: '連線中...',
+ },
+ database: {
+ placeholder: '所有資料庫',
+ selectDatabase: '選擇資料庫',
+ refresh: '重新整理',
+ refreshTooltip: '重新載入資料庫清單',
+ },
+ databases: {
+ actions: {
+ createObject: {
+ title: '建立{type}',
+ placeholder: '請輸入{type}名稱',
+ cancel: '取消',
+ confirm: '建立',
+ created: '{type}「{name}」建立成功',
+ error: '建立失敗:{error}',
+ types: {
+ database: '資料庫',
+ schema: '結構描述',
+ },
+ },
+ createDatabase: {
+ title: '建立資料庫',
+ name: '資料庫名稱',
+ namePlaceholder: '請輸入資料庫名稱',
+ charset: '字元集',
+ collation: '定序',
+ collationPlaceholder: '例如 utf8mb4_unicode_ci',
+ encoding: '編碼',
+ locale: '地區設定 / LC_COLLATE',
+ localePlaceholder: '例如 en_US.UTF-8',
+ optional: '選填',
+ cancel: '取消',
+ confirm: '建立',
+ },
+ dropDatabase: {
+ title: '刪除資料庫',
+ message: '確定要刪除「{name}」嗎?此操作無法復原。',
+ typeToConfirm: '請輸入資料庫名稱以確認:',
+ cancel: '取消',
+ confirm: '刪除',
+ success: '資料庫「{name}」已成功刪除',
+ error: '刪除資料庫失敗:{error}',
+ },
+ createTable: {
+ title: '建立資料表',
+ tableName: '資料表名稱',
+ tableNamePlaceholder: '請輸入資料表名稱',
+ engine: '引擎',
+ columns: '欄位',
+ addColumn: '新增欄位',
+ colName: '名稱',
+ colType: '類型',
+ colLength: '長度',
+ colAutoInc: '自動遞增',
+ colDefault: '預設值',
+ lengthPlaceholder: '255',
+ defaultPlaceholder: 'NULL',
+ preview: 'SQL 預覽',
+ cancel: '取消',
+ create: '建立',
+ opened: '資料表 SQL 已在編輯器中開啟,執行即可建立資料表。',
+ },
+ templateOpened: '新的{type}範本已在編輯器中開啟。',
+ },
+ },
+ actionMenu: {
+ label: '資料庫操作',
+ createScript: '建立指令碼',
+ newDatabase: '新增資料庫',
+ newSchema: '新增結構描述',
+ newTable: '新增資料表',
+ newView: '新增檢視',
+ newFunction: '新增函數',
+ newProcedure: '新增預存程序',
+ showErDiagram: 'ER 圖',
+ backupDatabase: '備份資料庫',
+ exportDatabase: '匯出資料庫',
+ dropDatabase: '刪除資料庫',
+ },
+ groups: {
+ tables: '資料表',
+ views: '檢視',
+ procedures: '預存程序',
+ functions: '函數',
+ },
+ loading: '載入中...',
+ empty: '尚未選擇資料庫。請選擇一個資料庫以瀏覽。',
+ noObjects: '找不到任何物件',
+ noDatabases: '找不到任何資料庫。請先連線到伺服器。',
+ search: '搜尋資料表、檢視...',
+ savedQueries: {
+ header: '已儲存的查詢',
+ expand: '展開已儲存的查詢',
+ collapse: '收起已儲存的查詢',
+ newQuery: '新增查詢',
+ empty: '尚無已儲存的查詢',
+ created: '建立時間',
+ modified: '修改時間',
+ connectionNone: '沒有目標連線',
+ actions: {
+ open: '開啟',
+ rename: '重新命名',
+ changeConnection: '變更目標連線',
+ reveal: '在檔案總管中顯示',
+ delete: '刪除',
+ },
+ delete: {
+ title: '刪除已儲存的查詢?',
+ description: '確定要刪除「{name}」嗎?此操作無法復原。',
+ cancel: '取消',
+ confirm: '刪除',
+ target: '目標',
+ created: '建立時間',
+ },
+ renameDialog: {
+ title: '重新命名已儲存的查詢',
+ label: '新名稱',
+ placeholder: '請輸入新檔名',
+ cancel: '取消',
+ confirm: '重新命名',
+ },
+ connectionDialog: {
+ title: '變更目標連線',
+ label: '選擇連線',
+ none: '沒有連線',
+ cancel: '取消',
+ confirm: '儲存',
+ },
+ },
+ notImplemented: '此功能尚未實作',
+ },
+}