From 6ed513b206a0dd8049a7f3b6e6f1ab99fa54f6b8 Mon Sep 17 00:00:00 2001 From: Wynne Pirini Date: Thu, 5 Nov 2026 07:04:53 +1300 Subject: [PATCH] docs: fix the remaining stale locale counts and translation caveats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #220 corrected the locale list in CLAUDE.md and ARCHITECTURE §23 but missed three other places that still claimed 9 languages, and left two claims that shipping Polish has now falsified: - README.md and CONTRIBUTING.md both still said 9 locales and listed 9. Both now say 11 and include Greek and Polish. Greek had already shipped without either file being updated, so this drift predates Polish. - ARCHITECTURE's LiveKit limitation repeated "9 languages". - ARCHITECTURE's "Plural rules are 2-form only" bullet said shipping Polish correctly needs a CLDR plural-category selector first. Polish now ships and does not need one: its plural-bearing keys dodge the missing categories (durations use the invariant abbreviations godz./min, and hostsLabel's inny/innych reads correctly at every count). Russian and Arabic still do need the selector. - "Every non-English locale is an LLM draft" is no longer true of pl, which was contributed and grammar-checked by a native speaker. Reworded to "most", with the exception stated and its two developer edits named. --- CONTRIBUTING.md | 9 +++++---- README.md | 7 ++++--- docs/ARCHITECTURE.md | 16 +++++++++++----- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 76870aa3..cb3fcad8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -74,14 +74,15 @@ prefer additive, nullable/defaulted columns. ## Translations -Calnode ships 9 locales (`en es fr fr-CA de it pt nl sv`) across the booker-facing surfaces: +Calnode ships 11 locales (`en es fr fr-CA de el it nl pl pt sv`) across the booker-facing surfaces: booking page, manage/reschedule page, embed widget, the four emails, and the calendar invite. The admin UI and the built-in video room are English-only. **Translation PRs are very welcome** - both new languages and corrections to existing -ones. **Every non-English locale is currently a machine draft with no native review**, so -if you speak one of them, fixes are genuinely valuable and will be merged readily. Small, -single-language PRs are easier to review than sweeping ones. +ones. **Most non-English locales are machine drafts with no native review, and none has +had a full native read** (Polish was contributed and grammar-checked by a native +speaker), so if you speak one of them, fixes are genuinely valuable and will be merged +readily. Small, single-language PRs are easier to review than sweeping ones. **Adding a language is adding one file:** `internal/i18n/locales/.json`. No Go, template, or frontend change is needed - `init()` globs the directory, and the language diff --git a/README.md b/README.md index b9db471f..4ce56269 100644 --- a/README.md +++ b/README.md @@ -200,13 +200,14 @@ domains, Resend email, Google & Microsoft OAuth, Litestream backups, troubleshoo - **Zoom** — per-host OAuth; a Zoom-located booking mints a meeting under the assigned host's account - **Built-in video meetings (LiveKit)** — in-browser rooms as a booking location (no app or account for guests); host controls (end-for-all, hand-off **and reclaim** host, attendee screen-share toggle), **meeting recording** straight to your own **Litestream backup bucket** (the same one you already use for DB backup — no extra storage to provision) with in-app downloads, **recording consent** (notice + consent-or-leave), and an **AI notetaker** (Deepgram transcript → LLM notes). Headless-consumable: MCP `get_meeting_notes`/`get_transcript` + `recording.completed`/`transcript.ready`/`notes.ready` webhooks. BYO LiveKit endpoint (Cloud or self-hosted); configured in Settings → Video — see [docs/VIDEO.md](docs/VIDEO.md) -- **9 languages** on every booker-facing surface - booking page, manage/reschedule page, +- **11 languages** on every booker-facing surface - booking page, manage/reschedule page, embed widget, all four emails, and the calendar invite: **English · Spanish · French · - Canadian French · German · Italian · Portuguese · Dutch · Swedish**. Picked from + Canadian French · German · Greek · Italian · Dutch · Polish · Portuguese · Swedish**. Picked from `Accept-Language` with a footer switcher and an operator-set fallback language; the booker's choice is stored on the booking, so reminders arrive in the language they booked in. Adding a language is adding one JSON file - no code change. *(The admin UI and the built-in video room are - English-only. Non-English translations are machine drafts without native review - + English-only. Most non-English translations are machine drafts and none has had a full + native review; Polish was contributed and grammar-checked by a native speaker - corrections by PR are very welcome.)* - Embeddable booking widget (Shadow-DOM web component; inline + popup) - Members, roles (owner/admin/member), email-token invitations diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index ccf2b8d0..73d63b6a 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -987,11 +987,14 @@ Each account can set `booking_accent` in its profile. The default preserves the patching. The **public** booking surfaces are unaffected and are verified on mobile; this is admin-only. Deferred 2026-08-22, not a regression. - **LiveKit room is not translated** - the booking surfaces, emails and calendar invites - ship in 9 languages (§23), but the in-browser meeting UI is ~45 hardcoded English + ship in 11 languages (§23), but the in-browser meeting UI is ~45 hardcoded English strings. It has its own vanilla-JS asset pipeline and shares no string plumbing with the Go templates, so it needs a small runtime `t()` of its own. Separate work, not hard. -- **Plural rules are 2-form only** (§23) - shipping Polish, Russian or Arabic correctly - needs a real CLDR plural-category selector first. +- **Plural rules are 2-form only** (§23) - every plural-bearing key splits on `n == 1` and + nothing else. Polish ships despite that because its keys dodge the missing categories: + durations use invariant abbreviations (`godz.`, `min`), and `hostsLabel`'s + `other`/`others` pair (`inny`/`innych`) is correct for every count. Russian or Arabic + genuinely do need a CLDR plural-category selector first. - **OAuth app verification** — the Google and Microsoft apps should go through publisher verification before wide public use to avoid "unverified app" warnings. @@ -1329,8 +1332,11 @@ Two traps: ### Translation quality -**Every non-English locale is an LLM draft with no native review.** The structure is -verified by the guards above; the *wording* is not. Register was chosen per language rather +**Most non-English locales are LLM drafts with no native review, and none has had a full +native read.** The structure is +verified by the guards above; the *wording* is not. `pl` is the partial exception: it was +contributed and grammar-checked by a native speaker in #216/#220, though two developer +edits (the CLDR date forms and `innych`) went in on top of his text. Register was chosen per language rather than uniformly (`fr`/`de`/`it`/`pt` formal, `es`/`nl`/`sv` informal), matching what business booking pages do in each market, but that too is unreviewed. Corrections via PR are welcome and are the expected path to improving them. Do not describe a language as production-quality