chore(i18n): drop 23 keys that no consumer can reach - #270
Merged
Merged
Conversation
The reachability gate added by the preceding PR in this series finds 59 (key, class) pairs that no consumer can reach. Delete the 23 that are unambiguously dead and, in the same commit, remove their sunset-list entries, so the list stays exactly equal to the computed unreachable set (59 -> 36 pairs). Nothing observable changes: none of the 23 keys is referenced by any T(...) call, data-i18n* attribute or other consumer in the UI corpus. - ui/js/i18n.js: 23 keys removed from each pack (46 lines = 811 - 788) - src/i18n_pack.rs: matching 23 sunset-list entries removed; ZH_KEY_COUNT / EN_KEY_COUNT recalibrated from the gate's own report - ui/index.html: cache-bust token for js/i18n.js bumped
Owner
Author
|
Self-review (R62, committer — Reviewed the diff and re-ran the verification on this exact branch. What I checked
Results on this branch
Out of scope, deliberately: the 36 remaining sunset entries (30 Merging after this comment, since the change is a pure deletion of keys with zero consumers and the gate's exact-equality assertion is green. |
argszero
added a commit
that referenced
this pull request
Sep 21, 2026
Ships the 10 PRs merged since v0.7.25 (#261-#270). No schema change, no config change, so the deployment-side config.toml needs no edit. One fact, one source / display must equal what it consumes (frontend, 6 places) - #261 read the spendable half of the wallet payload when refreshing your own balance; #262 the transactions payload signature covers the time range, with one reload trigger shared by the four controls; #263 the settings controls are either wired or explicitly inert; #265 the re-list outcome comes from the same entry as its action; #268 the sharing form shows a plan's label, not its config id; #269 the ops card stops reading a key's status count as a health verdict. i18n reachability - #266 every pack key must reach a consumer (the gate), and #270 drops the 23 keys that gate proved unreachable: ZH/EN key count 811 -> 788, sunset list 59 -> 36. Gateway - #267 applies the body limit where axum actually reads it (per-route DefaultBodyLimit, 8 MiB on the three gateway routes; unauthenticated endpoints keep the 2 MiB default). This is the application half of rant 2026-09-18T09:14:18. It also corrects the false v0.7.10 "raised to 70MB" CHANGELOG line, which described installing a layer rather than raising a limit. - Cargo.toml / Cargo.lock: 0.7.25 -> 0.7.26. - CHANGELOG.md: v0.7.26 entry plus the v0.7.10 correction. - ui/index.html cache-bust left as-is: this release touches no UI file; the live values are app.js 20260921-2 / i18n.js 20260921-2. cargo test 302 passed; cargo fmt --check clean; clippy -D warnings clean.
8 tasks
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.
Summary
The i18n reachability gate introduced by the preceding PR in this series finds 59 (key, class) pairs
that no consumer can reach. This PR deletes the 23 of them that are unambiguously dead — and, in the
same commit, removes their entries from the gate's sunset list, so the list stays exactly equal to
the computed unreachable set.
Nothing observable changes: these keys are not referenced by any
T(...)call, anydata-i18n*attribute, or any other consumer in the UI corpus, and no value on screen is produced fromthem.
Related Issue
Changes
ui/js/i18n.js: remove 23 keys from the Chinese pack and the same 23 from the English pack(46 lines = 23 × 2, i.e.
811 − 788).src/i18n_pack.rs:UNREACHABLE_PACK_KEYS(59 → 36 pairs);ZH_KEY_COUNT/EN_KEY_COUNT(811 → 788).ui/index.html: bump the cache-bust token forjs/i18n.js(the pack file changed).The deletion and the sunset-list edit are deliberately in the same commit: the gate asserts exact
equality, so splitting them would leave the tree red between the two commits.
Which 23 keys, and why they are safe
The classes below are mnemonics only. The sole criterion for deletion is zero consumers
(verified independently, see Tests), because the gate cannot catch the interesting mistake — see the
honesty note below.
dup-sibling— a reachable key in the same pack already carries the same valueadmin.emp.dept.unassigned→common.unassigned;admin.emp.status.near→common.nearLimit;admin.emp.status.normal→common.normal;common.calls→cnt.calls.unit;common.copy→settings.ak.copy;common.month→ops.stats.in.sub/out.sub;common.people→cnt.people(substring, not equal);common.rename→settings.ak.rename;mk.count→cnt.on;share.stats.listings.sub→cnt.hist;share.stats.used.sub→cnt.quotazero-mock— the render was removed but the keys stayedadmin.emp.stats.members.sub.mock,…mock2,admin.org.demo,admin.raise.demo,ops.demo,ops.stats.in.sub.mock,ops.stats.keys.sub.mock,ops.stats.out.sub.mock,ops.stats.users.sub.mockcomposite— the text is already embedded in a reachable composite valuelogin.forgot(⊂login.foot),wallet.withdraw.disabled(⊂wallet.note)rename— the column header now uses another keytx.col.keycommon.peopleis called out because its value is a bare人/people, while the apparent twincnt.peopleis{n} 人/{n} people— that is substring containment, not equality. So "has anequal-valued twin" must not be treated as a precondition for deletion; it would wrongly flag this
safe key. The criterion is consumers, not twins.
Honesty note: the gate is not the safety net for this change
The gate proves the sunset list equals the computed unreachable set. That means:
sunset entry (useful: it forces the pair to move together);
is unchanged and the gate stays green.
So the real safety net for this PR is the per-key zero-consumer verification (Tests), not the gate.
The gate keeps the bookkeeping honest.
What is deliberately left alone
The remaining 36 sunset entries are untouched, each for a stated reason:
old-design(30): superseded by the current design — retiring them is a larger product decision,not a cleanup, and belongs in its own change.
neutral-literal(4):login.email.ph,chat.close,settings.prefs.lang.zh,settings.prefs.lang.en— their values also appear as static text in
index.html(placeholder=,✕,<option>), soremoving the keys would turn the static-i18n gate red. Both packs carry the same literal by design.
weak-should-wire(1):admin.emp.dept.ok.unassignedshould be wired up in code, not deleted.host-decision(1):admin.usage.unit.pointsis a product-wording decision — out of scope here.Also out of scope: the two dead placeholder
divs (#dept-demo-note,#ops-demo-note) left behind bythe same commit that stopped rendering them. They are DOM, not pack keys; mixing them in would make this
PR two things at once.
Tests
cargo testpasses — 302 passed / 0 failed, the same count as this branch's pre-changebaseline (this change adds no new tests, by design: the work order says not to add a gate here).
cargo fmt --checkpassescargo clippy --all-targets -- -D warningspasses(36 pairs) is still exactly equal to the computed unreachable set.
recalibration is applied as a loop (read the reported numbers → patch those → recompile →
rerun) because
packs()asserts the Chinese pack first and short-circuits, so on the first passthe English number does not exist yet. A one-shot parser crashes here; this is instrument
shape, not a defect in the change.
(
(?<![A-Za-z0-9_.-])key(?![A-Za-z0-9_.-])) overui/index.html+ui/js/app.js+ui/js/api.js+ui/README.md(JS comments stripped;ui/js/i18n.jsexcluded — it is thepack) → 23/23 keys hit 0. Predicate shown to be tight, not loose:
common.copyexact = 0while the live
settings.ak.copyexact = 4.ui/js/i18n.js(zh + en) → 46 lines removed; all 23 are present in the 59-pair sunset list.
ZH_KEY_COUNT == EN_KEY_COUNT == 788; the pack files staysymmetric (zh key set == en key set).
green against a mirror carrying the whole queue plus this change — so the shortened list does
not depend on a later item in the series.
cargo test302/0 (baseline on the same treebefore the edit: 302/0),
cargo fmt --checkclean,cargo clippy --all-targets -- -D warningsclean. The count above is the measured one, not the projection the draft carried (the draft
projected ~299 because the series was shorter when it was written).
Checklist
refactor/…) — see the correction in §0 of the work orderchore(i18n): …)main)old-designkeys, no consumer edits)