From 810665bb4196bd27e8623c7df96d109adef77fdc Mon Sep 17 00:00:00 2001 From: Maximilian Noller Date: Mon, 13 Apr 2026 02:31:38 +0200 Subject: [PATCH 1/2] fix: replace hardcoded call pluralization with pluralize() helper Fixes grammar bugs where counts like "1 calls this month" were rendered instead of "1 call this month". Adds a shared pluralize() utility to console/src/lib/format.ts and applies it to all call-count strings in dashboard.tsx and models.tsx. Includes unit tests for the new helper. --- console/src/lib/format.test.ts | 26 ++++++++++++++++++++++++++ console/src/lib/format.ts | 8 ++++++++ console/src/routes/dashboard.tsx | 7 ++++--- console/src/routes/models.tsx | 7 ++++--- 4 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 console/src/lib/format.test.ts diff --git a/console/src/lib/format.test.ts b/console/src/lib/format.test.ts new file mode 100644 index 00000000..34c10a4a --- /dev/null +++ b/console/src/lib/format.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, it } from 'vitest'; +import { pluralize } from './format'; + +describe('pluralize', () => { + it('returns singular when n is 1', () => { + expect(pluralize(1, 'call')).toBe('1 call'); + }); + + it('returns plural when n is 0', () => { + expect(pluralize(0, 'call')).toBe('0 calls'); + }); + + it('returns plural when n is greater than 1', () => { + expect(pluralize(2, 'call')).toBe('2 calls'); + expect(pluralize(100, 'call')).toBe('100 calls'); + }); + + it('uses a custom plural form when provided', () => { + expect(pluralize(1, 'model', 'models')).toBe('1 model'); + expect(pluralize(3, 'model', 'models')).toBe('3 models'); + }); + + it('handles negative numbers as plural', () => { + expect(pluralize(-1, 'call')).toBe('-1 calls'); + }); +}); diff --git a/console/src/lib/format.ts b/console/src/lib/format.ts index 853b3a02..8e31910a 100644 --- a/console/src/lib/format.ts +++ b/console/src/lib/format.ts @@ -57,6 +57,14 @@ export function formatUptime(totalSeconds: number): string { return parts.join(' '); } +export function pluralize( + n: number, + word: string, + plural = `${word}s`, +): string { + return `${n} ${n === 1 ? word : plural}`; +} + export function parseStringList(value: string): string[] { return value .split(/[\n,]/g) diff --git a/console/src/routes/dashboard.tsx b/console/src/routes/dashboard.tsx index 64ddce2d..7e8d92db 100644 --- a/console/src/routes/dashboard.tsx +++ b/console/src/routes/dashboard.tsx @@ -16,6 +16,7 @@ import { formatTokenBreakdown, formatUptime, formatUsd, + pluralize, } from '../lib/format'; import { compareDateTime, compareNumber, compareText } from '../lib/sort'; @@ -170,7 +171,7 @@ export function DashboardPage() { {formatUsd(overview.usage.daily.totalCostUsd)} across{' '} - {overview.usage.daily.callCount} calls + {pluralize(overview.usage.daily.callCount, 'call')}
@@ -186,7 +187,7 @@ export function DashboardPage() { {formatUsd(overview.usage.monthly.totalCostUsd)} across{' '} - {overview.usage.monthly.callCount} calls + {pluralize(overview.usage.monthly.callCount, 'call')}
@@ -205,7 +206,7 @@ export function DashboardPage() { inputTokens: row.totalInputTokens ?? 0, outputTokens: row.totalOutputTokens ?? 0, })}{' '} - · {row.callCount} calls this month + · {pluralize(row.callCount, 'call')} this month {formatUsd(row.totalCostUsd)} diff --git a/console/src/routes/models.tsx b/console/src/routes/models.tsx index 50789664..3a2c4f72 100644 --- a/console/src/routes/models.tsx +++ b/console/src/routes/models.tsx @@ -15,6 +15,7 @@ import { formatRelativeTime, formatTokenBreakdown, formatUsd, + pluralize, } from '../lib/format'; import { compareNumber, compareText } from '../lib/sort'; @@ -308,7 +309,7 @@ export function ModelsPage() { {modelsQuery.isLoading ? (
Loading model catalog...
@@ -376,7 +377,7 @@ export function ModelsPage() { {formatUsd(model.usageMonthly.totalCostUsd)} ·{' '} - {model.usageMonthly.callCount} calls + {pluralize(model.usageMonthly.callCount, 'call')} ) : ( @@ -421,7 +422,7 @@ export function ModelsPage() { inputTokens: model.usageDaily.totalInputTokens ?? 0, outputTokens: model.usageDaily.totalOutputTokens ?? 0, })}{' '} - · {model.usageDaily.callCount} calls today + · {pluralize(model.usageDaily.callCount, 'call')} today {formatUsd(model.usageDaily.totalCostUsd ?? 0)} From e846949838ef19dbeba1330485ae6cc6f8ea2a1a Mon Sep 17 00:00:00 2001 From: Maximilian Noller Date: Mon, 13 Apr 2026 02:34:30 +0200 Subject: [PATCH 2/2] simplify: remove duplicate pluralize from channels-catalog, improve test channels-catalog.ts had its own local pluralize() with identical signature and implementation. Now imports from lib/format.ts instead. Also replaced the vacuous custom-plural test case (which passed a default- equivalent value) with an irregular plural to actually exercise the branch. --- console/src/lib/format.test.ts | 6 +++--- console/src/routes/channels-catalog.ts | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/console/src/lib/format.test.ts b/console/src/lib/format.test.ts index 34c10a4a..2e7f7bfc 100644 --- a/console/src/lib/format.test.ts +++ b/console/src/lib/format.test.ts @@ -15,9 +15,9 @@ describe('pluralize', () => { expect(pluralize(100, 'call')).toBe('100 calls'); }); - it('uses a custom plural form when provided', () => { - expect(pluralize(1, 'model', 'models')).toBe('1 model'); - expect(pluralize(3, 'model', 'models')).toBe('3 models'); + it('uses a custom plural form for irregular plurals', () => { + expect(pluralize(1, 'person', 'people')).toBe('1 person'); + expect(pluralize(3, 'person', 'people')).toBe('3 people'); }); it('handles negative numbers as plural', () => { diff --git a/console/src/routes/channels-catalog.ts b/console/src/routes/channels-catalog.ts index 22333297..886babbd 100644 --- a/console/src/routes/channels-catalog.ts +++ b/console/src/routes/channels-catalog.ts @@ -1,4 +1,5 @@ import type { AdminConfig } from '../api/types'; +import { pluralize } from '../lib/format'; export type ChannelKind = | 'discord' @@ -51,9 +52,6 @@ export function countTeamsOverrides(config: AdminConfig): number { }, 0); } -function pluralize(count: number, singular: string, plural = `${singular}s`) { - return `${count} ${count === 1 ? singular : plural}`; -} function describeDiscord( config: AdminConfig,