bba4bd075ab5e1d6a6a76d90b129ad0d58425b96
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1) # SPDX-FileCopyrightText: 2024 Marco Ricci <software@the13thletter.info>
2) #
3) # SPDX-Licence-Identifier: MIT
4) 
5) """Internal module.  Do not use.  Contains error strings and functions."""
6) 
7) from __future__ import annotations
8) 
Marco Ricci Provide a function to reloa...

Marco Ricci authored 1 week ago

9) import contextlib
Marco Ricci Add a writer function for d...

Marco Ricci authored 1 week ago

10) import datetime
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

11) import enum
12) import gettext
13) import inspect
Marco Ricci Provide a function to reloa...

Marco Ricci authored 1 week ago

14) import os
15) import sys
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

16) import textwrap
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

17) import types
Marco Ricci Add a writer function for d...

Marco Ricci authored 1 week ago

18) from typing import TYPE_CHECKING, NamedTuple, TextIO, cast
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

19) 
20) import derivepassphrase as dpp
21) 
22) if TYPE_CHECKING:
Marco Ricci Provide a function to reloa...

Marco Ricci authored 1 week ago

23)     from collections.abc import Iterable, Mapping, Sequence
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

24) 
25)     from typing_extensions import Any, Self
26) 
27) __author__ = dpp.__author__
28) __version__ = dpp.__version__
29) 
30) __all__ = ('PROG_NAME',)
31) 
32) PROG_NAME = 'derivepassphrase'
Marco Ricci Provide a function to reloa...

Marco Ricci authored 1 week ago

33) 
34) 
35) def load_translations(
36)     localedirs: list[str] | None = None,
37)     languages: Sequence[str] | None = None,
38)     class_: type[gettext.NullTranslations] | None = None,
Marco Ricci Fix coverage

Marco Ricci authored 1 week ago

39) ) -> gettext.NullTranslations:  # pragma: no cover
Marco Ricci Provide a function to reloa...

Marco Ricci authored 1 week ago

40)     """Load a translation catalog for derivepassphrase.
41) 
42)     Runs [`gettext.translation`][] under the hood for multiple locale
43)     directories.  `fallback=True` is implied.
44) 
45)     Args:
46)         localedirs:
47)             A list of directories to run [`gettext.translation`][]
48)             against.  Defaults to `$XDG_DATA_HOME/locale` (usually
49)             `~/.local/share/locale`), `{sys.prefix}/share/locale` and
50)             `{sys.base_prefix}/share/locale` if not given.
51)         languages:
52)             Passed directly to [`gettext.translation`][].
53)         class_:
54)             Passed directly to [`gettext.translation`][].
55) 
56)     Returns:
57)         A (potentially dummy) translation catalog.
58) 
59)     """
60)     if localedirs is None:
61)         if sys.platform.startswith('win'):
62)             xdg_data_home = os.environ.get(
63)                 'APPDATA',
64)                 os.path.expanduser('~'),
65)             )
66)         elif os.environ.get('XDG_DATA_HOME'):
67)             xdg_data_home = os.environ['XDG_DATA_HOME']
68)         else:
69)             xdg_data_home = os.path.join(
70)                 os.path.expanduser('~'), '.local', 'share'
71)             )
72)         localedirs = [
73)             os.path.join(xdg_data_home, 'locale'),
74)             os.path.join(sys.prefix, 'share', 'locale'),
75)             os.path.join(sys.base_prefix, 'share', 'locale'),
76)         ]
77)     for localedir in localedirs:
78)         with contextlib.suppress(OSError):
79)             return gettext.translation(
80)                 PROG_NAME,
81)                 localedir=localedir,
82)                 languages=languages,
83)                 class_=class_,
84)             )
85)     return gettext.NullTranslations()
86) 
87) 
88) translation = load_translations()
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

89) 
90) 
91) class TranslatableString(NamedTuple):
92)     singular: str
93)     plural: str
94)     l10n_context: str
95)     translator_comments: str
96)     flags: frozenset[str]
97) 
98) 
99) def _prepare_translatable(
100)     msg: str,
101)     comments: str = '',
102)     context: str = '',
103)     plural_msg: str = '',
104)     *,
105)     flags: Iterable[str] = (),
106) ) -> TranslatableString:
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

107)     def maybe_rewrap(string: str) -> str:
108)         string = inspect.cleandoc(string)
109)         if not any(s.strip() == '\b' for s in string.splitlines()):
110)             string = '\n'.join(
111)                 textwrap.wrap(
112)                     string,
113)                     width=float('inf'),  # type: ignore[arg-type]
114)                     fix_sentence_endings=True,
115)                 )
116)             )
117)         else:  # pragma: no cover
118)             string = ''.join(
119)                 s
120)                 for s in string.splitlines(True)  # noqa: FBT003
121)                 if s.strip() == '\b'
122)             )
123)         return string
124) 
125)     msg = maybe_rewrap(msg)
126)     plural_msg = maybe_rewrap(plural_msg)
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

127)     context = context.strip()
128)     comments = inspect.cleandoc(comments)
129)     flags = (
130)         frozenset(f.strip() for f in flags)
131)         if not isinstance(flags, str)
132)         else frozenset({flags})
133)     )
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

134)     assert '{' not in msg or bool(
135)         flags & {'python-brace-format', 'no-python-brace-format'}
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

136)     ), f'Missing flag for how to deal with brace in {msg!r}'
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

137)     assert '%' not in msg or bool(
138)         flags & {'python-format', 'no-python-format'}
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

139)     ), f'Missing flag for how to deal with percent character in {msg!r}'
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

140)     assert (
141)         not flags & {'python-format', 'python-brace-format'}
142)         or '%' in msg
143)         or '{' in msg
144)     ), f'Missing format string parameters in {msg!r}'
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

145)     return TranslatableString(msg, plural_msg, context, comments, flags)
146) 
147) 
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

148) class TranslatedString:
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

149)     def __init__(
150)         self,
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

151)         template: (
152)             str
153)             | TranslatableString
154)             | Label
155)             | InfoMsgTemplate
156)             | WarnMsgTemplate
157)             | ErrMsgTemplate
158)         ),
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

159)         args_dict: Mapping[str, Any] = types.MappingProxyType({}),
160)         /,
161)         **kwargs: Any,  # noqa: ANN401
162)     ) -> None:
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

163)         if isinstance(
164)             template, (Label, InfoMsgTemplate, WarnMsgTemplate, ErrMsgTemplate)
165)         ):
166)             template = cast(TranslatableString, template.value)
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

167)         self.template = template
168)         self.kwargs = {**args_dict, **kwargs}
169)         self._rendered: str | None = None
170) 
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

