How OfficeCLI Handles i18n and RTL Documents in Microsoft Word: A Complete Technical Guide

OfficeCLI handles i18n and RTL word documents through a centralized cascade system in WordHandler.I18n.cs that applies three-level RTL markup (<w:bidi/>, <w:rtl/> on paragraph-marks, and <w:rtl/> on every run) while detecting inheritance from styles, sections, and defaults to prevent validation errors and mixed-direction bugs.

Internationalization support in command-line document tools is often an afterthought, but OfficeCLI treats right-to-left scripts as a first-class concern. The implementation ensures Arabic, Hebrew, and other RTL documents maintain proper formatting without producing invalid Word XML. This article breaks down the exact mechanisms the tool uses to handle directionality, complex-script formatting, and inheritance detection.

RTL Cascade Architecture

The core of OfficeCLI's RTL handling lives in src/officecli/Handlers/Word/WordHandler.I18n.cs. The cascade architecture applies directionality at three distinct levels to match Word's internal expectations.

Three-Level Markup Application

The ApplyDirectionCascade method implements the complete markup pattern required for proper RTL rendering:

  1. <w:bidi/> on paragraph properties — signals the paragraph base direction
  2. <w:rtl/> on the paragraph-mark run properties — sets direction for the paragraph marker itself
  3. <w:rtl/> on every run inside the paragraph — ensures consistent character-level direction

This triple application prevents the "mixed bidi" scenario where paragraph direction conflicts with run direction, which causes unpredictable cursor behavior and layout bugs in Word.

// Apply complete RTL cascade to a paragraph
handler.ApplyDirectionCascade(para, rtl: true);

When setting rtl: false, the method becomes idempotent: it strips existing RTL markup and, critically, emits <w:bidi w:val="false"/> when any higher-level source still forces RTL. This explicit override prevents silent inheritance that would otherwise surprise users.

Schema-Correct XML Insertion

Word's Open XML schema is strict about element order. The helper EnsureParagraphMarkRunPropertiesInSchemaOrder (lines 13-22 of WordHandler.I18n.cs) inserts <w:rPr> at the exact required location in the pPr tree. Without this, documents fail validation against the Office Open XML strict schema.

Inheritance Detection System

RTL direction in Word can originate from multiple sources: section properties, paragraph styles, document defaults, or numbering levels. OfficeCLI traces all of them.

HasInheritedBidi: The Source Walker

The HasInheritedBidi method (lines 24-30) walks every possible RTL source to determine whether an explicit LTR setting needs to cancel inherited RTL. This powers both the cascade logic and the direction=ltr handler in the CLI.

StyleChainHasBidi: Following the basedOn Chain

Paragraph styles in Word form inheritance chains through the basedOn attribute. StyleChainHasBidi (lines 67-73) follows this chain recursively, stopping at the first explicit bidi true or false value—mirroring Word's own resolver exactly.

// Checking if a style chain forces RTL inheritance
bool hasBidiInChain = StyleChainHasBidi(styleId, stylesPart);

Complex-Script (CS) Run Formatting

RTL languages require distinct font, size, and emphasis properties. OfficeCLI preserves these through ReadComplexScriptRunFormatting, which extracts:

  • Font: <w:rFonts cs/>"font.cs"
  • Size: <w:szCs/>"size.cs"
  • Bold: <w:bCs/>"bold.cs"
  • Italic: <w:iCs/>"italic.cs"

The implementation respects explicit off-toggles like <w:bCs w:val="0"/>. This ensures round-tripping preserves intentional overrides that prevent unwanted inheritance in mixed-script documents.

var format = new Dictionary<string, object?>();
WordHandler.ReadComplexScriptRunFormatting(run, null, format);
// format["bold.cs"] will be false if <w:bCs w:val="0"/> exists,
// null if absent, or true if <w:bCs/> or <w:bCs w:val="1"/>

Integration Points Across the Codebase

Set Command (WordHandler.Set.cs)

The CLI's set command parses direction keywords and routes to the cascade:

User Input Internal Action
rtl, direction=rtl ApplyDirectionCascade(para, rtl: true)
ltr, direction=ltr ApplyDirectionCascade(para, rtl: false) with inheritance check

# CLI usage to force RTL on first paragraph

officecli set paragraph[1] direction=rtl

Selectors (WordHandler.Selector.cs)

Read-back operations expose computed effective direction through three keys:

  • rtl — boolean indicating RTL presence
  • direction — string "rtl" or "ltr"
  • bidi — raw <w:bidi/> element state

These respect the same inheritance chain used for writing, ensuring consistency between read and write operations.

Table Context Detection (IsTableContextRtl)

When inserting tables, IsTableContextRtl checks whether the surrounding section carries RTL defaults. If so, the table implementation auto-stamps <w:bidiVisual/> on table properties—required for proper cell ordering in RTL contexts.

bool contextIsRtl = handler.IsTableContextRtl(parentSection);
if (contextIsRtl) {
    tableProps.Append(new BiDiVisual());
}

Section-Level RTL (WordHandler.Set.SectionLayout.cs)

For document-level RTL control, the implementation handles <w:rtlGutter/> in section properties, affecting page layout margins in RTL locales.

File Reference Map

File Responsibility Lines of Interest
WordHandler.I18n.cs Core cascade, inheritance, CS formatting 13-73
WordHandler.Set.cs CLI key parsing, routing to cascade
WordHandler.Selector.cs Effective direction read-back
WordHandler.StyleList.cs effective.rtl in style queries
WordHandler.Set.SectionLayout.cs Section-level RTL gutter

Summary

  • OfficeCLI implements complete RTL handling through ApplyDirectionCascade in WordHandler.I18n.cs, applying three-level markup required by Word's Open XML schema.

  • Inheritance detection via HasInheritedBidi and StyleChainHasBidi prevents silent RTL propagation and enables explicit LTR overrides.

  • Complex-script formatting preserves explicit off-toggles for fonts, sizes, and emphasis to maintain round-trip fidelity.

  • Integration across the codebase ensures tables, sections, styles, and runs all respect consistent directionality rules.

  • Schema-correct output uses EnsureParagraphMarkRunPropertiesInSchemaOrder to place XML elements in valid order, avoiding validation failures.

Frequently Asked Questions

What happens if I set direction=ltr on a paragraph that inherits RTL from its style?

OfficeCLI detects the inherited RTL via HasInheritedBidi, then emits <w:bidi w:val="false"/> explicitly to override the style, rather than simply removing local markup. This forces LTR appearance regardless of upstream direction settings.

Does OfficeCLI handle mixed RTL/LTR documents correctly?

Yes. The per-run <w:rtl/> application ensures individual runs maintain their specified direction even within paragraphs of opposite base direction. The CLI preserves explicit directional overrides at the run level while managing paragraph defaults through the cascade.

How does the tool prevent invalid Open XML when modifying RTL properties?

The EnsureParagraphMarkRunPropertiesInSchemaOrder helper inserts <w:rPr> elements at schema-mandated positions within <w:pPr> trees. Additionally, all XML mutations go through the OpenXml SDK's DOM rather than string manipulation, ensuring structural validity.

Can I query the effective RTL direction of a paragraph through the CLI?

Yes. The selector system in WordHandler.Selector.cs exposes rtl, direction, and bidi keys that compute effective direction by walking the same inheritance chain used for writing—section properties, style chains, document defaults, and local overrides.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →