55from dataclasses import dataclass
66from gettext import GNUTranslations , NullTranslations
77from importlib .resources .abc import Traversable
8- from typing import Literal , NewType , Protocol , TypeAlias , cast , overload
8+ from typing import Literal , NewType , Protocol , TypeAlias , overload
99
1010from questionpy_common .environment import (
1111 Environment ,
@@ -207,18 +207,48 @@ def __call__(self, message: str, *, defer: bool | None = None) -> str | UserStri
207207 """Translate the given message.
208208
209209 Args:
210- message: Gettext `msgid`.
210+ message: Gettext `msgid`. This should also be the message in its primary language, usually english.
211211 defer: By default, translation is deferred only when no request is being processed at the time of the
212212 `gettext` call. This parameter can be explicitly set to `True` to force deferral or to `False` to never
213213 defer translations. In the latter case, calling `gettext` before a request is processed
214214 (e.g. during init) will raise an error.
215215 """
216216
217217
218- _NGettext : TypeAlias = Callable [[str ], str ]
218+ class _NGettext (Protocol ):
219+ @overload
220+ def __call__ (self , msgid1 : str , msgid2 : str , n : int , * , defer : None = None ) -> str | UserString : ...
221+
222+ @overload
223+ def __call__ (self , msgid1 : str , msgid2 : str , n : int , * , defer : Literal [True ]) -> UserString : ...
224+
225+ @overload
226+ def __call__ (self , msgid1 : str , msgid2 : str , n : int , * , defer : Literal [False ]) -> str : ...
227+
228+ def __call__ (self , msgid1 : str , msgid2 : str , n : int , * , defer : bool | None = None ) -> str | UserString :
229+ """Translate the given message, accounting for plural forms.
230+
231+ Args:
232+ msgid1: Message id in its (english) singular form, used if no plural form exists and `n == 1`.
233+ msgid2: Message id in its (english) plural form, used if no plural form exists and `n >= 2`.
234+ n: This number is passed through the plural formula of the active catalog to determine which form to use.
235+ defer: By default, translation is deferred only when no request is being processed at the time of the
236+ `gettext` call. This parameter can be explicitly set to `True` to force deferral or to `False` to never
237+ defer translations. In the latter case, calling `gettext` before a request is processed
238+ (e.g. during init) will raise an error.
239+ """
240+
241+
242+ _Noop : TypeAlias = Callable [[str ], str ]
243+ class GettextFunctions (tuple [_Gettext , _Noop ], _Gettext ):
244+ def __new__ (cls , * args , ** kwargs ):
245+
246+ def __init__ (self ):
247+ super ().__init__ ()
248+
219249
220250
221- def get_for (module_name : str ) -> tuple [_Gettext , _NGettext ]:
251+ def get_for (module_name : str ) -> tuple [_Gettext , _Noop ]:
222252 """Initializes i18n for the package owning the given Python module and returns the gettext-family functions.
223253
224254 Args:
@@ -240,10 +270,10 @@ def gettext(message: str, *, defer: bool | None = None) -> str | UserString:
240270 request_state = _require_request_state (domain , domain_state )
241271 return request_state .translations .gettext (message )
242272
243- def ngettext (message : str ) -> str :
273+ def gettext_N (message : str ) -> str :
244274 return message
245275
246- return cast (_Gettext , gettext ), ngettext
276+ return cast (_Gettext , gettext ), gettext_N
247277
248278
249279__all__ = ["DEFAULT_CATEGORY" , "GettextDomain" , "domain_of" , "get_for" , "get_translations_of_package" ]
0 commit comments