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
Related
I have question about show current language on mobile devices if I populate my language list in template dynamically (got from languages array from settings)...
So, this code working properly:
EN
BUT, when I'm trying this code, I can't achive that active class added to current language:
{% for lng in settings.LANGUAGES %}
{% if not lng.0 == "ru" %}
<a href="#" id="language-{{ lng.0 }}"
class="pure-drawer-link{% if LANGUAGE_CODE == '{{ lng.0 }}' %} active{% endif %}">
{{ lng.0|upper }}
</a>
{% if LANGUAGE_CODE == '{{ lng.0 }}' %} active {% else %} nonactive{% endif %} => this always return nonactive
{% endif %}
{% endfor %}
Can anyone help to understood why this is happening?
EDIT 1:
My middlewars in settings:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'my_app.middleware.ExpirationMiddleware',
'my_app.middleware.IPMiddleware',
'my_app.middleware.TranslationMiddleware',
]
and this for i18:
USE_I18N = True
USE_L10N = False
USE_TZ = True
TIME_ZONE = 'Europe/Zurich'
LANGUAGE_CODE = 'en-US'
I have a multiple language app (Django 1.11) with a form to create new users. In this form, the error messages when the user send invalid input must come in Portuguese (pt-BR) or English (en-US) based on the selected language. The custom validations and some of the automatic Django messages for validations are well translated, but not the following: "The password is too similar to the username."; "This password is too short. It must contain at least 8 characters." and "This password is too common.". Actually, they are shown in Portuguese, since the LANGUAGE_CODE from settings.py is 'pt-BR'.
I was able to translate some of the automatic messages such "A user with that username already exists." with django.utils.translation.activate as in the following code.
from django.utils.translation import activate
activate(curr_lang)
But this wasn't enough to translate the validations from settings.AUTH_PASSWORD_VALIDATORS. I manually changed the LANGUAGE_CODE from 'pt-BR' to 'en-US' and was able to see the messages only in English. What is the best strategy to translate these messages? As far as I researched, setting LANGUAGE_CODE is not a option, since the results I find suggest the use of django.utils.translation.activate. Thanks in advance
After several tries, I think the solution was:
Add "django.middleware.locale.LocaleMiddleware" to MIDDLEWARE at settings.py (be careful with the order as explained at the documentation)
MIDDLEWARE = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
...
Add the LANGUAGES const also at settings.py after LANGUAGE_CODE, which has to contain the default language
LANGUAGE_CODE = 'pt-BR'
LANGUAGES = [
('pt-BR', 'Portuguese'),
('en-US', 'English'),
]
Use Django's default set_language method - on urls.py, add the following line:
urlpatterns = [
....
url(r'^i18n/', include('django.conf.urls.i18n')),
And, on the html file with the selection of language,
{% load i18n %}
{% load staticfiles %}
<form action="{% url 'set_language' %}" method="post">{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}" />
<select name="language" id="curr_lang" class="select2-single" onchange="this.form.submit()">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
<option value="pt-BR" title="Português" {% if LANGUAGE_CODE == 'pt-br' %}selected{% endif %}>{% static 'img/flags/br.png' %}</option>
<option value="en-US" title="English" {% if LANGUAGE_CODE == 'en-us' %}selected{% endif %}>{% static 'img/flags/us.png' %}</option>
</select>
</form>
On context_processor.py, define a function (I'm calling global_env) to be run at the end of every view. On settings.py, add 'your-application-name-here.context_processor.global_env' such as
TEMPLATES = [
...
'OPTIONS': {
'context_processors': [
'your-application-name-here.context_processor.global_env',
...
And, on context_processor.py, the function must have
def global_env(request):
from django.utils.translation import activate
curr_lang = request.session[LANGUAGE_SESSION_KEY]
activate(curr_lang)
# More code to render dictionary to views for non-default messages on page
....
I think these steps complete the translation of default form validation messages from Django without the need of custom validators.
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!
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
After looking at the trying all of the recommendations I could find on this subject, my translations still do not work whatsoever.
/settings.py file
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'
LOCALE_PATHS = (
'/Users/samb/Projects/transtest/locale'
)
# Custom Languages
ugettext = lambda s: s
LANGUAGES = (
('de', ugettext('German')),
('en', ugettext('English')),
('fr', ugettext('French')),
('fr-CA', ugettext('French Canadian')),
)
SITE_ID = 1
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True
# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = True
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',
)
view.py
from django.shortcuts import render_to_response
from django.template import RequestContext
def trans(request):
return render_to_response('index.html', context_instance=RequestContext(request))
my template file (index.html)
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
<html>
<head>
<title>translations</title>
</head>
<body>
{% for l in LANGUAGES %}
{{ l }}<br />
{% endfor %}
{{ LANGUAGE_CODE }}<br />
{% trans "Welcome to my site" %}
</body>
</html>
po file (that has been compiled)
located at /Users/samb/Projects/transtest/locale/fr/LC_MESSAGES
#: transtest/templates/index.html:13
msgid "Welcome to my site"
msgstr "Please work"
I can never get the 'Welcome to my site' to work. The LANGUAGES and LANGUAGE_CODE variables in my template are all working (unless I 'Accept_language: fr_CA').
After reading all the other posts on this subject and still having the same problem, I feel like I must have a silly mistake, or am missing a vital step entirely. Any thoughts?
Update: This is how I am testing the translation:
telnet localhost 8000
Connected to localhost.
Escape character is '^]'.
GET /
Accept_language: fr
<html>
<head>
<title>Translations</title>
</head>
<body>
('de', u'Allemand')<br />
('en', u'Anglais')<br />
('fr', u'Fran\xe7ais')<br />
('fr-CA', u'French Canadian')<br />
fr<br />
Welcome to my site
</body>
</html>
Connection closed by foreign host.
I noticed that the languages are getting translated, but the 'Welcome to my site' is not.
The docs say here that LocaleMiddleware ...
... should come after SessionMiddleware, because LocaleMiddleware makes
use of session data. And it should come before CommonMiddleware
because CommonMiddleware needs an activated language in order to
resolve the requested URL.
Maybe it will help when you take account of this in your definition of the MIDDLEWARE_CLASSES.