← Back to team overview

schooltool-developers team mailing list archive

Re: Dynamic i18n messages

 

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Douglas Cerna wrote:
> Hey everybody.
> 
> I've been testing the Spanish (El Salvador) version of SchoolTool trunk and noticed some new untranslated strings. So I went to Launchpad and started translating them.
> 
> This message got my attention:
> 
> %s has no days in A%s
> 
> which is located in /src/schooltool/export/importer.py:78
> 
> So I checked that module and saw (line 78):
> 
> ...
> ERROR_HAS_NO_DAYS = _("%s has no days in A%s")
> ...
> 
> and then (line 528):
> 
> ...
> self.errors.append(ERROR_HAS_NO_DAYS % (data['title'], row + 1))
> ...
> 
> Correct me if I'm wrong, but I guess this won't work, right? I mean, it won't get translated, since i18n messages use a 'mapping' instead, correct?

  Once again, a big thank you for caring about i18n!  You are right -
this will not get translated.

  And in some rare scenarios, this approach can cause a traceback.  Let
me elaborate :)

  The thing with i18n Message objects, that once you treat them with %,
they return a plain unicode string - and they use the default message
text (english!) for that.

  Here's how it works.  Translatable messages have their id, default
text, translation domain and mapping.  Usually message id and the
default text are the same:

  >>> from zope.i18nmessageid import Message
  >>> recipe = Message(u'You need %d gallons of oil')

  >>> unicode(recipe)
  u'You need %d gallons of oil'

  >>> recipe % 5
  u'You need 5 gallons of oil'

  The result is not translatable:
  >>> type(recipe % 5)
  <type 'unicode'>

  Some messages, however, have different id and default text (for
example, compare "ok-button" and "All day event" in en_GB.po).  Bluntly
speaking, this mechanism is used to separate óleo from petróleo:

  >>> fuel = Message(u'fuel-text', u'You need %d gallons of oil')

  >>> unicode(fuel)
  u'fuel-text'

  >>> fuel % 5
  Traceback (most recent call last):
    File ...
  TypeError: not all arguments converted during string formatting

> I remember I asked Justas on a similar problem when I was working on the email package. Every time I had to present the user a translated message I created a new copy of the original message and used the 'mapping' parameter (src/schooltool/email/browser/email.py:323)
> 
> So in this importer case, it would be like:
> 
> ...
> ERROR_HAS_NO_DAYS = _("${x} has no days in A${y}")
> ...
> 
> and then
> 
> ...
> message = _(ERROR_HAS_NO_DAYS, mapping={'x': data['title'], 'y': row + 1})
> self.errors.append(message)
> ...
>
> Am I way off here? Is there a better solution? Is it a limitation of the i18n.message package? Or is it me who's not using it right?

  I didn't notice before that MessageFactory enforces it's own domain
and overrides the default value to None...

  So, here's a helper to make things right:

  >>> from schooltool.common import format_message
  >>> FUEL_MSG = _("You need ${amount} gallons.")
  >>> FIVE = _("five")

  >>> msg = format_message(FUEL_MSG, mapping={'amount': FIVE})

  And yes, you can nest translatable messages.  Once more - thank you
for noticing!


Cheers,
Justas


P.S.: fixed the importer, updated schooltool.email in trunk.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkxxSG8ACgkQaCT+W0+kcjQlNQCbBLmwfEfsoUIIh2gajuCc1GD/
khIAn2UW1qfaUGKktCuiepsKPYOyPWro
=japx
-----END PGP SIGNATURE-----



References