Customizing and Overriding Translations
This tutorial covers two advanced translation scenarios:
Overriding Theme Translations (e.g. Indigo)
Atlas-managed translations do not automatically include custom theme-level overrides. If you need to override strings coming specifically from a Tutor theme (for example, the Indigo theme), you must provide additional locale paths and patch the Open edX image.
A possible approach is:
Create a
django.pofile inside the theme repository:tutor-plugins/tutor-indigo/tutorindigo/locale/<lang>/LC_Messages/django.poExample:
msgid "" msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Discover courses" msgstr "Kurse suchen"
The header with charset specification is required. Without it,
msgfmtcompilation will fail for non-ASCII characters.Compile the file using gettext:
msgfmt django.po -o django.mo
Patch the Open edX Dockerfile (using a Tutor plugin) to copy the locale folder into the image:
hooks.Filters.ENV_PATCHES.add_item(( "openedx-dockerfile-pre-assets", """ COPY --chown=app:app ./locale /openedx/extra_locale """ ))
Register the additional locale path in both LMS and CMS:
hooks.Filters.ENV_PATCHES.add_item(( "lms-env", """ LOCALE_PATHS: ["/openedx/extra_locale"] """ )) hooks.Filters.ENV_PATCHES.add_item(( "cms-env", """ LOCALE_PATHS: ["/openedx/extra_locale"] """ ))
Rebuild and restart:
tutor images build openedx tutor local reboot
This ensures Django loads your theme-specific overrides alongside Atlas-pulled translations.
Handling Translations in Custom or Forked Repositories
If your deployment includes forked repositories, custom plugins, or additional MFEs alongside
upstream Open edX components, fork openedx-translations and populate its translations/
directory with your custom files.
The exact location depends on the repository type:
Custom MFEs (new, not in upstream)
For a brand-new MFE such as frontend-app-custom, create one JSON file per language:
translations/
└── frontend-app-custom/
└── src/i18n/messages/
├── ar.json
├── fr.json
└── ...
Each file is a flat key/value JSON object where values are the translated strings (empty string if not yet translated).
Forked core MFEs (e.g. frontend-app-authoring, frontend-app-learning)
Add or replace translation files at the same path used upstream:
translations/
└── frontend-app-authoring/
└── src/i18n/messages/
├── ar.json
└── ...
Keys that already exist in the upstream file will be overridden; new keys will be added.
Custom plugins (Python / Django)
Use the standard locale directory layout:
translations/
└── openedx-custom-plugin/
└── conf/locale/
├── ar/LC_MESSAGES/django.po
└── fr/LC_MESSAGES/django.po
Theme repositories (e.g. a custom Indigo fork)
Theme translations do not have their own folder. Merge them into edx-platform instead,
because Open edX loads theme strings from the platform’s own locale directory at runtime:
translations/
└── edx-platform/
└── conf/locale/
├── ar/LC_MESSAGES/django.po
└── fr/LC_MESSAGES/django.po
Note
You can write scripts to automate the steps of extracting strings from your repositories,
isolating the ones that are unique to your fork, and merging them into the translations/
directory. What matters is that the final output follows the layout described above.
Once your translations/ directory is ready, point Tutor at your fork:
tutor config save \
--set ATLAS_REPOSITORY=your-org/openedx-translations \
--set ATLAS_REVISION=your-branch
Then rebuild and restart:
tutor images build openedx mfe
tutor local reboot