Skip to content
4 changes: 2 additions & 2 deletions Doc/library/gettext.rst
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ install themselves in the built-in namespace as the function :func:`!_`.

If *localedir* is not given, then the default system locale directory is used.
[#]_ If *languages* is not given, then the environment variable :envvar:`LANGUAGE`
is searched, it falls back to :func:`locale.getlocale`, which in turn falls
is searched, it falls back to :func:`locale.setlocale`, which in turn falls
back to the environment variables :envvar:`LC_ALL`, :envvar:`LC_MESSAGES`, and
:envvar:`LANG` where the first one returning a non-empty value is used for the
*languages* variable. The environment variables should contain a colon separated
Expand All @@ -149,7 +149,7 @@ install themselves in the built-in namespace as the function :func:`!_`.
the environment variables.

.. versionchanged:: next
:func:`locale.getlocale` is used to generate *languages* if *languages* is
:func:`locale.setlocale` is used to generate *languages* if *languages* is
not provided.

.. function:: translation(domain, localedir=None, languages=None, class_=None, fallback=False)
Expand Down
3 changes: 1 addition & 2 deletions Lib/gettext.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@ def func(n):


def _expand_lang(loc):
import locale
loc = locale.normalize(loc)
COMPONENT_CODESET = 1 << 0
COMPONENT_TERRITORY = 1 << 1
Expand Down Expand Up @@ -494,7 +493,7 @@ def find(domain, localedir=None, languages=None, all=False):
languages = []
if val := os.environ.get('LANGUAGE'):
languages = val.split(':')
elif (loc := locale.getlocale()) != (None, None):
elif (loc := locale.setlocale(locale.LC_MESSAGES)) != (None, None):
languages = [".".join(filter(None, loc))]
else:
for envar in ('LC_ALL', 'LC_MESSAGES', 'LANG'):
Expand Down
39 changes: 20 additions & 19 deletions Lib/test/test_gettext.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import locale
import os
import base64
import gettext
Expand Down Expand Up @@ -737,30 +736,32 @@ def create_mo_file(self, lang):
f.write(GNU_MO_DATA)
return mo_file

@unittest.mock.patch("locale.getlocale", return_value=(None, None))
def test_find_with_env_vars(self, patch_getlocale):
# test that find correctly finds the environment variables
# when languages are not supplied
mo_file = self.create_mo_file("ga_IE")
for var in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'):
self.env.set(var, 'ga_IE')
result = gettext.find("mofile",
localedir=os.path.join(self.tempdir, "locale"))
self.assertEqual(result, mo_file)
self.env.unset(var)
# test fallbacks
def _for_all_vars(self, mo_file, locale):
for var in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'):
self.env.set(var, 'es_ES:ga_IE:fr_FR')
self.env.set(var, locale)
result = gettext.find("mofile",
localedir=os.path.join(self.tempdir, "locale"))
self.assertEqual(result, mo_file)
self.assertEqual(mo_file, result)
self.env.unset(var)

@unittest.mock.patch("locale.getlocale", return_value=('ga_IE', 'UTF-8'))
def test_process_vars_override(self, patch_getlocale):
@unittest.mock.patch("locale.setlocale", return_value=(None, None))
def test_find_with_env_vars(self, patch_getlocale):
# test that find correctly finds the environment variables
# when languages are not supplied
mo_file = self.create_mo_file("ga_IE")
result = gettext.find("mofile", localedir=os.path.join(self.tempdir, "locale"))
self.assertEqual(result, mo_file)
self._for_all_vars(mo_file, "ga_IE")
self._for_all_vars(mo_file, "ga_IE.UTF-8")
self._for_all_vars(mo_file, "es_ES:ga_IE:fr_FR")
self._for_all_vars(mo_file, "ga_IE@euro")

def test_process_vars_override(self):
mo_file = self.create_mo_file("ga_IE")
with unittest.mock.patch("locale.setlocale", return_value=('ga_IE', 'UTF-8')):
result = gettext.find("mofile", localedir=os.path.join(self.tempdir, "locale"))
self.assertEqual(mo_file, result)
with unittest.mock.patch("locale.setlocale", return_value=('ga_IE', None)):
result = gettext.find("mofile", localedir=os.path.join(self.tempdir, "locale"))
self.assertEqual(mo_file, result)

def test_find_with_languages(self):
# test that passed languages are used
Expand Down
Loading