171)     def __bool__(self) -> bool:
172)         return bool(str(self))
173) 
174)     def __eq__(self, other: object) -> bool:  # pragma: no cover
175)         return str(self) == other
176) 
177)     def __hash__(self) -> int:  # pragma: no cover
178)         return hash(str(self))
179) 
180)     def __repr__(self) -> str:  # pragma: no cover
181)         return (
182)             f'{self.__class__.__name__}({self.template!r}, '
183)             f'{dict(self.kwargs)!r})'
184)         )
185) 
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

186)     def __str__(self) -> str:
187)         if self._rendered is None:
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

188)             # raw str support is currently unneeded, so excluded from coverage
189)             if isinstance(self.template, str):  # pragma: no cover
190)                 context = None
191)                 template = self.template
192)             else:
193)                 context = self.template.l10n_context
194)                 template = self.template.singular
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

195)             if context is not None:
196)                 template = translation.pgettext(context, template)
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

197)             else:  # pragma: no cover
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

198)                 template = translation.gettext(template)
199)             self._rendered = template.format(**self.kwargs)
200)         return self._rendered
201) 
202)     def maybe_without_filename(self) -> Self:
203)         if (
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

204)             not isinstance(self.template, str)
205)             and self.kwargs.get('filename') is None
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

206)             and ': {filename!r}' in self.template.singular
207)         ):
208)             singular = ''.join(
209)                 self.template.singular.split(': {filename!r}', 1)
210)             )
211)             plural = (
212)                 ''.join(self.template.plural.split(': {filename!r}', 1))
213)                 if self.template.plural
214)                 else self.template.plural
215)             )
216)             return self.__class__(
217)                 self.template._replace(singular=singular, plural=plural),
218)                 self.kwargs,
219)             )
220)         return self
221) 
222) 
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

223) class Label(enum.Enum):
224)     DEPRECATION_WARNING_LABEL = _prepare_translatable(
225)         'Deprecation warning', comments='', context='diagnostic label'
226)     )
227)     WARNING_LABEL = _prepare_translatable(
228)         'Warning', comments='', context='diagnostic label'
229)     )
230)     DERIVEPASSPHRASE_01 = _prepare_translatable(
231)         msg="""
232)         Derive a strong passphrase, deterministically, from a master secret.
233)         """,
234)         comments='',
235)         context='help text (long form)',
236)     )
237)     DERIVEPASSPHRASE_02 = _prepare_translatable(
238)         msg="""
239)         The currently implemented subcommands are "vault" (for the
240)         scheme used by vault) and "export" (for exporting foreign
241)         configuration data).  See the respective `--help` output for
242)         instructions.  If no subcommand is given, we default to "vault".
243)         """,
244)         comments='',
245)         context='help text (long form)',
246)     )
247)     DERIVEPASSPHRASE_03 = _prepare_translatable(
248)         msg="""
249)         Deprecation notice: Defaulting to "vault" is deprecated.
250)         Starting in v1.0, the subcommand must be specified explicitly.
251)         """,
252)         comments='',
253)         context='help text (long form)',
254)     )
255)     DERIVEPASSPHRASE_EPILOG_01 = _prepare_translatable(
256)         msg=r"""
257)         Configuration is stored in a directory according to the
258)         `DERIVEPASSPHRASE_PATH` variable, which defaults to
259)         `~/.derivepassphrase` on UNIX-like systems and
260)         `C:\Users\<user>\AppData\Roaming\Derivepassphrase` on Windows.
261)         """,
262)         comments='',
263)         context='help text (long form)',
264)     )
265)     DERIVEPASSPHRASE_EXPORT_01 = _prepare_translatable(
266)         msg="""
267)         Export a foreign configuration to standard output.
268)         """,
269)         comments='',
270)         context='help text (long form)',
271)     )
272)     DERIVEPASSPHRASE_EXPORT_02 = _prepare_translatable(
273)         msg="""
274)         The only available subcommand is "vault", which implements the
275)         vault-native configuration scheme.  If no subcommand is given,
276)         we default to "vault".
277)         """,
278)         comments='',
279)         context='help text (long form)',
280)     )
281)     DERIVEPASSPHRASE_EXPORT_03 = DERIVEPASSPHRASE_03
282)     DERIVEPASSPHRASE_EXPORT_VAULT_01 = _prepare_translatable(
283)         msg="""
284)         Export a vault-native configuration to standard output.
285)         """,
286)         comments='',
287)         context='help text (long form)',
288)     )
289)     DERIVEPASSPHRASE_EXPORT_VAULT_02 = _prepare_translatable(
290)         msg="""
291)         Depending on the configuration format, {path_metavar!s} may
292)         either be a file or a directory.  We support the vault "v0.2",
293)         "v0.3" and "storeroom" formats.
294)         """,
295)         comments='',
296)         context='help text (long form)',
297)         flags='python-brace-format',
298)     )
299)     DERIVEPASSPHRASE_EXPORT_VAULT_03 = _prepare_translatable(
300)         msg="""
301)         If {path_metavar!s} is explicitly given as `VAULT_PATH`, then
302)         use the `VAULT_PATH` environment variable to determine the
303)         correct path.  (Use `./VAULT_PATH` or similar to indicate
304)         a file/directory actually named `VAULT_PATH`.)
305)         """,
306)         comments='',
307)         context='help text (long form)',
308)         flags='python-brace-format',
309)     )
310)     DERIVEPASSPHRASE_VAULT_01 = _prepare_translatable(
311)         msg="""
312)         Derive a passphrase using the vault derivation scheme.
313)         """,
314)         comments='',
315)         context='help text (long form)',
316)     )
317)     DERIVEPASSPHRASE_VAULT_02 = _prepare_translatable(
318)         msg="""
319)         If operating on global settings, or importing/exporting
320)         settings, then {service_metavar!s} must be omitted.  Otherwise
321)         it is required.
322)         """,
323)         comments='',
324)         context='help text (long form)',
325)         flags='python-brace-format',
326)     )
327)     DERIVEPASSPHRASE_VAULT_EPILOG_01 = _prepare_translatable(
328)         msg="""
329)         WARNING: There is NO WAY to retrieve the generated passphrases
330)         if the master passphrase, the SSH key, or the exact passphrase
331)         settings are lost, short of trying out all possible
332)         combinations.  You are STRONGLY advised to keep independent
333)         backups of the settings and the SSH key, if any.
334)         """,
335)         comments='',
336)         context='help text (long form)',
337)     )
338)     DERIVEPASSPHRASE_VAULT_EPILOG_02 = _prepare_translatable(
339)         msg="""
340)         The configuration is NOT encrypted, and you are STRONGLY
341)         discouraged from using a stored passphrase.
342)         """,
343)         comments='',
344)         context='help text (long form)',
345)     )
346)     DEPRECATED_COMMAND_LABEL = _prepare_translatable(
347)         msg='(Deprecated) {text}',
348)         comments='',
349)         context='help text (long form, label)',
350)         flags='python-brace-format',
351)     )
352)     DEBUG_OPTION_HELP_TEXT = _prepare_translatable(
353)         'also emit debug information (implies --verbose)',
354)         comments='',
355)         context='help text (option one-line description)',
356)     )
357)     EXPORT_VAULT_FORMAT_HELP_TEXT = _prepare_translatable(
358)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

