diff --git a/src/click/_termui_impl.py b/src/click/_termui_impl.py index 286271c8a..219fbaa1f 100644 --- a/src/click/_termui_impl.py +++ b/src/click/_termui_impl.py @@ -173,7 +173,13 @@ def format_eta(self) -> str: hours = t % 24 t //= 24 if t > 0: - return f"{t}d {hours:02}:{minutes:02}:{seconds:02}" + return "{d}{day_label} {h:02}:{m:02}:{s:02}".format( + d=t, + day_label=_("d"), + h=hours, + m=minutes, + s=seconds, + ) else: return f"{hours:02}:{minutes:02}:{seconds:02}" return "" diff --git a/src/click/_winconsole.py b/src/click/_winconsole.py index e56c7c6ae..d25178d66 100644 --- a/src/click/_winconsole.py +++ b/src/click/_winconsole.py @@ -28,6 +28,7 @@ from ctypes.wintypes import HANDLE from ctypes.wintypes import LPCWSTR from ctypes.wintypes import LPWSTR +from gettext import gettext as _ from ._compat import _NonClosingTextIOWrapper @@ -152,7 +153,7 @@ def readinto(self, b: Buffer) -> int: # wait for KeyboardInterrupt time.sleep(0.1) if not rv: - raise OSError(f"Windows error: {GetLastError()}") + raise OSError(_("Windows error: {error}").format(error=GetLastError())) if buffer[0] == EOF: return 0 @@ -169,7 +170,7 @@ def _get_error_message(errno: int) -> str: return "ERROR_SUCCESS" elif errno == ERROR_NOT_ENOUGH_MEMORY: return "ERROR_NOT_ENOUGH_MEMORY" - return f"Windows error {errno}" + return _("Windows error: {error}").format(error=errno) def write(self, b: Buffer) -> int: bytes_to_be_written = len(b) diff --git a/src/click/core.py b/src/click/core.py index d915d92bc..c5cab15c0 100644 --- a/src/click/core.py +++ b/src/click/core.py @@ -1136,14 +1136,13 @@ def get_short_help_str(self, limit: int = 45) -> str: text = "" if self.deprecated: + localised_deprectated = _("deprecated").upper() deprecated_message = ( - f"(DEPRECATED: {self.deprecated})" + f"({localised_deprectated}: {self.deprecated})" if isinstance(self.deprecated, str) - else "(DEPRECATED)" - ) - text = _("{text} {deprecated_message}").format( - text=text, deprecated_message=deprecated_message + else f"({localised_deprectated})" ) + text = f"{_(text)} {deprecated_message}" return text.strip() @@ -1173,14 +1172,13 @@ def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: text = "" if self.deprecated: + localised_deprectated = _("deprecated").upper() deprecated_message = ( - f"(DEPRECATED: {self.deprecated})" + f"({localised_deprectated}: {self.deprecated})" if isinstance(self.deprecated, str) - else "(DEPRECATED)" - ) - text = _("{text} {deprecated_message}").format( - text=text, deprecated_message=deprecated_message + else f"({localised_deprectated})" ) + text = f"{_(text)} {deprecated_message}" if text: formatter.write_paragraph() @@ -2984,7 +2982,7 @@ def _parse_decls( for decl in decls: if decl.isidentifier(): if name is not None: - raise TypeError(f"Name '{name}' defined twice") + raise TypeError(_("Name '{name}' defined twice").format(name=name)) name = decl else: split_char = ";" if decl[:1] == "/" else "/" @@ -2999,8 +2997,10 @@ def _parse_decls( secondary_opts.append(second.lstrip()) if first == second: raise ValueError( - f"Boolean option {decl!r} cannot use the" - " same flag for true/false." + _( + "Boolean option {decl!r} cannot use the" + " same flag for true/false." + ).format(decl=decl) ) else: possible_names.append(_split_opt(decl)) @@ -3016,14 +3016,18 @@ def _parse_decls( if not expose_value: return "", opts, secondary_opts raise TypeError( - f"Could not determine name for option with declarations {decls!r}" + _( + "Could not determine name for option with declarations {decls!r}" + ).format(decls=decls) ) if not opts and not secondary_opts: raise TypeError( - f"No options defined but a name was passed ({name})." - " Did you mean to declare an argument instead? Did" - f" you mean to pass '--{name}'?" + _( + "No options defined but a name was passed ({name})." + " Did you mean to declare an argument instead? Did" + " you mean to pass '--{name}'?" + ).format(name=name) ) return name, opts, secondary_opts @@ -3455,8 +3459,10 @@ def _parse_decls( name = name.replace("-", "_").lower() else: raise TypeError( - "Arguments take exactly one parameter declaration, got" - f" {len(decls)}: {decls}." + _( + "Arguments take exactly one parameter declaration, got" + " {length}: {decls}." + ).format(length=len(decls), decls=decls) ) return name, [arg], [] diff --git a/src/click/decorators.py b/src/click/decorators.py index 21f4c3422..14aee42ea 100644 --- a/src/click/decorators.py +++ b/src/click/decorators.py @@ -396,8 +396,8 @@ def callback(ctx: Context, param: Parameter, value: bool) -> None: kwargs.setdefault("is_flag", True) kwargs.setdefault("callback", callback) kwargs.setdefault("expose_value", False) - kwargs.setdefault("prompt", "Do you want to continue?") - kwargs.setdefault("help", "Confirm the action without prompting.") + kwargs.setdefault("prompt", _("Do you want to continue?")) + kwargs.setdefault("help", _("Confirm the action without prompting.")) return option(*param_decls, **kwargs) diff --git a/src/click/formatting.py b/src/click/formatting.py index 0b64f831b..de2ca4711 100644 --- a/src/click/formatting.py +++ b/src/click/formatting.py @@ -153,7 +153,7 @@ def write_usage(self, prog: str, args: str = "", prefix: str | None = None) -> N ``"Usage: "``. """ if prefix is None: - prefix = f"{_('Usage:')} " + prefix = "{usage} ".format(usage=_("Usage:")) usage_prefix = f"{prefix:>{self.current_indent}}{prog} " text_width = self.width - self.current_indent diff --git a/src/click/parser.py b/src/click/parser.py index 410d7fe10..4fcbf7caa 100644 --- a/src/click/parser.py +++ b/src/click/parser.py @@ -141,7 +141,11 @@ def __init__( for opt in opts: prefix, value = _split_opt(opt) if not prefix: - raise ValueError(f"Invalid start character for option ({opt})") + raise ValueError( + _("Invalid start character for option ({option})").format( + option=opt + ) + ) self.prefixes.add(prefix[0]) if len(prefix) == 1 and len(value) == 1: self._short_opts.append(opt) diff --git a/src/click/termui.py b/src/click/termui.py index 892e4c0bc..08d732895 100644 --- a/src/click/termui.py +++ b/src/click/termui.py @@ -652,13 +652,13 @@ def style( try: bits.append(f"\033[{_interpret_color(fg)}m") except KeyError: - raise TypeError(f"Unknown color {fg!r}") from None + raise TypeError(_("Unknown color {colour!r}").format(colour=fg)) from None if bg: try: bits.append(f"\033[{_interpret_color(bg, 10)}m") except KeyError: - raise TypeError(f"Unknown color {bg!r}") from None + raise TypeError(_("Unknown color {colour!r}").format(colour=bg)) from None if bold is not None: bits.append(f"\033[{1 if bold else 22}m") diff --git a/src/click/types.py b/src/click/types.py index 355e98423..699bb31f5 100644 --- a/src/click/types.py +++ b/src/click/types.py @@ -390,7 +390,7 @@ def get_invalid_choice_message(self, value: t.Any, ctx: Context | None) -> str: ).format(value=value, choice=choices_str, choices=choices_str) def __repr__(self) -> str: - return f"Choice({list(self.choices)})" + return _("Choice({choices})").format(choices=list(self.choices)) def shell_complete( self, ctx: Context, param: Parameter, incomplete: str @@ -888,7 +888,11 @@ def convert( return f except OSError as e: - self.fail(f"'{format_filename(value)}': {e.strerror}", param, ctx) + self.fail( + f"'{format_filename(value)}': {e.strerror}", + param, + ctx, + ) def shell_complete( self, ctx: Context, param: Parameter, incomplete: str diff --git a/src/click/utils.py b/src/click/utils.py index 89cae3b99..e2e3fe5f1 100644 --- a/src/click/utils.py +++ b/src/click/utils.py @@ -6,6 +6,7 @@ import sys import typing as t from functools import update_wrapper +from gettext import gettext as _ from types import ModuleType from types import TracebackType @@ -333,7 +334,7 @@ def get_binary_stream(name: t.Literal["stdin", "stdout", "stderr"]) -> t.BinaryI """ opener = binary_streams.get(name) if opener is None: - raise TypeError(f"Unknown standard stream '{name}'") + raise TypeError(_("Unknown standard stream '{name}'").format(name=name)) return opener() @@ -354,7 +355,7 @@ def get_text_stream( """ opener = text_streams.get(name) if opener is None: - raise TypeError(f"Unknown standard stream '{name}'") + raise TypeError(_("Unknown standard stream '{name}'").format(name=name)) return opener(encoding, errors)