No reviewers
Labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
schaefera/utStudyBIble!136
Loading…
Reference in a new issue
No description provided.
Delete branch "i18n/part-2"
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?
What
You can now choose the app's language in Settings (the phone's language, English, or any installed catalogue, each named in its own language). The change shows at once with no restart, and the choice is kept. The gettext catalogue now keeps message contexts, so
qsTr("…", "comment")is translated, and a string that isn't translated falls back to its source text, never to blank.tr_argsfills%1–%9in one pass, so a value that contains%2is never filled in again. CI's e2e job now gets the catalogues along with the binary.Closes #33. Refs #14 (it stays open for phone QC). Plural forms and languages beyond German are deferred to #135.
Blast radius
Tier: trunk
Trunk paths touched:
core/src/worker*core/src/tasks*qt/main.cpp,qt/src/i18n.rs,qt/src/reading_model.rsqml/Main.qmltools/e2e/cases/language-switch.sh.forgejo/workflows/ci.ymlTesting tier: maximum for
.forgejo/workflows/ci.yml(the e2e artifact). The rest is standard.Gate / rollback:
ui.languagedefaults to "" (the phone's language). On that path start-up is unchanged: the sameinit(), and no second catalogue. Undo: revert this merge.Proof
Local gates:
cargo make: fmt, clippy, the tests (utsb-core 291 passed), release, deny and audit all passed.cargo make app-docker: exit 0.tools/i18n/check-app.sh: the window title (a context string,"Study Bible", "window title") shows "Studienbibel" underLANGUAGE=deand "Study Bible" in the C locale.Fails without the change: with the
.moparser skipping context entries again, 2 of the i18n tests fail. Restored, all 9 pass.tr_argsis a new API with no base version.CI:
language-switch: the app listed 2 options, because the artifact held only the binary, withoutshare/locale.a65a67athe artifact has 2 files (binary and catalogue), as run 265's download shows.ed7ddb4: green on changes, rust, audit, app, e2e (withlanguage-switch) and click.Phone (Plinius), build
i18n/part-2@a65a67a93and thened7ddb4:utsb: language heading Sprache).ed7ddb4fixes that; both builds are shown in the shots below.Resources
#14 exit criteria
tools/goldencovers BSB, Darby, KJV, TR (KJV), OSHB (MT), and GerElb1871 and GerSch (German), with the v11n tablesv11n-KJV,v11n-MTandv11n-German.Mockup
No mockup. The language choice is a Settings section of plain Controls 2 RadioButtons with a heading and a hint line, like the Navigation and Module repositories sections. It adds no page, sheet or dialog.
Review
Reviewer:
e8eb225: 0 findings.a65a67a, the CI artifact fix: 0 findings.ed7ddb4is a one-line QML layout fix found on the phone. It comes after the reviews.Review-Confidence: 100/100 (audit). Every trunk file was reviewed at high, and the CI-only change got a delta review.
ed7ddb4touches only a leaf page (SettingsPage.qml); it was checked on the phone, and CI is green. 0 findings are open.Confidence by part
ed7ddb4is green.🤖 Generated with Claude Code
Fresh-context review. Level: high. Blast radius: trunk. Reviewed commit:
e8eb225b41. Range: origin/main...HEAD.Findings: none (no high, medium or low defect with a concrete failure scenario).
What was checked, in context: the Catalog context keys (\x04) and get_in against QML's empty-string disambiguation and the C++ null; select/load/CHOSEN/LOADED locking and the path guard on tags; the "" / "en" / unknown-tag fallbacks; tr_args in one pass against the old chained .replace (same results for %%, a value holding %N, a missing value, multi-byte text); every converted call site in tasks, worker and session (same placeholders, same order); the ui.language setting through SetSetting, set_setting (render.apply ignores the key), settings() at start and ReadingModel::initialize (a single ReadingModel instance, so the default "" cannot reset a chosen language); choose() on the GUI thread and the retranslate callback registered before engine.load; the SettingsPage options order against the e2e case's 6 coordinates; the xgettext keyword specs and the perl extraction of tr_args against po/ and the pot; check-app.sh against the msgctxt entry.
cargo test -p utsb-core --lib i18npasses locally (9 tests). CI on this commit was still pending at review time.Observations, not defects: strings the worker made before a language change (notices, task row texts already sent to QML) keep the old language until the next event; the code comment and docs say so. Plurals stay with #135.
Files reviewed: core/src/i18n.rs, core/src/settings.rs, core/src/starter.rs, core/src/tasks.rs, core/src/tasks/exec.rs, core/src/tasks/progress.rs, core/src/worker.rs, core/src/worker/session.rs, core/src/worker/session/jump.rs, core/src/worker/session/switch.rs, qt/main.cpp, qt/src/i18n.rs, qt/src/reading_model.rs, qml/Main.qml, qml/pages/SettingsPage.qml, qml/pages/ReadingPane.qml (usage), tools/e2e/cases/language-switch.sh, tools/e2e/lib.sh (helpers), tools/i18n/update.sh, tools/i18n/check-app.sh, po/de.po, po/utstudybible.schaefera.pot, docs/09-quality-gates.md, docs/superpowers/plans/2026-10-21-gettext.md, docs/superpowers/plans/2026-10-30-gettext-2.md, CLAUDE.md
Delta review (medium)
Commit:
a65a67a93dRange: e8eb225..a65a67a
Files: .forgejo/workflows/ci.yml
Findings: none.
Checked: upload-artifact@v3 with two paths (build-ci/utstudybible, build-ci/share/locale) roots the artifact at their least common ancestor, build-ci, so the download into app-amd64 gives app-amd64/utstudybible and app-amd64/share/locale//LC_MESSAGES/*.mo. CMakeLists.txt puts the .mo files in ${CMAKE_BINARY_DIR}/share/locale via the ALL
translationstarget, which the binary depends on. core/src/i18n.rs locale_dir looks at exe.parent()/share/locale, which matches that layout. Nothing else uses app-amd64: only the e2e download step and UTSB_APP=$PWD/app-amd64/utstudybible, and click does not consume it. tools/ci/e2e.sh only chmods the binary, so the artifact's old shape is not depended on.WIP: Translations 2/2: language choice in Settings, contexts, one-pass placeholders (#14, #33)to Translations 2/2: language choice in Settings, contexts, one-pass placeholders (#14, #33)Merge gate on
ed7ddb4. Reviews 359 (high,e8eb225) and 360 (medium delta,a65a67a, ci.yml) have 0 findings, so nothing is left to fix or refute. The only commit after them,ed7ddb4, is a one-line QML change in qml/pages/SettingsPage.qml (a leaf page): it drops Layout.fillWidth from the language RadioButtons, with a comment. It does not touch logic. CI on head is green on all six jobs of run 266: changes, rust, audit, app, e2e and click. The PR body's Proof has no unrun elevated, maximum or AI-behavior gate. The maximum-tier ci.yml change is backed by the failing run 264 and the green run 266, which includes the language-switch e2e case. The Review-Confidence of 100 comes from the audit. Approved.