Modify Django's translation library, such that the gettext family of
functions return an empty string when attempting to translate a
falsey value. This overrides the default behavior [0]:
> It is convention with GNU gettext to include meta-data as the
> translation for the empty string.
This patch provides a holistic solution to replace the current piecemeal
approach [1][2].
Affected Methods:
- gettext
- ugettext
[0] https://docs.python.org/2.7/library/gettext.html#the-gnutranslations-class
[1] bad803e451
[2] https://github.com/edx/edx-platform/pull/4653
81 lines
2.7 KiB
Python
81 lines
2.7 KiB
Python
"""
|
|
Monkey-patch the edX platform
|
|
|
|
Here be dragons (and simians!)
|
|
|
|
* USE WITH CAUTION *
|
|
No, but seriously, you probably never really want to make changes here.
|
|
This module contains methods to monkey-patch [0] the edx-platform.
|
|
Patches are to be applied as early as possible in the callstack
|
|
(currently lms/startup.py and cms/startup.py). Consequently, changes
|
|
made here will affect the entire platform.
|
|
|
|
That said, if you've decided you really need to monkey-patch the
|
|
platform (and you've convinced enough people that this is best
|
|
solution), kindly follow these guidelines:
|
|
- Reference django_utils_translation.py for a sample implementation.
|
|
- Name your module by replacing periods with underscores for the
|
|
module to be patched:
|
|
- patching 'django.utils.translation'
|
|
becomes 'django_utils_translation'
|
|
- patching 'your.module'
|
|
becomes 'your_module'
|
|
- Implement argumentless function wrappers in
|
|
monkey_patch.your_module for the following:
|
|
- is_patched
|
|
- patch
|
|
- unpatch
|
|
- Add the following code where needed (typically cms/startup.py and
|
|
lms/startup.py):
|
|
```
|
|
from monkey_patch import your_module
|
|
your_module.patch()
|
|
```
|
|
- Write tests! All code should be tested anyway, but with code that
|
|
patches the platform runtime, we must be extra sure there are no
|
|
unintended consequences.
|
|
|
|
[0] http://en.wikipedia.org/wiki/Monkey_patch
|
|
"""
|
|
# Use this key to store a reference to the unpatched copy
|
|
__BACKUP_ATTRIBUTE_NAME = '__monkey_patch'
|
|
|
|
|
|
def is_patched(module, attribute_name):
|
|
"""
|
|
Check if an attribute has been monkey-patched
|
|
"""
|
|
attribute = getattr(module, attribute_name)
|
|
return hasattr(attribute, __BACKUP_ATTRIBUTE_NAME)
|
|
|
|
|
|
def patch(module, attribute_name, attribute_replacement):
|
|
"""
|
|
Monkey-patch an attribute
|
|
|
|
A backup of the original attribute is preserved in the patched
|
|
attribute (see: __BACKUP_ATTRIBUTE_NAME).
|
|
"""
|
|
attribute = getattr(module, attribute_name)
|
|
setattr(attribute_replacement, __BACKUP_ATTRIBUTE_NAME, attribute)
|
|
setattr(module, attribute_name, attribute_replacement)
|
|
return is_patched(module, attribute_name)
|
|
|
|
|
|
def unpatch(module, attribute_name):
|
|
"""
|
|
Un-monkey-patch an attribute
|
|
|
|
Restore a backup of the original attribute from the patched
|
|
attribute, iff it exists (see: __BACKUP_ATTRIBUTE_NAME).
|
|
|
|
Return boolean whether or not the attribute could be unpatched
|
|
"""
|
|
was_patched = False
|
|
attribute = getattr(module, attribute_name)
|
|
if hasattr(attribute, __BACKUP_ATTRIBUTE_NAME):
|
|
attribute_old = getattr(attribute, __BACKUP_ATTRIBUTE_NAME)
|
|
setattr(module, attribute_name, attribute_old)
|
|
was_patched = True
|
|
return was_patched
|