Edgewall Software
Modify

Ticket #238 (new enhancement)

Opened 4 years ago

Last modified 4 years ago

Make recursive message extraction work from inside Genshi builder expressions

Reported by: hasienda <hoff.st@…> Owned by: cmlenz
Priority: major Milestone: 1.0
Component: Message Extraction Version: 0.9.5
Keywords: Genshi builder tag_ Cc: martin@…

Description

While doing i18n for [th:wiki:WatchlistPlugin WatchlistPlugin] I came across some strings missing from extraction and did some further investigation. The relevant code section after initial i18n Python code markup read as:

            raise WatchlistError(
                    tag_("Please ", tag.a("log in",
                         href=req.href('login')),
                         " to view or change your watchlist!")
            )

but only the first string got extracted. Then I did some variations on the code to find at least a quick workaround, but

            raise WatchlistError(
                    tag_("Please ", tag_.a("log in",
                         href=req.href('login')),
                         " to view or change your watchlist!")
            )
            raise WatchlistError(
                    tag_("Please ", tag.a(_("log in"),
                         href=req.href('login')),
                         _(" to view or change your watchlist!"))
            )

all did not work any better.

Finally I got the desired behavior by avoiding the tag_ wrapper for tag Genshi builder call at all:

            raise WatchlistError(
                    tag(_("Please "), tag.a(_("log in"),
                         href=req.href('login')),
                         _(" to view or change your watchlist!"))
            )

This changed extraction to the expected result (snippet from POT file)

  • plugin.po

     
    66msgid "Please " 
    77msgstr "Bitte " 
    88 
     9#: tracwatchlist/plugin.py:268 
     10msgid "log in" 
     11msgstr "" 
     12 
     13#: tracwatchlist/plugin.py:270 
     14msgid " to view or change your watchlist!" 
     15msgstr "" 
     16 
    917#: tracwatchlist/plugin.py:339 
    1018msgid "You are now watching this resource." 
    1119msgstr "" 

Shouldn't it be possible to do a markup as shown and get all three strings? The tag_ call seems to just recognize the first string and prevent processing of following code inside the same expression and expressions nested in it, even if all strings have proper translation helper markup.

Additionally it would be more consistent (= clever + really nice), if extraction of similar nested Python code could produce not three but just one string with special markup for the link, as it is already working with equivalent code in Genshi HTML templates, provided the <p> or <div> tag surrounding link and other strings has attribute i18n:msg"" attached properly.

Attachments

Change History

comment:1 Changed 4 years ago by Martin Scharrer <martin@…>

  • Cc martin@… added

comment:2 Changed 4 years ago by hasienda <hoff.st@…>

  • Summary changed from Extraction missing form inside Genshi builder expressions to Extraction missing from inside Genshi builder expressions

now listing some code versions potentially relevant for this report:

  • Python 2.5.2 (r252:60911, Jan 24 2010, 14:53:14) [GCC 4.3.2]
  • setuptools 0.6c9
  • Babel 1.0dev-r482
  • Genshi 0.7dev-r1134
  • Trac 0.12.1dev-r9990

comment:3 Changed 4 years ago by cboos

There's indeed no recursive message extraction. You can't currently do something like:

 _("Hello %(address)s", address=_("dear %(name)s", name=name)))

But there's nothing specific with tag_ although I agree it would be most useful in that situation.

Until this eventually gets implemented, the workaround is easy:

            a_login = tag.a(_("log in"), href=req.href('login'))
            raise WatchlistError(
                tag_("Please %(login)s to view or change your watchlist",
                     login=a_login)))

comment:4 follow-up: ↓ 6 Changed 4 years ago by hasienda <hoff.st@…>

I've not seen the recursion as the root cause, so thanks for pointing at this. A minor related question arises from your example: Why do you prefer

a_login = tag.a(_("log in"), href=req.href('login'))

over

a_login = tag_.a("log in", href=req.href('login'))

