Skip to content

Commit

Permalink
feat: Add gettext for JS translation
Browse files Browse the repository at this point in the history
JS translations will not be shown fetched without directing (gettext) to the
correct javascript file

Refs: FC-0012 OEP-58
  • Loading branch information
shadinaif committed Oct 10, 2023
1 parent ed52df4 commit 031286c
Show file tree
Hide file tree
Showing 15 changed files with 291 additions and 52 deletions.
19 changes: 6 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
WORKING_DIR := recommender
EXTRACT_DIR := $(WORKING_DIR)/conf/locale/en/LC_MESSAGES
EXTRACTED_DJANGO_PARTIAL := $(EXTRACT_DIR)/django-partial.po
EXTRACTED_DJANGOJS_PARTIAL := $(EXTRACT_DIR)/djangojs-partial.po
EXTRACTED_DJANGO := $(EXTRACT_DIR)/django.po
JS_TARGET := $(WORKING_DIR)/public/js/translations

COMMON_CONSTRAINTS_TXT=requirements/common_constraints.txt
.PHONY: $(COMMON_CONSTRAINTS_TXT)
Expand All @@ -22,12 +19,8 @@ upgrade: $(COMMON_CONSTRAINTS_TXT) ## update the requirements/*.txt files with
pip-compile --upgrade -o requirements/ci.txt requirements/ci.in

extract_translations: ## extract strings to be translated, outputting .po files
cd $(WORKING_DIR) && i18n_tool extract
mv $(EXTRACTED_DJANGO_PARTIAL) $(EXTRACTED_DJANGO)
# Safely concatenate djangojs if it exists
if test -f $(EXTRACTED_DJANGOJS_PARTIAL); then \
msgcat $(EXTRACTED_DJANGO) $(EXTRACTED_DJANGOJS_PARTIAL) -o $(EXTRACTED_DJANGO) && \
rm $(EXTRACTED_DJANGOJS_PARTIAL); \
fi
sed -i'' -e 's/nplurals=INTEGER/nplurals=2/' $(EXTRACTED_DJANGO)
sed -i'' -e 's/plural=EXPRESSION/plural=\(n != 1\)/' $(EXTRACTED_DJANGO)
cd $(WORKING_DIR) && i18n_tool extract --no-segment --merge-po-files

compile_translations: ## compile translation files, outputting .mo files for each supported language
cd $(WORKING_DIR) && i18n_tool generate -v
python manage.py compilejsi18n --namespace RecommenderXBlockI18N --output $(JS_TARGET)
92 changes: 92 additions & 0 deletions dev_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"""
Django settings for xblock-drag-and-drop-v2 project.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
from __future__ import absolute_import
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
# This is just a container for running tests, it's okay to allow it to be
# defaulted here if not present in environment settings
SECRET_KEY = os.environ.get('SECRET_KEY', '&=@m=qyqg#l!f99ouuuinpbsv0ah001unk@q^7)bkr^^n5@q1=')

# SECURITY WARNING: don't run with debug turned on in production!
# This is just a container for running tests
DEBUG = True

TEMPLATE_DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = (
'statici18n',
'recommender',
)

# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'en'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'

# statici18n
# http://django-statici18n.readthedocs.io/en/latest/settings.html

LANGUAGES = [
('ar', 'Arabic'),
('de', 'German'),
('en', 'English - Source Language'),
('eo', 'Esperanto'),
('es_419', 'Spanish (Latin America)'),
('fr', 'French'),
('he', 'Hebrew'),
('hi', 'Hindi'),
('it', 'Italian'),
('ja', 'Japanese'),
('ko', 'Korean (Korea)'),
('nl', 'Dutch'),
('pl', 'Polski'),
('pt_BR', 'Portuguese (Brazil)'),
('pt_PT', 'Portuguese (Portugal)'),
('ru', 'Russian'),
('tr', 'Turkish'),
('zh_CN', 'Chinese (China)'),
]

LOCALE_PATHS = [os.path.join(BASE_DIR, "locale")]

STATICI18N_DOMAIN = 'text'
STATICI18N_NAMESPACE = 'RecommenderXBlockI18N'
STATICI18N_PACKAGES = (
'recommender',
)
STATICI18N_ROOT = 'recommender/public/js'
STATICI18N_OUTPUT_DIR = 'translations'
12 changes: 12 additions & 0 deletions manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env python
import os
import sys
from django.core.management import execute_from_command_line

if __name__ == "__main__":
os.environ.setdefault(
"DJANGO_SETTINGS_MODULE",
"dev_settings"
)

execute_from_command_line(sys.argv)
4 changes: 3 additions & 1 deletion recommender/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
This XBlock will show a set of recommended resources which may be helpful to
students solving a given problem.
"""
from .recommender import RecommenderXBlock
# We avoid importing RecommenderXBlock here, because it's importing Filesystem from xblock.reference.plugins
# which is not loaded when running `manage.py` commands (which is used by `make compile_translations`)
# from .recommender import RecommenderXBlock

