L10N localization of numbers in templates using Jinja2 and Django - django

I'm trying to get Jinja2 (and Django, via django-jinja) to localize a number, eg. 123456 becomes 123,456 (or, of course, 123.456 depending on the locale). I've read every bit of documentation I can find on the subject, and can't find anything that actually works. Using standard DTL, one could just do:
{% localize on %}{{ some_number }}{% endlocalize %}
This works fine in my project using regular Django templates, but of course, doesn't work in Jinja2. I mention that this works fine because anything involving settings.py such as USE_L10N being False can be ruled out.
I've tried the following, all based on documentation I've found:
{{ gettext("%(num)d", num=some_number) }} - outputs number with no commas or localization.
{% trans num=some_number %}{{ num }} {% endtrans %} - as suggested by the django-jinja documentation - outputs number with no commas or localization.
{{ _(some_number|string) }} - outputs number with no commas or localization.
{{ some_number|localize }} - localize is not a valid filter.
So, how can I easily and properly localize a number using Jinja2?

Figured it out. Jinja2 doesn't seem to handle localization on its own, but django-jinja includes a built-in contrib that wraps django.contrib.humanize.templatetags. According to the documentation for that, format localization is respected using the |intcomma filter if L10n is enabled.
To use it, add django_jinja.contrib._humanize to INSTALLED_APPS in settings.py:
INSTALLED_APPS += ('django_jinja.contrib._humanize',)
And then in templates, simply use the |intcomma filter:
{{ some_number|intcomma }}

Though it is an old question, I encountered the same found this solution feasible without lot of edits.
Here is library that implements L10n for jinja2 templates. You could integrate it with your application like
TEMPLATES = [
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'extensions': [
'jdj_tags.extensions.DjangoStatic',
'jdj_tags.extensions.DjangoI18n',
'jdj_tags.extensions.DjangoL10n',
]
},
},
}

Related

Django Translation appears to not be using translations

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?

Translate date format in django: technical message id?

I'm working on a site that displays dates, and is in several languages via i18n.
I'm displaying dates with a filter (sometimes I want only the day, only the hour, etc.)
I've read the last paragraph of this: https://docs.djangoproject.com/en/1.2/topics/i18n/, and from what I understand I'm supposed to be able to specify the formats I want in the django.po locale and use them in the template filter ?
It doesn't seem to work though.
{{ date_start|date:"{% trans "DATE_HOUR_ONLY" %}" }}
With in the django.po for english language:
msgid "DATE_HOUR_ONLY"
msgstr "%P"
This completely blows up though...
And using single quotes instead of doubles ({{ date_start|date:"{% trans 'DATE_HOUR_ONLY' %}" }}) doesn't blow up but displays this :
{% 31Fri, 17 May 2013 00:00:00 -0500a.m.500 'FriAMCDTMay_00-05001368766800R_-0500MayFalse2013' %}
I can't find any concrete example online on how to proceed. Without the filters, the date switches correctly depending on the language, because of how DATE_FORMAT is set in my settings.py
Thanks a lot !
Well, after a bit of wandering around, this worked:
{{ date_start|date:_('DATE_WITH_HOUR') }}
Maybe you can try Django formats.py
https://docs.djangoproject.com/en/1.4/topics/i18n/formatting/
For example , i have a formats folder in my project, don't forget the "init.py"
if you want add a different locale,only need add a folder like 'zh_TW' in the 'en' same level
mysite/
formats/
__init__.py
en/
__init__.py
formats.py
the formats.py look like
SHORT_DATE_FORMAT = 'Y/m/d'
SHORT_DATETIME_FORMAT = 'Y/m/d G:i:s'
and in my template.html
{ now | date:"SHORT_DATE_FORMAT" }
that can change by your locale, hope the solution will help you :)

Format floats in Django template in language aware manner

I am using Django's humanize to make large float numbers in my app more readable. Also my app is available in different languages, and different languages use , and . signs in numbers the other way around.
For integer values the humanize tag intcomma works well:
{{ intvalue|intcomma }}
Would give for different locales:
English: 1,000,000
Dutch: 1.000.000
However, using floats this doesn't work very well. For example in my template you would find this:
{{ floatvalue|floatformat:2|intcomma }}
Would give for different locales:
English: 1,000,000.00
Dutch: 1,000,000,00
Note that instead of 1.000.000,00 for Dutch, it shows 1,000,000,00. Switching around the floatformat:2 and intcomma tags doesn't work either as then the value is nothing.
Any ideas on how to easily fix this?
(If possible, I'd rather not use an external libraries such as Babel)
Try the Django Format Localization feature. It gives you three options. As the Django docs say,
Django’s formatting system is capable to display dates, times and numbers in templates using the format specified for the current locale. It also handles localized input in forms.
When it’s enabled, two users accessing the same content may see dates, times and numbers formatted in different ways, depending on the formats for their current locale.
The formatting system is disabled by default. To enable it, it’s necessary to set USE_L10N = True in your settings file.
Thus this first option turns on locale-dependent number formatting for all of your templates.
A second option is to use the localize template tag to turn on locale-dependent number formatting for only part of a template. For example,
{% load l10n %}
{% localize on %}
{{ value }}
{% endlocalize %}
A third option is to use the localize template filter to force locale-dependent number formatting for a single value. For example,
{% load l10n %}
{{ value|localize }}

Is there any way to distinguish between two templatetags that have the same name?

I have 2 different template tags that share the same name: the_template_tag.
Is there any way to distinguish between the two template tags? Something like "source1.the_template_tag" and "source2.the_template_tag"?
Here is my case. I am using django-timezones. There is a templatetag called localtime that basically allows me to display the date in the client local time.
{% load timezone_filters %}
... some more code
"user_localtime": "{{ serverdate|localtime:user_timezone }}",
Also, I am using the new timezones of Django 1.4. When I need to use the client local time (with the django-timezone), then I start to have problems. Basically, I have to turn off the timezones of django:
{% load tz %}
... some more code
{% localtime off %}
But the templatetag is the same. Then, of course, I get an error when I try to use both:
{% load tz %}
{% load timezone_filters %}
... some more code
{% localtime off %}
"user_localtime": "{{ serverdate|localtime:user.user_timezone }}",
You have two options:
Stop using django-timezones and use the timezone features of django 1.4
If you must use django-timezones, edit the source and rename the tag.
I would highly recommend #1, and strongly discourage #2.

django - how to make translation work?

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.