Opened 5 years ago

Last modified 16 months ago

#14174 new New feature

Support for string interpolation in lazy translation

Reported by: zimnyx Owned by: nobody
Component: Internationalization Version: 1.2
Severity: Normal Keywords:
Cc: bronger@…, bouke Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

    ugettext_lazy('Hello %s') % 'Sid'

is immediately evaluated to unicode:

        def __mod__(self, rhs):
            if self._delegate_str:          
                return str(self) % rhs          
            elif self._delegate_unicode:    
                return unicode(self) % rhs      
            else:
                raise AssertionError('__mod__ not supported for non-string types')

My proposition is that mod() could return lazy again, and store params given after %, so they can be used in final conversion to unicode:

    unicode(self) % params

Change History (11)

comment:1 Changed 4 years ago by mk

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

You need to extend on your proposal a bit. What should happen in this case:

>>> lst = [1,2,3]
>>> s = ugettext_lazy('Hello %s') % (lst,)
>>> unicode(s)
'Hello [1,2,3]'
>>> lst.append(4)
>>> unicode(s)
'Hello [1,2,3]'

OR

'Hello [1,2,3,4]'

Would you want to deepcopy all arguments to %?

I'm not convinced this ticket is worth the trouble though.

comment:2 Changed 4 years ago by zimnyx

Hi!

Let users decide.

If they want to pass mutable which can later change, and they want translation to be always up-to-date with this value, they just pass mutable param:

    >>> lst = [1,2,3]
    >>> s = ugettext_lazy('Hello %s') % (lst,)
    >>> unicode(s)
    'Hello [1,2,3]'
    >>> lst.append(4)
    >>> unicode(s)
    'Hello [1,2,3,4]'

... or if they want to see value with its state during creation of lazy:

>>> lst = [1,2,3]
>>> s = ugettext_lazy('Hello %s') % (lst[:],)
>>> unicode(s)
'Hello [1,2,3]'
>>> lst.append(4)
>>> unicode(s)
'Hello [1,2,3]'

I'm not sure about backwards compatibility though... please decide.

comment:3 Changed 4 years ago by claudep

  • Component changed from Translations to Internationalization
  • Triage Stage changed from Unreviewed to Design decision needed

comment:4 Changed 4 years ago by bronger

  • Cc bronger@… added

comment:5 Changed 4 years ago by julien

  • Severity set to Normal
  • Type set to New feature

comment:6 Changed 3 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:7 Changed 3 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

comment:8 Changed 2 years ago by jezdez

  • Triage Stage changed from Design decision needed to Accepted

comment:9 Changed 2 years ago by aaugustin

This is related to #19160 which was recently fixed.

Specifically the patch for that ticket allowed using string interpolation on lazily translated objects.

comment:10 Changed 16 months ago by bouke

Not that besides having a lazy __mod__, we'd also want a lazy __add__. So we could write s = ugettext_lazy('Hello,') + ' ' + ugettext_lazy('World'). (Note that the example is imperfect; as those two strings should be a single msgid, but you get the idea.)

I've played around with this ticket for a while and came up with this: https://gist.github.com/Bouke/7303909. Although it roughly appears to work; I don't like the implementation. I'd rather use lazy() and not re-implement __add__ and __mod__. Somehow only the methods that return a string after some operation should be overriden.

comment:11 Changed 16 months ago by bouke

  • Cc bouke added
Note: See TracTickets for help on using tickets.
Back to Top