seifashraf.tech
01work02notes03blog04contact
CV
open to work
All writing

Published 9 October 2026· 3 min read

Arabic is a layout problem, not a translation problem

Six RTL sites later, here is the short list of what actually breaks when you add Arabic to a Next.js app, and the fixes that held up in production.

Written by Seif Ashrafnext.jsrtlarabici18nAlso available in ar

Every bilingual site I've shipped for Saudi and Egyptian clients went through the same arc. The translation arrives, you flip dir="rtl", and the page is suddenly wrong in twenty small ways. None of them are about words. They're about layout, fonts, numbers, and URLs.

This is the checklist I now run before a client sees the Arabic version. It comes from Aevenda, HotSpot, CPS, Athenas, Midex, and Edge, all Next.js App Router sites with a [locale] segment.

1. Stop using left and right in CSS

Physical properties (margin-left, padding-right, left: 0, text-align: left) don't flip. Logical ones do. In Tailwind that means:

PhysicalLogical
ml-4 / mr-4ms-4 / me-4
pl-4 / pr-4ps-4 / pe-4
left-0 / right-0start-0 / end-0
text-lefttext-start
rounded-l-lgrounded-s-lg

Grep for the physical ones before you ship:

grep -rnoE '\b(ml|mr|pl|pr|left|right)-[a-z0-9.\[\]/-]+|\btext-(left|right)\b' src

Anything left over should be inside an element you've deliberately kept left-to-right.

2. Some things must stay LTR

A diagram, a code block, a phone number, an email address, a URL. Wrap each one:

<span dir="ltr" className="inline-block">+20 100 700 4828</span>

The inline-block matters. Without it the bidi algorithm will still reorder punctuation around the number in some browsers.

3. The font you have doesn't have the glyphs

Geist, Inter, and Space Grotesk ship no Arabic. The browser falls back to whatever the OS has, which is usually fine on iOS and ugly on Windows. Pick an Arabic face on purpose and load it only on the Arabic routes:

// app/[locale]/layout.tsx
import { Cairo } from "next/font/google";
const arabic = Cairo({ variable: "--font-arabic", subsets: ["arabic", "latin"], weight: ["400", "500", "700"] });
 
<html lang={locale} dir="rtl" className={locale === "ar" ? `${arabic.variable} font-ar` : ""}>

Then swap the stack in CSS instead of touching every component:

html.font-ar {
  --font-display: var(--font-arabic), system-ui, sans-serif;
  --font-sans: var(--font-arabic), system-ui, sans-serif;
}
html.font-ar .display { letter-spacing: 0; line-height: 1.35; }

Two details people miss: Latin display faces use negative tracking, which makes Arabic unreadable, and Arabic needs more line height because of the marks above and below the baseline.

4. Numbers and dates

Intl will give you Arabic-Indic digits (٣ instead of 3) for ar-EG. Clients in Saudi Arabia and Egypt almost always prefer Western digits on the web. Force them with a locale extension:

new Intl.DateTimeFormat("ar-EG-u-nu-latn", { hour: "2-digit", minute: "2-digit" });

Use the same trick for Intl.NumberFormat and Intl.RelativeTimeFormat.

5. Mirror the icons that mean direction

Arrows that mean "next" or "open" should flip. Icons that depict a real object (a phone, a play button, a logo) should not. In Tailwind, rtl:rotate-180 on the arrow is enough.

6. URLs are part of the layout

Keep slugs translated and ASCII-safe. /ar/services/led-screens ranks, /ar/خدمات/شاشات-led is a support ticket waiting to happen in half the tools you'll integrate with. Put the Arabic keyword in the title and the H1, not in the path.

For SEO, every page needs hreflang links for all languages plus x-default, the same URLs in the sitemap, and og:locale set to ar_EG or ar_SA. Next's metadata API does this cleanly with alternates.languages.

7. Test on a real phone keyboard

The last bug is always in a form. A visitor types their name in Arabic, a pattern attribute written for Latin rejects it, and you never hear from them. Validate on the server with Zod, keep client-side constraints to required and type="email", and read the error messages aloud in Arabic once.

This is the layer I built into my own site, in four languages, with all of the above. The architecture diagram on the home page stays LTR on purpose, and the phone number is wrapped exactly as shown.

What I'd do again

Logical properties from day one. A dedicated Arabic font loaded per route. Western digits unless the client asks. And one native speaker reading the final copy before launch, because a layout can be perfect and the sentence still wrong.

Share Email

See it live

Aevendaaevenda.com

Event production company, Saudi Arabia

Building something like this?

I reply within 24 hours.

Tell me about your project

© 2026 Seif Ashraf · Cairo · +20 100 700 4828

GitHubLinkedInInstagramFacebookblog· no cookies
Let's talk