Make the i18n service available everywhere.
To get all dates localized, we need all runtimes to have the i18n service, and since runtimes are made by the modulestores, we need to pass it to them. Soon (fingers crossed), modulestores won't be involved in making runtimes, and many of these changes will go away.
This commit is contained in:
@@ -408,7 +408,7 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
|
||||
# set the due_date_display_format to what would have been shown previously (with no timezone).
|
||||
# Then remove show_timezone so that if the user clears out the due_date_display_format,
|
||||
# they get the default date display.
|
||||
self.due_date_display_format = u"%b %d, %Y at %H:%M"
|
||||
self.due_date_display_format = "DATE_TIME"
|
||||
delattr(self, 'show_timezone')
|
||||
|
||||
# NOTE: relies on the modulestore to call set_grading_policy() right after
|
||||
|
||||
@@ -6,15 +6,17 @@ Passes settings.MODULESTORE as kwargs to MongoModuleStore
|
||||
|
||||
from __future__ import absolute_import
|
||||
from importlib import import_module
|
||||
|
||||
import re
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.cache import get_cache, InvalidCacheBackendError
|
||||
from django.dispatch import Signal
|
||||
import django.utils
|
||||
|
||||
from xmodule.modulestore.loc_mapper_store import LocMapperStore
|
||||
from xmodule.util.django import get_current_request_hostname
|
||||
|
||||
|
||||
# We may not always have the request_cache module available
|
||||
try:
|
||||
from request_cache.middleware import RequestCache
|
||||
@@ -38,7 +40,7 @@ def load_function(path):
|
||||
return getattr(import_module(module_path), name)
|
||||
|
||||
|
||||
def create_modulestore_instance(engine, doc_store_config, options):
|
||||
def create_modulestore_instance(engine, doc_store_config, options, i18n_service=None):
|
||||
"""
|
||||
This will return a new instance of a modulestore given an engine and options
|
||||
"""
|
||||
@@ -68,6 +70,7 @@ def create_modulestore_instance(engine, doc_store_config, options):
|
||||
xblock_mixins=getattr(settings, 'XBLOCK_MIXINS', ()),
|
||||
xblock_select=getattr(settings, 'XBLOCK_SELECT_FUNCTION', None),
|
||||
doc_store_config=doc_store_config,
|
||||
i18n_service=i18n_service or ModuleI18nService(),
|
||||
**_options
|
||||
)
|
||||
|
||||
@@ -186,3 +189,33 @@ def editable_modulestore(name='default'):
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class ModuleI18nService(object):
|
||||
"""
|
||||
Implement the XBlock runtime "i18n" service.
|
||||
|
||||
Mostly a pass-through to Django's translation module.
|
||||
django.utils.translation implements the gettext.Translations interface (it
|
||||
has ugettext, ungettext, etc), so we can use it directly as the runtime
|
||||
i18n service.
|
||||
|
||||
"""
|
||||
def __getattr__(self, name):
|
||||
return getattr(django.utils.translation, name)
|
||||
|
||||
def strftime(self, *args, **kwargs):
|
||||
"""
|
||||
A locale-aware implementation of strftime.
|
||||
"""
|
||||
# This is the wrong place to import this function. I'm putting it here
|
||||
# because the xmodule test suite can't import this module, because
|
||||
# Django is not available in that suite. This function isn't called in
|
||||
# that suite, so this hides the import so the test won't fail.
|
||||
#
|
||||
# As I said, this is wrong. But Cale says this code will soon be
|
||||
# refactored to a place that will be right, and the code can be made
|
||||
# right there. If you are reading this comment after April 1, 2014,
|
||||
# then Cale was a liar.
|
||||
from util.date_utils import strftime_localized
|
||||
return strftime_localized(*args, **kwargs)
|
||||
|
||||
@@ -23,7 +23,7 @@ class MixedModuleStore(ModuleStoreWriteBase):
|
||||
ModuleStore knows how to route requests to the right persistence ms and how to convert any
|
||||
references in the xblocks to the type required by the app and the persistence layer.
|
||||
"""
|
||||
def __init__(self, mappings, stores, reference_type=None, **kwargs):
|
||||
def __init__(self, mappings, stores, reference_type=None, i18n_service=None, **kwargs):
|
||||
"""
|
||||
Initialize a MixedModuleStore. Here we look into our passed in kwargs which should be a
|
||||
collection of other modulestore configuration informations
|
||||
@@ -55,7 +55,8 @@ class MixedModuleStore(ModuleStoreWriteBase):
|
||||
store['ENGINE'],
|
||||
# XMLModuleStore's don't have doc store configs
|
||||
store.get('DOC_STORE_CONFIG', {}),
|
||||
store['OPTIONS']
|
||||
store['OPTIONS'],
|
||||
i18n_service=i18n_service,
|
||||
)
|
||||
|
||||
def _get_modulestore_for_courseid(self, course_id):
|
||||
|
||||
@@ -263,6 +263,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
|
||||
def __init__(self, doc_store_config, fs_root, render_template,
|
||||
default_class=None,
|
||||
error_tracker=null_error_tracker,
|
||||
i18n_service=None,
|
||||
**kwargs):
|
||||
"""
|
||||
:param doc_store_config: must have a host, db, and collection entries. Other common entries: port, tz_aware.
|
||||
@@ -312,6 +313,8 @@ class MongoModuleStore(ModuleStoreWriteBase):
|
||||
self.fs_root = path(fs_root)
|
||||
self.error_tracker = error_tracker
|
||||
self.render_template = render_template
|
||||
self.i18n_service = i18n_service
|
||||
|
||||
self.ignore_write_events_on_courses = []
|
||||
|
||||
def compute_metadata_inheritance_tree(self, location):
|
||||
@@ -498,6 +501,10 @@ class MongoModuleStore(ModuleStoreWriteBase):
|
||||
if apply_cached_metadata:
|
||||
cached_metadata = self.get_cached_metadata_inheritance_tree(location)
|
||||
|
||||
services = {}
|
||||
if self.i18n_service:
|
||||
services["i18n"] = self.i18n_service
|
||||
|
||||
# TODO (cdodge): When the 'split module store' work has been completed, we should remove
|
||||
# the 'metadata_inheritance_tree' parameter
|
||||
system = CachingDescriptorSystem(
|
||||
@@ -510,6 +517,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
|
||||
cached_metadata=cached_metadata,
|
||||
mixins=self.xblock_mixins,
|
||||
select=self.xblock_select,
|
||||
services=services,
|
||||
)
|
||||
return system.load_item(location)
|
||||
|
||||
@@ -631,6 +639,10 @@ class MongoModuleStore(ModuleStoreWriteBase):
|
||||
if metadata is None:
|
||||
metadata = {}
|
||||
if system is None:
|
||||
services = {}
|
||||
if self.i18n_service:
|
||||
services["i18n"] = self.i18n_service
|
||||
|
||||
system = CachingDescriptorSystem(
|
||||
modulestore=self,
|
||||
module_data={},
|
||||
@@ -641,6 +653,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
|
||||
cached_metadata={},
|
||||
mixins=self.xblock_mixins,
|
||||
select=self.xblock_select,
|
||||
services=services,
|
||||
)
|
||||
xblock_class = system.load_block_type(location.category)
|
||||
if definition_data is None:
|
||||
|
||||
@@ -105,6 +105,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
|
||||
default_class=None,
|
||||
error_tracker=null_error_tracker,
|
||||
loc_mapper=None,
|
||||
i18n_service=None,
|
||||
**kwargs):
|
||||
"""
|
||||
:param doc_store_config: must have a host, db, and collection entries. Other common entries: port, tz_aware.
|
||||
@@ -129,6 +130,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
|
||||
self.fs_root = path(fs_root)
|
||||
self.error_tracker = error_tracker
|
||||
self.render_template = render_template
|
||||
self.i18n_service = i18n_service
|
||||
|
||||
# TODO: Don't have a runtime just to generate the appropriate mixin classes (cpennington)
|
||||
# This is only used by _partition_fields_by_scope, which is only needed because
|
||||
@@ -180,6 +182,10 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
|
||||
'''
|
||||
system = self._get_cache(course_entry['structure']['_id'])
|
||||
if system is None:
|
||||
services = {}
|
||||
if self.i18n_service:
|
||||
services["i18n"] = self.i18n_service
|
||||
|
||||
system = CachingDescriptorSystem(
|
||||
modulestore=self,
|
||||
course_entry=course_entry,
|
||||
@@ -191,6 +197,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
|
||||
resources_fs=None,
|
||||
mixins=self.xblock_mixins,
|
||||
select=self.xblock_select,
|
||||
services=services,
|
||||
)
|
||||
self._add_cache(course_entry['structure']['_id'], system)
|
||||
self.cache_items(system, block_ids, depth, lazy)
|
||||
|
||||
@@ -347,8 +347,10 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
"""
|
||||
An XML backed ModuleStore
|
||||
"""
|
||||
def __init__(self, data_dir, default_class=None, course_dirs=None, course_ids=None,
|
||||
load_error_modules=True, **kwargs):
|
||||
def __init__(
|
||||
self, data_dir, default_class=None, course_dirs=None, course_ids=None,
|
||||
load_error_modules=True, i18n_service=None, **kwargs
|
||||
):
|
||||
"""
|
||||
Initialize an XMLModuleStore from data_dir
|
||||
|
||||
@@ -382,6 +384,8 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
# All field data will be stored in an inheriting field data.
|
||||
self.field_data = inheriting_field_data(kvs=DictKeyValueStore())
|
||||
|
||||
self.i18n_service = i18n_service
|
||||
|
||||
# If we are specifically asked for missing courses, that should
|
||||
# be an error. If we are asked for "all" courses, find the ones
|
||||
# that have a course.xml. We sort the dirs in alpha order so we always
|
||||
@@ -522,6 +526,10 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
"""
|
||||
return policy.get(policy_key(usage_id), {})
|
||||
|
||||
services = {}
|
||||
if self.i18n_service:
|
||||
services['i18n'] = self.i18n_service
|
||||
|
||||
system = ImportSystem(
|
||||
xmlstore=self,
|
||||
course_id=course_id,
|
||||
@@ -534,6 +542,7 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
default_class=self.default_class,
|
||||
select=self.xblock_select,
|
||||
field_data=self.field_data,
|
||||
services=services,
|
||||
)
|
||||
|
||||
course_descriptor = system.process_xml(etree.tostring(course_data, encoding='unicode'))
|
||||
|
||||
Reference in New Issue
Block a user