fix(i18n): translate backend error messages in connection failure toasts

This commit is contained in:
t8y2 2026-05-14 11:00:52 +08:00
parent 43bd3a9ef8
commit e61efdea12
8 changed files with 67 additions and 10 deletions

View File

@ -30,6 +30,7 @@ import { useNavigationTargets } from "@/composables/useNavigationTargets";
import { useDataGridActions } from "@/composables/useDataGridActions";
import { useTauriEvents } from "@/composables/useTauriEvents";
import "@/i18n";
import { translateBackendError } from "@/i18n/backend-errors";
import * as api from "@/lib/api";
import { resolveDefaultDatabase } from "@/lib/defaultDatabase";
import { resolveExecutableSql } from "@/lib/sqlExecutionTarget";
@ -288,7 +289,7 @@ async function newQuery() {
const options = await getDatabaseOptions(connId);
queryStore.updateDatabase(tabId, resolveDefaultDatabase(conn, options));
} catch (e: any) {
toast(t("connection.connectFailed", { message: e?.message || String(e) }), 5000);
toast(t("connection.connectFailed", { message: translateBackendError(t, e?.message || String(e)) }), 5000);
}
}
@ -302,7 +303,7 @@ async function openConnectionQuery(connectionId: string) {
const options = await getDatabaseOptions(connectionId);
queryStore.updateDatabase(tabId, resolveDefaultDatabase(connection, options));
} catch (e: any) {
toast(t("connection.connectFailed", { message: e?.message || String(e) }), 5000);
toast(t("connection.connectFailed", { message: translateBackendError(t, e?.message || String(e)) }), 5000);
}
}
@ -339,7 +340,7 @@ async function changeActiveConnection(connectionId: string) {
const options = await getDatabaseOptions(connectionId);
queryStore.updateDatabase(tab.id, resolveDefaultDatabase(connection, options));
} catch (e: any) {
toast(t("connection.connectFailed", { message: e?.message || String(e) }), 5000);
toast(t("connection.connectFailed", { message: translateBackendError(t, e?.message || String(e)) }), 5000);
}
}
@ -747,7 +748,9 @@ onUnmounted(() => {
@danger-confirm="onDangerConfirm"
@connect-started="(name: string) => toast(t('connection.connecting', { name }), 30000)"
@connect-succeeded="(name: string) => toast(t('connection.connectSuccess', { name }), 2000)"
@connect-failed="(msg: string) => toast(t('connection.connectFailed', { message: msg }), 5000)"
@connect-failed="
(msg: string) => toast(t('connection.connectFailed', { message: translateBackendError(t, msg) }), 5000)
"
@structure-editor-saved="onStructureEditorSaved(onReloadData, toast)"
@open-lineage-target="openLineageTarget"
@open-database-search-target="openDatabaseSearchTarget"

View File

@ -2,6 +2,7 @@
import { computed, nextTick, onMounted, ref } from "vue";
import { uuid } from "@/lib/utils";
import { useI18n } from "vue-i18n";
import { translateBackendError } from "@/i18n/backend-errors";
import {
ArrowUp,
ArrowRightLeft,
@ -152,7 +153,7 @@ async function changeConnection(connectionId: string) {
queryStore.updateDatabase(tab.id, database);
}
} catch (e: any) {
toast(t("connection.connectFailed", { message: e?.message || String(e) }), 5000);
toast(t("connection.connectFailed", { message: translateBackendError(t, e?.message || String(e)) }), 5000);
}
}

View File

@ -1,6 +1,7 @@
<script setup lang="ts">
import { ref } from "vue";
import { useI18n } from "vue-i18n";
import { translateBackendError } from "@/i18n/backend-errors";
import { Upload, Download, RefreshCw } from "lucide-vue-next";
import { Button } from "@/components/ui/button";
import { Tooltip, TooltipTrigger, TooltipContent } from "@/components/ui/tooltip";
@ -34,7 +35,7 @@ async function refreshTree() {
try {
await connectionStore.refreshAllTree();
} catch (e: any) {
toast(t("connection.connectFailed", { message: e?.message || String(e) }), 5000);
toast(t("connection.connectFailed", { message: translateBackendError(t, e?.message || String(e)) }), 5000);
}
}

View File

@ -1,6 +1,7 @@
<script setup lang="ts">
import { ref, computed, watch } from "vue";
import { useI18n } from "vue-i18n";
import { translateBackendError } from "@/i18n/backend-errors";
import {
Database,
Table,
@ -304,7 +305,7 @@ async function toggle() {
}
} catch (e: any) {
if (!wasExpanded) node.isExpanded = false;
toast(t("connection.connectFailed", { message: e?.message || String(e) }), 5000);
toast(t("connection.connectFailed", { message: translateBackendError(t, e?.message || String(e)) }), 5000);
}
}
@ -358,7 +359,7 @@ async function openObjectBrowser() {
await toggle();
}
} catch (e: any) {
toast(t("connection.connectFailed", { message: e?.message || String(e) }), 5000);
toast(t("connection.connectFailed", { message: translateBackendError(t, e?.message || String(e)) }), 5000);
}
}
@ -460,7 +461,7 @@ async function newQuery() {
const options = await getDatabaseOptions(node.connectionId);
queryStore.createTab(node.connectionId, resolveDefaultDatabase(connection, options), undefined, "query");
} catch (e: any) {
toast(t("connection.connectFailed", { message: e?.message || String(e) }), 5000);
toast(t("connection.connectFailed", { message: translateBackendError(t, e?.message || String(e)) }), 5000);
}
}
@ -488,7 +489,7 @@ async function refresh() {
try {
await connectionStore.refreshTreeNode(props.node);
} catch (e: any) {
toast(t("connection.connectFailed", { message: e?.message || String(e) }), 5000);
toast(t("connection.connectFailed", { message: translateBackendError(t, e?.message || String(e)) }), 5000);
}
}

