Laravel localization in Arabic العربية

Everything you need to ship Arabic in a Laravel app: the right locale codes, the exact plural forms trans_choice() expects, real localized Carbon output and Arabic-script considerations. Every value on this page was generated by running ICU, CLDR and Carbon — not copied from another article.

ISO 639-1

ar

Script / Direction

Arabic · RTL

Plural forms (Laravel)

6

Text vs English

Contracts

Locale codes

Set the base locale in config/app.php. For regional variants, Arabic commonly uses: ar_SA, ar_EG, ar_AE, ar_MA, ar_DZ

// config/app.php
'locale' => 'ar',
'fallback_locale' => 'en',

// Or switch at runtime
App::setLocale('ar');

Plural rules: what Arabic actually needs

CLDR defines 6 cardinal categories for Arabic. The sample numbers below were computed by ICU for this exact locale:

CLDR category Numbers that select it
zero 0
one 1
two 2
few 3–10, 103–110
many 11–99, 111–130
other 100–102, 200, 1000, 1000000, 1.5

Laravel's trans_choice() maps numbers to 6 pipe-separated forms for this locale:

Form index Numbers that select it
0 0
1 1
2 2
3 3–10, 103–110
4 11–99, 111–130
5 100–102, 200, 1000
// lang/ar/messages.php
'items' => ':count item|:count items'

// Usage
trans_choice('messages.items', $count, ['count' => $count]);

This language uses 6 plural forms. Laravel's built-in trans_choice only resolves two, so for grammatically correct output use an ICU MessageFormat package or handle the extra forms explicitly against the CLDR categories above.

Try any number live in the pluralization tester.

Localized dates with Carbon

Real output for Arabic (ar locale), generated by Carbon for March 21, 2026:

$date = now()->locale('ar');

$date->translatedFormat('l, j F Y');
// "السبت, 21 مارس 2026"

$date->isoFormat('LLLL');
// "السبت 21 مارس 2026 14:30"

$date->isoFormat('L');
// "21/3/2026"

$date->subDays(3)->diffForHumans();
// "منذ 3 أشهر"

What to watch out for in Arabic

Right-to-left is a layout problem, not a text problem

Arabic reads right to left, and the mistake teams make is treating that as something the font handles. Browsers do render the characters in the correct order automatically. What they do not do is mirror your interface: the sidebar stays on the left, the back arrow still points left, progress still flows left to right, and the whole product reads as though it were assembled backwards.

Setting direction at the document root is the first step and gets you most of the way.

Declaring direction

<html lang="ar" dir="rtl">

<!-- In Blade -->
<html lang="{{ app()->getLocale() }}"
      dir="{{ in_array(app()->getLocale(), ['ar', 'he', 'fa', 'ur']) ? 'rtl' : 'ltr' }}">

The second step is removing every physical direction from your CSS. Properties such as margin-left, padding-right, left and text-align: left are absolute, so they keep pointing the same way when the document flips. Logical properties follow the reading direction instead and need no per-locale overrides.

Physical (breaks in RTL) Logical (adapts) Tailwind
margin-left margin-inline-start ms-4
padding-right padding-inline-end pe-4
text-align: left text-align: start text-start
border-left border-inline-start border-s
left: 0 inset-inline-start: 0 start-0

Icons need mirroring too, but only those that carry direction. Back and forward arrows, undo and redo, indentation controls and progress indicators should flip. Icons representing real objects should not: a clock still runs clockwise, a play button still points right by universal convention, and a mirrored logo is simply wrong.

Test with real Arabic rather than with a reversed English string. Pseudo-localisation that reverses Latin characters exercises none of the shaping, bidirectional or numeral behaviour that actually breaks.

Bidirectional text and the numbers that jump around

Arabic text routinely contains left-to-right runs: numbers, Latin brand names, URLs, code identifiers, email addresses. The Unicode bidirectional algorithm decides how to lay these out, and it gets the common cases right and the boundary cases spectacularly wrong.

The classic failure is punctuation at the edge of a mixed run. A sentence ending in a Latin product name followed by a full stop can render with the stop on the wrong side, and a phone number adjacent to a parenthesis can appear to have swapped its brackets. Nothing is corrupt — the algorithm resolved the direction of a neutral character differently from how you intended.

Isolating an embedded LTR run

<!-- Let the browser scope the direction of untrusted
     or mixed content instead of guessing -->
<p>مرحبا <bdi>{{ $username }}</bdi> في التطبيق</p>

<!-- Or in CSS -->
.mixed { unicode-bidi: isolate; }

The <bdi> element exists precisely for this: it isolates a run whose direction you do not control, such as a user-supplied name, so it cannot reorder the text around it. Any interface that displays user input inside Arabic copy should use it.

Digits are a separate decision. Arabic-Indic numerals (٠١٢٣٤٥٦٧٨٩) are used in much of the Middle East, while Western digits are standard across North Africa and increasingly common everywhere in technical contexts. CLDR defaults to Western digits for ar and Arabic-Indic for some regional variants, so the numeral system your users see depends on the exact locale you pass.

Regardless of which digits are displayed, numbers themselves read left to right inside right-to-left text. A phone number, a price and a date all keep their internal order; only their position in the line flips.

Six plural forms, and why two is not close enough

Arabic has the most elaborate plural system CLDR describes: six categories, against two in English. A translation that supplies only a singular and a plural will produce grammatically wrong text across most of the number range, and it will do so silently.

