How to test an Arabic website before launch

Use this pre-launch plan to prioritize Arabic journeys, test RTL behavior, content, formats and forms, and decide which defects block release.

Guide14 min read

The final week before launch is too late for a page-by-page tour with generic Arabic copy. The expensive defects appear inside tasks: sign-in drops the locale, checkout loads an English service error, a phone field edits RTL, or the verification code at sign-in reads backwards across its boxes.

A useful pre-launch pass starts with the journeys that can stop users, forces their hidden states, and records evidence against a written locale contract. It does not attempt to inspect every pixel with equal depth.

This plan runs in risk order. If the Arabic route or document setup is wrong, fix that before reviewing spacing. If mixed values are corrupt or checkout cannot complete, do not spend the remaining test window polishing a minor icon offset.

Freeze the launch contract#

Before testing, write down what the release claims to support. Otherwise every format and fallback becomes a debate during triage.

The contract should identify:

  • Arabic locale and market combinations in scope, such as ar-SA or ar-AE
  • URL pattern and behavior of the language switcher
  • Required digit system, calendar, currency, date order and time zone
  • Supported browsers, operating systems and viewport range
  • Critical journeys that must complete in Arabic
  • Content allowed to remain in another language
  • Language-review owner and launch decision owner
  • Fallback behavior when Arabic content is missing

Do not let a generic ar locale silently decide market policy. Runtime defaults are useful, but a Saudi checkout and a UAE checkout can require different currency and content even though both are Arabic and RTL.

Freeze testable content at the same time. Use approved Arabic strings rather than temporary placeholders. Include a long navigation label, a multiline validation error, the hotline number in both digit systems, an email address, a verification code, a large price, a negative value, a date with a day above 12, a long address and a mixed-language user name.

The purpose of freezing is not to ban all changes. It creates a known baseline. A late translation or component update then has a visible test impact and a named owner.

Prioritize journeys before pages#

Rank product tasks by business impact, direction complexity and number of system boundaries. A static marketing page matters, but it should not consume the same depth as account recovery or payment.

A common risk order is:

  1. Authentication, account recovery and locale persistence
  2. Checkout, payment, confirmation and receipt
  3. Identity, contact, address and profile forms
  4. Search, filtering, sorting and result details
  5. Account, orders, billing and support journeys
  6. Public acquisition pages and metadata
  7. Secondary content and low-traffic informational pages

For each journey, list states rather than URLs. Checkout includes empty cart, populated cart, unavailable item, invalid promotion, loading, payment rejection, timeout, confirmation and receipt. Search includes initial, loading, results, no results, invalid input, network failure and retry.

Use the same account and domain state for LTR and Arabic comparisons. If the English screenshot shows a completed order while the Arabic screenshot shows an empty state, geometry differences cannot be attributed to direction or translation.

Mark system boundaries in the journey: identity provider, payment service, CMS, email service, document generator and analytics or support widget. These are common places for locale parameters or translated messages to disappear.

Prepare an environment that can fail realistically#

A staging environment filled with short placeholder copy and successful API responses produces false confidence. Seed the states the release must survive.

Prepare:

  • accounts in new, active, restricted and expired states;
  • successful and rejected payment fixtures;
  • products with long Arabic names and Latin model numbers;
  • orders with numeric and Latin-prefixed IDs;
  • empty, partial and large result sets;
  • long addresses and validation failures;
  • content with missing images and slow loading;
  • a way to trigger server, network and permission errors;
  • web-font success and fallback conditions.

Record the build, locale, browser, operating system and viewport in every result. A native select or font failure may depend on the environment. Do not generalize behavior observed in one engine to all supported browsers.

If feature flags or personalization change the page, include them in the test record. A defect that cannot be reproduced because the test state was undocumented is not useful release evidence.

Build a browser and device matrix by risk#

Do not test every route in every environment with the same depth. Define a small matrix that reflects actual support, then vary coverage by journey risk.

For each supported browser family, record:

  • browser and operating-system versions;
  • browser interface language;
  • installed Arabic fonts or expected web fonts;
  • input method and physical or virtual keyboard;
  • viewport dimensions, pixel ratio and zoom;
  • touch, pointer and keyboard availability;
  • whether autofill, password management or native validation is part of the task.

Browser interface language matters because it can affect native UI outside the page's translations. Measured in Chromium 151, a required input on an Arabic page displayed the browser's English validation message while the browser itself ran in English. The page's lang identifies the document language; it does not translate the browser's own UI.

Operating system and font availability also matter. If the web font fails, the fallback chosen for Arabic can differ by environment and change width, baseline or line height. A layout that fits on one test machine may wrap differently elsewhere. Test the intended font and a realistic failure or slow-load state.

Use coverage tiers:

