Arabic product QA for product and engineering teams

Learn how to assign Arabic QA ownership, prioritize product journeys, set release gates and prevent RTL, translation and formatting regressions.

Guide15 min read

Arabic product quality usually fails between teams. Translation says every assigned string is complete. Engineering says the locale builds. QA says the English journey passed. Product sees an Arabic account page with a reversed account number, an English payment error and a primary button clipped below the fold.

None of those teams necessarily made a false claim. They measured different things.

Arabic product QA is the operating model that joins those signals. It defines which Arabic journeys must work, who owns each failure class, what blocks a release, and which regressions are checked on every change. Without that model, the Arabic version becomes a periodic localization project. With it, Arabic is another supported product configuration with explicit risk and evidence.

Treat Arabic as a product surface#

A locale is not a layer of copy placed over a finished interface. It changes document direction, text shaping, component geometry, input behavior, number and date formatting, keyboard flow, routing and metadata. Those changes cut across the stack.

The team therefore needs an Arabic support contract. Keep it short enough to use, but specific enough to settle release decisions:

  • Supported locale and market combinations, such as ar-SA or ar-AE
  • URL and locale-switching behavior
  • Required digit system, calendar, currency and time zone
  • Supported browsers, operating systems and viewport range
  • Critical journeys and states
  • Content allowed to remain in another language
  • Required language-review stage
  • Named release owner and escalation path

Do not write "support Arabic" as if it were one binary requirement. A generic Arabic marketing site and a Saudi checkout with tax invoices have different format, content and legal needs. The contract tells engineering what to implement and QA what outcome to expect.

Keep the contract versioned near the product's other release criteria. If the team changes from generic Arabic to a market-specific locale, that is a product change. It can alter formats, content, fixtures and acceptance tests even if no component code changes.

Start with journeys, not a page inventory#

Testing every page once is a poor proxy for product risk. A user completes tasks, and defects often appear when state changes: after authentication, validation, an API error or a locale switch.

Choose Arabic journeys by impact and change frequency. A useful first set might include:

  • Enter through an Arabic deep link, sign in and return to the same destination
  • Search, filter and open a result containing mixed Arabic and Latin data
  • Add an item, change quantity, apply a promotion and complete checkout
  • Submit invalid identity, phone and address fields, then correct them
  • Open an order, copy its ID, download the receipt and contact support
  • Change language mid-task and verify the defined state-preservation behavior

For each journey, list the states that matter. Checkout is not one screen. It contains empty cart, populated cart, unavailable item, invalid promotion, loading, payment rejection, confirmation and receipt. Translation and layout gaps concentrate in the states that ordinary screenshots omit.

Tie fixtures to domain risk. An Arabic banking dashboard should include account numbers written in groups, an IBAN, an amount with decimals, a negative balance, long column headings, empty data, loading and a narrow viewport. A checkout should include a long address and an English product model. This makes failures reproducible instead of anecdotal.

Use a small risk table to decide depth:

Journey propertyHigher-risk signalTest response
Business impactPayment, identity, account recoveryFull manual and automated path
Direction complexityTables, mixed text, anchored controlsRTL component and browser tests
Content volatilityCMS, promotions, server errorsState and fallback coverage
Market sensitivityCurrency, dates, legal copyProduct and language approval
Interaction complexityDialogs, editors, drag or keyboard widgetsKeyboard and assistive-technology pass
Change frequencyFrequently edited shared componentRegression fixtures in both directions

The result is not permission to ignore low-risk pages. It decides where to spend deep manual effort and where stable automated checks provide enough confidence for a routine release.

Assign ownership by failure class#

"The Arabic team" is not an owner. Name a role and a response for each defect type.

Failure classPrimary ownerRequired reviewer
Missing or stale translationLocalization ownerArabic language reviewer
Root language or directionFrontend or platform engineeringQA
Bidi value corruptionFrontend engineeringQA with defined expected value
Overflow or clippingComponent ownerQA or design
Incorrect currency or calendarDomain engineeringProduct or market owner
Form direction and validationFeature engineeringQA and language reviewer
Focus or reading orderComponent ownerAccessibility reviewer
Canonical or language alternativesWeb platform or SEO ownerQA
Linguistic accuracy and toneArabic language reviewerProduct or content owner

The language reviewer should not be asked to repair code through translation. Shortening an accurate label until it fits a fixed-width button hides a component defect. Adding spaces around a phone number to influence its order hides a bidi boundary defect. Translators own language, not layout patches.

The reverse boundary matters too. A non-Arabic-speaking engineer can verify that a key resolved, a value stayed in the expected character order and a box did not overflow. The engineer cannot approve grammar, tone, terminology or whether a phrase suits the market. Record both forms of approval when both are required.

