使用python webapp2 babel在google app引擎上出现lazy_gettext错误

时间:2012-07-11 03:17:28

标签: google-app-engine internationalization webapp2 babel

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

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

错误消息:

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

环境详细信息:向下滚动到readme at github.com/coto/gae-boilerplate可以找到有关python,webapp2,babel等版本的所有详细信息。我正在运行最新的谷歌应用引擎sdk 1.7.0

如何重现

  1. https://github.com/coto/gae-boilerplate
  2. 下载代码
  3. 将web / handlers.py中的from webapp2_extras.i18n import gettext as _替换为from webapp2_extras.i18n import lazy_gettext as _
  4. 使用应用引擎开发服务器(https://developers.google.com/appengine/docs/python/tools/devserver提供的说明)
  5. 运行
  6. 注册或登录然后注销(localhost:8080 / logout /)。注销操作将产生一条flash消息,指示您已注销,这将触发错误,因为它是在logout处理程序中使用lazy_gettext包装消息生成的。
  7. 任何帮助都将非常感谢,无疑将帮助该项目的其他用户和webapp2。此外,如果您查看github上的代码,任何最佳实践技巧都将是一个奖励。 谢谢!

2 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:2)

这真的很古老,但也许其他人也有同样的问题。

Lazy gettext包含了以后的翻译过程,因此它不是真正的字符串,而是不同类型的对象。一些json libs检查你试图jsonify的expresion的类型,所以它给你一个例外。要解决此问题,您可以使用内置的unicode触发翻译。

实施例

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

希望它有用