diff mbox series

[4,1/1] parse-options: localize mark-up of placeholder text in the short help

Message ID 20241228114221.10351-4-ash@kambanaria.org (mailing list archive)
State New
Headers show
Series Localize mark-up of placeholder text in the short help | expand

Commit Message

Alexander Shopov Dec. 28, 2024, 11:42 a.m. UTC
i18n: expose substitution hint chars in functions and macros to
translators

For example (based on builtin/commit.c and shortened): the "--author"
option takes a name.  In source this can be represented as:

  OPT_STRING(0, "author", &force_author, N_("author"), N_("override author")),

When the command is run with "-h" (short help) option (git commit -h),
the above definition is displayed as:

  --[no-]author <author>    override author

Git does not use translated option names so the first part of the
above, "--[no-]author", is given as-is (it is based on the 2nd
argument of OPT_STRING).  However the string "author" in the pair of
"<>", and the explanation "override author for commit" may be
translated into user's language.

The user's language may use a convention to mark a replaceable part of
the command line (called a "placeholder string") differently from
enclosing it inside a pair of "<>", but the implementation in
parse-options.c hardcodes "<%s>".

Allow translators to specify the presentation of a placeholder string
for their languages by overriding the "<%s>".

In case the translator's writing system is sufficiently different than
Latin the "<>" characters can be substituted by an empty string thus
effectively skipping them in the output.  For example languages with
uppercase versions of characters can use that to deliniate
replaceability.

Alternatively a translator can decide to use characters that are
visually close to "<>" but are not interpreted by the shell.

Signed-off-by: Alexander Shopov <ash@kambanaria.org>
---
 parse-options.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

Comments

Junio C Hamano Dec. 28, 2024, 4:55 p.m. UTC | #1
Alexander Shopov <ash@kambanaria.org> writes:

> Subject: Re: [PATCH 4 1/1] parse-options: localize mark-up of placeholder text in the short help

It is more common to see "[PATCH v4 1/1]" around here.  In fact, I
suspect that you have to fight the tool to have them produce "[PATCH
4 1/1]".

Not that it matters to me personally (as "git am" on the receiving
end will strip it), but when looking for a specific version of your
patch from the mailing list archive, people may find it harder than
necessary because of the subtle difference.

> i18n: expose substitution hint chars in functions and macros to
> translators
> ...
> In case the translator's writing system is sufficiently different than
> Latin the "<>" characters can be substituted by an empty string thus
> effectively skipping them in the output.  For example languages with
> uppercase versions of characters can use that to deliniate
> replaceability.
>
> Alternatively a translator can decide to use characters that are
> visually close to "<>" but are not interpreted by the shell.

Very well written.

> diff --git a/parse-options.c b/parse-options.c
> index 33bfba0ed4..8904345c07 100644
> --- a/parse-options.c
> +++ b/parse-options.c
> @@ -1076,11 +1076,23 @@ static int usage_argh(const struct option *opts, FILE *outfile)
>  		!opts->argh || !!strpbrk(opts->argh, "()<>[]|");
>  	if (opts->flags & PARSE_OPT_OPTARG)
>  		if (opts->long_name)
> -			s = literal ? "[=%s]" : "[=<%s>]";
> +			s = literal ? "[=%s]" :
> +			  /* TRANSLATORS: %s is a command line argument name, `<>' prompt the user to supply a value for it.
> +			     Change only the `<>' characters to something else if you use another convention for this.
> +			     Most translations leave this message as is. */
> +			  _("[=<%s>]");

This is way too wide.  Documentation/CodingGuidelines should have
something to say on this, but in case it does not, we try to allow
those with 80-column terminals to read our code comfortably, and it
is even better to allow us to do so after a patch is quoted a few
times (i.e. adding a few columns on the left edge), so a practical
limit may be around 70-columns.

Also, our multi-line comments have opening slash-asterisk and closing
asterisk-slash on their own line.

This part is giving a help for the option value argument for a long
option, i.e. for "git subcommand --option[=<value>]", we are talking about
the "[=<value>]" part.  It is not clear "command line argument name"
conveys that.  Something along this line, perhaps?

    The "<%s>" part of this string stands for an optional value given to a
    command line option in the long form, and "<>" is there as a
    convention to signal that it is a placeholder (i.e. the user should
    substitute it with the real value).  If your language uses a different
    convention, you can change "<%s>" part to match yours, e.g. it might
    use "|%s|" instead, or if the alphabet is different enough it may use
    "%s" without any placeholder signal.  Most translations leave this
    message as is.

> +			  _("[=<%s>]");
>  		else
> -			s = literal ? "[%s]" : "[<%s>]";
> +			s = literal ? "[%s]" :
> +			  /* TRANSLATORS: %s is a command line argument name, `<>' prompt the user to supply a value for it.
> +			     Change only the `<>' characters to something else if you use another convention for this.
> +			     Most translations leave this message as is. */
> +			  _("[<%s>]");

Ditto, except that this is for "the short form".

>  	else
> -		s = literal ? " %s" : " <%s>";
> +		s = literal ? " %s" :
> +		  /* TRANSLATORS: %s is a command line argument name, `<>' prompt the user to supply a value for it.
> +		     Change only the `<>' characters to something else if you use another convention for this.
> +		     Most translations leave this message as is. */
> +		  _(" <%s>");

