我可以在一个库和同时使用它的模块中调用并设置Python的gettext模块吗?
我正在编写一个库,这个库需要包含一些文本反馈,而这些反馈需要翻译。
我在一个叫 _config.py
的模块里写了以下几行代码,这个模块在我的应用中到处都用到:
import gettext, os, sys
pathname = os.path.dirname(sys.argv[0])
localdir = os.path.abspath(pathname) + "/locale"
gettext.install("messages", localdir)
我把 *.mo
文件放在 ./locale/lang_LANG/LC_MESSAGES
这个文件夹里,并且我对所有需要翻译的字符串都使用了 _()
这个函数。
现在我刚刚添加了一个功能,让用户(假设是程序员)可以创建自己的消息。我不想让他们去关心底层的实现,所以我希望他们能用一种简单的方式来做,比如:
lib_object.message = "My message"
我使用了属性来保持代码的整洁,但如果我的用户想要翻译他们自己的代码(而这个代码又是基于我的库),并且做了类似这样的事情:
import gettext, os, sys
pathname = os.path.dirname(sys.argv[0])
localdir = os.path.abspath(pathname) + "/locale"
gettext.install("user_app", localdir)
lib_object.message = _("My message")
这样会有问题吗?我该怎么做才能避免麻烦,同时又不打扰到我的用户呢?
2 个回答
你只能使用 gettext.install() 一次。一般来说,这个函数在库的开发中没什么用处——因为 gettext.install() 只有在调用它的模块负责整个程序时才会正常工作,因为它只会提供一个可以加载的目录。库的代码应该像 Mailman 那样做:为 gettext() 创建一个自己的封装,传递正确的参数给这个模块,然后在每个想要使用它的模块中将其导入为 '_'。
你可以使用基于类的gettext API来管理消息目录,这也是在Python gettext文档中推荐的做法。
不过,这样做的缺点是你或者其他开发者需要使用gettext方法,或者在本地范围内定义一个_()
方法,并把它绑定到特定的gettext类上。下面是一个拥有自己字符串目录的类的例子:
import gettext
class MyClass(object):
def __init__(self, locale_for_instance):
self.lang = gettext.translation("appname", localedir, \
locale=locale_for_instance)
def some_method(self, arg):
return self.lang.gettext("You called some method")
def other_method(self, arg): # does the same thing
_ = self.lang.gettext
return _("You called some method")
你可以把添加_()
方法的代码放在一个装饰器里,这样所有需要这个方法的函数前面都可以加上类似@with_local_gettext
的标记。
(注意,我没有测试过上面的代码,但它应该能正常工作。)
如果你的目标是让用户使用起来更方便(而且他可能不太懂),我想你可以在代码中使用基于类的方法,让用户使用全局的方法。