Skip to content
I18n for DHIS 2
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Provides internationization support for d2 frontend Apps.


yarn add @dhis2/d2-i18n @dhis2/d2-i18n-generate @dhis2/d2-i18n-extract husky@next


Under scripts section, add commands extract-pot and localize

"extract-pot": "d2-i18n-extract -p src/ -o i18n/",
"localize": "yarn extract-pot && d2-i18n-generate -n NAMESPACE -p ./i18n/ -o ./src/locales/",

Prepend localize command to prestart and build steps

"prestart": "yarn localize && d2-manifest package.json ./public/manifest.webapp",
"build": "yarn localize && node scripts/build.js",

Commit Hooks

Add the "husky" section adjacent to the "scripts" section.

"husky": {
      "hooks": {
            "pre-commit": "yarn extract-pot && CI=true yarn test && git add ./i18n/"

In App Code

On dev/build phase src/locales directory would be created. It will contain necessary setup for internationalization, date/time, calendar etc. It is auto-generated, so please don't update it, any changes to it will be lost.

At the top of src/index.js (assuming it's the main entry point to your App). Add the following,

import './locales'

Changing User Locale

Create a function changeLocale and isLangRTL as below. You should call this function in App loading phase.

function isLangRTL(code) {
      const langs = ['ar', 'fa', 'ur']
      const prefixed = => `${c}-`)
      return langs.includes(code) || prefixed.filter(c => code.startsWith(c)).length > 0

function changeLocale(locale) {
      document.documentElement.setAttribute('dir', isLangRTL(locale) ? 'rtl' : 'ltr')


Pass strings to be translated into i18n.t function as below.

import i18n from '@dhis2/d2-i18n'
i18n.t('translation string')


Pass context property on second arg. to i18n.t

i18n.t('hello world', { context: 'a customary string to welcome a new born developer'})

extract-pot will automatically generate msgctxt field before msgid in the en.pot file, giving translators a better context for translations.

msgctxt "a customary string to welcome a new born developer"
msgid "hello world"
msgstr ""


Append directory src/locales at the end. Because on dev/build phase src/locales is auto-generated.



yarn upgrade --scope @dhis2


In .travis.yml before build/deploy step add yarn localize


  • We don't use react-i18next because handling cursor in text editor when ASCII and RTL characters are mixed is impossible to edit. Some ASCII characters move the cursor to one end of the line while RTL characters take cursor to the opposite end. Using variables in RTL language strings do not work because the first {{ might be entered correctly when translating but when we go to type the ending sequence }} the cursor ends up in the wrong place making it impossible to translate.
You can’t perform that action at this time.