Commit caa80c71 authored by Fred Drake's avatar Fred Drake

Fix for issue 233 in the Zope 3 collector.

This corresponds to the Hotfix_2004-07-13 product.
parent f606e849
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<p>[foo](bar/{})</p> <p>[foo](bar/{})</p>
<a href="foo" alt="[default](alttext/{})">link</a> <a href="foo" alt="[default](alttext/{})">link</a>
<p>[dom](${name} was born in ${country}./{'country':'Antarctica','name':'Lomax'})</p> <p>[dom](${name} was born in ${country}./{'country':'Antarctica','name':'Lomax'})</p>
<p>[default](hmm/{'age':25})</p> <p>[default](hmm/{'age':'25'})</p>
</head> </head>
</body> </body>
</html> </html>
...@@ -19,7 +19,7 @@ from types import ListType, TupleType ...@@ -19,7 +19,7 @@ from types import ListType, TupleType
from ITALES import ITALESErrorInfo from ITALES import ITALESErrorInfo
TAL_VERSION = "1.4" TAL_VERSION = "1.5"
XML_NS = "http://www.w3.org/XML/1998/namespace" # URI for XML namespace XML_NS = "http://www.w3.org/XML/1998/namespace" # URI for XML namespace
XMLNS_NS = "http://www.w3.org/2000/xmlns/" # URI for XML NS declarations XMLNS_NS = "http://www.w3.org/2000/xmlns/" # URI for XML NS declarations
......
...@@ -352,9 +352,8 @@ class TALGenerator: ...@@ -352,9 +352,8 @@ class TALGenerator:
assert action == I18N_EXPRESSION assert action == I18N_EXPRESSION
key, expr = parseSubstitution(expression) key, expr = parseSubstitution(expression)
cexpr = self.compileExpression(expr) cexpr = self.compileExpression(expr)
# XXX Would key be anything but 'text' or None? self.emit('i18nVariable',
assert key in ('text', None) varname, program, cexpr, int(key == "structure"))
self.emit('i18nVariable', varname, program, cexpr)
def emitTranslation(self, msgid, i18ndata): def emitTranslation(self, msgid, i18ndata):
program = self.popProgram() program = self.popProgram()
...@@ -783,7 +782,8 @@ class TALGenerator: ...@@ -783,7 +782,8 @@ class TALGenerator:
# - I18N_CONTENT for tal:content # - I18N_CONTENT for tal:content
# - I18N_EXPRESSION for explicit tal:replace # - I18N_EXPRESSION for explicit tal:replace
# o varname[2] will be None for the first two actions and the # o varname[2] will be None for the first two actions and the
# replacement tal expression for the third action. # replacement tal expression for the third action. This
# can include a 'text' or 'structure' indicator.
assert (varname[1] assert (varname[1]
in [I18N_REPLACE, I18N_CONTENT, I18N_EXPRESSION]) in [I18N_REPLACE, I18N_CONTENT, I18N_EXPRESSION])
self.emitI18nVariable(varname) self.emitI18nVariable(varname)
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
""" """
Interpreter for a pre-compiled TAL program. Interpreter for a pre-compiled TAL program.
""" """
import cgi
import sys import sys
import getopt import getopt
import re import re
...@@ -496,7 +496,7 @@ class TALInterpreter: ...@@ -496,7 +496,7 @@ class TALInterpreter:
bytecode_handlers["insertText"] = do_insertText bytecode_handlers["insertText"] = do_insertText
def do_i18nVariable(self, stuff): def do_i18nVariable(self, stuff):
varname, program, expression = stuff varname, program, expression, structure = stuff
if expression is None: if expression is None:
# The value is implicitly the contents of this tag, so we have to # The value is implicitly the contents of this tag, so we have to
# evaluate the mini-program to get the value of the variable. # evaluate the mini-program to get the value of the variable.
...@@ -510,7 +510,14 @@ class TALInterpreter: ...@@ -510,7 +510,14 @@ class TALInterpreter:
else: else:
# Evaluate the value to be associated with the variable in the # Evaluate the value to be associated with the variable in the
# i18n interpolation dictionary. # i18n interpolation dictionary.
if structure:
value = self.engine.evaluateStructure(expression)
else:
value = self.engine.evaluate(expression) value = self.engine.evaluate(expression)
if not structure:
value = cgi.escape(str(value))
# Either the i18n:name tag is nested inside an i18n:translate in which # Either the i18n:name tag is nested inside an i18n:translate in which
# case the last item on the stack has the i18n dictionary and string # case the last item on the stack has the i18n dictionary and string
# representation, or the i18n:name and i18n:translate attributes are # representation, or the i18n:name and i18n:translate attributes are
......
<span tal:replace="string:<foo>" />
<span i18n:translate="">
<span tal:replace="string:<foo>" i18n:name="name1" />
<span tal:replace="structure string:<bar />" i18n:name="name2" />
<span i18n:name="name3"><b>some</b> <i>text</i></span>
</span>
&lt;foo&gt;
<span>&lt;foo&gt; <bar /> <b>some</b> <i>text</i></span>
...@@ -594,7 +594,8 @@ translated string</span> ...@@ -594,7 +594,8 @@ translated string</span>
('span', ('span',
[('tal:replace', 'str:Lomax', 'tal'), [('tal:replace', 'str:Lomax', 'tal'),
('i18n:name', 'name', 'i18n')]))], ('i18n:name', 'name', 'i18n')]))],
'$str:Lomax$')), '$str:Lomax$',
0)),
('rawtextBeginScope', ('rawtextBeginScope',
(' was born in\n ', (' was born in\n ',
2, 2,
...@@ -607,7 +608,8 @@ translated string</span> ...@@ -607,7 +608,8 @@ translated string</span>
('span', ('span',
[('tal:replace', 'str:Antarctica', 'tal'), [('tal:replace', 'str:Antarctica', 'tal'),
('i18n:name', 'country', 'i18n')]))], ('i18n:name', 'country', 'i18n')]))],
'$str:Antarctica$')), '$str:Antarctica$',
0)),
('endScope', ()), ('endScope', ()),
('rawtextColumn', ('.\n', 0))])), ('rawtextColumn', ('.\n', 0))])),
('endScope', ()), ('endScope', ()),
...@@ -638,7 +640,8 @@ translated string</span> ...@@ -638,7 +640,8 @@ translated string</span>
('', ('',
[('insertText', ('$bar$', []))])), [('insertText', ('$bar$', []))])),
('rawtextOffset', ('</span>', 7))], ('rawtextOffset', ('</span>', 7))],
None)), None,
0)),
('endScope', ()), ('endScope', ()),
('rawtextOffset', ('.', 1))])), ('rawtextOffset', ('.', 1))])),
('endScope', ()), ('endScope', ()),
...@@ -662,12 +665,12 @@ translated string</span> ...@@ -662,12 +665,12 @@ translated string</span>
[('rawtextBeginScope', ('\n ', 2, (2, 2), 0, {'i18n:name': 'name'})), [('rawtextBeginScope', ('\n ', 2, (2, 2), 0, {'i18n:name': 'name'})),
('i18nVariable', ('i18nVariable',
('name', ('name',
[('rawtextOffset', ('<b>Jim</b>', 10))], None)), [('rawtextOffset', ('<b>Jim</b>', 10))], None, 0)),
('rawtextBeginScope', ('rawtextBeginScope',
(' was born in\n ', 2, (3, 2), 1, {'i18n:name': 'country'})), (' was born in\n ', 2, (3, 2), 1, {'i18n:name': 'country'})),
('i18nVariable', ('i18nVariable',
('country', ('country',
[('rawtextOffset', ('the USA', 7))], None)), [('rawtextOffset', ('the USA', 7))], None, 0)),
('endScope', ()), ('endScope', ()),
('rawtextColumn', ('.\n', 0))])), ('rawtextColumn', ('.\n', 0))])),
('endScope', ()), ('endScope', ()),
...@@ -782,7 +785,7 @@ translated string</span> ...@@ -782,7 +785,7 @@ translated string</span>
[('i18n:data', 'here/currentTime', 'i18n'), [('i18n:data', 'here/currentTime', 'i18n'),
('i18n:translate', 'timefmt', 'i18n'), ('i18n:translate', 'timefmt', 'i18n'),
('i18n:name', 'time', 'i18n')])), ('i18n:name', 'time', 'i18n')])),
('i18nVariable', ('time', [], None))], ('i18nVariable', ('time', [], None, 0))],
'$here/currentTime$')), '$here/currentTime$')),
('endScope', ()), ('endScope', ()),
('rawtextOffset', ('... beep!', 9))])), ('rawtextOffset', ('... beep!', 9))])),
...@@ -816,7 +819,8 @@ translated string</span> ...@@ -816,7 +819,8 @@ translated string</span>
('i18n:name', 'jobnum', 'i18n')])), ('i18n:name', 'jobnum', 'i18n')])),
('rawtextOffset', ('NN', 2)), ('rawtextOffset', ('NN', 2)),
('rawtextOffset', ('</span>', 7))], ('rawtextOffset', ('</span>', 7))],
'$context/@@object_name$')), '$context/@@object_name$',
0)),
('endScope', ())])), ('endScope', ())])),
('endScope', ()), ('endScope', ()),
('rawtextColumn', ('</span>\n', 0)) ('rawtextColumn', ('</span>\n', 0))
...@@ -860,7 +864,8 @@ translated string</span> ...@@ -860,7 +864,8 @@ translated string</span>
[('rawtextOffset', ('user@host.com', 13))])), [('rawtextOffset', ('user@host.com', 13))])),
('endScope', ()), ('endScope', ()),
('rawtextOffset', ('</a>', 4))], ('rawtextOffset', ('</a>', 4))],
None)), None,
0)),
('endScope', ()), ('endScope', ()),
('rawtextColumn', ('\n', 0))])), ('rawtextColumn', ('\n', 0))])),
('endScope', ()), ('endScope', ()),
...@@ -900,7 +905,8 @@ translated string</span> ...@@ -900,7 +905,8 @@ translated string</span>
('$request/submitter$', ('$request/submitter$',
[('rawtextOffset', ('user@host.com', 13))])), [('rawtextOffset', ('user@host.com', 13))])),
('rawtextOffset', ('</a>', 4))], ('rawtextOffset', ('</a>', 4))],
None)), None,
0)),
('endScope', ()), ('endScope', ()),
('rawtextColumn', ('\n', 0))])), ('rawtextColumn', ('\n', 0))])),
('endScope', ()), ('endScope', ()),
......
...@@ -94,7 +94,7 @@ class I18NCornerTestCase(TestCaseBase): ...@@ -94,7 +94,7 @@ class I18NCornerTestCase(TestCaseBase):
'<div>THIS IS TEXT FOR <span>BARVALUE</span>.</div>\n') '<div>THIS IS TEXT FOR <span>BARVALUE</span>.</div>\n')
def test_translate_static_text_as_dynamic_from_bytecode(self): def test_translate_static_text_as_dynamic_from_bytecode(self):
program = [('version', '1.4'), program = [('version', '1.5'),
('mode', 'html'), ('mode', 'html'),
('setPosition', (1, 0)), ('setPosition', (1, 0)),
('beginScope', {'i18n:translate': ''}), ('beginScope', {'i18n:translate': ''}),
...@@ -116,7 +116,8 @@ class I18NCornerTestCase(TestCaseBase): ...@@ -116,7 +116,8 @@ class I18NCornerTestCase(TestCaseBase):
('', ('',
[('insertText', ('$bar$', []))])), [('insertText', ('$bar$', []))])),
('rawtextOffset', ('</span>', 7))], ('rawtextOffset', ('</span>', 7))],
None)), None,
0)),
('endScope', ()), ('endScope', ()),
('rawtextOffset', ('.', 1))])), ('rawtextOffset', ('.', 1))])),
('endScope', ()), ('endScope', ()),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment