Unable to append a translated string to himself with gettext

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'

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).


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)