[ZPT] CVS: Zope/lib/python/TAL - TALInterpreter.py:1.74
Florent Guillaume
fg@nuxeo.com
Sun, 6 Oct 2002 13:21:09 -0400
Update of /cvs-repository/Zope/lib/python/TAL
In directory cvs.zope.org:/tmp/cvs-serv11392/lib/python/TAL
Modified Files:
TALInterpreter.py
Log Message:
Merged changes from the Zope-2_6-branch:
Modified the translation service to return None if no translation exist.
So now using i18n tags without a translation service should give the
same behavior as before. The tests reflect that.
=== Zope/lib/python/TAL/TALInterpreter.py 1.73 => 1.74 ===
--- Zope/lib/python/TAL/TALInterpreter.py:1.73 Tue Sep 24 17:59:57 2002
+++ Zope/lib/python/TAL/TALInterpreter.py Sun Oct 6 13:21:09 2002
@@ -47,6 +47,23 @@
return ' '.join(text.split())
+NAME_RE = r"[a-zA-Z][a-zA-Z0-9_]*"
+_interp_regex = re.compile(r'(?<!\$)(\$(?:%(n)s|{%(n)s}))' %({'n': NAME_RE}))
+_get_var_regex = re.compile(r'%(n)s' %({'n': NAME_RE}))
+
+def interpolate(text, mapping):
+ """Interpolate ${keyword} substitutions."""
+ if not mapping:
+ return text
+ # Find all the spots we want to substitute.
+ to_replace = _interp_regex.findall(text)
+ # Now substitute with the variables in mapping.
+ for string in to_replace:
+ var = _get_var_regex.findall(string)[0]
+ text = text.replace(string, mapping.get(var))
+ return text
+
+
class AltTALGenerator(TALGenerator):
def __init__(self, repldict, expressionCompiler=None, xml=0):
@@ -348,7 +365,11 @@
def i18n_attribute(self, s):
# s is the value of an attribute before translation
# it may have been computed
- return self.translate(s, {})
+ xlated = self.translate(s, {})
+ if xlated is None:
+ return s
+ else:
+ return xlated
def no_tag(self, start, program):
state = self.saveState()
@@ -518,25 +539,35 @@
# subnodes, which should /not/ go to the output stream.
tmpstream = self.StringIO()
self.interpretWithStream(stuff[1], tmpstream)
+ content = None
# We only care about the evaluated contents if we need an implicit
# message id. All other useful information will be in the i18ndict on
# the top of the i18nStack.
if msgid == '':
- msgid = normalize(tmpstream.getvalue())
+ content = tmpstream.getvalue()
+ msgid = normalize(content)
self.i18nStack.pop()
# See if there is was an i18n:data for msgid
if len(stuff) > 2:
obj = self.engine.evaluate(stuff[2])
xlated_msgid = self.translate(msgid, i18ndict, obj)
- # XXX I can't decide whether we want to cgi escape the translated
- # string or not. OT1H not doing this could introduce a cross-site
- # scripting vector by allowing translators to sneak JavaScript into
- # translations. OTOH, for implicit interpolation values, we don't
- # want to escape stuff like ${name} <= "<b>Timmy</b>".
- #s = escape(xlated_msgid)
- s = xlated_msgid
+ # If there is no translation available, use evaluated content.
+ if xlated_msgid is None:
+ if content is None:
+ content = tmpstream.getvalue()
+ # We must do potential substitutions "by hand".
+ s = interpolate(content, i18ndict)
+ else:
+ # XXX I can't decide whether we want to cgi escape the translated
+ # string or not. OT1H not doing this could introduce a cross-site
+ # scripting vector by allowing translators to sneak JavaScript into
+ # translations. OTOH, for implicit interpolation values, we don't
+ # want to escape stuff like ${name} <= "<b>Timmy</b>".
+ #s = escape(xlated_msgid)
+ s = xlated_msgid
# If there are i18n variables to interpolate into this string, better
# do it now.
+ # XXX efge: actually, this is already done by the translation service.
self._stream_write(s)
bytecode_handlers['insertTranslation'] = do_insertTranslation