Docs
Configure O3
Configure translations

Configuring translations

O3 supports multiple types of translations, each serving different purposes. This guide explains how to configure translations for your implementation.

Types of Translations

There are several categories of translations in O3:

Code Translations

We use Transifex (opens in a new tab) to automatically extract hard-coded strings from the codebase (e.g., "Click Here"), translate them in the Transifex UI, and contribute those translations back to the O3 RefApp.

When to use: For translating the entire application into a new language or updating existing translations that will benefit the entire community.

How to contribute: Use Transifex (opens in a new tab) to add or update translations for the O3 RefApp. See the "Contributing Translations" section below for more details.

Note: Code translations are different from translation overrides. Code translations are contributed through Transifex and become part of the application for all users. Translation overrides (covered below) are configuration-specific and only apply to your implementation.

Terminology Translations

Clinical terminology (concepts) can have translations attached to them. For example, the CIEL concept 121375 for Asthma has multiple translations (view here (opens in a new tab)).

When to use: When you need translations for clinical concepts (diagnoses, medications, etc.).

How to add: Add translations as metadata on the concept in Open Concept Lab (OCL) or via the Initializer module.

Form Translations

If you have translations attached to concepts you're using in forms, those translations will automatically appear in your forms. Simply don't supply a label in the Form Builder, and the form will use the concept name instead.

Note: Because of differences in form engines, unlabeled questions may appear in the Form Builder, but they will work correctly in the Angular Form Engine.

New locales: If you add a brand-new locale not previously in O3, note that the form-entry-app expects translation files (e.g., ar.json) to exist. You may see issues with forms loading. See Issue O3-2492 (opens in a new tab) for a workaround.

Translation Overrides

You can use the configuration system to override translations for specific O3 components. This is useful for:

  • Changing button labels
  • Renaming links or menu items
  • Customizing text for your implementation

Important: Translation overrides should not be used to translate components into a new locale. For full translations, please contribute to the RefApp using Transifex (opens in a new tab).

Translation overrides are available at multiple configuration levels:

  • Module-level (applies to all uses of the module)
  • Extension slot-level (applies to extensions in a specific slot)
  • Extension-level (applies to a specific extension in a specific slot)

Module-Level Overrides

Override translations for an entire module:

{
  "@openmrs/esm-patient-chart-app": {
    "Translation overrides": {
      "en": {
        "startVisit": "Check-in",
        "endVisit": "Check-out"
      },
      "fr": {
        "startVisit": "Enregistrement",
        "endVisit": "Sortie"
      }
    }
  }
}

Extension Slot-Level Overrides

Override translations for all extensions in a specific slot. These overrides apply to all extensions in the slot, but extension-specific overrides (see below) take precedence.

Important: Extension slot configuration is specified under the module that owns the slot, not the extension's module.

{
  "@openmrs/esm-patient-chart-app": {
    "extensionSlots": {
      "action-menu-patient-chart-items-slot": {
        "configure": {
          "Translation overrides": {
            "en": {
              "addNote": "Add Clinical Note"
            }
          }
        }
      }
    }
  }
}

Extension-Level Overrides

Override translations for a specific extension in a specific slot. These overrides take precedence over slot-level and module-level overrides for that extension.

{
  "@openmrs/esm-patient-chart-app": {
    "extensionSlots": {
      "action-menu-patient-chart-items-slot": {
        "configure": {
          "my-extension-id": {
            "Translation overrides": {
              "en": {
                "customAction": "Custom Action Label"
              }
            }
          }
        }
      }
    }
  }
}