Give one person release authority for the Arabic surface. That person does not need to execute every test. They need the evidence, the support contract and authority to accept or reject a documented risk.

Define release blockers before finding them#

Severity debates become slow when the team invents policy for each bug. Set the blocker rules while the build is healthy.

An Arabic defect should normally block release when it:

  • prevents a critical journey from completing;
  • changes the meaning or order of an identifier, price, date or user-entered value;
  • makes a required control unreachable, clipped or overlapped;
  • exposes sensitive or legally required content in the wrong language or market format;
  • loses the Arabic locale during authentication, payment or another required transition;
  • produces an illogical keyboard path that blocks operation;
  • makes the Arabic route identify itself as another language or direction at the document root.

Not every visual asymmetry is a blocker. A non-critical icon offset may be scheduled if the action remains clear and usable. A deliberate English trademark is not untranslated content. Severity follows user impact and the support contract, not the amount of Arabic script on the screen.

Write acceptance evidence for each gate. "RTL looks good" is not evidence. Better examples are: the live root is lang="ar" dir="rtl"; the complete checkout passes at the minimum supported viewport; the account number displays as 0012-3456-7890 in the accounts table, not only in the DOM; phone and email fields are editable left to right; no critical route has document-level horizontal overflow; and an Arabic reviewer approved changed task copy in context.

Time-boxed exceptions need an owner, affected routes, mitigation and expiry condition. Without an expiry, the exception silently becomes the new quality bar.

Give engineering a testable direction contract#

The contract starts at the document root, and it belongs in a release gate rather than a code review comment. lang and dir solve different problems, and the HTML dir guidance notes that language does not imply direction, so the gate checks both on the live page after direct entry, hydration and a client-side locale switch:

ts
await expect(page.locator("html")).toHaveAttribute("lang", /^ar(-|$)/);
await expect(page.locator("html")).toHaveAttribute("dir", "rtl");

A stylesheet rule is not evidence: direction: rtl can make content render right to left while :dir(rtl), and every component style written against it, never matches. R001 reports a missing or left-to-right root direction on an Arabic page, and R002 reports a missing or contradictory language declaration.

Build components so the same fixture can render under both directions. Use dir at the story, test or application boundary instead of adding one-off RTL classes to each child. That makes inherited-direction bugs visible and keeps direction as input to the component system.

Direction-aware layout should use CSS logical properties when the relationship is logical:

Fragile

css
.order-card {
  padding-left: var(--space-4);
  border-left: 3px solid var(--status-color);
}

Better

css
.order-card {
  padding-inline-start: var(--space-4);
  border-inline-start: 3px solid var(--status-color);
}

In the fragile version, the status stripe stays on the left of every Arabic card, on the side where the card's text ends rather than where it starts. Physical CSS is still right when the requirement is physical, such as a diagram of a device's ports. Code review should ask what the relationship means before mechanically replacing every left and right.

R030, R031, R032 and R033 report direction-sensitive physical properties, floats, shadow or text-indent offsets, and horizontal transforms without suitable RTL handling. These checks are useful ownership signals because the fix usually belongs in a shared component or token, not in translated copy.

Put Arabic behavior into the design system#

Product teams lose leverage when every feature team solves RTL independently. The design system should encode the ordinary decisions so feature code only handles genuine exceptions.

Start with primitives that inherit direction and use logical tokens. Spacing tokens named inline-start and inline-end communicate intent better than left and right. Field, menu, toast and dialog components should accept long Arabic copy, expose translated accessible names and avoid fixed heights. Directional icons should be selected by meaning such as previous, next or reply, not by filenames such as arrow-left.

Publish each interactive component with fixtures for both directions and the states most likely to fail:

ComponentRequired Arabic fixtures
ButtonLong label, loading text, leading and trailing icon
Text fieldArabic text, phone, email, help and multiline error
SelectLong Arabic option, open menu, selected and invalid states
Data tableLong headings, mixed-direction cells, empty and overflow states
DialogLong title, destructive action, validation and narrow viewport
PaginationFirst, previous, next and last with keyboard focus

Document which icons mirror and which do not. Pagination and breadcrumb arrows follow the reading direction; an upload or download arrow points up or down and has nothing to mirror. R025 reports a directional icon that points against the way its control moves, such as a "next" arrow pointing back toward the start, and flags unmirrored icons named for a side as worth a look. Also avoid copy such as "click the arrow on the left" when the control moves in RTL; R082 reports interface text that refers to physical arrow directions.

