Blog

Arabic and English in one Flutter app

A bilingual Flutter app in the Gulf is not a second locale file. Flutter RTL Arabic is direction, plurals, fonts, mixed script, and the Xcode language list.

  • Flutter
  • Arabic
  • RTL
Two planes meeting at a point — Flutter RTL Arabic as two directions, not two files.

A Gulf product is already bilingual. The chrome is Arabic. The product name is often Latin. The numbers are Western. Flutter RTL Arabic is not “add a locale file.” Locale sets direction. Direction sets padding, alignment, and which edge a chevron lives on.

A bilingual Flutter app is a layout that can reverse. It is not a second strings file. Flutter already does the reverse. Official docs cover ARB setup. This note is the work that is still wrong after that file exists.

Flutter is the default for mobile at this studio. This is the Arabic and English depth of that default. When the product belongs on Apple, we write it in Swift. The same bilingual problem exists there. The widgets change. The discipline does not.

Direction is the product

Directionality is ambient. MaterialApp plus GlobalWidgetsLocalizations set it from the locale. Arabic becomes right-to-left. A Row’s children reverse. TextAlign.start follows the locale. TextAlign.left does not.

Override Directionality only for a nested island — a Latin brand lockup, a map chrome that must stay LTR. Do not use it as a way to avoid directional insets. If the whole screen is wrapped to stay left-to-right, you have not localised. You have hidden the problem.

Start and end, not left and right

EdgeInsetsDirectional is the rule. start and end resolve through Directionality. AlignmentDirectional, PositionedDirectional, BorderRadiusDirectional do the same job. EdgeInsets.only(left: 16) is how an Arabic screen starts to look rented.

Icons that mean back or next flip. Clocks, logos, and photographs do not. Apple’s Human Interface Guidelines are clear on this. Do not mirror a product photo of a device. Do not flip a recitation waveform.

Test with Directionality forced to RTL. Then test on a physical phone held in the right hand. The first catch is almost always a hardcoded left.

Arabic plurals are six forms

English has one and other. Arabic cardinals, in CLDR, are zero, one, two, few, many, and other. Zero is 0. One is 1. Two is 2. Few is 3–10 (n modulo 100). Many is 11–99 (n modulo 100). Other is 100, 200, most fractions. Arabic ordinals are other only.

If the UI shows a count — bookings, members, sessions, ayahs, offers — the ARB file has to write all six. other alone ships “11 عنصر.” Dual is not decoration. “2 عنصر” is wrong.

  • zero — n is 0. Write the zero form. Do not reuse the plural.
  • one — n is 1. The singular.
  • two — n is 2. Dual. Not the plural.
  • few — n modulo 100 is 3 to 10.
  • many — n modulo 100 is 11 to 99.
  • other — 100, 200, 0.5. The fallback, not the only line.

Flutter’s plural syntax is the ICU form. Only other is required by the tool. Required by the language is six. That is the gap.

Latin names, Western numerals

Gulf UI is mixed by default. Arabic chrome. Latin product names. Western digits. Naqrah, T-CODE, Aalim, CareerFolio stay Latin on this site and in the products. We do not Arabise a brand to look local.

Unicode’s Bidirectional Algorithm keeps the digits inside a number in reading order. 541 does not become 145. Do not reverse a price, a phone number, or an ayah number. Western numerals are what this studio ships. Apple notes that Western versus Eastern Arabic numerals vary by locale. We do not declare a national standard we cannot source.

An isolated Latin run inside an Arabic sentence — a brand, an SKU, a URL — may need an LRM or an isolate. Do not leave it to toString() and hope. Design the run. Then look at it on a phone.

A font that shapes Arabic

Arabic letters change form by position. A Latin-only family with an Arabic fallback is how a screen starts to look rented. This site uses Thmanyah for that reason. Inside an app the family is chosen for the product. We will not name a font for a named app.

The same point size as uppercase Latin will look small. Apple’s guidance is often about two points up. Line height and fallbacks belong in the design system, not as a pubspec afterthought. We will not publish a recommended-fonts list. That list already exists elsewhere, and it is not the work.

Two products, two jobs

Aalim is mobile. Arabic is the product: a Quran reader, authentic Uthmani script, tafsir, Hifz. It is not a translated English app. We do not claim a stack for it. We claim the job.

CareerFolio is web. Say web. Bilingual performance portfolios for Ministry of Education employees, with RTL and LTR switching. Proof that bilingual is a product decision on the desk as well as on the phone. A Quran companion, a course platform, and that portfolio are three learning jobs — their own note.

WOSTA is also web, Arabic-primary. The same rule applies. These are not “we added app_ar.arb.” They are what the product is. See the shipped work.

Xcode is the second checklist

Flutter’s ARB files are not the App Store language list. You add supported languages in Xcode — Runner, Info, Localizations — so the store entry can show Arabic. Flutter localizations do not do this for you. CFBundleLocalizations is the plist name of the same list.

App Store Connect metadata is a third list. Arabic is a supported metadata language. On the Saudi storefront, Apple’s table is English (U.K.) as the default, Arabic as additional. If you only ship English metadata, the Saudi storefront shows English. Binary languages and listing languages are not the same work.

  • Flutter project — locales, ARB, directional insets, six plurals, a font that shapes Arabic.
  • Xcode — Localizations so the binary declares Arabic.
  • App Store Connect — Arabic metadata and screenshots that match the binary.

Flutter can do this. Discipline is the work

The framework will reverse a Row. It will not stop you writing left: 16, skipping two and few, dropping a Latin brand into an Arabic sentence, or shipping without Arabic in Xcode. That is the honest line. Flutter can do RTL. The gap is discipline.

If you are building a bilingual Flutter app for Saudi or the Gulf, write to us with the languages the first user will actually see. Not the locale file. The screen.

Tell us what you’re building.

Write to us with the product you want built. You will get a considered reply from the people who would do the work.

Start a conversation