Issues with multiple languages - django

I want my app will be available in multiple languages (let say two,one is default english and one more).
And these both options available in my home page and there must be a link shown which makes user able to select his choice of language.
I am reading the Django official documentation for this
so any one can let me know the general idea how I can do that.
and one more thing......in settings.py there is default LANGUAGE_CODE = 'en-us' given,BUT as I want my app in more then one language so How i can specify that country code here.
like this works LANGUAGE_CODE = 'en-us','es-MX (Spanish)' or I have to do it in some way.
And what is the purpose of this .po extension in this.

settings.py
LANGUAGE_CODE='en_us'
gettext = lambda s: s
LANGUAGES = (
('en', gettext('English')),
('de', gettext('German')),
)
MIDDLEWARE_CLASSES = (
...
'lang.SessionBasedLocaleMiddleware',
)
lang.py
from django.conf import settings
from django.utils.cache import patch_vary_headers
from django.utils import translation
class SessionBasedLocaleMiddleware(object):
"""
This Middleware saves the desired content language in the user session.
The SessionMiddleware has to be activated.
"""
def process_request(self, request):
if request.method == 'GET' and 'lang' in request.GET:
language = request.GET['lang']
request.session['language'] = language
elif 'language' in request.session:
language = request.session['language']
else:
language = translation.get_language_from_request(request)
for lang in settings.LANGUAGES:
if lang[0] == language:
translation.activate(language)
request.LANGUAGE_CODE = translation.get_language()
def process_response(self, request, response):
patch_vary_headers(response, ('Accept-Language',))
if 'Content-Language' not in response:
response['Content-Language'] = translation.get_language()
translation.deactivate()
return response
Access different languages http://example.com/?lang=de
And finaly let django create your .po files. Heres the documentation for that.

You want internationalization (or localization) of your software. With C it is often done thru gettext (which is related to .po files). Probably django uses these things.

Related

Django: prefix/postfix language slug in i18n_urls

