2011-04-04 33 views
6

Tôi sử dụng UTF-8 trong trình soạn thảo của mình, vì vậy tất cả các chuỗi được hiển thị ở đây là UTF-8 trong tệp.Lỗi UTF-8 với Python và gettext

Tôi có một kịch bản python như thế này:

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

Sau đó, tôi sử dụng xgettext để có được tất cả mọi thứ ra ngoài và có một tập tin .pot có thể được luộc xuống:

"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 "" 

Sau đó, Tôi đã sử dụng msginit để có được một số de.po mà tôi điền như sau:

"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\"" 

Chạy tập lệnh, tôi nhận được lỗi sau:

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) 

Làm cách nào để khắc phục điều đó?

+0

Loại '_ (" usage:% prog attack defending ")' là gì? tức là 'in loại gì (_ (" sử dụng:% prog tấn công phòng thủ "))' in? – Mikel

Trả lời

6

lỗi đó có nghĩa là bạn đã gọi mã hóa trên một bytestring, vì vậy nó sẽ cố gắng để giải mã nó sang Unicode bằng cách sử dụng mã hóa mặc định hệ thống (ascii trên Python 2), sau đó tái mã hóa nó với bất cứ điều gì bạn đã được specifi ed.

Nói chung, cách giải quyết nó là gọi s.decode('utf-8') (hoặc bất kỳ mã hóa chuỗi nào đang ở) trước khi cố gắng sử dụng các chuỗi. Nó cũng có thể hoạt động nếu bạn chỉ sử dụng các chữ cái unicode: u'automates...' (phụ thuộc vào cách các chuỗi được thay thế từ các tệp .po mà tôi không biết).

Loại hành vi khó hiểu này được cải thiện trong Python 3, điều này sẽ không cố gắng chuyển đổi byte thành unicode trừ khi bạn đặc biệt yêu cầu.

+0

chữ 'u" không hoạt động, nhưng 'giải mã (" utf-8 ")' hoạt động. Không phải là rất tốt đẹp, nhưng hoạt động. –

4

Nghi ngờ của tôi là vấn đề được gây ra bởi _("string") trả về một chuỗi byte chứ không phải chuỗi Unicode.

Cách giải quyết rõ ràng là thế này:

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

Nhưng mà cảm thấy sai.

ugettext hoặc install(True) có thể hữu ích.

Các Python gettext docs cung cấp cho các ví dụ:

import gettext 
t = gettext.translation('spam', '/usr/share/locale') 
_ = t.ugettext 

hay:

import gettext 
gettext.install('myapplication', '/usr/share/locale', unicode=1) 

tôi đang cố gắng để tái tạo vấn đề của bạn, và thậm chí nếu tôi sử dụng install(unicode=1), tôi nhận được trở lại một chuỗi byte (str loại).

Hoặc tôi đang sử dụng gettext không chính xác hoặc tôi thiếu một tuyên bố mã hóa ký tự trong tệp .po/.mo của tôi.

Tôi sẽ cập nhật khi tôi biết thêm.

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') 

(Một khả năng khác là sử dụng thoát hoặc điểm mã Unicode trong file .po, nhưng điều đó không hào hứng lắm đấy.)

(Hoặc bạn có thể nhìn vào .po file hệ thống của bạn để xem cách họ xử lý các ký tự không phải ASCII.)

Các vấn đề liên quan