django-bakery
django-bakery copied to clipboard
i18n localization support
One thing to consider might be posting an additional Content-Language
header when we upload to S3.
Here's a rough idea:
What if if USE_i18n
is True and a LANGUAGES
settings tuple is defined bakery will loop through and bake each view for each language, with the first argument of the LANGUAGES tuple being prepended to the build path.
Thought: Could we do that and also support an option for the default language to not have a prefix?
We could also consider a custom setting like BAKERY_USE_I18N
that would set all these efforts into motion and opt-in to the build path prepending of the language codes.
I think we'd also have to figure out how the language template context variable is set before rendering and do that ourselves during the build.
The LANGUAGES
and LANGUAGE_CODE
context variables are set by django.template.context_processors.i18n
. Defining request.LANGUAGE_CODE
in the build()
method should be sufficient to ensure context is properly set (assuming the project uses the i18n context processor).
@clintonb
you are almost correct, but because the default behaviour of the management commands execution is to disable the localization adding LANGUAGE_CODE to the request will have no effect.
# django/core/management/base.py : 302
def execute(self, *args, **options):
"""
Try to execute this command, performing system checks if needed (as
controlled by the ``requires_system_checks`` attribute, except if
force-skipped).
"""
if options['no_color']:
self.style = no_style()
self.stderr.style_func = None
if options.get('stdout'):
self.stdout = OutputWrapper(options['stdout'])
if options.get('stderr'):
self.stderr = OutputWrapper(options['stderr'], self.stderr.style_func)
saved_locale = None
if not self.leave_locale_alone:
# Deactivate translations, because django-admin creates database
# content like permissions, and those shouldn't contain any
# translations.
from django.utils import translation
saved_locale = translation.get_language()
translation.deactivate_all()
So the first solution would be to patch django-bakery changing the leave_locale_alone variable to True upon detecting USE_I18N in the application settings or by a custom option forcing the localization to build management action, in addition to adding LANGUAGE_CODE to all the requests.
The second solution (that I'm currently using), is to activate the localization with the desired language per view with
translation.activate(language_code)
here is a complete example generating pages for each local in the settings in separate folders:
from django.conf import settings
from django.utils import translation
from bakery.views import BuildableTemplateView
class LocalizedBuildableTemplateView(BuildableTemplateView):
def build(self):
if settings.USE_I18N:
original_build_path = self.build_path
for language_code, language in settings.LANGUAGES:
# management commands disable the localization by default
translation.activate(language_code)
# customize your output location
self.build_path = '{}/{}'.format(language_code, original_build_path)
# call the parent build
super(LocalizedBuildableTemplateView, self).build()
else:
super(LocalizedBuildableTemplateView, self).build()
class PublicView(LocalizedBuildableTemplateView):
build_path = 'public.html'
template_name = 'public/index.html'
which will result in this file hierarchy:
├── en
│ └── public.html
└── fr
└── public.html
Thanks for following up. I like your first solution since it is supported by Django and doesn't involve writing a somewhat-redundant (with Django itself) view/mixin.
I think we don't want to prefix locale paths in the build paths as it's up to the developer how to construct their url's (e.g. separate domains / third-party cms's).
It's the LocaleMiddleware
which already sets the LANGUAGE_CODE
and i18nurls
the url routing for you if the developer has put in in place.
In our case we use Wagtail CMS (https://github.com/moorinteractive/wagtail-bakery) where we have separate page tree's already per language. So we don't want to have each page rendered in another language as that page could not exist (e.g. no English contact page, only in Dutch available).