Recursive Translations of Message strings with mappings
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
BlueBream |
New
|
Undecided
|
Unassigned | ||
Zope 3 |
Fix Released
|
Wishlist
|
Christian Zagrodnick |
Bug Description
The following is not really a bug, but a missing feature. I need to translate messages that contain mappings with messages. Zope3 currently only translates the toplevel message and leaves the mappings untranslated, for instance:
--------------- snip ------------------
from zope.component import provideUtility
from zope.i18n import translate
from zope.i18n.
from zope.i18nmessageid import Message, MessageFactory
_ = MessageFactory(
messages = {
('en', u'pink'): u'pink',
('de', u'pink'): u'rosa',
('en', u'colour'): u'The colour is $pink',
('de', u'colour'): u'Die Farbe ist $pink'}
xyz = SimpleTranslati
provideUtility(xyz, name=u'xyz')
pink = _(u'pink', u'pink')
pink = Message(pink)
print translate(pink, target_
print translate(pink, target_
colour = _(u'colour', u'The colour is $pink')
colour = Message(colour, mapping={'pink' : pink})
print translate(colour, target_
print translate(colour, target_
------------ snip -----------------
The output of the above program is:
------
pink
rosa
The colour is pink
Die Farbe ist pink
------
It can be seen that the string "pink" is not translated if used as mapping in
another string to be translated.
The problem is easily solved by modifying the translate function in i18n.translatio
def translate(self, msgid, mapping=None, context=None,
"""See zope.i18n.
.....
# MessageID attributes override arguments
if isinstance(msgid, Message):
if msgid.domain != self.domain:
mapping = msgid.mapping
default = msgid.default
# FIX BEGIN
# Recursively translate mappings, if they are translatable
if isinstance(mapping, dict):
for key, value in mapping.items():
# FIX END
if default is None:
default = unicode(msgid)
The fix works perfectly for me, however, I'm not sure if it would break other things in Zope3, moreover one should probably write quick test for it.
Changed in zope3: | |
status: | Fix Committed → Fix Released |
The new diff looks much better. Thanks Hermann! I only have three more
comments :)
* I think we need a few more tests, especially for the edge cases. For
instance, what happens when you do:
msg1 = _('Message 1 and $msg2', mapping={}) mapping[ 'msg2'] = _('Message 2 and $msg1', mapping={'msg1':
msg1.
msg1})
I know, it's a bit of an edge case, but it should be dealt with.
* Copying the dictionary shouldn't be done with copy.copy. It can
easily be done with mapping.copy(). In other words, dictionaries have
a copy() method, you should use it.
* Style: Wrapping a long if-line is more nicely wrapped using
parantheses, rather than backspace. I suppose it's a matter of taste,
but PEP8 suggests using parantheses ("The preferred way of wrapping
long lines is by using Python's implied line continuation inside
parentheses, brackets and braces.").