I'm trying to render a template in a different language using i18n. I did everything I could read about, from setting the language code, creating and compiling translation files, including the translation tags in the template and all that, and my template still renders in English, even through the {{ LANGUAGE_CODE }} variable points to the correct (and different) code I intended to render. What am I missing?
template:
{% extends "base.html" %}
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_current_language_bidi as LANGUAGE_BIDI %}
{% block title %}{% trans "translation test" %}{% endblock %}
{% block content %}
<div id="some-text">
{% trans "some translated text goes here" %}
{% blocktrans %}
<ol>
<li>here are some</li>
<li>items that should be</li>
<li>translated as well</li>
</ol>
{% endblocktrans %}
<ul>
<li>The current language is <b>{{ LANGUAGE_CODE }}</b></li>
{% if LANGUAGE_BIDI %}
<li>The current language is bidirectional</li>
{% else %}
<li>The current language is <b>not</b> bidirectional</li>
{% endif %}
<li>Available languages are:
<ul>
{% for lang in LANGUAGES %}
<li>{{ lang.1}}</li>
{% endfor %}
</ul>
</li>
</ul>
</div>
{% endblock %}
view:
from django.shortcuts import render_to_response
from django.template import RequestContext
from pdb import set_trace as debugger
def check(request):
return render_to_response('index.html', context_instance=RequestContext(request)
command line (I did fill in the correct translations in .po files):
$ django-admin.py makemessages -l he-il -e html
$ django-admin.py compilemessages
settings.py:
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'he-il'
gettext = lambda s: s
LANGUAGES = (
('he-il', gettext('Hebrew')),
('en-us', gettext('English')),
)
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.auth",
"django.core.context_processors.i18n",
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
)
Just add the paths of the locale files generated to the settings.py file like the following
LOCALE_PATHS = ( "/xxx/xxx/Projects/xxx/sites/avb/locale/",)
This is a full solution that I have been using from Django 1.4 and still in 1.7.1:
In settings.py …
Add to MIDDLEWEAR_CLASSES, locale, it enables language selection based on request:
'django.middleware.locale.LocaleMiddleware',
Add LOCALE_PATHS, this is where your translation files will be stored:
LOCALE_PATHS = (
os.path.join(PROJECT_PATH, 'locale/'),
)
Enable I18N:
USE_I18N = True
Set LANGUAGES that you will be translating the site to:
ugettext = lambda s: s
LANGUAGES = (
('en', ugettext('English')),
('fr', ugettext('French')),
('pl', ugettext('Polish')),
)
Add i18n template context processor to TEMPLATE_CONTEXT_PROCESSORS, requests will now include LANGUAGES and LANGUAGE_CODE:
'django.core.context_processors.i18n',
In urls.py :
In url_patterns, add the below, it will enable the set language redirect view:
url(r'^i18n/', include('django.conf.urls.i18n')),
See Miscellaneous in Translations for more on this.
Add the following imports, and encapsulate the urls you want translated with i18n_patterns. Here is what mine looks like:
from django.conf.urls.i18n import i18n_patterns
from django.utils.translation import ugettext_lazy as _
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^i18n/', include('django.conf.urls.i18n')),
)
urlpatterns += i18n_patterns('',
(_(r'^dual-lang/'), include('duallang.urls')),
(r'^', include('home.urls')),
)
Now anywhere you use text and want to convert it, import lazytext and wrap every string with it like so _('text'), you can even go to your other urls.py files and do url translation like so:
url(_(r'^dual_language/$'), landing, name='duallang_landing'),
You can wrap text that you want translated in your other files, such as models.py, views.py etc.. Here is an example model field with translations for label and help_text:
name = models.CharField(_('name'), max_length=255, unique=True, help_text=_("Name of the FAQ Topic"))
In your html templates...
Do same for your templates and load the i18n templatetag and use trans and transblock on the static stuff you want to translate. Here is an example:
{% load i18n %}
{% trans "This is a translation" %}<br><br>
{% blocktrans with book_t='book title'|title author_t='an author'|title %}
This is {{ book_t }} by {{ author_t }}. Block trans is powerful!
{% endblocktrans %}
Now run a makemessages for each of your locales:
./manage.py makemessages -l pl
And now all is left is to go into your /locales folder, and edit each of the .po files. Fill in the data for each msgstr. Here is one such example of that:
msgid "English"
msgstr "Angielski"
And finally compile the messages:
./manage.py compilemessages
For model instance data translation you can use some of the reusable packages available like
There is a lot more to learn with translations and internationalization is closely related to this topic, so check out the docs for it too. I also recommend checking out some of the internationalization packages available for Django like django-rosetta, and django-linguo. They help translate model content, django-rosetta does not create new entries for this in your database, while django-linguo does.
If you followed this you should be off to a good start. I believe this is the most standardized way to get your site running in multiple languages. Cheers!
I may be wrong - as the only time I used translation stuff was on a test project many moons ago - but I think you don't want this:
$ django-admin.py makemessages -l he-il -e html
But rather this:
$ django-admin.py makemessages -l he_il -e html
Notice the underscore in he_il.
I was having issues with pt-BR too, until I made the messages file with pt_br instead. Then things started working...
Yeah, it is not obvious and I couldn't find documentation about it anywhere.
Hope that helps.
I have the same problem. But I solve it by putting "Language:" to .po file. In my case .po file does not contain the "Language:" attribute, it looks like...
"Language-Team: LANGUAGE \n"
"Language: \n"
"MIME-Version: 1.0\n"
but when I put language code (in my case 'ru' or 'en')
"Language-Team: LANGUAGE \n"
"Language: ru\n"
"MIME-Version: 1.0\n"
it works for me
I had the same issues, it seems that your locale path have to end with a slash :
LOCALE_PATHS = (
'/dir/to/my/locale/',
)
The way I went about it is by using the exact language code that django uses in it's own translation files (and not by the link provided inside settings.py), assuming this language is supported (if not things get complicated, since you have to provide your own translation files to django as well).
I found this code by going to $DJANGO_DIR/conf/locale and looking at the folder's name (for me it was at /usr/local/lib/python2.6/dist-packages/django/conf/locale, but it may differ depending on OS and such).
Yes you do need to make message files as celopes suggests and then compile them
python manage.py compilemessages
But you will still have a problem.
Disable LocaleMiddleware for a bit, i.e. remove this
django.middleware.locale.LocaleMiddleware
from your middleware list. Don't use it if you do not need to switch the language at run time, but if you do need it, then there is a solution. I had the same problem before and someone explained this to me.
Also I had this weird issue before. Makemessages command would choke on strings wrapped with backslash in .py files.
I had very the same issue, i tried to switch my language and django said no go. No error, no warning, but django switched language to pl-pl (in my case). However removing all folders from locale and executing command:
django-admin.py makemessages -l pl_PL (underscore instead of dash and capital letter for second PL, worked this issue out).
I hope it helps some guys out there.
I had the same issue. I explained it with details in this link under another similar question.
Briefly, my problem has been solved by reloading the server with this code:
sudo /etc/init.d/uwsgi reload
Now, everytime I change the phrases and after compiling language files, I reload the server too to see the changes.
Related
I am trying to set-up template translation inside of Django templates and I am bit puzzled by why it's not working. I've followed the docs but I imagine I am missing one small thing that is tripping this up.
I've done the following:
USE_I18N = True
LOCALE_PATHS = (os.path.join(BASE_DIR, 'locale/'),)
LANGUAGE_CODE = 'en-us'
LANGUAGES = [('en-us', _('English - US')), ('zh-hans', _('简体中文')), ('es', _('Spanish'))]
Added {% load i18n %} to the top of the templates
Added {% trans %} tags into the templates like this: {% trans 'About' %}
Ran ./manage.py makemessages -l es and got the .po file in the locale path so I know it's finding all the template tags.
Ran ./manage.py compilemessages and got the .mo file in the locale path
I added these two lines to a template to make sure the language code was being set.
{% get_current_language as LANGUAGE_CODE %}
<h2>Current Language Code: {{ LANGUAGE_CODE }}</h2>
I am then able to see that the correct language code is being set.
I am also using this tutorial's template to set the language:
http://joaoventura.net/blog/2016/django-translation-4/
With that I know a translation is being applied because the selection menu in the form updates the language (in the code side). I assume this is using locale files inside the i18n app.
I also noticed that it is picking up translations properly inside the admin interface.
I'm using Django 1.11.6 on OS X 12.12.6 with Python 3.6.3.
What I am puzzled with is, what could I still be missing?
Porting a Django site from 1.2 to 1.5 on Python 2.6 i ran into problems with internationalization.
The wierd thing is that only one string gets translated in the entire site (Well, almost, the date filter could translate long month names when I tested). Other strings located in the same template doesn't get translated, and all translations are located in a single po/mo file. All translations are there, verified with Poedit and compiled with manage.py compilemessages.
Edit: The reason for the single translated string was that it matched a string in the admin site.
While trying things to get it to work I cleared the LOCALE_PATH, restarted the dev server (manage.py runserver), cleared any browser cache (even though meta-data for the site disables cashing), lo and behold the element is still translated. I verified this by adding the same text again after, and it still gets translated, so no client side caching is involved.
Language switching works as expected and the only translated element is changed to the default language, {{ LANGUAGE_CODE }} confirms this.
I've tried clearing the session data and django cache (which doesn't seem to be used by the dev server).
Can someone guess what's going on here? Isn't there any debug flags to get more extensive logging or something?
A minimal view:
def locale_test(request):
locale = request.GET.get('l', None)
if locale:
translation.activate(locale)
di = {"foobar": _("foobar")}
return render_to_response('locale_test.html',di, context_instance=RequestContext(request))
And corresponding template (locale_test.html):
{% load i18n %}
<p>Language: {{ LANGUAGE_CODE }}</p>
<p>Matching string from admin site that gets translated correctly: {% trans "Log out" %}</p>
<p>Translated in template: {% trans "Foobar" %}</p>
<p>Translated in view: {{ foobar }}</p>
Relevant settings:
USE_I18N = True
USE_L10N = True
LANGUAGES = (
('en', 'English'),
('foo', 'Fooo'),
)
LANGUAGE_CODE = 'en'
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.i18n',
'django.core.context_processors.request',
)
LOCALE_PATHS = ('/path/to/my/locale',)
For reference, these questions didn't help me:
django internationalization and translations issue
Django not translating the site properly
Django i18n does not work
Gah! I got bit by the same issue as this guy :
https://code.djangoproject.com/ticket/18492
Namely that a trailing comma was missing in the LOCALE_PATHS tuple. Too bad Django doesn't raise an error for that.
I had a similar issue that I resolved in making sure that whenever I update the django.po file, I compile it:
./manage.py compilemessages
The translation get done from the compiled file (django.mo) and not the .po file
Generate the translation file: ./manage.py makemessages -a
Translate: manually or using a tool like autotranslate
compile the file: ./manage.py compilemessages
Test to see the changes: not that the default language might be picked first, make sure that you change the language. For example change localhost:8000/en/ to localhost:8000/fr/ or localhost:8000/foo/ depending on the language you want to see
I hope this helps
I have template with the following:
{% load i18n %}
{% trans "Welcome to my site!" %}
I use RequestContext, have called makemessages, edited .po files and compiled messages, but everything is not translated, I just see the same message even when I load the page.
Extract from .po file
msgid "Welcome to my site!"
msgstr "blahblah"
To get translations to show in templates:
Your settings.py should have the following:
USE_I18N = True
USE_L10N = True # optional, but recommended
LANGUAGE_CODE = 'en-us' # Or whatever language you want as default
You should have 'django.core.context_processors.i18n' in your TEMPLATE_CONTEXT_PROCESSORS
You should add 'django.middleware.locale.LocaleMiddleware' in your MIDDLEWARE_CLASSES (after 'django.contrib.sessions.middleware.SessionMiddleware')
Make sure your templates have {% load i18n %} somewhere near the top.
Once you have translated and compiled the messages, to actually get the translation to show, you need to tell django which language you need. To do that, do one of the following:
Set django_language key in the session which the language code you want.
Set a cookie called django_language to the language you want.
If after all the above, you are not getting any translations to show - then django is not able to find your message files.
I've already configured the necessary things to work the extends template function in django. here's my codes:
in settings.py
def my_dir():
import os.path
return os.path.abspath(os.path.dirname(__file__))
TEMPLATE_DIRS = ( my_dir() + '/app/templates', ) #dynamic template directory
in base.html - located in app/templates/site
....
<div id="SideBar" class="FloatLeft">
{% block sidebar %} {% endblock %}
</div>
....
in sidebar.html - located in app/templates/site
{% extends "site/base.html" %}
{% block sidebar %}
some code here
{% endblock %}
I've tried also the {% include "site/sidebar.html"%} tag in the base.html to check the template directory, and yes include tag is working...
what's the problem in the {% extends %} ? why does it doesnt detect its parent template..
please help me guys.. your help is greatly appreciated... im still waiting for the answer.. tnx
Which template are you rendering in your view? It should be the child, not the parent.
I am not sure what yout problem is, but you should check the following points :
The {% extends %} tage should be the first one in the template file (and put a blank line afterwards to be sure)
I think that the reference to the base template is relative to you TEMPLATE_DIR. Try different things like putting both templates at the same level etc.
Check all the tags in both templates to be sure that they are all correctly formatted
Check the encoding of the files. If it is UTF-8, try to disable the BOM in both files.
Maybe it is a problem with your directory setting. Try to hard code the absolute path to check that.
These are the problems I can imagine, but I can't guarantee that it will work.
The answer Daniel Roseman gave is spot on, but there is a quick and easy way around this if pointing to your child template is not practical (as it might not be with more complex projects).
In your child template, remove the {% extends "" %} tags you have that are pointing to your parent.
In your parent template, replace {% block content %} with {% include "path/to/child/template" %}
That's it! Your child template will now load into the block content exactly as if you had rendered it directly.
There are a lot of problems. The short answer is "No, you can't change template dirs on-the-fly, and even if you could, you would do it definitely not the way you're doing it now"
Your main issue is that you're forgetting a comma in the TEMPLATE_DIRS setting. Try this:
TEMPLATE_DIRS = ( my_dir() + '/app/templates', )
Please disregard cheshire's answer.
Use os.path.join to combine 2 directories.
import os.path
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates'),
)
Here I am assuming that templates is a directory where you keep your templates. Now, to access the templates this is the base directory for them. So to extend base.html in some other file do like this -
{% extends "base.html" %}
...
{% endblock %}
Are you sure you have the proper template loaders setup?
You should have this in your settings.py:
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
)
How to turn it on?
According to this http://docs.djangoproject.com/en/1.2/topics/i18n/internationalization/
I put into my template /var/www/project/template/index.html
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
<html><body><h1>{% trans "It works!" $}</h1>
get_current_language = {{ LANGUAGE_CODE }}<br>
get_available_languages = {{ LANGUAGES}}<br></body></html>
and in folder /var/www/project/template/ I create locale subfolder than I run
django-admin makemessages -l pl_pl
processing language pl_pl
and there's no files in locale/pl_pl/LC_MESSAGES/ (which are automagicaly created)
What should I do more?
Shouldn't your index file be in project/templates/ (with an s) ?
Otherwise, have you declared 'project' in your INSTALLED_APPS ?
DAMNED. I haven't noticed this:
<html><body><h1>{% trans "It works!" $}</h1>
___________________________________________________________________ ^
Now it works.. I mean - it creates django.po and django.mo. But I still see It works - not translated strings. I even creates locales/en and locales/en_us with some different strings - still I see It works.
SOLVED
I have to put /var/www/project/templates/app/locale into settings.py to variable LOCALE_PATHS
Not intuitive.