There are two complete sets of locale catalogs in this repository, and only one of them ships.
| Set |
Files |
en entries |
Imported by |
apps/web/src/lib/catalog*.ts |
13 |
213 |
apps/web/src/lib/i18n.ts — the app |
packages/i18n/src/locales/*.ts |
13 |
188 |
nothing but its own test |
packages/i18n/src/index.ts exports the machinery — flatten, createTranslator, createFormatters, LOCALES, resolveLocale — and deliberately does not export any catalog. A search for importers outside the package finds none:
$ grep -rn "i18n/src/locales\|@omm/i18n/locales" apps packages --include=*.ts --include=*.tsx | grep -v node_modules
(nothing)
So packages/i18n/src/locales/ is roughly 2,400 authored strings that no build includes and no visitor ever reads. They are not stale by a little: the two en files are already 25 keys apart, and packages/i18n/src/locales/en.ts is the one behind.
Why it matters beyond the dead weight
It is an active trap for exactly the work that found it. While fixing #69 I added the missing keys to packages/i18n/src/locales/* first, ran the tests green, and only noticed the page still rendered ⟦feed.share⟧ because the browser disagreed with the test suite. Anyone — human or agent — who greps for a catalog has a coin-flip chance of editing the copy that does not ship, and every check will agree with them.
packages/i18n/src/locales.test.ts makes that worse rather than better: ~200 lines of assertions about German, Spanish, French and Japanese strings, all of them describing catalogs the app never loads. It reads exactly like i18n coverage.
Fix shape
One catalog set. Either direction closes it:
- Delete
packages/i18n/src/locales/ and rewrite locales.test.ts to test the machinery against small inline fixtures, which is all it needs — the package's job is flatten/interpolate/resolve, not copy. The app keeps owning the copy it renders.
- Or promote them: export the catalogs from
packages/i18n, delete apps/web/src/lib/catalog*.ts, and have the app import them. This is the bigger change and only pays off if a second surface (the desktop client under apps/client) ever needs the same strings.
(1) matches how the code is actually arranged today. Whichever is chosen, the parity test added in #69 should move to sit beside whichever set survives.
There are two complete sets of locale catalogs in this repository, and only one of them ships.
enentriesapps/web/src/lib/catalog*.tsapps/web/src/lib/i18n.ts— the apppackages/i18n/src/locales/*.tspackages/i18n/src/index.tsexports the machinery —flatten,createTranslator,createFormatters,LOCALES,resolveLocale— and deliberately does not export any catalog. A search for importers outside the package finds none:So
packages/i18n/src/locales/is roughly 2,400 authored strings that no build includes and no visitor ever reads. They are not stale by a little: the twoenfiles are already 25 keys apart, andpackages/i18n/src/locales/en.tsis the one behind.Why it matters beyond the dead weight
It is an active trap for exactly the work that found it. While fixing #69 I added the missing keys to
packages/i18n/src/locales/*first, ran the tests green, and only noticed the page still rendered⟦feed.share⟧because the browser disagreed with the test suite. Anyone — human or agent — who greps for a catalog has a coin-flip chance of editing the copy that does not ship, and every check will agree with them.packages/i18n/src/locales.test.tsmakes that worse rather than better: ~200 lines of assertions about German, Spanish, French and Japanese strings, all of them describing catalogs the app never loads. It reads exactly like i18n coverage.Fix shape
One catalog set. Either direction closes it:
packages/i18n/src/locales/and rewritelocales.test.tsto test the machinery against small inline fixtures, which is all it needs — the package's job is flatten/interpolate/resolve, not copy. The app keeps owning the copy it renders.packages/i18n, deleteapps/web/src/lib/catalog*.ts, and have the app import them. This is the bigger change and only pays off if a second surface (the desktop client underapps/client) ever needs the same strings.(1) matches how the code is actually arranged today. Whichever is chosen, the parity test added in #69 should move to sit beside whichever set survives.