Skip to content

i18n: heading-section chunked translation for long MDX pages#1159

Merged
comfyui-wiki merged 3 commits into
mainfrom
feat/i18n-heading-section-chunking
Jun 18, 2026
Merged

i18n: heading-section chunked translation for long MDX pages#1159
comfyui-wiki merged 3 commits into
mainfrom
feat/i18n-heading-section-chunking

Conversation

@comfyui-wiki

@comfyui-wiki comfyui-wiki commented Jun 18, 2026

Copy link
Copy Markdown
Member

Summary

  • Add heading_sections chunking strategy: split long MDX at level-2 ## headings, translate per section, and checkpoint after each block to avoid output truncation (max_tokens: 8192).
  • Store per-section English hashes in translationBlockHashes for incremental sync; unify changelog update_blocks under the same chunked pipeline.
  • Enable auto_chunk (body ≥ 10k chars, ≥ 4 sections) and explicitly configure tutorials/partner-nodes/pricing.mdx.
  • Extend truncation scan with missing_sections detection.
  • Pin Comfy Cloud as a preserved brand term (preserve_terms + glossary overrides for zh/ja/ko).

Test plan

  • bun .github/scripts/i18n/translate-i18n.ts --dry-run -- tutorials/partner-nodes/pricing.mdx --lang ko shows [SECTIONS] with pending sections
  • Run pnpm translate -- tutorials/partner-nodes/pricing.mdx --lang ko and verify full output (no truncation)
  • Run pnpm translate:check-truncation -- --lang ko on pricing after translation

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ad9802b2-b9c8-40f7-96af-0212bb9fde17

📥 Commits

Reviewing files that changed from the base of the PR and between 3741841 and c625efd.

📒 Files selected for processing (2)
  • .github/scripts/i18n/chunked-translate.ts
  • .github/scripts/i18n/translate-i18n.ts

📝 Walkthrough

Walkthrough

Introduces a generalized chunked translation engine (chunked-translate.ts) supporting heading_sections and update_blocks strategies with per-block SHA-256 hashing, frontmatter metadata management, sync-status computation, and block validation. Integrates this engine into translate-i18n.ts and check-translation-truncation.ts to skip up-to-date blocks and detect missing sections. Updates configuration with auto-chunk thresholds and a pricing.mdx entry. Adds "Comfy Cloud" to glossary overrides for ja, ko, and zh — no room for translation confusion here, it's preserved across all languages!

Changes

Chunked Translation Engine

