-
Type:
Bug
-
Resolution: Unresolved
-
None
-
Affects Version/s: None
-
Component/s: Export
-
High
-
None
-
SDLXLIFF Export: Fix invalid tag structure on segments with nested track changes
-
None
-
Emptyshow more show less
Problem
When exporting translations with track changes back to SDLXLIFF, segments that contain nested track changes (for instance, an addition or styling edit nested inside another addition) along with inline formatting tags produce corrupted XML or fail export validation.
What was happening:
- Nested revisions were mangled: TrackChangesFormatter assumed that any element inside a revision block (<mrk>) was an internal formatting tag (<div>). When a revision was nested inside another revision, the formatter treated the inner <mrk> container as a regular tag and deleted/overwrote it, losing parts of the tracked changes.
- Invalid tag wrapping: When an opening formatting tag (like <g id="1086">) was opened before a tracked change and closed inside it without containing any visible text, the exporter attempted to wrap the entire tracked change or left unclosed tags at the end of the segment. In SDLXLIFF, such empty boundary tags must be self-closing (e.g. <g id="1086" sdl:end="false"/>).
- Closing tags in addition marks were missed: The logic that tracked whether an external tag had been closed within a revision block was only checking deletion blocks, missing tags that were closed inside added revisions.
Solution
Update TrackChangesFormatter to properly handle nested revision scopes and empty structure tags:
- Recursive Mark Processing: Extract processMrkNode() to recursively traverse nested <mrk> elements so each revision layer processes its own tags without overwriting child revisions.
- Self-closing Boundary Tags: Add hasNonWhitespaceBetween() to detect when an unclosed tag has no visible text before the next revision block. In these cases, it generates a self-closing marker tag (<g id="..." sdl:end="false"/>) instead of incorrectly wrapping the subsequent revision.
- Universal Scope Tracking: Track tags closed across all revision marks (both additions and deletions) to ensure matching open tags in the body are cleanly closed before track changes start.
- Test Coverage: Add and verify real-world test case Segment from real world 4 in TrackChangesFormatterTest.php.