View File

@ -0,0 +1,34 @@
import type { ComposerTranslation } from "vue-i18n";
const patterns: [RegExp, string][] = [
[/^(.+?) driver is not installed\. Please install it from the Driver Manager\.$/, "connection.driverNotInstalled"],
[/^JRE (.+?) runtime is not installed\. Please install it from the Driver Manager\.$/, "connection.jreNotInstalled"],
[
/^System Java runtime was not found on PATH\. Please install Java or choose a custom Java executable\.$/,
"connection.systemJavaNotFound",
],
[/^Custom Java runtime path is empty\. Please choose a Java executable\.$/, "connection.customJavaPathEmpty"],
[
/^JDBC plugin is not installed\. Install the optional JDBC plugin to use this connection\.$/,
"connection.jdbcPluginNotInstalled",
],
];
const paramNames: Record<string, string> = {
"connection.driverNotInstalled": "driver",
"connection.jreNotInstalled": "jre",
};
export function translateBackendError(t: ComposerTranslation, message: string): string {
for (const [regex, key] of patterns) {
const match = message.match(regex);
if (match) {
const name = paramNames[key];
if (name && match[1]) {
return t(key, { [name]: match[1] });
}
return t(key);
}
}
return message;
}

View File

@ -131,6 +131,12 @@ export default {
connecting: "Connecting to {name}...",
connectSuccess: "Connected to {name}",
connectFailed: "Connection failed: {message}",
driverNotInstalled: "{driver} driver is not installed. Please install it from the Driver Manager.",
jreNotInstalled: "JRE {jre} runtime is not installed. Please install it from the Driver Manager.",
systemJavaNotFound:
"System Java runtime was not found on PATH. Please install Java or choose a custom Java executable.",
customJavaPathEmpty: "Custom Java runtime path is empty. Please choose a Java executable.",
jdbcPluginNotInstalled: "JDBC plugin is not installed. Install the optional JDBC plugin to use this connection.",
lastError: "Connection error",
clearError: "Clear connection error",
saveFailed: "Failed to save connection: {message}",

View File

@ -131,6 +131,12 @@ export default {
connecting: "Conectando a {name}...",
connectSuccess: "Conectado a {name}",
connectFailed: "Error de conexión: {message}",
driverNotInstalled: "El controlador {driver} no está instalado. Instálelo desde el Administrador de controladores.",
jreNotInstalled: "El entorno JRE {jre} no está instalado. Instálelo desde el Administrador de controladores.",
systemJavaNotFound: "No se encontró Java en el PATH del sistema. Instale Java o elija un ejecutable personalizado.",
customJavaPathEmpty: "La ruta de Java personalizada está vacía. Elija un ejecutable de Java.",
jdbcPluginNotInstalled:
"El plugin JDBC no está instalado. Instale el plugin JDBC opcional para usar esta conexión.",
lastError: "Error de conexión",
clearError: "Limpiar error de conexión",
saveFailed: "Error al guardar la conexión: {message}",

View File

@ -130,6 +130,11 @@ export default {
connecting: "正在连接 {name}...",
connectSuccess: "已连接 {name}",
connectFailed: "连接失败:{message}",
driverNotInstalled: "{driver} 驱动未安装,请在驱动管理器中安装。",
jreNotInstalled: "JRE {jre} 运行环境未安装,请在驱动管理器中安装。",
systemJavaNotFound: "未在 PATH 中找到系统 Java 运行环境,请安装 Java 或选择自定义 Java 可执行文件。",
customJavaPathEmpty: "自定义 Java 运行环境路径为空,请选择 Java 可执行文件。",
jdbcPluginNotInstalled: "JDBC 插件未安装,请先安装 JDBC 插件再使用此连接。",
lastError: "连接错误",
clearError: "清除连接错误",
saveFailed: "保存连接失败:{message}",