Skip to content

Add qps-ploc pseudolocalization support - #158

Open
andrew-polk wants to merge 1 commit into
masterfrom
pseudolocalization
Open

Add qps-ploc pseudolocalization support#158
andrew-polk wants to merge 1 commit into
masterfrom
pseudolocalization

Conversation

@andrew-polk

@andrew-polk andrew-polk commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Problem

Applications built on L10NSharp have no good way for testers to verify internationalization. Hard-coded (non-localizable) strings, clipped layouts, broken format placeholders, and runtime string concatenation are invisible in an English UI and only surface after real translations arrive.

Fix

This PR adds the industry-standard qps-ploc pseudo-locale. Any lookup for language qps-ploc returns the live English text pseudolocalized — every vowel doubled with an accent on the first of the pair for ~30-40% in-word expansion, all wrapped in brackets (e.g. Title Missing[Tîitlée Mîissîing]) — with format placeholders ({0}, {0:n0}, named {app_title}-style, and %0-style) and HTML/XML tags passed through untouched. Plain English on screen then means a hard-coded string; a missing ] means truncation; brackets mid-sentence mean concatenation.

  • Lookups work by simply setting the language code (SetUILanguage("qps-ploc") or a per-call language list); all the lookup funnels (static, preferred-languages, dynamic, and the WinForms paths — both runtime lookups and designer-created controls, whose localizers read the string cache directly) are hooked, and the transform is applied exactly once. The code-supplied English wins over the cache, mirroring the existing en rule.
  • The pseudo-locale is derived from English at lookup time: no translation files exist, are loaded, or are written for it, it never maps to/from a real language, and it reports itself exactly as complete as English (availability and counts).
  • LocalizationManager.OfferPseudoLocalization (default false) gates only whether it is advertised in GetAvailableLocalizedLanguages()/GetUILanguages(), so end users never see the test locale unless the app opts in (e.g. alpha channels). Display name is hard-coded as "Pseudo-English (qps-ploc)".
  • The transform lives in an isolated, internal src/L10NSharp/Pseudo/ silo and adds no package dependency. The vowel-doubling style follows Mozilla’s pseudolocalization approach, chosen for readability after trying several styles live in Bloom; the MIT-licensed PseudoLocalizer project was the starting point, and its adapted placeholder/markup-skipping logic remains (attribution in the silo’s README). LocalizationManager.PseudoLocalize(string) exposes the transform for strings that bypass L10NSharp.

Additive only — no behavior change for consumers that never request qps-ploc. 31 new tests pin the transform behaviors and the lookup/gating semantics.


Devin review


This change is Reviewable

@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown

Test Results

    7 files  ±    0  144 suites  +20   27s ⏱️ +3s
218 tests +  31  213 ✔️ +  31    5 💤 ±0  0 ±0 
838 runs  +124  823 ✔️ +124  15 💤 ±0  0 ±0 

Results for commit 23cd79b. ± Comparison against base commit 36f0151.

♻️ This comment has been updated with latest results.

Comment thread src/L10NSharp/LocalizationManagerInternal.cs
@andrew-polk

Copy link
Copy Markdown
Contributor Author

[Claude Fable 5] Consulted Devin on 2026-08-21 up to commit 139d6fe. Across three review rounds it raised two bugs — an English-over-pseudo preference edge (fixed in c436838 before it reached GitHub) and a null preferred-language-id crash (fixed in 139d6fe, thread, resolved) — plus 6 informational notes assessed as not actionable. Final re-review is clean: 0 bugs, 0 investigate flags. CI green on all checks.

@andrew-polk

Copy link
Copy Markdown
Contributor Author

[Claude Fable 5] Consulted Devin on 2026-08-24 up to commit dd7f3a0 (the switch to the doubled-vowel transform). Re-review clean: 0 bugs, 0 investigate flags, 7 informational notes assessed as not actionable. CI green on all checks.

@andrew-polk

Copy link
Copy Markdown
Contributor Author

[Claude Fable 5] Consulted Devin on 2026-08-24 up to commit b5b346d. Re-review clean: 0 bugs, 0 investigate flags, 9 informational notes assessed as not actionable. CI green on all checks.

@andrew-polk
andrew-polk force-pushed the pseudolocalization branch 3 times, most recently from 3e71b88 to 0b956b2 Compare August 24, 2026 22:35
@andrew-polk

Copy link
Copy Markdown
Contributor Author

[Claude Fable 5] Consulted Devin on 2026-08-24 up to commit 303b495 (the WinForms designer-path fix and the master merge). Re-review clean: 0 bugs, 0 investigate flags, 9 informational notes assessed as not actionable. CI green on all checks.

Lookups for the standard qps-ploc pseudo-locale return the live English
text pseudolocalized at runtime — every vowel doubled with an accent on
the first of the pair, wrapped in brackets ("Title Missing" ->
"[Tîitlée Mîissîing]") — so testers can spot non-internationalized
strings (plain English), truncation (missing "]"), concatenation
(brackets mid-sentence), and layout problems (~30-40% in-word
expansion). Format placeholders ({0}, {0:n0}, named {app_title}-style,
and %0-style) and HTML/XML markup pass through untouched.

- Derived from English at lookup time: no translation files exist, are
  loaded, or are written for the pseudo-locale; it never maps to or from
  a real language; availability and counts report it exactly as complete
  as English.
- Lookups work by simply setting the language code; all lookup funnels
  are hooked (static, preferred-languages, dynamic, and the WinForms
  paths — both runtime lookups and designer-created controls, whose
  component localizers read the string cache directly), transforming
  exactly once, with code-supplied English winning over the cache as it
  does for "en".
- LocalizationManager.OfferPseudoLocalization (default false) gates only
  whether the locale is advertised in language lists; display name is
  hard-coded as "Pseudo-English (qps-ploc)".
- LocalizationManager.PseudoLocalize exposes the transform for strings
  that bypass L10NSharp.
- Self-contained in src/L10NSharp/Pseudo/ with no new package
  dependency; the placeholder-skipping logic is adapted from the
  MIT-licensed PseudoLocalizer project (attribution in the folder's
  README). 31 tests pin the transform and lookup semantics.

Smoke-tested end to end in Bloom (WinForms chrome incl. designer-created
dialogs, React UI, live placeholder substitution; no pseudo files
written).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@andrew-polk
andrew-polk marked this pull request as ready for review August 25, 2026 21:45
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