359)         TRANSLATORS: The defaults_hint is
360)         Label.EXPORT_VAULT_FORMAT_DEFAULTS_HELP_TEXT, the metavar is
361)         Label.EXPORT_VAULT_FORMAT_METAVAR_FMT.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

362)         """,
363)         msg=r"""
364)         try the following storage format {metavar!s}; may be
365)         specified multiple times, formats will be tried in order
366)         {defaults_hint!s}
367)         """,
368)         context='help text (option one-line description)',
369)         flags='python-brace-format',
370)     )
371)     EXPORT_VAULT_FORMAT_DEFAULTS_HELP_TEXT = _prepare_translatable(
372)         comments=r"""
373)         TRANSLATORS: See EXPORT_VAULT_FORMAT_HELP_TEXT.  The format
374)         names/labels "v0.3", "v0.2" and "storeroom" should not be
375)         translated.
376)         """,
377)         msg=r"""
378)         (default: v0.3, v0.2, storeroom)
379)         """,
380)         context='help text (option one-line description)',
381)     )
382)     EXPORT_VAULT_KEY_HELP_TEXT = _prepare_translatable(
383)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

384)         TRANSLATORS: The defaults_hint is
385)         Label.EXPORT_VAULT_KEY_DEFAULTS_HELP_TEXT, the metavar is
386)         Label.EXPORT_VAULT_KEY_METAVAR_K.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

387)         """,
388)         msg=r"""
389)         use {metavar!s} as the storage master key {defaults_hint!s}
390)         """,
391)         context='help text (option one-line description)',
392)         flags='python-brace-format',
393)     )
394)     EXPORT_VAULT_KEY_DEFAULTS_HELP_TEXT = _prepare_translatable(
395)         comments=r"""
396)         TRANSLATORS: See EXPORT_VAULT_KEY_HELP_TEXT.
397)         """,
398)         msg=r"""
399)         (default: check the `VAULT_KEY`, `LOGNAME`, `USER`, or
400)         `USERNAME` environment variables)
401)         """,
402)         context='help text (option one-line description)',
403)     )
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

404)     HELP_OPTION_HELP_TEXT = _prepare_translatable(
405)         'show this help text, then exit',
406)         comments='',
407)         context='help text (option one-line description)',
408)     )
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

409)     QUIET_OPTION_HELP_TEXT = _prepare_translatable(
410)         'suppress even warnings, emit only errors',
411)         comments='',
412)         context='help text (option one-line description)',
413)     )
414)     VERBOSE_OPTION_HELP_TEXT = _prepare_translatable(
415)         'emit extra/progress information to standard error',
416)         comments='',
417)         context='help text (option one-line description)',
418)     )
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

419)     VERSION_OPTION_HELP_TEXT = _prepare_translatable(
420)         'show applicable version information, then exit',
421)         comments='',
422)         context='help text (option one-line description)',
423)     )
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

424) 
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

425)     DERIVEPASSPHRASE_VAULT_PHRASE_HELP_TEXT = _prepare_translatable(
426)         msg='prompt for a master passphrase',
427)         comments='',
428)         context='help text (option one-line description)',
429)     )
430)     DERIVEPASSPHRASE_VAULT_KEY_HELP_TEXT = _prepare_translatable(
431)         msg='select a suitable SSH key from the SSH agent',
432)         comments='',
433)         context='help text (option one-line description)',
434)     )
435)     DERIVEPASSPHRASE_VAULT_LENGTH_HELP_TEXT = _prepare_translatable(
436)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

437)         TRANSLATORS: The metavar is
438)         Label.PASSPHRASE_GENERATION_METAVAR_NUMBER.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

439)         """,
440)         msg='ensure a passphrase length of {metavar!s} characters',
441)         context='help text (option one-line description)',
442)         flags='python-brace-format',
443)     )
444)     DERIVEPASSPHRASE_VAULT_REPEAT_HELP_TEXT = _prepare_translatable(
445)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

446)         TRANSLATORS: The metavar is
447)         Label.PASSPHRASE_GENERATION_METAVAR_NUMBER.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

448)         """,
449)         msg='forbid any run of {metavar!s} identical characters',
450)         context='help text (option one-line description)',
451)         flags='python-brace-format',
452)     )
453)     DERIVEPASSPHRASE_VAULT_LOWER_HELP_TEXT = _prepare_translatable(
454)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

455)         TRANSLATORS: The metavar is
456)         Label.PASSPHRASE_GENERATION_METAVAR_NUMBER.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

457)         """,
458)         msg='ensure at least {metavar!s} lowercase characters',
459)         context='help text (option one-line description)',
460)         flags='python-brace-format',
461)     )
462)     DERIVEPASSPHRASE_VAULT_UPPER_HELP_TEXT = _prepare_translatable(
463)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

464)         TRANSLATORS: The metavar is
465)         Label.PASSPHRASE_GENERATION_METAVAR_NUMBER.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

466)         """,
467)         msg='ensure at least {metavar!s} uppercase characters',
468)         context='help text (option one-line description)',
469)         flags='python-brace-format',
470)     )
471)     DERIVEPASSPHRASE_VAULT_NUMBER_HELP_TEXT = _prepare_translatable(
472)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

473)         TRANSLATORS: The metavar is
474)         Label.PASSPHRASE_GENERATION_METAVAR_NUMBER.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

475)         """,
476)         msg='ensure at least {metavar!s} digits',
477)         context='help text (option one-line description)',
478)         flags='python-brace-format',
479)     )
480)     DERIVEPASSPHRASE_VAULT_SPACE_HELP_TEXT = _prepare_translatable(
481)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

482)         TRANSLATORS: The metavar is
483)         Label.PASSPHRASE_GENERATION_METAVAR_NUMBER.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

484)         """,
485)         msg='ensure at least {metavar!s} spaces',
486)         context='help text (option one-line description)',
487)         flags='python-brace-format',
488)     )
489)     DERIVEPASSPHRASE_VAULT_DASH_HELP_TEXT = _prepare_translatable(
490)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

491)         TRANSLATORS: The metavar is
492)         Label.PASSPHRASE_GENERATION_METAVAR_NUMBER.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