Coverage tierWhat to run
Launch-criticalFull journey, all states, keyboard pass, minimum viewport and primary supported environments
Shared-componentDirection, long content, fonts, focus and interaction in each supported browser family
Secondary routesLocale-entry, translation, overflow and task smoke tests
Low-risk contentAutomated document and content checks plus targeted visual review

For mobile, test more than a resized desktop window when device support matters. Exercise the touch target, virtual keyboard, viewport resizing, sticky controls and scroll behavior. A form can pass at the same CSS width on desktop while the on-screen keyboard covers its error or submit action on a phone.

For desktop, include keyboard-only operation and zoom. Test tables, dense navigation, hover-triggered help and windows narrow enough to activate responsive layouts. Record the exact width at which a failure begins rather than reporting only "tablet" or "mobile."

Native controls deserve targeted coverage. Expanded selects, date pickers, autofill and validation can use browser or operating-system UI. If their behavior is uncertain, reproduce it in the launch matrix and record the environment rather than assuming one browser's result applies to another.

When time is constrained, reduce route coverage before reducing critical-journey depth. One checkout tested through rejection, correction and confirmation across the primary matrix is stronger launch evidence than twenty pages opened only at a desktop width.

Pass 1: locale entry and document setup#

Open an Arabic deep URL in a private session. Refresh it, navigate internally, open a new tab, sign in, sign out and follow any redirect used by a critical task. The locale should persist according to the contract.

Inspect the live root on every public route rather than a sample. A short script over the routes in your sitemap finds the one that lost its attributes:

