From 4488a54103f6c3f94affd052a5cf1ac8e2173027 Mon Sep 17 00:00:00 2001 From: gongcavalry <1793master@gmail.com> Date: Sat, 19 Sep 2026 00:10:43 +0800 Subject: [PATCH] Spell out the live turn stats instead of `3F +2.8K/-2.7K` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The status line under a running turn read `3F +2.8K/-2.7K`. Every part of it cost a decoding step: `F` for files, `+`/`-` for line direction, and the compact notation rounding both sides toward the same figure. That last one is the problem — the single comparison worth making at a glance is whether additions and deletions nearly cancel, which is how you spot a whole-file rewrite, and the formatting was the first thing to destroy it. Now reads `改了 3 个文件 · 新增 2751 行、删除 2744 行` and `0.2 token/秒`, with the same sentence as a hover hint. Line counts are formatted in full rather than compacted; the two helpers left unused by that change (`formatCompactInt`, `compactNumberFormatter`) are removed. Locale: five new keys in all ten files. English, German, French, Spanish and Portuguese use ICU plurals; CJK and Arabic stay flat. Tests: vitest 6608 passed / 453 files; eslint clean. --- src/components/message/live-turn-stats.tsx | 43 ++++++++++++---------- src/i18n/messages/ar.json | 7 +++- src/i18n/messages/de.json | 7 +++- src/i18n/messages/en.json | 7 +++- src/i18n/messages/es.json | 7 +++- src/i18n/messages/fr.json | 7 +++- src/i18n/messages/ja.json | 7 +++- src/i18n/messages/ko.json | 7 +++- src/i18n/messages/pt.json | 7 +++- src/i18n/messages/zh-CN.json | 7 +++- src/i18n/messages/zh-TW.json | 7 +++- 11 files changed, 84 insertions(+), 29 deletions(-) diff --git a/src/components/message/live-turn-stats.tsx b/src/components/message/live-turn-stats.tsx index ee52545331..fed53a7410 100644 --- a/src/components/message/live-turn-stats.tsx +++ b/src/components/message/live-turn-stats.tsx @@ -32,11 +32,6 @@ interface LiveEditStats extends LineChangeStats { files: number } -function formatCompactInt(n: number, formatter: Intl.NumberFormat): string { - if (n < 1000) return String(n) - return formatter.format(n) -} - function asObject(value: unknown): Record | null { if (!value || typeof value !== "object" || Array.isArray(value)) return null return value as Record @@ -317,14 +312,11 @@ export function LiveTurnStats({ const [elapsed, setElapsed] = useState(() => Date.now() - message.startedAt) const editStats = useMemo(() => extractLiveEditStats(message), [message]) const tps = useTokenOutputSpeed(message) - const compactNumberFormatter = useMemo( - () => - new Intl.NumberFormat(locale, { - notation: "compact", - maximumFractionDigits: 1, - }), - [locale] - ) + + // Line counts are shown in full rather than compacted: `+2.8K/-2.7K` asks the + // reader to undo the rounding before they can compare the two sides, and + // "additions nearly equal deletions" is exactly the reading that matters here. + const lineFormatter = useMemo(() => new Intl.NumberFormat(locale), [locale]) useEffect(() => { const timer = setInterval(() => { @@ -367,11 +359,24 @@ export function LiveTurnStats({ | - - - {editStats.files}F + - {formatCompactInt(editStats.additions, compactNumberFormatter)}/- - {formatCompactInt(editStats.deletions, compactNumberFormatter)} + + + {t("filesChanged", { count: editStats.files })} + · + {t("linesChanged", { + additions: lineFormatter.format(editStats.additions), + deletions: lineFormatter.format(editStats.deletions), + })} )} @@ -392,7 +397,7 @@ export function LiveTurnStats({ aria-label={t("outputSpeedAria")} className="h-3 w-3 shrink-0" /> - {tps.toFixed(1)} tok/s + {t("outputSpeedValue", { value: tps.toFixed(1) })} )} diff --git a/src/i18n/messages/ar.json b/src/i18n/messages/ar.json index 47ec2f0108..51c43ae46b 100644 --- a/src/i18n/messages/ar.json +++ b/src/i18n/messages/ar.json @@ -3431,7 +3431,12 @@ "elapsedMinutes": "{value}د", "elapsedSeconds": "{value}ث", "outputSpeedAria": "السرعة التقديرية للإخراج", - "outputSpeedTooltip": "السرعة التقديرية للإخراج (نص + تفكير)" + "outputSpeedTooltip": "السرعة التقديرية للإخراج (نص + تفكير)", + "filesChanged": "{count} ملف مُعدَّل", + "linesChanged": "إضافة {additions} سطر، حذف {deletions} سطر", + "editStatsAria": "تغييرات هذه الجولة", + "editStatsTooltip": "غيّرت هذه الجولة {files} ملف — إضافة {additions} سطر، حذف {deletions} سطر", + "outputSpeedValue": "{value} رمز/ثانية" }, "jsonTree": { "viewRaw": "عرض JSON الخام", diff --git a/src/i18n/messages/de.json b/src/i18n/messages/de.json index 013422a368..62a9a7f03c 100644 --- a/src/i18n/messages/de.json +++ b/src/i18n/messages/de.json @@ -3431,7 +3431,12 @@ "elapsedMinutes": "{value} Min", "elapsedSeconds": "{value} Sek", "outputSpeedAria": "Geschätzte Ausgabegeschwindigkeit", - "outputSpeedTooltip": "Geschätzte Ausgabegeschwindigkeit (Text + Denken)" + "outputSpeedTooltip": "Geschätzte Ausgabegeschwindigkeit (Text + Denken)", + "filesChanged": "{count, plural, one {# Datei geändert} other {# Dateien geändert}}", + "linesChanged": "{additions} Zeilen ergänzt, {deletions} entfernt", + "editStatsAria": "Änderungen in diesem Durchlauf", + "editStatsTooltip": "{files, plural, one {# Datei} other {# Dateien}} in diesem Durchlauf geändert: {additions} Zeilen ergänzt, {deletions} entfernt", + "outputSpeedValue": "{value} Tokens/s" }, "jsonTree": { "viewRaw": "Rohes JSON anzeigen", diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index d6ff59ba5f..23bae0f60a 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -3431,7 +3431,12 @@ "elapsedMinutes": "{value}m", "elapsedSeconds": "{value}s", "outputSpeedAria": "Estimated output speed", - "outputSpeedTooltip": "Estimated output speed (text + thinking)" + "outputSpeedTooltip": "Estimated output speed (text + thinking)", + "filesChanged": "{count, plural, one {# file changed} other {# files changed}}", + "linesChanged": "{additions} lines added, {deletions} removed", + "editStatsAria": "This turn's edits", + "editStatsTooltip": "{files, plural, one {# file changed} other {# files changed}} this turn — {additions} lines added, {deletions} removed", + "outputSpeedValue": "{value} tokens/sec" }, "jsonTree": { "viewRaw": "Show raw JSON", diff --git a/src/i18n/messages/es.json b/src/i18n/messages/es.json index f27b0b21fd..34c20003bc 100644 --- a/src/i18n/messages/es.json +++ b/src/i18n/messages/es.json @@ -3431,7 +3431,12 @@ "elapsedMinutes": "{value} min", "elapsedSeconds": "{value} s", "outputSpeedAria": "Velocidad de salida estimada", - "outputSpeedTooltip": "Velocidad de salida estimada (texto + razonamiento)" + "outputSpeedTooltip": "Velocidad de salida estimada (texto + razonamiento)", + "filesChanged": "{count, plural, one {# archivo modificado} other {# archivos modificados}}", + "linesChanged": "{additions} líneas añadidas, {deletions} eliminadas", + "editStatsAria": "Cambios de este turno", + "editStatsTooltip": "{files, plural, one {# archivo} other {# archivos}} modificados en este turno: {additions} líneas añadidas, {deletions} eliminadas", + "outputSpeedValue": "{value} tokens/s" }, "jsonTree": { "viewRaw": "Ver JSON sin formato", diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index 00005a02e1..af4d92c8a6 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -3431,7 +3431,12 @@ "elapsedMinutes": "{value} min", "elapsedSeconds": "{value} s", "outputSpeedAria": "Vitesse de sortie estimée", - "outputSpeedTooltip": "Vitesse de sortie estimée (texte + raisonnement)" + "outputSpeedTooltip": "Vitesse de sortie estimée (texte + raisonnement)", + "filesChanged": "{count, plural, one {# fichier modifié} other {# fichiers modifiés}}", + "linesChanged": "{additions} lignes ajoutées, {deletions} supprimées", + "editStatsAria": "Modifications de ce tour", + "editStatsTooltip": "{files, plural, one {# fichier} other {# fichiers}} modifiés ce tour : {additions} lignes ajoutées, {deletions} supprimées", + "outputSpeedValue": "{value} jetons/s" }, "jsonTree": { "viewRaw": "Afficher le JSON brut", diff --git a/src/i18n/messages/ja.json b/src/i18n/messages/ja.json index 28e0fc3397..d60dbbbd6f 100644 --- a/src/i18n/messages/ja.json +++ b/src/i18n/messages/ja.json @@ -3431,7 +3431,12 @@ "elapsedMinutes": "{value}分", "elapsedSeconds": "{value}秒", "outputSpeedAria": "推定出力速度", - "outputSpeedTooltip": "推定出力速度(テキスト + 思考)" + "outputSpeedTooltip": "推定出力速度(テキスト + 思考)", + "filesChanged": "{count} 個のファイルを変更", + "linesChanged": "{additions} 行追加、{deletions} 行削除", + "editStatsAria": "このターンの変更", + "editStatsTooltip": "このターンは {files} 個のファイルを変更 — {additions} 行追加、{deletions} 行削除", + "outputSpeedValue": "{value} token/秒" }, "jsonTree": { "viewRaw": "生の JSON を表示", diff --git a/src/i18n/messages/ko.json b/src/i18n/messages/ko.json index 418e1b7dfa..792bc4e240 100644 --- a/src/i18n/messages/ko.json +++ b/src/i18n/messages/ko.json @@ -3431,7 +3431,12 @@ "elapsedMinutes": "{value}분", "elapsedSeconds": "{value}초", "outputSpeedAria": "예상 출력 속도", - "outputSpeedTooltip": "예상 출력 속도(텍스트 + 추론)" + "outputSpeedTooltip": "예상 출력 속도(텍스트 + 추론)", + "filesChanged": "{count}개 파일 수정", + "linesChanged": "{additions}줄 추가, {deletions}줄 삭제", + "editStatsAria": "이번 턴 변경", + "editStatsTooltip": "이번 턴에 {files}개 파일 수정 — {additions}줄 추가, {deletions}줄 삭제", + "outputSpeedValue": "{value} token/초" }, "jsonTree": { "viewRaw": "원본 JSON 보기", diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json index 0b275b620c..31ea7b1c7e 100644 --- a/src/i18n/messages/pt.json +++ b/src/i18n/messages/pt.json @@ -3431,7 +3431,12 @@ "elapsedMinutes": "{value} min", "elapsedSeconds": "{value} s", "outputSpeedAria": "Velocidade de saída estimada", - "outputSpeedTooltip": "Velocidade de saída estimada (texto + raciocínio)" + "outputSpeedTooltip": "Velocidade de saída estimada (texto + raciocínio)", + "filesChanged": "{count, plural, one {# arquivo alterado} other {# arquivos alterados}}", + "linesChanged": "{additions} linhas adicionadas, {deletions} removidas", + "editStatsAria": "Alterações desta rodada", + "editStatsTooltip": "{files, plural, one {# arquivo} other {# arquivos}} alterados nesta rodada: {additions} linhas adicionadas, {deletions} removidas", + "outputSpeedValue": "{value} tokens/s" }, "jsonTree": { "viewRaw": "Ver JSON bruto", diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json index 1dee2f0027..a3d87f51fa 100644 --- a/src/i18n/messages/zh-CN.json +++ b/src/i18n/messages/zh-CN.json @@ -3431,7 +3431,12 @@ "elapsedMinutes": "{value} 分钟", "elapsedSeconds": "{value} 秒", "outputSpeedAria": "估算输出速度", - "outputSpeedTooltip": "估算输出速度(正文 + 思考)" + "outputSpeedTooltip": "估算输出速度(正文 + 思考)", + "filesChanged": "改了 {count} 个文件", + "linesChanged": "新增 {additions} 行、删除 {deletions} 行", + "editStatsAria": "本轮改动", + "editStatsTooltip": "本轮改了 {files} 个文件:新增 {additions} 行、删除 {deletions} 行", + "outputSpeedValue": "{value} token/秒" }, "jsonTree": { "viewRaw": "查看原始 JSON", diff --git a/src/i18n/messages/zh-TW.json b/src/i18n/messages/zh-TW.json index a76f71d746..46990816d5 100644 --- a/src/i18n/messages/zh-TW.json +++ b/src/i18n/messages/zh-TW.json @@ -3431,7 +3431,12 @@ "elapsedMinutes": "{value} 分鐘", "elapsedSeconds": "{value} 秒", "outputSpeedAria": "估算輸出速度", - "outputSpeedTooltip": "估算輸出速度(正文 + 思考)" + "outputSpeedTooltip": "估算輸出速度(正文 + 思考)", + "filesChanged": "改了 {count} 個檔案", + "linesChanged": "新增 {additions} 行、刪除 {deletions} 行", + "editStatsAria": "本輪改動", + "editStatsTooltip": "本輪改了 {files} 個檔案:新增 {additions} 行、刪除 {deletions} 行", + "outputSpeedValue": "{value} token/秒" }, "jsonTree": { "viewRaw": "檢視原始 JSON",