Skip to content

refactor(procest): translate 139 pre-existing Dutch property names - #842

Merged
rubenvdlinde merged 6 commits into
developmentfrom
tr2/english-vocabulary
Aug 15, 2026
Merged

refactor(procest): translate 139 pre-existing Dutch property names#842
rubenvdlinde merged 6 commits into
developmentfrom
tr2/english-vocabulary

Conversation

@rubenvdlinde

@rubenvdlinde rubenvdlinde commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Tranche 2 of the Dutch→English vocabulary programme, and the largest app so far:
179 Dutch names measured, 139 renamed, 22 held back with a recorded reason.

The map was drafted, not hand-written

Generated from the tranche-1 token dictionaries, then reviewed. The generator
splits rather than guesses: resolved when every token of the RESULT is
provably English, partial when any token is not, refused when the name is a
schema slug, a lifecycle value, or would collide inside its own schema. It
surfaced 7 partials needing a new token and 21 refusals — 28 names to read
instead of 179.

An early version called aangezochtBevoegdGezagaangezochtCompetentAuthority
"resolved": it applied translations only to tokens the Dutch wordlist knew, and
aangezocht is a participle the wordlist does not carry, so it passed through as
if it were English. It now applies any known translation and then verifies
every result token is English
— the property that actually matters.

Five things this app renamed that are not property names

Each caught by a test, each now excluded by path:

what why it must not move
StUF/ZKN adapters <zkn:omschrijving/> became <zkn:description/>, and getElementsByTagName('referentienummer') became 'referenceNumber'. Element names in a published standard — Dutch by specification.
ZGW mapping config zgw_mapping_zaak is a stored app-config key.
Email templates {{omschrijving}} is a placeholder, not an identifier.
MandaatCsvParser REQUIRED_COLUMNS are the headers of the CSV a user uploads. One of four was translated — the same shape as tranche 1's DSO defect.
triggerTerugvordering Both a property and a service method. The applier renames calls but not the declaration, so the test moved and the service did not.

Plus two more X ?? X tautologies from dual-spelling fallbacks written with
parentheses — $zioData['zaak'] ?? ($zioData['case'] ?? ''). The guard added for
softwarecatalog only matched the unparenthesised form. psalm names these
precisely (ParadoxicalCondition), which is the only reason they were not
shipped: collapsing the pair silently stops accepting the old spelling.

Verified against a control run of the same tree

check this branch control
PHPUnit 1899, 4 errors, 2 failures 1899, 4 errors, 2 failures
phpstan [OK] [OK]
psalm No errors found! No errors found!
vitest 349/349
eslint / prettier / build 0 / clean / OK
routes resolved / broken 383 / 0
slugs changed 0
surviving uses in src/ 0

139 migration entries appended; the map has 452 entries with no duplicate and no
identity pairs.

Tranche 2, and the largest so far: 179 Dutch names measured, 139 renamed, 22 held
back with a machine-recorded reason, 18 already covered.

The map was DRAFTED from the tranche-1 token dictionaries rather than written by
hand, then reviewed. The generator splits rather than guesses — resolved when
every token of the RESULT is provably English, partial when any token is not,
refused when the name is a schema slug, a lifecycle value, or would collide
inside its own schema. It found 7 partials that needed a token
(`afwijkend`, `deurwaarders`, `geadviseerde`, `inkomens`, `juridische`,
`overschreden`) and 21 refusals, and I only had to read those 28.

An early version called `aangezochtBevoegdGezag -> aangezochtCompetentAuthority`
"resolved": it applied translations only to tokens the DUTCH WORDLIST knew, and
`aangezocht` is a participle the wordlist does not carry, so it passed through as
if it were English. It now applies any known translation and then verifies every
RESULT token is English — which is the property that actually matters.

