FEATURE: Synchronization - #102
Open
JamesAlias wants to merge 86 commits into
Open
Conversation
…and is correctly translated/synced
…ening; Add sync to backend module
Resolves conflicts after the branch's base (retranslationUpmerge, PR sitegeist#95) was merged into 3.x and released as v3.3, and 3.3 then gained independent retranslation work (notably whole-workspace retranslation). Key resolutions: - Retranslator: keep this branch's cross-workspace per-node engine, renamed retranslateNode -> retranslateSubtree to match released v3.3; keep 3.3's retranslateWorkspace() + helpers (both whole-workspace paths kept, alongside FullWorkspaceSynchronizer). Callers renamed accordingly. - ReferenceDimensionSpacePointResolver: adopt 3.3's options.referenceLanguage config key; keep this branch's findAllTargetDimensionSpacePoints() API. All dimension-config fixtures/settings updated to options.referenceLanguage. - StaleTranslationProjection: keep this branch's handlers (empty structural rows retained); keep 3.3's automaticTranslation guard where auto-merged. - Neos.Ui: take 3.3's contentRepositoryId + isPending; Plugin.js rebuilt. - CI/tooling: take 3.3's phpcs.xml.dist + phpstan scanDirectories; keep this branch's Behat job. - Behat: keep this branch's suites; 3.3's workspace-retranslation scenario preserved in a new standalone WorkspaceRetranslation.feature.
…e with composer stability exception when installing neos/builtessentials
…on fix to behat jobs as well
…uth) leak; Remove retranslateWorkpace - keep workspace synchronization; Fix unwanted workspace rebasing
… for rule in Backend Module
JamesAlias
marked this pull request as ready for review
July 30, 2026 11:03
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.
Overview
Rule-based, automatic reconciliation of translations across workspaces and/or dimensions, built on the stale-translation projection that came with Retranslation. Where the inspector's Retranslate button is a per-node, on-demand action, a synchronization rule keeps a target dimension continuously in step with its source: content published into
live/enis translated intode-review/de, reviewed there, and published from there.Configuration is based on #54 by @mficzel:
Rules are opt-in — the default is
[], and with no rules configured nothing in this PR runs.Under the Hood
The design rests on one core decision:
A rule has only two knobs:
scopegoverns what synchronization may create, and nothing else.Contentonly fills in content below Documents that already exist in the target (adopting a Document into a language stays a deliberate manual act);Documentalso creates the missing Document variants.modegoverns when the translation runs, never what synchronization does. For the same source-side change both modes reach the same target state. Everything cheap runs inline on every publish under either mode — subtree tags, deletions, the cross-workspace rebase. Only translating, which costs a DeepL call per node, is deferred byask.Two consequences worth reviewing explicitly:
removedsubtree tag, so deletions ride the tag mirror — and restoring from the trash bin mirrors back, which the old hard-removal mirror could never do. AnySubtreeTagis mirrored, not a fixed list; sync owns the target dimension's whole tag space.Entry points
SynchronizationCommandHookWorkspaceSynchronizerlostintranslation:synchronizeFullWorkspaceSynchronizerlostintranslation:synchronize --fullrun at all (target workspace missing — rules never create it — or target not based on the source workspace,
which a cross-workspace rule requires). A blocked rule reports no pending count, because nothing would act
on it. A fresh install without
./flow cr:setupgets a guidance banner instead of an error.mode: askrules ("translations are out of date — synchronizenow?").
autorules need none.lostintranslation:synchronize(--full,--dry-run,--skip-existing),lostintranslation:retranslate-node,lostintranslation:reconcile(prunes orphaned stale rows left bydescendants of deleted aggregates).
Notes
uriPathSegmentslug coercion moved out of two hardcodedif ($name === 'uriPathSegment')sites into aper-property
TranslatedPropertyPostProcessorInterface(options.translationPostProcessor, read parallel tooptions.automaticTranslation).UriPathSegmentPostProcessoris registered onNeos.Neos:Document.uriPathSegmentbut inactive unless the integrator also enablesautomaticTranslationthere.
command hook factories return a no-op
DisabledCommandHookwhen the feature is off; they still throw when itis on, because a missing dimension under an enabled package is a real misconfiguration.
(
SynchronizationCommandHookmatches on set membership, and clears the tracker at the start of every publish).--dry-runis honest now. It previews variants, property updates, removals and tag changes withoutdispatching anything, without rebasing the target, and — the part that was actually broken — without paying
the full DeepL bill to produce a report of zeros.
Documentation/RetranslationAndSynchronization.md(811 lines) covers the projection, both features,all workflows, cross-workspace mechanics, superseded decisions and known gaps.
README.mdgains anintegrate-into-an-existing-project section and per-command reference.
TESTING.mddocuments the harness.make e2e, ~9s for the full suite) plus a Behatjob in the GitHub workflow across PHP 8.2–8.4 × Neos 9.0–9.1; the build now also runs on
3.*branches.