mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-31 11:01:36 +08:00
i18n: complete internationalization for v3.8+ features
- Add health status translations (operational, degraded, failed, circuitOpen) - Add proxy panel translations (serviceAddress, stats, stopped state) - Add usage filter translations (appType, statusCode, searchPlaceholder) - Add providerIcon click hints (clickToChange, clickToSelect) - Add config load error translations for main.tsx - Complete Japanese proxy section (failoverQueue, autoFailover) - Fix date/time locale in usage charts and tables - Use t() function in all hardcoded UI strings
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import React from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { HealthStatus } from "@/lib/api/model-test";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface HealthStatusIndicatorProps {
|
||||
status: HealthStatus;
|
||||
@@ -11,17 +12,20 @@ interface HealthStatusIndicatorProps {
|
||||
const statusConfig = {
|
||||
operational: {
|
||||
color: "bg-emerald-500",
|
||||
label: "正常",
|
||||
labelKey: "health.operational",
|
||||
labelFallback: "正常",
|
||||
textColor: "text-emerald-600 dark:text-emerald-400",
|
||||
},
|
||||
degraded: {
|
||||
color: "bg-yellow-500",
|
||||
label: "降级",
|
||||
labelKey: "health.degraded",
|
||||
labelFallback: "降级",
|
||||
textColor: "text-yellow-600 dark:text-yellow-400",
|
||||
},
|
||||
failed: {
|
||||
color: "bg-red-500",
|
||||
label: "失败",
|
||||
labelKey: "health.failed",
|
||||
labelFallback: "失败",
|
||||
textColor: "text-red-600 dark:text-red-400",
|
||||
},
|
||||
};
|
||||
@@ -31,13 +35,15 @@ export const HealthStatusIndicator: React.FC<HealthStatusIndicatorProps> = ({
|
||||
responseTimeMs,
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const config = statusConfig[status];
|
||||
const label = t(config.labelKey, { defaultValue: config.labelFallback });
|
||||
|
||||
return (
|
||||
<div className={cn("flex items-center gap-2", className)}>
|
||||
<div className={cn("w-2 h-2 rounded-full", config.color)} />
|
||||
<span className={cn("text-xs font-medium", config.textColor)}>
|
||||
{config.label}
|
||||
{label}
|
||||
{responseTimeMs !== undefined && ` (${responseTimeMs}ms)`}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { ProviderHealthStatus } from "@/types/proxy";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface ProviderHealthBadgeProps {
|
||||
consecutiveFailures: number;
|
||||
@@ -14,11 +15,14 @@ export function ProviderHealthBadge({
|
||||
consecutiveFailures,
|
||||
className,
|
||||
}: ProviderHealthBadgeProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
// 根据失败次数计算状态
|
||||
const getStatus = () => {
|
||||
if (consecutiveFailures === 0) {
|
||||
return {
|
||||
label: "正常",
|
||||
labelKey: "health.operational",
|
||||
labelFallback: "正常",
|
||||
status: ProviderHealthStatus.Healthy,
|
||||
color: "bg-green-500",
|
||||
// 使用更深/柔和的背景色,去除可能的白色内容感
|
||||
@@ -27,7 +31,8 @@ export function ProviderHealthBadge({
|
||||
};
|
||||
} else if (consecutiveFailures < 5) {
|
||||
return {
|
||||
label: "降级",
|
||||
labelKey: "health.degraded",
|
||||
labelFallback: "降级",
|
||||
status: ProviderHealthStatus.Degraded,
|
||||
color: "bg-yellow-500",
|
||||
bgColor: "bg-yellow-500/10",
|
||||
@@ -35,7 +40,8 @@ export function ProviderHealthBadge({
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
label: "熔断",
|
||||
labelKey: "health.circuitOpen",
|
||||
labelFallback: "熔断",
|
||||
status: ProviderHealthStatus.Failed,
|
||||
color: "bg-red-500",
|
||||
bgColor: "bg-red-500/10",
|
||||
@@ -45,6 +51,9 @@ export function ProviderHealthBadge({
|
||||
};
|
||||
|
||||
const statusConfig = getStatus();
|
||||
const label = t(statusConfig.labelKey, {
|
||||
defaultValue: statusConfig.labelFallback,
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -54,10 +63,13 @@ export function ProviderHealthBadge({
|
||||
statusConfig.textColor,
|
||||
className,
|
||||
)}
|
||||
title={`连续失败 ${consecutiveFailures} 次`}
|
||||
title={t("health.consecutiveFailures", {
|
||||
count: consecutiveFailures,
|
||||
defaultValue: `连续失败 ${consecutiveFailures} 次`,
|
||||
})}
|
||||
>
|
||||
<div className={cn("w-2 h-2 rounded-full", statusConfig.color)} />
|
||||
<span>{statusConfig.label}</span>
|
||||
<span>{label}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,15 @@ export function BasicFormFields({ form }: BasicFormFieldsProps) {
|
||||
<button
|
||||
type="button"
|
||||
className="w-20 h-20 p-3 rounded-xl border-2 border-muted hover:border-primary transition-colors cursor-pointer bg-muted/30 hover:bg-muted/50 flex items-center justify-center"
|
||||
title={currentIcon ? "点击更换图标" : "点击选择图标"}
|
||||
title={
|
||||
currentIcon
|
||||
? t("providerIcon.clickToChange", {
|
||||
defaultValue: "点击更换图标",
|
||||
})
|
||||
: t("providerIcon.clickToSelect", {
|
||||
defaultValue: "点击选择图标",
|
||||
})
|
||||
}
|
||||
>
|
||||
<ProviderIcon
|
||||
icon={currentIcon}
|
||||
@@ -145,7 +153,7 @@ export function BasicFormFields({ form }: BasicFormFieldsProps) {
|
||||
<FormItem>
|
||||
<FormLabel>{t("provider.websiteUrl")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} placeholder="https://" />
|
||||
<Input {...field} placeholder={t("providerForm.websiteUrlPlaceholder")} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
|
||||
@@ -150,9 +150,7 @@ export function ProviderPresetSelector({
|
||||
style={getPresetButtonStyle(isSelected, entry.preset)}
|
||||
title={
|
||||
presetCategoryLabels[category] ??
|
||||
t("providerPreset.categoryOther", {
|
||||
defaultValue: "其他",
|
||||
})
|
||||
t("providerPreset.other")
|
||||
}
|
||||
>
|
||||
{renderPresetIcon(entry.preset)}
|
||||
|
||||
Reference in New Issue
Block a user