Files
ihasmail/CLAUDE.md
T
jcoffey-dev 0ebdb38a98 Limit CLAUDE.md to translations and verifying UI work
The file was added without being asked for. It stays, but with its scope
stated at the top so it does not grow into a second contributor guide:
the nine catalogues and what it takes to confirm a visible change works,
and nothing else.
2026-09-07 16:41:10 -07:00

2.7 KiB

Notes for Claude

Scope: translations and verifying UI work. Nothing else.

This file covers exactly two things — the nine translation catalogues, and what it takes to confirm a visible change actually works. Do not add sections for anything else: no build, deploy, architecture, style or workflow notes, however useful they seem. CONTRIBUTING.md is the style guide, and everything else belongs in the code, the docs, or a commit message.

Translations

Nine languages ship alongside English: German, Spanish, French, Dutch, Portuguese (Brazil), Russian, Ukrainian, Simplified Chinese and Japanese, in web/src/locales/. A missing key renders its English source rather than failing, so an untranslated string is invisible until somebody reading that language finds it.

Any change that adds or alters a user-visible string adds work in all nine catalogues. Say so explicitly when reporting the change — how many keys, and the fallback count before and after — and say so just as explicitly when a change adds none, so it is never left to be inferred.

The catalogue key for a plural is the other form

plural() looks the entry up by forms.other, so a call site written as

plural(n, { one: "Deleted {n} contact", other: "Deleted {n} contacts" })

is keyed on "Deleted {n} contacts". Keying the catalogue on the one form type-checks, builds, passes every test, and silently falls back to English in all nine languages. Nothing errors. The only signal is the fallback count going up, so read it:

npm run i18n:check                    # literals wrapped, and catalogue health
node scripts/i18n-catalog-check.mjs   # per-language: translated / used / falling back

Compare the "falling back to English" number against main before and after. It should not rise. Do not read the percentage instead — adding keys moves the denominator, so it can hold steady while new strings go untranslated.

Plural forms are per language, from Intl.PluralRules: one/other for most, one/few/many/other for Russian and Ukrainian, other alone for Japanese and Chinese. Supplying a form a language does not draw is inventing a distinction, not being thorough.

Verifying UI work

Store tests do not exercise the component. At least one bug in this repo's history — a shift-click range measured inside a setState updater, which React runs after the anchor ref has already moved — passed every store assertion and failed the moment the built app was driven. If a change is visible on screen, run it: npm run dev:mock (mock Stalwart, credentials printed on start), then drive the real thing. Add a component test for what you find; there are examples in web/src/views/*/__tests__/.