1

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

问题:翻译正在使用gettext,但要翻译在我们的处理程序和wtforms类中产生的表单错误消息,据我所知,我需要lazy_gettext。当我调用 handlers.py 时,Lazy_gettext 不起作用from webapp2_extras.i18n import lazy_gettext as _。加载页面时,我收到以下致命错误消息。似乎创建了 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 等版本的所有详细信息可以通过向下滚动到github.com/coto/gae-boilerplate 的自述文件找到。我正在运行最新的 google app engine sdk 1.7.0

如何重现

  1. 从https://github.com/coto/gae-boilerplate下载代码
  2. from webapp2_extras.i18n import gettext as _在 web/handlers.py 中替换为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 上的代码,那么任何最佳实践技巧都会是一个奖励。谢谢!

4

2 回答 2

2

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

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

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

于 2012-07-23T19:20:06.070 回答
2

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

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

前任。

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

希望它有用

于 2014-07-09T18:35:20.240 回答