10

The following code is not working

from django.utils.translation import gettext_lazy as _ 

stringtest=_("First string")
stringtest= stringtest + _(" Second string")
print stringtest

I get the following exception:

cannot concatenate 'str' and '__proxy__' objects

Is it really impossible to append a "translated" string to himself ?

Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97
Erwan
  • 1,055
  • 1
  • 12
  • 26

4 Answers4

9

You cannot concatenate your two string but creating a new one (which is already the case with your + operation anyway, since string are immutable):

from django.utils.translation import gettext_lazy as _ 

stringtest = _("First string")
stringtest = "%s %s" % (stringtest, _(" Second string"))
print stringtest

The problem is gettext_lazy returns a proxy object, since it is usually used to translate string in class definition (in models attribute for exemple) and is not designed to be used in view code, like you are doing right now. The proxy object has a method to translate it to a str object BUT it is not a string.

If you don't really need this _lazy specificity, you can just use gettext in your views, which returns plain string:

>>> from django.utils.translation import gettext as _
>>> _("str1 ") + _("str2")
'str1 str2'
Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97
9

Adding empty string to proxy object will convert it to normal string. Example:

>>> ugettext_lazy("The Beatles frontmen") + ""
u'The Beatles frontmen'

but if you need to concatenate several proxies, then each of them (except first) needs to be converted to string first, example:

>>> ugettext_lazy("The Beatles frontmen ") + (ugettext_lazy('John Lennon') + " ") 
    + (ugettext_lazy('played guitar') + "")
u'The Beatles frontmen John Lennon played guitar'

Alternative for Django <=1.9

For django 2.0 this won't work - string_concat is removed in Django 2.0 (thanks to @Dzhuang).

If you really need to concatenate lazy translatable strings, django supports this:

you can use django.utils.translation.string_concat(), which creates a lazy object that concatenates its contents and converts them to strings only when the result is included in a string. For example:

from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy
...
name = ugettext_lazy('John Lennon')
instrument = ugettext_lazy('guitar')
result = string_concat(name, ': ', instrument)

the lazy translations in result will only be converted to strings when result itself is used in a string (usually at template rendering time).

Robert Lujo
  • 15,383
  • 5
  • 56
  • 73
5

We can use format_lazy.

from django.utils.text import format_lazy
from django.utils.translation import gettext_lazy as _ 

msgs_to_concat = [_("First string"), _(" Second string")]

stringtest = format_lazy('{}'*len(msgs_to_concat), *msgs_to_concat)
Valery Ramusik
  • 1,473
  • 18
  • 19
0

Answer by Valery Ramusik made me try and see that you can also do this:

from django.utils.translation import gettext_lazy as _ 

stringtest = f"{_('First string')} {_(' Second string')}"

if you want to avoid format_lazy() and any additional function.

Laurent Lyaudet
  • 630
  • 8
  • 16