493)         """,
494)         msg='ensure at least {metavar!s} "-" or "_" characters',
495)         context='help text (option one-line description)',
496)         flags='python-brace-format',
497)     )
498)     DERIVEPASSPHRASE_VAULT_SYMBOL_HELP_TEXT = _prepare_translatable(
499)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

500)         TRANSLATORS: The metavar is
501)         Label.PASSPHRASE_GENERATION_METAVAR_NUMBER.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

502)         """,
503)         msg='ensure at least {metavar!s} symbol characters',
504)         context='help text (option one-line description)',
505)         flags='python-brace-format',
506)     )
507) 
508)     DERIVEPASSPHRASE_VAULT_NOTES_HELP_TEXT = _prepare_translatable(
509)         msg='spawn an editor to edit notes for {service_metavar!s}',
510)         comments='',
511)         context='help text (option one-line description)',
512)         flags='python-brace-format',
513)     )
514)     DERIVEPASSPHRASE_VAULT_CONFIG_HELP_TEXT = _prepare_translatable(
515)         msg='save the given settings for {service_metavar!s}, or global',
516)         comments='',
517)         context='help text (option one-line description)',
518)         flags='python-brace-format',
519)     )
520)     DERIVEPASSPHRASE_VAULT_DELETE_HELP_TEXT = _prepare_translatable(
521)         msg='delete the settings for {service_metavar!s}',
522)         comments='',
523)         context='help text (option one-line description)',
524)         flags='python-brace-format',
525)     )
526)     DERIVEPASSPHRASE_VAULT_DELETE_GLOBALS_HELP_TEXT = _prepare_translatable(
527)         msg='delete the global settings',
528)         comments='',
529)         context='help text (option one-line description)',
530)     )
531)     DERIVEPASSPHRASE_VAULT_DELETE_ALL_HELP_TEXT = _prepare_translatable(
532)         msg='delete all settings',
533)         comments='',
534)         context='help text (option one-line description)',
535)     )
536)     DERIVEPASSPHRASE_VAULT_EXPORT_HELP_TEXT = _prepare_translatable(
537)         comments="""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

538)         TRANSLATORS: The metavar is
539)         Label.STORAGE_MANAGEMENT_METAVAR_SERVICE.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

540)         """,
541)         msg='export all saved settings to {metavar!s}',
542)         context='help text (option one-line description)',
543)         flags='python-brace-format',
544)     )
545)     DERIVEPASSPHRASE_VAULT_IMPORT_HELP_TEXT = _prepare_translatable(
546)         comments="""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

547)         TRANSLATORS: The metavar is
548)         Label.STORAGE_MANAGEMENT_METAVAR_SERVICE.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

549)         """,
550)         msg='import saved settings from {metavar!s}',
551)         context='help text (option one-line description)',
552)         flags='python-brace-format',
553)     )
554)     DERIVEPASSPHRASE_VAULT_OVERWRITE_HELP_TEXT = _prepare_translatable(
555)         comments="""
556)         TRANSLATORS: The corresponding option is displayed as
557)         "--overwrite-existing / --merge-existing", so you may want to
558)         hint that the default (merge) is the second of those options.
559)         """,
560)         msg='overwrite or merge (default) the existing configuration',
561)         context='help text (option one-line description)',
562)     )
563)     DERIVEPASSPHRASE_VAULT_UNSET_HELP_TEXT = _prepare_translatable(
564)         comments="""
565)         TRANSLATORS: The corresponding option is displayed as
566)         "--unset=phrase|key|...|symbol", so the "given setting" is
567)         referring to "phrase", "key", "lower", ..., or "symbol",
568)         respectively.  "with --config" here means that the user must
569)         also specify "--config" for this option to have any effect.
570)         """,
571)         msg="""
572)         with --config, also unsets the given setting; may be specified
573)         multiple times
574)         """,
575)         context='help text (option one-line description)',
576)     )
577)     DERIVEPASSPHRASE_VAULT_EXPORT_AS_HELP_TEXT = _prepare_translatable(
578)         comments="""
579)         TRANSLATORS: The corresponding option is displayed as
580)         "--export-as=json|sh", so json refers to the JSON format
581)         (default) and sh refers to the POSIX sh format.
582)         """,
583)         msg='when exporting, export as JSON (default) or POSIX sh',
584)         context='help text (option one-line description)',
585)     )
586) 
587)     EXPORT_VAULT_FORMAT_METAVAR_FMT = _prepare_translatable(
588)         msg='FMT',
589)         comments='',
590)         context='help text, metavar (export vault subcommand)',
591)     )
592)     EXPORT_VAULT_KEY_METAVAR_K = _prepare_translatable(
593)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

594)         TRANSLATORS: See Label.EXPORT_VAULT_KEY_HELP_TEXT.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

595)         """,
596)         msg='K',
597)         context='help text, metavar (export vault subcommand)',
598)     )
599)     EXPORT_VAULT_METAVAR_PATH = _prepare_translatable(
600)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

601)         TRANSLATORS: Used as "path_metavar" in
602)         Label.DERIVEPASSPHRASE_EXPORT_VAULT_02 and others.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

603)         """,
604)         msg='PATH',
605)         context='help text, metavar (export vault subcommand)',
606)     )
607)     PASSPHRASE_GENERATION_METAVAR_NUMBER = _prepare_translatable(
608)         comments=r"""
609)         TRANSLATORS: This metavar is also used in a matching epilog.
610)         """,
611)         msg='NUMBER',
612)         context='help text, metavar (passphrase generation group)',
613)     )
614)     STORAGE_MANAGEMENT_METAVAR_PATH = _prepare_translatable(
615)         comments=r"""
616)         TRANSLATORS: This metavar is also used in multiple one-line help
617)         texts.
618)         """,
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

619)         msg='PATH',
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

620)         context='help text, metavar (storage management group)',
621)     )
622)     VAULT_METAVAR_SERVICE = _prepare_translatable(
623)         comments=r"""
624)         TRANSLATORS: This metavar is also used in multiple one-line help
625)         texts, as "service_metavar".
626)         """,
627)         msg='SERVICE',
628)         context='help text, metavar (vault subcommand)',
629)     )
630)     CONFIGURATION_EPILOG = _prepare_translatable(
631)         'Use $VISUAL or $EDITOR to configure the spawned editor.',
632)         comments='',
633)         context='help text, option group epilog (configuration group)',
634)     )
635)     PASSPHRASE_GENERATION_EPILOG = _prepare_translatable(
636)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

637)         TRANSLATORS: The metavar is
638)         Label.PASSPHRASE_GENERATION_METAVAR_NUMBER.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

