DEV Community

James Sanderson
James Sanderson

Posted on

An RTL Checklist That Catches What Frameworks Miss

Turn on RTL support in React Native, Flutter, SwiftUI or Compose and roughly 80% of your layout mirrors correctly on the first try. That number is the problem. It is high enough to feel finished and low enough that the remaining 20% will be found by your users.

This is the checklist for the 20%.

1. Mirror by meaning, not by geometry

The framework mirrors the view hierarchy. It does not know which elements carry directional meaning.

Mirror: navigation and back affordances, the back gesture edge, progress indicators, sliders, carousels and their swipe direction, list disclosure chevrons, drawer position, alignment of body text.

Do not mirror: logos and wordmarks, media playback controls (a mirrored play button reads as rewind), clock and timer faces, phone numbers, most physical-world icons, and time-series charts where the reader's expectation of time flowing one way outweighs layout direction.

Ambiguous by product: back/forward media controls, undo and redo, and any icon whose arrow is metaphorical rather than navigational. Decide these deliberately and write the decision down, because otherwise a future contributor will "fix" it.

2. Use logical properties everywhere

Anywhere your codebase says left or right, it is a latent RTL bug.

Use start and end semantics: marginStart, paddingEnd, textAlign: start, flexDirection: row with logical alignment rather than manual reversal. Add a lint rule banning physical directional properties in UI code. Without the lint rule, the pattern degrades within two quarters, because writing marginLeft is muscle memory.

Padding asymmetries are the sneakiest case: a 16/8 left/right padding pair that reads as deliberate design in LTR reads as a misalignment in RTL, and nobody will file it as a bug — they will just find the screen slightly wrong.

3. Isolate mixed-content runs explicitly

This is where the real bugs live. Arabic apps constantly mix Latin content: brand names, URLs, product SKUs, email addresses, phone numbers, prices.

The Unicode bidirectional algorithm resolves runs by character class, and neutral characters (spaces, punctuation, digits) take direction from their surroundings. Concatenate a Latin string into an Arabic sentence without isolation and you get reordered phone digits, URLs split across the sentence, or a price rendered on the wrong side of its symbol.

Fixes, in order of preference:

  • Use the platform's localized formatters for numbers, currency and dates rather than string concatenation. This solves the majority of cases for free.
  • Wrap embedded foreign-direction runs in isolate marks (U+2068 / U+2069) or the platform's equivalent bidi-isolation API.
  • Never build a user-visible string by concatenating a localized fragment with a raw data value. Use parameterized format strings so the formatter can reason about the whole sentence.

Critically: these bugs will pass your tests. A snapshot test comparing strings passes because the characters are all present and in logical order — it is the visual order that is wrong. Only rendered-screenshot review, by someone who reads Arabic, catches them.

4. Typography needs its own pass

  • Use a typeface with a real Arabic cut, not system fallback. Fallback renders glyphs correctly in isolation and fails at contextual joining.
  • Increase line height relative to your Latin setting. Arabic sits differently on the baseline and carries marks above and below; Latin-tuned leading feels cramped.
  • Do not use Latin font weights as a proxy for Arabic emphasis. Many Arabic typefaces have fewer weights, and synthetic bolding looks broken.
  • Verify text rendering on older Android hardware, which remains common in the market — font fallback behaviour differs from what you see on a current device.

5. Numerals and calendars are product decisions

Eastern Arabic (٠١٢٣) versus Western Arabic (0123) numerals is not a technical choice; it is an audience choice with no universally correct answer. What matters is consistency across UI, notifications, receipts and exported documents.

Where dates carry religious, governmental or contractual meaning, Hijri calendar support is required — and it needs to work in scheduling and reminders, not only in a display formatter. Converting for display while scheduling against Gregorian internally is a defensible architecture; getting them out of sync is a support ticket you will not enjoy.

6. Test the things that only break at runtime

  • Language switch mid-session. On some platforms an RTL toggle requires a restart; if yours does, handle it deliberately rather than leaving the app in a half-mirrored state.
  • Deep links and push notifications opening into a screen in the other direction.
  • Text input with mixed direction — typing a Latin email address into an Arabic form is where cursor behaviour, selection and backspace get strange.
  • Screenshots for store listings in both directions, at every required device size.
  • Accessibility: verify screen reader reading order in RTL, which does not automatically follow visual order.

7. Put a native reader in the release process

Everything above is mechanical and can be enforced with tooling. This last item cannot.

A native Arabic speaker with product judgment needs to look at real screens before every release. Not a translator checking strings in a spreadsheet — someone using the app. They will catch the register of the copy, the mixed-content rendering, and the small wrongnesses that no test asserts on and every user perceives.

The broader guide — SAR cost benchmarks, PDPL and residency, mada and Nafath integration, and how to vet a partner — is here: Mobile App Development Company in Saudi Arabia: The 2026 Buyer's Guide. How we run delivery is on our mobile app development page.

Frequently Asked Questions

Does enabling RTL in my framework handle Arabic support?

It handles most layout mirroring and none of the judgment. Framework RTL does not know which elements carry directional meaning, does not fix bidirectional text isolation, and does not address typography, numerals or copy quality.

What should never be mirrored in an RTL layout?

Logos and wordmarks, media playback controls, clock and timer faces, phone numbers, most physical-world icons, and time-series charts. Mirroring these produces interfaces that look intentional and read as wrong.

Why do bidirectional text bugs pass automated tests?

Because the characters are present and in correct logical order — the failure is in visual order after the bidirectional algorithm resolves runs. Only rendered-screenshot review by an Arabic reader reliably catches them.

How do I prevent RTL regressions over time?

Add a lint rule banning physical directional properties (left, right, marginLeft) in UI code, and run screenshot tests in both directions on critical screens. Without enforcement, the pattern degrades within a couple of quarters.

Do I need Hijri calendar support?

Wherever dates carry religious, governmental or contractual meaning. It needs to work in scheduling and reminders rather than only in display formatting, and the conversion boundary between Hijri display and internal storage must be explicit.

Is screen reader order automatic in RTL?

No. Accessibility reading order does not automatically follow visual order in mirrored layouts, so verify it explicitly on both platforms as part of RTL QA.

Top comments (0)