I have a django-cms site, that uses i18n_patterns in urls.py. This works, urls are built like /lang/here-starts-the-normal/etc/.
Now, I would like to have urls like this: /prefix-lang/here-starts.... As there will be a couple of country specific domains, this wille be like /ch-de/here-... for Switzerland/.ch domain, /us-en/here-starts.... for the states, and some more. So, when the url would be /ch-de/..., the LANGUAGE would still be de. Hope this is clear?
As the content is filled with existing LANGUAGES=(('de', 'DE'), ('en', 'EN'), ...), I cannot change LANGUAGES for every domain - no content would be found in the cms, modeltranslation, only to mention those two.
How can I prefix the language slug in i18n_patterns? Is it possible at all?
I think a way without hacking Django too much would be to use URL rewrite facility provided by the webserver you run, for example, for mod_wsgi you can use mod_rewrite, similar facility exists also for uWSGI.
You may need to also post-process the output from Django to make sure that any links are also correctly re-written to follow the new schema. Not the cleanest approach but seems doable.
Working example, though the country/language order is reversed (en-ch instead of ch-en), to have it as django expects it when trying to find a language (ie, setting language to "en-ch", it will find "en", if available).
This solution involves a modified LocaleMiddleware, i18n_patterns, LocaleRegexResolver. It supports no country, or a 2 char country code, setup with settings.SITE_COUNTRY. It works by changing urls to a lang-country mode, but the found language code in middleware will still be language only, 2 chars, and work perfectly with existing LANGUAGES, that contain 2 chars language codes.
custom_i18n_patterns.py - this just uses our new resolver, see below
from django.conf import settings
from ceco.resolvers import CountryLocaleRegexURLResolver
def country_i18n_patterns(*urls, **kwargs):
"""
Adds the language code prefix to every URL pattern within this
function. This may only be used in the root URLconf, not in an included
URLconf.
"""
if not settings.USE_I18N:
return list(urls)
prefix_default_language = kwargs.pop('prefix_default_language', True)
assert not kwargs, 'Unexpected kwargs for i18n_patterns(): %s' % kwargs
return [CountryLocaleRegexURLResolver(list(urls), prefix_default_language=prefix_default_language)]
resolvers.py
import re
from django.conf import settings
from django.urls import LocaleRegexURLResolver
from modeltranslation.utils import get_language
class CountryLocaleRegexURLResolver(LocaleRegexURLResolver):
"""
A URL resolver that always matches the active language code as URL prefix.
extended, to support custom country postfixes as well.
"""
#property
def regex(self):
language_code = get_language() or settings.LANGUAGE_CODE
if language_code not in self._regex_dict:
if language_code == settings.LANGUAGE_CODE and not self.prefix_default_language:
regex_string = ''
else:
# start country changes
country_postfix = ''
if getattr(settings, 'SITE_COUNTRY', None):
country_postfix = '-{}'.format(settings.SITE_COUNTRY)
regex_string = '^%s%s/' % (language_code, country_postfix)
# end country changes
self._regex_dict[language_code] = re.compile(regex_string, re.UNICODE)
return self._regex_dict[language_code]
middleware.py - only very few lines changed, but had to replace the complete process_response.
from django.middleware.locale import LocaleMiddleware
from django.conf import settings
from django.conf.urls.i18n import is_language_prefix_patterns_used
from django.http import HttpResponseRedirect
from django.urls import get_script_prefix, is_valid_path
from django.utils import translation
from django.utils.cache import patch_vary_headers
class CountryLocaleMiddleware(LocaleMiddleware):
"""
This is a very simple middleware that parses a request
and decides what translation object to install in the current
thread context. This allows pages to be dynamically
translated to the language the user desires (if the language
is available, of course).
"""
response_redirect_class = HttpResponseRedirect
def process_response(self, request, response):
language = translation.get_language()
language_from_path = translation.get_language_from_path(request.path_info)
urlconf = getattr(request, 'urlconf', settings.ROOT_URLCONF)
i18n_patterns_used, prefixed_default_language = is_language_prefix_patterns_used(urlconf)
if (response.status_code == 404 and not language_from_path and
i18n_patterns_used and prefixed_default_language):
# Maybe the language code is missing in the URL? Try adding the
# language prefix and redirecting to that URL.
# start country changes
language_country = language
if getattr(settings, 'SITE_COUNTRY', None):
language_country = '{}-{}'.format(language, settings.SITE_COUNTRY)
language_path = '/%s%s' % (language_country, request.path_info)
# end country changes!
path_valid = is_valid_path(language_path, urlconf)
path_needs_slash = (
not path_valid and (
settings.APPEND_SLASH and not language_path.endswith('/') and
is_valid_path('%s/' % language_path, urlconf)
)
)
if path_valid or path_needs_slash:
script_prefix = get_script_prefix()
# Insert language after the script prefix and before the
# rest of the URL
language_url = request.get_full_path(force_append_slash=path_needs_slash).replace(
script_prefix,
'%s%s/' % (script_prefix, language_country),
1
)
return self.response_redirect_class(language_url)
if not (i18n_patterns_used and language_from_path):
patch_vary_headers(response, ('Accept-Language',))
if 'Content-Language' not in response:
response['Content-Language'] = language
return response

How do I change the local path of a language in Django?

I have a web set up with 3 languages (['es', 'en', 'it']) ​​in Angular that works with the Django server.
Django by default has the English local path defined as /en, I want the url of the English configuration to be '/us' (by default it is '/ en'), I just want to change it for English, for 'es' or 'it' as it comes by default is fine.
I want the URL to look like this myurl.com/us in English, how would you recommend me to make this change?
The structure is the following:
-apps
--webapp
---templates
----webapp
-----en (inside index.html)
-----es (inside index.html)
-----it (inside index.html)
-conf
--settings.py
-middleware
--locale.py
conf.settings.py have this language configuration
LANGUAGES = (
('es', _('Spanish')),
('it', _('Italian')),
('en', _('English')),
)
LANGUAGE_CODE = 'es'
LANGUAGE_CODES = [language[0] for language in LANGUAGES]
Additionally I have configured a middleware to recognize the user's location and place the corresponding language code in the URL
from django.conf import settings
from .utils.geolocation import get_language_by_ip
cookie_name = settings.LANGUAGE_COOKIE_NAME
class LocalizationMiddleware(object):
def get_language_cookie(self, request):
return request.COOKIES.get(cookie_name)
def set_language_cookie(self, request, value):
request.COOKIES[cookie_name] = value
def get_i18n_url_language(self, request):
url = request.path.split('/')
if len(url) > 1 and len(url[1].split('-')[0]) == 2:
return url[1]
return None
def process_request(self, request):
language = self.get_i18n_url_language(request)
if language is not None and language not in settings.LANGUAGE_CODES:
return
if language is None:
language = self.get_language_cookie(request)
if language is None:
language = get_language_by_ip(request)
if language is None:
language = settings.LANGUAGE_CODE
self.set_language_cookie(request, language)
return None
def process_response(self, request, response):
response.set_cookie(cookie_name, request.COOKIES.get(cookie_name, settings.LANGUAGE_CODE))
return response
This all works fine, however I want the url for the English language to change from .../en to .../us

