fix: code-fence balancing and depth tracking in chunked translation validation#1175
fix: code-fence balancing and depth tracking in chunked translation validation#1175lin-bot23 wants to merge 1 commit into
Conversation
…ation - Migrate toggleFence from bool toggle to depth counting to handle nested/multiple code blocks correctly. - Add fencesAreBalanced() helper to detect unclosed code fences in translated blocks. - validateTranslatedBlock rejects blocks with unbalanced fences. - Apply to all fence-aware functions for consistency.
📝 WalkthroughWalkthroughIn ChangesFence-depth Markdown parsing and validation
Possibly related PRs
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/scripts/i18n/chunked-translate.ts (1)
698-700:⚠️ Potential issue | 🟠 Major | ⚡ Quick winIntro blocks currently hop the fence-balance gate (Line 698).
_introreturnstruebefore the new balance check runs, so unclosed fences in intro content are still accepted. That can still swallow subsequent sections when content is re-parsed downstream.Suggested fix
- if (enBlock.label === "_intro") { - return true; - } - - // Must start with a level-2 heading. - if (!/^## (?![#])/.test(translated.trimStart())) { - return false; - } - // Validate code fence balance: every open fence must have a matching close. // Unmatched fences cause subsequent sections to be swallowed during re-parsing. if (!fencesAreBalanced(translated)) { const fenceLines = (translated.match(/^(```|~~~)/gm) || []).length; @@ return false; } + if (enBlock.label === "_intro") { + return true; + } + + // Must start with a level-2 heading. + if (!/^## (?![#])/.test(translated.trimStart())) { + return false; + } + return true;Also applies to: 707-715
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/scripts/i18n/chunked-translate.ts around lines 698 - 700, The intro block validation check (enBlock.label === "_intro" returning true) is executing before the fence-balance validation runs, allowing unclosed fences to pass validation in intro blocks. Reorder the validation logic so that the fence-balance check and the level-2 heading validation (checking for /^## (?![#])/.test(translated.trimStart())) both execute before the _intro block check is evaluated. Move the _intro block check to come after these other validation checks so that intro blocks are still subject to proper fence balance and heading structure requirements.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In @.github/scripts/i18n/chunked-translate.ts:
- Around line 698-700: The intro block validation check (enBlock.label ===
"_intro" returning true) is executing before the fence-balance validation runs,
allowing unclosed fences to pass validation in intro blocks. Reorder the
validation logic so that the fence-balance check and the level-2 heading
validation (checking for /^## (?![#])/.test(translated.trimStart())) both
execute before the _intro block check is evaluated. Move the _intro block check
to come after these other validation checks so that intro blocks are still
subject to proper fence balance and heading structure requirements.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 286ab9c2-4874-4a5c-926f-9aedd022ea57
📒 Files selected for processing (1)
.github/scripts/i18n/chunked-translate.ts
Summary
Fix a long-standing issue in
chunked-translate.tswhere thetoggleFencefunction used a boolean toggle, causing incorrect fence tracking when code blocks are nested inside lists or when multiple fence markers appear within the same section. This led to truncated translations where sections inside code blocks were misidentified as heading boundaries.Changes
toggleFence→ depth counter — Instead of togglingtrue/false, now tracks fence depth as an integer. Every```or~~~marker increments depth. A section is "inside a fence" whendepth % 2 !== 0.fencesAreBalanced()— New helper that verifies all code fences in a translated block are properly closed (even count of markers). Blocks with unbalanced fences are rejected, preventing downstream parse errors.isClosingFence()— New helper for cleaner semantics.validateTranslatedBlock()— Now performs fence-balance validation. Blocks with unclosed fences log a warning and returnfalse, preserving the existing content as a fallback.Applied to
parseHeadingSections,parseTargetSectionsByIndex, andcountH2Sectionsfor consistency.Background
During i18n translation, long MDX pages are split into heading-based chunks and translated individually. When a code block spanning multiple chunks had an unclosed fence in the middle, downstream parsing would swallow subsequent sections. This fix ensures fence boundaries are respected during chunk parsing and validation.