I just came across a weird bug (?) where I initially had
from django.utils.translation import ugettext as _
Which I changed for
from django.utils.translation import ugettext as __
But, surprisingly, running ./manage.py makemessages --all
after doing that breaks all translations, they basically get all commented in my .po
files, as if they weren't recognized as being translations anymore.
Going back to _
and running makemessages
fixes it. I don't quite follow why the name of the variable matters, and I wonder how I should name my ugettext and ugettext_lazy when I need both, for consistency.
Django 1.8, with python 2.7.14
That's because of the internals of the gettext
utility and more specifically of the xgettext
command.
In short, in order to mark strings as translatable you must wrap them in specific keywords (i.e translate("hello world")
, translate
here is the keyword). The xgettext
program works for many programming languages. Each language has its own predefined keywords (press Ctrl + f
and search for --keyword
).
In Python, these keywords are (note the _
at the end):
For Python:
gettext
,ugettext
,dgettext:2
,ngettext:1,2
,ungettext:1,2
,dngettext:2,3
,_
xgettext
command has several options which alter it's behavior. One of these, is --keyword
option. When you invoke the xgettext
command with the --keyword
option, then all strings in a python file will be considered translatable if they are wrapped in one of the predefined keywords or the --keyword
option(s) you gave. If, for example you run xgettext --keyword=jimmy_hendrix
then all strings like jimmy_hendrix("hello world")
will be included in your .po
file.
But, you will never run this command, in Django, explicitly. You use the makemessages
command. Looking at the source of makemessages
command, you can see that Django provides additional --keyword
s for marking strings for translation. In fact, these keywords are the same as Django's additional functions for translation.
After all these, I think it's clear now that aliasing __
or ___
will not work since it's not in the list of Django's xgettext
command invocation, neither in the predefined keywords of xgettext
command.
You may look at an outdated, but still valid answer.
Also, an example of xgettext
on MDN, using PHP.