FIVE THINGS THIS APP RENAMED THAT ARE NOT PROPERTY NAMES, each caught by a test
and each now excluded by path:

  StUF/ZKN adapters      `<zkn:omschrijving/>` became `<zkn:description/>` and
                         getElementsByTagName('referentienummer') became
                         'referenceNumber'. Those are element names in a
                         PUBLISHED STANDARD — Dutch by specification.
  ZGW mapping config     `zgw_mapping_zaak` is a STORED app-config key.
  Email templates        `{{omschrijving}}` is a placeholder, not an identifier.
  MandaatCsvParser       REQUIRED_COLUMNS are the headers of the CSV a user
                         uploads. One of four was translated — the same shape as
                         the DSO defect in tranche 1.
  triggerTerugvordering  Both a property and a service METHOD. The applier
                         renames method CALLS but not the DECLARATION, so the
                         test moved and the service did not.

And two more `X ?? X` tautologies, from dual-spelling fallbacks written with
parentheses — `$zioData['zaak'] ?? ($zioData['case'] ?? '')`. The guard added for
softwarecatalog only matched the unparenthesised form. psalm names these
precisely (ParadoxicalCondition), which is the only reason they were not shipped:
collapsing the pair silently stops accepting the old spelling.

VERIFIED against a control run of the same tree: PHPUnit 1899 tests with
IDENTICAL errors and failures on both sides (4 errors, 2 failures, all
pre-existing); phpstan [OK] both; psalm "No errors found!" both; vitest 349/349;
eslint 0; prettier clean; build OK; 383 routes resolved, 0 broken; 0 slugs
changed; 0 surviving uses in src/. 139 migration entries appended; the map has
452 entries with no duplicate and no identity pairs.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/procest @ 4c51bf8

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

Quality workflow — 2026-08-14 19:03 UTC

Download the full PDF report from the workflow artifacts.

Conduction Release Bot added 3 commits August 14, 2026 21:31
phpmd caps a variable name at 20 characters and `$escalationRecommended` is 21 —
the rename lengthened it. The ARRAY KEY it feeds is the property and is
unaffected; only the local moves, to `$escalationAdvised`. phpmd is green on
development, so this one was mine.

Also merges development's 2 commits (the ZGW volume-ceiling fix and a CI change).
The merge is clean and brought in no code using the old Dutch names — re-running
the applier over the merged tree reports 0 substitutions, which is the check that
matters after a merge: development can always add fresh code using names this
branch has already moved.

The remaining PHPUnit cell failure is the coverage ratchet at 0.01% — 46789
statements on both sides, 4 fewer COVERED. Nothing was added; four statements
stopped being reached. Re-measuring against the refreshed merge base.
The coverage ratchet was right and I had read it as noise. 46789 statements on
both sides, **4 fewer COVERED** — nothing added, four statements stopped being
reached. Chasing those four found a real defect.

Excluding the StUF/ZGW adapters protected their published wire element names —
`<zkn:omschrijving/>`, `getElementsByTagName('referentienummer')` — but those same
files also read OUR properties off our own objects:
`$case['zaakIdentificatie']`, `$data['externIdentificatie']`,
`$row['synchronisatieStatus']`. The rename moved the objects to English and left
the adapters reading keys that no longer exist. A missing subscript is `null`, so
nothing threw; the only trace anywhere was four statements dropping out of
coverage.

THE RULE, now enforced by the applier: **a file excluded from the rename pins
every property it reads.** Half-excluding a file is worse than either choice made
whole. 13 names pinned — zaakIdentificatie, externEntiteit, externIdentificatie,
laatsteSynchronisatie, synchronisatieStatus, fout, zaakIdentificatieStrategie,
bronId, authenticatie, gebruikersnaam, wachtwoordKluisRef, ontvangenOp,
omschrijving — leaving 126 renames.

The tree is RE-DERIVED from `origin/development` with the corrected map rather
than patched. Reverting `description` -> `omschrijving` and `error` -> `fout` in
place would have hit every pre-existing English `description` and `error` in the
app; re-deriving produces exactly the tree the corrected map would have made in
the first place, and needs no history rewrite.