639)         """,
640)         msg=r"""
641)         Use {metavar!s}=0 to exclude a character type from the output.
642)         """,
643)         context='help text, option group epilog (passphrase generation group)',
644)         flags='python-brace-format',
645)     )
646)     STORAGE_MANAGEMENT_EPILOG = _prepare_translatable(
647)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

648)         TRANSLATORS: The metavar is
649)         Label.STORAGE_MANAGEMENT_METAVAR_PATH.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

650)         """,
651)         msg=r"""
652)         Using "-" as {metavar!s} for standard input/standard output
653)         is supported.
654)         """,
655)         context='help text, option group epilog (storage management group)',
656)         flags='python-brace-format',
657)     )
658)     COMMANDS_LABEL = _prepare_translatable(
659)         'Commands', comments='', context='help text, option group name'
660)     )
661)     COMPATIBILITY_OPTION_LABEL = _prepare_translatable(
662)         'Compatibility and extension options',
663)         comments='',
664)         context='help text, option group name',
665)     )
666)     CONFIGURATION_LABEL = _prepare_translatable(
667)         'Configuration', comments='', context='help text, option group name'
668)     )
669)     LOGGING_LABEL = _prepare_translatable(
670)         'Logging', comments='', context='help text, option group name'
671)     )
672)     OPTIONS_LABEL = _prepare_translatable(
673)         'Options', comments='', context='help text, option group name'
674)     )
675)     OTHER_OPTIONS_LABEL = _prepare_translatable(
676)         'Other options', comments='', context='help text, option group name'
677)     )
678)     PASSPHRASE_GENERATION_LABEL = _prepare_translatable(
679)         'Passphrase generation',
680)         comments='',
681)         context='help text, option group name',
682)     )
683)     STORAGE_MANAGEMENT_LABEL = _prepare_translatable(
684)         'Storage management',
685)         comments='',
686)         context='help text, option group name',
687)     )
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

688)     VERSION_INFO_TEXT = _prepare_translatable(
689)         msg=r"""
690)         {PROG_NAME!s} {__version__}
691)         """,  # noqa: RUF027
692)         comments='',
693)         context='help text, version info text',
694)         flags='python-brace-format',
695)     )
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

696)     CONFIRM_THIS_CHOICE_PROMPT_TEXT = _prepare_translatable(
697)         comments=r"""
698)         TRANSLATORS: There is no support for "yes" or "no" in other
699)         languages than English, so it is advised that your translation
700)         makes it clear that only the strings "y", "yes", "n" or "no" are
701)         supported, even if the prompt becomes a bit longer.
702)         """,
703)         msg='Confirm this choice? (y/N)',
704)         context='interactive prompt',
705)     )
706)     SUITABLE_SSH_KEYS_LABEL = _prepare_translatable(
707)         comments=r"""
708)         TRANSLATORS: This label is the heading of the list of suitable
709)         SSH keys.
710)         """,
711)         msg='Suitable SSH keys:',
712)         context='interactive prompt',
713)     )
714)     YOUR_SELECTION_PROMPT_TEXT = _prepare_translatable(
715)         'Your selection? (1-{n}, leave empty to abort)',
716)         comments='',
717)         context='interactive prompt',
718)         flags='python-brace-format',
719)     )
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

720) 
721) 
722) class InfoMsgTemplate(enum.Enum):
723)     CANNOT_LOAD_AS_VAULT_CONFIG = _prepare_translatable(
724)         comments=r"""
725)         TRANSLATORS: "fmt" is a string such as "v0.2" or "storeroom",
726)         indicating the format which we tried to load the vault
727)         configuration as.
728)         """,
729)         msg='Cannot load {path!r} as a {fmt!s} vault configuration.',
730)         context='info message',
731)         flags='python-brace-format',
732)     )
733)     PIP_INSTALL_EXTRA = _prepare_translatable(
734)         comments=r"""
735)         TRANSLATORS: This message immediately follows an error message
736)         about a missing library that needs to be installed.  The Python
737)         Package Index (PyPI) supports declaring sets of optional
738)         dependencies as "extras", so users installing from PyPI can
739)         request reinstallation with a named "extra" being enabled.  This
740)         would then let the installer take care of the missing libraries
741)         automatically, hence this suggestion to PyPI users.
742)         """,
743)         msg='(For users installing from PyPI, see the {extra_name!r} extra.)',
744)         context='info message',
745)         flags='python-brace-format',
746)     )
747)     SUCCESSFULLY_MIGRATED = _prepare_translatable(
748)         comments=r"""
749)         TRANSLATORS: This info message immediately follows the "Using
750)         deprecated v0.1-style ..." deprecation warning.
751)         """,
752)         msg='Successfully migrated to {path!r}.',
753)         context='info message',
754)         flags='python-brace-format',
755)     )
756) 
757) 
758) class WarnMsgTemplate(enum.Enum):
759)     EMPTY_SERVICE_NOT_SUPPORTED = _prepare_translatable(
760)         comments='',
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

761)         msg="""
762)         An empty {service_metavar!s} is not supported by vault(1).
763)         For compatibility, this will be treated as if SERVICE was not
764)         supplied, i.e., it will error out, or operate on global settings.
765)         """,
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

766)         context='warning message',
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

767)         flags='python-brace-format',
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

768)     )
769)     EMPTY_SERVICE_SETTINGS_INACCESSIBLE = _prepare_translatable(
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

770)         msg="""
771)         An empty {service_metavar!s} is not supported by vault(1).
772)         The empty-string service settings will be inaccessible and
773)         ineffective.  To ensure that vault(1) and {PROG_NAME!s} see the
774)         settings, move them into the "global" section.
775)         """,
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

776)         comments='',
777)         context='warning message',
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

778)         flags='python-brace-format',
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

779)     )
780)     FAILED_TO_MIGRATE_CONFIG = _prepare_translatable(
781)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

782)         TRANSLATORS: "error" is supplied by the operating system
783)         (errno/strerror).
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

