feat(stats): rename all token display text to words

Replace every user-facing "token(s)" label, tooltip, and message in the
stats UI with "words" so the terminology is consistent and friendlier
(e.g. "Words Seen", "word occurrences", "3.4 / 100 words", "Words Today").

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-19 23:48:37 -07:00
parent 3995c396f8
commit 4a01cebca6
8 changed files with 21 additions and 21 deletions

View File

@@ -68,10 +68,10 @@ export function AnimeOverviewStats({ detail, knownWordsSummary }: AnimeOverviewS
tooltip="Number of completed episodes for this anime" tooltip="Number of completed episodes for this anime"
/> />
<Metric <Metric
label="Tokens Seen" label="Words Seen"
value={formatNumber(detail.totalTokensSeen)} value={formatNumber(detail.totalTokensSeen)}
color="text-ctp-mauve" color="text-ctp-mauve"
tooltip="Total token occurrences across all sessions" tooltip="Total word occurrences across all sessions"
/> />
</div> </div>
@@ -94,7 +94,7 @@ export function AnimeOverviewStats({ detail, knownWordsSummary }: AnimeOverviewS
label="Lookup Rate" label="Lookup Rate"
value={lookupRate.shortValue} value={lookupRate.shortValue}
color="text-ctp-sapphire" color="text-ctp-sapphire"
tooltip="Yomitan lookups per 100 tokens seen" tooltip="Yomitan lookups per 100 words seen"
/> />
) : ( ) : (
<Metric <Metric
@@ -116,7 +116,7 @@ export function AnimeOverviewStats({ detail, knownWordsSummary }: AnimeOverviewS
label="Known Words" label="Known Words"
value="—" value="—"
color="text-ctp-overlay2" color="text-ctp-overlay2"
tooltip="No token data available yet" tooltip="No word data available yet"
/> />
)} )}
</div> </div>

View File

@@ -86,7 +86,7 @@ export function EpisodeDetail({ videoId, onSessionDeleted }: EpisodeDetailProps)
<span className="text-ctp-blue">{formatDuration(s.activeWatchedMs)}</span> <span className="text-ctp-blue">{formatDuration(s.activeWatchedMs)}</span>
<span className="text-ctp-cards-mined">{formatNumber(s.cardsMined)} cards</span> <span className="text-ctp-cards-mined">{formatNumber(s.cardsMined)} cards</span>
<span className="text-ctp-peach"> <span className="text-ctp-peach">
{formatNumber(getSessionDisplayWordCount(s))} tokens {formatNumber(getSessionDisplayWordCount(s))} words
</span> </span>
<span className="text-ctp-green">{formatNumber(s.knownWordsSeen)} known words</span> <span className="text-ctp-green">{formatNumber(s.knownWordsSeen)} known words</span>
<button <button

View File

@@ -62,7 +62,7 @@ export function MediaHeader({ detail, initialKnownWordsSummary = null }: MediaHe
</div> </div>
<div> <div>
<div className="text-ctp-mauve font-medium">{formatNumber(detail.totalTokensSeen)}</div> <div className="text-ctp-mauve font-medium">{formatNumber(detail.totalTokensSeen)}</div>
<div className="text-xs text-ctp-overlay2">token occurrences</div> <div className="text-xs text-ctp-overlay2">word occurrences</div>
</div> </div>
<div> <div>
<div className="text-ctp-lavender font-medium"> <div className="text-ctp-lavender font-medium">
@@ -95,7 +95,7 @@ export function MediaHeader({ detail, initialKnownWordsSummary = null }: MediaHe
) : ( ) : (
<div> <div>
<div className="text-ctp-peach font-medium">{formatPercent(knownTokenRate)}</div> <div className="text-ctp-peach font-medium">{formatPercent(knownTokenRate)}</div>
<div className="text-xs text-ctp-overlay2">known token match rate</div> <div className="text-xs text-ctp-overlay2">known word match rate</div>
</div> </div>
)} )}
<div> <div>

View File