How to replace LocaleRegexURLResolver from django 1.11

I am currently upgrading Django from 1.11 to 2.0 (to 2.2 in the long run). But recently I bumped into a problem which a can't solve for quiet some time. LocaleRegexURLResolver has been removed in 2.0 without any warning and the whole code has been refactored. Sadly we were using LocaleRegexURLResolver and I am not sure how to replicate it's functionality in the current version of Django. Any ideas?
class SiteLocaleRegexURLResolver(LocaleRegexURLResolver):
"""
Overrides LocaleRegexURLResolver to use specified default language
by site instead of global default language
"""
def __init__(
self, urlconf_name, site, default_kwargs=None, app_name=None, namespace=None,
prefix_default_language=True
):
super(LocaleRegexURLResolver, self).__init__(
None, urlconf_name, default_kwargs, app_name, namespace,
)
self.prefix_default_language = prefix_default_language
self.default_language = site.language_code
#property
def regex(self):
language_code = get_language() or self.default_language
if language_code not in self._regex_dict:
if language_code == self.default_language and not self.prefix_default_language:
regex_string = ''
else:
regex_string = '^%s/' % language_code
self._regex_dict[language_code] = re.compile(regex_string, re.UNICODE)
return self._regex_dict[language_code]
Basically it changes the default language. In UK, site /docs/ would be in english and /fr/docs/ in french. In FR on the other hand, /docs/ would be in french and /uk/docs/ in english

Take language code from session in Django

I use i18n_patterns
What should I do so that http://localhost:8000 didn't redirect to url prefixed with language code?
In addition, I want to supply language, taken from session, not request.LANGUAGE_CODE
I found following code:
class NoPrefixLocaleRegexURLResolver(LocaleRegexURLResolver):
#property
def regex(self):
language_code = get_language()
if language_code not in self._regex_dict:
regex_compiled = (re.compile('' % language_code, 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]
However, there is problem with that code in checking if language_code == settings.LANGUAGE_CODE. If I enter http://localchost:8000, it will not redirect, but supply a page with translation from settings.LANGUAGE_CODE instead of request.session.get('django_language'). As I understood, I can't access request, so what should be done?

Django: How can I localize my urls?

How can I localize my urls in Django?
url(u'^{0}/$'.format(_('register')), RegisterView.as_view(), name='register'),
I tried the above but it only seems to work when I stop and start the server. I guess that the urls are translated when the application start.
So if there a way to solve this?
It's a bit more complicated than just throwing _() in urls.py. You have spotted the reason yourself: The URLs are evaluated once, when Django starts, and not for every request. Therefore you will have to
a) put every possible translation in urls.py, or
b) implement routing yourself
A. All in urls.py
url('hello', hello, name="hello_en"),
url('hallo', hello, name="hello_de"),
url('buenos_dias', hello, name="hello_es"),
Obviously not a nice solution, but it works for small projects.
B. Implementing routing
That has it's own drawback, especially when it comes to use reverse(). However, it works in principle:
urls.py:
#...
url('(?<path>.+)', dispatcher),
#...
views.py:
def dispatcher(request, path):
if path == "hallo":
lang = "de"
elif path == "buenos_dias":
lang = "de"
else:
lang = "en"
Of course, you can make the lookup more intelligent, but then you have to make preassumptions:
# if request.session['language'] can be trusted:
def dispatcher(request, path):
list_of_views = ['contact', 'about', 'foo']
v = None
for view in list_of_views:
if _(view) == path:
v = view
break
if v is None:
# return 404 or the home page
Internationalization of URLs has been introduced in django 1.4
see https://docs.djangoproject.com/en/dev/topics/i18n/translation/#url-internationalization
this is exactly what you are looking for