784)         """,
785)         msg='Failed to migrate to {path!r}: {error!s}: {filename!r}.',
786)         context='warning message',
787)         flags='python-brace-format',
788)     )
789)     GLOBAL_PASSPHRASE_INEFFECTIVE = _prepare_translatable(
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

790)         msg=r"""
791)         Setting a global passphrase is ineffective
792)         because a key is also set.
793)         """,
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

794)         comments='',
795)         context='warning message',
796)     )
797)     PASSPHRASE_NOT_NORMALIZED = _prepare_translatable(
798)         comments=r"""
799)         TRANSLATORS: The key is a (vault) configuration key, in JSONPath
800)         syntax, typically "$.global" for the global passphrase or
801)         "$.services.service_name" or "$.services["service with spaces"]"
802)         for the services "service_name" and "service with spaces",
803)         respectively.  The form is one of the four Unicode normalization
804)         forms: NFC, NFD, NFKC, NFKD.
805) 
806)         The asterisks are not special.  Please feel free to substitute
807)         any other appropriate way to mark up emphasis of the word
808)         "displays".
809)         """,
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

810)         msg=r"""
811)         The {key!s} passphrase is not {form!s}-normalized.  Its
812)         serialization as a byte string may not be what you expect it to
813)         be, even if it *displays* correctly.  Please make sure to
814)         double-check any derived passphrases for unexpected results.
815)         """,
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

816)         context='warning message',
817)         flags='python-brace-format',
818)     )
Marco Ricci Consolidate shell completio...

Marco Ricci authored 2 days ago

819)     SERVICE_NAME_INCOMPLETABLE = _prepare_translatable(
820)         msg="""
821)         The service name {service!r} contains an ASCII control
822)         character, which is not supported by our shell completion code.
823)         This service name will therefore not be available for completion
824)         on the command-line.  You may of course still type it in
825)         manually in whatever format your shell accepts, but we highly
826)         recommend choosing a different service name instead.
827)         """,
828)         comments='',
829)         context='warning message',
830)         flags='python-brace-format',
831)     )
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

832)     SERVICE_PASSPHRASE_INEFFECTIVE = _prepare_translatable(
833)         comments=r"""
834)         TRANSLATORS: The key that is set need not necessarily be set at
835)         the service level; it may be a global key as well.
836)         """,
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

837)         msg=r"""
838)         Setting a service passphrase is ineffective because a key is
839)         also set: {service!s}.
840)         """,
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

841)         context='warning message',
842)         flags='python-brace-format',
843)     )
844)     STEP_REMOVE_INEFFECTIVE_VALUE = _prepare_translatable(
845)         'Removing ineffective setting {path!s} = {old!s}.',
846)         comments='',
847)         context='warning message',
848)         flags='python-brace-format',
849)     )
850)     STEP_REPLACE_INVALID_VALUE = _prepare_translatable(
851)         'Replacing invalid value {old!s} for key {path!s} with {new!s}.',
852)         comments='',
853)         context='warning message',
854)         flags='python-brace-format',
855)     )
856)     V01_STYLE_CONFIG = _prepare_translatable(
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

857)         msg=r"""
858)         Using deprecated v0.1-style config file {old!r}, instead of
859)         v0.2-style {new!r}.  Support for v0.1-style config filenames
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

860)         will be removed in v1.0.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

861)         """,
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

862)         comments='',
863)         context='deprecation warning message',
864)         flags='python-brace-format',
865)     )
866)     V10_SUBCOMMAND_REQUIRED = _prepare_translatable(
867)         comments=r"""
868)         TRANSLATORS: This deprecation warning may be issued at any
869)         level, i.e. we may actually be talking about subcommands, or
870)         sub-subcommands, or sub-sub-subcommands, etc., which is what the
871)         "here" is supposed to indicate.
872)         """,
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

873)         msg="""
874)         A subcommand will be required here in v1.0.  See --help for
875)         available subcommands.  Defaulting to subcommand "vault".
876)         """,
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

877)         context='deprecation warning message',
878)     )
879) 
880) 
881) class ErrMsgTemplate(enum.Enum):
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

882)     AGENT_REFUSED_LIST_KEYS = _prepare_translatable(
883)         comments=r"""
884)         TRANSLATORS: "loaded keys" being keys loaded into the agent.
885)         """,
886)         msg="""
887)         The SSH agent failed to or refused to supply a list of loaded keys.
888)         """,
889)         context='error message',
890)     )
891)     AGENT_REFUSED_SIGNATURE = _prepare_translatable(
892)         comments=r"""
893)         TRANSLATORS: The message to be signed is the vault UUID, but
894)         there's no space to explain that here, so ideally the error
895)         message does not go into detail.
896)         """,
897)         msg="""
898)         The SSH agent failed to or refused to issue a signature with the
899)         selected key, necessary for deriving a service passphrase.
900)         """,
901)         context='error message',
902)     )
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

903)     CANNOT_CONNECT_TO_AGENT = _prepare_translatable(
904)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

905)         TRANSLATORS: "error" is supplied by the operating system
906)         (errno/strerror).
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

907)         """,
908)         msg='Cannot connect to the SSH agent: {error!s}: {filename!r}.',
909)         context='error message',
910)         flags='python-brace-format',
911)     )
912)     CANNOT_DECODEIMPORT_VAULT_SETTINGS = _prepare_translatable(
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

913)         comments=r"""
914)         TRANSLATORS: "error" is supplied by the operating system
915)         (errno/strerror).
916)         """,
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

917)         msg='Cannot import vault settings: cannot decode JSON: {error!s}.',
918)         context='error message',
919)         flags='python-brace-format',
920)     )
921)     CANNOT_EXPORT_VAULT_SETTINGS = _prepare_translatable(
922)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

923)         TRANSLATORS: "error" is supplied by the operating system
924)         (errno/strerror).
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

925)         """,
926)         msg='Cannot export vault settings: {error!s}: {filename!r}.',
927)         context='error message',
928)         flags='python-brace-format',
929)     )
930)     CANNOT_IMPORT_VAULT_SETTINGS = _prepare_translatable(
931)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

932)         TRANSLATORS: "error" is supplied by the operating system
933)         (errno/strerror).
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

934)         """,
935)         msg='Cannot import vault settings: {error!s}: {filename!r}.',
936)         context='error message',
937)         flags='python-brace-format',
938)     )
939)     CANNOT_LOAD_USER_CONFIG = _prepare_translatable(
940)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

941)         TRANSLATORS: "error" is supplied by the operating system
942)         (errno/strerror).
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

943)         """,
944)         msg='Cannot load user config: {error!s}: {filename!r}.',
945)         context='error message',
946)         flags='python-brace-format',
947)     )
948)     CANNOT_LOAD_VAULT_SETTINGS = _prepare_translatable(
949)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

950)         TRANSLATORS: "error" is supplied by the operating system
951)         (errno/strerror).
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

952)         """,
953)         msg='Cannot load vault settings: {error!s}: {filename!r}.',
954)         context='error message',
955)         flags='python-brace-format',
956)     )
957)     CANNOT_PARSE_AS_VAULT_CONFIG = _prepare_translatable(
958)         comments=r"""
959)         TRANSLATORS: Unlike the "Cannot load {path!r} as a {fmt!s} vault
960)         configuration." message, *this* error message is emitted when we
961)         have tried loading the path in each of our supported formats,
962)         and failed.  The user will thus see the above "Cannot load ..."
963)         warning message potentially multiple times, and this error
964)         message at the very bottom.
965)         """,
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

966)         msg=r"""
967)         Cannot parse {path!r} as a valid vault-native configuration
968)         file/directory.
969)         """,
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

970)         context='error message',
971)         flags='python-brace-format',
972)     )
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

