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
This commit is contained in:
Jason
2026-03-08 20:41:44 +08:00
parent 7dbceeafe6
commit c54515742f
6 changed files with 416 additions and 74 deletions
@@ -146,15 +146,24 @@ export function CircuitBreakerConfigPanel() {
};
if (isLoading) {
return <div className="text-sm text-muted-foreground">...</div>;
return (
<div className="text-sm text-muted-foreground">
{t("circuitBreaker.loading", "加载中...")}
</div>
);
}
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold"></h3>
<h3 className="text-lg font-semibold">
{t("circuitBreaker.title", "熔断器配置")}
</h3>
<p className="text-sm text-muted-foreground mt-1">
{t(
"circuitBreaker.description",
"调整熔断器参数以控制故障检测和恢复行为",
)}
</p>
</div>
@@ -163,7 +172,9 @@ export function CircuitBreakerConfigPanel() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* 失败阈值 */}
<div className="space-y-2">
<Label htmlFor="failureThreshold"></Label>
<Label htmlFor="failureThreshold">
{t("circuitBreaker.failureThreshold", "失败阈值")}
</Label>
<Input
id="failureThreshold"
type="number"
@@ -175,13 +186,18 @@ export function CircuitBreakerConfigPanel() {
}
/>
<p className="text-xs text-muted-foreground">
{t(
"circuitBreaker.failureThresholdHint",
"连续失败多少次后打开熔断器",
)}
</p>
</div>
{/* 超时时间 */}
<div className="space-y-2">
<Label htmlFor="timeoutSeconds"></Label>
<Label htmlFor="timeoutSeconds">
{t("circuitBreaker.timeoutSeconds", "超时时间(秒)")}
</Label>
<Input
id="timeoutSeconds"
type="number"
@@ -193,13 +209,18 @@ export function CircuitBreakerConfigPanel() {
}
/>
<p className="text-xs text-muted-foreground">
{t(
"circuitBreaker.timeoutSecondsHint",
"熔断器打开后多久尝试恢复(半开状态)",
)}
</p>
</div>
{/* 成功阈值 */}
<div className="space-y-2">
<Label htmlFor="successThreshold"></Label>
<Label htmlFor="successThreshold">
{t("circuitBreaker.successThreshold", "成功阈值")}
</Label>
<Input
id="successThreshold"
type="number"
@@ -211,13 +232,18 @@ export function CircuitBreakerConfigPanel() {
}
/>
<p className="text-xs text-muted-foreground">
{t(
"circuitBreaker.successThresholdHint",
"半开状态下成功多少次后关闭熔断器",
)}
</p>
</div>
{/* 错误率阈值 */}
<div className="space-y-2">
<Label htmlFor="errorRateThreshold"> (%)</Label>
<Label htmlFor="errorRateThreshold">
{t("circuitBreaker.errorRateThreshold", "错误率阈值 (%)")}
</Label>
<Input
id="errorRateThreshold"
type="number"
@@ -230,13 +256,18 @@ export function CircuitBreakerConfigPanel() {
}
/>
<p className="text-xs text-muted-foreground">
{t(
"circuitBreaker.errorRateThresholdHint",
"错误率超过此值时打开熔断器",
)}
</p>
</div>
{/* 最小请求数 */}
<div className="space-y-2">
<Label htmlFor="minRequests"></Label>
<Label htmlFor="minRequests">
{t("circuitBreaker.minRequests", "最小请求数")}
</Label>
<Input
id="minRequests"
type="number"
@@ -248,42 +279,75 @@ export function CircuitBreakerConfigPanel() {
}
/>
<p className="text-xs text-muted-foreground">
{t("circuitBreaker.minRequestsHint", "计算错误率前的最小请求数")}
</p>
</div>
</div>
<div className="flex gap-3">
<Button onClick={handleSave} disabled={updateConfig.isPending}>
{updateConfig.isPending ? "保存中..." : "保存配置"}
{updateConfig.isPending
? t("common.saving", "保存中...")
: t("circuitBreaker.saveConfig", "保存配置")}
</Button>
<Button
variant="outline"
onClick={handleReset}
disabled={updateConfig.isPending}
>
{t("common.reset", "重置")}
</Button>
</div>
{/* 说明信息 */}
<div className="p-4 bg-muted/50 rounded-lg space-y-2 text-sm">
<h4 className="font-medium"></h4>
<h4 className="font-medium">
{t("circuitBreaker.instructionsTitle", "配置说明")}
</h4>
<ul className="space-y-1 text-muted-foreground">
<li>
<strong></strong>
{" "}
<strong>{t("circuitBreaker.failureThreshold", "失败阈值")}</strong>
{t(
"circuitBreaker.instructions.failureThreshold",
"连续失败达到此次数时,熔断器打开",
)}
</li>
<li>
<strong></strong>
<strong>{t("circuitBreaker.timeoutSeconds", "超时时间")}</strong>
{t(
"circuitBreaker.instructions.timeout",
"熔断器打开后,等待此时间后尝试半开",
)}
</li>
<li>
<strong></strong>
{" "}
<strong>{t("circuitBreaker.successThreshold", "成功阈值")}</strong>
{t(
"circuitBreaker.instructions.successThreshold",
"半开状态下,成功达到此次数时关闭熔断器",
)}
</li>
<li>
<strong></strong>
{" "}
<strong>
{t("circuitBreaker.errorRateThreshold", "错误率阈值")}
</strong>
{t(
"circuitBreaker.instructions.errorRate",
"错误率超过此值时,熔断器打开",
)}
</li>
<li>
<strong></strong>
<strong>{t("circuitBreaker.minRequests", "最小请求数")}</strong>
{t(
"circuitBreaker.instructions.minRequests",
"只有请求数达到此值后才计算错误率",
)}
</li>
</ul>
</div>
+5
View File
@@ -44,12 +44,17 @@ export function ProxyToggle({ className, activeApp }: ProxyToggleProps) {
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 配置,让该应用请求走本地代理`,
});