Switch language in Django with the translated url redirect

后端 未结 2 1542
甜味超标
甜味超标 2020-12-18 11:09

I have internationalization correctly installed.

It\'s works with urls like:

/en/bookings/ #English
/es/reservas/ #Spanish

In the h

相关标签:
2条回答
  • 2020-12-18 11:35

    When I had the same problem, I implemented a custom template tag (current_url) that, given the request in context, re-renders the url for the active language:

    {% load custom_tags %}
    <ul>
    {% get_language_info_list for LANGUAGES as languages %}
    {% for language in languages %}
        {# IMPORTANT! enclose the 'current_url' tag in a 'language' block #}
        {% language language.code %}
            <li {% if language.code == LANGUAGE_CODE %}class="active"{% endif %}>
                <a href="{% current_url %}">{{ language.name_local }}</a>
            </li>
        {% endlanguage %}
    {% endfor %}
    </ul>
    

    Here is the code for the custom tag (custom_tags.py):

    import six
    import sys
    from django.template import Node, TemplateSyntaxError, Library
    from django.conf import settings
    
    register = Library()
    
    class CurrentURLNode(Node):
    
        def __init__(self, asvar=None):
            self.asvar = asvar
    
        def render(self, context):
            request = context['request']
            from django.core.urlresolvers import reverse, NoReverseMatch
            url = ''
            try:
                url = reverse(request.resolver_match.view_name, args=request.resolver_match.args, kwargs=request.resolver_match.kwargs, current_app=context.current_app)
            except NoReverseMatch:
                exc_info = sys.exc_info()
                if settings.SETTINGS_MODULE:
                    project_name = settings.SETTINGS_MODULE.split('.')[0]
                    try:
                        url = reverse(project_name + '.' + request.resolver_match.view_name,
                              args=request.resolver_match.args, kwargs=request.resolver_match.kwargs,
                              current_app=context.current_app)
                    except NoReverseMatch:
                        if self.asvar is None:                      
                            six.reraise(*exc_info)
                else:
                    if self.asvar is None:
                        raise
    
            if self.asvar:
                context[self.asvar] = url
                return ''
            else:
                return url
    
    @register.tag
    def current_url(parser, token):
        bits = token.split_contents()
        bits = bits[1:]
        asvar = None
        if len(bits) >= 2 and bits[-2] == 'as':
            asvar = bits[-1]
            bits = bits[:-2]
        if len(bits):
            raise TemplateSyntaxError("Unexpected arguments to current_url tag")
        return CurrentURLNode(asvar)
    

    There is no need to use the 'set_language' django view. There is no need to make a POST request to change the active language. With only html archors linking all your internationalized content together, it's better for SEO.

    0 讨论(0)
  • 2020-12-18 11:45

    I had similar problem so I sending my resolution to save Your time.

    main(urls.py)

    from django.conf.urls import include, url
    from django.conf.urls.i18n import i18n_patterns
    
    urlpatterns = [
        url(r'^i18n/', include('django.conf.urls.i18n')), 
    ]
    
    urlpatterns += i18n_patterns(
        url(r'^', include('index.urls', namespace='index')),
    )
    

    (index.urls.py)

    from django.conf.urls import url
    from django.views.generic import TemplateView
    from django.utils.translation import ugettext_lazy as _
    
    
    urlpatterns = [
        url(r'^$', TemplateView.as_view(template_name='index/index.html'), name='index'),
        url(_(r'^python-programming/$'), TemplateView.as_view(template_name='index/new_page.html'),
            name='new_page'),
    ]
    

    Creating template tag to return urls for current location in all languages that we support (index.templatetags.helper_tags.py)

    from django.template import Library
    from django.core.urlresolvers import resolve, reverse
    from django.utils.translation import activate, get_language
    
    register = Library()
    
    
    @register.simple_tag(takes_context=True)
    def change_lang(context, lang=None, *args, **kwargs):
        """
        Get active page's url by a specified language
        Usage: {% change_lang 'en' %}
        """
    
        path = context['request'].path
        url_parts = resolve(path)
    
        url = path
        cur_language = get_language()
        try:
            activate(lang)
            url = reverse(url_parts.view_name, kwargs=url_parts.kwargs)
        finally:
            activate(cur_language)
    
        return "%s" % url
    

    Creating middleware to change site language when user will click at alternative link to this sub site but in different language (middleware.py)

    from django.utils import translation
    from django.conf import settings
    from django.utils.deprecation import MiddlewareMixin
    
    
    class LangBasedOnUrlMiddleware(MiddlewareMixin):
    
        @staticmethod
        def process_request(request):
    
            if hasattr(request, 'session'):
                active_session_lang = request.session.get(translation.LANGUAGE_SESSION_KEY)
    
                if active_session_lang == request.LANGUAGE_CODE:
                    return
    
                if any(request.LANGUAGE_CODE in language for language in settings.LANGUAGES):
                    translation.activate(request.LANGUAGE_CODE)
                    request.session[translation.LANGUAGE_SESSION_KEY] = request.LANGUAGE_CODE
    

    Adding it to (settings.py) just after LocaleMiddleware

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.locale.LocaleMiddleware',
        'our_app.middleware.LangBasedOnUrlMiddleware',
    ]
    

    Sample usage in template:

    {% load i18n %}
    {% load helper_tags %}
        {% get_available_languages as languages %}
        {% for lang_code, lang_name in languages %}
            <a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{% change_lang lang_code %}">
        {% endfor %}
    
    0 讨论(0)
提交回复
热议问题