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

60 lines
2.7 KiB
Markdown

# 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
```ts
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:
```sh
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__/`.