Skip to content

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

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

test(l10n): ratchet the untranslated schema strings#712
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/stackiq @ 4b4fc5f

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

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

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/stackiq @ 06452e4

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

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

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit ccd57b3 into development Aug 23, 2026
45 checks passed
@rubenvdlinde
rubenvdlinde deleted the test/schema-l10n-ratchet branch August 23, 2026 21:28
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