Also carries the phpmd fix (`$escalationRecommended` is 21 chars against a
20-char cap; the array key it feeds is unaffected).

VERIFIED against a control run of the same tree: PHPUnit 1899 with IDENTICAL
errors and failures (4/2, all pre-existing); psalm "No errors found!"; phpstan
[OK]; vitest 349/349; prettier clean; 383 routes resolved, 0 broken; 126
migration entries, no duplicate or identity pairs. The two remaining src/ hits
are `fout` and `zaakIdentificatieStrategie` — both pinned, both still declared by
the schema, so those reads are correct.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/procest @ 56c5f82

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

Quality workflow — 2026-08-14 19:47 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/procest @ 1db16cf

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

Quality workflow — 2026-08-14 20:05 UTC

Download the full PDF report from the workflow artifacts.

…nslated

A PRODUCTION DEFECT already on `development`, found while chasing four missing
covered statements. #832 renamed five StUF element names, and an element name is
not ours to translate:

  StufZknMessageResponder::extractFields() passes each entry of `fieldNames`
  straight to getElementsByTagName(). `toelichting` had become `notes` and
  `einddatum` had become `endDate`, so those two tags never matched and the
  fields were silently dropped from every inbound zakLk01.

  StufFieldMappingService's mapping tables key on the ELEMENT name on the LEFT
  and the internal property on the RIGHT. Three ZKN keys (`toelichting`,
  `einddatum`, `registratiedatum`) and two BG keys (`geslachtsnaam`,
  `voornamen`) had been translated, so those fields never mapped either.

Restored all five, verified by diffing every mapping key against the last commit
before the vocabulary programme: **0 keys now differ from the specification.**

I NEARLY BROKE A SIXTH THE OTHER WAY. `DEFAULT_ZENDER` looks like the same shape
— `'organisation' => 'Procest'` next to `'applicatie' => 'Procest'`, one
translated and one not. It is NOT an element list: StufResponseBuilder hardcodes
`<stuf:organisatie>` and reads the array by key, so the English key is correct
and "fixing" it would have emitted an empty element. The difference is only
visible in the CONSUMER, which is the thing to read before deciding.

VERIFIED: PHPUnit 1899 with identical errors and failures to a control run of the
same tree (4/2, all pre-existing), phpstan [OK], psalm "No errors found!".
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/procest @ 83db14f

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

Quality workflow — 2026-08-14 20:46 UTC

Download the full PDF report from the workflow artifacts.

The coverage cell was failing for -7 statements and nothing else was red. The
clover diff put all of it in one file: StufMessageBuilder, 179 covered on
development and 171 here.

Cause: I excluded the whole StUF directory from the rename to protect the wire
element names, and that exclusion covered the TESTS as well. The source moved on
— it reads `$endpoint['freeMessagesTemplates']`, `['senderOrganisation']`,
`['recipientApplication']` — while the fixtures went on supplying
`vrijeBerichtenTemplates`, `zenderOrganisatie`, `ontvangerApplicatie`. Six keys.

Every read returned null, the free-message template branch was never entered, and
THE TESTS STILL PASSED, because they assert on the envelope they get rather than
on the branch being taken. The only signal was eight statements quietly leaving
coverage. That is the ratchet earning its place: no test failed, no analyser
complained, and the code under test was not being reached.

An endpoint CONFIG key is ours. Only the XML tag names belong to the
specification, and those are untouched — verified separately: every mapping key
in StufFieldMappingService matches the pre-programme spec names, 0 differ.

VERIFIED: PHPUnit 1899 with 4 errors and 2 failures, identical to a control run
of the same tree, and the eight statements are exercised again.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/procest @ ed0ef76

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

Quality workflow — 2026-08-14 21:29 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit 307cd27 into development Aug 15, 2026
41 of 43 checks passed
@rubenvdlinde
rubenvdlinde deleted the tr2/english-vocabulary branch August 15, 2026 05:29
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