js
// routes: the Arabic URLs from your sitemap
for (const url of routes) {
  const html = await (await fetch(url)).text();
  const root = html.match(/<html[^>]*>/)?.[0] ?? "";
  if (!/\bdir=["']?rtl/.test(root) || !/\blang=["']?ar/.test(root)) console.log("check", url, root);
}

This reads the server's HTML, which is what a crawler and a slow connection see first. Check the live DOM after hydration too, because client code can change the attributes in either direction.

That reads the server's response, so repeat the check in a browser after a client-side locale change: a route can look Arabic while keeping lang="en", dir="ltr" or both from the first page. lang does not imply direction, as the HTML dir documentation notes, and a global CSS direction: rtl is not a full substitute, because :dir(rtl) does not match it.

R001 reports a missing or left-to-right root direction on an Arabic page. R002 reports a missing, non-Arabic or contradictory root language.

For public pages, inspect title, meta description, social metadata, canonical and language alternatives. The Arabic URL should not identify a different-locale page as its canonical unless that is the deliberate product policy, and the alternate set should include Arabic. R003, R004, R005 and R006 cover these failures.

Block launch if critical Arabic entry points lose the locale, if the root semantics are wrong across the site, or if authentication or payment redirects users into another locale with no recovery.

Pass 2: translation coverage in every state#

Review visible and hidden content for each critical journey state. Begin with interactive copy because an untranslated action or error can stop a task.

Check:

  • navigation, tabs, menus and footer links;
  • buttons, labels, help and validation;
  • loading, empty, failure and confirmation messages;
  • placeholders, tooltips and image alternatives;
  • aria-label values and icon-only control names;
  • server errors, third-party widgets and CMS content;
  • emails, receipts and downloads generated by the task;
  • titles and metadata for shareable pages.

R011 reports untranslated interactive labels. R012 reports untranslated attribute text. R010 reports broader visible Latin-script body content above its thresholds.

Not every Latin term is wrong. Emails, URLs, approved brand names and model codes may remain Latin. Use the content policy rather than hiding complete components from review. A broad exception can conceal a future English fallback in the same region.

Test interpolation with long Arabic and Latin names, dates, numeric IDs and punctuation. Exercise every plural category returned by the localization runtime for the supported Arabic locale. Engineering verifies that the correct branch and variables render. An Arabic reviewer approves grammar, tone and terminology in the resolved state.

Block launch when a critical task exposes untranslated instructions, validation, errors, legal text or accessible names. A non-critical approved foreign term is not a blocker simply because it uses Latin script.

Pass 3: mixed-direction data#

Translation review cannot prove that dynamic values stay readable inside Arabic pages, and launch week is when real data arrives. The browser arranges Arabic letters, Latin letters, numbers and punctuation with the Unicode Bidirectional Algorithm, and two failures are worth checking by hand, because component tests rarely cover them.

The first is the verification code at sign-in. A six-box code input is a row of inputs, and in a right-to-left page a flex row starts at the right:

html
<div class="code-input">
  <input maxlength="1" inputmode="numeric" autocomplete="one-time-code">
  <!-- five more -->
</div>

The boxes fill in DOM order, so the first box, on the right, takes the first digit. Typing 482913 leaves the row reading 319284 from left to right, the reverse of the code in the message, while focus moves normally and typing feels right. A code is read left to right in both languages, so set dir="ltr" on the group and the boxes read 482913 again.

The second is a hotline written in Arabic-Indic digits, which a Saudi launch may use. The spaces between groups of Arabic-Indic digits resolve right to left even inside <bdi> or dir="ltr", so the groups display in reverse order, which in Western digits reads +5678 234 11 966. An override holds them in place:

html
<p dir="rtl">الرقم الموحد <bdo dir="ltr">+٩٦٦ ١١ ٢٣٤ ٥٦٧٨</bdo></p>

Then build a matrix from the values the launch actually shows:

  • the verification code at sign-in and at password reset;
  • the hotline and support numbers in the footer, in both digit systems if the product uses both;
  • order and invoice numbers in confirmation pages and emails;
  • the launch campaign's discount codes;
  • an email address and a URL;
  • each value at the start, middle and end of an Arabic sentence;
  • punctuation immediately after the value;
  • content injected after the initial render.

Check the displayed order, not only the value in the DOM: copy and paste and screen readers follow the source, so they agree with the API while the screen does not. Reversing the source string or adding spaces in translation is not an acceptable repair. R021 reports unisolated phones, emails and Latin tokens inside Arabic text. R024 reports punctuation at the wrong visual end.

Block launch when a price, phone number, verification code, order number or other task-critical value displays in an order that changes its meaning.

Pass 4: direction-aware layout and icons#

Compare relationships, not pixel symmetry. Navigation should sit at inline start, a suffix icon should remain at the suffix edge, and physical content should keep its physical meaning.

Physical CSS often exposes LTR assumptions:

Problem

css
.chat-launcher {
  position: fixed;
  right: 24px;
  bottom: 24px;
}

Better when the launcher belongs at the end corner

css
.chat-launcher {
  position: fixed;
  inset-inline-end: 24px;
  bottom: 24px;
}

CSS logical properties express positions relative to writing direction. Physical values remain correct for a genuinely physical relationship, such as a delivery map.

Review offsets, margins, padding, borders, corner radii, floats, shadows and text indents, and check sliding panels separately, because transforms have no logical form. R030, R031, R032 and R033 report common direction-sensitive properties without suitable RTL handling.

Avoid row-reverse as a substitute for RTL. A flex row already responds to the container direction. Visual reversal can leave DOM and keyboard order in conflict. R081 reports that pattern.

Inspect icons by meaning. Check the arrows on pagination, carousels and the checkout step indicator; a logo, a payment-method mark and a play button keep their shape. Test the icon, label, hit target and action together. R025 reports a directional icon that points against the way its control moves, such as a next arrow pointing back.

Block launch when primary controls are overlapped, unreachable or misleading, or when navigation meaning is reversed. Cosmetic spacing that does not impair meaning can be triaged separately with an owner and deadline.

Pass 5: widths, fonts and dynamic geometry#

Run every critical journey at the minimum supported viewport, one or more intermediate wrap points and a wide desktop size. Increase text size or zoom to 200 percent. Wait for fonts and data, then open menus, dialogs, tooltips, filters, toasts and error summaries.

At each size:

  1. Scroll to both horizontal extremes and look for unexpected document movement.
  2. Compare scrollWidth with clientWidth for the document and suspect containers.
  3. Inspect fixed, sticky and absolutely positioned elements at the left edge.
  4. Load the longest approved Arabic labels and values.
  5. Trigger multiline errors and asynchronous content.
  6. Repeat after the web font finishes loading.

Do not hide a defect with overflow-x: hidden on the page. Locate the element whose bounding box escapes and fix the sizing or position. R040, R041, R042 and R043 report document overflow, text overlap, clipping and fixed-width containers exceeded by Arabic content.

Inspect the rendered font in DevTools, and repeat it on a machine without the brand font installed: when the declared face has no Arabic glyphs, the Arabic characters, and only those, fall through to a different family with different metrics. R050 reports measured fallback or a stack with no Arabic-capable family.

Keep Latin display styling away from Arabic. Positive letter spacing separates connected letters, uppercase has no equivalent effect on Arabic, and synthetic italics may not match the approved type system. R051, R054 and R055 cover these patterns. R052 and R053 report cramped line height and undersized body text.

Block launch when critical content is clipped, overlapped or unreachable, or when Arabic shaping makes required text unreadable.

Pass 6: formats and market rules#

Verify formats against the launch contract, not against personal preference or a developer machine's defaults.

Locale defaults will not answer for you: current locale data gives ar-SA and ar-EG Arabic-Indic digits and ar and ar-AE Western digits, and it changes across runtime versions. Make the launch contract a test that fails the build:

js
import { priceFormat } from "./money"; // the one formatter every price goes through

test("prices follow the UAE launch contract", () => {
  const options = priceFormat.resolvedOptions();
  expect(options.locale).toBe("ar-AE");
  expect(options.currency).toBe("AED");
  expect(options.numberingSystem).toBe("latn");
});

That expresses one possible UAE requirement, not a universal Arabic convention.

Test a day above 12, month names, midnight, a time-zone boundary, decimals, thousands, negative values, zero, percentages and units. Check the same value in UI, filters, email, export and receipt. Keep formatter output intact, including locale spacing and bidi controls.

R060, R061, R062, R063 and R064 report common date, digit, currency, percent or unit, and punctuation inconsistencies.

Block launch when the wrong currency, date meaning or amount could affect a transaction, commitment or legal document. A consistent but non-preferred digit style may be triaged only if the written market contract allows it.

Pass 7: forms and validation#

Test forms as editing experiences. Arabic names, addresses, queries and prose normally inherit right to left. Phones, emails, URLs and many codes stay left to right, and only type="tel" is left to right by default, so check the computed direction of every other field that holds a machine format.

For each critical field, type, paste, select, move the caret and delete around punctuation. Trigger required, format, server and cross-field errors. Check labels, help, summary, focus movement, prefixes, suffixes and clear controls.

The root lang does not translate the browser's own UI, so plan for localized application messages if Arabic validation is required. R070, R071, R072 and R073 cover field direction, form copy, Arabic selects and autocomplete tokens.

Block launch when users cannot enter or correct required data, validation is unavailable in Arabic, or autofill and selection behavior corrupt task-critical values.

Pass 8: keyboard and assistive technology#

Run the critical journeys without a pointer. Tab through navigation and forms, use arrow keys inside composite widgets, submit invalid data, open and close overlays, and verify that focus remains visible and returns to the trigger.

Visual mirroring does not change DOM order, and the WCAG focus-order guidance asks for a sequence that preserves meaning and operation rather than a mechanical right-to-left trace.

Inspect the accessibility tree for names, roles and descriptions. A translated icon can still expose an English aria-label. Intentional foreign-language phrases may need their own lang attribute for appropriate language processing. R080 reports foreign-language runs without language markup.

Run a screen reader over the launch journeys in at least one supported environment, checking the page title, landmarks, control names, validation association, live status and dialog behavior. Automated rules can find missing semantics; they cannot decide whether the complete task order makes sense.

Block launch when a critical task cannot be completed by keyboard, required focus is invisible or lost, or controls expose missing or misleading accessible names.

Decide blockers with a written rule#

Set severity before the test pass so triage does not become a debate about each screenshot.

SeverityArabic launch exampleDecision
BlockerCritical journey cannot complete, locale is lost, value is corrupted, required control is unreachableStop launch
HighWrong currency or date meaning, critical error untranslated, serious keyboard barrierFix before launch unless release authority accepts documented risk
MediumNon-critical clipping, inconsistent icon direction, secondary state fallbackAssign owner and retest date
LowMinor spacing or visual inconsistency with no effect on meaning or operationMay ship with tracked follow-up

Context matters. An English trademark is not automatically a defect. A two-pixel offset is not equivalent to a reordered account number. Severity follows user impact and the locale contract.

Any accepted exception should record affected routes, environments, user impact, mitigation, owner and expiry condition. An exception without an expiry silently lowers the standard for future releases.

Keep the final launch record small and specific#

The release record should name:

  • build and environment tested;
  • Arabic locales and markets covered;
  • browsers, operating systems and viewport sizes;
  • critical journeys completed;
  • changed strings reviewed in context;
  • automated results and relevant screenshots;
  • known exceptions and owners;
  • the person who made the launch decision.

Automate stable invariants such as root attributes, locale persistence, critical translated labels, field direction, formatter options, focus sequence and absence of unexpected document overflow at selected widths. Keep human review for language quality, market fit, icon meaning and bidi readability.

Run a Ritla scan across the launch routes as part of the record: every check runs against each rendered page, and every finding names the element it came from. Use each one to reproduce the affected state and route it to the owning layer.

Run the RTL testing checklist for Arabic websites as the compact release sweep after the deeper journey work. It is a final net, not a substitute for forcing real payment errors, loaded data, form correction and keyboard operation.

After launch, turn any escaped defect into a fixture or invariant at the layer that owned it. The pre-launch plan improves when the same class of failure becomes easier to detect next time, not when the manual checklist merely becomes longer.

Checks in this guide

Show every check in this guideShow fewer

See what your Arabic pages are hiding

Paste a URL. Ritla renders the page on desktop and mobile, runs every check, and shows the top issues with screenshot evidence.