2013-02-18 134 views
2

我有以下代码,它应该在两个英文文本之间显示两行英文文本和一行罗马尼亚文本,但它只显示英文文本(翻译切换不起作用):在Python和gettext中切换翻译

main.py:

#! /usr/bin/env python2.7 

import gettext 
gettext.install('messages', '../i18n', unicode=True) 

import card 

if __name__ == '__main__': 
    x = card.Rank() 
    print x.j, x.a, x.q, x.k 

    ro = gettext.translation('messages', localedir='../i18n', languages=['ro']) 
    ro.install() 

    print x.j, x.a, x.q, x.k 

    en = gettext.translation('messages', localedir='../i18n', languages=['en']) 
    en.install() 

    print x.j, x.a, x.q, x.k 

card.py

class Suit(object): 
    clubs = _('Clubs'), 
    diamonds = _('Diamonds'), 
    hearts = _('Hearts'), 
    spades = _('Spades') 


class Rank(object): 
    j = _('Jack') 
    q = _('Queen') 
    k = _('King') 
    a = _('Ace') 


class Card(object): 
    # ... 

我的目录结构如下:

. 
├── i18n 
│   ├── en 
│   │   └── LC_MESSAGES 
│   │    └── messages.mo 
│   ├── en.po 
│   ├── en_US.po 
│   ├── ro 
│   │   └── LC_MESSAGES 
│   │    └── messages.mo 
│   ├── ro.po 
│   └── ro.pot 
├── Makefile 
├── README.md 
└── src 
    ├── card.py 
    ├── card.pyc 
    ├── deck.py 
    └── main.py 

我用xgettextmsgfmt生成.po.mo文件。

问题是,如果我只加载一种语言,文本被翻译(我必须在显示任何输出之前将其作为唯一的东西)。

#! /usr/bin/env python2.7 
import gettext 

if __name__ == '__main__': 
    ro = gettext.translation('messages', localedir='../i18n', languages=['ro']) 
    ro.install() 

    import card 
    x = card.Rank() 
    print x.j, x.a, x.q, x.k 

但是,如果我想动态更改语言,上面显示的第一个代码段所做的输出将不会被翻译。

我在做什么错了?我从文档中了解了什么错误?

回答

1

所有的gettext.install()都将_()函数定义为翻译文本的东西。在你的第一个例子中,在你的ro.install()调用之前你做了x = card.Rank() - 所以调用j = _('Jack')的唯一时间,_()将它翻译成默认的英文。随后,_()被重新定义为罗马尼亚语 - 但它永远不会被再次调用,因此永远不会被重新转换。

我希望这将工作:

#! /usr/bin/env python2.7 

import gettext 
gettext.install('messages', '../i18n', unicode=True) 

import card 

if __name__ == '__main__': 
    x = card.Rank() 
    print x.j, x.a, x.q, x.k 

    ro = gettext.translation('messages', localedir='../i18n', languages=['ro']) 
    ro.install() 

    x = card.Rank() 
    print x.j, x.a, x.q, x.k 

    en = gettext.translation('messages', localedir='../i18n', languages=['en']) 
    en.install() 

    x = card.Rank() 
    print x.j, x.a, x.q, x.k 
+0

不,它仍然不起作用。所有的信息都是英文的。 – Paul 2013-02-19 14:31:42

+2

是的,因为代码中的翻译是在类加载期间完成的,因为_()函数不是在构造函数中调用的,而是作为类定义的一部分。在这个答案中给出的解释是正确的,但是这个例子忽略了那个细节 – 02strich 2014-07-18 13:59:18

1

翻译通常为最终用户,而不是开发商。所以离开你的字符串作为密码文字,只有当你显示它们翻译:

class Rank(object): 
    j = 'Jack' 
    q = 'Queen' 
    k = 'King' 
    a = 'Ace' 

...

x = card.Rank() 
    print _(x.j), _(x.a), _(x.q), _(x.k) 

注意,列提取工具将无法再找到这些字符串除非你在你的代码中使用_()来调用它们。

如果你不想字符串手动添加到翻译文件,你可以像这样的东西添加到模块:

if False: 
    _('Jack') 
    _('Queen') 
    _('King') 
    _('Ace') 

或者这样:

assert(_('Jack')) 
assert(_('Queen')) 
assert(_('King')) 
assert(_('Ace')) 
0
x = card.Rank() 
print _(x.j), _(x.a), _(x.q), _(x.k) 

完全有效!

是的,字符串文字必须在你的代码中的某处。

字符串文字不需要在显示文本的相同模块中。将字符串文字放在同一个模块中并不漂亮(不是OOP)。

用py V2.7/GTK v2.24.10/gettext的0.18.1

python 
import gtk 
gtk.gtk_version 
(2, 24, 10) 

gettext --version 
gettext (GNU gettext-runtime) 0.18.1 

免责声明 获得的gettext你的Python应用程序的工作之前,不要尝试这个试验成功。包括能够即时更改语言环境(语言)。这些都不是什么小功夫。这将消除99%的混淆。然后,它将工作或不会。我说它会起作用!

+0

我会在晚上尝试这个。但我很好奇:gtk与我的问题有什么关系? – Paul 2013-04-08 06:54:38

+0

你的权利!在这种情况下,gtk不是必需的。 只有在包装应用程序时才使用gettext。其中很大一部分使用ui窗口库。 – faulkmore 2014-11-25 02:52:54