Bidi Test-Case Matrix — eight rendering cases
A 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.
id,case,fixture,marks,expectedRendering,why
b1,LRM after an RTL run,arabic-then-period,RLM,full stop stays at the right edge,"the trailing '.' is neutral and attaches to the paragraph, not the run"
b2,ALM around a phone number,phone-in-arabic,ALM,digit groups keep the order 555-0143,the '-' between digit runs is neutral
b3,LRI/PDI around a version range,version-range-in-arabic,LRI PDI,'2.4 - 3.1' renders left to right as one unit,spaces and hyphen are all neutral
b4,FSI/PDI around user content,unknown-direction-name,FSI PDI,name renders in its own direction inside either paragraph,direction is taken from the first strong character in the data
b5,Nested isolates in a file path,rtl-name-in-ltr-path,LRI FSI PDI PDI,path segments stay in order around an RTL name,"two levels of isolation, balanced"
b6,Bracket mirroring,parenthesis-in-rtl,none,'(' is drawn as ')' with no change to the stored bytes,"mirroring is a rendering property of the UBA, not a transformation of the text"
b7,Balanced RLE/PDF embedding,legacy-embedding,RLE PDF,run reorders but neutrals still interact across the boundary,the behaviour isolates were introduced to replace
b8,No marks at all,control-case,none,renders differently under LTR and RTL paragraph direction,the baseline every other row is compared against
Specifications
- Rows
- 8
- Columns
- 6
- Marks Covered
- RLM, ALM, LRI, FSI, PDI, RLE, PDF
- Delimiter
- ,
- Header
- true
- Control Row
- b8 (no marks at all)
- Seed
- 20260807
- Wave
- p7
- Line Endings
- LF
Testing contract
Reference control- Scenario
- Drive a parameterised rendering test from this table, one row per case.
- Expected result
- Seven rows render identically under LTR and RTL paragraph direction; the control row b8 does not, which is what proves the marks in the other rows are doing the work.
What is a .csv file?
CSV (Comma-Separated Values) is a plain-text tabular format where rows are lines and fields are separated by commas, with quoting rules for values that contain delimiters, quotes, or newlines. It has no formal type system and depends on encoding and dialect conventions. It is the most portable format for tabular data exchange.
How to use this file
Use an example CSV to test parsers against quoting and embedded-delimiter edge cases, header handling, encoding detection, and import pipelines into databases or spreadsheets.
How to use this file for testing
“Bidi Test-Case Matrix — eight rendering cases” is a deterministic Novus Examples fixture for Internationalization, CSV 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 · 8 rows · 6 columns · 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.
Code examples
import pandas as pd
df = pd.read_csv("bidi-test-cases.csv")
print(df.head())
print(df.dtypes)Related files
- csvCLDR Plural-Category Matrix — six languagesOne row per language, one column per CLDR plural category, filled with the smallest integers that select it — the sheet to hand a translator or a PM when explaining why 'one' and 'other' is not enough. Japanese needs one form and Welsh needs six.

- csvLocale Date and Time Patterns — ten locales (CSV)Short and medium date patterns, the short time pattern and the hour cycle for ten locales, each with the rendering of 2026-03-14T09:05. The ar-EG patterns contain U+200F between their fields and ru-RU's medium pattern ends in a quoted literal, so neither is the plain ASCII it appears to be.

- 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.

- htmlHTML 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.

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