Translated URL's

97 views
Skip to first unread message

Felipe Mesquita de Oliveira

unread,
Feb 7, 2014, 4:29:18 PM2/7/14
to django...@googlegroups.com
Hi all,


I'm trying to work with translated URL's, but the behavior  I'm getting is not the one I expected.

Part of the code is below:

from django.utils.translation import ugettext_lazy as _

urlpatterns += patterns('',
             url(_(r'^help/$'), HelpView.as_view(), name='HelpView'),
             url(_(r'^new/'), include('News.urls')),  # two views inside this include: "/page-one/" and "page-two"
)


Imagining that I have English (en) and Spanish (es), the possible URL's would be:

/help/
/ayuda/
/news/
/news/page-one/
/news/page-two/
/noticias/
/noticias/pagina-um/
/noticias/pagina-dos/


Ok..
When I reverse "HelpView", if user language is set to 'en', I would get '/help/', and if user's language is 'es', I would get '/ayuda/'.
But, if the user with language set to 'es' access '/help/' (which is 'en'), I wanted the user to be able to see the page, but I'm getting Http-404 error.

Actually, even if the user (somehow) get to '/news/pagina-um', I wanted him to see the page (rendered using his/her language setting), and not Http404.

Thanks for any help, and if I was not clear, please let me know.

Regards,
Felipe
(Sp/Bra)





werefrog

unread,
Feb 8, 2014, 1:23:39 AM2/8/14
to django...@googlegroups.com
Hello,

I don't know where you're trying the troublesome reverse but maybe the
following can help.


# myproject.urls

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

from help.views import HelpView


urlpatterns = patterns('',
#
)

urlpatterns += i18n_patterns('',
url(_(r'^help/$'), HelpView.as_view(), name='help-view')),
url(_(r'^news/'), include('news.urls')), # can add namespace
)


# news.urls

from django.conf.urls import patterns, url
from django.utils.translation import ugettext_lazy as _
from .views import PageOneView, PageTwoView


urlpatterns = patterns('',
url(_(r'^$'), PageOneView.as_view(), name='news'),
url(_(r'^page-one/$'), PageOneView.as_view(), name='news-page-one'),
url(_(r'^page-two/$'), PageTwoView.as_view(), name='news-page-two'),
)

# test.py

from django.utils.translation import activate

activate('es')
#...


# resulting urls

/en/help/
/es/ayuda/

/en/news/
/en/news/page-one/
/en/news/page-two/
/es/noticias/
/es/noticias/pagina-um/
/es/noticias/pagina-dos/

Of course, you need to translate to spanish.

#
https://docs.djangoproject.com/en/dev/topics/i18n/translation/#message-files
python manage.py makemessages -l es
# python manage.py makemessages -a

# translate resulting file then …

#
https://docs.djangoproject.com/en/dev/topics/i18n/translation/#compiling-message-files
python manage.py compilemessages

Regards,
Michel

Felipe Mesquita de Oliveira

unread,
Feb 10, 2014, 12:22:24 PM2/10/14
to django...@googlegroups.com
Michel,


Thanks for you reply. 
My ideia was to make it without the '/es/' or '/en/' starting the url.

Let's say a user share an 'es' link to an american user.
Like this:  '/ayuda/'
I wanted the american user to be able to open it using language defined in user's session ('en').

Thanks in advance,
Felipe

werefrog

unread,
Feb 11, 2014, 9:18:03 PM2/11/14
to django...@googlegroups.com
Felipe,

Well, if you don't prefix your urls with language code, Django will try
to match translated urls in the language retained for the session [1]
(black-box guessing).

I see multiple options, but the following is the less messy and seems to
fit your requirements:

# myproject.urls

from django.conf.urls import patterns, url
from django.utils.translation import ugettext_lazy as _

from help.views import HelpView


urlpatterns = patterns('',
url(_(r'^help/$'), HelpView.as_view(), name='help-view')),
url(r'^(help|ayuda)/$', HelpView.as_view())),
)

You keep first the translated named url for "reverse" sake then you add a forgiving pattern pointing to the right view.

Anyway, I found usefull to experience the localised rendering for different reasons (specific additions as legal informations, etc.) and you can easily propose a language selection "widget". I find also the prefix good for many reasons but you probably have your own ;)

Regards,

Michel

[1]
https://docs.djangoproject.com/en/dev/topics/i18n/translation/#how-django-discovers-language-preference

Felipe Mesquita de Oliveira

unread,
Feb 12, 2014, 1:33:32 PM2/12/14
to django...@googlegroups.com
Michel,

Thanks again, for your availability in helping me.

Actually, that was almost what I have been doing, except that I was not working with '( option1 | option2 )' regex. I was adding one language each line, but works the same.
Like this:
                        url(_(r'^planos/$'), WebSitePlanosView.as_view(), name='WebSitePlanosView'),
                        url(r'^planos/$', WebSitePlanosView.as_view()),
                        url(r'^plans/$', WebSitePlanosView.as_view()),

The problem is when I have the 'include's:
                        url(r'^suporte/', include('WebSuporte.urls', )), # pt_BR, es
                        url(r'^support/', include('WebSuporte.urls', )), # en
                        url(_(r'^suporte/'), include('WebSuporte.urls')),
In this cases my tests showed that the 'translated' should come last, or the reverse won't respect the user's language when choosing the url to show.

Of course this is a solution, but I was wondering if it has a DRY way of doing this, since I haven't found on the docs, mainly because of the maintenance when adding a language, for example, that would make changing both translation files and all urls.py.

Thanks for you time and attention, if an new solution raises, it would be great!

Felipe


werefrog

unread,
Feb 19, 2014, 11:14:31 PM2/19/14
to django...@googlegroups.com
Felipe,

Sorry, I'm quite busy these days.

Here is the beginning of something, but I'd prefer to avoid the 'myurl'
function. I'm not a dev' so you'll probably jump looking at that.

The base idea was to use only 'mypatterns' for obtainning the same
results we handwritten previously, including the ordering observation
you did. However, I cannot currently figure how to modify the url call,
that's why I had to use 'myurl'.

The following mess mostly butchered url and patterns functions normally
used.

It needs testing and that's quite raw but I'll take a look this week-end
probably. The don't think I handled 'prefix' variable how it should be
but that's for waiting ;)

# urls.py

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

urlpatterns = patterns('',
#
)
urlpatterns += mypatterns('',
myurl(_(r'^suporte/'), include('WebSuporte.urls') ),
)


# imbadwithnamestoo.utils

from django.conf import settings
from django.conf.urls import url
from django.utils.translation import activate, deactivate
from django.utils.translation import ugettext


def myurl(regex, view, kwargs=None, name=None, prefix=''):
return (regex, view, kwargs, name, prefix)

def mypatterns(prefix, *args):
pattern_list = []
for t in args:
# dealing with include or others
regex, view, kwargs, name, prefix = t

languages = [lang[0] for lang in settings.LANGUAGES]

if isinstance(view, (list,tuple)):
# For include(...) processing.
for lang in languages:
activate(lang)
translated_regex = ugettext(regex)
pattern_list.append(url(translated_regex, view, kwargs,
None, prefix))
deactivate()
pattern_list.append(url(regex, view, kwargs, name, prefix))
else:
pattern_list.append(url(regex, view, kwargs, name, prefix))
for lang in languages:
activate(lang)
translated_regex = ugettext(regex)
pattern_list.append(url(translated_regex, view, kwargs,
None, prefix))
deactivate()

return pattern_list

Regards,
Michel

Reply all
Reply to author
Forward
0 new messages