mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-28 00:35:32 +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:
@@ -106,7 +106,9 @@ export function PricingEditModal({
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, modelId: e.target.value })
|
||||
}
|
||||
placeholder="例如: claude-3-5-sonnet-20241022"
|
||||
placeholder={t("usage.modelIdPlaceholder", {
|
||||
defaultValue: "例如: claude-3-5-sonnet-20241022",
|
||||
})}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
@@ -122,7 +124,9 @@ export function PricingEditModal({
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, displayName: e.target.value })
|
||||
}
|
||||
placeholder="例如: Claude 3.5 Sonnet"
|
||||
placeholder={t("usage.displayNamePlaceholder", {
|
||||
defaultValue: "例如: Claude 3.5 Sonnet",
|
||||
})}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -16,8 +16,14 @@ export function RequestDetailPanel({
|
||||
requestId,
|
||||
onClose,
|
||||
}: RequestDetailPanelProps) {
|
||||
const { t } = useTranslation();
|
||||
const { t, i18n } = useTranslation();
|
||||
const { data: request, isLoading } = useRequestDetail(requestId);
|
||||
const dateLocale =
|
||||
i18n.language === "zh"
|
||||
? "zh-CN"
|
||||
: i18n.language === "ja"
|
||||
? "ja-JP"
|
||||
: "en-US";
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
@@ -69,7 +75,9 @@ export function RequestDetailPanel({
|
||||
{t("usage.time", "时间")}
|
||||
</dt>
|
||||
<dd>
|
||||
{new Date(request.createdAt * 1000).toLocaleString("zh-CN")}
|
||||
{new Date(request.createdAt * 1000).toLocaleString(
|
||||
dateLocale,
|
||||
)}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -23,7 +23,7 @@ import type { LogFilters } from "@/types/usage";
|
||||
import { ChevronLeft, ChevronRight, RefreshCw, Search, X } from "lucide-react";
|
||||
|
||||
export function RequestLogTable() {
|
||||
const { t } = useTranslation();
|
||||
const { t, i18n } = useTranslation();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
// 默认时间范围:过去24小时
|
||||
@@ -62,6 +62,13 @@ export function RequestLogTable() {
|
||||
});
|
||||
};
|
||||
|
||||
const dateLocale =
|
||||
i18n.language === "zh"
|
||||
? "zh-CN"
|
||||
: i18n.language === "ja"
|
||||
? "ja-JP"
|
||||
: "en-US";
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{/* 筛选栏 */}
|
||||
@@ -77,10 +84,12 @@ export function RequestLogTable() {
|
||||
}
|
||||
>
|
||||
<SelectTrigger className="w-[130px] bg-background">
|
||||
<SelectValue placeholder={t("usage.endpoint", "端点")} />
|
||||
<SelectValue placeholder={t("usage.appType", "应用类型")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">{t("common.all", "全部端点")}</SelectItem>
|
||||
<SelectItem value="all">
|
||||
{t("usage.allApps", { defaultValue: "全部应用" })}
|
||||
</SelectItem>
|
||||
<SelectItem value="claude">Claude</SelectItem>
|
||||
<SelectItem value="codex">Codex</SelectItem>
|
||||
<SelectItem value="gemini">Gemini</SelectItem>
|
||||
@@ -97,7 +106,7 @@ export function RequestLogTable() {
|
||||
}
|
||||
>
|
||||
<SelectTrigger className="w-[130px] bg-background">
|
||||
<SelectValue placeholder={t("usage.status", "状态码")} />
|
||||
<SelectValue placeholder={t("usage.statusCode", "状态码")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">{t("common.all", "全部状态")}</SelectItem>
|
||||
@@ -113,7 +122,10 @@ export function RequestLogTable() {
|
||||
<div className="relative flex-1">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
placeholder={t("usage.provider", "搜索供应商...")}
|
||||
placeholder={t(
|
||||
"usage.searchProviderPlaceholder",
|
||||
"搜索供应商...",
|
||||
)}
|
||||
className="pl-9 bg-background"
|
||||
value={tempFilters.providerName || ""}
|
||||
onChange={(e) =>
|
||||
@@ -125,7 +137,7 @@ export function RequestLogTable() {
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
placeholder={t("usage.model", "搜索模型...")}
|
||||
placeholder={t("usage.searchModelPlaceholder", "搜索模型...")}
|
||||
className="w-[180px] bg-background"
|
||||
value={tempFilters.model || ""}
|
||||
onChange={(e) =>
|
||||
@@ -140,7 +152,9 @@ export function RequestLogTable() {
|
||||
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<span className="whitespace-nowrap">时间范围:</span>
|
||||
<span className="whitespace-nowrap">
|
||||
{t("usage.timeRange", { defaultValue: "时间范围" })}:
|
||||
</span>
|
||||
<Input
|
||||
type="datetime-local"
|
||||
className="h-8 w-[200px] bg-background"
|
||||
@@ -267,7 +281,9 @@ export function RequestLogTable() {
|
||||
logs.map((log) => (
|
||||
<TableRow key={log.requestId}>
|
||||
<TableCell>
|
||||
{new Date(log.createdAt * 1000).toLocaleString("zh-CN")}
|
||||
{new Date(log.createdAt * 1000).toLocaleString(
|
||||
dateLocale,
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{log.providerName ||
|
||||
|
||||
@@ -56,15 +56,15 @@ export function UsageSummaryCards({ days }: UsageSummaryCardsProps) {
|
||||
color: "text-purple-500",
|
||||
bg: "bg-purple-500/10",
|
||||
subValue: (
|
||||
<div className="flex flex-col gap-1 text-xs text-muted-foreground mt-3 pt-3 border-t border-border/50">
|
||||
<div className="flex flex-col gap-1 text-xs text-muted-foreground mt-3 pt-3 border-t border-border/50">
|
||||
<div className="flex justify-between items-center">
|
||||
<span>Input</span>
|
||||
<span>{t("usage.input", { defaultValue: "Input" })}</span>
|
||||
<span className="text-foreground/80">
|
||||
{(inputTokens / 1000).toFixed(1)}k
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span>Output</span>
|
||||
<span>{t("usage.output", { defaultValue: "Output" })}</span>
|
||||
<span className="text-foreground/80">
|
||||
{(outputTokens / 1000).toFixed(1)}k
|
||||
</span>
|
||||
@@ -78,21 +78,21 @@ export function UsageSummaryCards({ days }: UsageSummaryCardsProps) {
|
||||
icon: Database,
|
||||
color: "text-orange-500",
|
||||
bg: "bg-orange-500/10",
|
||||
subValue: (
|
||||
<div className="flex flex-col gap-1 text-xs text-muted-foreground mt-3 pt-3 border-t border-border/50">
|
||||
<div className="flex justify-between items-center">
|
||||
<span>Write</span>
|
||||
<span className="text-foreground/80">
|
||||
{(cacheWriteTokens / 1000).toFixed(1)}k
|
||||
</span>
|
||||
subValue: (
|
||||
<div className="flex flex-col gap-1 text-xs text-muted-foreground mt-3 pt-3 border-t border-border/50">
|
||||
<div className="flex justify-between items-center">
|
||||
<span>{t("usage.cacheWrite", { defaultValue: "Write" })}</span>
|
||||
<span className="text-foreground/80">
|
||||
{(cacheWriteTokens / 1000).toFixed(1)}k
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span>{t("usage.cacheRead", { defaultValue: "Read" })}</span>
|
||||
<span className="text-foreground/80">
|
||||
{(cacheReadTokens / 1000).toFixed(1)}k
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span>Read</span>
|
||||
<span className="text-foreground/80">
|
||||
{(cacheReadTokens / 1000).toFixed(1)}k
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -17,7 +17,7 @@ interface UsageTrendChartProps {
|
||||
}
|
||||
|
||||
export function UsageTrendChart({ days }: UsageTrendChartProps) {
|
||||
const { t } = useTranslation();
|
||||
const { t, i18n } = useTranslation();
|
||||
const { data: trends, isLoading } = useUsageTrends(days);
|
||||
|
||||
if (isLoading) {
|
||||
@@ -29,14 +29,20 @@ export function UsageTrendChart({ days }: UsageTrendChartProps) {
|
||||
}
|
||||
|
||||
const isToday = days === 1;
|
||||
const dateLocale =
|
||||
i18n.language === "zh"
|
||||
? "zh-CN"
|
||||
: i18n.language === "ja"
|
||||
? "ja-JP"
|
||||
: "en-US";
|
||||
const chartData =
|
||||
trends?.map((stat) => {
|
||||
const pointDate = new Date(stat.date);
|
||||
return {
|
||||
rawDate: stat.date,
|
||||
label: isToday
|
||||
? pointDate.toLocaleTimeString("zh-CN", { hour: "2-digit" })
|
||||
: pointDate.toLocaleDateString("zh-CN", {
|
||||
? pointDate.toLocaleTimeString(dateLocale, { hour: "2-digit" })
|
||||
: pointDate.toLocaleDateString(dateLocale, {
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user