Internationalization release. The public booking flow and the highest-volume guest emails (confirmation, reminder, cancellation) are translated. Six locales ship out of the box, with English as the source, French human-translated by maintainers, and Spanish / Polish / German / Italian AI-seeded as starting points for native-speaker refinement on Hosted Weblate.
Added
- Six-language UI — public booking flow (slot picker, booking form, confirmation, cancel/decline/approve/claim/reschedule pages, theme-toggle chrome) renders in English, French, Spanish, Polish, German, or Italian. Translations live in Fluent
.ftlfiles underi18n/{lang}/main.ftl, embedded into the binary at compile time. Single-binary deploy preserved. - Automatic language detection — guests get their browser's
Accept-Language(RFC 7231 with q-weights honoured); logged-in users override via a Language dropdown in Profile & Settings (migration047_user_language). - Translated guest emails — confirmation, reminder, and cancellation emails render in the language captured at booking time. Migration
048_booking_languageaddsbookings.language TEXT. The reminder background task already loads it, so a reminder fired days after the booking still picks the right language. - Server-side date localization —
format_month_yearandformat_long_datehelpers render dates with locale-specific patterns:Tuesday, March 12, 2026(EN),mardi 12 mars 2026(FR),martes, 12 de marzo de 2026(ES),Montag, 12. März 2026(DE),lunedì 12 marzo 2026(IT). The format pattern itself is a Fluent message, so word order is a translation choice. - Hosted Weblate integration — translators contribute via hosted.weblate.org/projects/calrs without git or Rust knowledge. Commits flow back to the long-lived
i18nbranch via the Weblate GitHub App. - Translation-quality table in README — explicitly distinguishes human-translated French from AI-seeded locales and points readers at Weblate as the contribution path.
Fixed
- Docker image build broken by the i18n scaffolding — the multi-stage Dockerfile didn't
COPY i18n/, soinclude_str!on the embedded.ftlfiles failed at release-image build time even though localcargo buildworked. One-line fix landed before this release.
Internal
- Migrations
047_user_languageand048_booking_language - New
src/i18n.rs: concurrentFluentBundleper locale inOnceLock,Accept-Languageparser with q-weight sort, minijinjat(key, **kwargs)global,is_supported/resolve/supported_with_labelshelpers, date-formatter pair - 30 templates and ~25 web handlers wired through, each handler computes
langonce viacrate::i18n::detect_from_headersand threads it into render contexts BookingDetailsandCancellationDetailsgainguest_languageandhost_languagefields; both deriveDefaultso existing call sites use..Default::default()- 569 tests total (up from 545 in 1.7.0), including coverage for
Accept-Languageparsing, date-formatter output across locales, and full-locale parity for Spanish, Polish, German, Italian - Long-lived
i18nbranch documented inCLAUDE.mdas the working branch for translator commits and new translatable-string features
Known limitations
- Host-side emails (notification, reminder, cancellation, approval-request, decline) remain English. Infrastructure (
host_languagefield) is in place; translation pass scheduled for a follow-up. - Pending-notice / decline-notice / reschedule guest emails not yet translated.
decline_booking_by_tokenand dashboard-host-cancel paths don't yet loadbookings.language; cancellation emails sent from those paths fall back to English.- Polish month names are nominative, so date contexts read informally (
27 kwiecień 2026instead of grammatical27 kwietnia 2026). Native-speaker refinement on Weblate is welcome. - Dashboard, admin panel, and CLI command output remain English.
Full changelog: https://github.com/olivierlambert/calrs/blob/v1.8.0/CHANGELOG.md#180---2026-04-26