Translations: status.json is stale, so 36 languages at 70 % are offered as complete drafts #495

Closed
opened 2026-10-01 10:47:06 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, by recomputing the translation report with the tool's own functions and comparing it with the committed file.

Checked again on 2026-10-01 against main at 0a5cad587: still present. The code is now at accounts/forms.py:193 (language_choices) and accounts/forms.py:840 (the same test for Defaults); the other locations are unchanged. The catalogues were extracted again since the review and status.json was not rewritten, so the figures below are the ones recomputed at this commit.

The language picker and the bars on Server settings → Defaults read only locale/status.json. That file is written by scripts/messages.py stats --write and by nothing else, and nothing checks it. The committed copy counts 1,873 strings per language. The catalogues now hold 3,119. So 36 languages that are 70 % translated are shown as complete, and the reviewed share of French and European Portuguese is shown as nothing.

  • Where: locale/status.json; core/messages_tool.py:818 (cmd_stats, the only writer); core/languages.py:356 (translation_status, the reader); accounts/forms.py:192 (language_choices, the < 95 test that marks a language partial) and accounts/forms.py:843 (the same test for Defaults); .forgejo/workflows/ci.yml:100-105, which runs extract --check and check but nothing that compares status.json with the catalogues; docs/TRANSLATING.md:159, which leaves it to contributors to run stats --write by hand.

  • What happens: stats_for(_as_the_reader_sees_it(...)) over the snapshot's catalogues gives total: 3119 for every language. status.json gives total: 1873 for all 68, and differs for all 68. Two consequences:

    • 36 languages are stored at 100 % and are really at 70 % (2,186 of 3,119): bg, bs, ca, cs, cy, da, de, el, es, et, eu, fi, ga, gl, hr, hu, hy, is, it, ka, lb, lt, lv, mk, mt, nb, nl, pl, ro, sk, sl, sq, sr, sv, tr and uk. Because the stored percentage is 100, the picker lists each one among the drafted languages instead of as partial with its percentage, and Defaults draws it as wholly draft.
    • fr-fr and pt-pt are stored with reviewed: 0, though 153 of their strings are reviewed, so their bars show no reviewed part.
  • Why it matters: somebody who picks German or Polish is told the interface is complete and gets one where nearly a third of the strings are English. The figure shown is the one #312 and #127 exist to make true.

  • Fix: make the file impossible to forget.

    1. Add stats --check, which fails when a fresh report differs from the stored one, and run it in ci.yml beside extract --check.
    2. Or have extract (or compile, which CI, the release workflow and the image build all run) write status.json itself.
    3. Regenerate the committed file.

    Computing the report from the catalogues at start-up is the alternative, but the image deletes the .po files (docker/Dockerfile:101-104), so it would have to read the compiled .mo files instead.

Done when

  • A test in tests/test_messages_tool.py asserts that the committed locale/status.json equals what cmd_stats would write for the current catalogues. It fails today for all 68 languages.
  • CI runs the same comparison, so a pull request that adds strings without refreshing the report does not pass.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, by recomputing the translation report with the tool's own functions and comparing it with the committed file. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. The code is now at `accounts/forms.py:193` (`language_choices`) and `accounts/forms.py:840` (the same test for *Defaults*); the other locations are unchanged. The catalogues were extracted again since the review and `status.json` was not rewritten, so the figures below are the ones recomputed at this commit. The language picker and the bars on *Server settings → Defaults* read only `locale/status.json`. That file is written by `scripts/messages.py stats --write` and by nothing else, and nothing checks it. The committed copy counts 1,873 strings per language. The catalogues now hold 3,119. So 36 languages that are 70 % translated are shown as complete, and the reviewed share of French and European Portuguese is shown as nothing. - **Where:** `locale/status.json`; `core/messages_tool.py:818` (`cmd_stats`, the only writer); `core/languages.py:356` (`translation_status`, the reader); `accounts/forms.py:192` (`language_choices`, the `< 95` test that marks a language partial) and `accounts/forms.py:843` (the same test for *Defaults*); `.forgejo/workflows/ci.yml:100-105`, which runs `extract --check` and `check` but nothing that compares `status.json` with the catalogues; `docs/TRANSLATING.md:159`, which leaves it to contributors to run `stats --write` by hand. - **What happens:** `stats_for(_as_the_reader_sees_it(...))` over the snapshot's catalogues gives `total: 3119` for every language. `status.json` gives `total: 1873` for all 68, and differs for all 68. Two consequences: - 36 languages are stored at 100 % and are really at 70 % (2,186 of 3,119): bg, bs, ca, cs, cy, da, de, el, es, et, eu, fi, ga, gl, hr, hu, hy, is, it, ka, lb, lt, lv, mk, mt, nb, nl, pl, ro, sk, sl, sq, sr, sv, tr and uk. Because the stored percentage is 100, the picker lists each one among the drafted languages instead of as partial with its percentage, and *Defaults* draws it as wholly draft. - `fr-fr` and `pt-pt` are stored with `reviewed: 0`, though 153 of their strings are reviewed, so their bars show no reviewed part. - **Why it matters:** somebody who picks German or Polish is told the interface is complete and gets one where nearly a third of the strings are English. The figure shown is the one #312 and #127 exist to make true. - **Fix:** make the file impossible to forget. 1. Add `stats --check`, which fails when a fresh report differs from the stored one, and run it in `ci.yml` beside `extract --check`. 2. Or have `extract` (or `compile`, which CI, the release workflow and the image build all run) write `status.json` itself. 3. Regenerate the committed file. Computing the report from the catalogues at start-up is the alternative, but the image deletes the `.po` files (`docker/Dockerfile:101-104`), so it would have to read the compiled `.mo` files instead. ## Done when - A test in `tests/test_messages_tool.py` asserts that the committed `locale/status.json` equals what `cmd_stats` would write for the current catalogues. It fails today for all 68 languages. - CI runs the same comparison, so a pull request that adds strings without refreshing the report does not pass.
tiagoagueda added this to the 0.5.0 milestone 2026-10-01 10:47:06 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#495
No description provided.