Background: I'm one of the primary contributors to gae-boilerplate, an open source boilerplate project to help users jump start development on google app engine with webapp2 and the latest features. The latest feature i've worked on is i18n using Babel and gaepytz which is where the problem described below lies.
Problem: Translation is working with gettext but for translation of form error messages produced in our handlers and wtforms classes i need lazy_gettext as far as i'm aware. Lazy_gettext is not working when i call from webapp2_extras.i18n import lazy_gettext as _
in handlers.py. I get the below fatal error message when loading the page. It seems like the Babel Lazy proxy objects are created but then they are not invoked to render localized strings before being passed to a json serializer in the google app engine server code. I've looked through the babel sites, webapp2 docs (which i wish were more thorough), other frameworks, and some of the google code but I have not been able to figure out what i'm missing.
Error Message:
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
Environment details: All details about the version of python, webapp2, babel, etc can be found by scrolling down to the readme at github.com/coto/gae-boilerplate. I'm running the latest google app engine sdk 1.7.0
How to reproduce:
from webapp2_extras.i18n import gettext as _
in web/handlers.py with from webapp2_extras.i18n import lazy_gettext as _
Any help would be greatly appreciated and would undoubtedly help other users of this project and webapp2. Also if you do look through the code on github, any best practices tips would be a bonus. Thank you!
This is really old but maybe someone else has the same issue.
Lazy gettext wraps the translation process for later so it isn't a real string but a different type of object. Some json libs checks the type of the expresion you are trying to jsonify so it gives you an exception. To fix this you can trigger the translation using the unicode builtin.
Ex.
a = lazy_gettext("wololoh")
jsonify({'msg': a}) # this will throw an exception
jsonify({'msg': unicode(a)}) # this should work correctly
hope it's useful