python:在 __init__.py 中处处使用 gettext
我想在我的应用程序中使用gettext。
所以,我试着把基本的内容放到__ init__.py里,像这样:
import gettext
_ = gettext.gettext
gettext.bindtextdomain ( 'brainz', '../datas/translations/' )
gettext.textdomain ( 'brainz' )
然后我在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"
但是在执行的时候我遇到了以下错误:
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
因为我刚开始学python,所以我不太明白哪里出错了。
你能给我一些好的建议吗?
谢谢,
Damien
3 个回答
这真是个坏主意,但确实能达到你想要的效果。在你项目的 _init.py 文件里,做以下操作:
from django.utils.translation import ugettext
import __builtin__
__builtin__.__dict__['_'] = ugettext
现在,带下划线的 将会 在任何地方变成 ugettext。其他的回答也提到了一些注意事项;修改 Python 的内置列表并不是个好主意,这肯定会让那些不熟悉的人感到困惑。
通配符导入不会导入以下划线开头的内容。
使用通配符不好,因为它会弄乱命名空间,导致难以发现的错误。而且,下划线有时用来表示一个未使用的变量。
最好在需要的地方进行导入。只需要一行代码,打起来也不难,你还可以在你的开发工具中创建一个代码片段来方便使用。
更新:更多不使用通配符的理由,请查看 http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#importing。
sdolan 解释了为什么你的代码没有成功,并提供了一个很好的解决方案。不过,这个方案有个不方便的地方:你需要在每个想要启用翻译的模块中都导入gettext。
Elf Sternberg 提供了一个很方便的方法:手动让gettext在整个项目中可用。但这个方法看起来有点复杂,正如他说的,这简直是纯粹的邪恶 :)。他还提到了一种完全无关的Django的ugettext,虽然不知道为什么。其实没有必要使用Django,继续用你之前用的标准库gettext就可以了。
我可以建议一个第三种方法吗?这是一个官方推荐的方法。在你之前尝试的同一个__init__.py
文件中,使用这个:
import gettext
gettext.install('brainz', '../datas/translations/')
就这样! 这样就可以在整个项目中优雅而方便地使用_()
,而且是用标准的gettext
模块。不过,公平地说,如果你查看gettext的源代码,你会发现它使用了Elf建议的同样技巧。所以,从本质上讲,这也是纯粹的邪恶(tm)。但如果'brainz'模块只被你的应用使用,而不是被其他应用导入,那这样做是完全可以的。
如果你想把'brainz'分享给其他应用,你应该使用sdolan的方法:在每个模块中导入它。不过,再次提醒你,不要像之前那样使用bindtextdomain
和textdomain
,我建议你这样做:
import gettext
t = gettext.translation('brainz', '../datas/translations/')
_ = t.ugettext
不同之处在于使用gettext的基于类的API,而不是GNU gettext API。你可以查看官方文档了解原因。install
方法也是基于类的API的一部分。
顺便提一下:你会注意到文档建议使用pygettext
来替代GNU的xgettext
。不要! Pygettext是极其过时的,缺少很多功能。xgettext
要强大和灵活得多,完全支持Python。