Skip to content

refactor(i18n): delete 523 duplicated strings; move the legal controls to the source - #593

Merged
mrviduus merged 1 commit into
mainfrom
chore/locale-drop-duplicates
Sep 9, 2026
Merged

refactor(i18n): delete 523 duplicated strings; move the legal controls to the source#593
mrviduus merged 1 commit into
mainfrom
chore/locale-drop-duplicates

Conversation

@mrviduus

@mrviduus mrviduus commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Slice 3 of five, and the one the golden fixtures were built for.

Every key in web's file whose value was byte-identical to shared's is gone: 1193 → 670 keys, 72 KB → 40 KB, four namespaces (about, privacy, search, terms) vanishing whole. Web resolves them through the merge now.

The golden fixtures did not change by one character. That is the entire proof this slice needed — 606 deleted lines and not one string a reader can see moved. Had the script been wrong, the fixture would have said which key and what it became.

Why the legal work is in this PR and not a later one

privacy and terms were 54 and 36 keys, all identical, so they left web's file completely. The four deep-equality assertions in legalParity.test.ts compared web's copy to shared's; with one copy left they assert nothing. Deleting them without a replacement would leave a window with no control at all on text Google Play reads from the store-listing URL.

They are replaced by two things, both here:

  • packages/shared/src/i18n/legalContent.test.ts — the content rules, moved next to the file they describe, verbatim and with their reasons: the AI-retention disclosure must still say "indefinitely"; the third-party list must still name all seven processors; the policy must not have crept back to claiming data is browser-only or never shared. These were never about parity.
  • apps/web/src/locales/__tests__/legalShadow.test.ts — the inverted guard: web's overlay may not contain privacy.*, terms.*, library.insights.* or library.discuss.* at all.

"Two files must match" becomes "there is one file and web may not override it" — strictly stronger, because it also catches a divergence nobody thought to write an assertion for.

Verification

Both guards mutation-verified, not assumed: giving web its own privacy.title and library.insights.title fails the shadow guard on exactly those two and names the reason; reverting restores green.

Browser-checked /en/privacy, /en/terms, /en/about, /en/search and /en/books — the four namespaces that left web's file entirely — all render real headings with no key literals leaking through.

🤖 Generated with Claude Code

https://claude.ai/code/session_011rgEMvYYi4Egj99dVtvm6E

…s to the source

Slice 3 of five, and the one the golden fixtures were built for. Every key in
web's file whose value was byte-identical to shared's is gone: 1193 → 670 keys,
72 KB → 40 KB, four namespaces (`about`, `privacy`, `search`, `terms`) vanishing
whole. Web resolves them through the merge now.

**The golden fixtures did not change by one character.** That is the entire proof
this slice needed — 606 deleted lines and not a single string a reader can see
moved. Had the script been wrong, the fixture would have said which key and what
it became.

`privacy` and `terms` were 54 and 36 keys, all identical, so they left web's file
completely — which is why the legal work is in this PR and not a later one. The
four deep-equality assertions in `legalParity.test.ts` compared web's copy to
shared's; with one copy left they assert nothing. Deleting them without a
replacement would leave a window with no control at all on text Google Play reads
from the store-listing URL.

So they are replaced by two things, both here:

- `packages/shared/src/i18n/legalContent.test.ts` — the CONTENT rules, moved next
  to the file they describe, verbatim and with their reasons: the AI-retention
  disclosure must still say "indefinitely"; the third-party list must still name
  all seven processors; the policy must not have crept back to claiming data is
  browser-only or never shared. These were never about parity.
- `apps/web/src/locales/__tests__/legalShadow.test.ts` — the inverted guard: web's
  overlay may not contain `privacy.*`, `terms.*`, `library.insights.*` or
  `library.discuss.*` at all. "Two files must match" becomes "there is one file
  and web may not override it", which is strictly stronger — it also catches a
  divergence nobody thought to write an assertion for.

Both mutation-verified rather than assumed: giving web its own `privacy.title`
and `library.insights.title` fails the shadow guard on exactly those two and
names the reason; reverting restores green.

783 web + 449 shared + 385 mobile tests green; web typecheck clean. Browser-checked
/en/privacy, /en/terms, /en/about, /en/search and /en/books — the four namespaces
that left web's file entirely — all render real headings with no key literals
leaking through.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rgEMvYYi4Egj99dVtvm6E
@mrviduus
mrviduus merged commit 81f741a into main Sep 9, 2026
10 checks passed
@mrviduus
mrviduus deleted the chore/locale-drop-duplicates branch September 9, 2026 03:56
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