Customize translation in LMS and CMS

Hi How can I change the Persian translation of some words in LMS and CMS in the simplest way

Hi. Please specify your environment and tell us whether you’re using tutor, devstack or any other way of running the platform. Also please give more information about the translation issue. Is it from the MFE side or LMS / CMS?

I run the tutor on wsl with the Indigo theme and the problem I have, for example,I changed the language to persian but the dashboard page of the CMS is completely English, even in the courses I go to, it is 90% Persian, but some words are not translated. how should i do?

Hi! Did you check the documentation? Configuration and customisation — Tutor documentation

hi @regis For example, to translate the word “My Course” in this page , I created a file with the name and format “django.po” in this directory /env/build/openedx/locale/fa/LC_MESSAGES and I filled the django file with these commands

msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8"

msgid "My Course"
msgstr "دوره های من"

Then re-build the openedx Docker image with this command

tutor images build openedx
tutor local launch

But there was no change, am I missing something or am I doing something wrong?

The page you mentioned is in the front-end side (MFE)
You should check this doc instead.

Thank you @Anh_Vu_Nguy_n ٬, but I can’t find the ID of the part I want to translate in source , for example, the word “My Course” in the picture above

Have you tried changing language from It’s possible that your lang preference is still set to another language (English in this case I guess). For Persian you can try both fa and fa-ir but my suggestion would be fa-ir.

Hello @FatemeKhodayari ,I selected the persian language before launching the tutor and after that I changed account language to persian , but dashboard page still in English. Here, as you said, I went and type fa and fa_IR, but nothing happened and dashboard still english.

Based on my own experience, the new learner dashboard MFE is not currently supporting Persian (haven’t checked other languages yet). So the dashboard remains LTR and English even if you set your language to Persian. Check the learning MFE please. In Tutor v17 (Quince release), the learning MFE is displayed in RTL and supports Persian translations when your language is set to fa-ir.

You can find the key at i18n folder of MFE projects or transiflex.
But I think for Dashboard MFE fa or fa_ir is not there
If Dashboard MFE is enabled you can go to Account settings > Site language to set your language.
But the fact that Dashboard MFE is enabled by default but they’ve not implemented the language dropdown, making it really inconvenient.

I changed the language of the site, most of the words were translated except the learning-dashboard page and yes fa isnt there how can I add it or translate the words Manually

You can’t do anything about it unless you want to run a custom fork and refer to this PR to add an unsupported language.

As this is an issue I’m facing as well, I added translations for Persian here.

@Arthur378 not sure if you solved your issue or not, but in case you’re in a hurry, you can apply these changes to a fork of this MFE and use a custom MFE plugin to have the dashboard in RTL and with Persian support.

tnx @FatemeKhodayari how can I add it to my edx?
I forked the file and applied the changes, what should I do now?

These are the steps to having a customized MFE in Tutor v17

  1. Fork the repository of the MFE (frontend-app-learner-dashboard in this case)

  2. Apply your changes and push them to your fork

  3. Add a tutor plugin in .local/share/tutor-plugins/

from tutormfe.hooks import MFE_APPS