Is this the latter not possible, or is it just a matter of (personal) style?

comment:5 follow-up: ↓ 7 Changed 4 years ago by anonymous

As I see it, there is not only recursion, since the third part of my example is again a string at the same logical level as the first one, only that it's obviously not the first. tag_() loses a lot of it's usefulness by not being able to replace tag() in internationalized code in that very common use case:

tag("string 1 ", var, " string 2")

I had really expected this would automatically span around embedded variables similar to code in a Genshi template

<p i18n:msg="var">string 1 ${var} string 2</p>

but apparently this needs to be done by hand with (much more verbose) python code

tag_("string 1 %(var)s string 2", var=var)

So I guess, this is no longer a defect but a strong call for improvement. What do you think? May I change the summary and type accordingly?

comment:6 in reply to: ↑ 4 Changed 4 years ago by cboos

Replying to hasienda <hoff.st@…>:

I've not seen the recursion as the root cause, so thanks for pointing at this. A minor related question arises from your example: Why do you prefer

a_login = tag.a(_("log in"), href=req.href('login'))

This is all what is needed, we're only translating the "log in" string.

over

a_login = tag_.a("log in", href=req.href('login'))

Is this the latter not possible, or is it just a matter of (personal) style?

This won't work, as tag_ is not a replacement for the tag ElementFactory.

Rather, it is a helper function (defined in Trac's trac.util.translation) that is meant to build a Genshi Fragment out of a message string with the parameters that will be replaced by other Fragments.

E.g. assuming you have:

  mode = tag.em("secure")
  logged1 = _("logged in (%(mode)s)", mode=mode)
  logged2 = tag_("logged in (%(mode)s)", mode=mode)
  • logged1 is an unicode string, with content u"logged in (<em>secure</em>)", if you pass that to a Genshi template, the "<em>" stuff will be HTML escaped
  • logged2 is a Fragment object, with content equivalent to tag("logged in (", tag.em("secure"), ")"); passing that to a template will result in the expected content...

comment:7 in reply to: ↑ 5 Changed 4 years ago by cboos

Ok, I see now that you had different expectations about "tag_":

Replying to anonymous:

As I see it, there is not only recursion, since the third part of my example is again a string at the same logical level as the first one, only that it's obviously not the first. tag_() loses a lot of it's usefulness by not being able to replace tag() in internationalized code in that very common use case:

tag("string 1 ", var, " string 2")

I had really expected this would automatically span around embedded variables similar to code in a Genshi template

<p i18n:msg="var">string 1 ${var} string 2</p>

This is an almost entirely different matter: Babel python support has no support for such kind of extraction tags (a la Genshi i18:msg). I suppose this would be doable, by using automatically generated parameters names. However, as meaningful parameter names are useful for making good template messages, I don't see much of the benefit of this added complexity. And if you'd add support for giving the parameter names, then I don't think you can beat the "standard" way (i.e. your last example).

but apparently this needs to be done by hand with (much more verbose) python code

tag_("string 1 %(var)s string 2", var=var)

So I guess, this is no longer a defect but a strong call for improvement. What do you think? May I change the summary and type accordingly?

From my point of view (*), I'd like to see support for recursion (comment:3) as it can help improve current usage of tag_ where recursion is commonly found, but I don't think it's worth going down the alternative route you suggested in comment:5.

(*) as a Trac contributor; I don't speak for the Babel project.

comment:8 Changed 4 years ago by hasienda <hoff.st@…>

  • Type changed from defect to enhancement
  • Summary changed from Extraction missing from inside Genshi builder expressions to Make recursive message extraction work from inside Genshi builder expressions

Ok, I see. And I follow you regarding the suggested recursion capability. Made this clear in the ticket summary now. Thanks for clarification and discussion so far.

View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as new
as The resolution will be set. Next status will be 'closed'
to The owner will be changed from cmlenz. Next status will be 'new'
The owner will be changed from cmlenz to anonymous. Next status will be 'assigned'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.