11# A part of NonVisual Desktop Access (NVDA)
2- # Copyright (C) 2007-2021 NV access Limited, Joseph Lee, Łukasz Golonka
2+ # Copyright (C) 2007-2023 NV access Limited, Joseph Lee, Łukasz Golonka, Cyrille Bougot
33# This file is covered by the GNU General Public License.
44# See the file COPYING for more details.
55
@@ -288,9 +288,9 @@ def getAvailableLanguages(presentational: bool = False) -> List[Tuple[str, str]]
288288
289289
290290def makePgettext (translations ):
291- """Obtaina pgettext function for use with a gettext translations instance.
291+ """Obtain a pgettext function for use with a gettext translations instance.
292292 pgettext is used to support message contexts,
293- but Python's gettext module doesn't support this,
293+ but Python 3.7 's gettext module doesn't support this,
294294 so NVDA must provide its own implementation.
295295 """
296296 if isinstance (translations , gettext .GNUTranslations ):
@@ -301,14 +301,36 @@ def pgettext(context, message):
301301 except KeyError :
302302 return message
303303 elif isinstance (translations , gettext .NullTranslations ):
304- # A language with out a translation catalog, such as English.
304+ # A language without a translation catalog, such as English.
305305 def pgettext (context , message ):
306306 return message
307307 else :
308308 raise ValueError ("%s is Not a GNUTranslations or NullTranslations object" % translations )
309309 return pgettext
310310
311311
312+ def makeNpgettext (translations ):
313+ """Obtaina npgettext function for use with a gettext translations instance.
314+ npgettext is used to support message contexts with respect to ngettext,
315+ but Python 3.7's gettext module doesn't support this,
316+ so NVDA must provide its own implementation.
317+ """
318+ if isinstance (translations , gettext .GNUTranslations ):
319+ def npgettext (context , msgSingular , msgPlural , n ):
320+ try :
321+ # Look up the message with its context.
322+ return translations ._catalog [(f"{ context } \x04 { msgSingular } " , translations .plural (n ))]
323+ except KeyError :
324+ return msgSingular if n == 1 else msgPlural
325+ elif isinstance (translations , gettext .NullTranslations ):
326+ # A language without a translation catalog, such as English.
327+ def npgettext (context , msgSingular , msgPlural , n ):
328+ return msgSingular if n == 1 else msgPlural
329+ else :
330+ raise ValueError ("%s is Not a GNUTranslations or NullTranslations object" % translations )
331+ return npgettext
332+
333+
312334def getLanguageCliArgs () -> Tuple [str , ...]:
313335 """Returns all command line arguments which were used to set current NVDA language
314336 or an empty tuple if language has not been specified from the CLI."""
@@ -381,10 +403,11 @@ def setLanguage(lang: str) -> None:
381403 if trans is None :
382404 trans = _createGettextTranslation ("en" )
383405
384- trans .install ()
406+ trans .install (names = [ 'ngettext' ] )
385407 setLocale (getLanguage ())
386- # Install our pgettext function .
408+ # Install our pgettext and npgettext functions .
387409 builtins .pgettext = makePgettext (trans )
410+ builtins .npgettext = makeNpgettext (trans )
388411
389412 global installedTranslation
390413 installedTranslation = weakref .ref (trans )
0 commit comments