Layer / File(s) Summary
Core types, hashing, and frontmatter utilities
.github/scripts/i18n/chunked-translate.ts
Defines all exported interfaces (ChunkStrategy, ChunkedFileConfig, AutoChunkConfig, ContentBlock, ParsedDocument, BlockSlot, SectionSyncStatus with optional needsReserialize), SHA-256-based per-block and aggregate hashing, and frontmatter parsing/serialization including translationBlockHashes YAML round-trip, metadata stripping, and metadata injection.
Chunking strategies, sync logic, and block validation
.github/scripts/i18n/chunked-translate.ts
Implements heading_sections parsing (_intro + ##-delimited blocks) with positional fallback alignment, update_blocks regex extraction with label-set hashing, shouldAutoChunk eligibility, document-level parseDocument/serializeChunkedDocument, getSectionSyncStatus with per-strategy pending-block detection and structure-drift flagging, resolveChunkStrategy, validateTranslatedBlock, and missingSectionLabels.
translate-i18n.ts refactor to use chunked engine
.github/scripts/i18n/translate-i18n.ts
Extends TranslationConfig with auto_chunk and ChunkedFileConfig type, refactors frontmatter sanitization to use stripAndSanitizeTranslationMeta, replaces static chunked-file detection with dynamic resolveFileChunkStrategy, generalizes translateChunkedFile to accept strategy, build slots per strategy, translate only pending blocks, write per-block checkpoints, and serialize with enBlockHashes. Updates translateFile, job planning, and dry-run logging to report pending blocks granularly.
check-translation-truncation.ts: missing_sections detection
.github/scripts/i18n/check-translation-truncation.ts
Imports resolveChunkStrategy and ChunkedFileConfig, extends TranslationConfig, derives CHUNKED_FILES/AUTO_CHUNK, introduces a parseBody helper, adds missing_sections as a new truncation reason via missingSectionLabels for heading_sections files, and formats detail output listing up to five missing section labels.
Translation config and README docs
.github/scripts/i18n/translation-config.json, .github/scripts/i18n/README.md
Configures tutorials/partner-nodes/pricing.mdx with heading_sections strategy, sets auto_chunk thresholds (min_body_chars: 10000, min_sections: 4), and documents chunked translation strategies, configuration, incremental per-block flow, and CLI usage in the i18n README; updates the tooling inventory to list chunked-translate.ts.

Comfy Cloud Glossary and Preserve Term

Layer / File(s) Summary
Comfy Cloud glossary entries and preserve_terms config
.github/scripts/i18n/translation-config.json, .github/scripts/i18n/glossary/overrides/ja.json, ...ko.json, ...zh.json
Adds "Comfy Cloud": "Comfy Cloud" to the terms map in ja, ko, and zh glossary overrides, and appends Comfy Cloud to preserve_terms — ensuring this brand name stays cloud-bound and unaltered across all languages.

Sequence Diagram(s)

sequenceDiagram
  participant translateFile
  participant resolveFileChunkStrategy
  participant getSectionSyncStatus
  participant translateChunkedFile
  participant serializeChunkedDocument
  translateFile->>resolveFileChunkStrategy: relPath, enContent
  resolveFileChunkStrategy-->>translateFile: ChunkStrategy | null
  alt strategy resolved
    translateFile->>translateChunkedFile: relPath, lang, strategy
    translateChunkedFile->>getSectionSyncStatus: enContent, existingContent, strategy, force
    getSectionSyncStatus-->>translateChunkedFile: SectionSyncStatus (upToDate, pendingBlocks, needsFrontmatter)
    loop each pending block
      translateChunkedFile->>translateChunkedFile: translate + validate block
      translateChunkedFile->>translateChunkedFile: writeChunkedCheckpoint (per-block)
    end
    translateChunkedFile->>serializeChunkedDocument: frontmatter, slots, fileHash, enRel, blockHashes
    serializeChunkedDocument-->>translateChunkedFile: final MDX with updated translationBlockHashes
  end
Loading
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/i18n-heading-section-chunking
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/i18n-heading-section-chunking

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Split oversized docs at ## boundaries with per-section hash sync and
checkpointing, extend truncation detection, and pin Comfy Cloud as a
preserved brand term in preserve_terms and glossary overrides.
@comfyui-wiki comfyui-wiki force-pushed the feat/i18n-heading-section-chunking branch from 61aff54 to 3741841 Compare June 18, 2026 09:20

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

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.test.ts (1)

14-147: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add regression tests for label-key safety and fenced-heading parsing.

Please add focused tests for: (1) labels containing : or quotes, (2) duplicate H2 titles, and (3) ## inside fenced code blocks. These are high-risk sync boundaries and currently unguarded.

🤖 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.test.ts around lines 14 - 147, Add
three focused regression tests to the test file to cover high-risk edge cases in
heading parsing: First, add a test for the parseHeadingSections function to
verify it handles labels containing special characters like colons and quotes
correctly without breaking the label-key mapping. Second, add a test for
parseHeadingSections to ensure it properly handles duplicate H2 titles and
creates appropriate labels (possibly with numeric suffixes) to maintain
uniqueness. Third, add a test for parseHeadingSections to verify that double
hash symbols inside fenced code blocks are not treated as section boundaries and
remain part of the content. These tests should be positioned within the existing
describe blocks for the functions they test (parseHeadingSections, etc.) to
ensure they catch potential sync boundary issues.
🤖 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.

Inline comments:
In @.github/scripts/i18n/chunked-translate.ts:
- Around line 160-170: The parseHeadingSections and countH2Sections functions
don't account for code fences, causing them to incorrectly treat heading-like
text within code blocks as real section boundaries. Add fence detection by
creating a FENCE_RE regex pattern to match code block delimiters, then in both
functions add an inFence boolean flag that toggles when encountering fence
markers. Modify the H2_HEADING_RE check to only apply when inFence is false,
ensuring that heading detection is skipped inside code blocks. Apply this logic
consistently in parseHeadingSections (checking the condition before processing
the line) and countH2Sections (looping through lines to track fence state and
only incrementing count when not in a fence).
- Around line 90-103: The regex pattern in parseBlockHashesFromFrontmatter uses
([^:]+) to capture hash keys, which breaks when keys contain colons (like
"Setup: Windows") since it stops at the first colon and only captures the text
before it. Update the regex to properly handle YAML-safe keys by quoting them
and adjusting the pattern to match quoted keys like "([^"]+)" instead of
([^:]+), ensuring that keys with colons round-trip correctly and prevent
indefinite retranslation of sections.
- Around line 347-355: The issue is that when English sections are deleted, the
function does not detect this as a pending sync because it only compares hashes
for sections that currently exist in enHashes. To fix this, in addition to the
existing filter that finds changed blocks in the pendingBlocks calculation, also
identify and include any sections that exist in storedHashes but are no longer
present in enHashes (these represent deleted sections). Combine the changed
blocks with the deleted blocks so that upToDate correctly returns false when
sections have been removed from the English document, ensuring that stale
translated sections for deleted English sections are properly flagged for
resync.
- Around line 63-67: The documentBlockHashes function silently overwrites block
hash entries when duplicate labels are encountered, causing data loss and
breaking pending-block detection. Before assigning the block hash to
out[b.label] in the loop, add a guard check to detect if the label already
exists in the output object. If a duplicate is found, either throw an error with
details about the conflicting label or log a warning to prevent silent
corruption of the block hash mapping.

---

