Offer "Pseudo-English" (qps-ploc) as a UI language for i18n testing (BL-16748) - #8283
Offer "Pseudo-English" (qps-ploc) as a UI language for i18n testing (BL-16748)#8283andrew-polk wants to merge 1 commit into
Conversation
|
| Filename | Overview |
|---|---|
| src/BloomExe/Program.cs | Configures pseudo-localization before localization-manager initialization and safely falls back to English on channels where it is unavailable. |
| src/BloomExe/Workspace/WorkspaceView.cs | Adds a stable pseudo-locale label and places it last in the language menu while preserving existing selection behavior. |
| src/BloomExe/web/I18NApi.cs | Applies pseudo-localization to English fallback responses that bypass normal L10NSharp lookups, while excluding numeric IDs. |
| src/BloomExe/Book/TranslationGroupManager.cs | Prevents the testing-only pseudo-locale from generating persisted translated content in books. |
| src/BloomExe/web/controllers/CommonApi.cs | Excludes qps-ploc from the language chooser used to author persistent hint content. |
| src/BloomBrowserUI/react_components/TopBar/TopBar.tsx | Adds a stable language-independent data attribute to workspace tabs for automation. |
| .github/skills/bloom-automation/switchWorkspaceTab.mjs | Prefers the new stable workspace-tab selector while retaining legacy label-based fallbacks. |
| src/BloomTests/Workspace/PseudoLocalizationTests.cs | Covers pseudo-locale naming/completeness and non-development channel gating, though not the I18N fallback branches. |
| src/BloomExe/BloomExe.csproj | Upgrades L10NSharp to the beta version providing runtime pseudo-localization support. |
Reviews (1): Last reviewed commit: "Merge remote-tracking branch 'origin/mas..." | Re-trigger Greptile
|
[Claude Opus 5 (1M context) during preflight] Consulted Devin on 2026-09-02 18:29 UTC up to commit Clean: no bugs, no Investigate flags, no informational items. Nothing to mirror. |
c64f5ad to
a436f8e
Compare
d9a2a3e to
41ba906
Compare
SetUpLocalization normalizes a stored qps-ploc to English on channels that don't offer the locale, but it runs at Program.cs:228 and the previous version's settings are migrated at :380 — and that migration ends in Reload(), which throws the normalized value away. A tester who picked Pseudo-English in an alpha would then hit the ungated SetUILanguage(Settings.Default.UserInterfaceLanguage) further down and get a release build with a mangled UI and no menu entry to escape it, which is the exact outcome the guard exists to prevent. Extract the guard as RefusePseudoLocaleWhereNotOffered and re-apply it right after the migration, where it covers both later SetUILanguage calls. It is a no-op when no migration happened or when the channel does offer the locale. Found by Devin on PR #8283. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
[Claude Opus 5 (1M context) from Andrew Polk's machine during preflight] Consulted Devin on 2026-09-11 18:53 UTC up to commit It raised one Bug and two Investigate flags, each its own resolved thread:
No Informational items either round. CI ( Note the branch has since been collapsed to a single commit, so |
…BL-16748)
We have no way to see which of Bloom's on-screen strings actually go through
localization. A hard-coded string, a mangled placeholder, a label the layout
clips once it grows -- all of it looks fine in English, and only surfaces when
a translator or a user in another language hits it.
On the developer and alpha channels the UI Language menu now offers
"Pseudo-English (i18n test)". L10NSharp 10.1.0-beta0001 transforms the live
English at lookup time for the standard qps-ploc pseudo-locale -- each vowel
doubled and accented, the whole string bracketed, so `Title Missing` becomes
`[Tiitlee Miissiing]`. A tester reads the problems straight off the screen:
plain English means the string was never internationalized, a visible {0} or
%0 means a broken placeholder, a missing ] means truncation, brackets
mid-sentence mean the sentence is concatenated at runtime, and clipped layout
means we cannot absorb the ~30-40% growth real translations bring. No qps-*
translation files exist or are ever written.
- Program.SetUpLocalization turns the locale on for the developer and alpha
channels only, and GetDesiredUiLanguage falls back to English if a build
that does not offer it nonetheless finds qps-ploc stored.
- WorkspaceView names the locale itself, since Palaso's language-name lookup
has nothing useful to say about a pseudo-locale, and puts it last in the
menu rather than sorting it among real languages.
- I18NApi pseudolocalizes the English fallback it returns for ids that are not
in the English XLIFF. Without this those come back as plain English and are
indistinguishable from hard-coded text, which defeats the exercise.
- The locale is excluded from the two places where the list of available
localizations feeds book data rather than the UI: the pre-translated content
TranslationGroupManager writes into a new book, and the hint-bubble language
chooser.
- Several UI strings mark their hyperlink words with [square brackets].
Because pseudo-localization brackets the whole string as well, the five
parsers that took the first [ and the next ] swallowed the sentence into the
link and ate the wrapper -- making those strings look un-internationalized,
which is the one thing this locale must never get wrong. A shared
findLinkTextBrackets() now anchors on the first ] and takes the nearest [
before it, and the markdown link regex no longer allows [ inside link text.
- DistFiles/localization/README.md documents that the locale is runtime
derived, that no qps-* XLF should ever exist, and which surfaces stay plain
English on purpose, so the tester's rule stays exact.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
db7c2aa to
469e556
Compare
Problem
Nothing in Bloom shows which on-screen strings actually go through localization. A hard-coded string, a mangled placeholder, a label the layout will clip once the text grows — all of it looks fine in English, and only surfaces when a translator or a user in another language hits it.
What the PR does
On the developer and alpha channels, the UI Language menu now offers Pseudo-English (i18n test). L10NSharp 10.1.0-beta0001 transforms the live English at lookup time for the standard
qps-plocpseudo-locale — each vowel doubled and accented, the whole string bracketed, soTitle Missingbecomes[Tîitlée Mîissîing]. A tester then reads the problems straight off the screen: plain English means the string was never internationalized, a visible{0}or%0means a broken placeholder, a missing]means truncation, brackets mid-sentence mean the sentence is concatenated at runtime, and clipped layout means we can't absorb the ~30–40% growth real translations bring. Noqps-*translation files exist or are ever written.Program.SetUpLocalizationturns the locale on for the developer and alpha channels only, andGetDesiredUiLanguagefalls back to English if a build that doesn't offer the locale nonetheless findsqps-plocstored, so nobody is left with a mangled UI and no menu entry to escape it.WorkspaceViewnames the locale itself (Palaso's language-name lookup has nothing useful to say about a pseudo-locale) and puts it last in the menu rather than sorting it among real languages.I18NApipseudolocalizes the English fallback it returns for ids that aren't in the English XLIFF. Without this those come back as plain English and are indistinguishable from hard-coded text, which defeats the exercise.TranslationGroupManagerwrites into a new book, and the hint-bubble language chooser.[square brackets]. Because pseudo-localization brackets the whole string as well, the five parsers that took the first[and the next]swallowed the sentence into the link and ate the wrapper — making those strings look un-internationalized, which is the one thing the locale must never get wrong. A sharedfindLinkTextBrackets()now anchors on the first]and takes the nearest[before it (the innermost pair, correct in both plain and pseudo-localized text), and the markdown link regex no longer allows[inside link text.DistFiles/localization/README.mddocuments that the locale is runtime-derived, that noqps-*XLF should ever exist, and which surfaces stay plain English on purpose (the whole-file localizations — template readmes, help pages, xmatter descriptions), so the tester's rule stays exact.switchWorkspaceTab.mjsgets a label-independent fast path, since matching a tab by its visible English label fails under this locale.Ref: https://issues.bloomlibrary.org/youtrack/issue/BL-16748
Devin review
This change is