Category Selected by Example
zero 0 لا كتب
one 1 كتاب واحد
two 2 كتابان
few 3–10, 103–110… 3 كتب
many 11–99, 111–199… 11 كتابًا
other 100–102, 200–202, fractions 100 كتاب

The two category is genuinely distinct — Arabic has a dual grammatical number, not just singular and plural — and the few and many categories key off the last two digits, so they recur cyclically rather than applying only to small numbers.

Laravel's trans_choice() selects among pipe-separated forms in CLDR order, so an Arabic string needs six segments. Getting the order or the count wrong shifts every form by one and produces text that is wrong for almost every input.

Six forms in one string

// lang/ar/messages.php — order matters:
// zero|one|two|few|many|other
'books' => 'لا كتب|كتاب واحد|كتابان|:count كتب|:count كتابًا|:count كتاب',

trans_choice('messages.books', $count, ['count' => $count]);

Verify the boundaries with the pluralization tester rather than assuming. The cases that catch people out are 0, 2, 11 and 100, none of which behave like their English equivalents.

Script shaping, fonts and the diacritics you will not see

Arabic letters change shape according to their position in a word — isolated, initial, medial or final — and connect to their neighbours. This is handled by the font's shaping tables, not by your code, but it has two practical consequences.

First, you cannot manipulate Arabic strings character by character. Truncating at a fixed character count can cut a word in a way that changes which glyphs render, and reversing or slicing a string will produce nonsense. Truncate on word boundaries, and let the browser handle overflow with CSS rather than PHP.

Second, font choice matters more than in Latin scripts. A font lacking proper Arabic shaping tables renders disconnected letters that a reader sees as broken rather than merely ugly. Test with the fonts you actually ship, and verify that your icon or fallback font does not silently win for Arabic ranges.

Arabic script also runs taller than Latin. Ascenders, descenders and diacritical marks need more vertical space, so line heights tuned for English will clip. Increase line height for Arabic rather than assuming a shared value works — a common symptom is marks above letters being cut off by an overflow rule.

Short vowels are normally unwritten in modern Arabic, which means the same written form can represent several words distinguished by context. This is a reason machine translation of short, contextless interface strings performs particularly poorly in Arabic, and a reason to give translators the screen context rather than a bare key.

Text length is unpredictable in both directions: Arabic often runs shorter than English because short vowels are omitted, while the script's greater height and different letterforms mean the visual footprint may still be larger. Do not assume the German rule of thumb applies.

Calendars, dates and regional variation

Arabic-speaking markets span more than twenty countries with genuinely divergent conventions, and the calendar is the most significant difference. The Hijri (Islamic lunar) calendar is used alongside the Gregorian one across the Gulf, and Saudi Arabia uses it officially.

A Hijri year is about eleven days shorter than a Gregorian one, so the two drift continuously against each other. Any feature involving dates for a Gulf audience — billing periods, deadlines, reporting — may need to display both, and cannot compute one from the other with a fixed offset.

Egypt (ar_EG) Saudi Arabia (ar_SA) Morocco (ar_MA)
Digits Arabic-Indic Arabic-Indic Western
Calendar Gregorian Hijri + Gregorian Gregorian
First day of week Saturday Sunday Monday
Currency ج.م ر.س د.م.

The first day of the week varies by country, which affects every calendar and date-picker component. Defaulting to Monday, or to Sunday, will be wrong for a large part of your Arabic-speaking audience unless the component reads it from the locale.

Modern Standard Arabic, often abbreviated MSA, is the written register everywhere and is what interface copy should use. Regional dialects differ enormously in speech but are rarely written in formal contexts, so one Arabic translation genuinely does serve all markets. The variation you must handle sits in formatting, numerals and calendars rather than in the copy itself, which makes Arabic cheaper to maintain than its reputation suggests once the layout work is done.

Set the full locale so these differences resolve correctly. Passing a bare ar applies one set of defaults to every market, and the numeral system in particular is visible on every screen.

What ships broken most often

Arabic is the most demanding locale most products will add, and it is worth sequencing deliberately: fix the CSS to use logical properties first, then add the translations. Doing it the other way round means reviewing Arabic copy inside a layout that is itself broken, and neither problem can be judged clearly.

Install the Laravel-Lang Arabic files for framework strings rather than translating them yourself. Validation messages alone involve the full six-form plural system across dozens of rules, and getting that right by hand is a substantial piece of linguistic work that has already been done and reviewed by native speakers.

Budget review time with an actual Arabic reader rather than relying on coverage metrics. Every failure mode listed above is invisible to a reviewer who does not read the script: a mirrored layout looks plausible, a wrong plural form looks like text, and scrambled bidirectional punctuation looks like a font issue. Coverage percentages will report a fully translated locale in all of these cases.

Framework strings already translated

Laravel's own validation, auth and pagination strings are maintained in Arabic by the open-source Laravel-Lang project (MIT). Install them, then manage your app's own strings live:

composer require laravel-lang/common --dev
php artisan lang:add ar
php artisan lang:update

Translate your app into Arabic today

Import your lang files, translate every key into Arabic with one AI click, and publish changes live — no deploy. Set up in 5 minutes.

We use cookies to improve your experience and analyze site traffic. Cookie Policy

Cookie Preferences

Essential

Required for the site to work

Analytics

Help us improve the site

Marketing

Personalized ads and content