ZuloOne
English
Sign in
Menu

🔤 Arabic localization

Updated

Every number here is measured against the tree.

← Developer wiki

Where things live#

Localization consists of two independent halves. Confusing them names both the wrong file and the wrong number.

Half Where What it is
The interface frontend/src/i18n/locales/{en,ru,uk,ar}.ts the captions of buttons, columns, dialogs
Business captions the caption of workspace objects, inline the names of dictionaries, documents, fields

frontend/src/i18n/messages.ts is not a dictionary: 44 lines of a loader registry, with zero keys in it. Look for a translation in locales/.

Coverage#

en, ru and uk are complete; ar is 41 keys short. There is deliberately no absolute key count here — it changes with every commit to the front end and goes stale silently. Count the gap, not the total: a new UI key must land in all four locale files at once or ar falls behind.

Which means what you look at is the GAP, not the total. To recount:

for l in en ru uk ar; do
  printf "%s %s\n" "$l" "$(grep -cE "^\s*'[^']+':" frontend/src/i18n/locales/$l.ts)"
done

There are 41 untranslated keys, and they are clustered rather than spread out:

Group Keys What it is
logs.* 34 the system log screen
grid.* 2 "Open data", "Open event handler…"
menu.* 2 the model menu and its hint
obj.* 2 copying an object's code
nav.logs 1 a navigation item

So what is untranslated is essentially one screen — the log, an administrator's tool. There is not a single business caption among the gaps.

Business captions: Arabic is there on 277 of the 328 objects that carry a caption. The rest are service and test models.

RTL#

The writing direction is a property of the language, not a separate "Arabic mode": I18nContext holds dir: 'ltr' | 'rtl' and sets rtl for the languages in RTL_LANGS.

RTL is worth checking on mixed content — Arabic text with Latin identifiers and digits inside it (an invoice number, a VAT number, an item code). That is where it breaks most often, and in our data almost every record looks like that.

Compliance and country models#

Do not assume "Arabic locale" implies "no ZATCA code". Saudi compliance lives in LocalizationSaudiArabia, not in the ar.ts file:

  • ZATCA / Fatoora — onboarding web services, outbound channels, feedback job, QR, CSR and signing profile. Implementation — ZATCA / Fatoora; open defects are listed there.
  • VAT at 15% — shared tax contour (Tax), not a hardcoded rate in the locale files.

Not part of Arabic UI work today:

  • Hijri calendar — dates stay Gregorian. Empty date fields show a Gregorian format mask from DATE_INPUT in frontend/src/i18n/DatesLocaleProvider.tsx (Arabic DD/MM/YYYY). Do not hardcode valueFormat or placeholder on a Mantine date control unless the field is display-only (LL).
  • Zakat — no dedicated calculation module.
  • Localized exception text — user-facing errors are still English; in RTL that mismatch is especially visible.

How to finish the translation#

  1. Grep the file first. The same notions are almost certainly translated already, and a divergence in wording is more noticeable to the reader than a missing translation. Latin script inside a translated string is almost always a miss.
  2. An interface key goes into locales/ar.ts, next to its neighbours in the group.
  3. An object's caption goes inline into its caption: { "en": "Customer", "ar": "عميل", "ru": "Клиент" }. English is the base and the fallback; a language key removed from the file is deleted.
  4. A language that is not registered on the stand is ignored on import — a model does not create languages for a tenant. Registering it later (the Languages page, POST /api/metadata/languages) brings its captions from the installed model tree right away — without it a tenant shows English metadata under an Arabic interface.

What this page does not replace#

A review by a tax consultant. The machine translation ran over the whole tree, and Arabic grammar catches its mistakes better than any diff: in an iḍāfa the first noun takes no article, so two words in a row carrying ال — or "article + bare" — is almost always an inverted word order.

What is left of the machine pass and has not been verified by a human: ar_final_untranslated.json — 53 strings.

Where next#

Was this page helpful?