def _add_my_mfe(mfes):
    mfes["learner-dashboard"] = {
        "repository": "",
        "port": 1996,
        "version": "my-custom-branch-or-tag-or-commit", # optional, will default to the Open edX current tag.
    return mfes
  1. Enable the plugin by running tutor plugins enable dashboard

  2. Rebuild the mfe image by running tutor images build mfe

  3. Launch and check

1 Like

The default directory for tutor is .local/share/tutor as you have as well. To make tutor see your plugins, you should add them in the tutor-plugins directory on the same level with tutor root directory. So by default the tutor plugins directory will be .local/share/tutor-plugins/. As this directory isn’t created by default, you should add it yourself. For better understanding the tutor plugins structure and process read the docs please.

what is the problem?

root@HP-OMEN-17:~/.local/share/tutor-plugins# ls
root@HP-OMEN-17:~/.local/share/tutor-plugins# tutor plugins enable dashboard
⚠️  You are running Tutor as root. This is strongly not recommended. If you are doing this in order to access the Docker daemon, you should instead add your user to the 'docker' group. (see
Error applying action: func=<function discover_module.<locals>.load at 0x7f89e6205ea0> contexts=['plugins']'
Traceback (most recent call last):
  File "/usr/local/bin/tutor", line 8, in <module>
  File "/usr/local/lib/python3.10/dist-packages/tutor/commands/", line 27, in main
    cli()  # pylint: disable=no-value-for-parameter
  File "/usr/local/lib/python3.10/dist-packages/click/", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/click/", line 1078, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.10/dist-packages/click/", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.10/dist-packages/click/", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.10/dist-packages/click/", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.10/dist-packages/click/", line 783, in invoke
    return __callback(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/click/", line 33, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/tutor/commands/", line 142, in enable
  File "/usr/local/lib/python3.10/dist-packages/tutor/plugins/", line 111, in load
  File "/usr/local/lib/python3.10/dist-packages/tutor/core/hooks/", line 116, in do
    self.do_from_context(None, *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/tutor/core/hooks/", line 135, in do_from_context
  File "/usr/local/lib/python3.10/dist-packages/tutor/core/hooks/", line 36, in do
    self.func(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/tutor/plugins/", line 56, in load
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/root/.local/share/tutor-plugins/", line 1, in <module>
NameError: name 'MFE_APPS' is not defined
  1. You must have tutor-mfe installed
  2. You must have mfe plugin enabled and installed
  3. Do not run tutor as root as your log is also saying

I enabled mfe and dashboard, but it still gives this error when building:

Building image
docker buildx build --output=type=docker --cache-from=type=registry, /root/.local/share/tutor/env/plugins/mfe/build/mfe
[+] Building 5.3s (31/172)                                              docker:default
 => [internal] load .dockerignore                                                 0.0s
 => => transferring context: 2B                                                   0.0s
 => [internal] load build definition from Dockerfile                              0.0s
 => => transferring dockerfile: 25.69kB                                           0.0s
 => resolve image config for                        1.3s
 => CACHED docker-image://  0.0s
 => [internal] load metadata for     1.0s
 => [internal] load metadata for                    0.0s
 => importing cache manifest from  2.8s
 => git://       1.4s
 => git://   1.3s
 => git://      1.3s
 =>              2.7s
 => [base 1/4] FROM  0.0s
 => [internal] load build context                                                 0.0s
 => => transferring context: 151B                                                 0.0s
 => git://  1.4s
 => git://       1.4s
 => git://  1.2s
 => git://     1.3s
 => git://         1.4s
 => [production  1/12] FROM                         0.0s
 => git://   1.3s
 => CACHED [base 2/4] RUN apt update   && apt install -y git     gcc libgl1 libx  0.0s
 => CACHED [base 3/4] RUN mkdir -p /openedx/app /openedx/env                      0.0s
 => CACHED [base 4/4] WORKDIR /openedx/app                                        0.0s
 => [learner-dashboard-git 1/1] ADD --keep-git-dir=true  0.0s
 => [learner-dashboard-src 1/1] COPY --from=learner-dashboard-git /openedx/app /  0.0s
 => ERROR [learner-dashboard-common 1/5] COPY --from=learner-dashboard-src /pack  0.0s
 => ERROR [learner-dashboard-common 2/5] COPY --from=learner-dashboard-src /pack  0.0s
 => CACHED [i18n 1/3] COPY ./i18n /openedx/i18n                                   0.0s
 => CACHED [i18n 2/3] RUN chmod a+x /openedx/i18n/*.js                            0.0s
 => CACHED [i18n 3/3] RUN echo "copying i18n data"   && mkdir -p /openedx/i18n/a  0.0s
 => CANCELED [learner-dashboard-i18n 1/5] COPY --from=learner-dashboard-src / /o  0.0s
 > [learner-dashboard-common 1/5] COPY --from=learner-dashboard-src /package.json /openedx/app/package.json:
 > [learner-dashboard-common 2/5] COPY --from=learner-dashboard-src /package-lock.json /openedx/app/package-lock.json:
 393 |     FROM base AS learner-dashboard-common
 394 |     COPY --from=learner-dashboard-src /package.json /openedx/app/package.json
 395 | >>> COPY --from=learner-dashboard-src /package-lock.json /openedx/app/package-lock.json
 396 |     ARG NPM_REGISTRY=
 397 |
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref cf12243e-56e4-4327-abdd-d8ab1336d21f::1l8it7ucwmvnicrpaj2blw01d: "/package-lock.json": not found
Error: Command failed with status 1: docker buildx build --output=type=docker --cache-from=type=registry, /root/.local/share/tutor/env/plugins/mfe/build/mfe