973)     CANNOT_PARSE_AS_VAULT_CONFIG_OSERROR = _prepare_translatable(
974)         comments=r"""
975)         TRANSLATORS: "error" is supplied by the operating system
976)         (errno/strerror).
977)         """,
978)         msg=r"""
979)         Cannot parse {path!r} as a valid vault-native configuration
980)         file/directory: {error!s}: {filename!r}.
981)         """,
982)         context='error message',
983)         flags='python-brace-format',
984)     )
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

985)     CANNOT_STORE_VAULT_SETTINGS = _prepare_translatable(
986)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

987)         TRANSLATORS: "error" is supplied by the operating system
988)         (errno/strerror).
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

989)         """,
990)         msg='Cannot store vault settings: {error!s}: {filename!r}.',
991)         context='error message',
992)         flags='python-brace-format',
993)     )
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

994)     CANNOT_UNDERSTAND_AGENT = _prepare_translatable(
995)         comments=r"""
996)         TRANSLATORS: This error message is used whenever we cannot make
997)         any sense of a response from the SSH agent because the response
998)         is ill-formed (truncated, improperly encoded, etc.) or otherwise
999)         violates the communications protocol.  Well-formed responses
1000)         that adhere to the protocol, even if they indicate that the
1001)         requested operation failed, are handled with a different error
1002)         message.
1003)         """,
1004)         msg="""
1005)         Cannot understand the SSH agent's response because it violates
1006)         the communications protocol.
1007)         """,
1008)     )
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1009)     CANNOT_UPDATE_SETTINGS_NO_SETTINGS = _prepare_translatable(
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

1010)         msg=r"""
1011)         Cannot update {settings_type!s} settings without any given
1012)         settings.  You must specify at least one of --lower, ...,
1013)         --symbol, or --phrase or --key.
1014)         """,
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1015)         comments='',
1016)         context='error message',
1017)         flags='python-brace-format',
1018)     )
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

1019)     INVALID_USER_CONFIG = _prepare_translatable(
1020)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

1021)         TRANSLATORS: "error" is supplied by the operating system
1022)         (errno/strerror).
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

1023)         """,
1024)         msg=r"""
1025)         The user configuration file is invalid.  {error!s}: {filename!r}.
1026)         """,
1027)         context='error message',
1028)         flags='python-brace-format',
1029)     )
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1030)     INVALID_VAULT_CONFIG = _prepare_translatable(
1031)         comments=r"""
1032)         TRANSLATORS: This error message is a reaction to a validator
1033)         function saying *that* the configuration is not valid, but not
1034)         *how* it is not valid.  The configuration file is principally
1035)         parsable, however.
1036)         """,
1037)         msg='Invalid vault config: {config!r}.',
1038)         context='error message',
1039)         flags='python-brace-format',
1040)     )
1041)     MISSING_MODULE = _prepare_translatable(
1042)         'Cannot load the required Python module {module!r}.',
1043)         comments='',
1044)         context='error message',
1045)         flags='python-brace-format',
1046)     )
1047)     NO_AF_UNIX = _prepare_translatable(
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

1048)         msg=r"""
1049)         Cannot connect to an SSH agent because this Python version does
1050)         not support UNIX domain sockets.
1051)         """,
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1052)         comments='',
1053)         context='error message',
1054)     )
1055)     NO_KEY_OR_PHRASE = _prepare_translatable(
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

1056)         msg=r"""
1057)         No passphrase or key was given in the configuration.  In this
1058)         case, the --phrase or --key argument is required.
1059)         """,
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1060)         comments='',
1061)         context='error message',
1062)     )
1063)     NO_SSH_AGENT_FOUND = _prepare_translatable(
1064)         'Cannot find any running SSH agent because SSH_AUTH_SOCK is not set.',
1065)         comments='',
1066)         context='error message',
1067)     )
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

1068)     NO_SUITABLE_SSH_KEYS = _prepare_translatable(
1069)         msg="""
1070)         The SSH agent contains no keys suitable for {PROG_NAME!s}.
1071)         """,  # noqa: RUF027
1072)         comments='',
1073)         context='error message',
1074)         flags='python-brace-format',
1075)     )
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1076)     PARAMS_MUTUALLY_EXCLUSIVE = _prepare_translatable(
1077)         comments=r"""
1078)         TRANSLATORS: The params are long-form command-line option names.
1079)         Typical example: "--key is mutually exclusive with --phrase."
1080)         """,
1081)         msg='{param1!s} is mutually exclusive with {param2!s}.',
1082)         context='error message',
1083)         flags='python-brace-format',
1084)     )
1085)     PARAMS_NEEDS_SERVICE_OR_CONFIG = _prepare_translatable(
1086)         comments=r"""
1087)         TRANSLATORS: The param is a long-form command-line option name,
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

1088)         the metavar is Label.VAULT_METAVAR_SERVICE.
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1089)         """,
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

1090)         msg='{param!s} requires a {service_metavar!s} or --config.',
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1091)         context='error message',
1092)         flags='python-brace-format',
1093)     )
1094)     PARAMS_NEEDS_SERVICE = _prepare_translatable(
1095)         comments=r"""
1096)         TRANSLATORS: The param is a long-form command-line option name,
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

1097)         the metavar is Label.VAULT_METAVAR_SERVICE.
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1098)         """,
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

1099)         msg='{param!s} requires a {service_metavar!s}.',
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1100)         context='error message',
1101)         flags='python-brace-format',
1102)     )
1103)     PARAMS_NO_SERVICE = _prepare_translatable(
1104)         comments=r"""
1105)         TRANSLATORS: The param is a long-form command-line option name,
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

1106)         the metavar is Label.VAULT_METAVAR_SERVICE.
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1107)         """,
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

1108)         msg='{param!s} does not take a {service_metavar!s} argument.',
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1109)         context='error message',
1110)         flags='python-brace-format',
1111)     )
1112)     SERVICE_REQUIRED = _prepare_translatable(
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

1113)         comments=r"""
Marco Ricci Fix some translation typos...

Marco Ricci authored 1 week ago

1114)         TRANSLATORS: The metavar is Label.VAULT_METAVAR_SERVICE.
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

1115)         """,
1116)         msg='Deriving a passphrase requires a {service_metavar!s}.',
1117)         context='error message',
1118)         flags='python-brace-format',
1119)     )
1120)     SET_AND_UNSET_SAME_SETTING = _prepare_translatable(
1121)         comments=r"""
1122)         TRANSLATORS: The rephrasing "Attempted to unset and set the same
1123)         setting (--unset={setting!s} --{setting!s}=...) at the same
1124)         time." may or may not be more suitable as a basis for
1125)         translation instead.
1126)         """,
1127)         msg='Attempted to unset and set --{setting!s} at the same time.',
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1128)         context='error message',
Marco Ricci Add more translatable strin...

Marco Ricci authored 1 week ago

1129)         flags='python-brace-format',
Marco Ricci Extract translatable log me...

Marco Ricci authored 2 weeks ago

