RTL Support: Building Software That Works in Arabic and Hebrew
Date Published
Right-to-left (RTL) support means an interface reads correctly for languages like Arabic and Hebrew, where text flows from right to left instead of left to right. The mistake almost every team makes is treating that as a text-alignment setting. It isn't. RTL reverses the entire layout: navigation, icons, form fields, and the direction a user's eye moves across the screen. Get it wrong and the software doesn't look foreign. It looks broken, and RTL-speaking users notice in the first few seconds.
We flagged this as one of the two script families that expose weak internationalization (i18n) fastest, alongside CJK scripts, in multilingual software development. This article covers what RTL actually requires: layout mirroring, the CSS mechanism that makes it maintainable, bidirectional text handling, and a testing approach that catches the bugs before a real user does.
What RTL Actually Reverses
Setting dir="rtl" on a page flips more than most teams expect, and every one of these needs to be right, not just the paragraph text:
- Navigation and menus. A left-side nav becomes a right-side nav. Breadcrumbs, tabs, and dropdown arrows all reverse.
- Icons that imply direction. "Back" and "next" arrows, chevrons, and progress indicators point the opposite way, because "forward" in an RTL interface visually points left.
- Form layout. Labels, input alignment, and the tab order through a multi-field form all mirror, or a form reads correctly in isolation but tabs through fields in the wrong sequence.
- Progress and step indicators. A five-step signup flow that fills left to right in English has to fill right to left in Arabic, or the visual metaphor stops making sense.
Skip any one of these and you get a hybrid interface: Arabic text sitting inside an English-shaped layout. It reads as unfinished, because it is.
Logical CSS Properties: The Mechanism That Makes RTL Maintainable
The old approach to RTL was a separate stylesheet with every left swapped for right, maintained by hand, forever drifting out of sync with the primary layout. Modern CSS solves this properly with logical properties, which describe position relative to text direction instead of a physical side.
margin-inline-start and margin-inline-end replace margin-left and margin-right. padding-inline-start replaces a hardcoded padding-left. Written this way, the browser flips the layout automatically based on the page's dir attribute, and one stylesheet serves both directions correctly. Written the old way, with physical left and right values, nothing flips, and Arabic text ends up left-aligned in a right-aligned interface with the padding on the wrong side.
This is the single decision that matters most in RTL support. A codebase built on logical properties from the start supports RTL as a configuration. A codebase built on hardcoded left and right values needs a manual audit of every component before it can.
When Arabic Text Meets a Latin Product Code
Real content rarely stays in one direction. An Arabic sentence containing a product SKU, a phone number, or an English brand name has to render the RTL text right to left while the embedded Latin characters and numbers still read left to right, in place, without scrambling the surrounding sentence.
This is governed by the Unicode Bidirectional Algorithm (UAX #9), which determines the visual order of mixed-direction text from the underlying character properties. Most of the time it works automatically. It breaks in two predictable spots: numbers and punctuation at the edge of a text run, where the algorithm has to guess which direction "owns" a shared character like a dash or a slash, and dynamically inserted content, such as a product name pulled from a database and interpolated into a translated sentence, where the surrounding markup doesn't declare its direction. The fix in both cases is explicit: Unicode isolate characters (U+2066–U+2069) or the HTML dir and bdi elements mark where one direction's text is embedded inside the other, instead of leaving the algorithm to guess.
Skip this and you get the RTL equivalent of mojibake: a phone number rendered backward, or a sentence where a product code appears on the wrong side of the words around it.
Which Icons Mirror, and Which Shouldn't
Not every icon flips, and getting this wrong in either direction reads as a bug.
Mirror these: back and forward arrows, chevrons, "next" and "previous" buttons, progress bars, and any icon that encodes a left-right sequence or direction of travel.
Don't mirror these: clocks, a media player's play button, a checkmark, numerals, logos, and photographs of people or objects. A mirrored clock face or a backward play triangle looks like a rendering bug, not a localization choice, because these icons represent a real-world object, not a directional metaphor.
The distinction sounds simple stated this way. In practice it requires a deliberate pass over every icon in the interface, categorizing each one, because a global "flip everything" transform gets it wrong in both directions.
Testing RTL Before Real Users Find the Bugs
RTL bugs hide from an English-only QA pass, because nothing in the visible layout looks unfinished until real RTL content fills it in. Three checks catch what a casual glance misses:
- Test with real Arabic or Hebrew content, not lorem ipsum or placeholder boxes. Placeholder text is uniform in length and direction, so it never exposes bidi edge cases or the text-expansion problem: short interface labels can expand as much as 300% in translation, and even everyday words routinely run longer than their English source (W3C, Text size in translation). A button sized for "Save" doesn't survive its Arabic equivalent without a real-content test.
- Run a pseudo-localization pass with forced RTL mode. Most modern frameworks can flip a page's direction without a translation in place, which surfaces layout breaks (icons pointing the wrong way, misaligned forms, overflow) fast, before translated content is ready to test with.
- Include at least one mixed-direction test case. A form field, a search result, or a notification that combines RTL text with a Latin product code, price, or email address, since that's exactly where the bidirectional algorithm needs help and hand-off bugs hide.
We run pseudo-localization plus at least one RTL and one CJK locale on every multilingual build, for exactly this reason: RTL bugs are cheap to fix during development and expensive to fix after a customer reports that the app "looks broken" in Arabic.
Frequently Asked Questions About RTL Support
What does RTL mean in software?
RTL stands for right-to-left, referring to languages like Arabic and Hebrew that read in that direction. RTL support means the entire interface, not just the text, mirrors correctly: navigation, icons, forms, and layout direction all reverse together.
Which languages need RTL support?
Arabic and Hebrew are the two major RTL scripts in commercial software; Persian (Farsi) and Urdu also use Arabic script and read right to left. Every other major world language, including Chinese, Japanese, and Korean, reads left to right despite other layout quirks.
Can I just flip my CSS with left and right swapped?
You can, but it creates a second stylesheet that drifts out of sync with every update to the primary layout. Logical CSS properties (margin-inline-start instead of margin-left) let one stylesheet serve both directions automatically, based on the page's declared direction.
Why does Arabic text sometimes show numbers or English words in the wrong order?
This is a bidirectional text bug: mixed-direction content (Arabic text containing a Latin product code, phone number, or brand name) needs explicit direction markers so the Unicode Bidirectional Algorithm renders it correctly. Without them, the algorithm has to guess, and it sometimes guesses wrong at the boundary between scripts.
How do you test RTL support properly?
With real Arabic or Hebrew content rather than placeholder text, a forced RTL pseudo-localization pass to catch layout breaks early, and at least one test case mixing RTL text with Latin numbers or product codes. We build this testing into every multilingual project; request a fixed-price quote and RTL support is scoped in from the start.
Build It Right the First Time
Tell us which scripts and directions your software needs to support. We scope RTL in from the first commit, not as a retrofit, and reply with a fixed price and a delivery date.