Reputation: 111
settings.py:
INSTALLED_APPS = [
...,
'modeltranslation',
]
TIME_ZONE = 'Europe/Belgrade'
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGES = (
('en-us', _('English')),
('hu', _('Hungarian')),
('sr-latn', _('Serbian')),
)
LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale'),
os.path.join(BASE_DIR, 'books', 'locale'),
)
urls.py:
urlpatterns = [
url(r'^i18n/', include('django.conf.urls.i18n')),
]
urlpatterns += i18n_patterns(
url(_r('^books/'), include('books.urls', namespace='books'))
)
My default language is english. My model has 3 title fields for each language. It is how modeltranslation package works i.e.:
(title_en, title_hu, title_sr_latn)
Since I use slug field for url representation of an instance of the model in the url, I have 3 slug fileds for each language accordingly in my model class too.
I don't see any sence that my url should look something like this on hungarian for example:
127.0.0.1/hu/konyvek/learn-django
I want my urls to look like this:
English url (I don't want to have language prefix for the default language!):
127.0.0.1/books/the-lord-of-the-rings
Hungarian url:
127.0.0.1/hu/konyvek/a-gyuruk-ura
Serbian url (it is unfortunate that serbian language prefix looks extreamly ugly but that is another topic):
127.0.0.1/sr-latn/knjige/gospodar-prstenova
I couldn't find anything so far that solves this problem.
It is obvious that I can't use either of these in my language switching 'next' form element's value in template:
{{ request.path }}
or {{ request.get_absolute_path|slice:'3:' }}
So I excluded the 'next' element temporarily.
When I'm switching languages, on my front page everything works well.
If I go to a books page for example (/hu/konyvek/)
, it shows the language properly but if I want from there to change to a different language it doesn't let me do it.
It just reloads the current page.
Any suggestion how to accomplish this?
Upvotes: 2
Views: 2095
Reputation: 111
For now, I couldn't find any elegant way of solving this problem. I have now an ugly solution that works temporarily and only on this project, because it is hard-coded.
I found this code at https://djangosnippets.org/snippets/2875/
@register.simple_tag(takes_context=True)
def change_lang(context, lang=None, *args, **kwargs):
path = context['request'].path
url_parts = resolve( 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
But this solution solved only half of my problem. It took the translation of the 'book/' part of the url correctly, but the slug part e.i. 'the-lord-of-the-rings/' remained old, so. django couldn't resolve the url path because language was switched, first level of the url is changed but there is no such a thing in urlconf like, e.i. 'konyvek/the-lord-of-the-rings/'.
I have changed a code a little bit:
@register.simple_tag(takes_context=True)
def change_lang(context, lang=None, *args, **kwargs):
path = context['request'].path
url_parts = resolve(path)
cur_language = get_language()
try:
translation.activate(lang)
if 'book' in context:
slug = context['book'].slug
url = reverse(url_parts.view_name, kwargs={'slug': slug})
else:
url = reverse(url_parts.view_name, kwargs=url_parts.kwargs)
finally:
translation.activate(cur_language)
return '%s' % url
"Luckily", context list has the object instance called 'book', so I could use it to choose the appropriate Slugfield after I activated the new language then forwarded it to kwargs in reverse function.
Maybe better choice would be to write middleware then custom tag.
Anyway, for now it works, but I welcome if anyone has or finds much nicer and general solution for this.
It seems very strange the there is no out of the box solution for this problem.
But maybe I'm wrong and just can't find it.
Upvotes: 1