【问题标题】:django problems with i18n Python 3i18n Python 3的django问题
【发布时间】:2014-11-28 07:04:39
【问题描述】:

我们正在用 i18n 编写一个复杂的网站。 为了使翻译更容易,我们将翻译保存在模型中。 我们的员工通过 django-admin 编写和编辑翻译。 翻译完成后,会启动一个管理脚本,该脚本会写入 po-files,然后为所有这些文件执行 djangos compilemessages。 我知道,必须使用 utf-8 编写 po 文件。 但是在打开应用程序后,当使用带有特殊字符(如西班牙语或法语)的语言时,我仍然收到错误“'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)”。 我做错了什么?

这是我的(缩短的)代码:

class Command(NoArgsCommand):

def handle_noargs(self, **options):

    languages = XLanguage.objects.all()
    currPath = os.getcwd()

    for lang in languages:

        path = "{}/framework/locale/{}/LC_MESSAGES/".format(currPath, lang.langToplevel)

        # check and create path
        create_path(path)

        # add filename
        path = path + "django.po"

        with codecs.open(path, "w", encoding='utf-8') as file:

            # select all textitems for this language from XTranslation

            translation = XTranslation.objects.filter(langID=lang)

            for item in translation:

                    # check if menu-item
                    if item.textID.templateID:
                        msgid = u"menu_{}_label".format(item.textID.templateID.id)
                    else:
                        msgid = u"{}".format (item.textID.text_id)

                    trans = u"{}".format (item.textTranslate)

                    text = u'msgid "{}"      msgstr "{}"\n'.format(msgid, trans)

                file.write(text)


        file.close()

追溯:

Environment:

Request Method: GET
Request URL: http://127.0.0.1:8000/

Django Version: 1.7
Python Version: 3.4.0
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'simple_history',
'datetimewidget',
'payroll',
'framework',
'portal',
'pool',
'billing')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'simple_history.middleware.HistoryRequestMiddleware')


Traceback:
File "c:\python34\lib\site-packages\django\core\handlers\base.py" in get_response
  111. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "E:\python\sarlex\framework\views.py" in init
   34. activate("de")
File "c:\python34\lib\site-packages\django\utils\translation\__init__.py" in activate
  145. return _trans.activate(language)
File "c:\python34\lib\site-packages\django\utils\translation\trans_real.py" in activate
  225. _active.value = translation(language)
File "c:\python34\lib\site-packages\django\utils\translation\trans_real.py" in translation
  210. current_translation = _fetch(language, fallback=default_translation)
File "c:\python34\lib\site-packages\django\utils\translation\trans_real.py" in _fetch
  195. res = _merge(apppath)
File "c:\python34\lib\site-packages\django\utils\translation\trans_real.py" in _merge
  177. t = _translation(path)
File "c:\python34\lib\site-packages\django\utils\translation\trans_real.py" in _translation
  159. t = gettext_module.translation('django', path, [loc], DjangoTranslation)
File "c:\python34\lib\gettext.py" in translation
  410. t = _translations.setdefault(key, class_(fp))
File "c:\python34\lib\site-packages\django\utils\translation\trans_real.py" in __init__
  107. gettext_module.GNUTranslations.__init__(self, *args, **kw)
File "c:\python34\lib\gettext.py" in __init__
  160. self._parse(fp)
File "c:\python34\lib\gettext.py" in _parse
  300. catalog[str(msg, charset)] = str(tmsg, charset)

Exception Type: UnicodeDecodeError at /
Exception Value: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)

【问题讨论】:

  • 对于文件顶部的第一次导入,请尝试from __future__ import unicode_literals。要么,要么在字符串前面加上u"menu_{}_label"。我不太确定您是否以编程方式打开它们。有一种可能性是,由于您传递的是字符串,而不是 unicode,所以它会抛出一些东西。如果这碰巧有效,我将提交此评论作为答案。

标签: django internationalization


【解决方案1】:

每当您遇到编码/解码错误时,都意味着您处理 Unicode 不正确。这通常是在您将 Unicode 与字节字符串混合时,这将提示 Python 2.x 使用默认编码 'ascii' 将您的字节字符串隐式解码为 Unicode,这就是您收到以下错误的原因:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)

