The catalogue key for a plural is the `other` form -- `plural()` looks the entry up by `forms.other` -- and keying it on the `one` form type-checks, builds, passes every test, and falls back to English in all nine languages. Nothing errors. It cost a round trip on #278 and would cost the next one the same. The part worth writing down is not the rule but the signal, because there is only one: the "falling back to English" count from i18n-catalog-check. The percentage is no use for this -- adding keys moves the denominator, so it holds steady at 98% whether the new strings are translated or not. Also here: that a change touching user-visible strings is work in nine catalogues and should be reported as such, including when the answer is none; and that store tests do not exercise the component, with the shift-click range bug from #278 as the standing example -- measured inside a setState updater, which React runs after the anchor ref has moved, so it passed every store assertion and failed the moment the built app was driven. No CLAUDE.md existed before this.
55 lines
2.4 KiB
Markdown
55 lines
2.4 KiB
Markdown
# Notes for Claude
|
|
|
|
Things that are true of this repository and cost somebody a round trip to
|
|
find out. Not a style guide — `CONTRIBUTING.md` is that.
|
|
|
|
## 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__/`.
|