[PATCH v3 5/6] argp: use "command-line option" context for option name translation
Vivien Kraus
vivien@planete-kraus.eu
Sat May 31 21:14:48 GMT 2025
A disambiguation context is useful, because option names are usually
single words, but the public API cannot let the caller override it
without introducing new fields.
---
argp/argp-help.c | 35 +++++++++++++++++++++++++++++-----
argp/argp-parse.c | 1 +
argp/tst-argphelp-localized.c | 6 +++---
argp/tst-argphelp-localized.po | 1 +
argp/tst-argpusage-localized.c | 6 +++---
manual/argp.texi | 14 ++++++++------
6 files changed, 46 insertions(+), 17 deletions(-)
diff --git a/argp/argp-help.c b/argp/argp-help.c
index bf459bf372..672e733fc8 100644
--- a/argp/argp-help.c
+++ b/argp/argp-help.c
@@ -1213,6 +1213,7 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
unsigned num;
const struct argp_option *real = entry->opt, *opt;
char *so = entry->short_options;
+ char *option_msgid;
const char *translated_option_name;
int have_long_opt = 0; /* We have any long options. */
/* Saved margins. */
@@ -1277,12 +1278,25 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
if (opt->name && ovisible (opt))
{
comma (uparams.long_opt_col, &pest);
- translated_option_name = gettext (opt->name);
+ option_msgid =
+ malloc (strlen ("command-line option\004")
+ + strlen (opt->name) + 1);
+ if (option_msgid)
+ {
+ strcpy (option_msgid, "command-line option\004");
+ strcat (option_msgid, opt->name);
+ translated_option_name = gettext (option_msgid);
+ if (!strcmp (translated_option_name, option_msgid))
+ translated_option_name = opt->name;
+ }
+ else
+ translated_option_name = opt->name;
__argp_fmtstream_printf (stream, "--%s", translated_option_name);
arg (real, "=%s", "[=%s]",
state == NULL ? NULL : state->root_argp->argp_domain, stream);
if (strcmp (translated_option_name, opt->name))
__argp_fmtstream_printf (stream, " (--%s)", opt->name);
+ free (option_msgid);
}
}
@@ -1424,6 +1438,7 @@ usage_long_opt (const struct argp_option *opt,
{
argp_fmtstream_t stream = cookie;
const char *arg = opt->arg;
+ char *option_msgid;
const char *translated_opt_name = opt->name;
int flags = opt->flags | real->flags;
@@ -1432,10 +1447,19 @@ usage_long_opt (const struct argp_option *opt,
if (! (flags & OPTION_NO_USAGE))
{
- /* getopt does not recognize the domain, so the name will be
- translated in the current default textdomain. We want to
- document this string. */
- translated_opt_name = gettext (opt->name);
+ /* Since we cannot customize the translation context, we will
+ use a default one. FIXME: use pgettext_expr(). */
+ static const char *default_context = "command-line option\004";
+ option_msgid = malloc (strlen (default_context) + strlen (opt->name) + 1);
+ translated_opt_name = NULL;
+ if (option_msgid)
+ {
+ strcpy (option_msgid, default_context);
+ strcat (option_msgid, opt->name);
+ translated_opt_name = gettext (option_msgid);
+ if (!strcmp (translated_opt_name, option_msgid))
+ translated_opt_name = opt->name;
+ }
if (!strcmp (translated_opt_name, opt->name))
translated_opt_name = NULL;
if (arg)
@@ -1457,6 +1481,7 @@ usage_long_opt (const struct argp_option *opt,
translated_opt_name, opt->name);
else
__argp_fmtstream_printf (stream, " [--%s]", opt->name);
+ free (option_msgid);
}
return 0;
diff --git a/argp/argp-parse.c b/argp/argp-parse.c
index 82c7b784de..00fbf104db 100644
--- a/argp/argp-parse.c
+++ b/argp/argp-parse.c
@@ -472,6 +472,7 @@ parser_init (struct parser *parser, const struct argp *argp,
struct parser_sizes szs;
struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER;
+ opt_data.optctxt = "command-line option";
szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
szs.long_len = 0;
szs.num_groups = 0;
diff --git a/argp/tst-argphelp-localized.c b/argp/tst-argphelp-localized.c
index dc4019917a..abc3325827 100644
--- a/argp/tst-argphelp-localized.c
+++ b/argp/tst-argphelp-localized.c
@@ -30,13 +30,13 @@
#include <support/support.h>
-#define N_(str) (str)
+#define PN_(ctxt, str) (str)
const char *argp_program_version = "argphelp-test 1.0";
struct argp_option options[] =
{
- {N_ ("color"), 'c', 0, 0, "Rainbow!"},
+ {PN_ ("command-line option", "color"), 'c', 0, 0, "Rainbow!"},
{0}
};
@@ -83,7 +83,7 @@ main (int argc, char *argv[])
abort ();
}
/* Check that the catalog is OK: */
- if (strcmp (gettext ("color"), "colour") != 0)
+ if (strcmp (gettext ("command-line option\004color"), "colour") != 0)
{
fprintf (stderr, "%s:%d: the mo file does not work.\n",
__FILE__, __LINE__);
diff --git a/argp/tst-argphelp-localized.po b/argp/tst-argphelp-localized.po
index 88bafad274..4e301bf278 100644
--- a/argp/tst-argphelp-localized.po
+++ b/argp/tst-argphelp-localized.po
@@ -13,5 +13,6 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: tst-argphelp-localized.c:73
+msgctxt "command-line option"
msgid "color"
msgstr "colour"
\ No newline at end of file
diff --git a/argp/tst-argpusage-localized.c b/argp/tst-argpusage-localized.c
index 5a992ce3e2..4061609fc3 100644
--- a/argp/tst-argpusage-localized.c
+++ b/argp/tst-argpusage-localized.c
@@ -30,13 +30,13 @@
#include <support/support.h>
-#define N_(str) (str)
+#define PN_(ctxt, str) (str)
const char *argp_program_version = "argpusage-test 1.0";
struct argp_option options[] =
{
- {N_ ("color"), 'c', 0, 0, "Rainbow!"},
+ {PN_ ("command-line option", "color"), 'c', 0, 0, "Rainbow!"},
{0}
};
@@ -69,7 +69,7 @@ main (int argc, char *argv[])
abort ();
}
/* Check that the catalog is OK: */
- if (strcmp (gettext ("color"), "colour") != 0)
+ if (strcmp (gettext ("command-line option\004color"), "colour") != 0)
{
fprintf (stderr, "%s:%d: the mo file does not work.\n",
__FILE__, __LINE__);
diff --git a/manual/argp.texi b/manual/argp.texi
index 6cedf96110..97456ef20e 100644
--- a/manual/argp.texi
+++ b/manual/argp.texi
@@ -208,7 +208,8 @@ messages. @xref{Argp Help Filtering}.
If non-zero, the strings used in the argp library are translated using
the domain described by this string. If zero, the current default
domain is used. The long option names are always translated with the
-current default domain.
+current default domain, and with the @samp{"command-line option"}
+disambiguation string.
@end table
@end deftp
@@ -250,11 +251,12 @@ the following fields:
@item const char *name
The long name for this option, corresponding to the long option
@samp{--@var{name}}; this field may be zero if this option @emph{only}
-has a short name. You should mark this string for translation without
-a context. To specify multiple names for an option, additional
-entries may follow this one, with the @code{OPTION_ALIAS} flag set.
-@xref{Argp Option Flags}. Translations are added automatically, it is
-not necessary to use an alias for translations.
+has a short name. You should mark this string for translation with
+the fixed @samp{"command-line option"} context. To specify multiple
+names for an option, additional entries may follow this one, with the
+@code{OPTION_ALIAS} flag set. @xref{Argp Option Flags}. Translations
+are added automatically, it is not necessary to use an alias for
+translations.
@item int key
The integer key provided by the current option to the option parser. If
--
2.49.0
More information about the Libc-alpha
mailing list