避免这些错误的最佳方法是在您的程序中仅使用 Unicode,即您必须使用 'utf-8'(或您选择的其他 Unicode 编码)将所有输入字节字符串显式解码为 Unicode,并标记字符串在您的代码中作为 Unicode 类型,前缀为 u''。当你写出文件时,明确地用'utf-8'将这些编码回字节字符串。

具体到您的代码,我的猜测是

msgid = "menu_{}_label".format(item.textID.templateID.id)

text = 'msgid "{}"      msgstr "{}"\n'.format(msgid, item.textTranslate)

正在抛出错误。尝试通过像这样声明它们来制作 msgidtext Unicode 字符串而不是字节字符串:

msgid = u"menu_{}_label".format(item.textID.templateID.id)

text = u'msgid "{}"      msgstr "{}"\n'.format(msgid, item.textTranslate)

我假设item.textID.templateID.iditem.textTranslate 的值都是Unicode。如果不是(即它们是字节字符串),则必须先对其进行解码。

最后,这是一个关于如何在 Python 中处理 Unicode 的非常好的演示文稿:http://nedbatchelder.com/text/unipain.html。如果您从事大量 i18n 工作,我强烈建议您通过它。

编辑 1:由于 item.textID.templateID.iditem.textTranslate 是字节字符串,您的代码应该是:

for item in translation:
    # check if menu-item
    if item.textID.templateID:
        msgid = u"menu_{}_label".format(item.textID.templateID.id.decode('utf-8'))
    else:
        msgid = item.textID.text_id.decode('utf-8')  # you don't need to do u"{}".format() here since there's only one replacement field

    trans = item.textTranslate.decode('utf-8')  # same here, no need for u"{}".format()
    text = u'msgid "{}"      msgstr "{}"\n'.format(msgid, trans)  # msgid and trans should both be Unicode at this point
    file.write(text)

编辑 2:原始代码在 Python 3.x 中,因此上述所有内容均不适用。

【讨论】:

  • 感谢您的回答,特别感谢 oxymorOn 提供的演示文稿链接。我按照你的建议加了你。我还用 type () 检查了 item.textID.templateID.id 和 item.textTranslate,它们都返回 str。我还在写入文件之前检查了“文本”,它是 str to,但我仍然得到同样的错误
  • item.textID.templateID.id、item.textTranslate 和 text 的类型都应该是 Unicode,而不是 str。如果它们是 str 类型,请先使用 'utf-8' 解码您的字符串。让我知道他们是否仍然抛出异常。
  • 很抱歉再次打扰,但我无法进步。我更改了我的代码(请参阅上面的编辑代码)但它仍然不起作用:-(我想我仍然做错了什么,因为我是 python 新手
  • 我使用的是 python 3.4.2。并且解码消失了,因为 unicode 是字符串的默认值(为什么我不明白我遇到的问题)
  • 天哪,你应该说你从一开始就使用 3.x。我假设您使用 2.x。你能给我们完整的错误追溯吗?
【解决方案2】:

我遇到了同样的错误,这对我有帮助 https://stackoverflow.com/a/23278373/2571607

基本上,对我来说,这是 python 的问题。我的解决方案是,打开 C:\Python27\Lib\mimetypes.py

替换

‘default_encoding = sys.getdefaultencoding()’

if sys.getdefaultencoding() != 'gbk':  
    reload(sys)  
    sys.setdefaultencoding('gbk')  
default_encoding = sys.getdefaultencoding() 

【讨论】:

  • 我正在使用 Python 3 并且 default_encoding 不再存在。谢谢
【解决方案3】:

找到解决方案! 我将 msgid 和 msgstr 写在一行中,以空格分隔以使其更具可读性。 这适用于英语,但在具有特殊字符(如西班牙语或法语)的语言中会引发错误。 在 2 行中写入 msgid 和 msgstr 后,它就可以工作了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-10
    • 2014-02-25
    • 1970-01-01
    • 2015-04-17
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多