This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Deprecate and remove gettext.install
Type: enhancement Stage: resolved
Components: Versions: Python 3.5
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: akuchling, alex, barry, eric.araujo, iritkatriel, jwilk, r.david.murray, terry.reedy
Priority: normal Keywords:

Created on 2013-06-14 20:36 by alex, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
issue18217.txt akuchling, 2015-04-13 16:27 review
Messages (14)
msg191152 - (view) Author: Alex Gaynor (alex) * (Python committer) Date: 2013-06-14 20:36
There's a myriad of reasons it's a bad idea:

* Makes code harder to read
* Doesn't play nicely with multiple projects using gettext
* Defeats any attempt at static analysis
* etc...
msg191155 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-06-14 21:27
How would you do dynamic switching of translation locale at runtime, then?
msg191156 - (view) Author: Alex Gaynor (alex) * (Python committer) Date: 2013-06-14 21:34
I'm not sure I understand the question. What `install()` does is set `__builtins__._` to be gettext. I think people should import the gettext function they need.
msg191157 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2013-06-14 21:37
On Jun 14, 2013, at 09:27 PM, R. David Murray wrote:

>How would you do dynamic switching of translation locale at runtime, then?

flufl.i18n :)

http://pythonhosted.org/flufl.i18n/
msg191158 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-06-14 21:43
install says this:

    This installs the function _() in Python’s builtins namespace, based on domain, localedir, and codeset which are passed to the function translation()

Unless I'm misunderstanding something, this means that the actual value of _ is different depending on which domain, localedir, and codeset are in use.  So if my application allows the user to *change languages* at runtime, I need to *change* what is bound to _.  If my program has assigned a value to _, when another part of the application changes the language, what is bound to _ in other modules is not going to change.  This is my understanding of why _ is put in the global namespace.

Of course, I've only used gettext in one application (that did dynamic language switching), so I could just have been doing it wrong...and I suppose there is no reason (and some sense) why _ could not be a function that indirects to the current language.  Or is that the way it works now and I am just misunderstanding the documentation?
msg191159 - (view) Author: Alex Gaynor (alex) * (Python committer) Date: 2013-06-14 21:46
I think the code makes what this does much clearer: http://hg.python.org/cpython/file/01da7bf11ca1/Lib/gettext.py#l209

There's no reason you can't make your own translation object, and expose it's gettext method as as your API, and then you can update the underlying translation object to check locales. This is approximately exactly how Django works.
msg191160 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-06-14 21:55
Which is what Barry's library does.

But rather than just deprecating install, I think we should fix the module so that it supports this directly.  That could be as simple as adding a dynamic translations class.

What does library code that wants to provide internationalization do, though?  Right now they could just use _, and tell library users they need to call gettext.install in their application.  Is there some other technique that is currently used?
msg191595 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2013-06-21 16:18
Working with an explicit translator object sounds much better to me too.  I haven’t used it yet, but Babel has been on my radar for long, and does that (like flufl.i18n from what I can tell).
msg191597 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2013-06-21 16:35
On Jun 21, 2013, at 04:18 PM, Éric Araujo wrote:

>Working with an explicit translator object sounds much better to me too.  I
>haven’t used it yet, but Babel has been on my radar for long, and does that
>(like flufl.i18n from what I can tell).

flufl.enum didn't make it into the stdlib.  Think I'd have more luck with
flufl.i18n? ;)
msg191603 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-06-21 18:21
The rationale for install is "For convenience, you want the _() function to be installed in Python’s builtins namespace, so it is easily accessible in all modules of your application." As David noted, this also make it easy to update _ in just one place when a new language is selected.

Alex disagrees and would like to break any code that uses install, which I thing is much code, by removing it. This would force writers to do something else that will be *much* more work and which might make code harder to read. We do not do this without much greater reason than Alex has given. I think this a bad deprecation proposal and should be rejected. I also think the idea should have been posted to python-ideas first.

I do think that this should become a doc issue to clarify the meaning and usage of install.

