I would like to use gettext through my application.
So, I tried to put the basics into __ init__.py like this :
import gettext
_ = gettext.gettext
gettext.bindtextdomain ( 'brainz', '../datas/translations/' )
gettext.textdomain ( 'brainz' )
And I try simple call in Brainz.py :
#!/usr/bin/python
from brainz import *
##
# Main class of the game
class Brainz :
def __init__ ( self ) :
print _( "BrainZ" )
print _( "There will be blood..." )
print _( "By %s" ) % "MARTIN Damien"
But I have the following error at execution time :
Traceback (most recent call last):
File "main.py", line 8, in <module>
Brainz ()
File "/home/damien/Dropbox/Projets/BrainZ/brainz/Brainz.py", line 12, in __init__
print _( "BrainZ" )
NameError: global name '_' is not defined
As I'm new to python I don't understand what is wrong.
Could you give me good advices ?
Thanks,
Damien
sdolan explained why your code didn't work, and provided a great solution. But it has an inconvenience: you have to import gettext in every module you want to enable translations.
Elf Sternberg provided a very convenient approach: manually make gettext visible project-wide. But it looks a bit cryptic and, as he said, it is pure evil :). He also suggests, for an unknown reason, the totally unrelated Django ugettext. No need of Django, stick with the standard lib gettext like you did before.
May I suggest a 3rd, officially endorsed approach? In the same __init__.py
you tried before, use this:
import gettext
gettext.install('brainz', '../datas/translations/')
And that's it! Project-wide _()
availability, in a non-cryptic, elegant and convenient way, using the standard gettext
module. But, to be fair, if you look at gettext's source code, you'll see that uses the same trick Elf suggested. So, in essence, this is also Pure Evil(tm). But this is perfectly fine if 'brainz' module is only used by your application and not meant to imported by other applications.
If you want to share 'brainz' with other applications, you should use sdolan's approach: import it in each module. But, again, instead of using bindtextdomain
and textdomain
like you did, I suggest this:
import gettext
t = gettext.translation('brainz', '../datas/translations/')
_ = t.ugettext
The difference is using gettext's Class-based API instead of the GNU gettext API. Take a look in the official reference for why. The install
approach is also part of the Class-based API.
Side note: you will notice the docs suggest using pygettext
as a replacement for GNU's xgettext
. Don't! Pygettext is extremely outdated and lacks several features. xgettext
is much more powerful and flexible, and fully supports Python.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With