A sweep of lib/ and store/ for user-facing English, after the views were done. The pattern is the one #248 found: a module returns an English sentence and the view renders it without asking for a translation.
Scheduled send — entirely untranslated
The four presets (Later today, Tomorrow morning, Tomorrow afternoon, Monday morning) were rendered raw, and scheduleError() returned three English sentences straight into the picker.
describeSpan() built "30 days" with day${n === 1 ? "" : "s"} — English grammar written into the code. It produces correct German only because the two languages happen to agree, and Russian needs three forms. It is plural() now.
scheduleError translates in place rather than returning a key, because it composes a sentence around that span.
Read receipts
refusalText() returns five explanations, all rendered raw in MessageView. The offered case was a template literal — `Requested, to ${email}. Never sent automatically.` — with the address concatenated in. It takes a {address} placeholder now, so the sentence can be reordered.
Compose
The sending toast and its Undo, the Open draft action, two attachment failures, and three thrown errors that reach the reader as toasts.
A gap in my own earlier analysis
Add star and Remove star are rendered through t(desc.label) and have never been in any catalogue. The coverage scan that found the other 176 only looked at t("literal") call sites, so any label reaching t() through a variable was invisible to it.
I have now enumerated every such table — PUSH_LABEL, the settings menu, share rights, folder roles, date formats, appearance modes, swipe actions — and checked all 61 values. These two were the only ones missing. The settings menu labels, which #247 flagged, were all present and are fixed by #248 rendering them through t().
Strings
17 new strings and 3 new plural forms. They land with each language PR, which is why those are still open.
A sweep of `lib/` and `store/` for user-facing English, after the views were done. The pattern is the one #248 found: a module returns an English sentence and the view renders it without asking for a translation.
## Scheduled send — entirely untranslated
The four presets (`Later today`, `Tomorrow morning`, `Tomorrow afternoon`, `Monday morning`) were rendered raw, and `scheduleError()` returned three English sentences straight into the picker.
`describeSpan()` built "30 days" with ``day${n === 1 ? "" : "s"}`` — English grammar written into the code. It produces correct German only because the two languages happen to agree, and Russian needs three forms. It is `plural()` now.
`scheduleError` translates in place rather than returning a key, because it composes a sentence around that span.
## Read receipts
`refusalText()` returns five explanations, all rendered raw in `MessageView`. The offered case was a template literal — `` `Requested, to ${email}. Never sent automatically.` `` — with the address concatenated in. It takes a `{address}` placeholder now, so the sentence can be reordered.
## Compose
The sending toast and its `Undo`, the `Open draft` action, two attachment failures, and three thrown errors that reach the reader as toasts.
## A gap in my own earlier analysis
`Add star` and `Remove star` are rendered through `t(desc.label)` and have **never** been in any catalogue. The coverage scan that found the other 176 only looked at `t("literal")` call sites, so any label reaching `t()` through a variable was invisible to it.
I have now enumerated every such table — `PUSH_LABEL`, the settings menu, share rights, folder roles, date formats, appearance modes, swipe actions — and checked all 61 values. These two were the only ones missing. The settings menu labels, which #247 flagged, were all present and are fixed by #248 rendering them through `t()`.
## Strings
17 new strings and 3 new plural forms. They land with each language PR, which is why those are still open.
## Checks
Typecheck clean, 99 test files / 1000 tests pass.
**Merged** 2026-09-03 as coffey-labs/ihasmail@22f39a45076b
<sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
A sweep of
lib/andstore/for user-facing English, after the views were done. The pattern is the one #248 found: a module returns an English sentence and the view renders it without asking for a translation.Scheduled send — entirely untranslated
The four presets (
Later today,Tomorrow morning,Tomorrow afternoon,Monday morning) were rendered raw, andscheduleError()returned three English sentences straight into the picker.describeSpan()built "30 days" withday${n === 1 ? "" : "s"}— English grammar written into the code. It produces correct German only because the two languages happen to agree, and Russian needs three forms. It isplural()now.scheduleErrortranslates in place rather than returning a key, because it composes a sentence around that span.Read receipts
refusalText()returns five explanations, all rendered raw inMessageView. The offered case was a template literal —`Requested, to ${email}. Never sent automatically.`— with the address concatenated in. It takes a{address}placeholder now, so the sentence can be reordered.Compose
The sending toast and its
Undo, theOpen draftaction, two attachment failures, and three thrown errors that reach the reader as toasts.A gap in my own earlier analysis
Add starandRemove starare rendered throught(desc.label)and have never been in any catalogue. The coverage scan that found the other 176 only looked att("literal")call sites, so any label reachingt()through a variable was invisible to it.I have now enumerated every such table —
PUSH_LABEL, the settings menu, share rights, folder roles, date formats, appearance modes, swipe actions — and checked all 61 values. These two were the only ones missing. The settings menu labels, which #247 flagged, were all present and are fixed by #248 rendering them throught().Strings
17 new strings and 3 new plural forms. They land with each language PR, which is why those are still open.
Checks
Typecheck clean, 99 test files / 1000 tests pass.
Merged 2026-09-03 as coffey-labs/ihasmail@22f39a4507
Rebuilt from: git history, session transcript.