The two failure points that aren't about words
Word-for-word, most engines produce readable Arabic. Where they fall over is the machinery around the words: the direction the text flows, and the grammar of counting. strings.dev is built to get both right inside your native .xcloc and strings.xml files — while being honest about the one part that stays your job.
Right-to-left is a text-direction problem, not a translation one
Arabic reads right-to-left, but your strings are almost never purely Arabic. A single message can carry a format placeholder (%@, %lld, %1$@ on iOS; %s, %d, %1$s on Android), a URL, an @handle, a product name, or a Latin/numeric token. Those runs must stay left-to-right even while the sentence around them flows right-to-left. That's bidirectional (bidi) text, and it's exactly where naive output falls apart — a placeholder gets swallowed, a URL's slashes reorder, or %1$s comes back as s$1%.
What strings.dev preserves
strings.dev treats every placeholder, URL, email, @handle, and proper noun as an opaque LTR token. It:
- keeps the exact literal (
%1$@ stays %1$@, never reordered or re-indexed),
- places that token at the correct logical position for Arabic reading order,
- leaves your brand phrases intact via placeholder protection.
So the content reads correctly and the directional integrity of the tokens survives the trip. What strings.dev does not do is redraw your UI.
What you still own: layout mirroring
Mirroring is layout, not translation. Flipping the navigation, moving the back chevron, swapping leading/trailing constraints, right-aligning text, and mirroring directional icons are handled by the platform and your code — UIView semantic content on iOS, or android:supportsRtl="true" plus start/end (not left/right) attributes on Android. No translation service can do this for you, and any that claims to is overselling. strings.dev hands you correct Arabic strings; you flip the layout to RTL once, at the app level.
Arabic uses all six CLDR plural categories
This is the part that quietly wrecks otherwise-fine translations. English has two plural forms (one / other). Arabic uses all six CLDR categories — zero, one, two, few, many, other — and the counted noun physically changes form between them. A translation that only fills "1" and "many" is grammatically wrong for most numbers you'll ever display.
| CLDR category |
Applies to (integer counts) |
Noun form in Arabic |
zero |
0 |
plural (رسائل), negated |
one |
exactly 1 |
singular (رسالة) |
two |
exactly 2 |
dual (رسالتان) |
few |
n % 100 = 3–10 (3–10, 103–110…) |
broken plural (رسائل) |
many |
n % 100 = 11–99 (11–99, 111…) |
singular (رسالة) |
other |
everything else (100, 101, 1000, fractions) |
singular (رسالة) |
The counterintuitive bit: few takes the broken plural رسائل, but many and other snap back to the singular رسالة — that's the Arabic تمييز rule, where 11–99 governs a singular noun. And two uses a dedicated dual form رسالتان with dual adjective agreement. No amount of string interpolation over a two-form English source can reproduce that; you need six distinct strings authored by something that knows the grammar.
Before / after: one plural string, six forms
Your English source typically defines just two quantities:
<!-- English · values/strings.xml -->
<plurals name="new_messages">
<item quantity="one">You have %d new message</item>
<item quantity="other">You have %d new messages</item>
</plurals>
Correct Arabic expands that to all six categories, with %d kept as an LTR token inside the right-to-left text:
<!-- Arabic · values-ar/strings.xml · %d stays LTR -->
<plurals name="new_messages">
<item quantity="zero">ليس لديك رسائل جديدة</item>
<item quantity="one">لديك رسالة جديدة واحدة</item>
<item quantity="two">لديك رسالتان جديدتان</item>
<item quantity="few">لديك %d رسائل جديدة</item>
<item quantity="many">لديك %d رسالة جديدة</item>
<item quantity="other">لديك %d رسالة جديدة</item>
</plurals>
Compare the few and many items directly: same count-driven sentence, but the noun switches from رسائل (broken plural, for 3–10) to رسالة (singular, for 11–99), and even the dual رسالتان carries a matching dual adjective جديدتان. That switching is the entire point, and it's exactly what a "1 / many" template silently gets wrong. On iOS the same expansion lives inside your String Catalog's plural variations, keyed on the same six categories with %lld / %@ preserved.
Which Arabic code to use
For app UI, Modern Standard Arabic (ar) is the safe, region-neutral default and is understood everywhere Arabic is written. Regional variants exist (ar-SA, ar-EG, ar-AE) and strings.dev ships them as first-class locales — but the plural and RTL behavior above is identical across all of them. The difference is register and some vocabulary, not the six-category machinery. If you're unsure which BCP-47 code maps to which platform folder, the locale code reference lists ar and its variants for both .xcloc and values-* directories.
Why the effort pays off
Advisory, not a promise: Gulf-market storefronts (Saudi Arabia, the UAE) are consistently among the higher-ARPU App Store and Play regions, and a fully Arabic UI is table stakes there. That's a reason to do it well rather than half-render placeholders — but revenue depends on your app, not your locale list.
For the end-to-end mechanics of exporting, translating, and re-importing, see the mobile app localization guide, or upload a file directly on the platform.