From 24673069039eb55bc0174c95d0caaec28e902d24 Mon Sep 17 00:00:00 2001 From: xmk23333 Date: Sun, 28 Dec 2025 12:34:13 +0800 Subject: [PATCH] feat: remove hardcoded Chinese strings and improve i18n coverage --- src/main/config/profile.ts | 13 ++++++++++-- src/main/resolve/autoUpdater.ts | 3 ++- src/main/sys/misc.ts | 3 ++- src/renderer/src/components/base/toast.tsx | 9 +++++--- src/renderer/src/hooks/use-app-config.tsx | 4 +++- .../src/hooks/use-controled-mihomo-config.tsx | 4 +++- .../src/hooks/use-override-config.tsx | 10 +++++---- src/renderer/src/hooks/use-profile-config.tsx | 12 ++++++----- src/renderer/src/locales/en-US.json | 21 +++++++++++++++++++ src/renderer/src/locales/fa-IR.json | 21 +++++++++++++++++++ src/renderer/src/locales/ru-RU.json | 21 +++++++++++++++++++ src/renderer/src/locales/zh-CN.json | 21 +++++++++++++++++++ src/renderer/src/locales/zh-TW.json | 21 +++++++++++++++++++ src/renderer/src/pages/dns.tsx | 2 +- src/renderer/src/pages/sniffer.tsx | 2 +- src/renderer/src/pages/sysproxy.tsx | 2 +- src/renderer/src/pages/tun.tsx | 4 ++-- src/renderer/src/utils/error-display.ts | 7 +++++-- 18 files changed, 155 insertions(+), 25 deletions(-) diff --git a/src/main/config/profile.ts b/src/main/config/profile.ts index 20a14c2..1429c6e 100644 --- a/src/main/config/profile.ts +++ b/src/main/config/profile.ts @@ -13,6 +13,8 @@ import { join } from 'path' import { app } from 'electron' import { mihomoUpgradeConfig } from '../core/mihomoApi' +import i18next from 'i18next' + let profileConfig: IProfileConfig // profile.yaml // 最终选中订阅ID let targetProfileId: string | null = null @@ -33,7 +35,8 @@ export async function setProfileConfig(config: IProfileConfig): Promise { export async function getProfileItem(id: string | undefined): Promise { const { items } = await getProfileConfig() - if (!id || id === 'default') return { id: 'default', type: 'local', name: '空白订阅' } + if (!id || id === 'default') + return { id: 'default', type: 'local', name: i18next.t('profiles.emptyProfile') } return items.find((item) => item.id === id) } @@ -126,7 +129,13 @@ export async function removeProfileItem(id: string): Promise { export async function getCurrentProfileItem(): Promise { const { current } = await getProfileConfig() - return (await getProfileItem(current)) || { id: 'default', type: 'local', name: '空白订阅' } + return ( + (await getProfileItem(current)) || { + id: 'default', + type: 'local', + name: i18next.t('profiles.emptyProfile') + } + ) } interface FetchOptions { diff --git a/src/main/resolve/autoUpdater.ts b/src/main/resolve/autoUpdater.ts index 238435f..4eede61 100644 --- a/src/main/resolve/autoUpdater.ts +++ b/src/main/resolve/autoUpdater.ts @@ -11,6 +11,7 @@ import { exec, execSync, spawn } from 'child_process' import { promisify } from 'util' import { appLogger } from '../utils/logger' import { checkAdminPrivileges } from '../core/manager' +import i18next from 'i18next' export async function checkUpdate(): Promise { const { 'mixed-port': mixedPort = 7890 } = await getControledMihomoConfig() @@ -68,7 +69,7 @@ export async function downloadAndInstallUpdate(version: string): Promise { file = file.replace('-setup.exe', '-portable.7z') } if (!file) { - throw new Error('不支持自动更新,请手动下载更新') + throw new Error(i18next.t('common.error.autoUpdateNotSupported')) } if (process.platform === 'win32' && parseInt(os.release()) < 10) { file = file.replace('windows', 'win7') diff --git a/src/main/sys/misc.ts b/src/main/sys/misc.ts index 89796c3..586b381 100644 --- a/src/main/sys/misc.ts +++ b/src/main/sys/misc.ts @@ -11,10 +11,11 @@ import { profilePath, resourcesDir } from '../utils/dirs' +import i18next from 'i18next' export function getFilePath(ext: string[]): string[] | undefined { return dialog.showOpenDialogSync({ - title: '选择订阅文件', + title: i18next.t('common.dialog.selectSubscriptionFile'), filters: [{ name: `${ext} file`, extensions: ext }], properties: ['openFile'] }) diff --git a/src/renderer/src/components/base/toast.tsx b/src/renderer/src/components/base/toast.tsx index a07ace5..f83cc5f 100644 --- a/src/renderer/src/components/base/toast.tsx +++ b/src/renderer/src/components/base/toast.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useState, useCallback } from 'react' import { createPortal } from 'react-dom' import { IoCheckmark, IoClose, IoAlertSharp, IoInformationSharp, IoCopy } from 'react-icons/io5' +import i18next from 'i18next' type ToastType = 'success' | 'error' | 'warning' | 'info' @@ -125,7 +126,9 @@ const ToastItem: React.FC<{ > {icon} -

