From 83f448778a178655a241cf70a987a2d2dd0ffc77 Mon Sep 17 00:00:00 2001 From: Omar Al-Ithawi Date: Wed, 6 Mar 2024 18:50:59 +0300 Subject: [PATCH] feat!: atlas pull for studio-frontend translations (#34261) This pull request pulls translations via atlas for `studio-frontend` and refactor `load_sfe_i18n_messages` to load new translations into `conf/plugins-locale/studio-frontend` instead of relying on deprecated node.js package bundled translations. --- Makefile | 8 +-- .../pipeline_mako/helpers/studiofrontend.py | 34 ++++++++----- .../tests/test_studio_frontend.py | 51 +++++++++++++++++++ 3 files changed, 77 insertions(+), 16 deletions(-) create mode 100644 common/djangoapps/pipeline_mako/tests/test_studio_frontend.py diff --git a/Makefile b/Makefile index 1012e558a7..1ee0c1947b 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ endif push_translations: ## push source strings to Transifex for translation i18n_tool transifex push -pull_plugin_translations: ## Pull translations from Transifex for edx_django_utils.plugins for both lms and cms +pull_plugin_translations: ## Pull translations for edx_django_utils.plugins for both lms and cms rm -rf conf/plugins-locale/plugins # Clean up existing atlas translations mkdir -p conf/plugins-locale/plugins python manage.py lms pull_plugin_translations --verbose $(ATLAS_OPTIONS) @@ -70,7 +70,7 @@ pull_xblock_translations: ## pull xblock translations via atlas python manage.py cms compile_xblock_translations pull_translations: ## pull translations from Transifex - git clean -fdX conf/locale + git clean -fdX conf/locale conf/plugins-locale/studio-frontend ifeq ($(OPENEDX_ATLAS_PULL),) i18n_tool transifex pull i18n_tool extract @@ -83,7 +83,9 @@ else make pull_xblock_translations make pull_plugin_translations find conf/locale -mindepth 1 -maxdepth 1 -type d -exec rm -r {} \; - atlas pull $(ATLAS_OPTIONS) translations/edx-platform/conf/locale:conf/locale + atlas pull $(ATLAS_OPTIONS) \ + translations/edx-platform/conf/locale:conf/locale \ + translations/studio-frontend/src/i18n/messages:conf/plugins-locale/studio-frontend i18n_tool generate endif python manage.py lms compilejsi18n diff --git a/common/djangoapps/pipeline_mako/helpers/studiofrontend.py b/common/djangoapps/pipeline_mako/helpers/studiofrontend.py index dfdbb4b8ef..41e2c4daf5 100644 --- a/common/djangoapps/pipeline_mako/helpers/studiofrontend.py +++ b/common/djangoapps/pipeline_mako/helpers/studiofrontend.py @@ -1,4 +1,6 @@ """ +Helpers for studio-frontend. + Contains code that gets run inside our mako template Debugging python-in-mako is terrible, so we've moved the actual code out to its own file """ @@ -15,19 +17,25 @@ log = logging.getLogger(__name__) def load_sfe_i18n_messages(language): """ Loads i18n data from studio-frontend's published files. - """ - messages = "{}" - try: - if language != 'en': - # because en is the default, studio-frontend will have it loaded by default - messages_path = "{base}/studio-frontend/dist/i18n/messages/{locale}.json".format( - base=settings.STATIC_ROOT_BASE, - locale=to_locale(language) - ) - with open(messages_path) as inputfile: - messages = inputfile.read() - except: # pylint: disable=bare-except - log.error("Error loading studiofrontend language files", exc_info=True) + This loads the i18n files pulled by the `make pull_translations` command. + + Returns: + str: unparsed i18n locale JSON file content as a string. + """ + messages = '{}' + + # because en is the default, studio-frontend will have it loaded by default + if language != 'en': + locale = to_locale(language) # fr-ca --> fr_CA format to match the file name in studio-frontend + messages_path = settings.REPO_ROOT / 'conf/plugins-locale/studio-frontend' / f'{locale}.json' + if messages_path.exists(): + try: + with open(messages_path) as messages_file: + messages = messages_file.read() + except OSError: + log.error(f"Error loading studiofrontend language files for langauge '{language}'", exc_info=True) + else: + log.warning(f"studiofrontend language files for langauge '{language}' was not found.") return messages diff --git a/common/djangoapps/pipeline_mako/tests/test_studio_frontend.py b/common/djangoapps/pipeline_mako/tests/test_studio_frontend.py new file mode 100644 index 0000000000..61b0b51b6c --- /dev/null +++ b/common/djangoapps/pipeline_mako/tests/test_studio_frontend.py @@ -0,0 +1,51 @@ +""" +Tests for the studiofrontend helper module. +""" + +import logging +import os + +import pytest + +from ..helpers import studiofrontend + + +def test_messages_file_not_found(tmpdir, settings, caplog): + """ + Ensure load_sfe_i18n_messages returns an empty json string when the messages file is not found. + """ + caplog.set_level(logging.INFO) + settings.REPO_ROOT = tmpdir + assert studiofrontend.load_sfe_i18n_messages('ar') == '{}' + assert 'studiofrontend language files for langauge \'ar\' was not found' in caplog.text + + +def test_messages_file_error(tmpdir, settings, caplog): + """ + Ensure load_sfe_i18n_messages returns an empty json string when the messages file is not found. + """ + caplog.set_level(logging.INFO) + settings.REPO_ROOT = tmpdir + # create a directory to cause an OSError when attempting to read it as a file + os.makedirs(tmpdir / 'conf/plugins-locale/studio-frontend/ar.json') + assert studiofrontend.load_sfe_i18n_messages('ar') == '{}' + assert 'Error loading studiofrontend language files for langauge' in caplog.text + + +@pytest.mark.parametrize('language', ['jp-jp', 'jp_JP']) +def test_messages_file_found(tmpdir, settings, caplog, language): + """ + Ensure load_sfe_i18n_messages finds the right language file and returns its content as string. + + django.utils.translation.get_language() returns 'jp-jp' or 'fr-ca' instead of 'jp_JP' or 'fr_CA' respectively. + + This test checks load_sfe_i18n_messages on both formats. + """ + caplog.set_level(logging.INFO) + settings.REPO_ROOT = tmpdir + studio_frontend_messages_dir = tmpdir / 'conf/plugins-locale/studio-frontend' + os.makedirs(studio_frontend_messages_dir) + messages_path = studio_frontend_messages_dir / 'jp_JP.json' + messages_path.write_text('{"homepage": "Homepage"}', encoding='utf-8') + assert studiofrontend.load_sfe_i18n_messages(language) == '{"homepage": "Homepage"}' + assert caplog.text == ''