The link Alex gave was to NullTranslations.install. The module install function itself is at
http://hg.python.org/cpython/file/01da7bf11ca1/Lib/gettext.py#l424

The doc for install could be much improved to say what it actually does.

"Pass *domain*, *localedir*, fallback=True, and *codeset* to translation, which returns translation instance t. Pass *names* to t.install. The default install method, NullTranslations.install <link>, which is inherited by GNUTranslations <link>, installs t.gettext in builtins as _. See the description of translation and NullTranslations.install for the meaning of the parameters."
+ rationale quoted above

This expanded doc would make it clearer that one can write a custom subclass of NullTranslations with a custom .install method that would do something different, such as bind _ to a dynamic (indirect) gettext, whether in builtins or in a project module that is explicitly imported by every module that needs it.

The doc for NullTranslations.install needs the erroneous '()'s removed to make clear that the bindings are to bound methods and not the result of calls to bound methods. Ie, self.gettest() should be just self.gettext.
msg213355 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2014-03-13 05:15
> The doc for NullTranslations.install needs the erroneous '()'s removed to make clear
> that the bindings are to bound methods and not the result of calls to bound methods.
> Ie, self.gettest() should be just self.gettext.

The source contains :meth:`self.gettext`, and Sphinx adds the parentheses when creating markup for a function, probably because it’s common to say things like “the len() function”.  There is a Sphinx config value to control that.  If one wants to keep the parens for most functions but not have them in a few cases, other markup than :meth:/:func: has to be used.
msg213396 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2014-03-13 13:29
On Mar 13, 2014, at 05:15 AM, Éric Araujo wrote:

>The source contains :meth:`self.gettext`, and Sphinx adds the parentheses
>when creating markup for a function, probably because it’s common to say
>things like “the len() function”.  There is a Sphinx config value to control
>that.  If one wants to keep the parens for most functions but not have them
>in a few cases, other markup than :meth:/:func: has to be used.

The defaults should definitely be kept for :meth: and :func:
msg240644 - (view) Author: A.M. Kuchling (akuchling) * (Python committer) Date: 2015-04-13 16:27
I suggest we just close this ticket.  I tried producing a documentation patch (attached), but they seem like a marginal improvement.  

(I don't think the text in the docs such as "'gettext' (bound to self.gettext())" is confusing; given the context, I think the reader will assume it's bound to the method and not to the results of calling that method.)
msg415565 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2022-03-19 19:53
There were several votes in the discussion for rejecting this deprecation, so I am closing the issue.
History
Date User Action Args
2022-04-11 14:57:46adminsetgithub: 62417
2022-03-19 19:53:30iritkatrielsetstatus: open -> closed

nosy: + iritkatriel
messages: + msg415565

resolution: rejected
stage: resolved
2015-04-13 16:27:19akuchlingsetfiles: + issue18217.txt
nosy: + akuchling
messages: + msg240644

2014-03-13 13:29:59barrysetmessages: + msg213396
2014-03-13 05:15:57eric.araujosetmessages: + msg213355
versions: + Python 3.5, - Python 3.4
2013-06-27 21:52:48jwilksetnosy: + jwilk
2013-06-21 18:21:38terry.reedysetversions: + Python 3.4
nosy: + terry.reedy

messages: + msg191603

type: enhancement
2013-06-21 16:35:09barrysetmessages: + msg191597
2013-06-21 16:18:20eric.araujosetnosy: + eric.araujo
messages: + msg191595
2013-06-14 21:55:54r.david.murraysetmessages: + msg191160
2013-06-14 21:46:35alexsetmessages: + msg191159
2013-06-14 21:43:59r.david.murraysetmessages: + msg191158
2013-06-14 21:37:47barrysetmessages: + msg191157
2013-06-14 21:34:32alexsetmessages: + msg191156
2013-06-14 21:27:00r.david.murraysetnosy: + r.david.murray
messages: + msg191155
2013-06-14 21:07:59barrysetnosy: + barry
2013-06-14 20:36:49alexcreate