From 3aed0653243c9afa044b0f63e16904c3f0f23b24 Mon Sep 17 00:00:00 2001 From: Slinetrac Date: Tue, 4 Nov 2025 19:53:49 +0800 Subject: [PATCH] refactor(i18n): unify two-name locale namespaces --- .../connection/connection-detail.tsx | 30 +- src/components/connection/connection-item.tsx | 4 +- .../connection/connection-table.tsx | 24 +- src/components/profile/editor-viewer.tsx | 6 +- src/components/profile/file-input.tsx | 2 +- .../profile/groups-editor-viewer.tsx | 72 ++-- src/components/profile/log-viewer.tsx | 2 +- src/components/profile/profile-item.tsx | 46 +-- src/components/profile/profile-more.tsx | 16 +- src/components/profile/profile-viewer.tsx | 30 +- .../profile/proxies-editor-viewer.tsx | 10 +- .../profile/rules-editor-viewer.tsx | 2 +- src/locales/ar.json | 326 +++++++++--------- src/locales/de.json | 326 +++++++++--------- src/locales/en.json | 326 +++++++++--------- src/locales/es.json | 326 +++++++++--------- src/locales/fa.json | 326 +++++++++--------- src/locales/id.json | 326 +++++++++--------- src/locales/jp.json | 326 +++++++++--------- src/locales/ko.json | 326 +++++++++--------- src/locales/ru.json | 326 +++++++++--------- src/locales/tr.json | 326 +++++++++--------- src/locales/tt.json | 326 +++++++++--------- src/locales/zh.json | 326 +++++++++--------- src/locales/zhtw.json | 326 +++++++++--------- src/pages/connections.tsx | 6 +- 26 files changed, 2194 insertions(+), 2294 deletions(-) diff --git a/src/components/connection/connection-detail.tsx b/src/components/connection/connection-detail.tsx index ed1d9df7..c39bb56d 100644 --- a/src/components/connection/connection-detail.tsx +++ b/src/components/connection/connection-detail.tsx @@ -68,50 +68,50 @@ const InnerConnectionDetail = ({ data, onClose }: InnerProps) => { : metadata.remoteDestination; const information = [ - { label: t("connection.fields.host"), value: host }, + { label: t("connections.fields.host"), value: host }, { - label: t("connection.fields.downloaded"), + label: t("connections.fields.downloaded"), value: parseTraffic(data.download).join(" "), }, { - label: t("connection.fields.uploaded"), + label: t("connections.fields.uploaded"), value: parseTraffic(data.upload).join(" "), }, { - label: t("connection.fields.dlSpeed"), + label: t("connections.fields.dlSpeed"), value: parseTraffic(data.curDownload ?? -1).join(" ") + "/s", }, { - label: t("connection.fields.ulSpeed"), + label: t("connections.fields.ulSpeed"), value: parseTraffic(data.curUpload ?? -1).join(" ") + "/s", }, { - label: t("connection.fields.chains"), + label: t("connections.fields.chains"), value: chains, }, - { label: t("connection.fields.rule"), value: rule }, + { label: t("connections.fields.rule"), value: rule }, { - label: t("connection.fields.process"), + label: t("connections.fields.process"), value: `${metadata.process}${metadata.processPath ? `(${metadata.processPath})` : ""}`, }, { - label: t("connection.fields.time"), + label: t("connections.fields.time"), value: dayjs(data.start).fromNow(), }, { - label: t("connection.fields.source"), + label: t("connections.fields.source"), value: `${metadata.sourceIP}:${metadata.sourcePort}`, }, { - label: t("connection.fields.destination"), + label: t("connections.fields.destination"), value: Destination, }, { - label: t("connection.fields.destinationPort"), + label: t("connections.fields.destinationPort"), value: `${metadata.destinationPort}`, }, { - label: t("connection.fields.type"), + label: t("connections.fields.type"), value: `${metadata.type}(${metadata.network})`, }, ]; @@ -137,13 +137,13 @@ const InnerConnectionDetail = ({ data, onClose }: InnerProps) => { diff --git a/src/components/connection/connection-item.tsx b/src/components/connection/connection-item.tsx index d217e3e5..9c5cf737 100644 --- a/src/components/connection/connection-item.tsx +++ b/src/components/connection/connection-item.tsx @@ -48,8 +48,8 @@ export const ConnectionItem = (props: Props) => { edge="end" color="inherit" onClick={onDelete} - title={t("connection.actions.closeConnection")} - aria-label={t("connection.actions.closeConnection")} + title={t("connections.actions.closeConnection")} + aria-label={t("connections.actions.closeConnection")} > diff --git a/src/components/connection/connection-table.tsx b/src/components/connection/connection-table.tsx index 2c4e5475..c7c4d436 100644 --- a/src/components/connection/connection-table.tsx +++ b/src/components/connection/connection-table.tsx @@ -162,13 +162,13 @@ export const ConnectionTable = (props: Props) => { return [ { field: "host", - headerName: t("connection.fields.host"), + headerName: t("connections.fields.host"), width: columnWidths["host"] || 220, minWidth: 180, }, { field: "download", - headerName: t("connection.fields.downloaded"), + headerName: t("connections.fields.downloaded"), width: columnWidths["download"] || 88, align: "right", headerAlign: "right", @@ -176,7 +176,7 @@ export const ConnectionTable = (props: Props) => { }, { field: "upload", - headerName: t("connection.fields.uploaded"), + headerName: t("connections.fields.uploaded"), width: columnWidths["upload"] || 88, align: "right", headerAlign: "right", @@ -184,7 +184,7 @@ export const ConnectionTable = (props: Props) => { }, { field: "dlSpeed", - headerName: t("connection.fields.dlSpeed"), + headerName: t("connections.fields.dlSpeed"), width: columnWidths["dlSpeed"] || 88, align: "right", headerAlign: "right", @@ -192,7 +192,7 @@ export const ConnectionTable = (props: Props) => { }, { field: "ulSpeed", - headerName: t("connection.fields.ulSpeed"), + headerName: t("connections.fields.ulSpeed"), width: columnWidths["ulSpeed"] || 88, align: "right", headerAlign: "right", @@ -200,25 +200,25 @@ export const ConnectionTable = (props: Props) => { }, { field: "chains", - headerName: t("connection.fields.chains"), + headerName: t("connections.fields.chains"), width: columnWidths["chains"] || 340, minWidth: 180, }, { field: "rule", - headerName: t("connection.fields.rule"), + headerName: t("connections.fields.rule"), width: columnWidths["rule"] || 280, minWidth: 180, }, { field: "process", - headerName: t("connection.fields.process"), + headerName: t("connections.fields.process"), width: columnWidths["process"] || 220, minWidth: 180, }, { field: "time", - headerName: t("connection.fields.time"), + headerName: t("connections.fields.time"), width: columnWidths["time"] || 120, minWidth: 100, align: "right", @@ -229,19 +229,19 @@ export const ConnectionTable = (props: Props) => { }, { field: "source", - headerName: t("connection.fields.source"), + headerName: t("connections.fields.source"), width: columnWidths["source"] || 200, minWidth: 130, }, { field: "remoteDestination", - headerName: t("connection.fields.destination"), + headerName: t("connections.fields.destination"), width: columnWidths["remoteDestination"] || 200, minWidth: 130, }, { field: "type", - headerName: t("connection.fields.type"), + headerName: t("connections.fields.type"), width: columnWidths["type"] || 160, minWidth: 100, }, diff --git a/src/components/profile/editor-viewer.tsx b/src/components/profile/editor-viewer.tsx index c47556d1..f3c4c897 100644 --- a/src/components/profile/editor-viewer.tsx +++ b/src/components/profile/editor-viewer.tsx @@ -97,7 +97,7 @@ export const EditorViewer = (props: Props) => { onClose, } = props; - const resolvedTitle = title ?? t("profile.menu.editFile"); + const resolvedTitle = title ?? t("profiles.menu.editFile"); const resolvedInitialData = useMemo( () => initialData ?? Promise.resolve(""), [initialData], @@ -203,7 +203,7 @@ export const EditorViewer = (props: Props) => { mouseWheelZoom: true, // 按住Ctrl滚轮调节缩放比例 readOnly: readOnly, // 只读模式 readOnlyMessage: { - value: t("profile.editor.readOnlyMessage"), + value: t("profiles.editor.readOnlyMessage"), }, // 只读模式尝试编辑时的提示信息 renderValidationDecorations: "on", // 只读模式下显示校验信息 quickSuggestions: { @@ -233,7 +233,7 @@ export const EditorViewer = (props: Props) => { size="medium" color="inherit" sx={{ display: readOnly ? "none" : "" }} - title={t("profile.editor.format")} + title={t("profiles.editor.format")} onClick={() => editorRef.current ?.getAction("editor.action.formatDocument") diff --git a/src/components/profile/file-input.tsx b/src/components/profile/file-input.tsx index 3b858697..2b6de501 100644 --- a/src/components/profile/file-input.tsx +++ b/src/components/profile/file-input.tsx @@ -42,7 +42,7 @@ export const FileInput = (props: Props) => { sx={{ flex: "none" }} onClick={() => inputRef.current?.click()} > - {t("profile.fileInput.chooseFile")} + {t("profiles.fileInput.chooseFile")} = { - select: "proxy.strategies.select", - "url-test": "proxy.strategies.url-test", - fallback: "proxy.strategies.fallback", - "load-balance": "proxy.strategies.load-balance", - relay: "proxy.strategies.relay", + select: "proxies.strategies.select", + "url-test": "proxies.strategies.url-test", + fallback: "proxies.strategies.fallback", + "load-balance": "proxies.strategies.load-balance", + relay: "proxies.strategies.relay", }; const PROXY_POLICY_LABEL_KEYS: Record = builtinProxyPolicies.reduce( (acc, policy) => { - acc[policy] = `proxy.policies.${policy}`; + acc[policy] = `proxies.policies.${policy}`; return acc; }, {} as Record, @@ -400,7 +400,7 @@ export const GroupsEditorViewer = (props: Props) => { const validateGroup = () => { const group = formIns.getValues(); if (group.name === "") { - throw new Error(t("profile.groupsEditor.errors.nameRequired")); + throw new Error(t("profiles.groupsEditor.errors.nameRequired")); } }; @@ -415,7 +415,7 @@ export const GroupsEditorViewer = (props: Props) => { } await saveProfileFile(property, nextData); - showNotice.success("profile.notifications.saved"); + showNotice.success("profiles.notifications.saved"); setPrevData(nextData); onSave?.(prevData, nextData); onClose(); @@ -429,7 +429,7 @@ export const GroupsEditorViewer = (props: Props) => { { - {t("profile.groupsEditor.title")} + {t("profiles.groupsEditor.title")} @@ -937,7 +941,7 @@ export const GroupsEditorViewer = (props: Props) => { for (const item of [...appendSeq, ...groupList]) { if (item.name === formIns.getValues().name) { throw new Error( - t("profile.groupsEditor.errors.nameExists"), + t("profiles.groupsEditor.errors.nameExists"), ); } } @@ -947,7 +951,7 @@ export const GroupsEditorViewer = (props: Props) => { } }} > - {t("profile.groupsEditor.actions.append")} + {t("profiles.groupsEditor.actions.append")} diff --git a/src/components/profile/log-viewer.tsx b/src/components/profile/log-viewer.tsx index 44838884..de31d4cd 100644 --- a/src/components/profile/log-viewer.tsx +++ b/src/components/profile/log-viewer.tsx @@ -26,7 +26,7 @@ export const LogViewer = (props: Props) => { return ( - {t("profile.logViewer.title")} + {t("profiles.logViewer.title")} { // 如果已经过期,显示"更新失败" if (nextUpdateDate.isBefore(now)) { - setNextUpdateTime(t("profile.item.status.lastUpdateFailed")); + setNextUpdateTime(t("profiles.item.status.lastUpdateFailed")); } else { // 否则显示剩余时间 const diffMinutes = nextUpdateDate.diff(now, "minute"); if (diffMinutes < 60) { if (diffMinutes <= 0) { - setNextUpdateTime(`${t("profile.item.status.nextUp")} <1m`); + setNextUpdateTime(`${t("profiles.item.status.nextUp")} <1m`); } else { setNextUpdateTime( - `${t("profile.item.status.nextUp")} ${diffMinutes}m`, + `${t("profiles.item.status.nextUp")} ${diffMinutes}m`, ); } } else { const hours = Math.floor(diffMinutes / 60); const mins = diffMinutes % 60; setNextUpdateTime( - `${t("profile.item.status.nextUp")} ${hours}h ${mins}m`, + `${t("profiles.item.status.nextUp")} ${hours}h ${mins}m`, ); } } } else { console.log(`返回的下次更新时间为空`); - setNextUpdateTime(t("profile.item.status.noSchedule")); + setNextUpdateTime(t("profiles.item.status.noSchedule")); } } catch (err) { console.error(`获取下次更新时间出错:`, err); - setNextUpdateTime(t("profile.item.status.unknown")); + setNextUpdateTime(t("profiles.item.status.unknown")); } } else { console.log(`该配置未设置更新间隔或间隔为0`); - setNextUpdateTime(t("profile.item.status.autoUpdateDisabled")); + setNextUpdateTime(t("profiles.item.status.autoUpdateDisabled")); } }); @@ -365,18 +365,18 @@ export const ProfileItem = (props: Props) => { }; const menuLabels = { - home: "profile.menu.home", - select: "profile.menu.select", - editInfo: "profile.menu.editInfo", - editFile: "profile.menu.editFile", - editRules: "profile.menu.editRules", - editProxies: "profile.menu.editProxies", - editGroups: "profile.menu.editGroups", - extendConfig: "profile.menu.extendConfig", - extendScript: "profile.menu.extendScript", - openFile: "profile.menu.openFile", - update: "profile.menu.update", - updateViaProxy: "profile.menu.updateViaProxy", + home: "profiles.menu.home", + select: "profiles.menu.select", + editInfo: "profiles.menu.editInfo", + editFile: "profiles.menu.editFile", + editRules: "profiles.menu.editRules", + editProxies: "profiles.menu.editProxies", + editGroups: "profiles.menu.editGroups", + extendConfig: "profiles.menu.extendConfig", + extendScript: "profiles.menu.extendScript", + openFile: "profiles.menu.openFile", + update: "profiles.menu.update", + updateViaProxy: "profiles.menu.updateViaProxy", delete: "common.actions.delete", } as const; @@ -733,8 +733,8 @@ export const ProfileItem = (props: Props) => { textAlign="right" title={ showNextUpdate - ? t("profile.item.tooltips.showLast") - : `${t("common.labels.updateTime")}: ${parseExpire(updated)}\n${t("profile.item.tooltips.showNext")}` + ? t("profiles.item.tooltips.showLast") + : `${t("common.labels.updateTime")}: ${parseExpire(updated)}\n${t("profiles.item.tooltips.showNext")}` } sx={{ cursor: "pointer", @@ -891,8 +891,8 @@ export const ProfileItem = (props: Props) => { )} setConfirmOpen(false)} onConfirm={() => { diff --git a/src/components/profile/profile-more.tsx b/src/components/profile/profile-more.tsx index 90e752c2..97c57308 100644 --- a/src/components/profile/profile-more.tsx +++ b/src/components/profile/profile-more.tsx @@ -55,18 +55,18 @@ export const ProfileMore = (props: Props) => { const hasError = entries.some(([level]) => level === "exception"); const globalTitles: Record = { - Merge: "profile.more.global.merge", - Script: "profile.more.global.script", + Merge: "profiles.more.global.merge", + Script: "profiles.more.global.script", }; const chipLabels: Record = { - Merge: "profile.more.chips.merge", - Script: "profile.more.chips.script", + Merge: "profiles.more.chips.merge", + Script: "profiles.more.chips.script", }; const itemMenu = [ - { label: "profile.menu.editFile", handler: onEditFile }, - { label: "profile.menu.openFile", handler: onOpenFile }, + { label: "profiles.menu.editFile", handler: onEditFile }, + { label: "profiles.menu.openFile", handler: onOpenFile }, ]; const boxStyle = { @@ -121,7 +121,7 @@ export const ProfileMore = (props: Props) => { size="small" edge="start" color="error" - title={t("profile.logViewer.title")} + title={t("profiles.logViewer.title")} onClick={() => setLogOpen(true)} > @@ -132,7 +132,7 @@ export const ProfileMore = (props: Props) => { size="small" edge="start" color="inherit" - title={t("profile.logViewer.title")} + title={t("profiles.logViewer.title")} onClick={() => setLogOpen(true)} > diff --git a/src/components/profile/profile-viewer.tsx b/src/components/profile/profile-viewer.tsx index 590ba81a..88bfd640 100644 --- a/src/components/profile/profile-viewer.tsx +++ b/src/components/profile/profile-viewer.tsx @@ -144,7 +144,7 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { } } catch { // 首次创建/更新失败,尝试使用自身代理 - showNotice.info("profile.viewer.notifications.creationRetry"); + showNotice.info("profiles.viewer.notifications.creationRetry"); // 使用自身代理的配置 const retryItem = { @@ -167,7 +167,7 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { await patchProfile(form.uid, { option: originalOptions }); } - showNotice.success("profile.viewer.notifications.creationSuccess"); + showNotice.success("profiles.viewer.notifications.creationSuccess"); } } @@ -216,8 +216,8 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { open={open} title={ openType === "new" - ? t("profile.viewer.title.create") - : t("profile.viewer.title.edit") + ? t("profiles.viewer.title.create") + : t("profiles.viewer.title.edit") } contentSx={{ width: 375, pb: 0, maxHeight: "80%" }} okBtn={t("common.actions.save")} @@ -232,11 +232,11 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { control={control} render={({ field }) => ( - {t("profile.viewer.fields.type")} + {t("profiles.viewer.fields.type")}