1130)     )
1131)     SSH_KEY_NOT_LOADED = _prepare_translatable(
1132)         'The requested SSH key is not loaded into the agent.',
1133)         comments='',
1134)         context='error message',
1135)     )
1136)     USER_ABORTED_EDIT = _prepare_translatable(
1137)         'Not saving any new notes: the user aborted the request.',
1138)         comments='',
1139)         context='error message',
1140)     )
1141)     USER_ABORTED_PASSPHRASE = _prepare_translatable(
1142)         'No passphrase was given; the user aborted the request.',
1143)         comments='',
1144)         context='error message',
1145)     )
1146)     USER_ABORTED_SSH_KEY_SELECTION = _prepare_translatable(
1147)         'No SSH key was selected; the user aborted the request.',
1148)         comments='',
1149)         context='error message',
1150)     )
Marco Ricci Add a writer function for d...

Marco Ricci authored 1 week ago

1151) 
1152) 
Marco Ricci Fix coverage

Marco Ricci authored 1 week ago

1153) def _write_pot_file(fileobj: TextIO) -> None:  # pragma: no cover
Marco Ricci Add a writer function for d...

Marco Ricci authored 1 week ago

1154)     r"""Write a .po template to the given file object.
1155) 
1156)     Assumes the file object is opened for writing and accepts string
1157)     inputs.  The file will *not* be closed when writing is complete.
1158)     The file *must* be opened in UTF-8 encoding, lest the file will
1159)     declare an incorrect encoding.
1160) 
1161)     This function crucially depends on all translatable strings
1162)     appearing in the enums of this module.  Certain parts of the
1163)     .po header are hard-coded, as is the source filename.
1164) 
1165)     """
1166)     entries: dict[
1167)         str,
1168)         dict[
1169)             str,
1170)             Label | InfoMsgTemplate | WarnMsgTemplate | ErrMsgTemplate,
1171)         ],
1172)     ] = {}
1173)     for enum_class in (
1174)         Label,
1175)         InfoMsgTemplate,
1176)         WarnMsgTemplate,
1177)         ErrMsgTemplate,
1178)     ):
1179)         for member in enum_class.__members__.values():
1180)             ctx = member.value.l10n_context
1181)             msg = member.value.singular
1182)             if (
1183)                 msg in entries.setdefault(ctx, {})
1184)                 and entries[ctx][msg] != member
1185)             ):
1186)                 raise AssertionError(  # noqa: DOC501,TRY003
1187)                     f'Duplicate entry for ({ctx!r}, {msg!r}): '  # noqa: EM102
1188)                     f'{entries[ctx][msg]!r} and {member!r}'
1189)                 )
1190)             entries[ctx][msg] = member
1191)     now = datetime.datetime.now().astimezone()
1192)     header = (
1193)         inspect.cleandoc(rf"""
1194)         # English translation for {PROG_NAME!s}.
1195)         # Copyright (C) {now.strftime('%Y')} AUTHOR
1196)         # This file is distributed under the same license as {PROG_NAME!s}.
1197)         # AUTHOR <someone@example.com>, {now.strftime('%Y')}.
1198)         #
1199)         msgid ""
1200)         msgstr ""
1201)         "Project-Id-Version: {PROG_NAME!s} {__version__!s}\n"
1202)         "Report-Msgid-Bugs-To: software@the13thletter.info\n"
1203)         "POT-Creation-Date: {now.strftime('%Y-%m-%d %H:%M%z')}\n"
1204)         "PO-Revision-Date: {now.strftime('%Y-%m-%d %H:%M%z')}\n"
1205)         "Last-Translator: AUTHOR <someone@example.com>\n"
1206)         "Language: en\n"
1207)         "MIME-Version: 1.0\n"
1208)         "Content-Type: text/plain; charset=UTF-8\n"
1209)         "Content-Transfer-Encoding: 8bit\n"
1210)         "Plural-Forms: nplurals=2; plural=(n != 1);\n"
1211)         """).removesuffix('\n')
1212)         + '\n'
1213)     )
1214)     fileobj.write(header)
1215)     for _ctx, subdict in sorted(entries.items()):
1216)         for _msg, enum_value in sorted(
1217)             subdict.items(),
1218)             key=lambda kv: str(kv[1]),
1219)         ):
1220)             fileobj.writelines(_format_po_entry(enum_value))
1221) 
1222) 
1223) def _format_po_entry(
1224)     enum_value: Label | InfoMsgTemplate | WarnMsgTemplate | ErrMsgTemplate,
Marco Ricci Fix coverage

Marco Ricci authored 1 week ago

1225) ) -> tuple[str, ...]:  # pragma: no cover
Marco Ricci Add a writer function for d...

Marco Ricci authored 1 week ago

1226)     ret: list[str] = ['\n']
1227)     ts = enum_value.value
1228)     if ts.translator_comments:
1229)         ret.extend(
1230)             f'#. {line}\n'
1231)             for line in ts.translator_comments.splitlines(False)  # noqa: FBT003
1232)         )
1233)     ret.append(f'#: derivepassphrase/_cli_msg.py:{enum_value}\n')
1234)     if ts.flags:
1235)         ret.append(f'#, {", ".join(sorted(ts.flags))}\n')
1236)     if ts.l10n_context:
1237)         ret.append(f'msgctxt {_cstr(ts.l10n_context)}\n')
1238)     ret.append(f'msgid {_cstr(ts.singular)}\n')
1239)     if ts.plural:
1240)         ret.append(f'msgid_plural {_cstr(ts.plural)}\n')
1241)     ret.append('msgstr ""\n')
1242)     return tuple(ret)
1243) 
1244) 
Marco Ricci Fix coverage

Marco Ricci authored 1 week ago

1245) def _cstr(s: str) -> str:  # pragma: no cover
Marco Ricci Add a writer function for d...

Marco Ricci authored 1 week ago

1246)     def escape(string: str) -> str:
1247)         return string.translate({
1248)             0: r'\000',
1249)             1: r'\001',
1250)             2: r'\002',
1251)             3: r'\003',
1252)             4: r'\004',
1253)             5: r'\005',
1254)             6: r'\006',
1255)             7: r'\007',
1256)             8: r'\b',
1257)             9: r'\t',
1258)             10: r'\n',
1259)             11: r'\013',
1260)             12: r'\f',
1261)             13: r'\r',
1262)             14: r'\016',
1263)             15: r'\017',
1264)             ord('"'): r'\"',
1265)             ord('\\'): r'\\',
1266)             127: r'\177',
1267)         })
1268) 
1269)     return '\n'.join(
1270)         f'"{escape(line)}"'
1271)         for line in s.splitlines(True)  # noqa: FBT003
1272)     )
1273) 
1274) 
1275) if __name__ == '__main__':