[fix(web)] localize copied task-stats line instead of hardcoded Chinese (#8)

This commit is contained in:
Zhang Jason authored and GitHub committed 2026-07-22 22:06:45 +08:00
1 parent 81d8c0045c
commit 1425b2fb5f
5 files changed
+104 -29

No files matched your search

@@ -71,7 +71,16 @@ export function TaskStatsLine({
const copy = () => {
const text =
assistantText?.trim() || stats === null ? (assistantText ?? "") : formatTaskStats(stats);
assistantText?.trim() || stats === null
? (assistantText ?? "")
: formatTaskStats(stats, {
stats: S.chat.statsLabel,
input: S.chat.statInput,
cached: S.chat.statCached,
output: S.chat.statOutput,
parenOpen: S.chat.statParenOpen,
parenClose: S.chat.statParenClose,
});
void navigator.clipboard?.writeText(text).then(() => {
setCopied(true);
setTimeout(() => setCopied(false), 1500);
+22 -5
View File
@@ -287,17 +287,34 @@ export function endTask(t: TaskStatsTracker, elapsedMs: number): TaskStats | nul
return stats;
}
/** Localized labels for {@link formatTaskStats} (supplied by the view layer's active dictionary). */
export interface TaskStatsLabels {
/** Row prefix, e.g. "Stats" / "统计信息". */
stats: string;
/** Input-tokens label, e.g. "Input tokens" / "输入 tokens". */
input: string;
/** Cached-amount label, e.g. "cached" / "已缓存". */
cached: string;
/** Output-tokens label, e.g. "Output tokens" / "输出 tokens". */
output: string;
/** Opening wrapper before the cached amount — keeps per-locale typography (e.g. " (" / "("). */
parenOpen: string;
/** Closing wrapper after the cached amount (e.g. ")" / ")"). */
parenClose: string;
}
/**
* Stats row text (copy fallback / used when there's no body text): same basis as the stats row —
* this round's usage "input tokens (including cached amount) · output tokens · output TPS", e.g.
* `[统计信息] 输入 tokens 4k(已缓存 3k) · 输出 tokens 1.2k · 42.5 tok/s`; label can be overridden
* per UI locale.
* `[Stats] Input tokens 4k (cached 3k) · Output tokens 1.2k · 42.5 tok/s`. Labels (including the
* parenthesis wrappers) come from the caller's active locale dictionary, so the copied text keeps
* per-locale typography — ASCII `(…)` in English, fullwidth `(…)` in Chinese.
*/
export function formatTaskStats(s: TaskStats, label = "统计信息"): string {
export function formatTaskStats(s: TaskStats, labels: TaskStatsLabels): string {
const b = s.tokensByBucket;
return (
`[${label}] 输入 tokens ${humanizeTokens(b.cacheRead + b.cacheWrite)}(已缓存 ${humanizeTokens(b.cacheRead)})` +
` · 输出 tokens ${humanizeTokens(b.output)}` +
`[${labels.stats}] ${labels.input} ${humanizeTokens(b.cacheRead + b.cacheWrite)}${labels.parenOpen}${labels.cached} ${humanizeTokens(b.cacheRead)}${labels.parenClose}` +
` · ${labels.output} ${humanizeTokens(b.output)}` +
` · ${formatTps(s.outputTps)}`
);
}
+4
View File
@@ -609,8 +609,12 @@ When done, open index.html in a browser and self-test once.`,
statCost: "Cost",
statElapsed: "Elapsed",
statInput: "Input tokens",
statCached: "cached",
statOutput: "Output tokens",
statTps: "Output TPS",
/** Copied-stats-line parenthesis wrappers around the cached amount (ASCII with a leading space for en). */
statParenOpen: " (",
statParenClose: ")",
noSessions: "No Sessions yet",
emptyStream: "Send a message to start the conversation",
historyLoadFailed: "Failed to load history",
+4
View File
@@ -589,8 +589,12 @@ Penguin 视觉风格(见 web-design 技能),深色/浅色主题(<html da
statCost: "成本",
statElapsed: "用时",
statInput: "输入 tokens",
statCached: "已缓存",
statOutput: "输出 tokens",
statTps: "输出 TPS",
/** Copied-stats-line parenthesis wrappers around the cached amount (fullwidth for zh typography). */
statParenOpen: "(",
statParenClose: ")",
noSessions: "还没有 Session",
emptyStream: "发送一条消息开始对话",
historyLoadFailed: "历史消息加载失败",