python:在 __init__.py 中处处使用 gettext

5 投票
3 回答
4168 浏览
提问于 2025-04-16 04:49

我想在我的应用程序中使用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 个回答

4

这真是个坏主意,但确实能达到你想要的效果。在你项目的 _init.py 文件里,做以下操作:

from django.utils.translation import ugettext
import __builtin__
__builtin__.__dict__['_'] = ugettext

现在,带下划线的 将会 在任何地方变成 ugettext。其他的回答也提到了一些注意事项;修改 Python 的内置列表并不是个好主意,这肯定会让那些不熟悉的人感到困惑。

5

通配符导入不会导入以下划线开头的内容。

使用通配符不好,因为它会弄乱命名空间,导致难以发现的错误。而且,下划线有时用来表示一个未使用的变量。

最好在需要的地方进行导入。只需要一行代码,打起来也不难,你还可以在你的开发工具中创建一个代码片段来方便使用。

更新:更多不使用通配符的理由,请查看 http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#importing

5

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的方法:在每个模块中导入它。不过,再次提醒你,不要像之前那样使用bindtextdomaintextdomain,我建议你这样做:

import gettext
t = gettext.translation('brainz', '../datas/translations/')
_ = t.ugettext

不同之处在于使用gettext的基于类的API,而不是GNU gettext API。你可以查看官方文档了解原因。install方法也是基于类的API的一部分。

顺便提一下:你会注意到文档建议使用pygettext来替代GNU的xgettext不要! Pygettext是极其过时的,缺少很多功能。xgettext要强大和灵活得多,完全支持Python。

撰写回答