RTL testing vs localization testing
Learn how RTL and localization testing differ, where they overlap, which defects each finds and how to combine them for an Arabic release.
Guide15 min read
A translated Arabic screen can still be unusable in RTL. A perfectly mirrored screen can still contain the wrong words, currency or plural form. That is the practical difference between localization testing and RTL testing.
Localization testing checks whether the product has been adapted to a language and market. RTL testing checks whether the interface behaves correctly under right-to-left direction. An Arabic release needs both because neither discipline contains the other.
The boundary is useful when a defect appears. A payment error left in English belongs to the localization pipeline. A tracking number that displays in the wrong order inside a translated sentence belongs to bidi markup. A translated alert clipped at mobile width sits in the overlap: localized content exposed a layout constraint.
The difference at a glance#
| Question | Localization testing | RTL testing |
|---|---|---|
| Are strings translated and contextually correct? | Primary scope | Only where untranslated text affects RTL review |
| Do variables and plural branches render correctly? | Primary scope | Checks their direction boundaries when mixed |
| Are date, digit, currency and unit formats right for the market? | Primary scope | Checks their visual ordering in RTL context |
| Does the document declare RTL direction? | Confirms locale setup | Primary scope |
| Do Arabic and Latin runs stay readable together? | May supply the test content | Primary scope |
| Do components use logical start and end relationships? | Exposes failures through translated content | Primary scope |
| Does Arabic text fit and use the intended font? | Shared scope | Shared scope |
| Do phones, emails and URLs edit LTR inside an Arabic form? | Confirms localized form content | Primary scope |
| Is focus order logical after visual mirroring? | Usually secondary | Primary scope |
| Is terminology appropriate for the market? | Primary scope | Out of scope |
This is not a competition between two test plans. They inspect different properties of the same running product. The useful outcome is a combined pass whose failures route to the correct owner.
What localization testing proves#
Localization testing starts with the product's locale contract. It verifies that the Arabic version receives the right content and market behavior wherever the product can go.
Translation delivery#
A complete catalog does not prove runtime coverage. The product may request the wrong key, use a stale bundle, hard-code a component default or receive an untranslated message from a service.
Test states rather than pages:
- loading and progress;
- empty and no-results;
- validation and error summaries;
- server and network failures;
- permission denial and disabled states;
- session expiry;
- confirmation, receipt and follow-up actions.
Inspect non-visible strings as well: placeholders, image alternatives, tooltips, aria-label values and button values. R011 reports untranslated interactive labels such as buttons and menu items. R012 reports untranslated attribute text.
Not every Latin token is a translation gap. An email address, URL, product model or approved brand name may intentionally stay Latin. Localization testing needs a content policy narrow enough to distinguish those terms from an English fallback.
Message structure and grammar#
Localization testing checks whether variables appear in the right place and plural logic uses the target locale rather than English rules. English has two plural forms; Arabic has six, and a fixture that only tries 1 and 5 misses most of them:
const rules = new Intl.PluralRules("ar");
rules.resolvedOptions().pluralCategories;
// ["zero", "one", "two", "few", "many", "other"]
[0, 1, 2, 3, 11, 100].map((n) => rules.select(n));
// ["zero", "one", "two", "few", "many", "other"]Those are the results in Chromium 151. The six counts make a compact fixture: one result count per category, rendered through the real message. A message with a one and an other branch passes an English-shaped test and then shows the wrong noun form for two, three and eleven results. Messages built from translated fragments fail here too, because a fragment cannot agree with a number it never sees; keep the whole sentence in one resource with the count as a placeholder.
The framework should use locale-aware plural categories, and fixtures should exercise every category returned for the supported Arabic locale. Engineering can test branch selection. A qualified Arabic reviewer must approve the resulting grammar.
Market formats#
Localization testing owns the product rule for digits, calendar, dates, time, currency, percentages, units, names and addresses. There is no single universal Arabic choice.
Locale defaults are not the decision, and they change between runtime versions. A Kuwaiti store shows why the decision has more than one part: in Chromium 151, ar-KW defaults to Arabic-Indic digits, and the dinar is divided into 1,000 fils, so prices carry three decimal places where most currencies carry two. Because the formatted string carries locale spacing and invisible direction marks, assert the decisions rather than the text:
const price = new Intl.NumberFormat("ar-KW", {
style: "currency",
currency: "KWD",
numberingSystem: "latn",
});
expect(price.resolvedOptions().numberingSystem).toBe("latn");
expect(price.resolvedOptions().maximumFractionDigits).toBe(3);Those options demonstrate one possible Saudi product decision, not a rule for all Arabic products.
Test a date whose day is above 12, prices with decimals and thousands, negative amounts, zero and percentages. Check UI, email, export and receipt because they often use different formatting paths. R060, R061, R062 and R063 report common date, digit, currency and percentage or unit inconsistencies.
Locale delivery and metadata#
Open Arabic deep URLs, refresh, authenticate, follow links and switch locale mid-task. Confirm that the route and application state follow the product's defined behavior. Inspect title, description, social metadata, language alternatives and canonical URL for public pages. R003, R004, R005 and R006 cover common metadata and locale-relationship failures.
What RTL testing proves#
RTL testing starts with the direction contract and follows it into text, layout and interaction.
Semantic direction#
The two root attributes often come from different places, which is where this split first shows. A content system can supply lang from the entry's locale while dir is hard-coded in a layout template, and the result passes a translation review and fails a direction review:
<html lang="ar" dir="ltr">lang identifies the content language and does not imply direction. The HTML dir documentation recommends setting direction explicitly at the root for RTL documents, and both attributes should come from the same locale setting. A global CSS rule is not an equivalent contract either: direction: rtl renders right to left without making :dir(rtl) match. Test the live root after direct entry, hydration and client-side locale changes. R001 reports a missing or LTR root direction on an Arabic page. R002 reports a missing or contradictory root language.
Bidirectional text#
Arabic products contain LTR data inside RTL sentences. The browser resolves that line with the Unicode Bidirectional Algorithm, in which Latin letters, Arabic letters, digits and punctuation behave differently.
Problem
<p dir="rtl">رقم التتبع 1234 5678 9012</p>Measured in Chromium 151, the tracking number displays as 9012 5678 1234: after the Arabic label, its space-separated groups are laid out from right to left. A customer comparing it with the same number on the courier's left-to-right page sees the groups in a different order.
Better
<p dir="rtl">رقم التتبع <span dir="ltr">1234 5678 9012</span></p>A tracking number is always left to right, so dir="ltr" states it. <bdi> does the same job for a value whose direction is not known in advance, taking that direction from the value itself. Keep the wrapper around the value: an element that also holds the Arabic label takes its direction from the label.
The W3C inline bidi guidance recommends tightly wrapping opposite-direction phrases. Do not reverse values in application code or add spaces in translation as a repair. R021 reports unisolated phones, emails and Latin tokens inside Arabic text.
Direction-aware layout#
RTL layout follows logical relationships. Inline start is on the right. That does not mean every coordinate or icon should flip.
Problem
.dialog-close {
position: absolute;
top: 16px;
right: 16px;
}Better when the button belongs at the end corner
.dialog-close {
position: absolute;
top: 16px;
inset-inline-end: 16px;
}CSS logical properties express direction-relative placement. Physical properties remain correct for physical meaning, such as a media timeline.
Review offsets, margins, padding, floats, corners, shadows, text indents and transforms. Avoid row-reverse as a substitute for RTL because visual reversal can fight DOM and keyboard order. R030, R031, R032, R033 and R081 report these patterns.
Field and interaction direction#
Arabic labels and prose fields usually inherit RTL. Phone, email, URL and code values often remain LTR. A tracking-number lookup field shows why that matters: typed into a field that inherits right to left, the number's groups reorder exactly as they do on the page. Only type="tel" is left to right by default; other text fields need dir="ltr" for values like this.
Test typing, pasting, caret movement, selection and deletion. R070 reports telephone, email and URL controls rendered RTL. R023 reports text inputs rendered LTR where Arabic input is expected.
Use the keyboard through the task. CSS can change visual order without changing DOM order. The WCAG focus-order guidance requires a sequence that preserves meaning and operation. A visually mirrored toolbar with a jumping tab path is not complete RTL support.
Where the two disciplines overlap#
The overlap contains some of the hardest defects because content and rendering both contribute.
Text expansion and clipping#
Localization supplies the Arabic text; RTL layout determines where it flows. A long translated validation message may expose a fixed height, physical padding or an absolutely positioned icon. The copy is not wrong because it does not fit.
Reproduce the issue with the approved translation, then inspect font, line height, width, overflow and positioning. R041, R042 and R043 report overlap, clipping and fixed-width containers exceeded by Arabic content.
Typography and fallback#
Localization decides the script and content. Rendering decides the font and shaping. A declared family may cover Latin but omit Arabic, so product names use one face while Arabic falls through to another. Positive letter spacing can separate connected Arabic letters.
Inspect the rendered font after web fonts load. R050 reports measured fallback or a stack with no Arabic-capable family. R051 and R055 report positive tracking and Latin display styling applied to Arabic.
Form validation#
Localization owns the Arabic label, help and error message. RTL testing owns field direction, icon placement, editing and error geometry. Browser behavior adds another boundary: the document language does not translate native validation UI, so an Arabic page in an English browser shows English bubbles.
If the product requires Arabic validation, render localized application messages and test their field association. R071 reports untranslated form labels, validation and help text.
Formatted values inside Arabic sentences#
Localization testing decides how a price or date is formatted. RTL testing verifies that the formatted output remains readable next to Arabic text. A value can be correct in isolation and interact badly with surrounding punctuation or an unisolated variable.
Keep the formatter's output intact, including locale spacing and bidi controls. Test it in the complete sentence, not only in a unit test that strips invisible characters.
Similar symptoms can have different causes#
Classification prevents teams from applying the wrong fix.
| Symptom | Localization cause | RTL cause | Diagnostic step |
|---|---|---|---|
| English text on Arabic route | Missing key or server fallback | Intentional Latin value lacks isolation | Identify content source and policy |
| Text appears on wrong side | Wrong locale state | Missing or overridden dir | Inspect live root and computed direction |
| Button label clips | Translation is unusually long but valid | Fixed width, fallback font or physical padding | Render approved copy and inspect bounds |
| Price looks wrong | Wrong currency or numbering policy | Sign or unit reorders in RTL context | Compare formatter output alone and in sentence |
| Form feels backward | Label or help remains untranslated | Field uses direction unsuitable for its data | Inspect copy and edit a real value |
| Error is unreadable | Wrong translation or concatenated message | Unisolated ID or punctuation | Reduce to complete message and variable boundary |
| Tab sequence jumps | Not usually a translation issue | Visual reordering differs from DOM | Disable visual order rules and retest |
A screenshot rarely settles the cause. Use the DOM, translation key, formatter input, computed styles and authored value. Reduce the failing component until the content or layout behavior can be reproduced independently.
One symptom shows the boundary especially well. An untranslated fallback such as Payment failed. on an Arabic page displays as .Payment failed, with its full stop at the left end. It reads as a direction bug, and an RTL pass would find it, but the cause is a missing translation: the full stop takes the direction of the paragraph around it, and once the Arabic string arrives it sits where an Arabic sentence ends.
A wrong price splits the same way. First format the value outside the Arabic sentence. If currency and digits are already wrong, fix localization configuration. If the isolated output is correct but the sign moves in context, inspect bidi boundaries. One symptom, two owners.
Three ways a release can pass the wrong test#
The difference becomes clearest when one test plan reports success and users still encounter a defect.
Localization passes, RTL fails#
Suppose the language reviewer approves the shipping message and the correct tracking number reaches the component. The translation is accurate, the variable was interpolated and the stored value is right, so localization testing passes every assertion it makes. The number still displays with its groups reversed, because nothing isolates it from the Arabic sentence.
The repair is not a new translation. It is a tighter markup boundary, and the regression test belongs there too: assert the displayed order rather than the value the API returned, because that value is correct in the failing case. Sending the ticket back to the translator wastes time and encourages unsafe workarounds such as added spaces or manually reversed text.
RTL passes, localization fails#
Now consider a checkout whose document declares RTL, components use logical properties, mixed values are isolated and focus order is coherent. The direction pass succeeds. The total still uses USD, the delivery date shows an English month name and a server rejection appears in English.
Nothing about correct mirroring chooses the currency, translates the remote error or configures a date formatter. Those are locale and content-pipeline failures. Fix the formatter and the producing service, then add test states for the rejected payment and receipt. Do not add direction overrides to a correctly behaving component.
Both isolated tests pass, but the integrated state fails#
The most deceptive case appears when translation review and component RTL stories pass separately. A two-line Arabic payment error is approved in the catalog. The alert component passes RTL with a short fixture. In checkout at 320 pixels, the real message collides with the retry button because the production variant has a fixed height and an absolutely positioned action.
Neither isolated result was false. The tests omitted the combination that mattered. The fix belongs in component sizing and the missing evidence belongs in a product-state fixture containing the approved message.
This pattern also appears with fonts. A translation preview uses a system Arabic font and fits. A component story uses short Arabic copy and the production web font. The complete product falls back for some glyphs after loading, changes line metrics and clips the label. Localization supplied valid content; RTL supplied direction; integration exposed typography.
Treat every shared boundary as a combined test point:
- translated variables inside RTL sentences;
- locale-formatted values beside Arabic labels;
- approved long copy inside direction-aware components;
- localized errors returned asynchronously;
- Arabic font loading at narrow widths;
- translated controls after visual reordering;
- locale changes during a partially completed form.
The lesson is not to merge the disciplines into one vague Arabic review. Keep their assertions explicit, then run them against the same state. That preserves ownership while covering the interaction neither isolated plan can see.
A checkout shows why both are required#
Consider an Arabic checkout with product, address, payment and confirmation steps.
Localization testing should verify:
- every label, error, loading state and confirmation is translated;
- promotion and payment errors returned by services use Arabic;
- quantities use the correct Arabic plural branches;
- totals use the approved currency, digits and separators;
- delivery dates use the approved calendar and date pattern;
- names and addresses follow market requirements;
- the receipt and notification use the same locale rules as the UI.
RTL testing should verify:
- the document and nested components inherit RTL correctly;
- breadcrumbs, step indicators and action rows use logical order;
- product codes, phone numbers and tracking numbers remain readable;
- address fields accept Arabic while phone and email remain editable LTR;
- field icons, select arrows and validation indicators sit at the intended edge;
- long errors and totals do not overflow at supported widths;
- keyboard focus follows a logical task sequence;
- back and next icons communicate the correct action.
The confirmation screen needs both. A translated receipt whose tracking number displays in the wrong order causes support calls. A perfectly isolated ID beside an English confirmation still fails the locale promise.
Ownership should follow the failure layer#
Assigning every Arabic defect to localization creates a queue that cannot fix CSS, markup or focus order. Assigning every defect to frontend leaves language and market decisions to people without the required expertise.
| Defect | Primary owner | Reviewer |
|---|---|---|
| Missing translation | Localization or content owner | Arabic language reviewer |
| Wrong terminology or tone | Arabic language reviewer | Product or content owner |
| Wrong currency or calendar rule | Domain engineering | Product or market owner |
| Missing root direction | Frontend or platform engineering | QA |
| Reordered mixed-direction value | Frontend engineering | QA with expected value |
| Physical CSS failure | Component owner | QA or design |
| Arabic font fallback | Design-system or frontend owner | Design and language reviewer |
| Illogical focus after mirroring | Component owner | Accessibility reviewer |
The bug report should make routing easy. Include the route, locale, state, browser, viewport, translation key when known, authored value, observed display, expected market rule and a screenshot or computed-style detail.
Avoid titles such as "Arabic layout issue." Prefer "Shipping confirmation shows tracking number 1234 5678 9012 as 9012 5678 1234" or "Arabic payment error overlaps retry button at 320px." The owner can see the likely layer before opening the ticket.
Combine the plans without duplicating work#
Use shared journeys and fixtures, then attach different assertions.
Component tests#
Render direction-aware components with real Arabic content, mixed values, long labels and error states. RTL assertions cover logical placement, field direction and focus. Localization assertions cover resolved messages, placeholder integrity and plural branches.
Integration tests#
Exercise locale routing, fallback behavior, formatters, server errors and translation loading. Assert the live root attributes and test formatted values in their rendered Arabic context.
Browser journeys#
Choose critical tasks that cross real system boundaries. Checkout, account creation and order lookup are useful because they include routing, forms, validation, mixed data and confirmation. Run them at more than one viewport and preserve evidence when they fail.
Human review#
Arabic language reviewers approve grammar, tone, terminology and market fit in context. QA and engineering inspect direction, geometry and interaction. Accessibility review covers keyboard and assistive technology. No automated result replaces these judgments.
Ritla covers the RTL side of this split and part of the localization side: its checks for untranslated labels (R011) and attribute text (R012) sit beside the direction, layout and form checks in every check. Use each finding to reproduce the state and route it to the responsible layer.
A practical combined test pass#
Run one critical journey with a fixture containing Arabic copy, a tracking number, a Latin product code, phone, email, date and price.
- Enter through an Arabic deep link. Confirm locale persistence,
lang="ar"anddir="rtl"in the live document. - Expose every state. Open loading, empty, invalid, failed and success surfaces. Check visible and attribute text.
- Verify language and variables. Review terminology, plural branches, interpolation and intentional foreign terms.
- Verify market formats. Check digits, calendar, date order, currency, units and punctuation against the locale contract.
- Verify bidi values. Test IDs, phones, emails, URLs and percentages at several sentence positions.
- Stress geometry. Change width, zoom, load long strings, wait for fonts and open overlays. Measure overflow.
- Operate forms. Type Arabic prose and LTR values, move the caret, trigger every validation path and test autofill.
- Use only the keyboard. Follow focus through the task, including errors and dialogs.
- Classify every defect. Content delivery, language, format, direction, bidi boundary, CSS, font, form or DOM order.
- Add the regression at the owning layer. Preserve the smallest fixture that catches the failure.
For a shorter release-day pass, use the RTL testing checklist for Arabic websites. It does not replace language and market review, but it prevents the direction side of the release from becoming an informal visual check.
The distinction is simple enough to remember: localization testing adapts the product to Arabic and its market; RTL testing makes that adaptation behave correctly in a right-to-left interface. The release is ready only when both claims are true in the same product state.
Checks in this guide
- R011Untranslated interactive labels (buttons, nav/footer links, menu items, tabs)
- R012Untranslated attribute text (placeholder, alt, title, aria-label, button value)
- R060English month/day names or MM/DD/YYYY dates in Arabic text
- R061Arabic-Indic and Western digits mixed in the same context
- R062Foreign currency formatting in a SAR/AED market context
- R063Percent/unit ordering inconsistencies (%50 vs 50%)
Show every check in this guideShow fewer
- R003hreflang alternate set lacks any Arabic entry on an Arabic page
- R004<title> or meta description majority-Latin on an Arabic page
- R005OpenGraph/Twitter metadata untranslated or og:locale missing/invalid
- R006Canonical URL points at a different-locale variant
- R001document direction missing, contradicted, or declared only in CSS
- R002html[lang] missing, non-Arabic, or contradicting detected content
- R021Unisolated bidi hazards: phones, emails, Latin tokens inside Arabic text
- R030Direction-sensitive physical properties without an RTL override
- R031float: left/right on content elements in RTL context without override
- R032Direction-sensitive shadow x-offsets without an RTL counterpart
- R033translateX moves the element off-screen in RTL
- R081flex row-reverse faking RTL instead of dir (tab order fights visual order)
- R070tel/email/url inputs rendered RTL (these must stay LTR)
- R023Text inputs rendered LTR where Arabic input is expected
- R041Visible text-bearing elements overlapping
- R042Clipped text: content wider than its box with overflow hidden and no ellipsis
- R043Fixed-pixel-width container whose Arabic text exceeds the space
- R050Arabic text falling back past the declared font family (measured, declared, or a webfont that failed to load)
- R051letter-spacing applied to Arabic text (breaks the connected script)
- R055Latin display styling (uppercase + tracking) applied to Arabic
- R071Untranslated form labels / validation / help text