Translated URLs in Django that work simultaneously for all languages

Viewed 215

Given a view defined by a function about_us, I would like it to be accessible by either one of these URLs:

  • /about/
  • /acerca-de/

In a way that requesting any of those activates the corresponding language and renders the view, but both URLs remain accessible at all times regardless of the currently active language.

I would also like to reverse these URLs inside templates using the path name, so reverse('about_us') can give me the URL that corresponds to the currently active language.

Django offers a mechanism for translating URLs by wrapping the string matchers for path objects in gettext_lazy so reverse URL resolution can return the one appropriate for the current language, but AFAIK only one of the URLs works at any given time, depending on the current language.

If I instead define two path objects then I can point them to the same view wrapped by some view decorator that activates the given language first, but then I lose the ability to perform reverse URL resolution and I am forced to perform some ugly tricks to get links to respect the current language.

Has anyone found a solution to this problem?

1 Answers

It could create a common path to dispatch the translated urls to target views. for sake of dispatching url, make use of a register decorater for it.

utils.py

from django.utils.text import slugify
import functools

translated_urls = {}

def register_translated_url(trans_url=''):
    def decorator(viewfunc):
        nonlocal trans_url
        if trans_url and isinstance(trans_url, str):
            trans_url = slugify(trans_url)
            translated_urls[trans_url] = viewfunc
        @functools.wraps(viewfunc)
        def wraped(request, *args, **kwargs):
            return viewfunc(request, *args, **kwargs)
        return wraped
    return decorator

urls.py

# the below urlpatterns must append to the end to capture all slug url
urlpatterns += [
    path('<slug:slug>/', translated_url, name='translated_url'),
]

views.py

from . import utils
from django.http import Http404
# other codes
@utils.register_translated_url(trans_url='blabla')
def postvideo(request):
    pass

def translated_url(request, slug, *args, **kwargs):
    print(utils.translated_urls)
    viewfunc = utils.translated_urls.get(slug)
    if viewfunc:
        return viewfunc(request, *args, **kwargs)
    raise Http404
Related