背景:我是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
如何重现:
from webapp2_extras.i18n import gettext as _
替换为from webapp2_extras.i18n import lazy_gettext as _
任何帮助都将非常感谢,无疑将帮助该项目的其他用户和webapp2。此外,如果您查看github上的代码,任何最佳实践技巧都将是一个奖励。 谢谢!
答案 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
希望它有用