Internationalization, some problems with switching languages - django

I have a site in English and want to add Russian.
settings.py
LANGUAGE_CODE = 'en'
LANGUAGES = (
('en', ('English')),
('ru', ('Russian')), )
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware', )
urls.py
url(r'^i18n/', include('django.conf.urls.i18n')),
Simple form grom django docs
> <form action="/i18n/setlang/" method="post" id="language-select">
> <input name="next" type="hidden" value="/" />
> {% csrf_token %}
> <select name="language">
> {% for lang in LANGUAGES %}
> <option value="{{ lang.0 }}">{{ lang.1 }}</option>
> {% endfor %}
> </select>
> <input type="submit" value="Go" /> </form>
I install gettext, add 'locale' folder (in project folder, near manage.py). Create 'ru folder' with .po file and add some translations. But after language changing it returns [26/Jul/2013 13:43:32] "POST /i18n/setlang/ HTTP/1.1" 302 0 and redirect to English page. What's wrong here?

You have to put django.middleware.locale.LocaleMiddleware after django.contrib.sessions.middleware.SessionMiddleware and before django.middleware.common.CommonMiddleware
Example:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
)
https://docs.djangoproject.com/en/dev/topics/i18n/translation/#how-django-discovers-language-preference

Did you use i18n_patterns in the urls.py for the URL that support both languages?
from django.conf.urls import include, url
from django.conf.urls.i18n import i18n_patterns
urlpatterns += i18n_patterns(
url(r'^about/$', views.anything, name='about'),
)
https://docs.djangoproject.com/en/1.9/topics/i18n/translation/#language-prefix-in-url-patterns

Related

Django not translating the site properly

After spending too many hours on this, StackOverflow is for the rescue.
I configured my settings.py as below:
...
TIME_ZONE = 'Europe/Berlin'
LANGUAGE_CODE = 'de'
LANGUAGES = (
('en', u'English'),
('de', u'German'),
('fr', u'French'),
)
USE_I18N = True
USE_L10N = True
MIDDLEWARE_CLASSES = (
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.request',
'django.core.context_processors.static',
'django.contrib.messages.context_processors.messages',
)
...
In my base.html file, I have a form as below:
<form action="/i18n/setlang/" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="/" />
<select name="language">
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}">{{ language.name_local }} ({{ language.code }})</option>
{% endfor %}
</select>
<input type="submit" value="Go" />
</form>
My urls.py:
urlpatterns = patterns('',
url(r'^i18n/', include('django.conf.urls.i18n')),
url(r'^$', 'MainApp.views.index'), #root
)
In the same base.html file, I have on top {% load i18n %} and in the body, I have a sample {% trans "This is the title." %}. Before running the server, I did:
django-admin.py makemessages -l de
django-admin.py makemessages -l fr
The sample text above was picked up by makemessages, and I provided the respective translations for msgstr. After that, I did django-admin.py compilemessages. The command ran nicely and generated the .mo files in the respective locale folders.
I run the server and the the form does not work. From a another StackOverflow post, I was hinted to remove the #, fuzzy lines, which I did. What am I doing wrong?
Thanks!
You should put the LocaleMiddleware after the SessionMiddleware in your MIDDLEWARE_CLASSES:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
....
)
The order of middleware classes is important. The LocaleMiddleware uses session data to detect the user language, so it must come after the SessionMiddleware. It is also mentioned in the docs here https://docs.djangoproject.com/en/1.3/topics/i18n/deployment/#how-django-discovers-language-preference
Let's hope this works for you!

Django login sends empty username

