Skip to content

Internationalisation (i18n)

What it is

ManpowerIQ is bilingual English / Arabic end-to-end: the backend localises error and validation messages via resx resources, the frontend localises UI strings via i18next with right-to-left (RTL) support, and user-facing domain data is stored in paired bilingual columns.

Why it's built this way

The platform targets ports and terminals in Arabic-speaking regions, so Arabic is a first-class language, not a bolt-on translation. Three separate concerns each needed a home: system messages (backend), UI chrome (frontend), and business data (the database). Storing names in dedicated *_1_English / *_2_Arabic columns — rather than a translation side-table — keeps the bilingual value attached to the row and queryable directly.

How it works

flowchart LR
    subgraph BE[Backend · .NET]
        RESX[ErrorMessages.resx<br/>ErrorMessages.ar.resx]
        LOC[IStringLocalizer]
        RL[RequestLocalization en/ar]
    end
    subgraph DATA[Database]
        COLS[Name_1_English / Name_2_Arabic<br/>Description_1_English / _2_Arabic]
    end
    subgraph FE[Frontend · React]
        I18N[i18next · locales/en.json]
        RTL[RTL layout · عربي toggle]
    end
    RL --> LOC --> RESX
    FE -->|Accept-Language| RL
    DATA -->|both names in payload| FE
  • Backend messages — resx resources ErrorMessages.resx (default/English) and ErrorMessages.ar.resx (Arabic) under Application/Resources/, resolved through IStringLocalizer. The API registers request localization for en / ar (sheet 01 edge-cases, Program.cs:468-474).
  • Bilingual data columns — user-facing names use Name_1_English / Name_2_Arabic (and Description_1_English / Description_2_Arabic) on entities throughout the model; even the permission seed includes Arabic names (sheet 01 §entities + edge-cases). The convention is universal — both lookups and tenant entities carry the paired columns (sheet 03 §entities).
  • Frontend — i18next with an en locale bundle, and an RTL layout toggled by a عربي control (verified during UI screenshot capture). The web app sends the language preference so backend messages come back localised.

The detailed key-naming convention for resx keys (<Entity>.{Referenced.*, Validation.*, IsSystem.*}) is covered in the conventions section — see Backend i18n keys.

Gotchas / constraints

  • Two name columns, not one. Reads and writes of a user-facing entity must carry both Name_1_English and Name_2_Arabic; don't collapse to a single name.
  • Soft-delete unique filters interact with bilingual codes — uniqueness is on code, not on the localized names.
  • RTL is a layout concern, handled in the frontend; the backend simply returns the Arabic strings. There is no separate Arabic build of the API.
  • Wiki Arabic content is a different track. The MkDocs site has an Arabic locale scaffolded (i18n plugin, ar stub) but the translated wiki pages are a later phase — distinct from the product's i18n described here.

Build status

Available — backend resx localization (en/ar) + IStringLocalizer + request localization; frontend i18next + RTL; bilingual data columns across the model. Verified LIVE (sheet 01 §build-status + edge-cases).

  • be-i18n-keys (conventions, Batch C) — the resx key-naming convention.
  • Architecture overview
  • Fact sheets: 01 (foundation), 03 (employee master — bilingual columns).