11👍
UPDATE: Read answer bellow, Django 1.10 supports it natively
I faced this problem and solved this way:
-
Created an alternative
i18n_patterns
that do not prefix the site main language (defined insettings.LANGUAGE_CODE
). -
Created an alternative middleware that only uses the URL prefixes language to activate the current language.
I didn’t see any side-effect using this technique.
The code:
# coding: utf-8
"""
Cauê Thenório - cauelt(at)gmail.com
This snippet makes Django do not create URL languages prefix (i.e. /en/)
for the default language (settings.LANGUAGE_CODE).
It also provides a middleware that activates the language based only on the URL.
This middleware ignores user session data, cookie and 'Accept-Language' HTTP header.
Your urls will be like:
In your default language (english in example):
/contact
/news
/articles
In another languages (portuguese in example):
/pt/contato
/pt/noticias
/pt/artigos
To use it, use the 'simple_i18n_patterns' instead the 'i18n_patterns'
in your urls.py:
from this_sinppet import simple_i18n_patterns as i18n_patterns
And use the 'SimpleLocaleMiddleware' instead the Django's 'LocaleMiddleware'
in your settings.py:
MIDDLEWARE_CLASSES = (
...
'this_snippet.SimpleLocaleMiddleware'
...
)
Works on Django >=1.4
"""
import re
from django.conf import settings
from django.conf.urls import patterns
from django.core.urlresolvers import LocaleRegexURLResolver
from django.middleware.locale import LocaleMiddleware
from django.utils.translation import get_language, get_language_from_path
from django.utils import translation
class SimpleLocaleMiddleware(LocaleMiddleware):
def process_request(self, request):
if self.is_language_prefix_patterns_used():
lang_code = (get_language_from_path(request.path_info) or
settings.LANGUAGE_CODE)
translation.activate(lang_code)
request.LANGUAGE_CODE = translation.get_language()
class NoPrefixLocaleRegexURLResolver(LocaleRegexURLResolver):
@property
def regex(self):
language_code = get_language()
if language_code not in self._regex_dict:
regex_compiled = (re.compile('', re.UNICODE)
if language_code == settings.LANGUAGE_CODE
else re.compile('^%s/' % language_code, re.UNICODE))
self._regex_dict[language_code] = regex_compiled
return self._regex_dict[language_code]
def simple_i18n_patterns(prefix, *args):
"""
Adds the language code prefix to every URL pattern within this
function, when the language not is the main language.
This may only be used in the root URLconf, not in an included URLconf.
"""
pattern_list = patterns(prefix, *args)
if not settings.USE_I18N:
return pattern_list
return [NoPrefixLocaleRegexURLResolver(pattern_list)]
The code above is available on:
https://gist.github.com/cauethenorio/4948177
16👍
I used solid-i18n-url to solve similar problem:
https://github.com/st4lk/django-solid-i18n-urls
Nice description how it works located here:
http://www.lexev.org/en/2013/multilanguage-site-django-without-redirects/
13👍
Django 1.10 supports it natively. As they say in the doc:
i18n_patterns(*urls, prefix_default_language=True)
This function can be used in a root URLconf and Django will automatically prepend the current active language code to all url patterns defined within
i18n_patterns()
.Setting prefix_default_language to False removes the prefix from the default language (
LANGUAGE_CODE
). This can be useful when adding translations to existing site so that the current URLs won’t change.
Source: https://docs.djangoproject.com/en/1.10/topics/i18n/translation/#language-prefix-in-url-patterns
- Django – settings.py seems to load multiple times?
- Schedule number of web dynos by time of day
- Tracking changes to all models in Django
- Django – Delete file from amazon S3
- What method attributes are used in Django?
0👍
Since Django 1.10 there is a prefix_default_language parameter you can specify in i18n_patterns()
.
OP says that he doesn’t want to use a prefix for the default language, so he sets prefix_default_language=False
. However by doing that you are losing one nice feature provided by the LocaleMiddleware
which is automatically redirecting the user to the version of the website in his preferred language. You only have this behavior when you set prefix_default_language=True
.
In my case I wanted to preserve this functionality. Here I’m sharing a workaround I found to this problem, highly inspired by the mentioned django-solid-i18n-urls
module and updated to newer Django. Tested and works on Django 3.2.
# urlresolvers.py
from django.conf import settings
from django.urls import LocalePrefixPattern, URLResolver
from django.utils.translation import get_language
def solid_i18n_patterns(*urls, prefix_default_language=True):
"""
Same as i18n_patterns but uses SolidLocalePrefixPattern instead of LocalePrefixPattern
"""
if not settings.USE_I18N:
return list(urls)
return [
URLResolver(
SolidLocalePrefixPattern(prefix_default_language=prefix_default_language),
list(urls),
)
]
class SolidLocalePrefixPattern(LocalePrefixPattern):
"""
Based on django-solid-i18n-urls.
"""
@property
def language_prefix(self):
language_code = get_language() or settings.LANGUAGE_CODE
if language_code == settings.LANGUAGE_CODE:
return ""
else:
return "%s/" % language_code
# Original:
"""
if language_code == settings.LANGUAGE_CODE and not self.prefix_default_language:
return ""
else:
return "%s/" % language_code
"""
# urls.py
from .urlresolvers import solid_i18n_patterns
# And replace i18n_patterns by solid_i18n_patterns
- Django runserver error when specifying port
- How to test django caching?
- Can i get models field type from a model queryset in Django?
- TimeField format in Django template