2 Commits
Author SHA1 Message Date
MarekWoandClaude Opus 5 b1add0efc2 feat(i18n): translate contacts.js (stage 5b)
~100 keys, finishing stage 5. Catalog now 471 keys, pl at 100%.

Covers the cleanup form's validation and progress messages, the protect/block/
ignore/approve button set, bulk approve and ignore with their partial-failure
reports, the QR and URI add flows, and every toast in the file.

Folded in the fourth and last copy of relative-time formatting. contacts.js had
its own formatRelativeTime with more granularity than the shared helper — months
and years instead of falling back to a date past a week. Rather than drop that,
formatTimeAgo gained a `long` option that keeps counting, so a stale advert still
reads "3 months ago" / "3 miesiące temu". dm.js's copy is the only one left and
goes with stage 6.

Two things worth recording about verification. I first checked these pages only
for leaked catalog keys, which came back clean and told me nothing — the page was
still full of English. Running the actual en/pl diff turned up the page heading,
Back and Refresh, all four sort options, the "Last advert:" prefix, the activity
tooltips, "Protect" in its second render site, and the hop counter. The lesson is
that a key-leak check proves the keys you used are real, not that you used them.

And the diff's raw output on this page is 2000 lines because every contact name
and public key is legitimately identical in both languages. Filtering those out
made the eight real misses obvious; the per-page exclusion lists exist for exactly
this and the contacts entries now carry them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 19:29:36 +02:00
MarekWoandClaude Opus 5 4e8292bd03 refactor(i18n): consolidate date/time formatting (stage 0b)
Prerequisite for string extraction. formatTime() existed twice with subtly
different behaviour, and both hardcoded 'Yesterday ' — a string that would have
survived a naive extraction pass and stayed English forever.

app/static/js/datetime-utils.js now owns the today/yesterday/older logic, with
options for the two variants that actually differed: app.js needs an absolute
date in archive views, dm.js needs the short "5 Aug" form because DM rows are
narrower. Both keep a thin local formatTime() wrapper, so their ~15 call sites
are untouched. formatTimeAgo() moves over as-is (it only ever existed in app.js).

repeater-manage.js's fmtInt() no longer forces toLocaleString('en-US'), so
thousands separators follow the reader's locale. Kept as a function declaration
rather than a const alias so it stays hoisted, like the code it replaced.

Policy, documented in the module header: numeric formatting follows the BROWSER
locale, only the words are translated. Tying the clock to the UI language would
flip a Polish operator to "09:53 AM" the moment they switched the interface to
English, and mesh operators want 24-hour time whatever language the menus are in.

First five real catalog entries: common.yesterday, just_now, minutes_ago,
hours_ago, days_ago. days_ago exercises the plural machinery — Polish needs
"1 dzień temu" / "3 dni temu" / "5 dni temu" where English has one form.

Verified in the browser in both languages: all four helpers global, both
formatTime wrappers still routing through the shared core, Polish plural
categories correct, and the clock and number formats provably unchanged by the
UI language. Live chat timestamps render identically to before.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 17:42:34 +02:00