refactor(i18n/proxies): migrate proxies UI to structured locale keys

This commit is contained in:
Slinetrac
2025-10-31 18:11:27 +08:00
Unverified
parent 04ff3dc460
commit 15e73c603b
20 changed files with 725 additions and 42 deletions

View File

@@ -150,7 +150,7 @@ export const ProviderButton = () => {
onClick={() => setOpen(true)}
sx={{ mr: 1 }}
>
{t("Proxy Provider")}
{t("pages.proxies.provider.title")}
</Button>
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth>
@@ -160,7 +160,9 @@ export const ProviderButton = () => {
justifyContent="space-between"
alignItems="center"
>
<Typography variant="h6">{t("Proxy Provider")}</Typography>
<Typography variant="h6">
{t("pages.proxies.provider.title")}
</Typography>
<Box>
<Button
variant="contained"

View File

@@ -299,7 +299,7 @@ export const ProxyChain = ({
// onUpdateChain([]);
} catch (error) {
console.error("Failed to disconnect from proxy chain:", error);
alert(t("Failed to disconnect from proxy chain") || "断开链式代理失败");
alert(t("pages.proxies.chain.disconnectFailed") || "断开链式代理失败");
} finally {
setIsConnecting(false);
}
@@ -307,9 +307,7 @@ export const ProxyChain = ({
}
if (proxyChain.length < 2) {
alert(
t("Chain proxy requires at least 2 nodes") || "链式代理至少需要2个节点",
);
alert(t("pages.proxies.chain.minimumNodes") || "链式代理至少需要2个节点");
return;
}
@@ -341,7 +339,7 @@ export const ProxyChain = ({
console.log("Successfully connected to proxy chain");
} catch (error) {
console.error("Failed to connect to proxy chain:", error);
alert(t("Failed to connect to proxy chain") || "连接链式代理失败");
alert(t("pages.proxies.chain.connectFailed") || "连接链式代理失败");
} finally {
setIsConnecting(false);
}
@@ -471,7 +469,7 @@ export const ProxyChain = ({
mb: 2,
}}
>
<Typography variant="h6">{t("Chain Proxy Config")}</Typography>
<Typography variant="h6">{t("pages.proxies.chain.header")}</Typography>
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
{proxyChain.length > 0 && (
<IconButton
@@ -486,7 +484,9 @@ export const ProxyChain = ({
backgroundColor: theme.palette.error.light + "20",
},
}}
title={t("Delete Chain Config") || "删除链式配置"}
title={
t("pages.proxies.actions.clearChainConfig") || "删除链式配置"
}
>
<DeleteIcon fontSize="small" />
</IconButton>
@@ -507,16 +507,16 @@ export const ProxyChain = ({
}}
title={
proxyChain.length < 2
? t("Chain proxy requires at least 2 nodes") ||
? t("pages.proxies.chain.minimumNodes") ||
"链式代理至少需要2个节点"
: undefined
}
>
{isConnecting
? t("Connecting...") || "连接中..."
? t("pages.proxies.actions.connecting") || "连接中..."
: isConnected
? t("Disconnect") || "断开"
: t("Connect") || "连接"}
? t("pages.proxies.actions.disconnect") || "断开"
: t("pages.proxies.actions.connect") || "连接"}
</Button>
</Box>
</Box>
@@ -526,10 +526,9 @@ export const ProxyChain = ({
sx={{ mb: 2 }}
>
{proxyChain.length === 1
? t(
"Chain proxy requires at least 2 nodes. Please add one more node.",
) || "链式代理至少需要2个节点请再添加一个节点。"
: t("Click nodes in order to add to proxy chain") ||
? t("pages.proxies.chain.minimumNodesHint") ||
"链式代理至少需要2个节点请再添加一个节点。"
: t("pages.proxies.chain.instruction") ||
"按顺序点击节点添加到代理链中"}
</Alert>
@@ -544,7 +543,7 @@ export const ProxyChain = ({
color: theme.palette.text.secondary,
}}
>
<Typography>{t("No proxy chain configured")}</Typography>
<Typography>{t("pages.proxies.chain.empty")}</Typography>
</Box>
) : (
<DndContext

View File

@@ -239,7 +239,7 @@ export const ProxyGroups = (props: Props) => {
setProxyChain((prev) => {
// 检查是否已经存在相同名称的代理,防止重复添加
if (prev.some((item) => item.name === proxy.name)) {
const warningMessage = t("Proxy node already exists in chain");
const warningMessage = t("pages.proxies.chain.duplicateNode");
setDuplicateWarning({
open: true,
message: warningMessage,
@@ -403,7 +403,7 @@ export const ProxyGroups = (props: Props) => {
variant="h6"
sx={{ fontWeight: 600, fontSize: "16px" }}
>
{t("Proxy Rules")}
{t("pages.proxies.rules.title")}
</Typography>
{currentGroup && (
<Box
@@ -442,7 +442,7 @@ export const ProxyGroups = (props: Props) => {
variant="body2"
sx={{ mr: 0.5, fontSize: "12px" }}
>
{t("Select Rules")}
{t("pages.proxies.rules.select")}
</Typography>
<ExpandMoreRounded fontSize="small" />
</IconButton>

View File

@@ -67,7 +67,7 @@ export const ProxyHead = ({
<IconButton
size="small"
color="inherit"
title={t("locate")}
title={t("pages.proxies.tooltips.locate")}
onClick={onLocation}
>
<MyLocationRounded />
@@ -76,7 +76,7 @@ export const ProxyHead = ({
<IconButton
size="small"
color="inherit"
title={t("Delay check")}
title={t("pages.proxies.tooltips.delayCheck")}
onClick={() => {
console.log(`[ProxyHead] 点击延迟测试按钮,组: ${groupName}`);
// Remind the user that it is custom test url
@@ -94,9 +94,11 @@ export const ProxyHead = ({
size="small"
color="inherit"
title={
[t("Sort by default"), t("Sort by delay"), t("Sort by name")][
sortType
]
[
t("pages.proxies.tooltips.sortDefault"),
t("pages.proxies.tooltips.sortDelay"),
t("pages.proxies.tooltips.sortName"),
][sortType]
}
onClick={() =>
onHeadState({ sortType: ((sortType + 1) % 3) as ProxySortType })
@@ -110,7 +112,7 @@ export const ProxyHead = ({
<IconButton
size="small"
color="inherit"
title={t("Delay check URL")}
title={t("pages.proxies.tooltips.delayCheckUrl")}
onClick={() =>
onHeadState({ textState: textState === "url" ? null : "url" })
}
@@ -125,7 +127,11 @@ export const ProxyHead = ({
<IconButton
size="small"
color="inherit"
title={showType ? t("Proxy basic") : t("Proxy detail")}
title={
showType
? t("pages.proxies.tooltips.showBasic")
: t("pages.proxies.tooltips.showDetail")
}
onClick={() => onHeadState({ showType: !showType })}
>
{showType ? <VisibilityRounded /> : <VisibilityOffRounded />}
@@ -134,7 +140,7 @@ export const ProxyHead = ({
<IconButton
size="small"
color="inherit"
title={t("Filter")}
title={t("pages.proxies.tooltips.filter")}
onClick={() =>
onHeadState({ textState: textState === "filter" ? null : "filter" })
}
@@ -154,7 +160,7 @@ export const ProxyHead = ({
value={filterText}
size="small"
variant="outlined"
placeholder={t("Filter conditions")}
placeholder={t("pages.proxies.placeholders.filter")}
onChange={(e) => onHeadState({ filterText: e.target.value })}
sx={{ ml: 0.5, flex: "1 1 auto", input: { py: 0.65, px: 1 } }}
/>
@@ -169,7 +175,7 @@ export const ProxyHead = ({
value={testUrl}
size="small"
variant="outlined"
placeholder={t("Delay check URL")}
placeholder={t("pages.proxies.placeholders.delayCheckUrl")}
onChange={(e) => onHeadState({ testUrl: e.target.value })}
sx={{ ml: 0.5, flex: "1 1 auto", input: { py: 0.65, px: 1 } }}
/>

View File

@@ -271,7 +271,9 @@ export const ProxyItemMini = (props: Props) => {
<span
className={proxy.name === group.now ? "the-pin" : "the-unpin"}
title={
group.type === "URLTest" ? t("Delay check to cancel fixed") : ""
group.type === "URLTest"
? t("pages.proxies.labels.delayCheckReset")
: ""
}
>
📌

View File

@@ -160,7 +160,7 @@ export const ProxyRender = (props: RenderProps) => {
}}
/>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Tooltip title={t("Proxy Count")} arrow>
<Tooltip title={t("pages.proxies.labels.proxyCount")} arrow>
<Chip
size="small"
label={`${group.all.length}`}

View File

@@ -16,6 +16,57 @@
"Delete": "حذف",
"Enable": "تمكين",
"Disable": "تعطيل",
"pages": {
"proxies": {
"title": {
"default": "مجموعات الوكلاء",
"chainMode": "Proxy Chain Mode"
},
"actions": {
"toggleChain": "🔗 بروكسي السلسلة",
"connect": "Connect",
"disconnect": "Disconnect",
"connecting": "Connecting...",
"clearChainConfig": "Delete Chain Config"
},
"provider": {
"title": "مزود الوكيل"
},
"rules": {
"title": "Proxy Rules",
"select": "Select Rules"
},
"labels": {
"proxyCount": "Proxy Count",
"delayCheckReset": "فحص التأخير لإلغاء الثابت"
},
"tooltips": {
"locate": "الموقع",
"delayCheck": "فحص التأخير",
"sortDefault": "الترتيب الافتراضي",
"sortDelay": "الترتيب حسب التأخير",
"sortName": "الترتيب حسب الاسم",
"delayCheckUrl": "رابط فحص التأخير",
"showBasic": "إعدادات الوكيل الأساسية",
"showDetail": "تفاصيل الوكيل",
"filter": "تصفية"
},
"placeholders": {
"filter": "شروط التصفية",
"delayCheckUrl": "رابط فحص التأخير"
},
"chain": {
"header": "Chain Proxy Config",
"empty": "No proxy chain configured",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
"minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.",
"connectFailed": "Failed to connect to proxy chain",
"disconnectFailed": "Failed to disconnect from proxy chain",
"duplicateNode": "Proxy node already exists in chain"
}
}
},
"Label-Home": "Home",
"Label-Proxies": "الوكلاء",
"Label-Profiles": "الملفات الشخصية",

View File

@@ -16,6 +16,57 @@
"Delete": "Löschen",
"Enable": "Aktivieren",
"Disable": "Deaktivieren",
"pages": {
"proxies": {
"title": {
"default": "Proxy-Gruppen",
"chainMode": "Proxy Chain Mode"
},
"actions": {
"toggleChain": "🔗 Ketten-Proxy",
"connect": "Connect",
"disconnect": "Disconnect",
"connecting": "Connecting...",
"clearChainConfig": "Delete Chain Config"
},
"provider": {
"title": "Proxy-Sammlung"
},
"rules": {
"title": "Proxy Rules",
"select": "Select Rules"
},
"labels": {
"proxyCount": "Anzahl der Knoten",
"delayCheckReset": "Latenztest durchführen, um Fixierung aufzuheben"
},
"tooltips": {
"locate": "Aktueller Knoten",
"delayCheck": "Latenztest",
"sortDefault": "Standard Sortierung",
"sortDelay": "Nach Latenz sortieren",
"sortName": "Nach Name sortieren",
"delayCheckUrl": "Latenztest-URL",
"showBasic": "Knotendetails ausblenden",
"showDetail": "Knotendetails anzeigen",
"filter": "Knoten filtern"
},
"placeholders": {
"filter": "Filterbedingungen",
"delayCheckUrl": "Latenztest-URL"
},
"chain": {
"header": "Chain Proxy Config",
"empty": "No proxy chain configured",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
"minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.",
"connectFailed": "Failed to connect to proxy chain",
"disconnectFailed": "Failed to disconnect from proxy chain",
"duplicateNode": "Proxy node already exists in chain"
}
}
},
"Label-Home": "Startseite",
"Label-Proxies": "Proxy",
"Label-Profiles": "Abonnement",

View File

@@ -16,6 +16,57 @@
"Delete": "Delete",
"Enable": "Enable",
"Disable": "Disable",
"pages": {
"proxies": {
"title": {
"default": "Proxy Groups",
"chainMode": "Proxy Chain Mode"
},
"actions": {
"toggleChain": "🔗 Chain Proxy",
"connect": "Connect",
"disconnect": "Disconnect",
"connecting": "Connecting...",
"clearChainConfig": "Delete Chain Config"
},
"provider": {
"title": "Proxy Provider"
},
"rules": {
"title": "Proxy Rules",
"select": "Select Rules"
},
"labels": {
"proxyCount": "Proxy Count",
"delayCheckReset": "Delay check to cancel fixed"
},
"tooltips": {
"locate": "locate",
"delayCheck": "Delay check",
"sortDefault": "Sort by default",
"sortDelay": "Sort by delay",
"sortName": "Sort by name",
"delayCheckUrl": "Delay check URL",
"showBasic": "Proxy basic",
"showDetail": "Proxy detail",
"filter": "Filter"
},
"placeholders": {
"filter": "Filter conditions",
"delayCheckUrl": "Delay check URL"
},
"chain": {
"header": "Chain Proxy Config",
"empty": "No proxy chain configured",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
"minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.",
"connectFailed": "Failed to connect to proxy chain",
"disconnectFailed": "Failed to disconnect from proxy chain",
"duplicateNode": "Proxy node already exists in chain"
}
}
},
"Label-Home": "Home",
"Label-Proxies": "Proxies",
"Label-Profiles": "Profiles",

View File

@@ -16,6 +16,57 @@
"Delete": "Eliminar",
"Enable": "Habilitar",
"Disable": "Deshabilitar",
"pages": {
"proxies": {
"title": {
"default": "Grupos de proxies",
"chainMode": "Proxy Chain Mode"
},
"actions": {
"toggleChain": "🔗 Proxy en cadena",
"connect": "Connect",
"disconnect": "Disconnect",
"connecting": "Connecting...",
"clearChainConfig": "Delete Chain Config"
},
"provider": {
"title": "Proveedor de proxies"
},
"rules": {
"title": "Proxy Rules",
"select": "Select Rules"
},
"labels": {
"proxyCount": "Número de nodos",
"delayCheckReset": "Realizar prueba de latencia para cancelar la fijación"
},
"tooltips": {
"locate": "Nodo actual",
"delayCheck": "Prueba de latencia",
"sortDefault": "Ordenación predeterminada",
"sortDelay": "Ordenar por latencia",
"sortName": "Ordenar por nombre",
"delayCheckUrl": "URL de prueba de latencia",
"showBasic": "Ocultar detalles del nodo",
"showDetail": "Mostrar detalles del nodo",
"filter": "Filtrar nodos"
},
"placeholders": {
"filter": "Condiciones de filtrado",
"delayCheckUrl": "URL de prueba de latencia"
},
"chain": {
"header": "Chain Proxy Config",
"empty": "No proxy chain configured",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
"minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.",
"connectFailed": "Failed to connect to proxy chain",
"disconnectFailed": "Failed to disconnect from proxy chain",
"duplicateNode": "Proxy node already exists in chain"
}
}
},
"Label-Home": "Hogar",
"Label-Proxies": "Proxies",
"Label-Profiles": "Perfiles",

View File

@@ -16,6 +16,57 @@
"Delete": "حذف",
"Enable": "فعال کردن",
"Disable": "غیرفعال کردن",
"pages": {
"proxies": {
"title": {
"default": "گروه‌های پراکسی",
"chainMode": "Proxy Chain Mode"
},
"actions": {
"toggleChain": "🔗 پراکسی زنجیره‌ای",
"connect": "Connect",
"disconnect": "Disconnect",
"connecting": "Connecting...",
"clearChainConfig": "Delete Chain Config"
},
"provider": {
"title": "تأمین‌کننده پروکسی"
},
"rules": {
"title": "Proxy Rules",
"select": "Select Rules"
},
"labels": {
"proxyCount": "Proxy Count",
"delayCheckReset": "بررسی تأخیر برای لغو ثابت"
},
"tooltips": {
"locate": "موقعیت",
"delayCheck": "بررسی تأخیر",
"sortDefault": "مرتب‌سازی بر اساس پیش‌فرض",
"sortDelay": "مرتب‌سازی بر اساس تأخیر",
"sortName": "مرتب‌سازی بر اساس نام",
"delayCheckUrl": "آدرس بررسی تأخیر",
"showBasic": "پراکسی پایه",
"showDetail": "جزئیات پراکسی",
"filter": "فیلتر"
},
"placeholders": {
"filter": "شرایط فیلتر",
"delayCheckUrl": "آدرس بررسی تأخیر"
},
"chain": {
"header": "Chain Proxy Config",
"empty": "No proxy chain configured",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
"minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.",
"connectFailed": "Failed to connect to proxy chain",
"disconnectFailed": "Failed to disconnect from proxy chain",
"duplicateNode": "Proxy node already exists in chain"
}
}
},
"Label-Home": "Home",
"Label-Proxies": "پراکسی‌ها",
"Label-Profiles": "پروفایل‌ها",

View File

@@ -16,6 +16,57 @@
"Delete": "Hapus",
"Enable": "Aktifkan",
"Disable": "Nonaktifkan",
"pages": {
"proxies": {
"title": {
"default": "Grup Proksi",
"chainMode": "Proxy Chain Mode"
},
"actions": {
"toggleChain": "🔗 Proxy Rantai",
"connect": "Connect",
"disconnect": "Disconnect",
"connecting": "Connecting...",
"clearChainConfig": "Delete Chain Config"
},
"provider": {
"title": "Penyedia Proksi"
},
"rules": {
"title": "Proxy Rules",
"select": "Select Rules"
},
"labels": {
"proxyCount": "Proxy Count",
"delayCheckReset": "Periksa keterlambatan untuk membatalkan tetap"
},
"tooltips": {
"locate": "Lokasi",
"delayCheck": "Periksa Keterlambatan",
"sortDefault": "Urutkan secara default",
"sortDelay": "Urutkan berdasarkan keterlambatan",
"sortName": "Urutkan berdasarkan nama",
"delayCheckUrl": "URL Periksa Keterlambatan",
"showBasic": "Dasar Proksi",
"showDetail": "Detail Proksi",
"filter": "Filter"
},
"placeholders": {
"filter": "Kondisi Filter",
"delayCheckUrl": "URL Periksa Keterlambatan"
},
"chain": {
"header": "Chain Proxy Config",
"empty": "No proxy chain configured",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
"minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.",
"connectFailed": "Failed to connect to proxy chain",
"disconnectFailed": "Failed to disconnect from proxy chain",
"duplicateNode": "Proxy node already exists in chain"
}
}
},
"Label-Home": "Home",
"Label-Proxies": "Proksi",
"Label-Profiles": "Profil",

View File

@@ -16,6 +16,57 @@
"Delete": "削除",
"Enable": "有効にする",
"Disable": "無効にする",
"pages": {
"proxies": {
"title": {
"default": "プロキシグループ",
"chainMode": "Proxy Chain Mode"
},
"actions": {
"toggleChain": "🔗 チェーンプロキシ",
"connect": "Connect",
"disconnect": "Disconnect",
"connecting": "Connecting...",
"clearChainConfig": "Delete Chain Config"
},
"provider": {
"title": "プロキシプロバイダー"
},
"rules": {
"title": "Proxy Rules",
"select": "Select Rules"
},
"labels": {
"proxyCount": "ノード数",
"delayCheckReset": "遅延テストを実行して固定を解除する"
},
"tooltips": {
"locate": "現在のノード",
"delayCheck": "遅延テスト",
"sortDefault": "デフォルトでソート",
"sortDelay": "遅延でソート",
"sortName": "名前でソート",
"delayCheckUrl": "遅延テストURL",
"showBasic": "ノードの詳細を隠す",
"showDetail": "ノードの詳細を表示する",
"filter": "ノードをフィルタリング"
},
"placeholders": {
"filter": "フィルタリング条件",
"delayCheckUrl": "遅延テストURL"
},
"chain": {
"header": "Chain Proxy Config",
"empty": "No proxy chain configured",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
"minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.",
"connectFailed": "Failed to connect to proxy chain",
"disconnectFailed": "Failed to disconnect from proxy chain",
"duplicateNode": "Proxy node already exists in chain"
}
}
},
"Label-Home": "ホーム",
"Label-Proxies": "プロキシ",
"Label-Profiles": "プロファイル",

View File

@@ -16,6 +16,57 @@
"Delete": "삭제",
"Enable": "활성화",
"Disable": "비활성화",
"pages": {
"proxies": {
"title": {
"default": "프록시 그룹",
"chainMode": "Proxy Chain Mode"
},
"actions": {
"toggleChain": "🔗 체인 프록시",
"connect": "Connect",
"disconnect": "Disconnect",
"connecting": "Connecting...",
"clearChainConfig": "Delete Chain Config"
},
"provider": {
"title": "프록시 제공자"
},
"rules": {
"title": "Proxy Rules",
"select": "Select Rules"
},
"labels": {
"proxyCount": "프록시 개수",
"delayCheckReset": "고정 취소를 위한 지연 확인"
},
"tooltips": {
"locate": "로케이트",
"delayCheck": "지연 확인",
"sortDefault": "기본값으로 정렬",
"sortDelay": "지연시간으로 정렬",
"sortName": "이름으로 정렬",
"delayCheckUrl": "지연 확인 URL",
"showBasic": "프록시 기본",
"showDetail": "프록시 상세",
"filter": "필터"
},
"placeholders": {
"filter": "Filter conditions",
"delayCheckUrl": "지연 확인 URL"
},
"chain": {
"header": "Chain Proxy Config",
"empty": "No proxy chain configured",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
"minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.",
"connectFailed": "Failed to connect to proxy chain",
"disconnectFailed": "Failed to disconnect from proxy chain",
"duplicateNode": "Proxy node already exists in chain"
}
}
},
"Label-Home": "홈",
"Label-Proxies": "프록시",
"Label-Profiles": "프로필",

View File

@@ -16,6 +16,57 @@
"Delete": "Удалить",
"Enable": "Включить",
"Disable": "Отключить",
"pages": {
"proxies": {
"title": {
"default": "Группы прокси",
"chainMode": "Proxy Chain Mode"
},
"actions": {
"toggleChain": "🔗 Цепной прокси",
"connect": "Connect",
"disconnect": "Disconnect",
"connecting": "Connecting...",
"clearChainConfig": "Delete Chain Config"
},
"provider": {
"title": "Провайдер прокси"
},
"rules": {
"title": "Proxy Rules",
"select": "Select Rules"
},
"labels": {
"proxyCount": "Proxy Count",
"delayCheckReset": "Проверка задержки для отмены фиксированного"
},
"tooltips": {
"locate": "Местоположение",
"delayCheck": "Проверка задержки",
"sortDefault": "Сортировать по умолчанию",
"sortDelay": "Сортировать по задержке",
"sortName": "Сортировать по названию",
"delayCheckUrl": "URL проверки задержки",
"showBasic": "Отображать меньше сведений о прокси",
"showDetail": "Отображать больше сведений о прокси",
"filter": "Фильтр"
},
"placeholders": {
"filter": "Условия фильтрации",
"delayCheckUrl": "URL проверки задержки"
},
"chain": {
"header": "Конфигурация цепочки прокси",
"empty": "Цепочка прокси не настроена",
"instruction": "Нажимайте узлы по порядку, чтобы добавить в цепочку прокси",
"minimumNodes": "Chain proxy requires at least 2 nodes",
"minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.",
"connectFailed": "Failed to connect to proxy chain",
"disconnectFailed": "Failed to disconnect from proxy chain",
"duplicateNode": "Proxy node already exists in chain"
}
}
},
"Label-Home": "Главная",
"Label-Proxies": "Прокси",
"Label-Profiles": "Профили",

View File

@@ -16,6 +16,57 @@
"Delete": "Sil",
"Enable": "Etkinleştir",
"Disable": "Devre Dışı Bırak",
"pages": {
"proxies": {
"title": {
"default": "Vekil Grupları",
"chainMode": "Proxy Chain Mode"
},
"actions": {
"toggleChain": "🔗 Zincir Proxy",
"connect": "Connect",
"disconnect": "Disconnect",
"connecting": "Connecting...",
"clearChainConfig": "Delete Chain Config"
},
"provider": {
"title": "Vekil Sağlayıcısı"
},
"rules": {
"title": "Proxy Rules",
"select": "Select Rules"
},
"labels": {
"proxyCount": "Vekil Sayısı",
"delayCheckReset": "Sabit iptali için gecikme kontrolü"
},
"tooltips": {
"locate": "konum",
"delayCheck": "Gecikme kontrolü",
"sortDefault": "Varsayılana göre sırala",
"sortDelay": "Gecikmeye göre sırala",
"sortName": "İsme göre sırala",
"delayCheckUrl": "Gecikme kontrol URL'si",
"showBasic": "Temel Vekil",
"showDetail": "Vekil detayı",
"filter": "Filtre"
},
"placeholders": {
"filter": "Filtre koşulları",
"delayCheckUrl": "Gecikme kontrol URL'si"
},
"chain": {
"header": "Chain Proxy Config",
"empty": "No proxy chain configured",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
"minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.",
"connectFailed": "Failed to connect to proxy chain",
"disconnectFailed": "Failed to disconnect from proxy chain",
"duplicateNode": "Proxy node already exists in chain"
}
}
},
"Label-Home": "Ana Sayfa",
"Label-Proxies": "Vekil'ler",
"Label-Profiles": "Profiller",

View File

@@ -16,6 +16,57 @@
"Delete": "Бетерү",
"Enable": "Кушу",
"Disable": "Сүндерү",
"pages": {
"proxies": {
"title": {
"default": "Прокси төркемнәре",
"chainMode": "Proxy Chain Mode"
},
"actions": {
"toggleChain": "🔗 Чылбыр прокси",
"connect": "Connect",
"disconnect": "Disconnect",
"connecting": "Connecting...",
"clearChainConfig": "Delete Chain Config"
},
"provider": {
"title": "Прокси провайдеры"
},
"rules": {
"title": "Proxy Rules",
"select": "Select Rules"
},
"labels": {
"proxyCount": "Proxy Count",
"delayCheckReset": "Беркетелгәнне гамәлдән чыгару өчен задержканы тикшерү"
},
"tooltips": {
"locate": "Урын",
"delayCheck": "Задержканы тикшерү",
"sortDefault": "Башлангыч итеп сортлау",
"sortDelay": "Задержка буенча сортлау",
"sortName": "Исем буенча сортлау",
"delayCheckUrl": "Задержканы тикшерү URL-ы",
"showBasic": "Прокси турында кыскача мәгълүмат",
"showDetail": "Прокси турында тулы мәгълүмат",
"filter": "Фильтр"
},
"placeholders": {
"filter": "Фильтр шартлары",
"delayCheckUrl": "Задержканы тикшерү URL-ы"
},
"chain": {
"header": "Chain Proxy Config",
"empty": "No proxy chain configured",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
"minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.",
"connectFailed": "Failed to connect to proxy chain",
"disconnectFailed": "Failed to disconnect from proxy chain",
"duplicateNode": "Proxy node already exists in chain"
}
}
},
"Label-Home": "Home",
"Label-Proxies": "Прокси",
"Label-Profiles": "Профильләр",

View File

@@ -16,6 +16,57 @@
"Delete": "删除",
"Enable": "启用",
"Disable": "禁用",
"pages": {
"proxies": {
"title": {
"default": "代理组",
"chainMode": "链式代理模式"
},
"actions": {
"toggleChain": "🔗 链式代理",
"connect": "连接",
"disconnect": "断开",
"connecting": "连接中...",
"clearChainConfig": "删除链式配置"
},
"provider": {
"title": "代理集合"
},
"rules": {
"title": "代理规则",
"select": "选择规则"
},
"labels": {
"proxyCount": "节点数量",
"delayCheckReset": "进行延迟测试,以取消固定"
},
"tooltips": {
"locate": "当前节点",
"delayCheck": "延迟测试",
"sortDefault": "默认排序",
"sortDelay": "按延迟排序",
"sortName": "按名称排序",
"delayCheckUrl": "延迟测试链接",
"showBasic": "隐藏节点细节",
"showDetail": "展示节点细节",
"filter": "过滤节点"
},
"placeholders": {
"filter": "过滤条件",
"delayCheckUrl": "延迟测试链接"
},
"chain": {
"header": "代理链配置",
"empty": "暂无代理链配置",
"instruction": "顺序点击节点添加到代理链中",
"minimumNodes": "链式代理至少需要 2 个节点",
"minimumNodesHint": "链式代理至少需要 2 个节点,请再添加一个节点。",
"connectFailed": "连接链式代理失败",
"disconnectFailed": "断开链式代理失败",
"duplicateNode": "该节点已在链式代理表中"
}
}
},
"Label-Home": "首 页",
"Label-Proxies": "代 理",
"Label-Profiles": "订 阅",

View File

@@ -16,6 +16,57 @@
"Delete": "刪除",
"Enable": "啟用",
"Disable": "停用",
"pages": {
"proxies": {
"title": {
"default": "代理組",
"chainMode": "鏈式代理模式"
},
"actions": {
"toggleChain": "🔗 鏈式代理",
"connect": "連線",
"disconnect": "中斷",
"connecting": "連線中...",
"clearChainConfig": "刪除鏈式設定"
},
"provider": {
"title": "代理集合"
},
"rules": {
"title": "代理規則",
"select": "選擇規則"
},
"labels": {
"proxyCount": "節點數量",
"delayCheckReset": "測試延遲以取消固定"
},
"tooltips": {
"locate": "目前節點",
"delayCheck": "延遲測試",
"sortDefault": "預設排序",
"sortDelay": "按延遲排序",
"sortName": "按名稱排序",
"delayCheckUrl": "延遲測試網址",
"showBasic": "隱藏節點細節",
"showDetail": "展示節點細節",
"filter": "篩選節點"
},
"placeholders": {
"filter": "篩選條件",
"delayCheckUrl": "延遲測試網址"
},
"chain": {
"header": "鏈式代理設定",
"empty": "暫無鏈式代理設定",
"instruction": "依序點擊節點新增到鏈式代理中",
"minimumNodes": "鏈式代理至少需要 2 個節點",
"minimumNodesHint": "鏈式代理至少需要 2 個節點,請再新增一個節點。",
"connectFailed": "連線鏈式代理失敗",
"disconnectFailed": "中斷鏈式代理失敗",
"duplicateNode": "該節點已在鏈式代理表中"
}
}
},
"Label-Home": "首 頁",
"Label-Proxies": "代 理",
"Label-Profiles": "訂 閱",

View File

@@ -15,6 +15,12 @@ import {
updateProxyChainConfigInRuntime,
} from "@/services/cmds";
const MODES = ["rule", "global", "direct"] as const;
type Mode = (typeof MODES)[number];
const MODE_SET = new Set<string>(MODES);
const isMode = (value: unknown): value is Mode =>
typeof value === "string" && MODE_SET.has(value);
const ProxyPage = () => {
const { t } = useTranslation();
@@ -50,11 +56,12 @@ const ProxyPage = () => {
const { verge } = useVerge();
const modeList = useMemo(() => ["rule", "global", "direct"], []);
const modeList = useMemo(() => MODES, []);
const curMode = clashConfig?.mode?.toLowerCase();
const normalizedMode = clashConfig?.mode?.toLowerCase();
const curMode = isMode(normalizedMode) ? normalizedMode : undefined;
const onChangeMode = useLockFn(async (mode: string) => {
const onChangeMode = useLockFn(async (mode: Mode) => {
// 断开连接
if (mode !== curMode && verge?.auto_close_connection) {
closeAllConnections();
@@ -124,16 +131,20 @@ const ProxyPage = () => {
}, [isChainMode, updateChainConfigData]);
useEffect(() => {
if (curMode && !modeList.includes(curMode)) {
if (normalizedMode && !isMode(normalizedMode)) {
onChangeMode("rule");
}
}, [curMode, modeList, onChangeMode]);
}, [normalizedMode, onChangeMode]);
return (
<BasePage
full
contentStyle={{ height: "101.5%" }}
title={isChainMode ? t("Proxy Chain Mode") : t("Proxy Groups")}
title={
isChainMode
? t("pages.proxies.title.chainMode")
: t("pages.proxies.title.default")
}
header={
<Box display="flex" alignItems="center" gap={1}>
<ProviderButton />
@@ -146,7 +157,7 @@ const ProxyPage = () => {
onClick={() => onChangeMode(mode)}
sx={{ textTransform: "capitalize" }}
>
{t(mode)}
{t(`pages.proxies.modes.${mode}`)}
</Button>
))}
</ButtonGroup>
@@ -157,13 +168,13 @@ const ProxyPage = () => {
onClick={onToggleChainMode}
sx={{ ml: 1 }}
>
{t("Chain Proxy")}
{t("pages.proxies.actions.toggleChain")}
</Button>
</Box>
}
>
<ProxyGroups
mode={curMode!}
mode={curMode ?? "rule"}
isChainMode={isChainMode}
chainConfigData={chainConfigData}
/>