#278 closed defect (fixed)
advanced-18n: an i18n:msg gets partially translated
Reported by: | cboos | Owned by: | palgarvio |
---|---|---|---|
Priority: | major | Milestone: | 0.6 |
Component: | Internationalization | Version: | devel |
Keywords: | i18n:msg | Cc: | cboos@… |
Description
This is with genshi's branches/experimental/advanced-i18n@966.
The following html snippet in a Trac template, added in [T7727]:
<div i18n:msg=""> <label>View changes from <input type="text" size="10" name="from" value="${format_date(fromdate)}" /></label> <br /> and <label><input type="text" size="3" name="daysback" value="$daysback" /> days back</label><br /> <label>done by <input type="text" size="16" name="author" value="$author" /></label> </div>
gets extracted like that:
#: trac/timeline/templates/timeline.html:20 msgid "" "[1:View changes from [2:]] [3:]\n" " and [4:[5:] days back][6:]\n" " [7:done by [8:]]" msgstr "" "[1:Afficher les modifications entre le : [2:]] [3:]\n" " et les : [4:[5:] jours précédents][6:]\n" " [7:Auteur : [8:]]"
The extraction seems to be correct.
But the translated text skips the "days back" (default language) or "jours précédents" (fr_FR) part.
The generated HTML is (in the default language):
<div><label>View changes from </label><input type="text" size="10" name="from" value="11/22/2008" /> <br /> and <label><input type="text" size="3" name="daysback" value="30" /></label><br /> <label>done by </label><input type="text" size="16" name="author" value="" /></div> <fieldset> <label> <input type="checkbox" name="changeset" checked="checked" /> Repository checkins </label><label> <input type="checkbox" name="milestone" checked="checked" /> Milestones </label><label> <input type="checkbox" name="wiki" checked="checked" /> Wiki changes </label> </fieldset> <div class="buttons"> <input type="submit" name="update" value="Update" /> </div>
(no "days back" on second line)
Attachments (2)
Change History (25)
comment:1 Changed 16 years ago by cboos
- Cc cboos@… added
- Summary changed from advanced-18n: n i18n:msg gets partially translated to advanced-18n: an i18n:msg gets partially translated
comment:2 Changed 16 years ago by palgarvio
- Owner changed from palgarvio to cmlenz
- Version changed from 0.5.1 to devel
comment:3 Changed 16 years ago by palgarvio
- Owner changed from cmlenz to palgarvio
Needed to reassign to cmlenz because I can't add him to CC directly.
comment:4 Changed 16 years ago by palgarvio
This can, although, be fixed on this branch since ticket #129 is also related to advanced i18n stuff, though that exact piece of code was cmlenz's work, he knows more about that part.
Either way, when I find the time, probably Friday, I'll have a deep look at it.
comment:5 Changed 16 years ago by palgarvio
A test just changing the place holders does not correct the issue:
-
genshi/filters/tests/i18n.py
192 192 tmpl.add_directives(Translator.NAMESPACE, translator) 193 193 messages = list(translator.extract(tmpl.stream)) 194 194 self.assertEqual(1, len(messages)) 195 self.assertEqual('Please see [1:Help]for details.', messages[0][2])195 self.assertEqual('Please see {{1:Help}} for details.', messages[0][2]) 196 196 197 197 def test_translate_i18n_msg(self): 198 198 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" … … 201 201 Please see <a href="help.html">Help</a> for details. 202 202 </p> 203 203 </html>""") 204 gettext = lambda s: u"Für Details siehe bitte [1:Hilfe]."204 gettext = lambda s: u"Für Details siehe bitte {{1:Hilfe}}." 205 205 translator = Translator(gettext) 206 206 setup_i18n(tmpl, translator) 207 207 self.assertEqual("""<html> … … 219 219 tmpl.add_directives(Translator.NAMESPACE, translator) 220 220 messages = list(translator.extract(tmpl.stream)) 221 221 self.assertEqual(1, len(messages)) 222 self.assertEqual('Please see [1:[2:Help] page] for details.',222 self.assertEqual('Please see {{1:{{2:Help}} page}} for details.', 223 223 messages[0][2]) 224 224 225 225 def test_translate_i18n_msg_nested(self): … … 229 229 Please see <a href="help.html"><em>Help</em> page</a> for details. 230 230 </p> 231 231 </html>""") 232 gettext = lambda s: u"Für Details siehe bitte [1:[2:Hilfeseite]]."232 gettext = lambda s: u"Für Details siehe bitte {{1:{{2:Hilfeseite}}}}." 233 233 translator = Translator(gettext) 234 234 setup_i18n(tmpl, translator) 235 235 self.assertEqual("""<html> … … 247 247 tmpl.add_directives(Translator.NAMESPACE, translator) 248 248 messages = list(translator.extract(tmpl.stream)) 249 249 self.assertEqual(1, len(messages)) 250 self.assertEqual('Show me [1:] entries per page.', messages[0][2])250 self.assertEqual('Show me {{1:}} entries per page.', messages[0][2]) 251 251 252 252 def test_translate_i18n_msg_empty(self): 253 253 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" … … 256 256 Show me <input type="text" name="num" /> entries per page. 257 257 </p> 258 258 </html>""") 259 gettext = lambda s: u" [1:] Einträge pro Seite anzeigen."259 gettext = lambda s: u"{{1:}} Einträge pro Seite anzeigen." 260 260 translator = Translator(gettext) 261 261 setup_i18n(tmpl, translator) 262 262 self.assertEqual("""<html> … … 274 274 tmpl.add_directives(Translator.NAMESPACE, translator) 275 275 messages = list(translator.extract(tmpl.stream)) 276 276 self.assertEqual(1, len(messages)) 277 self.assertEqual('Please see [1:Help] for [2:details].', messages[0][2])277 self.assertEqual('Please see {{1:Help}} for {{2:details}}.', messages[0][2]) 278 278 279 279 def test_translate_i18n_msg_multiple(self): 280 280 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" … … 283 283 Please see <a href="help.html">Help</a> for <em>details</em>. 284 284 </p> 285 285 </html>""") 286 gettext = lambda s: u"Für [2:Details] siehe bitte [1:Hilfe]."286 gettext = lambda s: u"Für {{2:Details}} siehe bitte {{1:Hilfe}}." 287 287 translator = Translator(gettext) 288 288 setup_i18n(tmpl, translator) 289 289 self.assertEqual("""<html> … … 301 301 tmpl.add_directives(Translator.NAMESPACE, translator) 302 302 messages = list(translator.extract(tmpl.stream)) 303 303 self.assertEqual(1, len(messages)) 304 self.assertEqual('Show me [1:] entries per page, starting at page [2:].',304 self.assertEqual('Show me {{1:}} entries per page, starting at page {{2:}}.', 305 305 messages[0][2]) 306 306 307 307 def test_translate_i18n_msg_multiple_empty(self): … … 311 311 Show me <input type="text" name="num" /> entries per page, starting at page <input type="text" name="num" />. 312 312 </p> 313 313 </html>""") 314 gettext = lambda s: u" [1:] Einträge pro Seite, beginnend auf Seite [2:]."314 gettext = lambda s: u"{{1:}} Einträge pro Seite, beginnend auf Seite {{2:}}." 315 315 translator = Translator(gettext) 316 316 setup_i18n(tmpl, translator) 317 317 self.assertEqual("""<html> … … 366 366 Hello, <a href="#${anchor}">dude</a>! 367 367 </p> 368 368 </html>""") 369 gettext = lambda s: u"Sei gegrüßt, [1:Alter]!"369 gettext = lambda s: u"Sei gegrüßt, {{1:Alter}}!" 370 370 translator = Translator(gettext) 371 371 setup_i18n(tmpl, translator) 372 372 self.assertEqual("""<html> … … 415 415 tmpl.add_directives(Translator.NAMESPACE, translator) 416 416 messages = list(translator.extract(tmpl.stream)) 417 417 self.assertEqual(1, len(messages)) 418 self.assertEqual('Show me [1:] entries per page.', messages[0][2])418 self.assertEqual('Show me {{1:}} entries per page.', messages[0][2]) 419 419 420 420 def test_translate_i18n_msg_with_directive(self): 421 421 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" … … 424 424 Show me <input type="text" name="num" py:attrs="{'value': 'x'}" /> entries per page. 425 425 </p> 426 426 </html>""") 427 gettext = lambda s: u" [1:] Einträge pro Seite anzeigen."427 gettext = lambda s: u"{{1:}} Einträge pro Seite anzeigen." 428 428 translator = Translator(gettext) 429 429 setup_i18n(tmpl, translator) 430 430 self.assertEqual("""<html> … … 1182 1182 tmpl.add_directives(Translator.NAMESPACE, translator) 1183 1183 messages = list(translator.extract(tmpl.stream)) 1184 1184 self.assertEqual(1, len(messages)) 1185 self.assertEqual((3, None, u'Please see [1:Help] for details.', []),1185 self.assertEqual((3, None, u'Please see {{1:Help}} for details.', []), 1186 1186 messages[0]) 1187 1187 1188 1188 def test_extract_i18n_msg_with_py_strip_and_comment(self): … … 1196 1196 tmpl.add_directives(Translator.NAMESPACE, translator) 1197 1197 messages = list(translator.extract(tmpl.stream)) 1198 1198 self.assertEqual(1, len(messages)) 1199 self.assertEqual((3, None, u'Please see [1:Help] for details.',1199 self.assertEqual((3, None, u'Please see {{1:Help}} for details.', 1200 1200 ['Foo']), messages[0]) 1201 1201 1202 1202 def test_extract_i18n_choose_as_attribute_and_py_strip(self): -
genshi/filters/i18n.py
===================================================================
92 92 >>> 93 93 >>> setup_i18n(tmpl, translator) 94 94 >>> 95 >>> list(translator.extract(tmpl.stream)) 96 [(2, None, u'[1:Foo]\n [2:Bar]', []), (6, None, u'Foo [1:bar]!', [])] 95 >>> list(translator.extract(tmpl.stream)) #doctest: +NORMALIZE_WHITESPACE 96 [(2, None, u'{{1:Foo}}\n {{2:Bar}}', []), 97 (6, None, u'Foo {{1:bar}}!', [])] 97 98 >>> print tmpl.generate().render() 98 99 <html> 99 100 <div><p>Foo</p> … … 110 111 ... </html>''') 111 112 >>> setup_i18n(tmpl, translator) 112 113 >>> list(translator.extract(tmpl.stream)) #doctest: +NORMALIZE_WHITESPACE 113 [(2, None, u' [1:First Name: %(fname)s]\n [2:Last Name: %(lname)s]', []),114 (6, None, u'Foo [1:bar]!', [])]114 [(2, None, u'{{1:First Name: %(fname)s}}\n {{2:Last Name: %(lname)s}}', 115 []), (6, None, u'Foo {{1:bar}}!', [])] 115 116 >>> 116 117 >>> tmpl = MarkupTemplate('''<html xmlns:i18n="http://genshi.edgewall.org/i18n"> 117 118 ... <div i18n:msg="fname, lname"> … … 985 986 self.values[param] = (kind, data, pos) 986 987 else: 987 988 if kind is START: 988 self.string.append(u' [%d:' % self.order)989 self.string.append(u'{{%d:' % self.order) 989 990 self.events.setdefault(self.order, []).append((kind, data, pos)) 990 991 self.stack.append(self.order) 991 992 self.depth += 1 … … 994 995 self.depth -= 1 995 996 if self.depth: 996 997 self.events[self.stack[-1]].append((kind, data, pos)) 997 self.string.append(u' ]')998 self.string.append(u'}}') 998 999 self.stack.pop() 999 1000 1000 1001 def format(self): … … 1028 1029 break 1029 1030 1030 1031 1031 def parse_msg(string, regex=re.compile(r'(?:\ [(\d+)\:)|\]')):1032 def parse_msg(string, regex=re.compile(r'(?:\{\{(\d+)\:)|\}\}')): 1032 1033 """Parse a translated message using Genshi mixed content message 1033 1034 formatting. 1034 1035 1035 >>> parse_msg("See [1:Help].")1036 >>> parse_msg("See {{1:Help}}.") 1036 1037 [(0, 'See '), (1, 'Help'), (0, '.')] 1037 1038 1038 >>> parse_msg("See [1:our [2:Help] page]for details.")1039 >>> parse_msg("See {{1:our {{2:Help}} page}} for details.") 1039 1040 [(0, 'See '), (1, 'our '), (2, 'Help'), (1, ' page'), (0, ' for details.')] 1040 1041 1041 >>> parse_msg(" [2:Details] finden Sie in [1:Hilfe].")1042 >>> parse_msg("{{2:Details}} finden Sie in {{1:Hilfe}}.") 1042 1043 [(2, 'Details'), (0, ' finden Sie in '), (1, 'Hilfe'), (0, '.')] 1043 1044 1044 >>> parse_msg(" [1:]Bilder pro Seite anzeigen.")1045 >>> parse_msg("{{1:}} Bilder pro Seite anzeigen.") 1045 1046 [(1, ''), (0, ' Bilder pro Seite anzeigen.')] 1046 1047 1047 1048 :param string: the translated message string
This must then be related with the Message Buffer.
comment:6 Changed 16 years ago by palgarvio
The above testcase mimics the failure you talk about.
What apparently happens is that since an input field does not hold any text like <a href="/foo">Foo</a> does, it's being neglected, let's see if I'm right.
comment:7 Changed 16 years ago by palgarvio
Could you please try the above fix to see if you find any more problems?
comment:8 Changed 16 years ago by cboos
Thanks for the patch, I'll test it soon.
Changed 16 years ago by palgarvio
comment:9 Changed 16 years ago by palgarvio
Updated the fix patch with a simpler version.
comment:10 follow-up: ↓ 11 Changed 16 years ago by cboos
I confirm that the fix works (both patches), and it seems that there's no bad side-effects.
comment:11 in reply to: ↑ 10 Changed 16 years ago by palgarvio
- Status changed from new to assigned
Replying to cboos:
I confirm that the fix works (both patches), and it seems that there's no bad side-effects.
Ok, I'll check these changes in, Thanks!
comment:12 Changed 16 years ago by palgarvio
- Resolution set to fixed
- Status changed from assigned to closed
Fixed in [967].
comment:13 follow-up: ↓ 14 Changed 16 years ago by cboos
- Resolution fixed deleted
- Status changed from closed to reopened
I've seen it again today with [T8107], when running advanced-i18n at r1028.
The following translation:
#: trac/templates/error.html:131 msgid "" "Before you do that, though, please first try\n" " [1:[2:searching]\n" " for similar issues], as it is quite likely that this " "problem\n" " has been reported before. For questions about " "installation\n" " and configuration of Trac, please try the\n" " [3:mailing list]\n" " instead of filing a ticket." msgstr "" "Avant de faire cela, [1:veuillez au préalable essayer de\n" " [2:trouver]\n" " d'éventuels rapports similaires], car il est probable que" " ce problème\n" " ait déjà été reporté. Pour des questions concernant " "l'installation\n" " et la configuration de Trac, veuillez utiliser la\n" " [3:liste de diffusion]\n" " plutôt que de créer un ticket."
appears like this in the generated HTML:
Avant de faire cela, veuillez au préalable essayer de trouver, car il est probable que ce problème ...
i.e. d'éventuels rapports similaires is missing.
The untranslated string is displayed correctly, with r1028.
What is eventually interesting is that with r966, the untranslated string becomes:
Before you do that, though, please first try searching, as it is quite likely
i.e. for similar issues is missing here as well.
comment:14 in reply to: ↑ 13 Changed 16 years ago by cboos
comment:15 follow-up: ↓ 16 Changed 16 years ago by cboos
The comment:13 issue is still present with [1057].
comment:16 in reply to: ↑ 15 Changed 16 years ago by palgarvio
Replying to cboos:
The comment:13 issue is still present with [1057].
Hmm, I'm unable to confirm the issue, for me it renders well. The catalog part, for pt_PT:
#: trac/timeline/templates/timeline.html:20 msgid "" "[1:View changes from [2:]] [3:]\n" " and [4:[5:] days back][6:]\n" " [7:done by [8:]]" msgstr "" "[1:Ver mudanças desde [2:]] [3:]\n" " e à [4:[5:] dias atrás][6:]\n" " [7:feitas por [8:]]"
The rendered html:
<label>Ver mudanças desde </label><input size="10" name="from" value="13/05/09" type="text"> <br> e à <label><input size="3" name="daysback" value="30" type="text"> dias atrás</label><br> <label>feitas por </label><input size="16" name="authors" value="" type="text">
For the fr_FR locale:
<label>Afficher les modifications entre le </label><input size="10" name="from" value="13/05/09" type="text"> <br> et les <label><input size="3" name="daysback" value="30" type="text"> jours précédents</label><br> <label>Auteur : </label><input size="16" name="authors" value="" type="text">
Which also appears correct.
Did you re-{extracted/updated/compiled} the French catalog?
comment:17 Changed 16 years ago by palgarvio
I'm on [T8197].
comment:18 Changed 16 years ago by palgarvio
cboos can this be closed?
comment:19 follow-up: ↓ 21 Changed 16 years ago by cboos
Well, in comment:16 you just tried the specific example shown in the original description, and this is indeed working fine now.
But I reopened the ticket because I detected a very similar problem elsewhere, please read comment:13, and I definitely still have that problem with latest Trac [T8199], [G1057], Babel 0.9.4 and Python 2.6.
I noticed that the structure of the embedding is slightly different in the translation than in the original, for the French translation:
English:
text \n [1:[2: text ] \n text ] text \n ...
French:
text [1: text [2: text ] \n text ] text \n ...
Is this allowed? (I hope so). Could that be the problem?
comment:20 Changed 16 years ago by cboos
(and it also still happens with [1058])
comment:21 in reply to: ↑ 19 Changed 16 years ago by palgarvio
Replying to cboos:
Well, in comment:16 you just tried the specific example shown in the original description, and this is indeed working fine now.
But I reopened the ticket because I detected a very similar problem elsewhere, please read comment:13, and I definitely still have that problem with latest Trac [T8199], [G1057], Babel 0.9.4 and Python 2.6.
I noticed that the structure of the embedding is slightly different in the translation than in the original, .....
Is this allowed? (I hope so). Could that be the problem?
Yes, the problem is the restructure of the phrase. I'll see if I can get MessageBuffer to handle that though.
comment:22 Changed 16 years ago by palgarvio
- Resolution set to fixed
- Status changed from reopened to closed
Fixed in [1059].
comment:23 Changed 16 years ago by cboos
Verified, thanks!
This seems to be non-related to the adavanced-i18n branch since the same happens with current trunk and is probably also related to the unfinished work on #129. Chris, how about this ticket, have an idea?