What a bilingual product really is
Many teams picture a bilingual product as the English product with its words swapped. That version passes a demo and then breaks in real use: a name is rejected, a date reads wrongly, a heading is cut off, a sentence makes no sense. The words are only one of four layers, and each layer needs its own decision.
| Layer | What it covers | What goes wrong when it is ignored |
|---|---|---|
| Language | Wording, tone, grammar, plurals, how you address the reader | Sentences built from fragments read as broken Arabic |
| Direction | Layout order, alignment, icons, gestures, motion | A back arrow that points forward; a menu on the wrong side |
| Script | Letter joining, fonts, line height, marks above and below the line | Clipped text, broken letters, headings in a font with no Arabic glyphs |
| Locale | Names, addresses, dates, calendars, numbers, currency, sorting | A form that rejects a valid name; a total with the wrong separators |
Localization is the name for all four together, and right-to-left design covers direction and script. This guide sits above them. It follows a whole product from the first decision to the long run, and it leaves the hands-on detail to deeper pages: Arabic and RTL design for the design service, the article on designing bilingual RTL products for CSS, icons and type, the Arabic website development checklist for a website build, and multilingual CMS for content systems.
Cheap on day one, costly later
Language and direction are cheap to include at the start and expensive to add at the end. Retrofitting touches every screen: hard-coded strings, left and right values in the styles, fixed-width buttons, words baked into images, a data model with one name field. If an Arabic launch is even likely, plan for it in the first prototype. The same goes for a second or third language you have not chosen yet: build for more than one, and the next language costs far less than the first extra one did.
This guide is about products people use: websites, web apps and mobile apps. Rules about which language a contract, receipt or notice must be in depend on the country and the sector, so confirm them with qualified counsel. Nothing here is legal advice.
Decide the language strategy before you design
The first decision is not technical. Which language leads, and what does leading mean? The leading language is the one you design, write and test first, and the one whose needs win when two conflict. It should follow your audience, not the habits of the team.
Four strategies
| Strategy | How it works | Fits when | Main risk |
|---|---|---|---|
| English first, Arabic follows | Design and write in English, then adapt to Arabic | Most users read English at work, the team writes in English and speed matters | Arabic becomes an afterthought, with layouts tuned to English length and phrasing |
| Arabic first, English follows | Design and write in Arabic, then adapt to English | The main audience reads Arabic, as in many consumer and public services | English is rushed, or nobody on the team can review it |
| Parity | Both languages are designed and written together from the first prototype | Both audiences matter equally | More effort up front, and a native reviewer needed for each language |
| Separate regional versions | A shared core with different content or features per market | Offers, rules or payment methods differ between markets | The versions drift apart and cost double to maintain |
These choices are not exclusive. One product can lead in one language for customers and in another for staff. Imagine a clinic booking app: patients choose their language on first launch and get full parity, while the clinicians' tools lead in English because their records are written in English. The strategy follows the audience of each surface.
Who decides
The product owner decides, with three people at the table. One knows the audience data: which language people choose, search in and speak when they call support. One writes natively in each language. One is the engineer who will maintain the strings and layouts. Do not let the choice settle on whatever is easiest for the team to build.
Record the decision in a one-page language brief. It should hold the lead language, the supported languages, the variety of Arabic you write in, the tone for each language, who approves text and what happens when a translation is missing. For product text aimed at Gulf business readers, Modern Standard Arabic is the safe base. Use a dialect only for short, deliberate and tested microcopy.
Questions to settle first
- Which language do users pick when you let them choose? If you do not know, find out in research instead of guessing.
- Does a regulator, contract or partner require a language on some screens, such as terms or receipts?
- Which language will support staff use when they reply, and are they ready for both?
- Who writes the source text, and who reviews the other language as a native speaker?
- Will a third language follow? If so, build for any number of languages now.
Write each language for its readers, not word for word
Word-for-word translation is the most common reason an Arabic product feels foreign. Sentence order, the way the reader is addressed and the weight of a word all differ. A button that is short and friendly in English may have no Arabic equivalent of the same length and tone. The goal is the same meaning and the same result for the reader, said the way a native writer would say it.
A content workflow that holds up
- Write the language brief: audience, tone, variety of Arabic and a list of names that stay in Latin script.
- Build a glossary of product terms (feature names, plan names, roles) and agree one Arabic term for each, so one English word is not rendered three ways.
- Write the source text with the adapter in mind: short sentences, no idioms or puns, no jokes that live in one language only.
- Brief the native writer with context: a screenshot, where the text appears and any space limit.
- Review in the running product, not in a spreadsheet. Text reads differently on a button than in a cell.
- Mark each string as draft, in review or approved, so everyone knows what is final.
Machine translation can produce a first draft of low-risk text and save time, but a native reader must review it. Some text should always be written by a person: payment and security prompts, errors that ask the user to act, legal and health content, and anything where a wrong word costs money or trust.
Write strings that survive both languages
- Whole sentences. Never glue fragments together. Word order differs, so a message about the number of new messages is one string with a placeholder.
- Real plurals. English has two forms. Arabic has six categories: zero, one, two, few, many and other. Use plural rules from a message-format library or Intl.PluralRules, not an s added in code.
- Gender. Arabic verbs and adjectives agree with the person addressed. Prefer wording that avoids the problem, and ask for gender only when the product truly needs it.
- No words in images. If a graphic holds text, make one version per language and write alt text for each.
- Punctuation belongs to the language. Arabic has its own comma, semicolon and question mark. Do not hard-code English punctuation into the code.
Everything that carries language
The interface is only part of it. Emails, text messages, push notifications, PDFs and invoices, error pages, empty states, legal pages and support replies all speak a language. Two technical traps catch teams late. An Arabic text message is sent in an encoding that fits fewer characters, so it splits into more parts. And some PDF libraries join Arabic letters wrongly or print them reversed, so test the library with real Arabic text before you commit to it.
Editors who maintain content need a system that models languages properly: a field per language, a status per translation and a preview in both directions. See multilingual CMS and the article on a CMS for multilingual teams.
Layout and mirroring: what flips and what stays
In a right-to-left language the reading path reverses. The eye starts at the right and moves left, and the interface has to follow. The rule is simple to state: mirror what depends on reading direction or progress, and keep what has a fixed meaning of its own. The skill is applying it to your product once, writing the result down and not deciding again screen by screen.
| Element | In Arabic | Reason |
|---|---|---|
| Page layout, columns, navigation order, sidebars | Mirror | Reading starts at the right |
| Text alignment and list markers | Mirror (use start and end, not left and right) | Text begins at the start edge |
| Back, forward, next and previous arrows | Mirror | They point along the reading path |
| Progress bars, steppers, sliders, carousels | Mirror | Progress runs with the reading direction |
| Drawers, toasts, swipe gestures, slide-in animation | Mirror | They should match the layout |
| Numbers, maths, codes, web and email addresses | Keep left to right | They are always read left to right |
| Phone numbers and order references | Keep left to right, as one unit | A broken number is a wrong number |
| Logos, photographs, maps | Keep | They are not language content |
| Icons of real objects, checkmarks, plus and close signs | Keep | The object or meaning does not change |
| Media controls such as play and skip | Usually keep | Most players follow the convention for time, not for text |
| Charts and timelines | Decide once | Practice differs; see below |
Keep this list in your design system, with each icon marked as mirrored or fixed, so a developer never makes the call alone.
Numbers, phone numbers and other left-to-right islands
Digits run left to right even inside an Arabic sentence. So do phone numbers, email addresses, web addresses, order numbers and code. The usual bug comes from neutral characters such as the plus sign, hyphens, brackets and full stops: the browser places them by the text around them, so a number that starts with a plus can show it at the wrong end. Wrap each such value in an element with its direction set to left to right, or in a bdi element, and keep it on one line.
Mixed-direction text
Arabic sentences often contain English names, product codes and links. The classic fault is a full stop or bracket that jumps to the wrong side of a Latin word at the end of a sentence. Isolate inserted values, and give every field or container that shows user-written text automatic direction.
Imagine a list of order titles typed by customers: some Arabic, some English, some mixed. With automatic direction, each title aligns to its own start edge. Without it, an English title on an Arabic page hugs the wrong side and its punctuation scrambles.
Charts and data tables
There is no single industry rule for charts. A bar chart over time reads like a line of text, so many Arabic interfaces run time from right to left, put the value axis on the right and mirror the legend. A scatter plot, or any chart that follows a mathematical convention, can stay as it is. Numbers on the axes never flip.
Tables mirror as a whole: the first column moves to the right and number columns keep their digits aligned. Choose a rule per chart type, test it with readers of Arabic and apply it everywhere. The failure to avoid is two rules in one dashboard.
Mobile apps
Native and cross-platform toolkits ship with direction support, but only if you build with start and end instead of left and right. Flutter uses directional insets and alignment. React Native uses start and end styles and an RTL setting that may need an app restart to change. Android needs RTL support declared in the app manifest, and iOS uses leading and trailing constraints. The same decisions about icons and gestures apply, and our page on mobile app design covers phone screens.
Arabic typography and line height
Arabic is not Latin text running the other way. It is a connected script: letters change shape by position, join to their neighbours and carry marks above and below the line. Type settings tuned for English can break it in ways that look like bugs. Set these once, as tokens in the design system, for each script.
| Setting | What to do | Why |
|---|---|---|
| Letter spacing | Zero for Arabic, even if English headings use negative or positive spacing | Extra space pulls apart letters that should join |
| Line height | More generous than Latin; roughly 1.6 to 1.8 for body text is a common start, and large headings need extra room | Tall letters and marks above and below the line collide or clip when lines are tight |
| Size | Compare by eye; Arabic often needs a slightly larger setting than Latin at the same nominal size | Letter bodies look smaller relative to the font size |
| Emphasis | Use weight or colour; do not slant the text or use capitals | Arabic has no italic or capital forms, and a fake slant looks wrong |
| Underlines | Check where they cut through letter tails | Descenders collide with the line |
| Marks | Leave room above and below, and do not strip them from text that carries them | They are part of the word |
| Font pairing | Pick Arabic and Latin faces of matching weight and colour, and check that every weight you use exists in Arabic | A mismatch shows in mixed lines and buttons |
| Fallback fonts | Declare a stack that supports Arabic | Without one, each device picks a different face |
Fonts and loading
Load the Arabic font only on pages that need it, subset it by script where the licence and format allow, and set a font display strategy so text shows while the font loads. Check that the headline font has Arabic glyphs. If it does not, the browser falls back to another face with different metrics, and headings are where this shows first. Check, too, that the licence allows web and app embedding.
Clipping is the typical symptom of a line height set for Latin. It appears first in boxes with a fixed height and hidden overflow: truncated titles, cards and animated headlines. Give those boxes room for the tallest Arabic line, and never put a word that can wrap into a fixed-height window.
Build it so direction is a setting, not a rewrite
A sound bilingual product has one codebase and one set of components. The user's locale decides language and direction, and the components adapt. These practices make that true.
- Declare language and direction on the root element from the locale, so the page, the browser and assistive technology agree.
- Write styles in logical terms. Use margin-inline-start, padding-inline-end, inset-inline-start and text-align start instead of left and right. Flexbox and grid already follow direction, so do not reverse rows by hand. Flip only what is truly physical, such as transforms and gradients.
- Keep every string in a message file with a key, one file per language and no literal text in components. Make a missing key fail the build instead of appearing on screen.
- Format with the platform. Intl.NumberFormat, DateTimeFormat, PluralRules, ListFormat and Collator take the locale and do the hard work. Hand-written formatting breaks at the first edge case.
- Mark icons once. One flag per icon says whether it mirrors, and one rule applies it. Avoid per-screen overrides.
- Mirror horizontal motion. A panel should enter from the start edge in both languages. Drive it from one direction value rather than writing two animations.
- Model data for languages. Store names as entered, with an optional Latin spelling. Store content with a language field. Store money as an amount in minor units with a currency code, and dates in a universal form, then format at display time.
A route per locale with a dictionary per language is a common pattern in Next.js apps, and our Next.js development page describes how we build them. The choice of tools matters less than the habit: no screen is finished until it works in both directions.
Forms, names, addresses, dates, numbers and currency
Forms are where bilingual products fail quietly, because every field carries an assumption about the person filling it in. Check each field against what real users will type.
| Field | The usual assumption | What to do |
|---|---|---|
| Name | First name and last name, Latin letters only | Allow Arabic letters, spaces, hyphens, apostrophes and marks. Arabic names often have several parts and no fixed family name, so prefer one full-name field unless a system truly needs a split. Add an optional Latin spelling for documents, and never match people by the spelling of a name, because one name has several valid Latin spellings. |
| Phone | One local format | Use a country code picker, accept spaces and either set of digits, store the international form and display it left to right. |
| Latin characters | Display it left to right. Addresses with non-Latin characters exist, but mail systems support them unevenly, so do not promise them without testing. | |
| Address | Street, building number and postcode | Make the postcode optional or specific to each country. Allow area, landmark, P.O. box, building and unit descriptions, and a map pin. Follow each country's own addressing system instead of forcing one layout. |
| Date | Day, month and year in one calendar, with the week starting on Monday | Format by locale. Show the Gregorian calendar by default and offer Hijri where users expect it. Week start and weekend differ between countries and have changed in some, so confirm them for your markets and never hard-code them. |
| Number | Digits 0 to 9 and one set of separators | Pick a digit policy (below), accept both sets of digits on input and normalise on the server, since people type verification codes and IDs with whichever keyboard is active. |
| Currency | Symbol before the amount, two decimals | Format with Intl.NumberFormat and the currency code, because symbol position and spacing differ. Some Gulf currencies use three decimal places. Never add two currencies into one total. |
| Sorting and search | English alphabetical order | Use a locale-aware collator for sorting and normalise Arabic text for search (see the search section). |
Digits: pick a policy
Two sets of digits are in everyday use across the Arabic-speaking world: 0 to 9, and the Eastern forms that Unicode calls Arabic-Indic digits. Preference varies by country, product type and age, and the default digits of an Arabic locale can differ between browsers and versions.
Many business products show 0 to 9 in both languages so that numbers match across screens, exports and documents. Others use Eastern digits in Arabic. Neither is wrong, but mixing them on one screen is. Decide with your users, set the numbering system explicitly in your formatting code and apply it everywhere. Do not rely on names: the phrase Arabic numerals points to different sets in different places, so show a sample in the language brief instead of only naming one.
Search, hreflang and URLs for two languages
For search engines, and for people who share links, two languages should mean two sets of URLs, one language per page, each page linked to its twin.
- One URL per language per page. Put the language in the path (for example an /en/ and an /ar/ prefix), on a subdomain or on a country domain. A path prefix on one domain is the simplest to run for most teams. Do not switch language at the same URL by cookie or browser setting alone: crawlers, and people who share the link, see only one version.
- hreflang annotations. Each page names itself and every translation, using language codes such as en and ar, or a language with a region such as ar-AE when content differs by country. Every version must link back to the others, or the annotations may be ignored. Add x-default for the page shown to visitors who match no language, such as a language chooser. The tags can sit in the page head, in HTTP headers or in the XML sitemap.
- Canonical links that point to themselves. Each language version names itself as canonical. A canonical tag that points the Arabic page to the English one asks search engines to drop the Arabic page.
- Two attributes, two jobs. The lang attribute is for browsers, fonts and assistive technology. hreflang is for search engines.
- No silent redirects. Do not send visitors to a language by IP address or browser setting without a way to choose. Suggest a language in a banner and remember the choice. Automatic redirects can also hide a language from crawlers.
- A language switcher that goes to the same page. Link to the equivalent page in the other language, not to the home page. Write each language name in its own script, and use words, not flags. A flag stands for a country, not a language.
- A rule for slugs. Arabic words in a URL are valid, but they turn into long percent-encoded strings when copied into some apps. Many sites keep Latin slugs for both languages, and others translate them. Pick one rule. If a URL ever changes, redirect the old one.
- Native metadata. Titles, descriptions, headings and alt text are written in each language, using the words people search for. Arabic search has spelling variants: forms of alef, ya and alef maqsura, ta marbuta and ha, with or without marks. Keyword research in Arabic is its own task, not a translated English list.
- Structured data and social previews. Declare the page language in structured data, set Open Graph locale tags and make a share image for each language.
URL structure options
| Option | Example | Good for | Watch for |
|---|---|---|---|
| Path prefix | example.com/ar/page | Most products: one domain, one deployment, easy linking | Routing and sitemap logic must handle every page in each language |
| Subdomain | ar.example.com | Teams that deploy languages separately | More set-up, and more to measure and secure |
| Country domain | example.ae | A market with its own offer and local presence | A separate site to run for each domain, and registration rules that vary by country |
Search inside your product
Site search and filters need Arabic-aware matching, or users get empty results for words that are on the page. Normalise text in the index and in the query: remove marks and the stretching character, treat the alef forms as one, unify ya with alef maqsura and ta marbuta with ha where your content allows it, and treat both sets of digits as equal. Use a search engine with an Arabic analyser, or do the normalisation yourself, and test with real queries.
Accessibility in two languages
Accessibility standards apply in both languages, and a two-language product adds failures of its own. Meeting WCAG in English does not mean you meet it in Arabic.
- Declare the language of the page and of passages in another language. WCAG asks for both: the language of the page and the language of its parts. Screen readers use the language to choose a voice, so an English brand name inside an Arabic paragraph needs its own language mark or it is read with the wrong voice.
- Keep source order the same as reading order. Mirror with direction, not by reordering elements in CSS, so keyboard order, screen reader order and visual order agree in both languages.
- Translate every accessible name. Alt text, form labels, button labels, error messages, skip links and page titles. Write alt text in each language instead of converting it mechanically.
- Mirror keyboard behaviour. On a right-to-left page, the arrow keys in tabs, menus, sliders and carousels follow the visual direction, so the right arrow moves to the previous item.
- Check contrast and size in Arabic. Thin strokes and small marks blur at small sizes and low contrast. Test body text at the sizes you ship.
- Do not let direction carry the meaning alone. An arrow that means next needs a text label too, and the label and icon must still agree after mirroring.
- Caption and transcribe video in both languages, and check the direction of the subtitles.
- Test with a screen reader that has an Arabic voice installed, on the platforms your users have.
Automated checks find only part of the problems. A manual pass in each language, with the keyboard alone and with a screen reader, finds the rest.
Test both directions
Testing a bilingual product means every change is checked twice, in two directions and with two kinds of text. Plan the test matrix once and automate the cheap parts.
What to check
| Check | How |
|---|---|
| Layout at each breakpoint in both directions | Screenshots at phone, tablet and desktop widths, compared side by side |
| Overflow and clipping | Long Arabic and long English strings, marks above and below the line, headings in fixed-height boxes |
| Mixed-direction text | Strings with names, numbers, brackets and links, including ones that end in English |
| Forms | Arabic names, both sets of digits, long addresses, pasted text and every validation message |
| Numbers, dates and currency | Zero, one, large, negative and boundary values in each locale |
| Plurals | Counts that fall in each Arabic category: zero, one, two, few and many |
| Icons, gestures and motion | Every directional icon, swipe and animation mirrors; fixed ones stay |
| Fonts | Every weight renders Arabic glyphs and nothing falls back |
| Search engine signals | hreflang return links, canonicals, sitemap entries and switcher targets |
| Accessibility | Keyboard order, language marks and a screen reader pass in each language |
| Email, text messages and PDFs | Real clients and devices, with real Arabic text |
| Real devices | The phone's system language set to Arabic, because system settings change defaults |
Automate the cheap checks
Pseudo-localisation generates a fake locale that stretches text, adds accents and wraps strings in markers, so hard-coded text and tight layouts show up without a translator. A right-to-left pseudo-locale lets developers check mirroring before the Arabic text exists. Add a lint rule that flags left and right in styles, a build check that fails when a key exists in one language only, visual snapshots in both directions, and end-to-end tests that run once per locale.
Test with people
Automation finds breakage, not awkward wording. Ask native readers to review the running product for tone, terms and anything that feels translated. Run short usability sessions in each language, because users of one language do not always stumble where users of the other do.
Launch, and keep the two languages in step
Bilingual products usually drift. English gets the new feature, Arabic gets it some weeks later, and for a while the two versions say different things. The cause is almost always process, not skill, so fix it in the process.
Ship both together
- Make both languages part of the definition of done. A feature whose Arabic is not ready is not ready.
- Decide the fallback in advance. For interface text, never show a missing key. For editorial content, either hold the page back or show the other language with a clear label.
- Use a flag per language if you must release one earlier than the other, and tell users which parts are still arriving.
- Apply the same rule to release notes, emails, help articles and legal pages.
Make drift visible
- Give every string one source of truth and a status. When the English text changes, mark its Arabic version as needing review.
- Report pages and strings that exist in one language only, and fail the build where that would ship a gap.
- Measure by language: conversion, searches with no results, support questions and error rates. A drop on the Arabic path disappears inside a combined average.
- Name an owner for each language and keep a shared editorial calendar.
After launch
- Make it easy to report a wrong or awkward translation, in either language.
- Keep the glossary alive. When a feature is planned, agree its terms before the screens are built.
- Run the test matrix again when you change fonts, upgrade the framework or add a third-party widget such as chat, payments or maps. Ask each vendor whether the widget supports right-to-left and Arabic.
- When you add a third language, look for assumptions that two languages baked in, such as a toggle button where a menu is needed.
For the wider launch questions in the Gulf, such as payments, data and support, read the guide to launching software in the Gulf. We treat both languages as part of every project, and you see progress each week in weekly demos; the how we work page describes the rhythm.
Bilingual quality is not one big task. It is a set of small decisions made once and kept: a lead language, a glossary, an icon list, a digit policy, a URL rule and a test matrix. Write them down early and the product stays coherent as it grows.