Files
CC-Switch/src/components/proxy/ProxyToggle.tsx
T
Jason c54515742f fix: comprehensive i18n audit - add 69 missing keys and fix hardcoded Chinese
- Add 69 missing translation keys to zh/en/ja (usage, proxy, sessionManager,
  deeplink, codexConfig, openclaw, circuitBreaker, streamCheck, etc.)
- Replace 15 hardcoded Chinese strings in CircuitBreakerConfigPanel with t() calls
- Fix ColorPicker component to use i18n for default label
- Add i18n interpolation params to ProxyToggle tooltip translations
- All three language files synchronized at 1838 keys
2026-03-08 20:41:44 +08:00

89 lines
2.5 KiB
TypeScript

/**
* 代理模式切换开关组件
*
* 放置在主界面头部,用于一键启用/关闭代理模式
* 启用时自动接管 Live 配置,关闭时恢复原始配置
*/
import { Radio, Loader2 } from "lucide-react";
import { Switch } from "@/components/ui/switch";
import { useProxyStatus } from "@/hooks/useProxyStatus";
import { cn } from "@/lib/utils";
import { useTranslation } from "react-i18next";
import type { AppId } from "@/lib/api";
interface ProxyToggleProps {
className?: string;
activeApp: AppId;
}
export function ProxyToggle({ className, activeApp }: ProxyToggleProps) {
const { t } = useTranslation();
const { isRunning, takeoverStatus, setTakeoverForApp, isPending, status } =
useProxyStatus();
const handleToggle = async (checked: boolean) => {
try {
await setTakeoverForApp({ appType: activeApp, enabled: checked });
} catch (error) {
console.error("[ProxyToggle] Toggle takeover failed:", error);
}
};
const takeoverEnabled = takeoverStatus?.[activeApp] || false;
const appLabel =
activeApp === "claude"
? "Claude"
: activeApp === "codex"
? "Codex"
: activeApp === "gemini"
? "Gemini"
: "OpenCode";
const tooltipText = takeoverEnabled
? isRunning
? t("proxy.takeover.tooltip.active", {
appLabel,
address: status?.address,
port: status?.port,
defaultValue: `${appLabel} 已接管 - ${status?.address}:${status?.port}\n切换该应用供应商为热切换`,
})
: t("proxy.takeover.tooltip.broken", {
appLabel,
defaultValue: `${appLabel} 已接管,但代理服务未运行`,
})
: t("proxy.takeover.tooltip.inactive", {
appLabel,
defaultValue: `接管 ${appLabel} 的 Live 配置,让该应用请求走本地代理`,
});
return (
<div
className={cn(
"flex items-center gap-1 px-1.5 h-8 rounded-lg bg-muted/50 transition-all",
className,
)}
title={tooltipText}
>
{isPending ? (
<Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
) : (
<Radio
className={cn(
"h-4 w-4 transition-colors",
takeoverEnabled
? "text-emerald-500 animate-pulse"
: "text-muted-foreground",
)}
/>
)}
<Switch
checked={takeoverEnabled}
onCheckedChange={handleToggle}
disabled={isPending}
/>
</div>
);
}