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. For English: 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 > ); 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 ; } 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 ); } 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 : " ابدأ مشروعك " , }, }; 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 ; } 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 ); } 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/ or: /en/services/web-design/ /ar/services/web-design/ 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 : 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.
راسلنا على hello@example.com
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 " ); }); 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 .``
