将wxPython应用程序做成多语言支持
我有一个用wxPython写的应用程序,想让它支持多种语言。我们有以下两个选择:
- 使用gettext http://docs.python.org/library/gettext.html
- 把所有的界面文本分离到一个messages.py文件中,然后用这个文件来翻译文本
我更倾向于第二种方法,因为我觉得用第二种方法可以把所有的消息集中在一个地方,而不是分散在代码里。如果我需要修改某条消息,就不需要改代码。而如果用gettext,我可能会搞混消息常量,因为我只是把原始消息包裹起来,而不是把它转换成messages.py中的常量。
基本上,我觉得
wx.MessageBox(_("Hi stackoverflow!"))
这样做
wx.MessageBox(messages.GREET_SO)
更好。那么,使用gettext有什么好处,而第二种方法有什么缺点呢?还有没有第三种方法呢?
补充说明:
而且gettext的语言文件似乎和代码联系得太紧了。如果我想在英语中用同样的消息,但在法语中用不同的表达,比如法语在不同场景下有更细腻的翻译,而英语的表达就比较简单,这该怎么办呢?
经验分享:
我已经采用了第二种方法,我必须说每个应用程序都应该尝试把界面文本从代码中提取出来,这样可以重新组织代码,看看界面是如何渗透到模型中的,以及界面文本可以如何改进。相比之下,gettext的方式比较机械,对程序员没有太多帮助,我觉得维护起来会更困难。
而且在给文本起名字时,比如PRINT_PROGRESS_MSG,可以看到在很多地方同样的消息被稍微不同地使用,这样可以合并成一个名字,这在我需要只改一次消息的时候会很有帮助。
总结:我仍然不确定使用gettext有什么优势,目前我在用自己的消息文件。不过我选择了一个答案,至少解释了一些gettext可能带来的好处。我的最终解决方案是结合两种方法的优点,也就是用我自己的消息标识符包裹gettext,比如:
wx.MessageBox(_("GREET_SO"))
3 个回答
在网页开发中(这里用的是PHP,但这个思路是一样的),我通常会在一个特定的文件夹里创建多个语言文件,比如 en.php、fr.php 等等。这些文件里定义了所有输出文本的内容,都是用特定语言写的。用户选择的语言决定了哪个文件会被加载,从而决定输出的语言是什么。举个例子……
在 en.php 文件里: TEXT_I_AM = "I am"
在 fr.php 文件里: TEXT_I_AM = "Je suis"
gettext 有一些优点:
- 最大的优点之一是:使用 poedit 进行翻译时,你可以利用翻译数据库。简单来说,poedit 可以扫描你的硬盘,找到已经翻译过的文件,并在你翻译时给出建议。
- 当你把代码交给其他人翻译时,他们可能已经熟悉 gettext 的翻译方式,而你就不需要再向他们解释你的翻译方法。
- 你可以在代码的上下文中看到文本,这样在翻译时会更容易,因为你能看到与翻译相关的代码。
- 比如有这样的文本:
print _('%d files of %d files selected') % (num, numTotal)
,还有更复杂的情况。在这种情况下,看到周围的代码真的很有帮助……
Gettext 是一个很好的选择。在你的例子中,你也可以使用 gettext 来“避免把翻译直接写在代码里”。
wx.MessageBox(messages.GREET_SO)
这可能和使用 gettext 是一样的:
wx.MessageBox(_("GREET_SO")) or wx.MessageBox(_("messages.GREET_SO"))
Gettext 基本上是多语言应用的标准,我相信你将来会从中受益。举个例子,你可以使用 Poedit(或者其他类似的应用)来给你的合作者或贡献者分配翻译任务,之后你还可以标记一些信息为翻译不准确。如果有缺失或多余的翻译,Poedit 也会提醒你。别自欺欺人了,gettext 是维护翻译的唯一可靠方法。