How OfficeCLI Handles Word i18n and RTL Text Direction: Implementation Guide
OfficeCLI centralizes Word internationalization in WordHandler.I18n.cs, implementing a three-level RTL cascade that adds <w:bidi/> to paragraphs, <w:rtl/> to paragraph marks, and <w:rtl/> to every run, while detecting inherited direction and preserving complex-script formatting.
OfficeCLI, the open-source document automation toolkit from iOfficeAI, provides robust support for right-to-left (RTL) scripts and internationalization (i18n) in Word documents. The implementation ensures that Arabic, Hebrew, and other RTL languages render correctly by manipulating the underlying Open XML markup with precision. Understanding these internals helps developers generate valid, localized Word documents programmatically without producing mixed-bidi or validator-rejected files.
The RTL Cascade Architecture
The core RTL logic resides in src/officecli/Handlers/Word/WordHandler.I18n.cs. This file implements a cascade system that applies directional markup at multiple levels to satisfy Word's strict requirements for bidirectional text.
Paragraph-Level Direction with ApplyDirectionCascade
When switching a paragraph to RTL, OfficeCLI applies three distinct XML elements through the ApplyDirectionCascade method (lines 33-46):
<w:bidi/>on the paragraph properties (pPr)<w:rtl/>on the paragraph-mark run properties<w:rtl/>on every run inside the paragraph
The method is idempotent; passing rtl: false removes the cascade entirely. If higher-level sources still force RTL, the method emits <w:bidi w:val="false"/> to override inheritance explicitly.
// Assume `handler` is an instance of WordHandler and `para` is a Paragraph.
handler.ApplyDirectionCascade(para, rtl: true);
This adds <w:bidi/>, <w:rtl/> on the paragraph-mark, and <w:rtl/> on every run.
To force LTR and clear any inherited RTL:
handler.ApplyDirectionCascade(para, rtl: false);
This removes the cascade and emits <w:bidi w:val="false"/> if any inherited RTL exists.
Inheritance Detection via HasInheritedBidi
To determine whether explicit LTR markup is needed to cancel inherited settings, HasInheritedBidi (lines 24-30) walks all possible RTL sources. The method checks section properties, paragraph-style chains, docDefaults, and numbering levels. This detection prevents mixed-direction artifacts by identifying when an inherited RTL state requires explicit cancellation.
Style-Chain Resolution with StyleChainHasBidi
The StyleChainHasBidi method (lines 67-73) follows the basedOn chain of paragraph styles, stopping at the first explicit bidi true or false value. This mirrors Word's internal style resolver, ensuring that direction changes propagate correctly through inherited styles without creating invalid override conflicts.
Schema-Correct XML Insertion
When adding <w:rtl/> to paragraph marks, EnsureParagraphMarkRunPropertiesInSchemaOrder (lines 13-22) inserts the <w:rPr> element at the proper location within the pPr tree. This strict schema compliance prevents validation errors that occur when run properties are placed out of sequence relative to other paragraph properties.
Complex-Script (CS) Run Formatting
RTL documents often require complex-script formatting distinct from Latin (Ascii) text. The ReadComplexScriptRunFormatting method (lines 34-44) extracts CS-specific properties from runs:
Crucially, the method respects explicit off-toggles (e.g., <w:bCs w:val="0"/>), ensuring round-trip fidelity for documents where complex-script formatting must be explicitly disabled to prevent unwanted inheritance from Latin text settings.
var format = new Dictionary<string, object?>();
WordHandler.ReadComplexScriptRunFormatting(run, null, format);
// `format` now contains keys: "font.cs", "size.cs", "bold.cs", "italic.cs"
CLI Integration and Usage Patterns
OfficeCLI exposes these internal mechanisms through simple command-line interfaces while maintaining the integrity of the underlying XML manipulation.
Setting Direction via the CLI
The Set command in WordHandler.Set.cs parses direction keywords (rtl, ltr, direction) and forwards them to ApplyDirectionCascade:
officecli set paragraph[1] direction=rtl
The CLI resolves the target paragraph and internally calls ApplyDirectionCascade, abstracting the complex XML generation.
Reading Direction State
Selectors in WordHandler.Selector.cs expose rtl, direction, and bidi keys that return the effective direction computed by the cascade logic. This enables scripts to query document state before modification, ensuring conditional logic based on the current text direction.
Automatic RTL Context for Tables
When inserting tables, IsTableContextRtl determines whether the surrounding section or document defaults specify RTL. If the context is RTL, the implementation automatically stamps <w:bidiVisual/> on table properties to maintain visual consistency with the text direction.
// `parent` can be a Section, Body, etc.
bool contextIsRtl = handler.IsTableContextRtl(parent);
if (contextIsRtl)
{
// Auto-stamp BiDiVisual on the table properties.
tableProperties.BidiVisual = new BiDiVisual();
}
Summary
- OfficeCLI implements Word i18n through a centralized RTL cascade in
WordHandler.I18n.cs ApplyDirectionCascadeapplies three XML elements (<w:bidi/>, paragraph-mark<w:rtl/>, and run-level<w:rtl/>) to ensure proper RTL renderingHasInheritedBidiandStyleChainHasBididetect style-based direction inheritance to prevent conflicting markup- Complex-script formatting preserves explicit off-toggles for
font.cs,size.cs,bold.cs, anditalic.csto ensure round-trip accuracy - CLI commands abstract the XML manipulation, allowing simple
direction=rtlsyntax while maintaining schema compliance
Frequently Asked Questions
How does OfficeCLI ensure Word documents remain valid when adding RTL markup?
By using EnsureParagraphMarkRunPropertiesInSchemaOrder to insert XML elements at schema-compliant positions within the paragraph properties tree, avoiding validation errors that occur with out-of-order elements according to the Open XML standard.
Can OfficeCLI handle mixed-direction documents where some paragraphs are RTL and others LTR?
Yes. The ApplyDirectionCascade method is idempotent and context-aware; it removes RTL markup when rtl: false is specified and emits <w:bidi w:val="false"/> to override inherited RTL from styles or sections, enabling precise per-paragraph direction control without affecting neighboring content.
What complex-script formatting properties does OfficeCLI preserve for RTL text?
OfficeCLI preserves font.cs, size.cs, bold.cs, and italic.cs properties through ReadComplexScriptRunFormatting, including explicit off-toggles (w:val="0"), ensuring that complex-script formatting does not inherit incorrectly from Latin text settings and maintains round-trip fidelity.
Does OfficeCLI automatically detect RTL context when inserting tables?
Yes. The IsTableContextRtl method checks section properties and document defaults to determine if the surrounding context is RTL, automatically applying <w:bidiVisual/> to table properties when necessary to maintain proper visual layout alignment with the text direction.
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 →