django-bakery icon indicating copy to clipboard operation
django-bakery copied to clipboard

i18n localization support

Open palewire opened this issue 8 years ago • 9 comments

palewire avatar Nov 13 '15 06:11 palewire

One thing to consider might be posting an additional Content-Language header when we upload to S3.

palewire avatar Jan 20 '16 00:01 palewire

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.

palewire avatar Jan 20 '16 00:01 palewire

Thought: Could we do that and also support an option for the default language to not have a prefix?

palewire avatar Jan 20 '16 00:01 palewire

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.

palewire avatar Jan 20 '16 00:01 palewire

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.

palewire avatar Jan 21 '16 00:01 palewire

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 avatar Jul 21 '16 02:07 clintonb

@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

Chedi avatar Apr 23 '17 22:04 Chedi

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.

clintonb avatar Apr 23 '17 22:04 clintonb

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).

robmoorman avatar May 11 '17 07:05 robmoorman