The Globalisation check in Quality Control keeps an internationalised project world-ready. It runs on task QA and on pull requests, and reads only what a change touched:
- Catalogues. The strings the change added or changed, in every language.
- Code. The lines the change adds, for text and formatting that assume one language or one culture.
- Pages. When the project says how to start its app, its pages rendered with a pseudo translation.
The wizard turns the check on by default once its pull request is merged. Its settings are in Quality Control → Globalisation; the workbench's Settings shows whether it is on.
What blocks by default
A change goes back for repair when it leaves strings missing or broken, or when the code it adds puts text people read straight into the code or assembles a sentence from parts. Everything else is reported as a finding and blocks nothing until you choose to block it. Formatting, sorting and layout findings stay reported until a project has seen them on its own code.
Choose what blocks under Quality Control → Globalisation: the catalogue codes, What in the code sends a change back, and Page problems that send a change back for repair. Check source code and Render pages turn the code and page steps off.
Catalogue codes
| Code | Meaning | Blocks by default |
|---|---|---|
missing | The string has no translation | Yes |
invalid_syntax | The translation does not parse, for example broken ICU | Yes |
placeholder_mismatch | Placeholders differ from the source | Yes |
plural_categories | A plural form the language needs is missing | Yes |
stale | The source changed after the string was translated | No |
Glossary, length and forbidden-term rules report their own codes when your configuration file sets them.
Code codes
| Code | What it finds | Blocks by default |
|---|---|---|
hardcoded_text | Text a person reads written into the code instead of the catalogue: JSX and template text, visible attributes such as placeholder, title, alt and aria-label, toasts and alerts | Yes |
concatenated_text | A sentence assembled from parts: a translation joined with text or a value by +, a template literal or neighbouring elements | Yes |
locale_number | A number formatted without the reader's locale, such as toFixed in UI code or toLocaleString() without a locale | No |
locale_date | A date or time formatted without the reader's locale, or with a fixed pattern such as MM/dd/yyyy | No |
hardcoded_currency | A currency symbol or code written next to an amount | No |
ordinal_sort | Text sorted or compared by character code, or localeCompare without a locale | No |
case_mapping | toUpperCase() or toLowerCase() on text without the locale | No |
physical_direction | Left and right in CSS and utility classes, in a project with a right-to-left language | No |
postal_code_format | A postal code validated with one country's pattern | No |
phone_number_format | A phone number validated as North American | No |
latin_only_input | A name, city, street or address limited to a–z | No |
joined_list | A list people read joined with a comma or "and" | No |
calendar_names | Weekday or month names written in the code, or a fixed first day of the week | No |
paper_size | Letter, A4 and the like fixed in print or PDF settings | No |
fixed_unit | A unit such as mi, lb or °F written next to a displayed number | No |
locale_parsing | A number a person typed read with parseFloat or Number | No |
ime_composition | Enter handled in a text input without checking that a Chinese, Japanese or Korean word is still being composed | No |
Design for every market shows the fix for each.
What the check reads
The code step parses JavaScript and TypeScript, with JSX, and reads Vue, Svelte, Astro, HTML, ERB and Handlebars templates and CSS as text. A rule applies only where its context names it: a postal code pattern is reported only next to a postal code field, and a joined list only where people read it.
- Translated by definition. Text inside the project's translation calls
and components (
t(),formatMessage,<Trans>,<FormattedMessage>,$t()) and the functions listed in the configuration file. - Never text. Protected terms, and the words the configuration file allows.
- Left out on purpose. A line with an
i18n-ignorecomment, and the line after it. Give the reason:// i18n-ignore: product name.
The optional world section of .coroid/i18n.json sets the rest:
{
"world": {
"exclude": ["src/legacy/**", "scripts/**"],
"translate": ["translateText", "i18n.translate"],
"allow": ["Storefront", "OK"]
}
}| Field | Meaning |
|---|---|
exclude | Globs of files the rules skip |
translate | Translation functions besides the frameworks' own |
allow | Words that are never translated, besides protected terms |
formatter, currencies | Set by the wizard's Culture step; see Culture |
render | How to start the app for pseudo-localised pages; see Pseudo-localisation |
Findings and repairs
Every finding is stored on the check's run and listed in the task's Issues found: catalogue findings by catalogue, key and language, code findings by file, line and the text found, page findings by page, element and text. A finding is fixed when the latest check of the same work no longer has it.
- Openui · checkout.total · fr: missingGlobalisation · Not translated
- Being fixedsrc/pricing.tsx:7 · “Simple pricing”Globalisation · Text written into the code
- Open/{locale}/ · p#promo · “Free shipping on every order” · runtime_text (de-DE, ar-SA)Globalisation · Text that did not come from the catalogue
- Being fixedui · cart.items · ja: placeholder_mismatchGlobalisation · Placeholders differ from the source
- Fixedui · cart.count · ar: plural_categoriesGlobalisation · Plural forms missing for this locale
Quality findings from the Globalisation check: catalogue strings, code a change added and a pseudo-localised page, one issue code per finding. Illustrative data.
On pull requests, code findings also appear as annotations on the changed lines: a failure when they block, a warning when they are only reported.
When the check blocks a task, the developer agent gets each blocking finding,
such as src/pricing.tsx:7 hardcoded_text: “Simple pricing”, with how to fix
it. It repairs translations through a translation session for the task, never
by editing other languages' catalogues by hand. It moves text into the source
catalogue, rewrites assembled sentences as one message with placeholders, and
runs the code rules on its own change before it hands the task over.
Contributions from every source
The check holds every change to the same standard, whoever wrote it:
- Coroid's agents working on an internationalised project are told in every task: the source catalogue and translation function, one message per sentence, the project's formatter, logical layout when a language is written right to left, and the markets' conventions from Culture.
- Pull requests from people and other tools get the check through Coroid Check, with the same findings and annotations. Turn on Review every PR to run it on every pull request.
- Changes merged without passing it are caught after the merge. Translate strings merged outside Coroid reads the check that ran on the pull request. It files a translation task when strings were left missing or out of date. When the check blocked code findings, it also files a task called Internationalise the code merged in the pull request, listing where to look. Each merge gets at most one task of each kind.
Existing code is never blocked: World readiness lists it and files fix tasks you start when you choose.
Run it yourself
The engine is the command-line tool coroid-i18n, the version pinned in your
configuration file:
coroid-i18n check # catalogues
coroid-i18n source --changed main # the code a branch adds since main
coroid-i18n check --source --changed mainsource reads the code without reading the catalogues, so it works even when
they are not set up yet. Without --changed or --diff it reads the whole
repository. Both commands exit with 1 when they find something; add
--format json for a machine-readable report.