All Articles

Bidirectional Text Guide for Software Teams

September 12, 2026

Bidirectional Text Guide for Software Teams

A mixed Arabic and English error message can look correct in a translator’s editor, then render with the version number on the wrong side of the sentence in the product. The source string may be valid, the translation may be accurate, and the defect can still reach production because bidirectional behavior is a rendering and layout concern, not only a linguistic one.

This bidirectional text guide is for software teams that need to build, localize, and validate products containing right-to-left (RTL) languages such as Arabic, Hebrew, Persian, and Urdu. It focuses on the Unicode Bidirectional Algorithm, the places where mixed-direction content fails, and the workflow controls that prevent defects before release.

What bidirectional text means in software

Bidirectional text, often shortened to bidi text, combines scripts that read in opposite directions. Arabic and Hebrew are generally written right to left. English, Latin-based product names, URLs, email addresses, code, file paths, and many numbers are generally written left to right.

A common misunderstanding is that an RTL interface simply reverses all text. It does not. A Hebrew sentence may be displayed right to left while an embedded filename such as `report-Q3-2026.pdf` must remain internally left to right. Unicode assigns directional properties to characters and uses contextual rules to determine their visual order.

That distinction matters because logical order and visual order are not the same thing. Logical order is the character sequence stored in a resource file, database, or source code. Visual order is what the user sees after the rendering engine applies bidi rules. Developers should preserve logical order in data and let Unicode-aware controls render it correctly.

Why bidi defects are difficult to find

Most bidi defects appear only when a string mixes strong directional characters with neutral or weak characters. Strong characters establish direction, such as Arabic letters or English letters. Numbers, punctuation, parentheses, slashes, currency symbols, and spaces often depend on surrounding context.

Consider a localized status message that includes an English server name and a port number. In an Arabic UI, a colon or closing parenthesis can attach visually to the wrong token. The problem may become more visible when the server name changes, a placeholder is empty, or a translator rearranges the sentence to make it natural in the target language.

The same issue affects structured content. Dates, build identifiers, semantic versions, SKU values, hexadecimal strings, and command-line options are all frequent sources of confusing display. A value such as `v2.10.4-beta` should normally be treated as an LTR run even inside an RTL paragraph. If it is not isolated, adjacent RTL text can alter how punctuation around that value is resolved.

Copying text from a browser, spreadsheet, or ticket system can add another layer of risk. Invisible directional controls may be present in the copied value. They can be necessary in specific cases, but unmanaged controls make troubleshooting difficult and may create security concerns when source code or commands appear differently than expected.

The Unicode controls teams need to understand

Unicode supplies control characters that help define direction when surrounding context is insufficient. The older embedding and override controls include left-to-right embedding (LRE), right-to-left embedding (RLE), left-to-right override (LRO), right-to-left override (RLO), and pop directional formatting (PDF).

Overrides are particularly risky because they force displayed direction rather than allowing Unicode to interpret character properties. They can make a string appear correct in one case while hiding its true logical order. They should be avoided unless a specific format requires them and the behavior is documented and tested.

For application strings, directional isolates are usually the safer choice. Left-to-right isolate (LRI), right-to-left isolate (RLI), and first strong isolate (FSI), closed by pop directional isolate (PDI), create a directional boundary around embedded content. Isolation prevents the surrounding paragraph from affecting the embedded run and prevents the embedded run from affecting neighboring punctuation.

For example, an Arabic message containing a variable product name may need the product name isolated if that value can contain Latin text, digits, or mixed scripts. First strong isolate is useful when the application does not know the value’s direction in advance. The renderer uses the first strong directional character inside the value to determine its base direction.

Use controls with restraint. They are not a substitute for correctly setting the base direction of the document, UI element, or paragraph. They are targeted tools for mixed-direction fragments, dynamic values, and punctuation-sensitive content.

Set direction at the right layer

Direction should be defined structurally wherever the platform supports it. On the web, set `dir="rtl"` on the HTML root for an RTL page or on the smallest meaningful container for RTL content within an otherwise LTR page. Use the `dir` attribute rather than CSS alone for text direction, because semantic direction is needed by browser bidi processing and assistive technologies.

