76

Looking through some of the Django code at authentication forms I noticed the following syntax

label=_("Username")

Normally I would have just used a pair of quotes around the string. Can someone exaplain to me what the underscore and parenthesis around "Username" do?

wobbily_col
  • 11,390
  • 12
  • 62
  • 86
  • 3
    Check you import statments you will find: `from django.utils.translation import ugettext_lazy as _`, your are calling `ugettext_lazy` function. Read: [When shoud I use ugettext_lazy?](http://stackoverflow.com/questions/4160770/when-shoud-i-use-ugettext-lazy) – Grijesh Chauhan Jan 04 '14 at 12:30
  • 3
    That's really unintuitive. A definite WFT from Python, which prides itself on avoidng these. – wobbily_col Sep 08 '15 at 18:13

3 Answers3

87

The _ is the name of a callable (function, callable object). It's usually used for the gettext function, for example in Django:

 from django.utils.translation import gettext as _
 print _("Hello!")  # Will print Hello! if the current language is English
                    # "Bonjour !" in French
                    # ¡Holà! in Spanish, etc.

As the doc says:

Python’s standard library gettext module installs _() into the global namespace, as an alias for gettext(). In Django, we have chosen not to follow this practice, for a couple of reasons:

[...]

The underscore character (_) is used to represent “the previous result” in Python’s interactive shell and doctest tests. Installing a global _() function causes interference. Explicitly importing gettext() as _() avoids this problem.

Even if it's a convention, it may not be the case in your code. But be reassured, 99.9% of the time _ is an alias for gettext :)

Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97
  • 2
    Yes, I didn't notice it in the imports. – wobbily_col Jan 05 '14 at 14:14
  • What's wrong with ugettext("Hello!") ? – ZuLu Feb 08 '22 at 04:58
  • 1
    @ZuLu Nothing wrong, as said by the Django doc, it is a convention to use `_` as an alias so you don't have to write "gettext" every time you use a string to translate in your code. If you're using gettext only a few time in your file, you can ditch the alias and use gettext(...) directly, it will have the same effect. – Maxime Lorant Feb 08 '22 at 10:00
14

The underscore is just another Python object, but by convention the gettext library scans for it to find translatable text.

Usually it is bound to the ugettext callable:

from django.utils.translation import ugettext as _

See the translation chapter of the Django documentation:

Python’s standard library gettext module installs _() into the global namespace, as an alias for gettext(). In Django, we have chosen not to follow this practice, for a couple of reasons:

  • For international character set (Unicode) support, ugettext() is more useful than gettext(). Sometimes, you should be using ugettext_lazy() as the default translation method for a particular file. Without _() in the global namespace, the developer has to think about which is the most appropriate translation function.
  • The underscore character (_) is used to represent “the previous result” in Python’s interactive shell and doctest tests. Installing a global _() function causes interference. Explicitly importing ugettext() as _() avoids this problem.
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
5

It calls the function _ with the argument "Username", just like f("Username") would call the function f. Probably _ is a function for internationalising strings.

Paul Hankin
  • 54,811
  • 11
  • 92
  • 118