How to add custom translations for Open edX® MFEs?
An Abstract Technology technical guide.
Guide i18n
XBlock and platform strings
The following guide applies to overriding translation and making translation for both, XBlocks and platform.
There are two main files to put the translations in, either django.po or djanogjs.po. To find out in which of the two files the original string is, you have to access the original files and check in which file the string you are looking to adapt already exists.
Tutor would compile the created files, once they are added to the correct location in the repository. See also the tutor i18 guide.
Let's make an example:
Imagine you want to adapt a German translation within the SCORM Xblock.
Note: The SCORM XBlock does not have translations in any of the two “.po”-files mentioned before.
Thus, to create the source strings you have to clone the repository, install the requirements and cd to it. Once there run:
django-admin makemessages -l de_DE
Note: The code for German language is de_DE. It's important to match the language code with what the platform is using by default.
If everything matches the default version, the previous command will create a django.po file.There is not yet a djangojs.po file, since there is no need for Xblocks to use javascript.
In the following a snapshot of the file content:
#: openedxscorm/scormxblock.py:90
msgid "Display name for this module"
msgstr ""
#: openedxscorm/scormxblock.py:95
msgid "Path to the index page in scorm file"
msgstr ""
#: openedxscorm/scormxblock.py:112
msgid "Weight"
msgstr ""
#: openedxscorm/scormxblock.py:113
msgid "Weight/Maximum grade"
msgstr ""
Then when translated it would look like the following:
#: scormxblock.py:89
msgid "Display Name"
msgstr "Name anzeigen"
#: scormxblock.py:90
msgid "Display name for this module"
msgstr "Anzeigename für dieses Modul"
#: scormxblock.py:95
msgid "Path to the index page in scorm file"
msgstr "Pfad zur Indexseite in der Scorm-Datei"
#: scormxblock.py:112
msgid "Weight"
msgstr "Gewicht"
#: scormxblock.py:113
msgid "Weight/Maximum grade"
msgstr "Gewicht/Höchstnote"
Now that we have customized the translation, we just need to put this in the right place. In case we do not already have a django.po file in the repository (e.g. community-theme-tutor/env/build/openedx/locale/de_DE/LC_MESSAGES/django.po), we create a new one. And in case a django.po file already exists, we just append the strings.
Important Note: You should always create a new django.po file before adapting the translations, in case such a file doesn’t yet exist. In order to do this, keep in mind that the new file should only include the minimum metadata as followed:
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8"
Thus taking our example above, if it's a new file the final result would be:
cat community-theme-tutor/env/build/openedx/locale/de_DE/LC_MESSAGES/django.po
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8"
#: scormxblock.py:89
msgid "Display Name"
msgstr "Name anzeigen"
#: scormxblock.py:90
msgid "Display name for this module"
msgstr "Anzeigename für dieses Modul"
#: scormxblock.py:95
msgid "Path to the index page in scorm file"
msgstr "Pfad zur Indexseite in der Scorm-Datei"
#: scormxblock.py:112
msgid "Weight"
msgstr "Gewicht"
#: scormxblock.py:113
msgid "Weight/Maximum grade"
msgstr "Gewicht/Höchstnote"
Lastly, you need to rebuild the openedx image, via tutor images build openedx. Once this command was sent you have to restart the image again by using:
tutor local start -d
Overriding MFE translations
The way translation is handled in the MFEs differ from how the platform handles translations (which is Python gettext based).The translation framework in MFEs is based on formatjs (https://formatjs.io/docs).
Instead of .po files the translations lie in .json files. Every language has its own file (per MFE), so to override a specific string in all MFEs, we would have to override it in all translation files in all MFEs This also sometimes applies to decency pkgs, like header, footer..etc.
However tutor does make the process, by injecting the overriding strings at build time in all MFEs. In the following you can see how it is implemented:
An example override strings for MFE
There can be up to 4 sources for a particular MFE to get its strings.
- MFE source code, this can be easily changed following tutor-mfe official tutor guide
Paragon
- Footer
- Header
Would it be possible to use tutor-mfe official guide to handle all the cases? It depends on the order the strings are imported
For example in learning MFE, the order of the strings are, paragon, appMessages, then footer/header
export default [
paragonMessages,
appMessages,
footerMessages,
headerMessages,
];
While for the account MFE the appMessages are loaded last:
export default [
headerMessages,
paragonMessages,
footerMessages,
appMessages,
];
So for the account MFE (1), using the current version master(9b45aa) we would be able to change any string using tutor-mfe tool, because the appMessages is loaded last, while for the learning MFE, we would be able only to change paragon messages, and for header/footer it wouldn't be possible to override their strings, unless we forked because our changes would be overridden by the original strings. Unless it's not translated at all.
Thus to be able to change the strings of header/footer, one way is to edit the i18n folder, which is in header i18n/messages and footer i18n/messages.