{data.title || '错误'}

+

+ {data.title || i18next.t('common.error.default')} +

@@ -158,7 +161,7 @@ const ToastItem: React.FC<{ onClick={handleClose} className="self-end px-4 py-1.5 text-sm font-medium text-white bg-danger rounded-lg hover:bg-danger/90 transition-colors" > - 确定 + {i18next.t('common.ok')} ) diff --git a/src/renderer/src/hooks/use-app-config.tsx b/src/renderer/src/hooks/use-app-config.tsx index bf415a0..274b0e1 100644 --- a/src/renderer/src/hooks/use-app-config.tsx +++ b/src/renderer/src/hooks/use-app-config.tsx @@ -1,4 +1,5 @@ import React, { createContext, useContext, ReactNode } from 'react' +import { useTranslation } from 'react-i18next' import { showError } from '@renderer/utils/error-display' import useSWR from 'swr' import { getAppConfig, patchAppConfig as patch } from '@renderer/utils/ipc' @@ -12,13 +13,14 @@ interface AppConfigContextType { const AppConfigContext = createContext(undefined) export const AppConfigProvider: React.FC<{ children: ReactNode }> = ({ children }) => { + const { t } = useTranslation() const { data: appConfig, mutate: mutateAppConfig } = useSWR('getConfig', () => getAppConfig()) const patchAppConfig = async (value: Partial): Promise => { try { await patch(value) } catch (e) { - await showError(e, '更新应用配置失败') + await showError(e, t('common.error.updateAppConfigFailed')) } finally { mutateAppConfig() } diff --git a/src/renderer/src/hooks/use-controled-mihomo-config.tsx b/src/renderer/src/hooks/use-controled-mihomo-config.tsx index a1b0a7a..abe7371 100644 --- a/src/renderer/src/hooks/use-controled-mihomo-config.tsx +++ b/src/renderer/src/hooks/use-controled-mihomo-config.tsx @@ -1,4 +1,5 @@ import React, { createContext, useContext, ReactNode } from 'react' +import { useTranslation } from 'react-i18next' import { showError } from '@renderer/utils/error-display' import useSWR from 'swr' import { getControledMihomoConfig, patchControledMihomoConfig as patch } from '@renderer/utils/ipc' @@ -14,6 +15,7 @@ const ControledMihomoConfigContext = createContext = ({ children }) => { + const { t } = useTranslation() const { data: controledMihomoConfig, mutate: mutateControledMihomoConfig } = useSWR( 'getControledMihomoConfig', () => getControledMihomoConfig() @@ -23,7 +25,7 @@ export const ControledMihomoConfigProvider: React.FC<{ children: ReactNode }> = try { await patch(value) } catch (e) { - await showError(e, '更新内核配置失败') + await showError(e, t('common.error.updateCoreConfigFailed')) } finally { mutateControledMihomoConfig() } diff --git a/src/renderer/src/hooks/use-override-config.tsx b/src/renderer/src/hooks/use-override-config.tsx index 4159370..448ef33 100644 --- a/src/renderer/src/hooks/use-override-config.tsx +++ b/src/renderer/src/hooks/use-override-config.tsx @@ -1,4 +1,5 @@ import React, { createContext, useContext, ReactNode } from 'react' +import { useTranslation } from 'react-i18next' import { showError } from '@renderer/utils/error-display' import useSWR from 'swr' import { @@ -21,6 +22,7 @@ interface OverrideConfigContextType { const OverrideConfigContext = createContext(undefined) export const OverrideConfigProvider: React.FC<{ children: ReactNode }> = ({ children }) => { + const { t } = useTranslation() const { data: overrideConfig, mutate: mutateOverrideConfig } = useSWR('getOverrideConfig', () => getOverrideConfig() ) @@ -29,7 +31,7 @@ export const OverrideConfigProvider: React.FC<{ children: ReactNode }> = ({ chil try { await set(config) } catch (e) { - await showError(e, '保存覆写配置失败') + await showError(e, t('common.error.saveOverrideConfigFailed')) } finally { mutateOverrideConfig() } @@ -39,7 +41,7 @@ export const OverrideConfigProvider: React.FC<{ children: ReactNode }> = ({ chil try { await add(item) } catch (e) { - await showError(e, '添加覆写失败') + await showError(e, t('common.error.addOverrideFailed')) } finally { mutateOverrideConfig() } @@ -49,7 +51,7 @@ export const OverrideConfigProvider: React.FC<{ children: ReactNode }> = ({ chil try { await remove(id) } catch (e) { - await showError(e, '删除覆写失败') + await showError(e, t('common.error.deleteOverrideFailed')) } finally { mutateOverrideConfig() } @@ -59,7 +61,7 @@ export const OverrideConfigProvider: React.FC<{ children: ReactNode }> = ({ chil try { await update(item) } catch (e) { - await showError(e, '更新覆写失败') + await showError(e, t('common.error.updateOverrideFailed')) } finally { mutateOverrideConfig() } diff --git a/src/renderer/src/hooks/use-profile-config.tsx b/src/renderer/src/hooks/use-profile-config.tsx index 355d695..434798c 100644 --- a/src/renderer/src/hooks/use-profile-config.tsx +++ b/src/renderer/src/hooks/use-profile-config.tsx @@ -1,4 +1,5 @@ import React, { createContext, ReactNode, useContext } from 'react' +import { useTranslation } from 'react-i18next' import { showError } from '@renderer/utils/error-display' import useSWR from 'swr' import { @@ -23,6 +24,7 @@ interface ProfileConfigContextType { const ProfileConfigContext = createContext(undefined) export const ProfileConfigProvider: React.FC<{ children: ReactNode }> = ({ children }) => { + const { t } = useTranslation() const { data: profileConfig, mutate: mutateProfileConfig } = useSWR('getProfileConfig', () => getProfileConfig() ) @@ -33,7 +35,7 @@ export const ProfileConfigProvider: React.FC<{ children: ReactNode }> = ({ child try { await set(config) } catch (e) { - await showError(e, '保存配置失败') + await showError(e, t('common.error.saveProfileConfigFailed')) } finally { mutateProfileConfig() window.electron.ipcRenderer.send('updateTrayMenu') @@ -44,7 +46,7 @@ export const ProfileConfigProvider: React.FC<{ children: ReactNode }> = ({ child try { await add(item) } catch (e) { - await showError(e, '添加配置失败') + await showError(e, t('common.error.addProfileFailed')) } finally { mutateProfileConfig() window.electron.ipcRenderer.send('updateTrayMenu') @@ -55,7 +57,7 @@ export const ProfileConfigProvider: React.FC<{ children: ReactNode }> = ({ child try { await remove(id) } catch (e) { - await showError(e, '删除配置失败') + await showError(e, t('common.error.deleteProfileFailed')) } finally { mutateProfileConfig() window.electron.ipcRenderer.send('updateTrayMenu') @@ -66,7 +68,7 @@ export const ProfileConfigProvider: React.FC<{ children: ReactNode }> = ({ child try { await update(item) } catch (e) { - await showError(e, '更新配置失败') + await showError(e, t('common.error.updateProfileFailed')) } finally { mutateProfileConfig() window.electron.ipcRenderer.send('updateTrayMenu') @@ -108,7 +110,7 @@ export const ProfileConfigProvider: React.FC<{ children: ReactNode }> = ({ child if (errorMsg.includes('reply was never sent')) { setTimeout(() => mutateProfileConfig(), 1000) } else { - await showError(errorMsg, '切换配置失败') + await showError(errorMsg, t('common.error.switchProfileFailed')) mutateProfileConfig() } } finally { diff --git a/src/renderer/src/locales/en-US.json b/src/renderer/src/locales/en-US.json index 22e127c..09203c5 100644 --- a/src/renderer/src/locales/en-US.json +++ b/src/renderer/src/locales/en-US.json @@ -39,6 +39,27 @@ "common.error.shortcutRegistrationFailedWithError": "Failed to register shortcut: {{error}}", "common.error.adminRequired": "Please run with administrator privileges for first launch", "common.error.initFailed": "Application initialization failed", + "common.error.default": "Error", + "common.error.updateAppConfigFailed": "Failed to update app config", + "common.error.updateCoreConfigFailed": "Failed to update core config", + "common.error.saveProfileConfigFailed": "Failed to save profile config", + "common.error.addProfileFailed": "Failed to add profile", + "common.error.deleteProfileFailed": "Failed to delete profile", + "common.error.updateProfileFailed": "Failed to update profile", + "common.error.switchProfileFailed": "Failed to switch profile", + "common.error.saveOverrideConfigFailed": "Failed to save override config", + "common.error.addOverrideFailed": "Failed to add override", + "common.error.deleteOverrideFailed": "Failed to delete override", + "common.error.updateOverrideFailed": "Failed to update override", + "common.error.firewallSetupFailed": "Failed to setup firewall", + "common.error.coreAuthFailed": "Failed to authorize core", + "common.error.sysproxySetupFailed": "Failed to setup system proxy", + "common.error.snifferConfigSaveFailed": "Failed to save sniffer config", + "common.error.dnsConfigSaveFailed": "Failed to save DNS config", + "common.copied": "Copied", + "common.ok": "OK", + "common.error.autoUpdateNotSupported": "Auto update not supported, please download manually", + "common.dialog.selectSubscriptionFile": "Select Subscription File", "core.highPrivilege.title": "High Privilege Core Detected", "core.highPrivilege.message": "A high-privilege core is detected. The application needs to restart in administrator mode to match permissions. Restart now?", "common.updater.versionReady": "v{{version}} Version Ready", diff --git a/src/renderer/src/locales/fa-IR.json b/src/renderer/src/locales/fa-IR.json index d0352c5..279754a 100644 --- a/src/renderer/src/locales/fa-IR.json +++ b/src/renderer/src/locales/fa-IR.json @@ -39,6 +39,27 @@ "common.error.shortcutRegistrationFailedWithError": "ثبت میانبر با خطا مواجه شد: {{error}}", "common.error.adminRequired": "لطفا برای اولین اجرا با دسترسی مدیر برنامه را اجرا کنید", "common.error.initFailed": "راه‌اندازی برنامه با خطا مواجه شد", + "common.error.default": "خطا", + "common.error.updateAppConfigFailed": "به‌روزرسانی تنظیمات برنامه با خطا مواجه شد", + "common.error.updateCoreConfigFailed": "به‌روزرسانی تنظیمات هسته با خطا مواجه شد", + "common.error.saveProfileConfigFailed": "ذخیره تنظیمات پروفایل با خطا مواجه شد", + "common.error.addProfileFailed": "افزودن پروفایل با خطا مواجه شد", + "common.error.deleteProfileFailed": "حذف پروفایل با خطا مواجه شد", + "common.error.updateProfileFailed": "به‌روزرسانی پروفایل با خطا مواجه شد", + "common.error.switchProfileFailed": "تغییر پروفایل با خطا مواجه شد", + "common.error.saveOverrideConfigFailed": "ذخیره تنظیمات بازنویسی با خطا مواجه شد", + "common.error.addOverrideFailed": "افزودن بازنویسی با خطا مواجه شد", + "common.error.deleteOverrideFailed": "حذف بازنویسی با خطا مواجه شد", + "common.error.updateOverrideFailed": "به‌روزرسانی بازنویسی با خطا مواجه شد", + "common.error.firewallSetupFailed": "تنظیم فایروال با خطا مواجه شد", + "common.error.coreAuthFailed": "احراز هویت هسته با خطا مواجه شد", + "common.error.sysproxySetupFailed": "تنظیم پروکسی سیستم با خطا مواجه شد", + "common.error.snifferConfigSaveFailed": "ذخیره تنظیمات اسنیفر با خطا مواجه شد", + "common.error.dnsConfigSaveFailed": "ذخیره تنظیمات DNS با خطا مواجه شد", + "common.copied": "کپی شد", + "common.ok": "تأیید", + "common.error.autoUpdateNotSupported": "به‌روزرسانی خودکار پشتیبانی نمی‌شود، لطفاً به صورت دستی دانلود کنید", + "common.dialog.selectSubscriptionFile": "انتخاب فایل اشتراک", "core.highPrivilege.title": "هسته با سطح دسترسی بالا شناسایی شد", "core.highPrivilege.message": "هسته‌ای با سطح دسترسی بالا شناسایی شد. برنامه باید در حالت مدیر سیستم برای تطابق سطح دسترسی‌ها دوباره راه‌اندازی شود. آیا می‌خواهید اکنون راه‌اندازی مجدد شود؟", "common.updater.versionReady": "نسخه v{{version}} آماده است", diff --git a/src/renderer/src/locales/ru-RU.json b/src/renderer/src/locales/ru-RU.json index 12fc2ff..059223f 100644 --- a/src/renderer/src/locales/ru-RU.json +++ b/src/renderer/src/locales/ru-RU.json @@ -39,6 +39,27 @@ "common.error.shortcutRegistrationFailedWithError": "Не удалось зарегистрировать сочетание клавиш: {{error}}", "common.error.adminRequired": "Для первого запуска требуются права администратора", "common.error.initFailed": "Не удалось инициализировать приложение", + "common.error.default": "Ошибка", + "common.error.updateAppConfigFailed": "Не удалось обновить конфигурацию приложения", + "common.error.updateCoreConfigFailed": "Не удалось обновить конфигурацию ядра", + "common.error.saveProfileConfigFailed": "Не удалось сохранить конфигурацию профиля", + "common.error.addProfileFailed": "Не удалось добавить профиль", + "common.error.deleteProfileFailed": "Не удалось удалить профиль", + "common.error.updateProfileFailed": "Не удалось обновить профиль", + "common.error.switchProfileFailed": "Не удалось переключить профиль", + "common.error.saveOverrideConfigFailed": "Не удалось сохранить конфигурацию переопределения", + "common.error.addOverrideFailed": "Не удалось добавить переопределение", + "common.error.deleteOverrideFailed": "Не удалось удалить переопределение", + "common.error.updateOverrideFailed": "Не удалось обновить переопределение", + "common.error.firewallSetupFailed": "Не удалось настроить брандмауэр", + "common.error.coreAuthFailed": "Не удалось авторизовать ядро", + "common.error.sysproxySetupFailed": "Не удалось настроить системный прокси", + "common.error.snifferConfigSaveFailed": "Не удалось сохранить конфигурацию сниффера", + "common.error.dnsConfigSaveFailed": "Не удалось сохранить конфигурацию DNS", + "common.copied": "Скопировано", + "common.ok": "ОК", + "common.error.autoUpdateNotSupported": "Автообновление не поддерживается, пожалуйста, скачайте вручную", + "common.dialog.selectSubscriptionFile": "Выберите файл подписки", "core.highPrivilege.title": "High Privilege Core Detected", "core.highPrivilege.message": "Обнаружено ядро с повышенными привилегиями. Приложение необходимо перезапустить в режиме администратора для согласования прав. Перезапустить сейчас?", "common.updater.versionReady": "Обнаружено ядро с повышенными привилегиями", diff --git a/src/renderer/src/locales/zh-CN.json b/src/renderer/src/locales/zh-CN.json index e7fe1be..acd2f45 100644 --- a/src/renderer/src/locales/zh-CN.json +++ b/src/renderer/src/locales/zh-CN.json @@ -39,6 +39,27 @@ "common.error.shortcutRegistrationFailedWithError": "快捷键注册失败:{{error}}", "common.error.adminRequired": "首次启动请以管理员权限运行", "common.error.initFailed": "应用初始化失败", + "common.error.default": "错误", + "common.error.updateAppConfigFailed": "更新应用配置失败", + "common.error.updateCoreConfigFailed": "更新内核配置失败", + "common.error.saveProfileConfigFailed": "保存配置失败", + "common.error.addProfileFailed": "添加配置失败", + "common.error.deleteProfileFailed": "删除配置失败", + "common.error.updateProfileFailed": "更新配置失败", + "common.error.switchProfileFailed": "切换配置失败", + "common.error.saveOverrideConfigFailed": "保存覆写配置失败", + "common.error.addOverrideFailed": "添加覆写失败", + "common.error.deleteOverrideFailed": "删除覆写失败", + "common.error.updateOverrideFailed": "更新覆写失败", + "common.error.firewallSetupFailed": "防火墙设置失败", + "common.error.coreAuthFailed": "内核授权失败", + "common.error.sysproxySetupFailed": "系统代理设置失败", + "common.error.snifferConfigSaveFailed": "嗅探配置保存失败", + "common.error.dnsConfigSaveFailed": "DNS 配置保存失败", + "common.copied": "已复制", + "common.ok": "确定", + "common.error.autoUpdateNotSupported": "不支持自动更新,请手动下载更新", + "common.dialog.selectSubscriptionFile": "选择订阅文件", "core.highPrivilege.title": "检测到高权限内核", "core.highPrivilege.message": "检测到运行中的高权限内核,需以管理员模式重启应用以匹配权限,确定重启?", "common.updater.versionReady": "v{{version}} 版本就绪", diff --git a/src/renderer/src/locales/zh-TW.json b/src/renderer/src/locales/zh-TW.json index e3a5939..1b722de 100644 --- a/src/renderer/src/locales/zh-TW.json +++ b/src/renderer/src/locales/zh-TW.json @@ -39,6 +39,27 @@ "common.error.shortcutRegistrationFailedWithError": "快捷鍵註冊失敗:{{error}}", "common.error.adminRequired": "首次啟動請以系統管理員身分執行", "common.error.initFailed": "應用初始化失敗", + "common.error.default": "錯誤", + "common.error.updateAppConfigFailed": "更新應用配置失敗", + "common.error.updateCoreConfigFailed": "更新內核配置失敗", + "common.error.saveProfileConfigFailed": "保存配置失敗", + "common.error.addProfileFailed": "添加配置失敗", + "common.error.deleteProfileFailed": "刪除配置失敗", + "common.error.updateProfileFailed": "更新配置失敗", + "common.error.switchProfileFailed": "切換配置失敗", + "common.error.saveOverrideConfigFailed": "保存覆寫配置失敗", + "common.error.addOverrideFailed": "添加覆寫失敗", + "common.error.deleteOverrideFailed": "刪除覆寫失敗", + "common.error.updateOverrideFailed": "更新覆寫失敗", + "common.error.firewallSetupFailed": "防火牆設置失敗", + "common.error.coreAuthFailed": "內核授權失敗", + "common.error.sysproxySetupFailed": "系統代理設置失敗", + "common.error.snifferConfigSaveFailed": "嗅探配置保存失敗", + "common.error.dnsConfigSaveFailed": "DNS 配置保存失敗", + "common.copied": "已複製", + "common.ok": "確定", + "common.error.autoUpdateNotSupported": "不支持自動更新,請手動下載更新", + "common.dialog.selectSubscriptionFile": "選擇訂閱文件", "core.highPrivilege.title": "檢測到高權限內核", "core.highPrivilege.message": "檢測到運行中的高權限內核,需以系統管理員模式重新啟動應用程式以匹配權限,確定重新啟動?", "common.updater.versionReady": "v{{version}} 版本就緒", diff --git a/src/renderer/src/pages/dns.tsx b/src/renderer/src/pages/dns.tsx index 0f6467b..a10b1aa 100644 --- a/src/renderer/src/pages/dns.tsx +++ b/src/renderer/src/pages/dns.tsx @@ -146,7 +146,7 @@ const DNS: React.FC = () => { await restartCore() } } catch (e) { - showErrorSync(e, 'DNS 配置保存失败') + showErrorSync(e, t('common.error.dnsConfigSaveFailed')) } } diff --git a/src/renderer/src/pages/sniffer.tsx b/src/renderer/src/pages/sniffer.tsx index 85ff475..3ac50ee 100644 --- a/src/renderer/src/pages/sniffer.tsx +++ b/src/renderer/src/pages/sniffer.tsx @@ -71,7 +71,7 @@ const Sniffer: React.FC = () => { await restartCore() } } catch (e) { - showErrorSync(e, '嵅探配置保存失败') + showErrorSync(e, t('common.error.snifferConfigSaveFailed')) } } diff --git a/src/renderer/src/pages/sysproxy.tsx b/src/renderer/src/pages/sysproxy.tsx index 49a0c26..9a30935 100644 --- a/src/renderer/src/pages/sysproxy.tsx +++ b/src/renderer/src/pages/sysproxy.tsx @@ -106,7 +106,7 @@ const Sysproxy: React.FC = () => { } catch (e) { setValues({ ...values, enable: previousState }) setChanged(true) - showErrorSync(e, '系统代理设置失败') + showErrorSync(e, t('common.error.sysproxySetupFailed')) await patchAppConfig({ sysProxy: { enable: false } }) } diff --git a/src/renderer/src/pages/tun.tsx b/src/renderer/src/pages/tun.tsx index 799225f..e626cc8 100644 --- a/src/renderer/src/pages/tun.tsx +++ b/src/renderer/src/pages/tun.tsx @@ -113,7 +113,7 @@ const Tun: React.FC = () => { new Notification(t('tun.notifications.firewallResetSuccess')) await restartCore() } catch (e) { - showErrorSync(e, '防火墙设置失败') + showErrorSync(e, t('common.error.firewallSetupFailed')) } finally { setLoading(false) } @@ -134,7 +134,7 @@ const Tun: React.FC = () => { new Notification(t('tun.notifications.coreAuthSuccess')) await restartCore() } catch (e) { - showErrorSync(e, '内核授权失败') + showErrorSync(e, t('common.error.coreAuthFailed')) } }} > diff --git a/src/renderer/src/utils/error-display.ts b/src/renderer/src/utils/error-display.ts index 82e7ce0..0367e08 100644 --- a/src/renderer/src/utils/error-display.ts +++ b/src/renderer/src/utils/error-display.ts @@ -1,4 +1,5 @@ import { toast } from '@renderer/components/base/toast' +import i18next from 'i18next' const DETAILED_ERROR_KEYWORDS = [ 'yaml', @@ -33,9 +34,10 @@ function shouldShowDetailedError(message: string): boolean { export async function showError(error: unknown, title?: string): Promise { const message = error instanceof Error ? error.message : String(error) + const defaultTitle = i18next.t('common.error.default') if (shouldShowDetailedError(message)) { - toast.detailedError(message, title || '错误') + toast.detailedError(message, title || defaultTitle) } else { toast.error(message, title) } @@ -43,9 +45,10 @@ export async function showError(error: unknown, title?: string): Promise { export function showErrorSync(error: unknown, title?: string): void { const message = error instanceof Error ? error.message : String(error) + const defaultTitle = i18next.t('common.error.default') if (shouldShowDetailedError(message)) { - toast.detailedError(message, title || '错误') + toast.detailedError(message, title || defaultTitle) } else { toast.error(message, title) }