DEV Community

Kreetive Digital Marketing
Kreetive Digital Marketing

Posted on Fully Autonomous

How to Build a Fast Bilingual Website with RTL and LTR Support

Building a bilingual website is not the same as translating a few strings. The direction of the interface changes, typography behaves differently, components need to survive longer text, and search engines need a clear relationship between language versions.

This guide presents a practical architecture for websites that support both English and Arabic without duplicating the entire frontend.

1. Treat language and direction as document state

Set both lang and dir on the root element. Do not rely on CSS classes alone.

<html lang="ar" dir="rtl">
Enter fullscreen mode Exit fullscreen mode

For English:

<html lang="en" dir="ltr">
Enter fullscreen mode Exit fullscreen mode

This helps browsers, screen readers, form controls, punctuation, and bidirectional text behave correctly.

In a React application, derive both values from the active locale:

const direction = locale === "ar" ? "rtl" : "ltr";

return (
  <html lang={locale} dir={direction}>
    <body>{children}</body>
  </html>
);
Enter fullscreen mode Exit fullscreen mode

2. Use CSS logical properties

Directional declarations such as margin-left and padding-right create avoidable RTL bugs. Logical properties describe the purpose of the spacing instead of a physical side.

.card {
  padding-inline: 1.25rem;
  margin-block-end: 1rem;
  border-inline-start: 4px solid #ff6b00;
}

.icon {
  margin-inline-end: 0.5rem;
}
Enter fullscreen mode Exit fullscreen mode

The same component now adapts automatically when the document direction changes.

Use these replacements whenever possible:

  • margin-inline-start instead of margin-left
  • padding-inline-end instead of padding-right
  • inset-inline-start instead of left
  • border-start-start-radius for direction-aware corners

3. Do not mirror everything

Layout direction should change, but not every visual element should flip. Logos, photographs, media controls, phone numbers, code snippets, and many charts should preserve their original orientation.

For directional icons, flip only the icons that communicate movement:

[dir="rtl"] .directional-icon {
  transform: scaleX(-1);
}
Enter fullscreen mode Exit fullscreen mode

Avoid applying scaleX(-1) to a whole container. It may reverse images and text rendering in surprising ways.

4. Keep translation content separate from components

A component should receive content rather than contain language-specific copy.

const messages = {
  en: {
    heroTitle: "Build a website around real customer demand",
    cta: "Start a project",
  },
  ar: {
    heroTitle: "ابنِ موقعك بناءً على طلب العملاء الحقيقي",
    cta: "ابدأ مشروعك",
  },
};
Enter fullscreen mode Exit fullscreen mode

For production systems, validate message keys during the build so a missing translation cannot silently reach the interface.

5. Design for text expansion

Arabic and English strings rarely occupy identical widths. Navigation labels, buttons, cards, and validation messages should grow naturally.

Avoid fixed widths for text controls:

.button {
  min-inline-size: 9rem;
  inline-size: fit-content;
  max-inline-size: 100%;
  white-space: normal;
}
Enter fullscreen mode Exit fullscreen mode

Test components with deliberately long labels. A layout that survives difficult content is more reliable than one tested only with short placeholder text.

6. Choose and load fonts carefully

A font may look excellent in Latin characters but offer weak Arabic glyphs. Choose a family with deliberate Arabic support, or define a compatible pair.

:root {
  --font-latin: "Inter", system-ui, sans-serif;
  --font-arabic: "Noto Sans Arabic", system-ui, sans-serif;
}

html[lang="en"] body { font-family: var(--font-latin); }
html[lang="ar"] body { font-family: var(--font-arabic); }
Enter fullscreen mode Exit fullscreen mode

Subset font files, preload only the critical weight, and use font-display: swap. Loading five weights for two writing systems can quickly become one of the page's largest performance costs.

7. Give each language a stable URL

Use separate, indexable URLs such as:

/services/web-design/
/ar/services/web-design/
Enter fullscreen mode Exit fullscreen mode

or:

/en/services/web-design/
/ar/services/web-design/
Enter fullscreen mode Exit fullscreen mode

Do not change visible language only through JavaScript while keeping one URL. Separate URLs make sharing, analytics, caching, and search indexing more predictable.

Connect equivalent pages with hreflang:

<link rel="alternate" hreflang="en" href="https://example.com/en/service/" />
<link rel="alternate" hreflang="ar" href="https://example.com/ar/service/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/en/service/" />
Enter fullscreen mode Exit fullscreen mode

Each page should also use a self-referencing canonical URL. Do not canonicalize the Arabic version to the English version; they are alternate language pages, not duplicates.

8. Test mixed-direction content

Arabic interfaces often contain English product names, email addresses, URLs, and numbers. Wrap isolated fragments when the browser may infer the wrong direction.

<p>راسلنا على <bdi>hello@example.com</bdi></p>
Enter fullscreen mode Exit fullscreen mode

Test at least:

  • Arabic text containing an English brand name
  • phone numbers and prices
  • form validation messages
  • breadcrumbs and pagination
  • icons inside buttons
  • mobile navigation
  • copied URLs and email addresses

9. Make direction part of automated testing

A small end-to-end test can catch many regressions:

test("Arabic page uses RTL direction", async ({ page }) => {
  await page.goto("/ar/");
  await expect(page.locator("html")).toHaveAttribute("lang", "ar");
  await expect(page.locator("html")).toHaveAttribute("dir", "rtl");
});
Enter fullscreen mode Exit fullscreen mode

Add visual snapshots for a few shared components in both languages. The goal is not pixel-perfect mirroring; it is consistent hierarchy, readable text, and correct interaction order.

Final checklist

  • Set lang and dir at document level.
  • Prefer CSS logical properties.
  • Mirror only directional UI elements.
  • Keep translated content outside components.
  • Allow labels and controls to expand.
  • Load fonts with strong Arabic support efficiently.
  • Give every language version a stable URL.
  • Implement reciprocal hreflang links.
  • Test mixed-direction content and keyboard navigation.

A bilingual website becomes much easier to maintain when direction is treated as a core system property instead of a late visual patch.

Kreetive applies these principles when planning and building multilingual service websites as a Digital marketing company in Qatar.``

Top comments (0)