__version__ = '2.1.0'
3 changes: 3 additions & 0 deletions recommender/conf/locale/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

locales:
- en # English - Source Language

ignore_dirs:
- public
22 changes: 22 additions & 0 deletions recommender/recommender.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import bleach
from webob.response import Response
from django.utils import translation

from xblock.core import XBlock
from xblock.exceptions import JsonHandlerError
Expand Down Expand Up @@ -944,6 +945,21 @@ def _construct_view_resource(self, resource):

return result

@staticmethod
def _get_statici18n_js_url(): # pragma: no cover
"""
Returns the Javascript translation file for the currently selected language, if any found by `pkg_resources`
"""
lang_code = translation.get_language()
if not lang_code:
return None
text_js = 'public/js/translations/{lang_code}/text.js'
country_code = lang_code.split('-')[0]
for code in (translation.to_locale(lang_code), lang_code, country_code):
if pkg_resources.resource_exists(resource_loader.module_name, text_js.format(lang_code=code)):
return text_js.format(lang_code=code)
return None

def student_view(self, _context=None): # pylint: disable=unused-argument
"""
The primary view of the RecommenderXBlock, shown to students
Expand Down Expand Up @@ -990,6 +1006,9 @@ def student_view(self, _context=None): # pylint: disable=unused-argument
frag.add_css(self.resource_string("static/css/recommender.css"))
frag.add_css(self.resource_string("static/css/introjs.css"))
frag.add_javascript(self.resource_string("static/js/src/jquery.tooltipster.min.js"))
statici18n_js_url = self._get_statici18n_js_url()
if statici18n_js_url:
frag.add_javascript(self.resource_string(statici18n_js_url))
frag.add_javascript(self.resource_string("static/js/src/cats.js"))
frag.add_javascript(self.resource_string("static/js/src/recommender.js"))
frag.initialize_js('RecommenderXBlock', self.get_client_configuration())
Expand All @@ -1007,6 +1026,9 @@ def studio_view(self, _context=None): # pylint: disable=unused-argument
))
frag.add_css(load("static/css/recommenderstudio.css"))
frag.add_javascript_url("//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js")
statici18n_js_url = self._get_statici18n_js_url()
if statici18n_js_url:
frag.add_javascript(self.resource_string(statici18n_js_url))
frag.add_javascript(load("static/js/src/recommenderstudio.js"))
frag.initialize_js('RecommenderXBlock')
return frag
Expand Down
24 changes: 20 additions & 4 deletions recommender/static/js/src/cats.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,26 @@
//
// Note: The global `window.*` variables should be converted into local ones to avoid over-using global variables. This is a 2014-era legacy XBlock coding standard that should be refactored -- @OmarIthawi at Apr 4, 2023
//
var gettext = window.gettext || (function (string) {
// Shim Django's `gettext` if unavailable.
return string;
});
var gettext;
if ('RecommenderXBlockI18N' in window) {
// Use Recommender's local translations
gettext = function(string) {
var translated = window.RecommenderXBlockI18N.gettext(string);
// if Recommender's translation is the same as the input, check if global has a different value
// This is useful for overriding the XBlock's string by themes (only for English)
if (string === translated && 'gettext' in window) {
translated = window.gettext(string);
}
return translated;
};
} else if ('gettext' in window) {
// Use edxapp's global translations
gettext = window.gettext;
}
if (typeof gettext == "undefined") {
// No translations -- used by test environment
gettext = function(string) { return string; };
}

var span = function(text) {
// Surround text with a span.
Expand Down
1 change: 1 addition & 0 deletions requirements/base.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ mako
simplejson
webob
web_fragments
edx-i18n-tools
30 changes: 26 additions & 4 deletions requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,26 +1,48 @@
#
# This file is autogenerated by pip-compile with Python 3.8
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# make upgrade
#
appdirs==1.4.4
# via fs
bleach==6.0.0
asgiref==3.7.2
# via django
bleach==6.1.0
# via -r requirements/base.in
django==3.2.22
# via
# -c requirements/common_constraints.txt
# edx-i18n-tools
edx-i18n-tools==1.3.0
# via -r requirements/base.in
fs==2.4.16
# via -r requirements/base.in
lxml==4.9.3
# via edx-i18n-tools
mako==1.2.4
# via -r requirements/base.in
markupsafe==2.1.3
# via mako
simplejson==3.19.1
path==16.7.1
# via edx-i18n-tools
polib==1.2.0
# via edx-i18n-tools
pytz==2023.3.post1
# via django
pyyaml==6.0.1
# via edx-i18n-tools
simplejson==3.19.2
# via -r requirements/base.in
six==1.16.0
# via
# bleach
# fs
web-fragments==2.0.0
sqlparse==0.4.4
# via django
typing-extensions==4.8.0
# via asgiref
web-fragments==2.1.0
# via -r requirements/base.in
webencodings==0.5.1
# via bleach
Expand Down
49 changes: 44 additions & 5 deletions requirements/ci.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# This file is autogenerated by pip-compile with Python 3.8
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# make upgrade
Expand All @@ -8,26 +8,65 @@ appdirs==1.4.4
# via
# -r requirements/test.txt
# fs
bleach==6.0.0
asgiref==3.7.2
# via
# -r requirements/test.txt
# django
bleach==6.1.0
# via -r requirements/test.txt
django==3.2.22
# via
# -c requirements/common_constraints.txt
# -r requirements/test.txt
# edx-i18n-tools
edx-i18n-tools==1.3.0
# via -r requirements/test.txt
fs==2.4.16
# via -r requirements/test.txt
lxml==4.9.3
# via
# -r requirements/test.txt
# edx-i18n-tools
mako==1.2.4
# via -r requirements/test.txt
markupsafe==2.1.3
# via
# -r requirements/test.txt
# mako
pycodestyle==2.10.0
path==16.7.1
# via
# -r requirements/test.txt
# edx-i18n-tools
polib==1.2.0
# via
# -r requirements/test.txt
# edx-i18n-tools
pycodestyle==2.11.0
# via -r requirements/test.txt
simplejson==3.19.1
pytz==2023.3.post1
# via
# -r requirements/test.txt
# django
pyyaml==6.0.1
# via
# -r requirements/test.txt
# edx-i18n-tools
simplejson==3.19.2
# via -r requirements/test.txt
six==1.16.0
# via
# -r requirements/test.txt
# bleach
# fs
web-fragments==2.0.0
sqlparse==0.4.4
# via
# -r requirements/test.txt
# django
typing-extensions==4.8.0
# via
# -r requirements/test.txt
# asgiref
web-fragments==2.1.0
# via -r requirements/test.txt
webencodings==0.5.1
# via
Expand Down
5 changes: 0 additions & 5 deletions requirements/common_constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,3 @@ django-simple-history==3.0.0
# tox>4.0.0 isn't yet compatible with many tox plugins, causing CI failures in almost all repos.
# Details can be found in this discussion: https://github.com/tox-dev/tox/discussions/1810
tox<4.0.0

# edx-sphinx-theme is not compatible with latest Sphinx==6.0.0 version
# Pinning Sphinx version unless the compatibility issue gets resolved
# For details, see issue https://github.com/openedx/edx-sphinx-theme/issues/197
sphinx<6.0.0
10 changes: 5 additions & 5 deletions requirements/pip.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#
# This file is autogenerated by pip-compile with python 3.8
# To update, run:
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# make upgrade
#
wheel==0.40.0
wheel==0.41.2
# via -r requirements/pip.in

# The following packages are considered to be unsafe in a requirements file:
pip==23.1.2
pip==23.2.1
# via -r requirements/pip.in
setuptools==67.8.0
setuptools==68.2.2
# via -r requirements/pip.in
Loading

0 comments on commit 031286c

Please sign in to comment.