wiki:Proposals/I18NURLs

I18N URLs

Motivation

We need to solve problem of different URLs depending of site language.

If your customer want a Spanish based site, he will want URLs like:

  • http://yoursite.com/noticias/ (instead of /news/).
  • http://yoursite.com/mi-seccion/ (instead of /my-section/).

Assumptions

We will assume one URL (permalink) for one object. When you decide to put settings.LANGUAGE_CODE = 'es' this language will be used in reversed URLs.

Proposal & Implementation

We propose attack this problem with three new features.

Plugin url_prefix configurated by manager

Now a existing plugin can configurated as follows:

class PluginConfig(Plugin):
    name = 'News'

    url_prefixes = (
        ('news', 'plugins.news.urls'),
    )

Once you install and activates this plugin, Merengue internally will add the URL prefix news like here:

    urlpatterns += patterns('',
      (r'^news/', include('plugins.news.urls')),
    )

Proposal: We propose url_prefixes was configured by manager after plugin installation. The plugin definition will change to:

class PluginConfig(Plugin):
    name = 'News'

    initial_url_prefixes = (
        ('news', 'plugins.news.urls'),
    )

    def _get_url_prefixes(self):
        ... # get url prefixes from database
    url_prefixes = property(_get_url_prefixes)

Translatable url function

Now you can have something like this:

from django.conf.urls.defaults import patterns, url

urlpatterns = patterns('plugins.news.views',
    url(r'^$', 'news_index', name='news_index'),
    url(r'^year/(?P<year>\d{4})/month/(?P<month>\d{1,2})/day/(?P<day>\d{1,2})/$', 'news_by_date'),
    url(r'^(?P<newsitem_slug>[\w-]+)/$', 'newsitem_view', name='newsitem_view'),
    url(r'^category/(?P<newscategory_slug>[\w-]+)/$', 'newsitem_by_category_view', name='newsitem_by_category_view'),
)

Proposal: We propose a translatable function url

from django.conf.urls.defaults import patterns, url

def merengue_url(regex, view, kwargs=None, name=None, prefix=''):
    if isinstance(regex, dict):
        regex_translatable = regex.get(settings.LANGUAGE_CODE)
    else:
        regex_translatable = regex
    return url(regex_translatable, view, kwargs, name, prefix)

And you will be able to write a file urls.py likes this:

from django.conf.urls.defaults import patterns
from merengue.XXX import merengue_url as url

urlpatterns = patterns('plugins.news.views',
    url(r'^$', 'news_index', name='news_index'),
    url({'es': r'^anual/(?P<year>\d{4})/mes/(?P<month>\d{1,2})/día/(?P<day>\d{1,2})/$',
         'en': r'^year/(?P<year>\d{4})/month/(?P<month>\d{1,2})/day/(?P<day>\d{1,2})/$'},
         'news_by_date'),
    url(r'^(?P<newsitem_slug>[\w-]+)/$', 'newsitem_view', name='newsitem_view'),
    url({'en': r'^category/(?P<newscategory_slug>[\w-]+)/$',
         'es': r'^categoria/(?P<newscategory_slug>[\w-]+)/$'},
        'newsitem_by_category_view', name='newsitem_by_category_view'),
)

Note: a important fact is url is calculated in import time. Once you defines settings.LANGUAGE_CODE and run development/production server, url will be unique and only one. You need this behaviour for maintain django.core.urlresolvers.reverse function intacted.