Skip to content

Commit

Permalink
feat: add catalog url and js namespace for OEP-58 JS translations
Browse files Browse the repository at this point in the history
  • Loading branch information
OmarIthawi committed Dec 15, 2023
1 parent 06eafc8 commit de497a8
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 1 deletion.
19 changes: 19 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@ These are notable changes in XBlock.
Unreleased
----------

1.9.0 - 2023-11-20
------------------

* Support for `OEP-58 JavaScript translations <https://docs.openedx.org/en/latest/developers/concepts/oep58.html>`_:

* Introduced abstract JavaScript translations support by adding the ``i18n_js_namespace`` property and
``get_i18n_js_namespace`` method to the ``SharedBlockBase``. This allows XBlocks to define a JavaScript namespace
so the XBlock i18n runtime service can manage and load JavaScript translations for XBlocks.

* Added the stub ``get_javascript_i18n_catalog_url`` method to the ``NullI18nService`` class to be implemented
by runtime services.

* See the `edx-platform atlas translations proposal <https://github.com/openedx/edx-platform/blob/master/docs/decisions/0019-oep-58-atlas-translations-design.rst>`_

1.8.1 - 2023-10-07
------------------

* Python Requirements Update
* Update setup.py, adds required packages

1.8.0 - 2023-09-25
------------------
Expand Down
2 changes: 1 addition & 1 deletion xblock/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ def __init__(self, *args, **kwargs):
# without causing a circular import
xblock.fields.XBlockMixin = XBlockMixin

__version__ = '1.8.1'
__version__ = '1.9.0'
12 changes: 12 additions & 0 deletions xblock/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class SharedBlockBase(Plugin):

resources_dir = ''
public_dir = 'public'
i18n_js_namespace = None

@classmethod
def get_resources_dir(cls):
Expand All @@ -70,6 +71,17 @@ def get_public_dir(cls):
"""
return cls.public_dir

@classmethod
def get_i18n_js_namespace(cls):
"""
Gets the JavaScript translations namespace for this XBlock.
Returns:
str: The JavaScript namespace for this XBlock.
None: If this doesn't have JavaScript translations configured.
"""
return cls.i18n_js_namespace

@classmethod
def open_local_resource(cls, uri):
"""
Expand Down
10 changes: 10 additions & 0 deletions xblock/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,16 @@ def strftime(self, dtime, format): # pylint: disable=redefined-builtin
timestring = dtime.strftime(format)
return timestring

def get_javascript_i18n_catalog_url(self):
"""
Return the URL to the JavaScript i18n catalog file.
This method returns None in NullI18nService. When implemented in
a runtime, it should return the URL to the JavaScript i18n catalog so
it can be loaded in frontends.
"""
return None

@property
def ugettext(self):
"""
Expand Down
33 changes: 33 additions & 0 deletions xblock/test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,39 @@ class FieldTester(XBlock):
assert {1} == field_tester._field_data.get(field_tester, 'field_d')


def test_shared_block_base_defaults():
"""
Test default values and static methods provided by the SharedBlockBase class.
"""
class DefaultsTester(XBlock):
pass

defaults_tester = DefaultsTester(
TestRuntime(services={'field-data': DictFieldData({})}),
scope_ids=Mock(spec=ScopeIds)
)

# Testing the default static method return values of SharedBlockBase
assert defaults_tester.get_resources_dir() == ''
assert defaults_tester.get_public_dir() == 'public'
assert defaults_tester.get_i18n_js_namespace() is None

class CustomizedValuesTester(XBlock):
resources_dir = 'custom_resource_dir'
public_dir = 'another_public_dir'
i18n_js_namespace = 'CustomizedValuesTesterI18N'

customized_values_tester = CustomizedValuesTester(
TestRuntime(services={'field-data': DictFieldData({})}),
scope_ids=Mock(spec=ScopeIds),
)

# Testing the customized static method return values of SharedBlockBase
assert customized_values_tester.get_resources_dir() == 'custom_resource_dir'
assert customized_values_tester.get_public_dir() == 'another_public_dir'
assert customized_values_tester.get_i18n_js_namespace() == 'CustomizedValuesTesterI18N'


def test_mutable_none_values():
# Check that fields with values intentionally set to None
# save properly.
Expand Down
3 changes: 3 additions & 0 deletions xblock/test/test_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,9 @@ def assert_equals_unicode(str1, str2):
assert_equals_unicode("Feb 14, 2013 at 22:30", i18n.strftime(when, "DATE_TIME"))
assert_equals_unicode("10:30:17 PM", i18n.strftime(when, "TIME"))

# Runtimes are expected to implement this method though.
assert i18n.get_javascript_i18n_catalog_url() is None, 'NullI18nService does not implement this method.'

# secret_service is available.
assert self.runtime.service(self, "secret_service") == 17

Expand Down

0 comments on commit de497a8

Please sign in to comment.