appy.gen: solved a tricky encoding problem.
This commit is contained in:
parent
d5f26dd1df
commit
c1174fac79
|
@ -1 +1 @@
|
||||||
0.7.1
|
0.8.0
|
||||||
|
|
|
@ -2556,8 +2556,7 @@ class Transition:
|
||||||
notifier.sendMail(obj.appy(), self, transitionName, wf)
|
notifier.sendMail(obj.appy(), self, transitionName, wf)
|
||||||
# Return a message to the user if needed
|
# Return a message to the user if needed
|
||||||
if not doSay or (transitionName == '_init_'): return
|
if not doSay or (transitionName == '_init_'): return
|
||||||
if not msg:
|
if not msg: msg = 'Changes saved.' # XXX Translate
|
||||||
msg = obj.translate(u'Changes saved.')
|
|
||||||
obj.say(msg)
|
obj.say(msg)
|
||||||
|
|
||||||
class Permission:
|
class Permission:
|
||||||
|
|
|
@ -370,15 +370,21 @@ class ToolMixin(BaseMixin):
|
||||||
maxWidth = appyType['width']
|
maxWidth = appyType['width']
|
||||||
if isinstance(value, str): value = value.decode('utf-8')
|
if isinstance(value, str): value = value.decode('utf-8')
|
||||||
if len(value) > maxWidth:
|
if len(value) > maxWidth:
|
||||||
return value[:maxWidth] + '...'
|
return value[:maxWidth].encode('utf-8') + '...'
|
||||||
return value
|
return value.encode('utf-8')
|
||||||
|
|
||||||
def truncateText(self, text, width=15):
|
def truncateText(self, text, width=15):
|
||||||
'''Truncates p_text to max p_width chars. If the text is longer than
|
'''Truncates p_text to max p_width chars. If the text is longer than
|
||||||
p_width, the truncated part is put in a "acronym" html tag.'''
|
p_width, the truncated part is put in a "acronym" html tag.'''
|
||||||
if isinstance(text, str): text = text.decode('utf-8')
|
# p_text has to be unicode-encoded for being truncated (else, one char
|
||||||
if len(text) <= width: return text
|
# may be spread on 2 chars). But this method must return an encoded
|
||||||
return '<acronym title="%s">%s</acronym>' % (text, text[:width] + '...')
|
# string, else, ZPT crashes. The same remark holds for m_truncateValue
|
||||||
|
# above.
|
||||||
|
uText = text # uText will store the unicode version
|
||||||
|
if isinstance(text, str): uText = text.decode('utf-8')
|
||||||
|
if len(uText) <= width: return text
|
||||||
|
return '<acronym title="%s">%s</acronym>' % \
|
||||||
|
(text, uText[:width].encode('utf-8') + '...')
|
||||||
|
|
||||||
def getPublishedObject(self):
|
def getPublishedObject(self):
|
||||||
'''Gets the currently published object, if its meta_class is among
|
'''Gets the currently published object, if its meta_class is among
|
||||||
|
@ -820,9 +826,8 @@ class ToolMixin(BaseMixin):
|
||||||
urlBack = rq['HTTP_REFERER']
|
urlBack = rq['HTTP_REFERER']
|
||||||
|
|
||||||
if jsEnabled and not cookiesEnabled:
|
if jsEnabled and not cookiesEnabled:
|
||||||
msg = self.translate(u'You must enable cookies before you can ' \
|
msg = 'You must enable cookies before you can log in.' # XXX transl.
|
||||||
'log in.')
|
return self.goto(urlBack, msg)
|
||||||
return self.goto(urlBack, msg.encode('utf-8'))
|
|
||||||
# Perform the Zope-level authentication
|
# Perform the Zope-level authentication
|
||||||
login = rq.get('__ac_name', '')
|
login = rq.get('__ac_name', '')
|
||||||
password = rq.get('__ac_password', '')
|
password = rq.get('__ac_password', '')
|
||||||
|
@ -832,12 +837,11 @@ class ToolMixin(BaseMixin):
|
||||||
user = self.acl_users.validate(rq)
|
user = self.acl_users.validate(rq)
|
||||||
if self.userIsAnon():
|
if self.userIsAnon():
|
||||||
rq.RESPONSE.expireCookie('__ac', path='/')
|
rq.RESPONSE.expireCookie('__ac', path='/')
|
||||||
msg = self.translate(u'Login failed')
|
msg = 'Login failed' # XXX to translate
|
||||||
logMsg = 'Authentication failed (tried with login "%s")' % login
|
logMsg = 'Authentication failed (tried with login "%s")' % login
|
||||||
else:
|
else:
|
||||||
msg = self.translate(u'Welcome! You are now logged in.')
|
msg = 'Welcome! You are now logged in.' # XXX to translate
|
||||||
logMsg = 'User "%s" has been logged in.' % login
|
logMsg = 'User "%s" has been logged in.' % login
|
||||||
msg = msg.encode('utf-8')
|
|
||||||
self.log(logMsg)
|
self.log(logMsg)
|
||||||
# Bring Managers to the config, leave others on the main page.
|
# Bring Managers to the config, leave others on the main page.
|
||||||
user = self.getUser()
|
user = self.getUser()
|
||||||
|
|
|
@ -184,7 +184,7 @@ class BaseMixin:
|
||||||
fields in the database.'''
|
fields in the database.'''
|
||||||
rq = self.REQUEST
|
rq = self.REQUEST
|
||||||
tool = self.getTool()
|
tool = self.getTool()
|
||||||
errorMessage = self.translate('Please correct the indicated errors.')
|
errorMessage = 'Please correct the indicated errors.' # XXX Translate
|
||||||
isNew = rq.get('is_new') == 'True'
|
isNew = rq.get('is_new') == 'True'
|
||||||
# If this object is created from an initiator, get info about him.
|
# If this object is created from an initiator, get info about him.
|
||||||
initiator = None
|
initiator = None
|
||||||
|
@ -205,7 +205,7 @@ class BaseMixin:
|
||||||
urlBack = tool.getSiteUrl()
|
urlBack = tool.getSiteUrl()
|
||||||
else:
|
else:
|
||||||
urlBack = self.getUrl()
|
urlBack = self.getUrl()
|
||||||
self.say(self.translate('Changes canceled.'))
|
self.say('Changes canceled.') # XXX Translate
|
||||||
return self.goto(urlBack)
|
return self.goto(urlBack)
|
||||||
|
|
||||||
# Object for storing validation errors
|
# Object for storing validation errors
|
||||||
|
@ -241,7 +241,7 @@ class BaseMixin:
|
||||||
obj, msg = self.createOrUpdate(isNew, values, initiator, initiatorField)
|
obj, msg = self.createOrUpdate(isNew, values, initiator, initiatorField)
|
||||||
|
|
||||||
# Redirect the user to the appropriate page
|
# Redirect the user to the appropriate page
|
||||||
if not msg: msg = obj.translate('Changes saved.')
|
if not msg: msg = 'Changes saved.' # XXX Translate
|
||||||
# If the object has already been deleted (ie, it is a kind of transient
|
# If the object has already been deleted (ie, it is a kind of transient
|
||||||
# object like a one-shot form and has already been deleted in method
|
# object like a one-shot form and has already been deleted in method
|
||||||
# onEdit), redirect to the main site page.
|
# onEdit), redirect to the main site page.
|
||||||
|
@ -1058,7 +1058,7 @@ class BaseMixin:
|
||||||
instead of returning a list of string values, the result is a list
|
instead of returning a list of string values, the result is a list
|
||||||
of tuples (s_value, s_translation). If p_withBlankValue is True, a
|
of tuples (s_value, s_translation). If p_withBlankValue is True, a
|
||||||
blank value is prepended to the list. If no p_className is defined,
|
blank value is prepended to the list. If no p_className is defined,
|
||||||
the field is supposed to belong to self's class'''
|
the field is supposed to belong to self's class.'''
|
||||||
appyType = self.getAppyType(name, className=className)
|
appyType = self.getAppyType(name, className=className)
|
||||||
if className:
|
if className:
|
||||||
# We need an instance of className, but self can be an instance of
|
# We need an instance of className, but self can be an instance of
|
||||||
|
@ -1333,51 +1333,40 @@ class BaseMixin:
|
||||||
p_mapping.'''
|
p_mapping.'''
|
||||||
cfg = self.getProductConfig()
|
cfg = self.getProductConfig()
|
||||||
if not domain: domain = cfg.PROJECTNAME
|
if not domain: domain = cfg.PROJECTNAME
|
||||||
if domain != cfg.PROJECTNAME:
|
# Get the label name, and the field-specific mapping if any.
|
||||||
# We need to translate something that is in a standard Zope catalog
|
if field:
|
||||||
try:
|
# p_field is the dict version of a appy type or group
|
||||||
res = self.Control_Panel.TranslationService.utranslate(
|
if field['type'] != 'group':
|
||||||
domain, label, mapping, self, default=default,
|
fieldMapping = field['mapping'][label]
|
||||||
target_language=language)
|
if fieldMapping:
|
||||||
except AttributeError:
|
if callable(fieldMapping):
|
||||||
# When run in test mode, Zope does not create the
|
appyField = self.getAppyType(field['name'])
|
||||||
# TranslationService
|
fieldMapping=appyField.callMethod(self,fieldMapping)
|
||||||
res = label
|
mapping.update(fieldMapping)
|
||||||
else:
|
label = field['%sId' % label]
|
||||||
# Get the label name, and the field-specific mapping if any.
|
# We will get the translation from a Translation object.
|
||||||
if field:
|
# In what language must we get the translation?
|
||||||
# p_field is the dict version of a appy type or group
|
if not language: language = self.getUserLanguage()
|
||||||
if field['type'] != 'group':
|
tool = self.getTool()
|
||||||
fieldMapping = field['mapping'][label]
|
try:
|
||||||
if fieldMapping:
|
translation = getattr(tool, language).appy()
|
||||||
if callable(fieldMapping):
|
except AttributeError:
|
||||||
appyField = self.getAppyType(field['name'])
|
# We have no translation for this language. Fallback to 'en'.
|
||||||
fieldMapping=appyField.callMethod(self,fieldMapping)
|
translation = getattr(tool, 'en').appy()
|
||||||
mapping.update(fieldMapping)
|
res = getattr(translation, label, '')
|
||||||
label = field['%sId' % label]
|
if not res:
|
||||||
# We will get the translation from a Translation object.
|
# Fallback to 'en'.
|
||||||
# In what language must we get the translation?
|
translation = getattr(tool, 'en').appy()
|
||||||
if not language: language = self.getUserLanguage()
|
|
||||||
tool = self.getTool()
|
|
||||||
try:
|
|
||||||
translation = getattr(tool, language).appy()
|
|
||||||
except AttributeError:
|
|
||||||
# We have no translation for this language. Fallback to 'en'.
|
|
||||||
translation = getattr(tool, 'en').appy()
|
|
||||||
res = getattr(translation, label, '')
|
res = getattr(translation, label, '')
|
||||||
if not res:
|
# If still no result, put the label instead of a translated message
|
||||||
# Fallback to 'en'.
|
if not res: res = label
|
||||||
translation = getattr(tool, 'en').appy()
|
else:
|
||||||
res = getattr(translation, label, '')
|
# Perform replacements, according to p_format.
|
||||||
# If still no result, put the label instead of a translated message
|
res = self.formatText(res, format)
|
||||||
if not res: res = label
|
# Perform variable replacements
|
||||||
else:
|
for name, repl in mapping.iteritems():
|
||||||
# Perform replacements, according to p_format.
|
if not isinstance(repl, basestring): repl = str(repl)
|
||||||
res = self.formatText(res, format)
|
res = res.replace('${%s}' % name, repl)
|
||||||
# Perform variable replacements
|
|
||||||
for name, repl in mapping.iteritems():
|
|
||||||
if not isinstance(repl, basestring): repl = str(repl)
|
|
||||||
res = res.replace('${%s}' % name, repl)
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getPageLayout(self, layoutType):
|
def getPageLayout(self, layoutType):
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
_ python: tool.translate;
|
_ python: tool.translate;
|
||||||
req python: request;
|
req python: request;
|
||||||
resp req/RESPONSE;
|
resp req/RESPONSE;
|
||||||
x python: resp.setHeader('Content-Type', 'text/html;;charset=utf-8');
|
x python: resp.setHeader('Content-Type', 'text/html;;charset=UTF-8');
|
||||||
x python: resp.setHeader('Expires', 'Thu, 11 Dec 1975 12:05:00 GMT+2');
|
x python: resp.setHeader('Expires', 'Thu, 11 Dec 1975 12:05:00 GMT+2');
|
||||||
x python: resp.setHeader('Content-Language', req.get('language', 'en'))">
|
x python: resp.setHeader('Content-Language', req.get('language', 'en'))">
|
||||||
|
|
||||||
|
|
|
@ -13,17 +13,17 @@ class UserWrapper(AbstractWrapper):
|
||||||
'''Is this p_login valid?'''
|
'''Is this p_login valid?'''
|
||||||
# The login can't be the id of the whole site or "admin"
|
# The login can't be the id of the whole site or "admin"
|
||||||
if login == 'admin':
|
if login == 'admin':
|
||||||
return self.translate('This username is reserved.')
|
return 'This username is reserved.' # XXX Translate
|
||||||
# Check that no user or group already uses this login.
|
# Check that no user or group already uses this login.
|
||||||
if self.count('User', login=login) or self.count('Group', login=login):
|
if self.count('User', login=login) or self.count('Group', login=login):
|
||||||
return self.translate('This login is already in use.')
|
return 'This login is already in use.' # XXX Translate
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def validatePassword(self, password):
|
def validatePassword(self, password):
|
||||||
'''Is this p_password valid?'''
|
'''Is this p_password valid?'''
|
||||||
# Password must be at least 5 chars length
|
# Password must be at least 5 chars length
|
||||||
if len(password) < 5:
|
if len(password) < 5:
|
||||||
return self.translate('Passwords must contain at least 5 letters.')
|
return 'Passwords must contain at least 5 letters.' # XXX Translate
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def showPassword(self):
|
def showPassword(self):
|
||||||
|
@ -43,7 +43,8 @@ class UserWrapper(AbstractWrapper):
|
||||||
page = self.request.get('page', 'main')
|
page = self.request.get('page', 'main')
|
||||||
if page == 'main':
|
if page == 'main':
|
||||||
if hasattr(new, 'password1') and (new.password1 != new.password2):
|
if hasattr(new, 'password1') and (new.password1 != new.password2):
|
||||||
msg = self.translate('Passwords do not match.')
|
# XXX Translate
|
||||||
|
msg = 'Passwords do not match.'
|
||||||
errors.password1 = msg
|
errors.password1 = msg
|
||||||
errors.password2 = msg
|
errors.password2 = msg
|
||||||
return self._callCustom('validate', new, errors)
|
return self._callCustom('validate', new, errors)
|
||||||
|
|
Loading…
Reference in a new issue