【问题标题】:lazy_gettext error on google app engine with python webapp2 babelpython webapp2 babel在谷歌应用引擎上的lazy_gettext错误
【发布时间】:2012-07-10 14:55:22
【问题描述】:

背景:我是 gae-boilerplate 的主要贡献者之一,gae-boilerplate 是一个开源样板项目,旨在帮助用户快速开始使用 webapp2 和最新功能开发谷歌应用引擎。我使用的最新功能是使用 Babel 和 gaepytz 的 i18n,这就是下面描述的问题所在。

问题:据我所知,翻译正在使用 gettext,但要翻译在我们的处理程序和 wtforms 类中产生的表单错误消息,我需要lazy_gettext。当我在 handlers.py 中调用 from webapp2_extras.i18n import lazy_gettext as _ 时,Lazy_gettext 不起作用。加载页面时,我收到以下致命错误消息。似乎创建了 Babel Lazy 代理对象,但是在传递给谷歌应用引擎服务器代码中的 json 序列化程序之前,它们没有被调用来呈现本地化字符串。我浏览了 babel 站点、webapp2 文档(我希望更详尽)、其他框架和一些 google 代码,但我无法弄清楚我缺少什么。

错误信息:

Traceback (most recent call last):
File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2.py", line 1536, in __call__
  rv = self.handle_exception(request, response, e)
File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2.py", line 1530, in __call__
  rv = self.router.dispatch(request, response)
File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2.py", line 1278, in default_dispatcher
  return route.handler_adapter(request, response)
File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2.py", line 1102, in __call__
  return handler.dispatch()
File "H:\jesse\python_dev\workspace\gae-boilerplate\lib\basehandler.py", line 54, in dispatch
  self.session_store.save_sessions(self.response)
File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2_extras\sessions.py", line 420, in save_sessions
  session.save_session(response)
File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2_extras\sessions.py", line 205, in save_session
  response, self.name, dict(self.session), **self.session_args)
File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2_extras\sessions.py", line 423, in save_secure_cookie
  value = self.serializer.serialize(name, value)
File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2_extras\securecookie.py", line 47, in serialize
  value = self._encode(value)
File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2_extras\securecookie.py", line 92, in _encode
  return json.b64encode(value)
File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2_extras\json.py", line 84, in b64encode
  return base64.b64encode(encode(value, *args, **kwargs))
File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2_extras\json.py", line 55, in encode
  return json.dumps(value, *args, **kwargs).replace("</", "<\\/")
File "C:\Program Files (x86)\Google\google_appengine\lib\simplejson\simplejson\__init__.py", line 272, in dumps
  use_decimal=use_decimal, **kw).encode(obj)
File "C:\Program Files (x86)\Google\google_appengine\lib\simplejson\simplejson\encoder.py", line 216, in encode
  chunks = list(chunks)
File "C:\Program Files (x86)\Google\google_appengine\lib\simplejson\simplejson\encoder.py", line 485, in _iterencode
  for chunk in _iterencode_dict(o, _current_indent_level):
File "C:\Program Files (x86)\Google\google_appengine\lib\simplejson\simplejson\encoder.py", line 459, in _iterencode_dict
  for chunk in chunks:
File "C:\Program Files (x86)\Google\google_appengine\lib\simplejson\simplejson\encoder.py", line 380, in _iterencode_list
  for chunk in chunks:
File "C:\Program Files (x86)\Google\google_appengine\lib\simplejson\simplejson\encoder.py", line 380, in _iterencode_list
  for chunk in chunks:
File "C:\Program Files (x86)\Google\google_appengine\lib\simplejson\simplejson\encoder.py", line 495, in _iterencode
  o = _default(o)
File "C:\Program Files (x86)\Google\google_appengine\lib\simplejson\simplejson\encoder.py", line 190, in default
  raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <babel.support.LazyProxy object at 0x00000000084E81F8> is not JSON serializable

环境详情:所有关于python、webapp2、babel等版本的详情都可以通过向下滚动到readme at github.com/coto/gae-boilerplate找到。我正在运行最新的 google app engine sdk 1.7.0

如何重现

  1. https://github.com/coto/gae-boilerplate下载代码
  2. 将 web/handlers.py 中的 from webapp2_extras.i18n import gettext as _ 替换为 from webapp2_extras.i18n import lazy_gettext as _
  3. 使用应用引擎开发服务器运行(在https://developers.google.com/appengine/docs/python/tools/devserver 提供的说明)
  4. 注册或登录然后注销 (localhost:8080/logout/)。注销的行为将产生一条闪现消息,表明您已注销,这将触发错误,因为它是在注销处理程序中产生的,带有一个 lazy_gettext 包装的消息。

我们将不胜感激任何帮助,并且无疑会帮助该项目和 webapp2 的其他用户。此外,如果您确实浏览了 github 上的代码,那么任何最佳实践技巧都会是一个奖励。 谢谢!

【问题讨论】:

    标签: python google-app-engine internationalization webapp2 python-babel


    【解决方案1】:

    这确实很旧,但也许其他人也有同样的问题。

    懒惰的 gettext 将翻译过程包装起来以备后用,因此它不是真正的字符串,而是不同类型的对象。一些 json 库会检查您尝试 jsonify 的表达式的类型,因此它会给您一个异常。要解决此问题,您可以使用内置的 unicode 触发翻译。

    例如

    a = lazy_gettext("wololoh")
    jsonify({'msg': a}) # this will throw an exception
    jsonify({'msg': unicode(a)}) # this should work correctly
    

    希望有用

    【讨论】:

      【解决方案2】:

      Babel 有一个名为 LazyProxy 的自定义类,它基本上只是包装了一个函数,并且只有在它确实需要函数的返回值时才调用它。代理试图尽可能透明,但我假设 simplejson 检查实际的类对象,这就是它失败的地方。

      我不确定 simplejson 是否使用协议向未知类询问实例的可序列化版本(然后我们可以在 LazyProxy 中实现它)。

      如果您能以某种方式更改您的库,您还可以为 LazyProxy 实例创建一个自定义序列化程序(这应该非常简单)。另一种选择是找到 LazyProxy 实例并使用“proxy.value”来获取代理值(我假设它是 json-serializable)。

      【讨论】:

      • 非常感谢。一有机会我会试一试,然后告诉你进展如何。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-18
      相关资源
      最近更新 更多