Skip to content

Latest commit

 

History

History
92 lines (66 loc) · 4.75 KB

i18n.md

File metadata and controls

92 lines (66 loc) · 4.75 KB

openIMIS Frontent localization

There are 4 main dimensions to localization:

  • (1) screen labels, error messages (with variable parts),... must be displayed in user's language
  • data is language sensitive, along 2 dimnesions:
    • (2) the (coded) value itself can be language-sensitive (such as gender: male/female,...)
    • (3) the data format (date formats, numbers,...)
  • (4) generated documents (forms, reports,...) are language-sensitive... but must match the language of the person the document is dedicated to (which is not necessary the user's language!)

Dimensions (2) and (4) are managed from backend application and are out of scope for openIMIS frontend application (this repo).

Besides these 4 very generic dimensions and because of its modular architecture, openIMIS adds a 5th dimension: where is the translation defined. There are indeed module-specific terms (like "claim renewal") and others more generic (like "cancel"). Module-specific terms are provided by the module themselves. While some generic terms are provided at root level (in this repo). Finally translations can be added by dedicated modules (a.k.a. "language packs"), which can:

  • provide new languages or overwrite default (en) language
  • be limited to one module or cover the whole openIMIS assembly (release).

openIMIS Frontend localization is managed via react-intl library.

Data formats

Within react-intl, data formats (dates, amounts,...) are managed via 'locales', loaded at application startup. In openIMIS, each used user language is mapped to an intl locale based on the 'locales' entry in /openimis.json file.

Defaut mapping is:

{
    "locales": [{"intl": "en", "languages":["en"]}]
}

... indicating that 'en' language (the default one) is mapped to 'en' locale.

You can map several user languages to a same locale. Example:

{
    "locales": [
        {"intl": "en", "languages":["en"]},
        {"intl": "fr", "languages":["fr_BE", "fr_CH"]}
    ]
}

...would map both fr_BE and fr_CH to "fr" intl locale (along with "en" language to "en" locale). In other words data formats will be managed from "fr" locale for both users in fr_BE and fr_CH languages.

Translations

Translations are dedicated to provide the messages to display in screens: labels, error messages,...

These messages can contain 'variables'. Example:

Do you want to submit the 23 selected claims?

... where 23 depends on the actual number of selected claims.

As a consequence, formatting a message consist in merging a template message (identified by a key) to a (set of) values. Here again, the react-intl library (formatMessage function) is used.

All message templates are loaded at application startup into dictionaries (one by used language)... as the sum of modules 'translations' contributions, plus the 'root' (default) terms.

Example: if the openIMIS distribution contains the refrenece 'claim' and 'insuree' modules, there will be only one dictionary (en) with all 'terms' contained in:

  • openimis-fe-claim_js/translations/en.json (exported in openimis-fe-claim_js/src/index.js)
  • openimis-fe-insuree_js/translations/en.json (exported in openimis-fe-insuree_js/src/index.js)
  • ... and /translations/ref.json (in this repo)

Module translations contributions are loaded in the module order of /openimis.json file.

In other words, if the openimis-fe-insuree_js/translations/en.json config file contains a insuree.mainMenu, translated (by default) as 'Insurees'... but if

  • the /openimis.json config file contains a openimis-fe-insuree_NE_pack_js after openimis-fe-insuree_js entry
  • that openimis-fe-insuree_NE_pack_js module contributes to (en) dictionnary with the same insuree.mainMenu key (with 'Patients' as translation)

... then the screen will display 'Patients' (instead of 'Insurees') for the insuree main menu entry.

Language Packs

The reference modules only provide entries (keys) for the 'en' dictionary. Other languages can be added by dedicated module(s) contributing to other dictionaries.

Example a 'insuree-fr-pack' module can be added to provide 'fr' dictionary:

import messages_fr from "./translations/fr.json";

const InsureeFrPackModule = {
  "translations": [{key: 'fr', messages: messages_fr}],
}

Message key lookups

Modules look at keys in 3 steps:

  • first it search dictionary for overwrite.key entry
  • if the entry is not found, it will look at module.key entry
  • if the entry is not found, it will look at key entry (supposed to be provided by default/shared translations)

The first overwrite.* lookup allows language pack modules to replace any entry, even the one given by /translations/ref.json default (root) translations.