Skip to content

i18n pass: fix web-template extraction, wrap missing UI strings, AI-fill all translations#488

Merged
brickbots merged 2 commits into
mainfrom
i18n-template-fix-and-translations
Jun 22, 2026
Merged

i18n pass: fix web-template extraction, wrap missing UI strings, AI-fill all translations#488
brickbots merged 2 commits into
mainfrom
i18n-template-fix-and-translations

Conversation

@brickbots

Copy link
Copy Markdown
Owner

An internationalization (i18n) pass over main. Three parts: a real extraction bug fix, wrapping user-visible strings that were missing _(), and filling every translation gap across all four languages.

1. Fix web-template extraction (the headline bug)

babel.cfg's Jinja2 mapping pointed at views2/ (which doesn't exist), and the extract command only scanned ./PiFinder — but the templates live in the sibling dir python/views/. Net effect: all 141 {{ _() }} strings across 19 web templates were silently never extracted, so the entire web UI fell back to English regardless of the selected language. The runtime path is wired up (server.py binds template _ to the device gettext catalog), so this was purely an extraction-config bug.

Fix: [jinja2: **.html] in babel.cfg + add ./views as a scan root in noxfile.py, and update the i18n skill docs to match. No user-visible change on its own — empty msgstr falls back to English — but it unblocks translating the web UI (see part 3).

2. Wrap missing device-UI strings + fix antipatterns

  • menu_structure.pyComets, Confirm, Cancel (their twins elsewhere were already wrapped, so these reuse existing msgids and translate immediately).
  • location_list.py — action labels (Load/Rename/Delete) and the Loaded/Deleted/Renamed/Location-Name popups. English keys are kept for action dispatch; only the displayed label is translated (via a small label map), so the action == "Load" logic is unaffected in other locales.
  • callbacks.py — Location Reset / Time-Date Reset / user-object popups.
  • Antipatterns: object_details.py animated-ellipsis f-strings (a different msgid per frame → never translatable) now translate the base word and append dots outside _(); object_list.py drops a no-op double-_() wrap; software.py {} → named {mode}. f-string popups converted to named-placeholder .format().

3. AI-fill all translations (de / es / fr / zh)

Ran the babel pipeline against the corrected config (.pot: 508 → 666 msgids) and filled every untranslated + fuzzy entry — 181 each for de/es/fr, 186 for zh.

⚠️ These are machine translations and need human review. Each is tagged so you can find them:

grep -rn "AI-TRANSLATED" python/locale/

Placeholders, newlines, and the EQ / RA/Dec / Alt/Az / GPS abbreviations are preserved verbatim. One low-confidence zh entry (det {n}) is also flagged #, fuzzy so it falls back to English until reviewed. (The repo already carried AI-TRANSLATED markers from prior passes — this continues that workflow.)

Verification

  • ruff check + ruff format ✓ · mypy ✓ (6 changed files) · msgfmt -c ✓ (all 4 languages)
  • gettext runtime load resolves translations from the compiled .mo
  • 5 smoke + 530 unit tests pass

Note on diff size

The .po files have large diffs. Most of it is unavoidable: 141 new template msgids + 181 filled translations/language + location-comment refresh from re-extraction. There's also cosmetic line-rewrap churn — pybabel 2.16.0 doesn't reproduce the committed files' prior wrapping at any --width, so any nox -s babel run reflows them. .mo binaries are regenerated (the repo checks them in).

🤖 Generated with Claude Code

brickbots and others added 2 commits June 22, 2026 09:29
The Jinja2 extractor in babel.cfg pointed at `views2/` (which doesn't
exist) and the extract command only scanned `./PiFinder`, so the 141
`{{ _() }}` strings in python/views/*.html were never extracted — the
entire web UI fell back to English regardless of the selected language.
Point the extractor at `**.html` and add `./views` as a scan root
(babel.cfg, noxfile.py, and the i18n SKILL.md docs).

Also wrap user-visible device strings that were missing `_()`:
- menu_structure.py: Comets / Confirm / Cancel (their twins elsewhere
  were already wrapped, so these reuse existing msgids)
- location_list.py: action labels (Load/Rename/Delete) and the Loaded/
  Deleted/Renamed/Location-Name popups. English keys are kept for action
  dispatch; labels are translated at draw time via a small label map.
- callbacks.py: Location Reset / Time-Date Reset / user-object popup

And fix broken `_()` antipatterns:
- object_details.py: animated-ellipsis f-strings produced a different
  msgid per frame; translate the base word and append dots outside `_()`
- object_list.py: drop a no-op double `_()` wrap around a runtime string
- software.py: positional `{}` -> named `{mode}` placeholder

f-string popups are converted to named-placeholder `.format()` so
translators get stable msgids.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Run the babel extract/update/compile pipeline against the corrected
config. The template (.pot) grows 508 -> 666 msgids: the newly-extracted
web-template strings plus the device strings wrapped in the previous
commit.

Fill every untranslated and fuzzy entry across all four languages
(181 each for de/es/fr, 186 for zh) with machine translations, each
tagged `# AI-TRANSLATED (claude): needs human review` so a reviewer can
find and validate them (`grep -rn AI-TRANSLATED python/locale/`).
Placeholders, newlines, and the EQ / RA/Dec / Alt/Az / GPS abbreviations
are preserved verbatim; gettext's `msgfmt -c` passes for all languages.
One low-confidence zh entry ("det {n}") is additionally flagged
`#, fuzzy` so it falls back to English until reviewed.

All languages are now fully translated. .mo binaries recompiled.

Note: the bulk of the .po line churn is unavoidable re-wrapping —
pybabel 2.16.0 does not reproduce the committed files' previous wrapping
at any --width, so any `nox -s babel` run reflows them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@brickbots brickbots merged commit f076bc0 into main Jun 22, 2026
1 check passed
brickbots added a commit that referenced this pull request Jun 22, 2026
Review the release..main delta and update the v2.6.0 release notes:
add Polar Alignment Assist (#459) and Multi-Format Observing List
Import (#394); add comet-propagation speedup (#470) and missing bug
fixes (#472, #479, #465, #483, #473, #474); correct the Telemetry
menu path; note the menu reorganization (#480); refresh i18n (#488),
developer items (#478, #481), and the footer commit/file/line stats.
Excludes the NixOS migration (#433).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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