refactor(procest): translate 139 pre-existing Dutch property names - #842
Merged
Conversation
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.
rubenvdlinde
requested review from
Rem-Dam,
SudoThijn,
WilcoLouwerse,
bbrands02,
remko48 and
rjzondervan
as code owners
August 14, 2026 18:46
Contributor
Quality Report — ConductionNL/procest @
|
| 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.
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.
Contributor
Quality Report — ConductionNL/procest @
|
| 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.
Contributor
Quality Report — ConductionNL/procest @
|
| 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!".
Contributor
Quality Report — ConductionNL/procest @
|
| 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.
Contributor
Quality Report — ConductionNL/procest @
|
| 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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
aangezochtBevoegdGezag→aangezochtCompetentAuthority"resolved": it applied translations only to tokens the Dutch wordlist knew, and
aangezochtis a participle the wordlist does not carry, so it passed through asif 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:
<zkn:omschrijving/>became<zkn:description/>, andgetElementsByTagName('referentienummer')became'referenceNumber'. Element names in a published standard — Dutch by specification.zgw_mapping_zaakis a stored app-config key.{{omschrijving}}is a placeholder, not an identifier.REQUIRED_COLUMNSare the headers of the CSV a user uploads. One of four was translated — the same shape as tranche 1's DSO defect.triggerTerugvorderingPlus two more
X ?? Xtautologies from dual-spelling fallbacks written withparentheses —
$zioData['zaak'] ?? ($zioData['case'] ?? ''). The guard added forsoftwarecatalog only matched the unparenthesised form. psalm names these
precisely (
ParadoxicalCondition), which is the only reason they were notshipped: collapsing the pair silently stops accepting the old spelling.
Verified against a control run of the same tree
[OK][OK]src/139 migration entries appended; the map has 452 entries with no duplicate and no
identity pairs.