Skip to content

feat(l10n): French localization#26

Merged
Periicles merged 3 commits into
feat/authorization-recoveryfrom
feat/french-localization
Jul 13, 2026
Merged

feat(l10n): French localization#26
Periicles merged 3 commits into
feat/authorization-recoveryfrom
feat/french-localization

Conversation

@Periicles

@Periicles Periicles commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • The landing page has been bilingual FR/EN from the start, but the app itself was English-only. This closes that gap by following the system language, per macOS convention (CFBundleLocalizations + a String Catalog), rather than adding an in-app language switcher.
  • Adds Sources/Resources/Localizable.xcstrings (source language en, fr translations) covering every user-facing label, status string, format string, and the two Settings authorization messages.
  • Threads locale: Locale = .current through SnapshotBuilder.computeSnapshot and its per-state builders; EventProgressSnapshot.noCalendar/.emptyToday become static func(locale:). Views adopt Text(_:bundle:) / a small Localized.string(_:locale:) helper.
  • Countdown/duration digit formats (%02d:%02d:%02d) are intentionally left unlocalized — only labels and format-string text are translated.

Why a build tool plugin

SwiftPM's native build system (swift build/swift test, as opposed to Xcode's build system) copies .xcstrings files verbatim instead of compiling them into per-locale .lproj/Localizable.strings — verified empirically: the resulting resource bundle reported localizations: ["en"] only, and French lookups silently fell back to the English key. Plugins/CompileStringCatalogPlugin is a .buildTool() plugin that shells out to Apple's xcstringstool compile so the catalog is correctly compiled for CLI-only builds (no .xcodeproj in this repo).

A related discovery: String(localized:bundle:locale:) does not reliably honor an explicit locale: override when given a plain Bundle on the toolchain used here — it silently falls back to Locale.current. Routing through LocalizedStringResource with a .atURL bundle description (wrapped in Sources/Utilities/Localization.swift's Localized.string(_:locale:)) resolves correctly regardless of the host machine's locale. This is what lets SnapshotComputationTests reliably pin en (Step 4 of the task brief) even if CI or a contributor's machine is set to French.

Test plan

  • swiftlint — 0 errors (1 pre-existing file_length warning on NotchPanelView.swift, unrelated to this PR)
  • swift build
  • DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer swift test — 56/56 passing, including with LANG=fr_FR.UTF-8 LC_ALL=fr_FR.UTF-8 set to simulate a French host
  • bash scripts/package.shdist/NotchBar.app/Contents/Resources/NotchBar_NotchBar.bundle/fr.lproj/Localizable.strings present
  • Manual French-system smoke test — skipped per task instructions

The landing page has been bilingual FR/EN since launch, but the app itself
was English-only. Follow system language per macOS convention: a String
Catalog carries en/fr translations, threaded through SnapshotBuilder and
the views, with a build tool plugin to compile it for swift build/test
(SwiftPM's own build system copies .xcstrings verbatim instead of
compiling it, unlike Xcode's build system).
SwiftPM's own build system doesn't compile .xcstrings catalogs, so the
prior approach shelled out to xcstringstool via a custom build plugin
and leaked the raw JSON catalog into the shipped app bundle. Convert
the catalog to en.lproj/fr.lproj Localizable.strings, which SwiftPM
processes natively, and drop the plugin entirely. Localized.string
now resolves .lproj sub-bundles directly via Bundle(path:) for
explicit non-current locales, deferring to Bundle.module's standard
search order otherwise.
Base automatically changed from feat/multi-calendar to feat/authorization-recovery July 13, 2026 07:35
@Periicles Periicles self-assigned this Jul 13, 2026
@Periicles
Periicles merged commit 85252d3 into feat/authorization-recovery Jul 13, 2026
3 checks passed
@Periicles
Periicles deleted the feat/french-localization branch July 13, 2026 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant