fix(translator): pair localized blocks/arrays by id across locales#31
Open
SearheiParkhamchuk wants to merge 1 commit into
Open
fix(translator): pair localized blocks/arrays by id across locales#31SearheiParkhamchuk wants to merge 1 commit into
SearheiParkhamchuk wants to merge 1 commit into
Conversation
The translation pipeline paired source and target array/block elements by position in two places. When a localized blocks/array field is reordered or independently authored per locale, position no longer identifies the same element: - DataReconciler merged each source block with whatever target block sat at the same index — values leaked between unrelated blocks. - FieldChunkCollector fed the wrong element's value into strategy.shouldTranslate, so under skip_existing a block needing translation was silently skipped (and an already-translated one re-sent). Extract a shared `matchElementById` helper (shared/field-traversal, beside resolveBlockFields) used by both sites: pair the target by id (and, for blocks, blockType); no match falls back to source. The walkFields engine stays data-agnostic — pairing is caller-side. Non-localized fields share the id across locales (behaviour unchanged, now order-robust); independent localized content has diverging ids, so we mirror source instead of grafting mismatched values. Adds the "Cross-locale block identity" design doc and tests: matchElementById unit tests, reconciler reorder/independent/different-type cases, and a collector reorder-under-skip_existing regression. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
Problem
The translation pipeline paired source/target array & block elements by position in two places. When a localized
blocks/arrayfield is reordered or independently authored per locale, position no longer identifies the same element:DataReconcilermerged each source block with whatever target block sat at the same index → values leaked between unrelated blocks (blockTypefrom one, values from another).FieldChunkCollectorfed the wrong element's value intostrategy.shouldTranslate→ underskip_existing, a block needing translation was silently skipped (a populated, unrelated block sat at its index) and an already-translated one re-sent.Same root cause as the per-field translate control will hit — there is no cross-locale block identity for localized blocks (independent per-locale partitions).
Fix
Extract one shared helper
matchElementByIdintoshared/field-traversal(besideresolveBlockFields), used by both pipeline sites: pair the target element byid(and, for blocks,blockType); no match → fall back to source. ThewalkFieldsengine stays data-agnostic — pairing is caller-side.blockTypeHonest limit: removes the corruption / wrong-skip; it does not make
skip_existingpreserve per-block target edits for genuinely-independent localized blocks — no identity to preserve them by. See the design doc.Scope
Document-level pipeline only. The field-level per-field control (separate feature) gets its own guard (refuse with a notice under a localized blocks/array ancestor) — tracked in the design doc, ships with that feature.
Tests / verification
matchElementByIdunit tests (kernel.test.ts)skip_existingregression (collects the right block, skips the right one)check-types✓ ·ultracite✓ ·vitest688 passedDesign:
packages/payload-plugin-translator/docs/plans/2026-06-12-cross-locale-block-identity.md🤖 Generated with Claude Code