On Tue, 2007-08-21 at 00:09 +0200, Tomas Kopecek wrote:
> Hello,
> I've been playing with these functions and finally I've become totally 
> confused.
> 
> I've expected that there would be some difference in behaviour, but I 
> was not able to create such use case in which these two functions 
> produces different results. More precisely, I haven't find place where 
> would be better to use ugettext_lazy. In documentation is said to use 
> this function in models.py everywhere. But for me it looks that ugettext 
> makes the same work. All text marked to translation is translated 
> accordingly to locale set by user via browser with both of them.

There is quite a large difference. Noticing it would depend where you
are using them.

The difference is that ugettext() is a straight function call that
returns the translation result immediately. Executing

        s1 = ugettext('redirect')

makes 's1' a Unicode object. It's value will be based on the locale when
it is executed and then never change, no matter what the locale is. So
anything that is executed at *import* time should not be using
ugettext(). Since it's a cause of great confusion for some people about
what when particular lines are executed, I simplified a little in the
docs and wrote "use ugettext_lazy() everywhere", since it's not actually
harmful to do so.

Have a look at the following fragment. Everywhere I am using _(), it is
important to use ugettext_lazy, not ugettext:

        class Example(models.Model):
           name = models.CharField(_('Your name'), max_length = 100)
        
           class Meta:
             verbose_name = _('An example')
        
Both of those lines are executed at import time. To see this in action,
load a model like this into the Admin interface and view it. Now change
your browser's locale and don't restart anything on the server. Reload
the page. If you are using ugettext() and not the lazy variant, the
displayed string will not change, because the function isn't called
again. If you use ugettext_lazy, the displayed form is locale-aware
(obviously if you are testing this, use some strings that are
translated. I tend to use the string "redirect" a lot, because most
locales have translated that one in Django's core).

This test might need some persistence to replicate if you are using
something like a multi-process web-server since you need to hit the same
piece of code twice -- once to force the first translation and once to
force it to be redisplayed to see the difference. The Django dev server
is ideal for showing the effects, though, since it's single-threaded and
only a single process.

Other places where ugettext_lazy might be reqiured because the code is
executed at import time are default arguments to views and form classes
that you create at the module level somewhere.

> Furthermore i was not able to use template strings and stay in __proxy__ 
> mode. anything like ugettext_lazy('xyz %s') % 'some_text' comes to 
> unicode string representation immediately. So, it looks there is no way 
> to use template strings with *_lazy. From my view it is little bit 
> painful to use it.

Normally, you would be doing the substitution very close to where you
are using the string. At least in the same execution thread and already
in the right locale. So it doesn't typically matter that it now becomes
a Unicode string.

However full generality would be nice. Unfortunately, it's very hard to
make something that understands the '%' operator and returns the right
object so that it will retain it's laziness without breaking other
usages. If you come up with a way to do that, feel free to submit a
patch.

If you really need a case where you need to use ugettext_lazy and apply
a subsitution *and* have it only evaluated much later in another locale
setting, you probably want to investigate the use of
django.utils.functional.lazy(). You give it a function and a return type
(or a number of return types) and it returns something that is only
evaluated when used as one of those return types. This is exactly how
ugettext_lazy() and friends are created. Again, if you come up with
something that might have broad use, submit a patch. Our i18n support is
driven by user requests.

django.utils.translation.string_concat might also be useful in some
cases (we use it internally for a few things): it provides a way to do
the equivalent of ''.join([...]), but evaluated only when needed.

Regards,
Malcolm

-- 
Two wrongs are only the beginning. 
http://www.pointy-stick.com/blog/


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to