Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add gettext for JS translation #70

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
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",
"translation_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
54 changes: 0 additions & 54 deletions recommender/conf/locale/en/LC_MESSAGES/django.po

This file was deleted.

1 change: 0 additions & 1 deletion recommender/conf/locale/en/LC_MESSAGES/text.po

This file was deleted.

54 changes: 54 additions & 0 deletions recommender/conf/locale/en/LC_MESSAGES/text.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2016-05-27 11:04+0500\n"
"PO-Revision-Date: 2016-05-27 11:04+0500\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#: recommender.py
msgid "The resource you are attempting to provide already exists"
msgstr ""

#: recommender.py
msgid ""
"The resource you are attempting to provide has been disallowed by the staff. "
"Reason: "
msgstr ""

#: recommender.py
msgid "The selected resource does not exist"
msgstr ""

#: recommender.py
msgid "Size of uploaded file exceeds threshold"
msgstr ""

#: recommender.py
msgid "The configuration of pyfs is not properly set"
msgstr ""

#: recommender.py:729
msgid "Endorse resource without permission"
msgstr ""

#: recommender.py
msgid "You don't have the permission to remove this resource"
msgstr ""

#: recommender.py
msgid "Only staff can import resources"
msgstr ""

#: recommender.py
msgid "Please submit the JSON file obtained with the download resources button"
msgstr ""

#: recommender.py
msgid "Tried to access flagged resources without staff permission"
msgstr ""
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
28 changes: 25 additions & 3 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,43 @@
#
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
47 changes: 43 additions & 4 deletions requirements/ci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Comment on lines -29 to -32
Copy link
Contributor

@brian-smith-tcril brian-smith-tcril Oct 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This stood out to me when I was looking through this PR so I'm leaving a comment to provide context

Removing this is definitely the right call.

Loading
Loading