A pseudo translation replaces every string with a recognisable fake. In a
left-to-right language, each letter is accented and the string grows inside
brackets: Save changes becomes ⟦Šáṽé çĥáñĝéš··········⟧. In a
right-to-left language, each string is reversed with a direction override, so
the page reads right to left even before Arabic or Hebrew exists.
On a page rendered this way, three problems become visible:
- Plain text did not come from the catalogue: it is written into the code or built at run time.
- Cut-off text did not leave room for longer languages.
- Layout that stays put in a right-to-left page uses left and right instead of start and end.
Free shipping on every order
Save changes⟦Šáṽé çĥáñĝéš··········⟧Prices include tax.⟦Þŕíçéš íñçļúðé ţáẋ.················⟧
Free shipping on every order
Save changesSave changesPrices include tax.Prices include tax.
- Text that did not come from the catalogue/{locale}/ · p#promo · “Free shipping on every order” · runtime_text (de-DE, ar-SA)
- Text cut off when it grows/{locale}/ · button#save · “⟦Šáṽé çĥáñĝéš··········⟧” · clipped_text (de-DE)
- Layout that does not mirror right to left/{locale}/ · p#note · “padding-left: 12px” · unmirrored_layout (ar-SA)
What the pseudo-localised pages show: the same page in German, with every string accented and longer, and in Arabic, reversed right to left. The probe marks text written into the code, a button that cuts its text off and a rule that stays on the left. Illustrative data.
In the Globalisation check
When the configuration file says how to start the app, the Globalisation check renders its pages on every change it checks. It works on a copy of the change in the check's own sandbox, so the fake translation never reaches your repository or other checks:
- It writes the pseudo translation into one left-to-right and one right-to-left language of the project.
- It installs the dependencies and starts the app.
- It opens every page in both languages in a browser set to that language, and reads what is on screen.
- It stops the app and deletes the copy.
What it finds becomes findings of the check:
| Code | What it finds |
|---|---|
runtime_text | Visible text without the pseudo marks |
clipped_text | Pseudo text cut off by its box, with overflow hidden or an ellipsis |
unmirrored_layout | In a right-to-left page: a page that is not right to left, text aligned or floated left or right, or an element placed, margined or padded by left or right |
The same text found in both languages is one finding. The findings appear in
the task's Issues found as the page, the element, the text and the
languages, such as /{locale}/ · p#promo · “Free shipping on every order” · runtime_text (de-DE, ar-SA).
They are reported and block nothing until you choose. Under Quality Control → Globalisation, Render pages turns the step off, and Page problems that send a change back for repair chooses which codes block.
An app that does not install or start is reported as not rendered, with its output, never as a clean render. It holds the change only when you block page problems.
Set it up
Add world.render to .coroid/i18n.json:
{
"world": {
"render": {
"start": "npm run dev",
"pages": ["/{locale}/", "/{locale}/pricing", "/{locale}/checkout"]
}
}
}| Field | Meaning |
|---|---|
start | Starts the app. It must listen on the port in $PORT; HOST is 127.0.0.1 |
pages | Up to ten paths, from the app's root. {locale} becomes the language's tag, so /{locale}/pricing opens /de-DE/pricing; use /?lang={locale} if the language is a query parameter |
directory | The app's folder in the repository, when it is not the root |
install | The command that installs dependencies. Without it, Coroid runs npm when a package.json declares any |
locales | Up to three target languages to render. Without it, the first left-to-right and the first right-to-left target |
readyTimeoutMs | How long the app may take to answer, 120,000 by default |
The browser also sends each language as its preferred language, so an app that
picks its language from the browser works without {locale}.
The field needs CLI 1.16.0 or later in the configuration's cli pin; an older
engine refuses the configuration.
What is left out
The check reads only what a person sees. It skips hidden elements, code
(code, pre, kbd, samp), form fields' own values, and elements marked
translate="no", aria-hidden="true", data-i18n-ignore or with the class
notranslate. Words in the configuration's world.allow list, such as product
names, are never reported as plain text.
Text that comes from your own data, such as product names or user content, is
not translated by the catalogue either. Mark its container translate="no" or
data-i18n-ignore, which also tells browser translation tools to leave it alone.
Try it yourself
The pseudo translation is part of the command-line tool. Run it in a throwaway checkout, because it replaces the language's translations:
coroid-i18n pseudo --locale de-DE # accented and longer
coroid-i18n pseudo --locale ar-SA # reversed, right to left
coroid-i18n pseudo --locale de-DE --style rtl # choose the style yourselfThen start the app and open its pages in that language. Placeholders, plural forms and markup stay intact, so the app works as usual. Markdown and MDX pages are left as they are.