This is another solution we deployed. It involved monkey patching the _add_installed_apps_translations
method of the DjangoTranslation
class to prioritize the translations of the project apps over the translations of the Django apps.
# patches.py
from __future__ import absolute_import, unicode_literals
import os
from django.apps import apps
from django.core.exceptions import AppRegistryNotReady
from django.utils.translation.trans_real import DjangoTranslation
def patchDjangoTranslation():
"""
Patch Django to prioritize the project's app translations over
its own. Fixes GitLab issue #734 for Django 1.11.
Might needs to be updated for future Django versions.
"""
def _add_installed_apps_translations_new(self):
"""Merges translations from each installed app."""
try:
# Django apps
app_configs = [
app for app in apps.get_app_configs() if app.name.startswith('django.')
]
# Non Django apps
app_configs = [
app for app in apps.get_app_configs() if not app.name.startswith('django.')
]
app_configs = reversed(app_configs)
except AppRegistryNotReady:
raise AppRegistryNotReady(
"The translation infrastructure cannot be initialized before the "
"apps registry is ready. Check that you don't make non-lazy "
"gettext calls at import time.")
for app_config in app_configs:
localedir = os.path.join(app_config.path, 'locale')
if os.path.exists(localedir):
translation = self._new_gnu_trans(localedir)
self.merge(translation)
DjangoTranslation._add_installed_apps_translations = _add_installed_apps_translations_new
Then in the .ready()
method of your main app, call patchDjangoTranslation
:
from .patches import patchDjangoTranslation
class CommonApp(MayanAppConfig):
app_namespace = 'common'
app_url = ''
has_rest_api = True
has_tests = True
name = 'mayan.apps.common'
verbose_name = _('Common')
def ready(self):
super(CommonApp, self).ready()
patchDjangoTranslation() # Apply patch
The main change are these lines:
# Django apps
app_configs = [
app for app in apps.get_app_configs() if app.name.startswith('django.')
]
# Non Django apps
app_configs = [
app for app in apps.get_app_configs() if not app.name.startswith('django.')
]
app_configs = reversed(app_configs)
The original are:
app_configs = reversed(list(apps.get_app_configs()))
Instead of interpreting the translations of the apps in the order they appear in the INSTALLED_APPS
setting, this block outputs the list of apps placing the project apps before the Django apps. Since this only happens when determining the translation to use, it doesn't affect any other part of the code and no other changes are necessary.
It works on Django version 1.11 up to 2.2.