From 33ab52bfebae0314bd052839990f09907fd0932a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Behmo?= Date: Thu, 16 Apr 2020 19:26:49 +0200 Subject: [PATCH] Make it easy to add custom translation strings to edx-platform Users can now add custom translation strings to a locale folder at build time, very much in the same way as custom themes or requirements. This is quite convenient, although is does require quite a bit of time to rebuild the docker images. --- CHANGELOG.md | 1 + docs/configuration.rst | 47 +++++++++++++++++++ .../openedx/settings/partials/common_all.py | 3 +- tutor/templates/build/openedx/Dockerfile | 10 +++- .../build/openedx/locale/customlocales.md | 13 +++++ .../build/openedx/settings/cms/assets.py | 3 +- .../build/openedx/settings/lms/assets.py | 3 +- .../build/openedx/settings/partials/i18n.py | 3 +- 8 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 tutor/templates/build/openedx/locale/customlocales.md diff --git a/CHANGELOG.md b/CHANGELOG.md index b693fa4..3d25c02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Note: Breaking changes between versions are indicated by "💥". ## Unreleased +- [Feature] Make it easy to add custom translation strings to the openedx Docker image - [Improvement] Make it possible to rely on a different npm registry for faster image building ## v3.11.11 (2020-04-15) diff --git a/docs/configuration.rst b/docs/configuration.rst index d6ecb84..9e3ddd0 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -267,6 +267,53 @@ You may want to run your own flavor of edx-platform instead of the `official ver Note that your release must be a fork of Ironwood in order to work. Otherwise, you may have important compatibility issues with other services. In particular, **don't try to run Tutor with older versions of Open edX**. +Adding custom translations +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are not running Open edX in English, chances are that some strings will not be properly translated. In most cases, this is because not enough contributors have helped translate Open edX in your language. It happens! With Tutor, available translated languages include those that come bundled with `edx-platform `__ as well as those from `openedx-i18n `__. + +Tutor offers a relatively simple mechanism to add custom translations to the openedx Docker image. You should create a folder that corresponds to your language code in the "build/openedx/locale" folder of the Tutor environment. This folder should contain a "LC_MESSAGES" folder. For instance:: + + mkdir -p "$(tutor config printroot)/env/build/openedx/locale/fr/LC_MESSAGES" + +The language code should be similar to those used in edx-platform or openedx-i18n (see links above). + +Then, add a "django.po" file there that will contain your custom translations:: + + msgid "String to translate" + msgstr "你翻译的东西 la traduction de votre bidule" + +The "String to translate" part should match *exactly* the string that you would like to translate. You cannot make it up! The best way to find this string is to copy-paste it from the `upstream django.po file for the English language `__. + +If you cannot find the string to translate in this file, then it means that you are trying to translate a string that is used in some piece of javascript code. Those strings are stored in a different file named "djangojs.po". You can check it out `in the edx-platform repo as well `__. Your custom javascript strings should also be stored in a "djangojs.po" file that should be placed in the same + +To recap, here is an example. To translate a few strings in French, both from django.po and djangojs.po, we would have the following file hierarchy:: + + $(tutor config printroot)/env/build/openedx/locale/ + fr/ + LC_MESSAGES/ + django.po + djangojs.po + +With django.po containing:: + + msgid "It works! Powered by Open edX{registered_trademark}" + msgstr "Ça marche ! Propulsé by Open edX{registered_trademark}" + +And djangojs.po:: + + msgid "%(num_points)s point possible (graded, results hidden)" + msgid_plural "%(num_points)s points possible (graded, results hidden)" + msgstr[0] "%(num_points)s point possible (noté, résultats cachés)" + msgstr[1] "%(num_points)s points possibles (notés, résultats cachés)" + +Then you will have to re-build the openedx Docker image:: + + tutor images build openedx openedx-dev + + Beware that this will take a long time! Unfortunately it's difficult to accelerate this process, as translation files need to be compiled prior to collecting the assets. In development it's possible to accelerate the iteration loop -- but that exercise is left to the reader. + + Running a different ``openedx`` Docker image ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tutor/templates/apps/openedx/settings/partials/common_all.py b/tutor/templates/apps/openedx/settings/partials/common_all.py index e3d1ecd..5594fa2 100644 --- a/tutor/templates/apps/openedx/settings/partials/common_all.py +++ b/tutor/templates/apps/openedx/settings/partials/common_all.py @@ -45,7 +45,8 @@ ACE_CHANNEL_DEFAULT_EMAIL = "django_email" ACE_CHANNEL_TRANSACTIONAL_EMAIL = "django_email" EMAIL_FILE_PATH = "/tmp/openedx/emails" -LOCALE_PATHS.append("/openedx/locale") +LOCALE_PATHS.append("/openedx/locale/contrib/locale") +LOCALE_PATHS.append("/openedx/locale/user/locale") {{ patch("openedx-common-settings") }} ######## End of settings common to LMS and CMS \ No newline at end of file diff --git a/tutor/templates/build/openedx/Dockerfile b/tutor/templates/build/openedx/Dockerfile index 0b92b97..e4ab12c 100644 --- a/tutor/templates/build/openedx/Dockerfile +++ b/tutor/templates/build/openedx/Dockerfile @@ -37,11 +37,12 @@ RUN curl https://github.com/overhangio/edx-platform/commit/0d4f6cc3433013960b28e RUN curl https://github.com/edx/edx-platform/commit/adb2c672e4d17cc1c42bdc206a0051e0fa16b5be.patch | git apply - RUN curl https://github.com/edx/edx-platform/commit/b7ecd80a2bef0d845c3bce97818e70fb3ed9e36d.patch | git apply - -# Download extra locales to /openedx/locale +# Download extra locales to /openedx/locale/contrib/locale RUN cd /tmp \ && curl -L -o openedx-i18n.tar.gz https://github.com/openedx/openedx-i18n/archive/ironwood.tar.gz \ && tar xzf /tmp/openedx-i18n.tar.gz \ - && mv openedx-i18n-ironwood/edx-platform/locale/ /openedx/locale/ \ + && mkdir -p /openedx/locale/contrib \ + && mv openedx-i18n-ironwood/edx-platform/locale /openedx/locale/contrib \ && rm -rf openedx-i18n* # Install python requirements in a virtualenv @@ -81,6 +82,11 @@ ENV CONFIG_ROOT /openedx/config COPY settings/lms/*.py ./lms/envs/tutor/ COPY settings/cms/*.py ./cms/envs/tutor/ +# Copy user-specific locales to /openedx/locale/user/locale and compile them +RUN mkdir -p /openedx/locale/user +COPY ./locale/ /openedx/locale/user/locale/ +RUN cd /openedx/locale/user && \ + django-admin.py compilemessages -v1 # Compile i18n strings: in Ironwood, js locales are not properly compiled out of the box # and we need to do a pass ourselves. Also, we need to compile the djangojs.js files for # the downloaded locales. diff --git a/tutor/templates/build/openedx/locale/customlocales.md b/tutor/templates/build/openedx/locale/customlocales.md new file mode 100644 index 0000000..a098936 --- /dev/null +++ b/tutor/templates/build/openedx/locale/customlocales.md @@ -0,0 +1,13 @@ +Add your custom translations to this folder, with the following filesystem structure: + + languagecode/ + LC_MESSAGES/ + django.po + djangojs.po + +Where "languagecode" is one of "fr", "de_DE", "zh_CN", etc. + +The localized string in the *.po file should have the following format: + + msgid "String to translate" + msgstr "Your custom translation 你发音的东西 le bidule que vous voulez traduire" diff --git a/tutor/templates/build/openedx/settings/cms/assets.py b/tutor/templates/build/openedx/settings/cms/assets.py index 4acdef6..59b1dd0 100644 --- a/tutor/templates/build/openedx/settings/cms/assets.py +++ b/tutor/templates/build/openedx/settings/cms/assets.py @@ -5,4 +5,5 @@ WEBPACK_LOADER['DEFAULT']['STATS_FILE'] = STATIC_ROOT / "webpack-stats.json" derive_settings(__name__) -LOCALE_PATHS.append("/openedx/locale") +LOCALE_PATHS.append("/openedx/locale/contrib/locale") +LOCALE_PATHS.append("/openedx/locale/user/locale") diff --git a/tutor/templates/build/openedx/settings/lms/assets.py b/tutor/templates/build/openedx/settings/lms/assets.py index d286363..4cf476d 100644 --- a/tutor/templates/build/openedx/settings/lms/assets.py +++ b/tutor/templates/build/openedx/settings/lms/assets.py @@ -5,4 +5,5 @@ WEBPACK_LOADER['DEFAULT']['STATS_FILE'] = STATIC_ROOT / "webpack-stats.json" derive_settings(__name__) -LOCALE_PATHS.append("/openedx/locale") +LOCALE_PATHS.append("/openedx/locale/contrib/locale") +LOCALE_PATHS.append("/openedx/locale/user/locale") diff --git a/tutor/templates/build/openedx/settings/partials/i18n.py b/tutor/templates/build/openedx/settings/partials/i18n.py index 7a418d9..fb30466 100644 --- a/tutor/templates/build/openedx/settings/partials/i18n.py +++ b/tutor/templates/build/openedx/settings/partials/i18n.py @@ -14,4 +14,5 @@ DATABASES = { derive_settings(__name__) -LOCALE_PATHS.append("/openedx/locale") \ No newline at end of file +LOCALE_PATHS.append("/openedx/locale/contrib/locale") +LOCALE_PATHS.append("/openedx/locale/user/locale")