Internationalization in URL Patterns

Django provides two mechanisms to internationalize URL patterns:

  • Adding the language prefix to the root of the URL patterns to make it possible for LocaleMiddleware to detect the language to activate from the requested URL.
  • Making URL patterns themselves translatable via the django.utils.translation.ugettext_lazy() function.

Using either one of these features requires that an active language be set for each request; in other words, you need to have django.middleware.locale.LocaleMiddleware in your MIDDLEWARE_CLASSES setting.

Language Prefix in URL Patterns

This function can be used in your root URLconf and Django will automatically prepend the current active language code to all url patterns defined within i18n_patterns(). Example URL patterns:

from django.conf.urls import include, url
from django.conf.urls.i18n import i18n_patterns
from about import views as about_views
from news import views as news_views
from sitemap.views import sitemap

urlpatterns = [
    url(r'^sitemap\.xml$', sitemap, name='sitemap_xml'),
]

news_patterns = [
    url(r'^$', news_views.index, name='index'),
    url(r'^category/(?P<slug>[\w-]+)/$', 
        news_views.category,
        name='category'),
    url(r'^(?P<slug>[\w-]+)/$', news_views.details, name='detail'),
]

urlpatterns += i18n_patterns(
    url(r'^about/$', about_views.main, name='about'),
    url(r'^news/', include(news_patterns, namespace='news')),
)

After defining these URL patterns, Django will automatically add the language prefix to the URL patterns that were added by the i18n_patterns function. Example:

>>> from django.core.urlresolvers import reverse
>>> from django.utils.translation import activate
>>> activate('en')
>>> reverse('sitemap_xml')
'/sitemap.xml'
>>> reverse('news:index')
'/en/news/'

>>> activate('nl')
>>> reverse('news:detail', kwargs={'slug': 'news-slug'})
'/nl/news/news-slug/'

i18n_patterns() is only allowed in your root URLconf. Using it within an included URLconf will throw an ImproperlyConfigured exception.

Translating URL Patterns

URL patterns can also be marked translatable using the ugettext_lazy() function. Example:

from django.conf.urls import include, url
from django.conf.urls.i18n import i18n_patterns
from django.utils.translation import ugettext_lazy as _

from about import views as about_views
from news import views as news_views
from sitemaps.views import sitemap

urlpatterns = [
    url(r'^sitemap\.xml$', sitemap, name='sitemap_xml'),
]

news_patterns = [
    url(r'^$', news_views.index, name='index'),
    url(_(r'^category/(?P<slug>[\w-]+)/$'), 
        news_views.category,
        name='category'),
    url(r'^(?P<slug>[\w-]+)/$', news_views.details, name='detail'),
]

urlpatterns += i18n_patterns(
    url(_(r'^about/$'), about_views.main, name='about'),
    url(_(r'^news/'), include(news_patterns, namespace='news')),
)

After you’ve created the translations, the reverse() function will return the URL in the active language. Example:

from django.core.urlresolvers import reverse
from django.utils.translation import activate

>>> activate('en')
>>> reverse('news:category', kwargs={'slug': 'recent'})
'/en/news/category/recent/'

>>> activate('nl')
>>> reverse('news:category', kwargs={'slug': 'recent'})
'/nl/nieuws/categorie/recent/'

In most cases, it’s best to use translated URLs only within a language-code-prefixed block of patterns (using i18n_patterns()), to avoid the possibility that a carelessly translated URL causes a collision with a non-translated URL pattern.

Reversing in Templates

If localized URLs get reversed in templates, they always use the current language. To link to a URL in another language use the language template tag. It enables the given language in the enclosed template section:

{% load i18n %}

{% get_available_languages as languages %}

{% trans "View this category in:" %}
{% for lang_code, lang_name in languages %}
    {% language lang_code %}
    <a href="{% url 'category' slug=category.slug %}">{{
lang_name }}</a>
    {% endlanguage %}
{% endfor %}
The `language` tag expects the language code as the only argument.