Skip to content

test(l10n): ratchet the untranslated schema strings - #329

Merged
rubenvdlinde merged 2 commits into
developmentfrom
test/schema-l10n-ratchet
Aug 23, 2026
Merged

test(l10n): ratchet the untranslated schema strings#329
rubenvdlinde merged 2 commits into
developmentfrom
test/schema-l10n-ratchet

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

The gap

Every string inside a form comes from the OpenRegister schema, not the manifest. fieldsFromSchema() runs a property title and description through the injected cnTranslate, which CnAppRoot binds to this app's id — so a schema title is a key in this catalogue. When the key is absent, t() hands the source string back and the field renders in English inside an otherwise translated form. Nothing errors, and no existing check looks at this surface.

Measured across the fleet on 2026-08-23:

strings
Field + schema titles 9,718
Helper descriptions 16,064
Enum values 4,677
Total 30,459

Why a ratchet and not a gate

30,459 is far too much to translate in one pass — and the descriptions need rewriting for the person filling in the form before translating them is even worth doing. humaniq's own pass rewrote 592 of 739 descriptions (median length 108 → 76 characters) before a single word was translated; translating them as they stood would have cemented developer-facing copy in two languages.

So this records the current uncovered count and fails only when it grows. The debt is measured and cannot expand, while burning it down stays an ordinary PR. Same shape as the JSDoc baseline in @conduction/nextcloud-vue.

What counts

Counted: schema title, property title, property description, and the VALUES of x-enum-labels.

Not counted: enum values themselves — they are stored contract values, several non-English by design (ingediend), and are never rendered once a property declares its labels — and x-notes, which holds engineering rationale that is never rendered.

Verification

Must-fail control — inject one untranslated title:

1450 schema string(s); 1 uncovered, baseline 0

1 schema string(s) added with no catalogue key — they will render
in English inside an otherwise translated form.
$ echo $?
1

Lower the baseline as strings get translated: npm run check:schema-l10n -- --update

Every string inside a form comes from the OpenRegister schema, not from the
manifest: `fieldsFromSchema()` runs a property `title` and `description`
through the injected `cnTranslate`, which CnAppRoot binds to THIS app's id. So
a schema title is a key in THIS catalogue — and when the key is absent, `t()`
hands the source string back and the field renders in English inside an
otherwise translated form. Nothing errors, and no existing check looks.

Measured across the fleet on 2026-08-23: 30,459 schema strings had no
catalogue key. Far too much to translate in one pass, and the descriptions
need rewriting for the person filling in the form before translating them is
even worth doing — humaniq's own pass rewrote 592 of 739 before a word was
translated.

So this is a RATCHET, not a gate: it records how many strings are currently
uncovered and fails only when that number GROWS. The debt is measured and
cannot expand, while burning it down stays an ordinary PR. Same shape as the
JSDoc baseline in @conduction/nextcloud-vue.

Counted: schema titles, property titles, property descriptions, and the VALUES
of `x-enum-labels`. NOT counted: enum values themselves (stored contract
values, several non-English by design, never rendered once a property declares
its labels) and `x-notes` (engineering rationale, never rendered).

Verified must-fail: adding one untranslated title takes the count past the
baseline and exits 1, naming the file and property and the command that lists
what is uncovered.

Lower the baseline as strings get translated:
  npm run check:schema-l10n -- --update
…is repo

Two things the fleet CI caught.

`build-l10n-js.js` discovers locales by globbing `l10n/*.json`, which now also
matches `l10n/.schema-l10n-baseline.json` — the ratchet's own state file, kept
there so prettier ignores it. The generator read it as a locale named
`.schema-l10n-baseline` and exited 1 for having no `translations`. Dotfiles are
never locale catalogues, so it skips them.

Also prettier-normalised both scripts to this repo's config; several apps run a
format check over scripts/.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/launchpad @ f50ba55

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
format
check-schema-l10n
composer ✅ 104/104
npm ✅ 525/525
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-23 21:00 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit 887aa37 into development Aug 23, 2026
38 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/launchpad @ bd243c5

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
format
check-schema-l10n
composer ✅ 104/104
npm ✅ 525/525
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-23 21:38 UTC

Download the full PDF report from the workflow artifacts.

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