docs(localization): describe the TUI packs and gate locale drift in CI#4839
Merged
Conversation
docs/LOCALIZATION.md is the stated single source of truth for what the project ships, plans, or has deferred — but it only described the website and README surfaces. The TUI locale packs are the largest translation surface in the repo (eight packs, 1128 keys each), and they were absent entirely. So complete ko/es-419/pt-BR packs shipped while the matrix read as though no Latin-American work existed, and zh-Hant's deliberate 478/1128 partial (#4057) appeared nowhere at all. Every check that would have caught the drift was listed as Planned and unbuilt. That matters more now than it did: the v0.9.2 wave adds six locales (#4788, #4789, #4790, #4791, #4749). Adding them to a matrix that already misdescribes reality compounds the problem once per locale. - Add a TUI locale packs table with measured key counts against en.json, and represent zh-Hant as partial with a pointer to its English-fallback behaviour rather than omitting it. - Add scripts/check-tui-locale-parity.py, which fails when a pack that claims completeness diverges from en.json's key set in either direction or drops a {named} placeholder. Declared partials are exempt from completeness but still may not define keys English lacks, since the English fallback can never surface those. PARTIAL_PACKS mirrors Locale::is_partial_pack(). The check is file-based on purpose: it also covers packs whose Locale wiring has not landed yet, and it attributes a failure to a file instead of burying it in a test binary. - Wire that gate and the already-existing scripts/check-readme-locales.sh into the CI Lint job, and flip both Drift-checks rows off Planned. The three rows that remain Planned now name their tracking issue (#3091) instead of sitting bare. - Extend "How to add a locale" into a three-surface checklist (TUI pack, README, website) so the v0.9.2 wave follows one procedure rather than six improvisations. - Record the #4749 assessment of Galician and Basque: defer both. The argument #4788 makes for Catalan is about review capacity, not market size, and it does not transfer — neither language has a localization community that could review a pack, Galician already has a workable fallback in the shipped es-419 pack, and Basque is an isolate with none. The website-side items from #4787 (npm run check:locales, and using the existing "partial" LocaleStatus for zh-Hant in web/lib/i18n/config.ts) depend on the #3091 dictionary layer and stay Planned under that issue. Closes #4787 Refs #4749
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
Contributor
|
Claude encountered an error after 21s —— View job Reviewing PR #4839
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What was broken
docs/LOCALIZATION.mdis the stated single source of truth for every locale the project ships, plans, or has deferred — but it only had tables for the website and README surfaces. The TUI locale packs undercrates/tui/locales/are the largest translation surface in the repo (8 packs, 1128 keys each) and were absent entirely.Consequences, all verified against the tree:
ko,es-419, andpt-BRTUI packs ship, while the website table marksesandpt-BRdeferred— the doc reads as though no Latin-American work exists.zh-Hantships as a deliberate 478/1128 partial with English fallback (v0.8.67: bring shipped UI locale packs to parity or explicitly scope zh-Hant as partial #4057) and appeared nowhere in the matrix.scripts/check-readme-locales.sh, which already existed and simply was not wired into CI.The v0.9.2 locale wave (#4788, #4789, #4790, #4791, #4749) adds six more locales. Each one added to a matrix that already misdescribes reality compounds the drift.
Why the fix is shaped this way
The parity gate is file-based, not a Rust test.
crates/tui/src/localization.rsalready hasshipped_complete_packs_have_raw_key_parity_with_english, but it can only see packs that have aLocalevariant. During a locale wave the pack JSON lands before (or in a different PR from) the Rust wiring, and that window is exactly when a pack silently drifts.scripts/check-tui-locale-parity.pyreads the directory, so it covers packs whose wiring has not landed — and a failure names a file instead of being buried in a test binary.Placeholder parity is checked, not just keys. Call sites substitute
{named}placeholders with.replace(), so a translator who drops or renames one produces literal braces at runtime with no test failure. The gate compares placeholder sets per key.Partials are a declared status, not an escape hatch.
PARTIAL_PACKSmirrorsLocale::is_partial_pack()and requires a tracking issue per entry. A partial is exempt from completeness but still may not define keys English lacks, because the English fallback can never surface those.Galician/Basque (#4749) is recorded as an assessment, not a pack. #4749 asked whether
gl/euare "similar-value European additions" worth shipping with Catalan. The answer is no, and the reasoning is written down in the matrix rather than left in a PR comment: the case #4788 makes for Catalan is about review capacity ("an unusually strong software-localization tradition and an active volunteer community"), not market size, and that argument does not transfer to either language.Gates I actually ran
cargo fmt/clippy/cargo testwere not run for this PR and are not applicable: the diff touches onlydocs/LOCALIZATION.md,.github/workflows/ci.yml, and a new Python script. No Rust source is modified.What I could NOT verify
ci.ymlparses and that both new steps land in thelintjob's step list, and I ran both scripts locally on this tree. I did not observe them execute on GitHub Actions.npm run check:locales(website dictionary parity) and switchingzh-Hantto the existing"partial"LocaleStatusinweb/lib/i18n/config.tsboth depend on the v0.9.2: Bring the website to parity with existing Japanese and Vietnamese README locales #3091 dictionary layer, which does not exist yet. They stay Planned in the matrix, now explicitly attributed to v0.9.2: Bring the website to parity with existing Japanese and Vietnamese README locales #3091 instead of sitting unattributed.Closes #4787
Refs #4749