如何同时使用多个.mo文件进行gettext转换?

时间:2012-01-15 18:30:55

标签: python plugins internationalization gettext

简而言之,我可以同时在python中使用同一种语言的许多.mo个文件吗?

在我的python应用程序中,我需要将gettext用于I18N。这个应用程序使用一种插件系统。这意味着你可以下载一个插件并将其放在适当的目录中,它就像任何其他python包一样运行。主应用程序存储它使用的.mo文件,例如./locale/en/LC_MESSAGES/main.mo。插件nr 1在同一目录中有自己的.mo文件plugin1.mo

我会用它来加载main.mo I18N消息:

gettext.install('main', './locale', unicode=False)

我如何安装其他插件,以便所有插件按照应有的方式进行翻译?

我想到的解决方案:

我应该在每个包的命名空间中gettext.install()吗?但是这会覆盖先前定义的_()并弄乱主应用程序的未来翻译。

有没有办法将两个.mo文件合二为一(例如安装新的插件时)?

在运行时,我可以将它们组合成一个GNUTranslation对象吗?或者覆盖添加到全局命名空间的默认_()方法?然后,我将如何选择该选项? 我会使用_('Hello World')

而不是_('plugin1', 'Hello World in plug-in 1')

注意:应用程序不应该知道要安装的所有插件,因此它不能将所有消息都翻译在其main.mo文件中。

2 个答案:

答案 0 :(得分:3)

gettext.install()将不可更改的版本_安装到内置版本(模块__builtin__或{3}}中的py3) - app-global。这种方式没有灵活性 注意:Python名称解析顺序为:locals> module-globals> builtins。

因此,无论如何builtins(基于类的API)或甚至gettext.translation()(例如,对于自定义.mo路径方案)将明确地用于分别具有多个翻译或同时具有混合风格。

一些选项:

  • 通过gettext.GNUTranslations(),你可以简单地将t = gettext.translation(...); _ = t.ugettext单独翻译成每个模块 - 全局命名空间 - 在现实世界中可能更加自动化。也许主翻译也可能会进入内置函数(通过_)。

  • 如果所有/多个翻译的混合都可以,或者您想要的是什么,您可以通过main_t.install()全局链接多个翻译 - 并保留应用程序全局方法。

  • 可以使用_以外的gettext关键字 - 并且可以通过t.install(); t.add_fallback(t_plugin1); t.add_fallback(t_plugin1);...;选项提供。但我不喜欢冗长且模块独特的名字 (但我个人更喜欢关键字xgettext -k other_keyword通常超过I,我还启用了_而非I % "some text"_("some text")的运营商方案.Via {{ 1}}有效;加上一小段 pygettext.py 。这个模式更适合打字,看起来更具可读性和Pythonic给我,并避免了{{1}的关键/丑陋名称冲突在交互式Python提示中使用gettext' ed模块时,在Python中使用了interactive-last-result-anaphor(参见I("some text"))。I = t; t.__call__ = t.__mod__ = t.ugettext也是"保留"作为我的首选(本地)占位符,用于_等表达式中未使用的值 毕竟sys.displayhook是一个相当简单的模块&机制,事情很容易在Python中自定义。)

答案 1 :(得分:1)

您应该为每个插件使用不同的。域名可以是包名称以防止冲突。

我不明白为什么你需要使用插件的域来翻译插件之外的东西,但如果你真的需要,那么你应该每次都消除域的歧义。

每个插件都可以提供它自己的“非核心”,很容易绑定到插件的域名:

from my.plugin import MessageFactory as _my_plugin

请注意,下划线只是一种约定,因此提取工具可以在程序中找到支持i18n的消息。插件的消息应该在各自的包中用下划线标记(你确实将它们放在单独的包中,对吧?)。在所有其他地方,您可以通过其他名称自由调用这些工厂,并为主程序翻译域留下下划线。

我对.mo文件不太了解,但您肯定可以将所有.po文件编译成一个.mo文件。但是,如果插件是由独立的不合作作者编写的,则可能存在msgid冲突。

更新:

如果插件与主应用程序位于同一个包中,那么为他们使用单独的翻译域是没有意义的(这不是您的情况)。如果插件位于单独的包中,则应该针对这些包单独进行提取。在这两种情况下,变量_都没有问题。如果由于某种原因主应用程序在其代码中需要插件的翻译,请使用_的其他名称,如答案中所示。当然,提取工具除了下划线外不会识别任何东西。

换句话说,插件应该自己关心他们的翻译。主应用程序可以使用插件特定的翻译功能作为插件API的一部分。将字符串提取或手动添加到po / mo文件中也不是主要应用程序所关注的问题:它是插件作者提供翻译。

相关问题