@@ -174,7 +174,7 @@ function SessionItem({
<div className="text-ctp-mauve font-medium font-mono tabular-nums"> <div className="text-ctp-mauve font-medium font-mono tabular-nums">
{formatNumber(displayWordCount)} {formatNumber(displayWordCount)}
</div> </div>
<div className="text-ctp-overlay2">tokens</div> <div className="text-ctp-overlay2">words</div>
</div> </div>
<div> <div>
<div className="text-ctp-green font-medium font-mono tabular-nums"> <div className="text-ctp-green font-medium font-mono tabular-nums">
@@ -265,7 +265,7 @@ function AnimeGroupRow({
<div className="text-ctp-mauve font-medium font-mono tabular-nums"> <div className="text-ctp-mauve font-medium font-mono tabular-nums">
{formatNumber(group.totalWords)} {formatNumber(group.totalWords)}
</div> </div>
<div className="text-ctp-overlay2">tokens</div> <div className="text-ctp-overlay2">words</div>
</div> </div>
<div> <div>
<div className="text-ctp-green font-medium font-mono tabular-nums"> <div className="text-ctp-green font-medium font-mono tabular-nums">
@@ -340,7 +340,7 @@ function AnimeGroupRow({
<div className="text-ctp-mauve font-medium font-mono tabular-nums"> <div className="text-ctp-mauve font-medium font-mono tabular-nums">
{formatNumber(getSessionDisplayWordCount(s))} {formatNumber(getSessionDisplayWordCount(s))}
</div> </div>
<div className="text-ctp-overlay2">tokens</div> <div className="text-ctp-overlay2">words</div>
</div> </div>
<div> <div>
<div className="text-ctp-green font-medium font-mono tabular-nums"> <div className="text-ctp-green font-medium font-mono tabular-nums">

View File

@@ -95,7 +95,7 @@ export function TrackingSnapshot({
</div> </div>
</div> </div>
</Tooltip> </Tooltip>
<Tooltip text="Lifetime Yomitan lookups normalized by total tokens seen"> <Tooltip text="Lifetime Yomitan lookups normalized by total words seen">
<div className="rounded-lg bg-ctp-surface1/60 p-3"> <div className="rounded-lg bg-ctp-surface1/60 p-3">
<div className="text-xs uppercase tracking-wide text-ctp-overlay2">Lookup Rate</div> <div className="text-xs uppercase tracking-wide text-ctp-overlay2">Lookup Rate</div>
<div className="mt-1 text-xl font-semibold font-mono tabular-nums text-ctp-flamingo"> <div className="mt-1 text-xl font-semibold font-mono tabular-nums text-ctp-flamingo">
@@ -103,9 +103,9 @@ export function TrackingSnapshot({
</div> </div>
</div> </div>
</Tooltip> </Tooltip>
<Tooltip text="Total token occurrences encountered in today's sessions"> <Tooltip text="Total word occurrences encountered in today's sessions">
<div className="rounded-lg bg-ctp-surface1/60 p-3"> <div className="rounded-lg bg-ctp-surface1/60 p-3">
<div className="text-xs uppercase tracking-wide text-ctp-overlay2">Tokens Today</div> <div className="text-xs uppercase tracking-wide text-ctp-overlay2">Words Today</div>
<div className="mt-1 text-xl font-semibold font-mono tabular-nums text-ctp-sky"> <div className="mt-1 text-xl font-semibold font-mono tabular-nums text-ctp-sky">
{formatNumber(summary.todayTokens)} {formatNumber(summary.todayTokens)}
</div> </div>

View File

@@ -333,7 +333,7 @@ function RatioView({
} }
if (chartData.length === 0) { if (chartData.length === 0) {
return <div className="text-ctp-overlay2 text-xs p-2">No token data for this session.</div>; return <div className="text-ctp-overlay2 text-xs p-2">No word data for this session.</div>;
} }
const tsMin = chartData[0]!.tsMs; const tsMin = chartData[0]!.tsMs;
@@ -522,7 +522,7 @@ function RatioView({
{/* ── Bottom: Token accumulation sparkline ── */} {/* ── Bottom: Token accumulation sparkline ── */}
<div className="flex items-center gap-2 border-t border-ctp-surface1 pt-1"> <div className="flex items-center gap-2 border-t border-ctp-surface1 pt-1">
<span className="text-[9px] text-ctp-overlay0 whitespace-nowrap">total tokens</span> <span className="text-[9px] text-ctp-overlay0 whitespace-nowrap">total words</span>
<div className="flex-1 h-[28px]"> <div className="flex-1 h-[28px]">
<ResponsiveContainer width="100%" height={28}> <ResponsiveContainer width="100%" height={28}>
<LineChart data={sparkData}> <LineChart data={sparkData}>
@@ -608,7 +608,7 @@ function FallbackView({
} }
if (chartData.length === 0) { if (chartData.length === 0) {
return <div className="text-ctp-overlay2 text-xs p-2">No token data for this session.</div>; return <div className="text-ctp-overlay2 text-xs p-2">No word data for this session.</div>;
} }
const tsMin = chartData[0]!.tsMs; const tsMin = chartData[0]!.tsMs;
@@ -654,7 +654,7 @@ function FallbackView({
<Tooltip <Tooltip
contentStyle={tooltipStyle} contentStyle={tooltipStyle}
labelFormatter={formatTime} labelFormatter={formatTime}
formatter={(value: number) => [`${value.toLocaleString()}`, 'Total tokens']} formatter={(value: number) => [`${value.toLocaleString()}`, 'Total words']}
/> />
{pauseRegions.map((r, i) => ( {pauseRegions.map((r, i) => (
@@ -711,7 +711,7 @@ function FallbackView({
strokeWidth={1.5} strokeWidth={1.5}
dot={false} dot={false}
activeDot={{ r: 3, fill: '#8aadf4', stroke: '#1e2030', strokeWidth: 1 }} activeDot={{ r: 3, fill: '#8aadf4', stroke: '#1e2030', strokeWidth: 1 }}
name="Total tokens" name="Total words"
type="monotone" type="monotone"
isAnimationActive={false} isAnimationActive={false}
/> />

View File

@@ -96,7 +96,7 @@ export function SessionRow({
<div className="text-ctp-mauve font-medium font-mono tabular-nums"> <div className="text-ctp-mauve font-medium font-mono tabular-nums">
{formatNumber(displayWordCount)} {formatNumber(displayWordCount)}
</div> </div>
<div className="text-ctp-overlay2">tokens</div> <div className="text-ctp-overlay2">words</div>
</div> </div>
<div> <div>
<div className="text-ctp-green font-medium font-mono tabular-nums"> <div className="text-ctp-green font-medium font-mono tabular-nums">

View File

@@ -15,8 +15,8 @@ export function buildLookupRateDisplay(
} }
const per100 = ((Math.max(0, yomitanLookupCount) / tokensSeen) * 100).toFixed(1); const per100 = ((Math.max(0, yomitanLookupCount) / tokensSeen) * 100).toFixed(1);
return { return {
shortValue: `${per100} / 100 tokens`, shortValue: `${per100} / 100 words`,
longValue: `${per100} lookups per 100 tokens`, longValue: `${per100} lookups per 100 words`,
}; };
} }