In desktop and mobile applications, use framework-level directionality and locale settings. Controls should inherit RTL behavior where appropriate, including text alignment, cursor movement, selection behavior, and mirrored layout. A right-aligned label is not equivalent to an RTL text control. Alignment changes placement; direction changes how characters, words, and editing actions behave.

The right layer depends on the content. An entire Arabic dialog should have an RTL base direction. A single Arabic comment inside an English activity feed may need RTL direction only on that comment container. An LTR identifier inside either context should retain its own directional treatment and may need isolation.

Avoid applying RTL direction broadly to values that are intrinsically LTR, including URLs, code samples, file paths, and machine-readable identifiers. Their surrounding labels can be RTL while the value field remains LTR. This is often clearer for users and safer for copy-and-paste operations.

Design localization resources for mixed content

Localization resource design determines whether bidi can be solved cleanly or repeatedly patched in the UI. Do not concatenate fragments such as `"Error: " + serverName + " failed"`. Concatenation removes the translator’s control over word order, punctuation, spacing, and directional context.

Use complete, parameterized messages instead. Give placeholders meaningful names and provide translator comments that identify expected content, direction, and formatting constraints. A note such as “{fileName} is an LTR filename; preserve it exactly” is more actionable than a generic instruction to retain a variable.

Treat markup and placeholders as protected structure. Translators need context, but they should not have to guess whether `{0}`, `%s`, or `{{orderId}}` may contain RTL text, LTR text, or a number. If a placeholder is inserted into a punctuation-sensitive position, the resource format or rendering layer should support applying an isolate around the resolved value.

Dates and numbers deserve separate attention. Arabic locales may use different numeral preferences, calendar conventions, separators, and ordering. Formatting values through locale-aware APIs handles more than translation alone. Hard-coded date patterns and manually assembled currency strings create defects that are easy to miss in English testing.

A practical bidirectional text guide for QA

Bidi validation requires visual testing in the actual target environment. A translation preview is useful, but it cannot fully expose browser behavior, native control behavior, font fallback, clipping, mirrored navigation, or copy-and-paste problems.

Test representative strings that combine RTL prose with Latin product names, long URLs, email addresses, file paths, version numbers, percentages, currency values, parenthetical phrases, and punctuation at the beginning and end of placeholders. Test empty placeholders and values that begin with a digit or symbol. These cases reveal directional assumptions hidden in ordinary content.

Review interaction behavior as well as appearance. Confirm that caret movement follows expected character and word boundaries, text selection includes the intended characters, and copied values retain their logical order. In editable controls, verify that typing an LTR value into an RTL paragraph does not produce an unusable cursor experience.

Automated checks can support this work. Scan resources and generated output for unexpected bidi control characters, flag overrides for manual review, and validate that required controls are balanced. A localization platform such as Soluling can centralize resource scanning, translation context, visual review, and validation across application and document formats, which reduces the chance that one format receives less bidi scrutiny than another.

Common implementation mistakes

The first mistake is reversing strings in code. Reversing text corrupts logical order, breaks shaping for Arabic scripts, and creates unreliable results for numbers and punctuation. Store normal Unicode text in logical order.

The second is relying on text alignment. `text-align: right` may make a label look plausible, but it does not establish paragraph direction or correct the order of embedded runs. Directionality and alignment must be configured independently.

The third is using directional controls as permanent patches without recording why they exist. If a resource contains an invisible control, document its purpose in translator notes or source comments. Otherwise, a future edit can remove the matching boundary or introduce another control that changes the result.

Finally, do not assume all RTL locales behave identically. Arabic, Hebrew, Persian, and Urdu share RTL writing direction, but their typography, numeral expectations, terminology, and product conventions differ. Test with the actual locales your product supports rather than a generic RTL pseudo-locale alone.

A reliable RTL release comes from treating directionality as part of product engineering: define direction structurally, isolate dynamic mixed-direction values when needed, preserve complete translatable messages, and validate the rendered output where users will actually read and edit it.