i18n: complete usage panel and settings internationalization

- Add missing i18n keys for usage statistics panel (trends, cost, perMillion, etc.)
- Add i18n keys for settings advanced section (configDir, proxy, modelTest, etc.)
- Add streamCheck i18n keys for health check configuration
- Remove hardcoded Chinese fallback values from t() calls
- Add common keys (all, search, reset, actions, deleting)
This commit is contained in:
Jason
2025-12-20 22:29:39 +08:00
parent 2fb3b5405a
commit ca7cb398c2
9 changed files with 355 additions and 103 deletions
+16 -19
View File
@@ -215,7 +215,7 @@ export function SettingsPage({
{t("settings.tabAdvanced")}
</TabsTrigger>
<TabsTrigger value="usage">
{t("usage.title", "使用统计")}
{t("usage.title")}
</TabsTrigger>
<TabsTrigger value="about">{t("common.about")}</TabsTrigger>
</TabsList>
@@ -254,10 +254,10 @@ export function SettingsPage({
<FolderSearch className="h-5 w-5 text-primary" />
<div className="text-left">
<h3 className="text-base font-semibold">
{t("settings.advanced.configDir.title")}
</h3>
<p className="text-sm text-muted-foreground font-normal">
ClaudeCodex Gemini
{t("settings.advanced.configDir.description")}
</p>
</div>
</div>
@@ -289,10 +289,10 @@ export function SettingsPage({
<Server className="h-5 w-5 text-green-500" />
<div className="text-left">
<h3 className="text-base font-semibold">
{t("settings.advanced.proxy.title")}
</h3>
<p className="text-sm text-muted-foreground font-normal">
{t("settings.advanced.proxy.description")}
</p>
</div>
</div>
@@ -307,7 +307,7 @@ export function SettingsPage({
<Activity
className={`h-3 w-3 ${isRunning ? "animate-pulse" : ""}`}
/>
{isRunning ? "运行中" : "已停止"}
{isRunning ? t("settings.advanced.proxy.running") : t("settings.advanced.proxy.stopped")}
</Badge>
<Switch
checked={isRunning}
@@ -330,10 +330,10 @@ export function SettingsPage({
<Activity className="h-5 w-5 text-indigo-500" />
<div className="text-left">
<h3 className="text-base font-semibold">
{t("settings.advanced.modelTest.title")}
</h3>
<p className="text-sm text-muted-foreground font-normal">
使
{t("settings.advanced.modelTest.description")}
</p>
</div>
</div>
@@ -353,10 +353,10 @@ export function SettingsPage({
<Activity className="h-5 w-5 text-orange-500" />
<div className="text-left">
<h3 className="text-base font-semibold">
{t("settings.advanced.failover.title")}
</h3>
<p className="text-sm text-muted-foreground font-normal">
{t("settings.advanced.failover.description")}
</p>
</div>
</div>
@@ -376,13 +376,10 @@ export function SettingsPage({
<div className="space-y-4">
<div>
<h4 className="text-sm font-semibold">
{t("proxy.failoverQueue.title", "故障转移队列")}
{t("proxy.failoverQueue.title")}
</h4>
<p className="text-xs text-muted-foreground">
{t(
"proxy.failoverQueue.description",
"管理各应用的供应商故障转移顺序",
)}
{t("proxy.failoverQueue.description")}
</p>
</div>
<Tabs defaultValue="claude" className="w-full">
@@ -432,10 +429,10 @@ export function SettingsPage({
<Coins className="h-5 w-5 text-yellow-500" />
<div className="text-left">
<h3 className="text-base font-semibold">
{t("settings.advanced.pricing.title")}
</h3>
<p className="text-sm text-muted-foreground font-normal">
Token
{t("settings.advanced.pricing.description")}
</p>
</div>
</div>
@@ -454,10 +451,10 @@ export function SettingsPage({
<Database className="h-5 w-5 text-blue-500" />
<div className="text-left">
<h3 className="text-base font-semibold">
{t("settings.advanced.data.title")}
</h3>
<p className="text-sm text-muted-foreground font-normal">
{t("settings.advanced.data.description")}
</p>
</div>
</div>
+12 -12
View File
@@ -47,12 +47,12 @@ export function ModelTestConfigPanel() {
try {
setIsSaving(true);
await saveStreamCheckConfig(config);
toast.success(t("streamCheck.configSaved", "健康检查配置已保存"), {
toast.success(t("streamCheck.configSaved"), {
closeButton: true,
});
} catch (e) {
toast.error(
t("streamCheck.configSaveFailed", "保存失败") + ": " + String(e),
t("streamCheck.configSaveFailed") + ": " + String(e),
);
} finally {
setIsSaving(false);
@@ -78,12 +78,12 @@ export function ModelTestConfigPanel() {
{/* 测试模型配置 */}
<div className="space-y-4">
<h4 className="text-sm font-medium text-muted-foreground">
{t("streamCheck.testModels", "测试模型")}
{t("streamCheck.testModels")}
</h4>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="space-y-2">
<Label htmlFor="claudeModel">
{t("streamCheck.claudeModel", "Claude 模型")}
{t("streamCheck.claudeModel")}
</Label>
<Input
id="claudeModel"
@@ -97,7 +97,7 @@ export function ModelTestConfigPanel() {
<div className="space-y-2">
<Label htmlFor="codexModel">
{t("streamCheck.codexModel", "Codex 模型")}
{t("streamCheck.codexModel")}
</Label>
<Input
id="codexModel"
@@ -111,7 +111,7 @@ export function ModelTestConfigPanel() {
<div className="space-y-2">
<Label htmlFor="geminiModel">
{t("streamCheck.geminiModel", "Gemini 模型")}
{t("streamCheck.geminiModel")}
</Label>
<Input
id="geminiModel"
@@ -128,12 +128,12 @@ export function ModelTestConfigPanel() {
{/* 检查参数配置 */}
<div className="space-y-4">
<h4 className="text-sm font-medium text-muted-foreground">
{t("streamCheck.checkParams", "检查参数")}
{t("streamCheck.checkParams")}
</h4>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="space-y-2">
<Label htmlFor="timeoutSecs">
{t("streamCheck.timeout", "超时时间(秒)")}
{t("streamCheck.timeout")}
</Label>
<Input
id="timeoutSecs"
@@ -152,7 +152,7 @@ export function ModelTestConfigPanel() {
<div className="space-y-2">
<Label htmlFor="maxRetries">
{t("streamCheck.maxRetries", "最大重试次数")}
{t("streamCheck.maxRetries")}
</Label>
<Input
id="maxRetries"
@@ -171,7 +171,7 @@ export function ModelTestConfigPanel() {
<div className="space-y-2">
<Label htmlFor="degradedThresholdMs">
{t("streamCheck.degradedThreshold", "降级阈值(毫秒)")}
{t("streamCheck.degradedThreshold")}
</Label>
<Input
id="degradedThresholdMs"
@@ -196,12 +196,12 @@ export function ModelTestConfigPanel() {
{isSaving ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
{t("common.saving", "保存中...")}
{t("common.saving")}
</>
) : (
<>
<Save className="mr-2 h-4 w-4" />
{t("common.save", "保存")}
{t("common.save")}
</>
)}
</Button>
+20 -26
View File
@@ -63,7 +63,7 @@ export function PricingConfigPanel() {
<div className="flex items-center gap-2">
<ChevronRight className="h-4 w-4" />
<CardTitle className="text-base">
{t("usage.modelPricing", "模型定价")}
{t("usage.modelPricing")}
</CardTitle>
</div>
</CardHeader>
@@ -85,7 +85,7 @@ export function PricingConfigPanel() {
<ChevronRight className="h-4 w-4" />
)}
<CardTitle className="text-base">
{t("usage.modelPricing", "模型定价")}
{t("usage.modelPricing")}
</CardTitle>
</div>
</CardHeader>
@@ -93,7 +93,7 @@ export function PricingConfigPanel() {
<CardContent>
<Alert variant="destructive">
<AlertDescription>
{t("usage.loadPricingError", "加载定价数据失败")}:{" "}
{t("usage.loadPricingError")}:{" "}
{String(error)}
</AlertDescription>
</Alert>
@@ -107,7 +107,7 @@ export function PricingConfigPanel() {
<div className="space-y-4">
<div className="flex items-center justify-between mb-4">
<h4 className="text-sm font-medium text-muted-foreground">
{t("usage.modelPricingDesc", "配置各模型的 Token 成本")} ()
{t("usage.modelPricingDesc")} {t("usage.perMillion")}
</h4>
<Button
onClick={(e) => {
@@ -117,7 +117,7 @@ export function PricingConfigPanel() {
size="sm"
>
<Plus className="mr-1 h-4 w-4" />
{t("common.add", "新增")}
{t("common.add")}
</Button>
</div>
@@ -125,10 +125,7 @@ export function PricingConfigPanel() {
{!pricing || pricing.length === 0 ? (
<Alert>
<AlertDescription>
{t(
"usage.noPricingData",
'暂无定价数据。点击"新增"添加模型定价配置。',
)}
{t("usage.noPricingData")}
</AlertDescription>
</Alert>
) : (
@@ -136,22 +133,22 @@ export function PricingConfigPanel() {
<Table>
<TableHeader>
<TableRow>
<TableHead>{t("usage.model", "模型")}</TableHead>
<TableHead>{t("usage.displayName", "显示名称")}</TableHead>
<TableHead>{t("usage.model")}</TableHead>
<TableHead>{t("usage.displayName")}</TableHead>
<TableHead className="text-right">
{t("usage.inputCost", "输入成本")}
{t("usage.inputCost")}
</TableHead>
<TableHead className="text-right">
{t("usage.outputCost", "输出成本")}
{t("usage.outputCost")}
</TableHead>
<TableHead className="text-right">
{t("usage.cacheReadCost", "缓存读取")}
{t("usage.cacheReadCost")}
</TableHead>
<TableHead className="text-right">
{t("usage.cacheWriteCost", "缓存写入")}
{t("usage.cacheWriteCost")}
</TableHead>
<TableHead className="text-right">
{t("common.actions", "操作")}
{t("common.actions")}
</TableHead>
</TableRow>
</TableHeader>
@@ -183,7 +180,7 @@ export function PricingConfigPanel() {
setIsAddingNew(false);
setEditingModel(model);
}}
title={t("common.edit", "编辑")}
title={t("common.edit")}
>
<Pencil className="h-4 w-4" />
</Button>
@@ -191,7 +188,7 @@ export function PricingConfigPanel() {
variant="ghost"
size="icon"
onClick={() => setDeleteConfirm(model.modelId)}
title={t("common.delete", "删除")}
title={t("common.delete")}
className="text-destructive hover:text-destructive"
>
<Trash2 className="h-4 w-4" />
@@ -224,18 +221,15 @@ export function PricingConfigPanel() {
<DialogContent>
<DialogHeader>
<DialogTitle>
{t("usage.deleteConfirmTitle", "确认删除")}
{t("usage.deleteConfirmTitle")}
</DialogTitle>
<DialogDescription>
{t(
"usage.deleteConfirmDesc",
"确定要删除此模型定价配置吗?此操作无法撤销。",
)}
{t("usage.deleteConfirmDesc")}
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline" onClick={() => setDeleteConfirm(null)}>
{t("common.cancel", "取消")}
{t("common.cancel")}
</Button>
<Button
variant="destructive"
@@ -243,8 +237,8 @@ export function PricingConfigPanel() {
disabled={deleteMutation.isPending}
>
{deleteMutation.isPending
? t("common.deleting", "删除中...")
: t("common.delete", "删除")}
? t("common.deleting")
: t("common.delete")}
</Button>
</DialogFooter>
</DialogContent>
+24 -27
View File
@@ -84,11 +84,11 @@ export function RequestLogTable() {
}
>
<SelectTrigger className="w-[130px] bg-background">
<SelectValue placeholder={t("usage.appType", "应用类型")} />
<SelectValue placeholder={t("usage.appType")} />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">
{t("usage.allApps", { defaultValue: "全部应用" })}
{t("usage.allApps")}
</SelectItem>
<SelectItem value="claude">Claude</SelectItem>
<SelectItem value="codex">Codex</SelectItem>
@@ -106,10 +106,10 @@ export function RequestLogTable() {
}
>
<SelectTrigger className="w-[130px] bg-background">
<SelectValue placeholder={t("usage.statusCode", "状态码")} />
<SelectValue placeholder={t("usage.statusCode")} />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">{t("common.all", "全部状态")}</SelectItem>
<SelectItem value="all">{t("common.all")}</SelectItem>
<SelectItem value="200">200 OK</SelectItem>
<SelectItem value="400">400 Bad Request</SelectItem>
<SelectItem value="401">401 Unauthorized</SelectItem>
@@ -122,10 +122,7 @@ 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.searchProviderPlaceholder",
"搜索供应商...",
)}
placeholder={t("usage.searchProviderPlaceholder")}
className="pl-9 bg-background"
value={tempFilters.providerName || ""}
onChange={(e) =>
@@ -137,7 +134,7 @@ export function RequestLogTable() {
/>
</div>
<Input
placeholder={t("usage.searchModelPlaceholder", "搜索模型...")}
placeholder={t("usage.searchModelPlaceholder")}
className="w-[180px] bg-background"
value={tempFilters.model || ""}
onChange={(e) =>
@@ -153,7 +150,7 @@ 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">
{t("usage.timeRange", { defaultValue: "时间范围" })}:
{t("usage.timeRange")}:
</span>
<Input
type="datetime-local"
@@ -204,7 +201,7 @@ export function RequestLogTable() {
className="h-8"
>
<Search className="mr-2 h-3.5 w-3.5" />
{t("common.search", "查询")}
{t("common.search")}
</Button>
<Button
size="sm"
@@ -213,7 +210,7 @@ export function RequestLogTable() {
className="h-8"
>
<X className="mr-2 h-3.5 w-3.5" />
{t("common.reset", "重置")}
{t("common.reset")}
</Button>
<Button
size="sm"
@@ -236,34 +233,34 @@ export function RequestLogTable() {
<TableHeader>
<TableRow>
<TableHead className="whitespace-nowrap">
{t("usage.time", "时间")}
{t("usage.time")}
</TableHead>
<TableHead className="whitespace-nowrap">
{t("usage.provider", "供应商")}
{t("usage.provider")}
</TableHead>
<TableHead className="min-w-[280px] whitespace-nowrap">
{t("usage.billingModel", "计费模型")}
{t("usage.billingModel")}
</TableHead>
<TableHead className="text-right whitespace-nowrap">
{t("usage.inputTokens", "输入")}
{t("usage.inputTokens")}
</TableHead>
<TableHead className="text-right whitespace-nowrap">
{t("usage.outputTokens", "输出")}
{t("usage.outputTokens")}
</TableHead>
<TableHead className="text-right min-w-[90px] whitespace-nowrap">
{t("usage.cacheReadTokens", "缓存读取")}
{t("usage.cacheReadTokens")}
</TableHead>
<TableHead className="text-right min-w-[90px] whitespace-nowrap">
{t("usage.cacheCreationTokens", "缓存写入")}
{t("usage.cacheCreationTokens")}
</TableHead>
<TableHead className="text-right whitespace-nowrap">
{t("usage.totalCost", "成本")}
{t("usage.totalCost")}
</TableHead>
<TableHead className="text-center min-w-[140px] whitespace-nowrap">
{t("usage.timingInfo", "用时/首字")}
{t("usage.timingInfo")}
</TableHead>
<TableHead className="whitespace-nowrap">
{t("usage.status", "状态")}
{t("usage.status")}
</TableHead>
</TableRow>
</TableHeader>
@@ -274,7 +271,7 @@ export function RequestLogTable() {
colSpan={10}
className="text-center text-muted-foreground"
>
{t("usage.noData", "暂无数据")}
{t("usage.noData")}
</TableCell>
</TableRow>
) : (
@@ -287,7 +284,7 @@ export function RequestLogTable() {
</TableCell>
<TableCell>
{log.providerName ||
t("usage.unknownProvider", "未知供应商")}
t("usage.unknownProvider")}
</TableCell>
<TableCell
className="font-mono text-sm max-w-[280px] truncate"
@@ -355,8 +352,8 @@ export function RequestLogTable() {
}`}
>
{log.isStreaming
? t("usage.stream", "流")
: t("usage.nonStream", "非流")}
? t("usage.stream")
: t("usage.nonStream")}
</span>
</div>
</TableCell>
@@ -382,7 +379,7 @@ export function RequestLogTable() {
{total > 0 && (
<div className="flex items-center justify-between px-2">
<span className="text-sm text-muted-foreground">
{t("usage.totalRecords", "共 {{total}} 条记录", { total })}
{t("usage.totalRecords", { total })}
</span>
<div className="flex items-center gap-1">
<Button
+8 -8
View File
@@ -25,9 +25,9 @@ export function UsageDashboard() {
>
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
<div className="flex flex-col gap-1">
<h2 className="text-2xl font-bold">{t("usage.title", "使用统计")}</h2>
<h2 className="text-2xl font-bold">{t("usage.title")}</h2>
<p className="text-sm text-muted-foreground">
{t("usage.subtitle", "查看 AI 模型的使用情况和成本统计")}
{t("usage.subtitle")}
</p>
</div>
@@ -41,19 +41,19 @@ export function UsageDashboard() {
value="1d"
className="flex-1 sm:flex-none sm:px-6 data-[state=active]:bg-primary/10 data-[state=active]:text-primary hover:text-primary transition-colors"
>
{t("usage.today", "24小时")}
{t("usage.today")}
</TabsTrigger>
<TabsTrigger
value="7d"
className="flex-1 sm:flex-none sm:px-6 data-[state=active]:bg-primary/10 data-[state=active]:text-primary hover:text-primary transition-colors"
>
{t("usage.last7days", "7天")}
{t("usage.last7days")}
</TabsTrigger>
<TabsTrigger
value="30d"
className="flex-1 sm:flex-none sm:px-6 data-[state=active]:bg-primary/10 data-[state=active]:text-primary hover:text-primary transition-colors"
>
{t("usage.last30days", "30天")}
{t("usage.last30days")}
</TabsTrigger>
</TabsList>
</Tabs>
@@ -69,15 +69,15 @@ export function UsageDashboard() {
<TabsList className="bg-muted/50">
<TabsTrigger value="logs" className="gap-2">
<ListFilter className="h-4 w-4" />
{t("usage.requestLogs", "请求日志")}
{t("usage.requestLogs")}
</TabsTrigger>
<TabsTrigger value="providers" className="gap-2">
<Activity className="h-4 w-4" />
{t("usage.providerStats", "Provider 统计")}
{t("usage.providerStats")}
</TabsTrigger>
<TabsTrigger value="models" className="gap-2">
<BarChart3 className="h-4 w-4" />
{t("usage.modelStats", "模型统计")}
{t("usage.modelStats")}
</TabsTrigger>
</TabsList>
</div>
+8 -8
View File
@@ -34,7 +34,7 @@ export function UsageSummaryCards({ days }: UsageSummaryCardsProps) {
return [
{
title: t("usage.totalRequests", "总请求数"),
title: t("usage.totalRequests"),
value: totalRequests.toLocaleString(),
icon: Activity,
color: "text-blue-500",
@@ -42,7 +42,7 @@ export function UsageSummaryCards({ days }: UsageSummaryCardsProps) {
subValue: null,
},
{
title: t("usage.totalCost", "总成本"),
title: t("usage.totalCost"),
value: `$${totalCost.toFixed(4)}`,
icon: DollarSign,
color: "text-green-500",
@@ -50,7 +50,7 @@ export function UsageSummaryCards({ days }: UsageSummaryCardsProps) {
subValue: null,
},
{
title: t("usage.totalTokens", "总 Token 数"),
title: t("usage.totalTokens"),
value: totalTokens.toLocaleString(),
icon: Layers,
color: "text-purple-500",
@@ -58,13 +58,13 @@ export function UsageSummaryCards({ days }: UsageSummaryCardsProps) {
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.input", { defaultValue: "Input" })}</span>
<span>{t("usage.input")}</span>
<span className="text-foreground/80">
{(inputTokens / 1000).toFixed(1)}k
</span>
</div>
<div className="flex justify-between items-center">
<span>{t("usage.output", { defaultValue: "Output" })}</span>
<span>{t("usage.output")}</span>
<span className="text-foreground/80">
{(outputTokens / 1000).toFixed(1)}k
</span>
@@ -73,7 +73,7 @@ export function UsageSummaryCards({ days }: UsageSummaryCardsProps) {
),
},
{
title: t("usage.cacheTokens", "缓存 Token"),
title: t("usage.cacheTokens"),
value: totalCacheTokens.toLocaleString(),
icon: Database,
color: "text-orange-500",
@@ -81,13 +81,13 @@ export function UsageSummaryCards({ days }: UsageSummaryCardsProps) {
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>{t("usage.cacheWrite")}</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>{t("usage.cacheRead")}</span>
<span className="text-foreground/80">
{(cacheReadTokens / 1000).toFixed(1)}k
</span>
+89 -1
View File
@@ -32,7 +32,11 @@
"back": "Back",
"refresh": "Refresh",
"refreshing": "Refreshing...",
"notInstalled": "Not installed"
"all": "All",
"search": "Search",
"reset": "Reset",
"actions": "Actions",
"deleting": "Deleting..."
},
"apiKeyInput": {
"placeholder": "Enter API Key",
@@ -142,6 +146,34 @@
"general": "General",
"tabGeneral": "General",
"tabAdvanced": "Advanced",
"advanced": {
"configDir": {
"title": "Configuration Directory",
"description": "Manage storage paths for Claude, Codex and Gemini configurations"
},
"proxy": {
"title": "Local Proxy",
"description": "Control proxy service toggle, view status and port info",
"running": "Running",
"stopped": "Stopped"
},
"modelTest": {
"title": "Model Test Config",
"description": "Configure default models and prompts for model testing"
},
"failover": {
"title": "Auto Failover",
"description": "Configure failover queue and circuit breaker strategy"
},
"pricing": {
"title": "Cost Pricing",
"description": "Manage token pricing rules for each model"
},
"data": {
"title": "Data Management",
"description": "Import/export configurations and backup/restore"
}
},
"language": "Language",
"languageHint": "Preview interface language immediately after switching, takes effect permanently after saving.",
"theme": "Theme",
@@ -365,6 +397,50 @@
"hint": "You can continue to adjust the fields below after selecting a preset."
},
"usage": {
"title": "Usage Statistics",
"subtitle": "View AI model usage and cost statistics",
"today": "24 Hours",
"last7days": "7 Days",
"last30days": "30 Days",
"totalRequests": "Total Requests",
"totalCost": "Total Cost",
"cost": "Cost",
"perMillion": "(per million)",
"trends": "Usage Trends",
"rangeToday": "Today (hourly)",
"rangeLast7Days": "Last 7 days",
"rangeLast30Days": "Last 30 days",
"totalTokens": "Total Tokens",
"cacheTokens": "Cache Tokens",
"requestLogs": "Request Logs",
"providerStats": "Provider Stats",
"modelStats": "Model Stats",
"time": "Time",
"provider": "Provider",
"billingModel": "Billing Model",
"inputTokens": "Input",
"outputTokens": "Output",
"cacheReadTokens": "Cache Read",
"cacheCreationTokens": "Cache Write",
"timingInfo": "Duration/TTFT",
"status": "Status",
"noData": "No data",
"unknownProvider": "Unknown Provider",
"stream": "Stream",
"nonStream": "Non-stream",
"totalRecords": "{{total}} records total",
"modelPricing": "Model Pricing",
"loadPricingError": "Failed to load pricing data",
"modelPricingDesc": "Configure token costs for each model",
"noPricingData": "No pricing data. Click \"Add\" to add model pricing configuration.",
"model": "Model",
"displayName": "Display Name",
"inputCost": "Input Cost",
"outputCost": "Output Cost",
"cacheReadCost": "Cache Read",
"cacheWriteCost": "Cache Write",
"deleteConfirmTitle": "Confirm Delete",
"deleteConfirmDesc": "Are you sure you want to delete this model pricing? This action cannot be undone.",
"queryFailed": "Query failed",
"refreshUsage": "Refresh usage",
"planUsage": "Plan usage",
@@ -944,5 +1020,17 @@
"errorRateLabel": "Error Rate Threshold",
"errorRateExplain": "Open circuit breaker when error rate exceeds this value, even if failure threshold not reached"
}
},
"streamCheck": {
"configSaved": "Health check config saved",
"configSaveFailed": "Save failed",
"testModels": "Test Models",
"claudeModel": "Claude Model",
"codexModel": "Codex Model",
"geminiModel": "Gemini Model",
"checkParams": "Check Parameters",
"timeout": "Timeout (seconds)",
"maxRetries": "Max Retries",
"degradedThreshold": "Degraded Threshold (ms)"
}
}
+89 -1
View File
@@ -32,7 +32,11 @@
"back": "戻る",
"refresh": "更新",
"refreshing": "更新中...",
"notInstalled": "未インストール"
"all": "すべて",
"search": "検索",
"reset": "リセット",
"actions": "操作",
"deleting": "削除中..."
},
"apiKeyInput": {
"placeholder": "API Key を入力",
@@ -142,6 +146,34 @@
"general": "一般",
"tabGeneral": "一般",
"tabAdvanced": "詳細",
"advanced": {
"configDir": {
"title": "設定ディレクトリ",
"description": "Claude、Codex、Gemini の設定保存パスを管理"
},
"proxy": {
"title": "ローカルプロキシ",
"description": "プロキシサービスの切り替え、ステータスとポート情報を表示",
"running": "実行中",
"stopped": "停止中"
},
"modelTest": {
"title": "モデルテスト設定",
"description": "モデルテストで使用するデフォルトモデルとプロンプトを設定"
},
"failover": {
"title": "自動フェイルオーバー",
"description": "フェイルオーバーキューとサーキットブレーカー戦略を設定"
},
"pricing": {
"title": "コスト計算",
"description": "各モデルのトークン料金ルールを管理"
},
"data": {
"title": "データ管理",
"description": "設定のインポート/エクスポートとバックアップ/復元"
}
},
"language": "言語",
"languageHint": "切り替えるとすぐにプレビューされ、保存後に永続化されます。",
"theme": "テーマ",
@@ -365,6 +397,50 @@
"hint": "プリセットを選んだ後でも、下のフィールドで調整できます。"
},
"usage": {
"title": "利用統計",
"subtitle": "AI モデルの利用状況とコスト統計を表示",
"today": "24時間",
"last7days": "7日間",
"last30days": "30日間",
"totalRequests": "総リクエスト数",
"totalCost": "総コスト",
"cost": "コスト",
"perMillion": "(100万あたり)",
"trends": "利用トレンド",
"rangeToday": "今日 (時間別)",
"rangeLast7Days": "過去7日間",
"rangeLast30Days": "過去30日間",
"totalTokens": "総トークン数",
"cacheTokens": "キャッシュトークン",
"requestLogs": "リクエストログ",
"providerStats": "プロバイダー統計",
"modelStats": "モデル統計",
"time": "時間",
"provider": "プロバイダー",
"billingModel": "課金モデル",
"inputTokens": "入力",
"outputTokens": "出力",
"cacheReadTokens": "キャッシュ読取",
"cacheCreationTokens": "キャッシュ書込",
"timingInfo": "応答時間/TTFT",
"status": "ステータス",
"noData": "データなし",
"unknownProvider": "不明なプロバイダー",
"stream": "ストリーム",
"nonStream": "非ストリーム",
"totalRecords": "全 {{total}} 件",
"modelPricing": "モデル料金",
"loadPricingError": "料金データの読み込みに失敗しました",
"modelPricingDesc": "各モデルのトークンコストを設定",
"noPricingData": "料金データがありません。「追加」をクリックしてモデル料金を設定してください。",
"model": "モデル",
"displayName": "表示名",
"inputCost": "入力コスト",
"outputCost": "出力コスト",
"cacheReadCost": "キャッシュ読取",
"cacheWriteCost": "キャッシュ書込",
"deleteConfirmTitle": "削除の確認",
"deleteConfirmDesc": "このモデル料金を削除しますか?この操作は元に戻せません。",
"queryFailed": "照会に失敗しました",
"refreshUsage": "利用状況を更新",
"planUsage": "プラン利用状況",
@@ -944,5 +1020,17 @@
"errorRateLabel": "エラー率しきい値",
"errorRateExplain": "失敗しきい値に達していなくても、エラー率がこの値を超えるとサーキットブレーカーが開きます"
}
},
"streamCheck": {
"configSaved": "ヘルスチェック設定を保存しました",
"configSaveFailed": "保存に失敗しました",
"testModels": "テストモデル",
"claudeModel": "Claude モデル",
"codexModel": "Codex モデル",
"geminiModel": "Gemini モデル",
"checkParams": "チェックパラメーター",
"timeout": "タイムアウト(秒)",
"maxRetries": "最大リトライ回数",
"degradedThreshold": "劣化しきい値(ミリ秒)"
}
}
+89 -1
View File
@@ -32,7 +32,11 @@
"back": "返回",
"refresh": "刷新",
"refreshing": "刷新中...",
"notInstalled": "未安装"
"all": "全部",
"search": "查询",
"reset": "重置",
"actions": "操作",
"deleting": "删除中..."
},
"apiKeyInput": {
"placeholder": "请输入API Key",
@@ -142,6 +146,34 @@
"general": "通用",
"tabGeneral": "通用",
"tabAdvanced": "高级",
"advanced": {
"configDir": {
"title": "配置文件目录",
"description": "管理 Claude、Codex 和 Gemini 的配置存储路径"
},
"proxy": {
"title": "本地代理",
"description": "控制代理服务开关、查看状态与端口信息",
"running": "运行中",
"stopped": "已停止"
},
"modelTest": {
"title": "模型测试配置",
"description": "配置模型测试使用的默认模型和提示词"
},
"failover": {
"title": "自动故障转移",
"description": "配置故障转移队列和熔断策略"
},
"pricing": {
"title": "成本定价",
"description": "管理各模型 Token 计费规则"
},
"data": {
"title": "数据管理",
"description": "导入导出配置与备份恢复"
}
},
"language": "界面语言",
"languageHint": "切换后立即预览界面语言,保存后永久生效。",
"theme": "外观主题",
@@ -365,6 +397,50 @@
"hint": "选择预设后可继续调整下方字段。"
},
"usage": {
"title": "使用统计",
"subtitle": "查看 AI 模型的使用情况和成本统计",
"today": "24小时",
"last7days": "7天",
"last30days": "30天",
"totalRequests": "总请求数",
"totalCost": "总成本",
"cost": "成本",
"perMillion": "(每百万)",
"trends": "使用趋势",
"rangeToday": "今天 (按小时)",
"rangeLast7Days": "过去 7 天",
"rangeLast30Days": "过去 30 天",
"totalTokens": "总 Token 数",
"cacheTokens": "缓存 Token",
"requestLogs": "请求日志",
"providerStats": "Provider 统计",
"modelStats": "模型统计",
"time": "时间",
"provider": "供应商",
"billingModel": "计费模型",
"inputTokens": "输入",
"outputTokens": "输出",
"cacheReadTokens": "缓存读取",
"cacheCreationTokens": "缓存写入",
"timingInfo": "用时/首字",
"status": "状态",
"noData": "暂无数据",
"unknownProvider": "未知供应商",
"stream": "流",
"nonStream": "非流",
"totalRecords": "共 {{total}} 条记录",
"modelPricing": "模型定价",
"loadPricingError": "加载定价数据失败",
"modelPricingDesc": "配置各模型的 Token 成本",
"noPricingData": "暂无定价数据。点击\"新增\"添加模型定价配置。",
"model": "模型",
"displayName": "显示名称",
"inputCost": "输入成本",
"outputCost": "输出成本",
"cacheReadCost": "缓存读取",
"cacheWriteCost": "缓存写入",
"deleteConfirmTitle": "确认删除",
"deleteConfirmDesc": "确定要删除此模型定价配置吗?此操作无法撤销。",
"queryFailed": "查询失败",
"refreshUsage": "刷新用量",
"planUsage": "套餐用量",
@@ -944,5 +1020,17 @@
"errorRateLabel": "错误率阈值",
"errorRateExplain": "错误率超过此值时,即使未达到失败阈值也会打开熔断器"
}
},
"streamCheck": {
"configSaved": "健康检查配置已保存",
"configSaveFailed": "保存失败",
"testModels": "测试模型",
"claudeModel": "Claude 模型",
"codexModel": "Codex 模型",
"geminiModel": "Gemini 模型",
"checkParams": "检查参数",
"timeout": "超时时间(秒)",
"maxRetries": "最大重试次数",
"degradedThreshold": "降级阈值(毫秒)"
}
}