fix(i18n): use single-brace {count} in organisations count labels #275

Merged
james merged 1 commit from 272-orgs-count-interpolation into main 2026-06-24 12:46:30 +00:00
Owner

Summary

Four catalog entries (linkCountLabel_one|other, keyPeopleCountLabel_one|other under network.organizationsScreen in packages/i18n/messages/en.json) used i18next's default {{count}} double-brace placeholder. The universal client configures i18next with interpolation: { prefix: "{", suffix: "}" } (single-brace, to match next-intl and the rest of the catalog), so {{count}} was passing through literally. The Organizations tab rendered {{count}} links and {{count}} key people instead of the actual counts.

Fix

Switch the four placeholders to {count}. No client code changes — t("organizationsScreen.linkCountLabel", { count: o.linkCount }) in apps/client/app/(app)/network.tsx already passes count correctly, and pluralization (_one / _other) keeps working because that's a key-suffix convention, not a placeholder.

No API-side impact — next-intl does not read these keys.

Catalog-syntax audit

Before: 37 single-brace {var} placeholders, 4 double-brace {{count}} stragglers (all introduced in #28).
After: 0 double-brace placeholders remain (grep '{{' packages/i18n/messages/*.json is clean).

Other count-style keys in the catalog (e.g. experience.jobs.positionsCount_one: "{count} position") already use the correct shape — this PR brings the orgs keys in line.

Test plan

  • pnpm -F @carol/client typecheck
  • pnpm -F @carol/client lint
  • pnpm -F @carol/client test (106/106 pass)
  • pnpm -F @carol/client export:web builds clean; grep of dist/ confirms linkCountLabel_one:"{count} link" etc. ship in the bundle and no {{count}} remains
  • Visual: open /network → Organizations tab on an instance with tracked orgs; each row shows e.g. 3 links and 2 key people, not literal placeholders

Closes #272.

## Summary Four catalog entries (`linkCountLabel_one|other`, `keyPeopleCountLabel_one|other` under `network.organizationsScreen` in `packages/i18n/messages/en.json`) used i18next's default `{{count}}` double-brace placeholder. The universal client configures i18next with `interpolation: { prefix: "{", suffix: "}" }` (single-brace, to match next-intl and the rest of the catalog), so `{{count}}` was passing through literally. The Organizations tab rendered `{{count}} links` and `{{count}} key people` instead of the actual counts. ## Fix Switch the four placeholders to `{count}`. No client code changes — `t("organizationsScreen.linkCountLabel", { count: o.linkCount })` in `apps/client/app/(app)/network.tsx` already passes `count` correctly, and pluralization (`_one` / `_other`) keeps working because that's a key-suffix convention, not a placeholder. No API-side impact — `next-intl` does not read these keys. ## Catalog-syntax audit Before: 37 single-brace `{var}` placeholders, 4 double-brace `{{count}}` stragglers (all introduced in #28). After: 0 double-brace placeholders remain (`grep '{{' packages/i18n/messages/*.json` is clean). Other count-style keys in the catalog (e.g. `experience.jobs.positionsCount_one: "{count} position"`) already use the correct shape — this PR brings the orgs keys in line. ## Test plan - [x] `pnpm -F @carol/client typecheck` - [x] `pnpm -F @carol/client lint` - [x] `pnpm -F @carol/client test` (106/106 pass) - [x] `pnpm -F @carol/client export:web` builds clean; grep of `dist/` confirms `linkCountLabel_one:"{count} link"` etc. ship in the bundle and no `{{count}}` remains - [ ] Visual: open `/network` → Organizations tab on an instance with tracked orgs; each row shows e.g. `3 links` and `2 key people`, not literal placeholders Closes #272.
fix(i18n): use single-brace {count} in organisations count labels (#272)
Some checks failed
Commits / Conventional Commits (pull_request) Successful in 6s
PR / OpenAPI (pull_request) Successful in 2m17s
PR / Lint (pull_request) Successful in 3m24s
PR / Static analysis (pull_request) Successful in 2m55s
PR / Client (web export smoke) (pull_request) Successful in 2m50s
PR / Build (pull_request) Successful in 2m59s
PR / pnpm audit (pull_request) Successful in 1m26s
PR / OSV-Scanner (pull_request) Successful in 1m17s
PR / Package age policy (soft) (pull_request) Successful in 28s
Secrets / gitleaks (pull_request) Successful in 41s
PR / Typecheck (pull_request) Successful in 4m36s
PR / Test (sqlite) (pull_request) Successful in 3m8s
PR / Test (postgres) (pull_request) Failing after 4m12s
PR / Coverage (soft) (pull_request) Successful in 2m34s
PR / Trivy (image) (pull_request) Successful in 3m42s
87f39dfa9e
The four `linkCountLabel`/`keyPeopleCountLabel` entries used i18next's
default `{{count}}` syntax, but the universal client configures i18next
with `interpolation: { prefix: "{", suffix: "}" }` so the catalog matches
next-intl's single-brace ICU shape (and the other 37 placeholders in the
catalog). Result: the Organizations tab rendered `{{count}} links` and
`{{count}} key people` literally instead of interpolating the count.

Switch the four placeholders to `{count}`. No client code changes — the
`t()` call already passes `count`. Pluralization (`_one`/`_other`) keeps
working.

Closes #272.

📊 Test coverage

Patch coverage: no testable lines changed.

Overall (app/, lib/, db/, excluding UI per ADR-0019):

Metric Value Soft target
Lines 81.6% ≥ 50%
Branches 72.8% ⚠️ ≥ 75%
Functions 91.1% informational

Soft thresholds per ADR-0019. Coverage is informational and does not block merge.

<!-- coverage-comment --> ## 📊 Test coverage **Patch coverage:** no testable lines changed. **Overall** (`app/`, `lib/`, `db/`, excluding UI per ADR-0019): | Metric | Value | Soft target | |---|---|---| | Lines | 81.6% ✅ | ≥ 50% | | Branches | 72.8% ⚠️ | ≥ 75% | | Functions | 91.1% | informational | Soft thresholds per [ADR-0019](docs/adr/0019-coverage-soft-targets.md). Coverage is informational and does not block merge.
james merged commit ea91b4b712 into main 2026-06-24 12:46:30 +00:00
james deleted branch 272-orgs-count-interpolation 2026-06-24 12:46:31 +00:00
Sign in to join this conversation.
No description provided.