HTML Bidi — dir=auto, <bdi> and a scoped <bdo>
The HTML half of bidi handling: paragraphs with dir=ltr, dir=rtl and dir=auto, the same user-supplied string with and without a <bdi> wrapper, one balanced <bdo> showing display override scoped to a single element, and explicit RLM/FSI marks inside markup. No scripts and no external resources.
<!doctype html>
<meta charset="utf-8">
<title>Bidirectional text — dir, bdi and bdo</title>
<!--
A rendering fixture for the HTML side of bidi. Nothing here is scripted and nothing is fetched;
the whole point is that the browser's own bidi implementation does the work.
dir="auto" : direction comes from the first strong character in the element's text.
<bdi> : isolates its contents (the HTML equivalent of FSI...PDI) — the correct wrapper
for user-supplied names, which is what the "comments" list below demonstrates.
<bdo dir> : OVERRIDES direction for display. It is included once, balanced and scoped to a
single element, because a bdo is the markup analogue of the override characters
this fixture set deliberately does not ship.
-->
<style>
body { font: 16px/1.6 system-ui, sans-serif; max-width: 46rem; margin: 2rem auto; }
section { border: 1px solid #ccc; border-radius: 6px; padding: 1rem; margin: 1rem 0; }
code { background: #f4f4f4; padding: 0 .2em; }
.rtl { direction: rtl; }
</style>
<h1>Bidirectional text rendering cases</h1>
<section>
<h2>1. Paragraph direction</h2>
<p dir="ltr">LTR paragraph containing عربية in the middle.</p>
<p dir="rtl">فقرة عربية تحتوي على English في وسطها.</p>
<p dir="auto">عربية first, so <code>dir="auto"</code> resolves this whole paragraph to RTL.</p>
<p dir="auto">English first, so <code>dir="auto"</code> resolves this whole paragraph to LTR
even though it also contains عربية.</p>
</section>
<section class="rtl">
<h2>2. User content without and with <bdi></h2>
<p>بدون bdi: <span>مستخدم -3</span> علق على الملف.</p>
<p>مع bdi: <bdi>مستخدم -3</bdi> علق على الملف.</p>
<p>مع bdi واسم لاتيني: <bdi>Novus File Manager</bdi> علق على الملف.</p>
</section>
<section>
<h2>3. <bdo> — display override, balanced and scoped</h2>
<p>Normal: <span>file-2026.pdf</span></p>
<p>Overridden: <bdo dir="rtl">file-2026.pdf</bdo></p>
<p>The stored text is identical in both lines; only the drawing order differs.</p>
</section>
<section>
<h2>4. Explicit marks inside HTML text</h2>
<p>An RLM after the Arabic run pins the trailing full stop:
المنتج جاهز.</p>Specifications
- Sections
- 4
- Elements
- dir=ltr|rtl|auto, <bdi>, <bdo dir="rtl">
- Scripts
- Latin, Arabic
- Scripts Note
- no JavaScript, no external requests
- Marks Used
- RLM, FSI, PDI
- Encoding
- UTF-8
- Seed
- 20260807
- Wave
- p7
- Line Endings
- LF
Testing contract
Expected to pass- Scenario
- Open in a browser (or a headless renderer) and compare each pair of lines visually, then screenshot-diff across browsers.
- Expected result
- dir=auto resolves from the first strong character, so the two auto paragraphs lay out in opposite directions; the <bdi>-wrapped name keeps the sentence intact while the unwrapped one lets the leading '-' pull the name to the wrong side.
What is a .html file?
HTML (HyperText Markup Language) is the structural markup language of the web, using nested tags to define document content, semantics, and links. It is typically paired with CSS for presentation and JavaScript for behavior. It is the foundational format rendered by browsers.
How to use this file
Use an example HTML file to test parsers, DOM construction, sanitization of untrusted markup, and rendering or scraping pipelines.
How to use this file for testing
“HTML Bidi — dir=auto, <bdi> and a scoped <bdo>” is a deterministic Novus Examples fixture for Internationalization, HTML parsing, Localization catalogs. Parallel text and accented, multi-script content — for testing translation pipelines, Unicode handling, and localization tooling.
Documented properties for this file: seed 20260807 · UTF-8 · LF. Compare results against paired or grouped companions on this page when present (clean↔damaged, searchable↔scanned, or format twins) so scores stay reproducible across runs.
Download the file once, keep the path stable in CI or local scripts, and treat the spec table as the contract: dimensions, seeds, field lists, and roles are intentional. Corrupt or invalid samples are labelled as such — expect parsers to fail loudly rather than silently accept them.
Translation-catalog fixtures carry the same message set across formats, each with its native placeholder syntax. Test your i18n loader, catalog converter, or translation-memory tool, and use the RTL and CJK variants to check bidirectional text and Unicode handling.
Load the catalog with your i18n framework and verify placeholder interpolation and plural handling; the RTL and CJK variants exercise bidirectional text and font fallback.
Related files
- txtBidi — bracket mirroring in RTL paragraphs (Hebrew and Arabic)Mirroring is a rendering property of the bidi algorithm, not a transformation of the text: a U+0028 LEFT PARENTHESIS inside an RTL run is DRAWN as ')' while the stored byte never changes. These Hebrew and Arabic lines make that testable, and list the neutral characters that look like they should mirror but do not.

- txtBidi — where a mark is actually required (Arabic)Six Arabic sentences containing a Latin filename, a phone number, a version range, a mixed-script path, a percentage and a bracketed insertion — each shown first as a translator usually delivers it and then with the one invisible character that makes it render correctly. The two forms differ by exactly one code point.

- jsonBidi Isolates — UI templates for user-supplied namesThree notification templates in English, Arabic and Hebrew, each given raw and with every interpolation slot wrapped in FSI…PDI, plus four argument sets covering an LTR name in an RTL sentence, an RTL name in an LTR sentence and a name beginning with a neutral character. This is the fixture for the bug where a display name reorders the sentence around it.

- csvBidi Test-Case Matrix — eight rendering casesA flat index of the bidi cases in this wave — which mark each one uses, what it should render as, and why the neutral characters involved need help. Row b8 is the control case with no marks, against which the other seven are compared.

- txtUnicode Bidi Controls — LRM, RLM, ALM, isolates and embeddingsA reference sheet in which each of the ten shipped bidi control characters appears literally between ASCII guards, with its code point, UTF-8 bytes and the job it does. The two override characters are named but deliberately absent: a bidi rendering fixture does not need to ship the Trojan Source vector.

- resx.NET RESX — composite format strings (Arabic (Egypt))A Arabic (Egypt) resource file built around composite format strings — {0:N2}, {2:P1}, {0:C}, {0:d} and {0:t} — whose rendered output depends entirely on CultureInfo. Includes a whitespace-significant resource guarded by xml:space, and documents the suffixed-key convention .NET falls back on because String.Format has no plural selector.

Generated by generation/localization_p7.py. Free for any use, no attribution required — license.