feat(i18n): data-driven language picker + Weblate translation guard #5
Reference in New Issue
Block a user
Delete Branch "feat/translations"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Enables community-driven translations end to end.
App
res/xml/locales_config.xml(en, de) as the single source of truth for shipped languages, wired viaandroid:localeConfig→ also gives the Android 13+ per-app language entry in system settings.AppLanguageis now data-driven: it parseslocales_config.xmlfor supported BCP-47 tags and renders autonyms ("Deutsch", "English", …); the hardcodedLanguagePrefenum is gone and the Settings picker is built from that list.settings_language_german/englishstrings.Adding a language is now just: drop in
values-<tag>/strings.xml+ add one<locale>line.CI
scripts/check_translations.py+ a lightweight Translations workflow (no Android SDK) for fast feedback on translation PRs. Fails on stale keys and on translatingtranslatable="false"entries; missing keys are coverage-only.MissingTranslationdowngraded to informational (partial translations fall back to English);ExtraTranslationstays fatal.Verification
:app:assembleDebug,:app:testDebugUnitTest,:app:lintDebugall pass locally.⚠️ Not yet reviewed on-device — the Settings → App language picker should be eyeballed on a real device before merge/release.
Paired with the self-hosted Weblate component (
calendula/strings, Gitea-PR push) now wired to this repo.🤖 Generated with Claude Code
Update — on-device review fixes + merge with main
On-device review (Pixel 10, Android 16) surfaced a real bug, now fixed:
AppCompatDelegate.setApplicationLocalesonly syncs to the system from anAppCompatActivity, butMainActivitywas a plainComponentActivity. Switched it toAppCompatActivity+ basedTheme.CalendulaonTheme.AppCompat.DayNight.NoActionBar. Verified: system per-app locale now flips correctly on tap.android:windowBackgroundto a DayNight colour matching the Compose background (light#FBFCFE/ dark#101316) so the recreation no longer flashes a lighter backdrop.Merged
main: reconciled with the new full-screen picker (ui/common/Picker.kt). The language row now feeds the data-driven tag list + autonyms into main'sOptionPicker(the redesigned picker is preserved, not reverted). Parity guard green at 244/244;assembleDebug+ unit tests pass on the merged tree.Still pending: final on-device sign-off on the merged build before merge/release.