Ditto, except that this is for "a value given to a command line option",
not specific to either long or short form.

>  	return utf8_fprintf(outfile, s, opts->argh ? _(opts->argh) : _("..."));
>  }


I'll queue with the following change on top.
Thanks.


 parse-options.c | 55 ++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 40 insertions(+), 15 deletions(-)

diff --git c/parse-options.c w/parse-options.c
index 8904345c07..3ff6a5d1fa 100644
--- c/parse-options.c
+++ w/parse-options.c
@@ -1076,23 +1076,48 @@ static int usage_argh(const struct option *opts, FILE *outfile)
 		!opts->argh || !!strpbrk(opts->argh, "()<>[]|");
 	if (opts->flags & PARSE_OPT_OPTARG)
 		if (opts->long_name)
-			s = literal ? "[=%s]" :
-			  /* TRANSLATORS: %s is a command line argument name, `<>' prompt the user to supply a value for it.
-			     Change only the `<>' characters to something else if you use another convention for this.
-			     Most translations leave this message as is. */
-			  _("[=<%s>]");
+			/*
+			 * TRANSLATORS: The "<%s>" part of this string
+			 * stands for an optional value given to a command
+			 * line option in the long form, and "<>" is there
+			 * as a convention to signal that it is a
+			 * placeholder (i.e. the user should substitute it
+			 * with the real value).  If your language uses a
+			 * different convention, you can change "<%s>" part
+			 * to match yours, e.g. it might use "|%s|" instead,
+			 * or if the alphabet is different enough it may use
+			 * "%s" without any placeholder signal.  Most
+			 * translations leave this message as is.
+			 */
+			s = literal ? "[=%s]" : _("[=<%s>]");
 		else
-			s = literal ? "[%s]" :
-			  /* TRANSLATORS: %s is a command line argument name, `<>' prompt the user to supply a value for it.
-			     Change only the `<>' characters to something else if you use another convention for this.
-			     Most translations leave this message as is. */
-			  _("[<%s>]");
+			/*
+			 * TRANSLATORS: The "<%s>" part of this string
+			 * stands for an optional value given to a command
+			 * line option in the short form, and "<>" is there
+			 * as a convention to signal that it is a
+			 * placeholder (i.e. the user should substitute it
+			 * with the real value).  If your language uses a
+			 * different convention, you can change "<%s>" part
+			 * to match yours, e.g. it might use "|%s|" instead,
+			 * or if the alphabet is different enough it may use
+			 * "%s" without any placeholder signal.  Most
+			 * translations leave this message as is.
+			 */
+			s = literal ? "[%s]" : _("[<%s>]");
 	else
-		s = literal ? " %s" :
-		  /* TRANSLATORS: %s is a command line argument name, `<>' prompt the user to supply a value for it.
-		     Change only the `<>' characters to something else if you use another convention for this.
-		     Most translations leave this message as is. */
-		  _(" <%s>");
+		/*
+		 * TRANSLATORS: The "<%s>" part of this string stands for a
+		 * value given to a command line option, and "<>" is there
+		 * as a convention to signal that it is a placeholder
+		 * (i.e. the user should substitute it with the real value).
+		 * If your language uses a different convention, you can
+		 * change "<%s>" part to match yours, e.g. it might use
+		 * "|%s|" instead, or if the alphabet is different enough it
+		 * may use "%s" without any placeholder signal.  Most
+		 * translations leave this message as is.
+		 */
+		s = literal ? " %s" : _(" <%s>");
 	return utf8_fprintf(outfile, s, opts->argh ? _(opts->argh) : _("..."));
 }
diff mbox series

Patch

diff --git a/parse-options.c b/parse-options.c
index 33bfba0ed4..8904345c07 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -1076,11 +1076,23 @@  static int usage_argh(const struct option *opts, FILE *outfile)
 		!opts->argh || !!strpbrk(opts->argh, "()<>[]|");
 	if (opts->flags & PARSE_OPT_OPTARG)
 		if (opts->long_name)
-			s = literal ? "[=%s]" : "[=<%s>]";
+			s = literal ? "[=%s]" :
+			  /* TRANSLATORS: %s is a command line argument name, `<>' prompt the user to supply a value for it.
+			     Change only the `<>' characters to something else if you use another convention for this.
+			     Most translations leave this message as is. */
+			  _("[=<%s>]");
 		else
-			s = literal ? "[%s]" : "[<%s>]";
+			s = literal ? "[%s]" :
+			  /* TRANSLATORS: %s is a command line argument name, `<>' prompt the user to supply a value for it.
+			     Change only the `<>' characters to something else if you use another convention for this.
+			     Most translations leave this message as is. */
+			  _("[<%s>]");
 	else
-		s = literal ? " %s" : " <%s>";
+		s = literal ? " %s" :
+		  /* TRANSLATORS: %s is a command line argument name, `<>' prompt the user to supply a value for it.
+		     Change only the `<>' characters to something else if you use another convention for this.
+		     Most translations leave this message as is. */
+		  _(" <%s>");
 	return utf8_fprintf(outfile, s, opts->argh ? _(opts->argh) : _("..."));
 }