How OfficeCLI Handles i18n and RTL Text Direction for Word Documents
OfficeCLI implements comprehensive internationalization support by cascading bidirectional XML elements through paragraph properties, paragraph marks, and individual runs, while preserving complex-script formatting via the WordHandler.I18n.cs module.
OfficeCLI is an open-source command-line interface for automating Microsoft Office document generation and modification. When processing right-to-left scripts such as Arabic or Hebrew, the tool must generate schema-compliant WordprocessingML that respects both explicit direction settings and inherited style properties. The library centralizes all bidirectional logic in WordHandler.I18n.cs, ensuring that RTL documents validate correctly and render properly in Microsoft Word.
RTL Cascade Architecture in WordHandler.I18n.cs
Paragraph-Level Direction Control
The ApplyDirectionCascade method (lines 33-46 in src/officecli/Handlers/Word/WordHandler.I18n.cs) implements the three-tier XML structure required for RTL paragraphs:
<w:bidi/>on paragraph properties (pPr)<w:rtl/>on the paragraph-mark run properties<w:rtl/>on every run inside the paragraph
This method is idempotent; calling it with rtl: false removes the cascade and emits <w:bidi w:val="false"/> when inherited RTL needs cancellation.
// Apply RTL to a paragraph
handler.ApplyDirectionCascade(para, rtl: true);
// Force LTR by clearing RTL cascade
handler.ApplyDirectionCascade(para, rtl: false);
Inheritance Detection and Style Resolution
To handle Word's complex inheritance model, HasInheritedBidi (lines 24-30) walks all possible RTL sources including section properties, paragraph-style chains, docDefaults, and numbering levels. This determines whether explicit LTR markup is required to override inherited RTL settings.
The StyleChainHasBidi helper (lines 67-73) follows the basedOn chain of paragraph styles, stopping at the first explicit bidi value to mirror Word's internal resolver.
Schema-Compliant XML Insertion
The helper EnsureParagraphMarkRunPropertiesInSchemaOrder (lines 13-22) inserts <w:rPr> elements at the correct location within the pPr tree, preventing validation errors that occur when RTL properties are misplaced in the XML hierarchy.
Complex-Script Formatting Preservation
Extracting CS Run Properties
The ReadComplexScriptRunFormatting method (lines 34-44) extracts complex-script variants from run properties:
This method respects explicit off-toggles (e.g., <w:bCs w:val="0"/>), ensuring that formatting overrides preventing unwanted inheritance are preserved during round-tripping.
var format = new Dictionary<string, object?>();
WordHandler.ReadComplexScriptRunFormatting(run, null, format);
// Keys available: "font.cs", "size.cs", "bold.cs", "italic.cs"
CLI Integration and Command Handling
Setting Direction via Commands
The Set command implementation in WordHandler.Set.cs parses keys like rtl, ltr, and direction, forwarding them to ApplyDirectionCascade. Users can invoke this via:
officecli set paragraph[1] direction=rtl
Reading Effective Direction
Selectors defined in WordHandler.Selector.cs expose rtl, direction, and bidi keys that return the effective direction computed by the cascade logic, allowing scripts to query document state without parsing XML manually.
RTL-Aware Table Insertion
When inserting tables, IsTableContextRtl detects whether the surrounding section or document defaults specify RTL direction. This automatically triggers the insertion of <w:bidiVisual/> on table properties to ensure proper visual ordering.
bool contextIsRtl = handler.IsTableContextRtl(parent);
if (contextIsRtl)
{
tableProperties.BidiVisual = new BiDiVisual();
}
Summary
- OfficeCLI centralizes RTL logic in
WordHandler.I18n.cswith cascade-aware methods likeApplyDirectionCascade - The implementation handles three levels of bidirectional markup: paragraph properties, paragraph marks, and individual runs
- Complex-script formatting (fonts, sizing, bold, italic) is preserved via
ReadComplexScriptRunFormattingwith explicit toggle support - Inheritance detection through
HasInheritedBidiandStyleChainHasBidiensures accurate override of style-based RTL settings - CLI commands and programmatic APIs both leverage these helpers to produce validation-compliant WordprocessingML
Frequently Asked Questions
How does OfficeCLI ensure Word documents remain valid when applying RTL formatting?
OfficeCLI uses EnsureParagraphMarkRunPropertiesInSchemaOrder to insert RTL properties at schema-compliant positions within the XML tree. The ApplyDirectionCascade method ensures all three required elements (<w:bidi/>, paragraph-mark <w:rtl/>, and run-level <w:rtl/>) are present simultaneously, preventing the mixed-bidi states that cause Word validation errors.
Can OfficeCLI override inherited RTL settings from document styles?
Yes. When ApplyDirectionCascade is called with rtl: false, it invokes HasInheritedBidi to detect RTL values inherited from section properties, style chains, or document defaults. If inheritance is detected, the method emits <w:bidi w:val="false"/> to explicitly cancel the inherited direction, ensuring LTR rendering regardless of style hierarchy.
What complex-script formatting properties does OfficeCLI preserve during document processing?
OfficeCLI preserves four complex-script variants through ReadComplexScriptRunFormatting: font.cs (complex-script font), size.cs (complex-script size), bold.cs (complex-script bold), and italic.cs (complex-script italic). The method explicitly handles off-toggles (values of "0") to prevent unwanted formatting inheritance in multilingual documents.
How do I programmatically detect if a table should use RTL layout in OfficeCLI?
Use the IsTableContextRtl method to inspect the surrounding section or document defaults before table insertion. This helper returns true when the context requires right-to-left layout, allowing your code to automatically set tableProperties.BidiVisual and ensure the table renders with correct visual ordering for Arabic or Hebrew content.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →