diff --git a/src/main/core/manager.ts b/src/main/core/manager.ts index fb3db585..267005b3 100644 --- a/src/main/core/manager.ts +++ b/src/main/core/manager.ts @@ -38,13 +38,14 @@ import os from 'os' import { createWriteStream, existsSync } from 'fs' import { uploadRuntimeConfig } from '../resolve/gistApi' import { startMonitor } from '../resolve/trafficMonitor' +import i18next from '../../shared/i18n' chokidar.watch(path.join(mihomoCoreDir(), 'meta-update'), {}).on('unlinkDir', async () => { try { await stopCore(true) await startCore() } catch (e) { - dialog.showErrorBox('内核启动出错', `${e}`) + dialog.showErrorBox(i18next.t('mihomo.error.coreStartFailed'), `${e}`) } }) @@ -130,7 +131,7 @@ export async function startCore(detached = false): Promise[]> { patchControledMihomoConfig({ tun: { enable: false } }) mainWindow?.webContents.send('controledMihomoConfigUpdated') ipcMain.emit('updateTrayMenu') - reject('虚拟网卡启动失败, 请尝试手动授予内核权限') + reject(i18next.t('tun.error.tunPermissionDenied')) } if ( @@ -189,7 +190,7 @@ export async function restartCore(): Promise { try { await startCore() } catch (e) { - dialog.showErrorBox('内核启动出错', `${e}`) + dialog.showErrorBox(i18next.t('mihomo.error.coreStartFailed'), `${e}`) } } @@ -200,7 +201,7 @@ export async function keepCoreAlive(): Promise { await writeFile(path.join(dataDir(), 'core.pid'), child.pid.toString()) } } catch (e) { - dialog.showErrorBox('内核启动出错', `${e}`) + dialog.showErrorBox(i18next.t('mihomo.error.coreStartFailed'), `${e}`) } } @@ -230,7 +231,7 @@ async function checkProfile(): Promise { .split('\n') .filter((line) => line.includes('level=error')) .map((line) => line.split('level=error')[1]) - throw new Error(`Profile Check Failed:\n${errorLines.join('\n')}`) + throw new Error(`${i18next.t('mihomo.error.profileCheckFailed')}:\n${errorLines.join('\n')}`) } else { throw error } diff --git a/src/main/index.ts b/src/main/index.ts index 48662161..59455ea2 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -50,8 +50,8 @@ if (process.platform === 'win32' && !is.dev && !process.argv.includes('noadmin') // ignore } dialog.showErrorBox( - i18next.t('main.error.adminRequired'), - `${i18next.t('main.error.adminRequired')}\n${createErrorStr}\n${eStr}` + i18next.t('common.error.adminRequired'), + `${i18next.t('common.error.adminRequired')}\n${createErrorStr}\n${eStr}` ) } finally { app.exit() @@ -123,12 +123,13 @@ powerMonitor.on('shutdown', async () => { app.whenReady().then(async () => { // Set app user model id for windows electronApp.setAppUserModelId('party.mihomo.app') + try { const appConfig = await getAppConfig() await initI18n({ lng: appConfig.language }) await initPromise } catch (e) { - dialog.showErrorBox(i18next.t('main.error.initFailed'), `${e}`) + dialog.showErrorBox(i18next.t('common.error.initFailed'), `${e}`) app.quit() } try { @@ -137,7 +138,7 @@ app.whenReady().then(async () => { await initProfileUpdater() }) } catch (e) { - dialog.showErrorBox(i18next.t('main.error.coreStartFailed'), `${e}`) + dialog.showErrorBox(i18next.t('mihomo.error.coreStartFailed'), `${e}`) } try { await startMonitor() @@ -178,7 +179,7 @@ async function handleDeepLink(url: string): Promise { const profileUrl = urlObj.searchParams.get('url') const profileName = urlObj.searchParams.get('name') if (!profileUrl) { - throw new Error(i18next.t('main.error.urlParamMissing')) + throw new Error(i18next.t('profiles.error.urlParamMissing')) } await addProfileItem({ type: 'remote', @@ -186,10 +187,10 @@ async function handleDeepLink(url: string): Promise { url: profileUrl }) mainWindow?.webContents.send('profileConfigUpdated') - new Notification({ title: i18next.t('main.notification.importSuccess') }).show() + new Notification({ title: i18next.t('profiles.notification.importSuccess') }).show() break } catch (e) { - dialog.showErrorBox(i18next.t('main.error.importFailed'), `${url}\n${e}`) + dialog.showErrorBox(i18next.t('profiles.error.importFailed'), `${url}\n${e}`) } } } diff --git a/src/main/resolve/shortcut.ts b/src/main/resolve/shortcut.ts index 489ab60c..334f27b7 100644 --- a/src/main/resolve/shortcut.ts +++ b/src/main/resolve/shortcut.ts @@ -10,6 +10,7 @@ import { triggerSysProxy } from '../sys/sysproxy' import { patchMihomoConfig } from '../core/mihomoApi' import { quitWithoutCore, restartCore } from '../core/manager' import { floatingWindow, triggerFloatingWindow } from './floatingWindow' +import i18next from '../../shared/i18n' export async function registerShortcut( oldShortcut: string, @@ -42,7 +43,7 @@ export async function registerShortcut( await triggerSysProxy(!enable) await patchAppConfig({ sysProxy: { enable: !enable } }) new Notification({ - title: `系统代理已${!enable ? '开启' : '关闭'}` + title: i18next.t(!enable ? 'common.notification.systemProxyEnabled' : 'common.notification.systemProxyDisabled') }).show() mainWindow?.webContents.send('appConfigUpdated') floatingWindow?.webContents.send('appConfigUpdated') @@ -65,7 +66,7 @@ export async function registerShortcut( } await restartCore() new Notification({ - title: `虚拟网卡已${!enable ? '开启' : '关闭'}` + title: i18next.t(!enable ? 'common.notification.tunEnabled' : 'common.notification.tunDisabled') }).show() mainWindow?.webContents.send('controledMihomoConfigUpdated') floatingWindow?.webContents.send('appConfigUpdated') @@ -81,7 +82,7 @@ export async function registerShortcut( await patchControledMihomoConfig({ mode: 'rule' }) await patchMihomoConfig({ mode: 'rule' }) new Notification({ - title: '已切换至规则模式' + title: i18next.t('common.notification.ruleMode') }).show() mainWindow?.webContents.send('controledMihomoConfigUpdated') ipcMain.emit('updateTrayMenu') @@ -92,7 +93,7 @@ export async function registerShortcut( await patchControledMihomoConfig({ mode: 'global' }) await patchMihomoConfig({ mode: 'global' }) new Notification({ - title: '已切换至全局模式' + title: i18next.t('common.notification.globalMode') }).show() mainWindow?.webContents.send('controledMihomoConfigUpdated') ipcMain.emit('updateTrayMenu') @@ -103,7 +104,7 @@ export async function registerShortcut( await patchControledMihomoConfig({ mode: 'direct' }) await patchMihomoConfig({ mode: 'direct' }) new Notification({ - title: '已切换至直连模式' + title: i18next.t('common.notification.directMode') }).show() mainWindow?.webContents.send('controledMihomoConfigUpdated') ipcMain.emit('updateTrayMenu') diff --git a/src/renderer/src/components/settings/webdav-config.tsx b/src/renderer/src/components/settings/webdav-config.tsx index 54660638..4480be49 100644 --- a/src/renderer/src/components/settings/webdav-config.tsx +++ b/src/renderer/src/components/settings/webdav-config.tsx @@ -109,7 +109,7 @@ const WebdavConfig: React.FC = () => { className="ml-1" onPress={handleRestore} > - {t('webdav.restore')} + {t('webdav.restore.title')} diff --git a/src/renderer/src/locales/en-US.json b/src/renderer/src/locales/en-US.json index b5504959..fb08f86e 100644 --- a/src/renderer/src/locales/en-US.json +++ b/src/renderer/src/locales/en-US.json @@ -31,7 +31,9 @@ "restoreFailed": "Failed to restore: {{error}}", "deleteFailed": "Failed to delete: {{error}}", "shortcutRegistrationFailed": "Failed to register shortcut", - "shortcutRegistrationFailedWithError": "Failed to register shortcut: {{error}}" + "shortcutRegistrationFailedWithError": "Failed to register shortcut: {{error}}", + "adminRequired": "Please run with administrator privileges for first launch", + "initFailed": "Application initialization failed" }, "updater": { "versionReady": "v{{version}} Version Ready", @@ -129,8 +131,8 @@ "coreUpgradeSuccess": "Core upgrade successful. If you want to use virtual network card (Tun), please go to the virtual network card page to manually authorize the Core again", "alreadyLatestVersion": "Already Latest Version", "selectCoreVersion": "Select Core Version", - "stableVersion": "Stable Version", - "alphaVersion": "Alpha Version", + "stableVersion": "Stable", + "alphaVersion": "Alpha", "mixedPort": "Mixed Port", "confirm": "Confirm", "socksPort": "Socks Port", @@ -152,7 +154,10 @@ "logLevel": "Log Level", "selectLogLevel": "Select Log Level", "silent": "Silent", - "error": "Error", + "error": { + "coreStartFailed": "Core start failed", + "profileCheckFailed": "Profile Check Failed" + }, "warning": "Warning", "info": "Info", "debug": "Debug", @@ -310,6 +315,7 @@ } }, "proxies": { + "title": "Proxy Groups & Nodes", "card": { "title": "ProxyGrp" }, @@ -418,6 +424,9 @@ "notifications": { "coreAuthSuccess": "Core Authorization Successful", "firewallResetSuccess": "Firewall Reset Successful" + }, + "error": { + "tunPermissionDenied": "TUN interface start failed, please try to manually grant core permissions" } }, "dns": { @@ -471,7 +480,9 @@ "visit": "Visit Sub-Store" }, "error": { - "unsupportedFileType": "Unsupported file type" + "unsupportedFileType": "Unsupported file type", + "urlParamMissing": "Missing parameter: url", + "importFailed": "Subscription import failed" }, "emptyProfile": "Empty Profile", "viewRuntimeConfig": "View Current Runtime Config", @@ -506,6 +517,9 @@ "expired": "Expired", "remainingDays": "{{days}} days", "lastUpdate": "Last updated: {{time}}" + }, + "notification": { + "importSuccess": "Subscription imported successfully" } }, "outbound": { @@ -575,10 +589,10 @@ "filter": "Filter", "orderBy": "Order By", "time": "Time", - "uploadAmount": "Upload Amount", - "downloadAmount": "Download Amount", - "uploadSpeed": "Upload Speed", - "downloadSpeed": "Download Speed", + "uploadAmount": "Up Amount", + "downloadAmount": "Down Amount", + "uploadSpeed": "Up Speed", + "downloadSpeed": "Down Speed", "detail": { "title": "Connection Details", "establishTime": "Establish Time", @@ -708,17 +722,5 @@ "title": "Tutorial Complete", "description": "Now that you understand the basic usage of the software, import your subscription and start using it. Enjoy!\nYou can also join our official Telegram group for the latest news." } - }, - "main": { - "error": { - "adminRequired": "Please run with administrator privileges for first launch", - "initFailed": "Application initialization failed", - "coreStartFailed": "Core startup error", - "importFailed": "Subscription import failed", - "urlParamMissing": "Missing parameter: url" - }, - "notification": { - "importSuccess": "Subscription imported successfully" - } } } \ No newline at end of file diff --git a/src/renderer/src/locales/zh-CN.json b/src/renderer/src/locales/zh-CN.json index e27ef766..72c58f44 100644 --- a/src/renderer/src/locales/zh-CN.json +++ b/src/renderer/src/locales/zh-CN.json @@ -31,7 +31,9 @@ "restoreFailed": "恢复失败:{{error}}", "deleteFailed": "删除失败:{{error}}", "shortcutRegistrationFailed": "快捷键注册失败", - "shortcutRegistrationFailedWithError": "快捷键注册失败:{{error}}" + "shortcutRegistrationFailedWithError": "快捷键注册失败:{{error}}", + "adminRequired": "首次启动请以管理员权限运行", + "initFailed": "应用初始化失败" }, "updater": { "versionReady": "v{{version}} 版本就绪", @@ -152,7 +154,10 @@ "logLevel": "日志等级", "selectLogLevel": "选择日志等级", "silent": "静默", - "error": "错误", + "error": { + "coreStartFailed": "内核启动出错", + "profileCheckFailed": "配置检查失败" + }, "warning": "警告", "info": "信息", "debug": "调试", @@ -310,6 +315,7 @@ } }, "proxies": { + "title": "代理组与节点", "card": { "title": "代理组" }, @@ -418,6 +424,9 @@ "notifications": { "coreAuthSuccess": "内核授权成功", "firewallResetSuccess": "防火墙重设成功" + }, + "error": { + "tunPermissionDenied": "虚拟网卡启动失败,请尝试手动授予内核权限" } }, "dns": { @@ -471,7 +480,9 @@ "visit": "访问 Sub-Store" }, "error": { - "unsupportedFileType": "不支持的文件类型" + "unsupportedFileType": "不支持的文件类型", + "urlParamMissing": "缺少参数 url", + "importFailed": "订阅导入失败" }, "emptyProfile": "空白订阅", "viewRuntimeConfig": "查看当前运行时配置", @@ -506,7 +517,10 @@ "feature": "功能" }, "openFile": "打开文件", - "home": "主页" + "home": "主页", + "notification": { + "importSuccess": "订阅导入成功" + } }, "outbound": { "title": "出站模式", @@ -708,17 +722,5 @@ "title": "教程结束", "description": "现在您已经了解了软件的基本用法,导入您的订阅开始使用吧,祝您使用愉快!\n您还可以加入我们的官方 Telegram 群组 获取最新资讯" } - }, - "main": { - "error": { - "adminRequired": "首次启动请以管理员权限运行", - "initFailed": "应用初始化失败", - "coreStartFailed": "内核启动出错", - "importFailed": "订阅导入失败", - "urlParamMissing": "缺少参数 url" - }, - "notification": { - "importSuccess": "订阅导入成功" - } } } \ No newline at end of file diff --git a/src/renderer/src/pages/connections.tsx b/src/renderer/src/pages/connections.tsx index cd358b9b..a6d9338f 100644 --- a/src/renderer/src/pages/connections.tsx +++ b/src/renderer/src/pages/connections.tsx @@ -233,7 +233,7 @@ const Connections: React.FC = () => {