How Translation Overrides Work

  1. Merging and precedence: Translation overrides are merged in this order (later overrides take precedence):

    • Base translations (from Transifex)
    • Module-level overrides
    • Extension slot-level overrides
    • Extension-level overrides

    If the same translation key is overridden at multiple levels, the most specific override wins. For example, if "addNote" is overridden at both the slot level and extension level, the extension-level override will be used for that specific extension.

  2. Language codes: Language codes must follow the format: [a-z]{2,3}(-[A-Z]{2,3})?

    • Valid examples: en, fr, en-US, fr-CA, swa
    • Invalid examples: EN, en_us, english
  3. Translation keys: The translation key (e.g., startVisit) must match exactly what is in the module's translation file.

    • If you override a key that doesn't exist in the module's translation files, it will be ignored (no error, but no effect)
    • Translation keys are case-sensitive
    • See the "Finding Translation Keys" section below for help locating the correct keys
  4. Case sensitivity: The string "Translation overrides" must be written exactly as shown (capital T, lowercase r, etc.).

Finding Translation Keys

To find the correct translation keys to override:

  1. Inspect the code: Look in the module's repository for translation files (typically JSON files in src/translations/ or similar directories). The module name usually matches the package name (e.g., @openmrs/esm-patient-chart-app → look for files in that module's repo).

  2. Browser DevTools: Use the browser console to inspect i18n namespaces. First, identify the module namespace (usually the module name without the @openmrs/ prefix), then:

    // Get all translations for a module
    window.i18next.getResourceBundle('en', 'esm-patient-chart-app')
     
    // Or list all available namespaces
    window.i18next.store.data
  3. Module documentation: Some modules document their translation keys in their README or documentation files.

  4. Implementer Tools: If the module is loaded, you can see "Translation overrides" in the Implementer Tools configuration UI, which may help identify available keys.

Complete Example

Here's a complete example showing multiple override levels:

{
  "@openmrs/esm-patient-chart-app": {
    "Translation overrides": {
      "en": {
        "startVisit": "Check-in"
      }
    },
    "extensionSlots": {
      "action-menu-patient-chart-items-slot": {
        "configure": {
          "Translation overrides": {
            "en": {
              "addNote": "Add Clinical Note"
            }
          },
          "vitals-and-biometrics": {
            "Translation overrides": {
              "en": {
                "recordVitals": "Record Vital Signs"
              }
            }
          }
        }
      }
    }
  }
}

This configuration demonstrates:

  • Module-level: startVisit is overridden for the entire patient chart module (affects all uses of this translation key in the module)
  • Slot-level: addNote is overridden for all extensions in the action menu slot (unless overridden at extension level)
  • Extension-level: recordVitals is overridden specifically for the vitals-and-biometrics extension in the action menu slot (takes precedence over slot-level and module-level overrides for this extension)

Note: If addNote were also overridden at the extension level for vitals-and-biometrics, that extension-level override would take precedence over the slot-level override for that specific extension.

Troubleshooting

Translation override not working?

  • Verify the translation key exists in the module's translation files (non-existent keys are silently ignored)
  • Check that "Translation overrides" is spelled exactly as shown (case-sensitive)
  • Ensure the language code follows the correct format (e.g., en, not EN or en-US not en_us)
  • Verify the module is loaded (see the Overview guide for details on module loading)
  • For extension-level overrides, ensure you're configuring under the module that owns the slot, not the extension's module

Can't find translation keys?

  • Use browser DevTools to inspect loaded translations (see "Finding Translation Keys" above)
  • Check the module's GitHub repository for translation files
  • Some modules may use translation keys from other modules (check the module's dependencies)

Contributing Translations

If you want to contribute translations to the O3 RefApp (rather than just overriding them for your implementation), you can help the community by adding translations through Transifex.

Getting started:

  1. Visit om.rs/translate (opens in a new tab) for the complete translation guide
  2. Join the OpenMRS translation team on Transifex (opens in a new tab)
  3. Select your language and start translating strings

Community support:

Note: Contributing translations through Transifex helps the entire OpenMRS community. If you need translations for a new language or want to improve existing translations, please consider contributing rather than only using overrides for your implementation.

Related Documentation

  • The Configuration System - Learn about the configuration system, including how "Translation overrides" is a reserved key in every module's schema
  • Extension System - Learn about configuring extensions and extension slots