Outside diff comments:
In @.github/scripts/i18n/chunked-translate.test.ts:
- Around line 14-147: Add three focused regression tests to the test file to
cover high-risk edge cases in heading parsing: First, add a test for the
parseHeadingSections function to verify it handles labels containing special
characters like colons and quotes correctly without breaking the label-key
mapping. Second, add a test for parseHeadingSections to ensure it properly
handles duplicate H2 titles and creates appropriate labels (possibly with
numeric suffixes) to maintain uniqueness. Third, add a test for
parseHeadingSections to verify that double hash symbols inside fenced code
blocks are not treated as section boundaries and remain part of the content.
These tests should be positioned within the existing describe blocks for the
functions they test (parseHeadingSections, etc.) to ensure they catch potential
sync boundary issues.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1265bb33-5c2f-4c5e-9fde-ca96f547a903

📥 Commits

Reviewing files that changed from the base of the PR and between 2fb1f0d and ccd46b6.

📒 Files selected for processing (9)
  • .github/scripts/i18n/README.md
  • .github/scripts/i18n/check-translation-truncation.ts
  • .github/scripts/i18n/chunked-translate.test.ts
  • .github/scripts/i18n/chunked-translate.ts
  • .github/scripts/i18n/glossary/overrides/ja.json
  • .github/scripts/i18n/glossary/overrides/ko.json
  • .github/scripts/i18n/glossary/overrides/zh.json
  • .github/scripts/i18n/translate-i18n.ts
  • .github/scripts/i18n/translation-config.json

Comment thread .github/scripts/i18n/chunked-translate.ts
Comment thread .github/scripts/i18n/chunked-translate.ts
Comment thread .github/scripts/i18n/chunked-translate.ts
Comment thread .github/scripts/i18n/chunked-translate.ts
Skip code-fence lines when splitting on ## headings, quote YAML block-hash
keys for labels with colons, detect removed EN sections for re-serialize,
and throw on duplicate section labels instead of silently overwriting.
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
cat .github/scripts/i18n/chunked-translate.ts

Length of output: 13848


🏁 Script executed:

#!/bin/bash
# Check translate-i18n.ts for the needsReserialize handling
rg -n "needsReserialize\|translateChunkedFile\|getSectionSyncStatus" .github/scripts/i18n/translate-i18n.ts -A3 -B1

Length of output: 430


🏁 Script executed:

#!/bin/bash
# Search for needsReserialize in translate-i18n.ts with PCRE2
rg -n "needsReserialize" .github/scripts/i18n/translate-i18n.ts || echo "NOT FOUND"
# Also check for the function and broader chunked handling
rg -n "translateChunked\|getSectionSync\|needsReseria" .github/scripts/i18n/translate-i18n.ts || echo "NOT FOUND"

Length of output: 459


🏁 Script executed:

#!/bin/bash
# Get key sections of translate-i18n.ts around chunked translation
grep -n "needsReserialize\|translateChunked\|getSectionSync\|serializeChunked\|resolveFileChunk" .github/scripts/i18n/translate-i18n.ts | head -60

Length of output: 1246



@comfyui-wiki All four fixes check out — no loose ends, no surprise snags! Here's what I verified in the updated code:

1. Fence-aware heading parsing
FENCE_RE + toggleFence() + isH2SectionLine() are defined and applied consistently in all three parsing functions (parseHeadingSections, parseTargetSectionsByIndex, countH2Sections). The ordering is correct: toggleFence runs first, then isH2SectionLine checks the updated inFence state, so a fence-opening line itself is never misidentified as a heading.

2. YAML-safe block-hash keys
formatBlockHashesYaml now emits JSON.stringify(label) for each key. parseBlockHashesFromFrontmatter handles both the new quoted form and legacy plain keys, with the proper exit condition (column-0 key pattern ^[A-Za-z_][\w-]*:) so it won't prematurely stop on indented values.

3. Deleted EN sections not detected
getSectionSyncStatus sets needsReserialize: true when hasStructureDrift && pendingBlocks.length === 0. translate-i18n.ts line 617 handles the fast-path re-serialization (serializeChunkedDocument) without re-calling the translation API — clean and efficient.

4. Duplicate H2 titles throw instead of silently overwriting
documentBlockHashes now throws "Duplicate block label: ..." immediately on collision, surfacing the problem early.

One minor pre-existing observation (not introduced by these fixes): stripTranslationMetaFromFrontmatter has duplicate .replace(...) calls for translationSourceHash, translationFrom, and translationBlockHashes — once without the m flag and once with. They're redundant but harmless; worth tidying in a follow-up if you'd like.

Overall the implementation is solid. The chunked translation pipeline should now handle fenced code blocks, colon-containing section titles, removed English sections, and duplicate headings robustly. Great work, and thanks for the thorough follow-up! 🐇✨

…x passes.

Extract shared frontmatter-stripping helpers and reuse them from translate-i18n.ts instead of maintaining a second copy.
@mintlify

mintlify Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
comfy 🟢 Ready View Preview Jun 18, 2026, 9:52 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant