Python和gettext的UTF-8错误

Mar*_*ing 6 python localization gettext

我在编辑器中使用UTF-8,因此这里显示的所有字符串都是文件中的UTF-8.

我有一个像这样的python脚本:

# -*- coding: utf-8 -*-
...
parser = optparse.OptionParser(
  description=_('automates the dice rolling in the classic game "risk"'), 
  usage=_("usage: %prog attacking defending"))
Run Code Online (Sandbox Code Playgroud)

然后我使用xgettext来解决所有问题并得到一个.pot文件,可以归结为:

"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"

#: auto_dice.py:16
msgid "automates the dice rolling in the classic game \"risk\""
msgstr ""
Run Code Online (Sandbox Code Playgroud)

之后,我使用msginit来获取de.po我填写的内容,如下所示:

"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: auto_dice.py:16
msgid "automates the dice rolling in the classic game \"risk\""
msgstr "automatisiert das Würfeln bei \"Risiko\""
Run Code Online (Sandbox Code Playgroud)

运行脚本,我收到以下错误:

  File "/usr/lib/python2.6/optparse.py", line 1664, in print_help
    file.write(self.format_help().encode(encoding, "replace"))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 60: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?

Tho*_*s K 7

该错误意味着您在字节串上调用了编码,因此它尝试使用系统默认编码(Python 2上的ascii)将其解码为Unicode,然后使用您指定的任何内容对其进行重新编码.

通常,解决它的方法是s.decode('utf-8')在尝试使用字符串之前调用(或字符串所在的任何编码).如果您只使用unicode文字,它也可能有效:( u'automates...'这取决于字符串如何从.po文件中替换,我不知道).

Python 3中改进了这种令人困惑的行为,除非你明确告诉它,否则不会尝试将字节转换为unicode.


Mik*_*kel 5

我怀疑是问题是由_("string")返回字节字符串而不是Unicode字符串引起的.

明显的解决方法是:

parser = optparse.OptionParser(
        description=_('automates the dice rolling in the classic game "risk"').decode('utf-8'),
        usage=_("usage: %prog attacking defending").decode('utf-8'))
Run Code Online (Sandbox Code Playgroud)

但这感觉不对.

ugettextinstall(True)可能有所帮助.

Python的gettext的文档给这些例子:

import gettext
t = gettext.translation('spam', '/usr/share/locale')
_ = t.ugettext
Run Code Online (Sandbox Code Playgroud)

要么:

import gettext
gettext.install('myapplication', '/usr/share/locale', unicode=1)
Run Code Online (Sandbox Code Playgroud)

我试图重现你的问题,即使我使用install(unicode=1),我得到一个字节字符串(str类型).

要么我错误地使用gettext,要么我在.po/.mo文件中缺少字符编码声明.

当我知道更多时,我会更新.

xlt = _('automates the dice rolling in the classic game "risk"')
print type(xlt)
if isinstance(xlt, str):
    print 'gettext returned a str (wrong)'
    print xlt
    print xlt.decode('utf-8').encode('utf-8')
elif isinstance(xlt, unicode):
    print 'gettext returned a unicode (right)'
    print xlt.encode('utf-8')
Run Code Online (Sandbox Code Playgroud)

(另一种可能性是在.po文件中使用转义符或Unicode代码点,但这听起来并不好玩.)

(或者您可以查看系统的.po文件以了解它们如何处理非ASCII字符.)