I am using django.contrib.auth.views.login with a form like this at my login template
<form method="post" action="/login/" id="loginform">{% csrf_token %}
<label for="id_username">Username:</label>
<br>
{{ form.username }}
<br>
<label for="id_password">Password:</label>
<br>
{{ form.password }}
<br>
<input type="hidden" name="next" value="/redirect/">
<input type='button' class='button' value='Sign In'>
</form>
my urls.py is something like this:
url(r'^login/$', 'django.contrib.auth.views.login'),
url(r'^redirect/$', redirect)
and my view is:
def redirect(request):
logging.debug('user logging in: %s' %request.user.username)
username = request.user.username
try:
user = User.objects.get(username=username)
[...]
the problem is that request username is empty. So I always get an error at user = User.objects.get(username=username)
Any ideas how did that happened?
PS: Admin (django contrib admin) login fails with the same reason, too
UPDATE: at my logging file I get this:
2013-06-17 07:11:01,932 DEBUG request user is: AnonymousUser
UPDATE 2:
I also paste this from settings.py:
MIDDLEWARE_CLASSES = (
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'main.common.tz_middleware.TimezoneMiddleware',
'main.common.sslMiddleware.SSLRedirect',
'django.middleware.cache.FetchFromCacheMiddleware',
)
UPDATE 3: Things are getting more absurd. I substituted the redirect function with this:
def redirect(request):
return HttpResponseRedirect('/home/')
and it works. So, request object when redirected keeps user info... However this is not the solution
Try to put template_name in urls...
url(r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
And why don't you use django-registration (it works on Django 1.4.5)

Django setLang does not process "Next" parameter

I'm trying to implement on-fly language change with the following code:
{% for lang in LANGUAGES %}
<li>
<form name="setLang{{ lang.1}}" action="/i18n/setlang/" method="POST">{% csrf_token %}
<input name="next" type="hidden" value="http://google.com" />
<input type="hidden" name="language" value="{{ lang.0 }}" />
{{ lang.0 }}
</form>
</li>
{% endfor %}
It works great, the problem is that it doesn't return to URL specified in "next" field. I forced it to be "google.com" just to see how it works, but it keeps redirecting me back to my homepage.
Here is my urls.py:
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'izolyatsia.views.home', name='home'),
# url(r'^izolyatsia/', include('izolyatsia.foo.urls')),
url(r'^$', 'showcase.views.home', name='home'),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
(r'^project/(?P<project_name>[a-zA-Z0-9_.-]+)/$', 'izolyatsia.views.project'),
(r'^post/(?P<slug>[a-zA-Z0-9_.-]+)/$', 'izolyatsia.views.post'),
#Uncomment the next line to enable the admin:
url(r'^admin/', include(admin.site.urls)),
(r'^tinymce/', include('tinymce.urls')),
url(r'^wysiwyg_post/$', 'izolyatsia.views.wysiwyg_post', name='wysiwyg_post'),
url(r'', include('multiuploader.urls')),
(r'^i18n/', include('django.conf.urls.i18n')),
url(r'^(.*)/$', 'pages.views.show_page', name='show_page'),
)
I've got no idea why it doesn't work, maybe someone here can help me?
thanks in advance,
m.
Redirecting to sites outside your domain is explicitly prevented by the code - the set_language view calls django.utils.is_safe_url(), which checks you're not trying to do exactly that.
Please take a look to the django doc here, where you can find that you should have the middlewares in this order in your settings.py file:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
)
maybe it can be what is happen to you with, I think.

Issues with Django and pytz

I've followed the time zone documentation on the Django site with no luck. My issue is that I have a select box on my template that should be populated with common timezones provided by pytz, but, for whatever reason it's empty.
My end goal is to allow users to select their own time zone.
Any help is appreciated, thanks in advance.
view.py:
def set_timezone(request):
if request.method == 'POST':
request.session['django_timezone'] = pytz.timezone(request.POST['timezone'])
return redirect('/')
else:
return render(request, 'n2w/leads.html', {'timezones': pytz.common_timezones})
leads.html:
{% load tz %}
{{ datetime }}
<form action="" method="POST">
{% csrf_token %}
<label for="timezone">Time zone:</label>
<select name="timezone">
{% for tz in timezones %}
<option value="{{ tz }}"{% if tz == TIME_ZONE %} selected="selected"{% endif %}>{{ tz }}</option>
{% endfor %}
</select>
<input type="submit" value="Set" />
</form>
settings.py:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.timezone.TimeZoneMiddleware',
# Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
#'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'django.contrib.admindocs',
'registration',
'django.contrib.humanize',
'n2w',
'n2api',
'dajaxice',
'pytz',
)
middleware class (timezone.py):
from django.utils import timezone
class TimeZoneMiddleware(object):
def process_request(self, request):
tz = request.session.get('django_timezone')
if tz:
timezone.activate(tz)
I think you are probably raising a NameError or something. Try importing pytz:
from pytz import common_timezones
...
...
return render(request, 'n2w/leads.html', {'timezones': common_timezones})
After upgrading my Python installation from 2.7.1 -> 2.7.3, I was able to import pytz flawlessly. Thanks for all your help!

django 1.3 internationalization... switching language requires server restart?

I used django 1.2 before and didn't have any problem switching language... In my template i have this...
<form action="/i18n/setlang/" method="post" class="forms">
{% csrf_token %}
<input name="next" type="hidden" value="/next/page/" />
<select name="language" id="select_langauge" class="m_show hide">
{% for lang in LANGUAGES %}
{% if lang.0 != '' %}
<option value="{{lang.0}}">{{lang.1}}</option>
{% endif %}
{% endfor %}
</select>
This was working fine with django 1.2. But since upgraded to Django 1.3 this does not work. I can see that LANGUAGE_CODE changes, but the actual language output is not what I was expecting.
However, when i restart django server, it shows correct language. What am i missing???
I have this in my settings.py
LANGUAGE_CODE = 'en-us'
SITE_ID = 1
USE_I18N = True
gettext = lambda s: s
LANGUAGES = (
('', gettext('Please select')),
('en', gettext('English')),
('ko', gettext('Korean')),
)
USE_L10N = True
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.locale.LocaleMiddleware',
)
I figured out.
To change language dynamically, using ugettext_lazy() fixed the problem. (Before I was using ugettext).
Reference: https://docs.djangoproject.com/en/1.3/topics/i18n/internationalization/#lazy-translation