Code review can then ask specific questions. Does a new physical property describe a physical requirement? Does the component work through inherited dir, or does it depend on a page-specific class? Does visual reordering preserve the DOM sequence? Are width and height constraints tested with Arabic content? Does a new string contain a complete message rather than fragments joined around variables?

Add a direction switch to the component workshop or preview environment. It shortens the feedback loop, but it must load real Arabic fixtures as well as flipping dir. Mirrored English reveals physical CSS. It does not reveal Arabic shaping, font fallback, translation length or mixed-direction data.

When a route-level bug traces back to a shared primitive, fix and test the primitive first. A local override may make the screenshot pass while leaving every other consumer exposed. The design system is where one Arabic QA finding becomes a product-wide prevention mechanism.

Make mixed-direction data a first-class fixture#

Arabic products inevitably render LTR data. Account numbers, IBANs, invoice numbers, emails and product names are not rare edge cases. Put them in shared fixtures and automated tests.

The browser lays mixed text out using the Unicode Bidirectional Algorithm. Letters, digits and punctuation have different directional behavior. An Arabic reader still expects an identifier to preserve the product's defined character order even when the sentence around it reads right to left.

Problem

html
<td>رقم الحساب 0012-3456-7890</td>

Measured in Chromium 151, the account number displays as 7890-3456-0012 in this cell: the digits after the Arabic label are treated as Arabic numbers, and the hyphens split them into three numbers laid out from right to left.

Better

html
<td>رقم الحساب <bdi>0012-3456-7890</bdi></td>

Fix it once, in the table cell component that renders identifiers, rather than in each feature's markup: a shared identifier cell that wraps its value in <bdi> covers every table in the product. Do not reverse the value in application code. Copy and paste and screen readers follow the source, so they would receive the reversed number. R021 reports unisolated phones, emails and Latin tokens inside Arabic text.

Place each identifier your product shows in a table cell, a toast and a sentence, follow it with punctuation, and repeat after API data loads, since the placeholder row may not reproduce the problem. Keep the isolation boundary tight: a dir="auto" element that also holds the Arabic label takes its direction from the label, so isolate the value, not the complete label-and-value component.

Test content pressure and font behavior#

Arabic layout defects are often data-dependent. A component can pass with one short translation and fail when a server error adds a second line or a web font changes metrics after load.

Create content-pressure fixtures for each shared component:

  • shortest and longest approved labels;
  • one-line and multiline errors;
  • empty, loading and success states;
  • mixed Arabic and Latin content;
  • large numbers and long unbroken tokens;
  • minimum and maximum supported viewport widths;
  • 200 percent zoom or increased text size;
  • font-loading and font-failure states.

In a design system, the font stack is a token like any other. If the brand face has no Arabic glyphs, every component hands its Arabic text to a fallback face with different widths and line heights, and a fixture can pass or fail depending on which fallback the test machine has. Inspect the rendered font in DevTools. R050 reports measured fallback or a stack that names no Arabic-capable family.

Keep Latin display treatments out of the tokens Arabic text uses. A tracked uppercase label style pulls connected letters apart and does nothing for a script without case. R051 and R055 report those patterns. R052, R053 and R054 surface cramped line height, undersized body text and italic or oblique Arabic styling for review.

Measure overflow rather than hiding it. Compare document scrollWidth with clientWidth, inspect the escaping element's bounding box, and open dynamic surfaces such as dialogs and toasts. Adding overflow-x: hidden to a shared layout component silences the symptom on every page at once and leaves the content that caused it unreachable. R040, R041, R042 and R043 report document overflow, overlap, clipped text and fixed-width containers exceeded by Arabic content.

Test formats and forms as domain behavior#

Product QA needs an expected result for dates, numbers and currency. The answer comes from the market contract, not from whichever locale default the test machine happens to provide.

Locale defaults are not that answer: current locale data gives ar-SA and ar-EG Arabic-Indic digits and ar and ar-AE Western digits, and it changes between versions. The way to keep every screen agreeing is one formatting helper that takes the market's decision as input:

js
// money.js: the only place prices are formatted
export const formatPrice = (amount, market) =>
  new Intl.NumberFormat(market.locale, {
    style: "currency",
    currency: market.currency,
    numberingSystem: market.numberingSystem,
  }).format(amount);

Test the helper against the market table with zero, decimals, thousands and negative values, then test that the UI, the email, the export and the receipt all call it. R060, R061, R062 and R063 report common date, digit, currency and percent or unit inconsistencies.

Forms require field-level direction, and design-system components are where a wrong decision spreads. A shared phone field built on a text input looks harmless:

html
<input type="text" inputmode="tel" autocomplete="tel">

On a right-to-left page it inherits right to left, and a typed +968 9123 4567 shows its groups in reverse order, as 4567 9123 968+. type="tel" is left to right by default and keeps them in order; a component that needs a text input for its formatting should set dir="ltr" on it. Test editing, not just appearance: type, paste, select, move the caret and delete around punctuation. R070 reports telephone, email and URL controls rendered RTL; R023 reports text inputs rendered LTR where Arabic input is expected.

Trigger every validation path. A component library that leans on the browser's native validation bubbles ships the browser's own messages, which the page's lang does not translate, so provide localized application messages when Arabic validation is required. R071, R072 and R073 cover untranslated form copy, LTR selects with Arabic options and missing autocomplete tokens on identity fields.

Include keyboard and assistive-technology evidence#

Mirroring can separate visual order from DOM order. The default tab sequence still follows the document structure, and assistive technology uses that structure to understand relationships. The WCAG focus-order guidance asks for an order that preserves meaning and operability, and in a product that is a property of each composite component, so test it in the component's fixtures as well as on pages.

Run the critical journey without a pointer. Tab through navigation and forms, use arrow keys in composite widgets, submit invalid data, open and close overlays, and verify that focus remains visible and returns to the trigger. Record where focus jumps across the visual layout.

Do not use positive tabindex as a quick repair. It creates a parallel order that becomes fragile when controls appear conditionally. Start with logical DOM order and let direction-aware layout position the controls. row-reverse and CSS order deserve attention when the screen looks right but focus feels wrong. R081 reports flex reversal used to imitate RTL.

Inspect accessible names and language changes. A translated icon button can still expose an English aria-label. An English product title inside Arabic content may need lang="en" for correct language processing. R012 reports untranslated attribute text, and R080 reports intentional foreign-language runs without a language attribute.

Automated accessibility tests identify missing semantics. A screen-reader pass in a supported environment is still needed for page title, landmarks, control names, error association, live status and the logic of the complete task.

Layer automation around likely regressions#

One large Arabic end-to-end test is slow to diagnose and easy to distrust. Use layers with clear failure messages.

Component layer#

Render shared components under dir="ltr" and dir="rtl" with content-pressure fixtures. Assert logical styles and accessible names. Capture reviewed screenshots for high-risk states at more than one width.

Integration layer#

Test locale routing, catalog fallback, plural selection, date and number configuration, form validation, API errors and locale persistence through authentication. These tests should identify the string key, formatter or state that failed.

Browser journey layer#

Automate the smallest set of critical journeys that cross real boundaries. Assert the live root language and direction, translated actions, lack of document overflow at target widths, field direction and predictable focus progression. Preserve screenshots and DOM details when a test fails.

Manual review layer#

Reserve human review for language quality, market fit, icon meaning, bidi readability and whether the task feels coherent. Manual review is not a substitute for deterministic checks, and automation is not a substitute for language judgment.

Ritla belongs next to the browser journey layer: it runs every check against rendered pages, so a regression in a shared component shows up on each scanned page that uses it. Use a finding to reproduce the product state and route it to the owning team. The RTL testing checklist for Arabic websites is the short version to run on release day.

Make bug reports route themselves#

An Arabic QA report should contain enough evidence for the owner to reproduce it without guessing:

  • route, locale, build and account state;
  • browser, operating system and viewport;
  • exact action that exposed the issue;
  • authored value and observed display for bidi defects;
  • expected market rule for formats;
  • translation key or content source when known;
  • screenshot plus a DOM or computed-style detail when relevant;
  • whether the problem blocks a critical journey;
  • likely failure class and owner.

Avoid titles such as "RTL broken." Prefer "Accounts table: account number 0012-3456-7890 displays as 7890-3456-0012 after the Arabic label" or "Payment error overlaps retry button at 320px after server rejection." The title already points toward the owning layer and test fixture.

Triage clusters, not only tickets. Several spacing bugs may come from one physical design token. English labels in unrelated dialogs may share one fallback path. Fixing the source and adding one focused regression test is more valuable than applying route-level patches.

Use a release record that can improve#

For each release, keep a small record of the Arabic evidence: journeys run, automated results, changed strings reviewed, supported environments covered, accepted exceptions and the person who made the release decision.

After a defect escapes, change the system that allowed it. Add the missing state to a fixture, the route transition to a journey, the format rule to the locale contract or the component to RTL visual coverage. Do not respond only with a longer manual checklist.

The useful measure is not how many bugs the team logged. It is whether known failure classes become cheaper to detect and harder to repeat. Arabic product QA is working when ownership is obvious, the expected behavior is written down, and ordinary product development exercises the Arabic surface before release day.

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.