From: Bruno Haible Date: Sat, 15 Sep 2018 20:54:24 +0000 (+0200) Subject: Add support for translation lookup with context in shell scripts. X-Git-Tag: v0.20~399 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e43fde63ea6fcdd88113ba903ffbc774d39e57f6;p=thirdparty%2Fgettext.git Add support for translation lookup with context in shell scripts. Reported by Markus Gothe in . * gettext-runtime/src/gettext.c (long_options): Add option '--context'. (main): Handle option -c/--context. (usage): Document option -c/--context. Split usage message. * gettext-runtime/src/ngettext.c (long_options): Add option '--context'. (main): Handle option -c/--context. (usage): Document option -c/--context. Split usage message. * gettext-runtime/src/gettext.sh.in (eval_pgettext, eval_npgettext): New functions. * gettext-tools/src/xgettext.h (struct arglist_parser): Add 'next_is_msgctxt' field. (arglist_parser_remember_msgctxt): New declaration. * gettext-tools/src/xgettext.c (arglist_parser_alloc, arglist_parser_clone): Update accordingly. (arglist_parser_remember_msgctxt): New function. * gettext-tools/src/x-sh.c (init_keywords): Recognize also eval_pgettext and eval_npgettext. (init_flag_table_sh): Set flags for eval_pgettext, eval_npgettext. (substring_of_word): New function. (read_command): Recognize and handle -c/--context argument of 'gettext' and 'ngettext'. * gettext-tools/tests/lang-sh: Add test of message lookup with context. * gettext-runtime/doc/rt-gettext.texi: Mention the --context option. * gettext-runtime/doc/rt-ngettext.texi: Likewise. * gettext-tools/doc/gettext.texi (sh, Preparing Shell Scripts, gettext.sh): Mention the new shell functions. (eval_pgettext Invocation, eval_npgettext Invocation): New subsubsections. * gettext-tools/doc/xgettext.texi: Mention the support for eval_pgettext, eval_npgettext. * NEWS: Mention the changes. --- diff --git a/NEWS b/NEWS index 15d309d8d..a6d777140 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,10 @@ - C++: xgettext now supports single-quotes in number tokens, as specified in C++14. + - Shell: + o The programs 'gettext', 'ngettext' now support a --context argument. + o gettext.sh contains new function eval_pgettext and eval_npgettext + for producing translations of messages with context. - Java: o xgettext now supports UTF-8 encoded .properties files (a new feature of Java 9). diff --git a/gettext-runtime/doc/rt-gettext.texi b/gettext-runtime/doc/rt-gettext.texi index 68dc3fe78..884041896 100644 --- a/gettext-runtime/doc/rt-gettext.texi +++ b/gettext-runtime/doc/rt-gettext.texi @@ -12,6 +12,13 @@ textual message. @noindent @strong{Arguments} @table @samp +@item -c @var{context} +@itemx --context=@var{context} +@opindex -c@r{, @code{gettext} option} +@opindex --context@r{, @code{gettext} option} +Specify the context for the messages to be translated. +See @ref{Contexts} for details. + @item -d @var{textdomain} @itemx --domain=@var{textdomain} @opindex -d@r{, @code{gettext} option} diff --git a/gettext-runtime/doc/rt-ngettext.texi b/gettext-runtime/doc/rt-ngettext.texi index 1b8c5a703..acb589c54 100644 --- a/gettext-runtime/doc/rt-ngettext.texi +++ b/gettext-runtime/doc/rt-ngettext.texi @@ -11,6 +11,13 @@ textual message whose grammatical form depends on a number. @noindent @strong{Arguments} @table @samp +@item -c @var{context} +@itemx --context=@var{context} +@opindex -c@r{, @code{ngettext} option} +@opindex --context@r{, @code{ngettext} option} +Specify the context for the messages to be translated. +See @ref{Contexts} for details. + @item -d @var{textdomain} @itemx --domain=@var{textdomain} @opindex -d@r{, @code{ngettext} option} diff --git a/gettext-runtime/src/gettext.c b/gettext-runtime/src/gettext.c index 32d6d4971..f14675f02 100644 --- a/gettext-runtime/src/gettext.c +++ b/gettext-runtime/src/gettext.c @@ -49,6 +49,7 @@ static bool do_expand; /* Long options. */ static const struct option long_options[] = { + { "context", required_argument, NULL, 'c' }, { "domain", required_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, { "shell-script", no_argument, NULL, 's' }, @@ -76,6 +77,7 @@ main (int argc, char *argv[]) bool do_version = false; const char *domain = getenv ("TEXTDOMAIN"); const char *domaindir = getenv ("TEXTDOMAINDIR"); + const char *context = NULL; add_newline = true; do_expand = false; @@ -95,12 +97,15 @@ main (int argc, char *argv[]) atexit (close_stdout); /* Parse command line options. */ - while ((optchar = getopt_long (argc, argv, "+d:eEhnsV", long_options, NULL)) + while ((optchar = getopt_long (argc, argv, "+c:d:eEhnsV", long_options, NULL)) != EOF) switch (optchar) { case '\0': /* Long option. */ break; + case 'c': + context = optarg; + break; case 'd': domain = optarg; break; @@ -186,7 +191,10 @@ There is NO WARRANTY, to the extent permitted by law.\n\ bindtextdomain (domain, domaindir); /* Write out the result. */ - fputs (dgettext (domain, msgid), stdout); + fputs ((context != NULL + ? dpgettext_expr (domain, context, msgid) + : dgettext (domain, msgid)), + stdout); } } else @@ -212,7 +220,10 @@ There is NO WARRANTY, to the extent permitted by law.\n\ msgid = expand_escape (msgid); /* Write out the result. */ - fputs (domain == NULL ? msgid : dgettext (domain, msgid), + fputs ((domain == NULL ? msgid : + context != NULL + ? dpgettext_expr (domain, context, msgid) + : dgettext (domain, msgid)), stdout); /* We separate the arguments by a single ' '. */ @@ -252,15 +263,26 @@ Display native language translation of a textual message.\n")); printf ("\n"); /* xgettext: no-wrap */ printf (_("\ - -d, --domain=TEXTDOMAIN retrieve translated messages from TEXTDOMAIN\n\ - -e enable expansion of some escape sequences\n\ - -E (ignored for compatibility)\n\ - -h, --help display this help and exit\n\ - -n suppress trailing newline\n\ - -V, --version display version information and exit\n\ + -d, --domain=TEXTDOMAIN retrieve translated messages from TEXTDOMAIN\n")); + printf (_("\ + -c, --context=CONTEXT specify context for MSGID\n")); + printf (_("\ + -e enable expansion of some escape sequences\n")); + printf (_("\ + -n suppress trailing newline\n")); + printf (_("\ + -E (ignored for compatibility)\n")); + printf (_("\ [TEXTDOMAIN] MSGID retrieve translated message corresponding\n\ to MSGID from TEXTDOMAIN\n")); printf ("\n"); + printf (_("\ +Informative output:\n")); + printf (_("\ + -h, --help display this help and exit\n")); + printf (_("\ + -V, --version display version information and exit\n")); + printf ("\n"); /* xgettext: no-wrap */ printf (_("\ If the TEXTDOMAIN parameter is not given, the domain is determined from the\n\ diff --git a/gettext-runtime/src/gettext.sh.in b/gettext-runtime/src/gettext.sh.in index 06dc04dc7..218e998c5 100644 --- a/gettext-runtime/src/gettext.sh.in +++ b/gettext-runtime/src/gettext.sh.in @@ -95,6 +95,20 @@ eval_ngettext () { ngettext "$1" "$2" "$3" | (export PATH `envsubst --variables "$1 $2"`; envsubst "$1 $2") } +# eval_pgettext MSGCTXT MSGID +# looks up the translation of MSGID in the context MSGCTXT and substitutes +# shell variables in the result. +eval_pgettext () { + gettext --context="$1" "$2" | (export PATH `envsubst --variables "$2"`; envsubst "$2") +} + +# eval_npgettext MSGCTXT MSGID MSGID-PLURAL COUNT +# looks up the translation of MSGID / MSGID-PLURAL for COUNT in the context +# MSGCTXT and substitutes shell variables in the result. +eval_npgettext () { + ngettext --context="$1" "$2" "$3" "$4" | (export PATH `envsubst --variables "$2 $3"`; envsubst "$2 $3") +} + # Note: This use of envsubst is much safer than using the shell built-in 'eval' # would be. # 1) The security problem with Chinese translations that happen to use a diff --git a/gettext-runtime/src/ngettext.c b/gettext-runtime/src/ngettext.c index ae3070999..59a0126b9 100644 --- a/gettext-runtime/src/ngettext.c +++ b/gettext-runtime/src/ngettext.c @@ -44,6 +44,7 @@ static int do_expand; /* Long options. */ static const struct option long_options[] = { + { "context", required_argument, NULL, 'c' }, { "domain", required_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, @@ -72,6 +73,7 @@ main (int argc, char *argv[]) bool do_version = false; const char *domain = getenv ("TEXTDOMAIN"); const char *domaindir = getenv ("TEXTDOMAINDIR"); + const char *context = NULL; do_expand = false; /* Set program name for message texts. */ @@ -90,12 +92,15 @@ main (int argc, char *argv[]) atexit (close_stdout); /* Parse command line options. */ - while ((optchar = getopt_long (argc, argv, "+d:eEhV", long_options, NULL)) + while ((optchar = getopt_long (argc, argv, "+c:d:eEhV", long_options, NULL)) != EOF) switch (optchar) { case '\0': /* Long option. */ break; + case 'c': + context = optarg; + break; case 'd': domain = optarg; break; @@ -192,7 +197,10 @@ There is NO WARRANTY, to the extent permitted by law.\n\ bindtextdomain (domain, domaindir); /* Write out the result. */ - fputs (dngettext (domain, msgid, msgid_plural, n), stdout); + fputs ((context != NULL + ? dnpgettext_expr (domain, context, msgid, msgid_plural, n) + : dngettext (domain, msgid, msgid_plural, n)), + stdout); } exit (EXIT_SUCCESS); @@ -220,14 +228,26 @@ form depends on a number.\n")); printf ("\n"); /* xgettext: no-wrap */ printf (_("\ - -d, --domain=TEXTDOMAIN retrieve translated message from TEXTDOMAIN\n\ - -e enable expansion of some escape sequences\n\ - -E (ignored for compatibility)\n\ - -h, --help display this help and exit\n\ - -V, --version display version information and exit\n\ - [TEXTDOMAIN] retrieve translated message from TEXTDOMAIN\n\ - MSGID MSGID-PLURAL translate MSGID (singular) / MSGID-PLURAL (plural)\n\ + -d, --domain=TEXTDOMAIN retrieve translated message from TEXTDOMAIN\n")); + printf (_("\ + -c, --context=CONTEXT specify context for MSGID\n")); + printf (_("\ + -e enable expansion of some escape sequences\n")); + printf (_("\ + -E (ignored for compatibility)\n")); + printf (_("\ + [TEXTDOMAIN] retrieve translated message from TEXTDOMAIN\n")); + printf (_("\ + MSGID MSGID-PLURAL translate MSGID (singular) / MSGID-PLURAL (plural)\n")); + printf (_("\ COUNT choose singular/plural form based on this value\n")); + printf ("\n"); + printf (_("\ +Informative output:\n")); + printf (_("\ + -h, --help display this help and exit\n")); + printf (_("\ + -V, --version display version information and exit\n")); printf ("\n"); /* xgettext: no-wrap */ printf (_("\ diff --git a/gettext-tools/doc/gettext.texi b/gettext-tools/doc/gettext.texi index ca8c638fb..fc8fa879f 100644 --- a/gettext-tools/doc/gettext.texi +++ b/gettext-tools/doc/gettext.texi @@ -450,6 +450,8 @@ sh - Shell Script * envsubst Invocation:: Invoking the @code{envsubst} program * eval_gettext Invocation:: Invoking the @code{eval_gettext} function * eval_ngettext Invocation:: Invoking the @code{eval_ngettext} function +* eval_pgettext Invocation:: Invoking the @code{eval_pgettext} function +* eval_npgettext Invocation:: Invoking the @code{eval_npgettext} function Perl @@ -9582,7 +9584,8 @@ bash, gettext-base @pindex gettext @pindex ngettext @code{gettext}, @code{ngettext} programs -@*@code{eval_gettext}, @code{eval_ngettext} shell functions +@*@code{eval_gettext}, @code{eval_ngettext}, @code{eval_pgettext}, +@code{eval_npgettext} shell functions @item textdomain @vindex TEXTDOMAIN@r{, environment variable} @@ -9624,6 +9627,8 @@ An example is available in the @file{examples} directory: @code{hello-sh}. * envsubst Invocation:: Invoking the @code{envsubst} program * eval_gettext Invocation:: Invoking the @code{eval_gettext} function * eval_ngettext Invocation:: Invoking the @code{eval_ngettext} function +* eval_pgettext Invocation:: Invoking the @code{eval_pgettext} function +* eval_npgettext Invocation:: Invoking the @code{eval_npgettext} function @end menu @node Preparing Shell Scripts, gettext.sh, sh, sh @@ -9644,8 +9649,10 @@ Insert the line near the top of the script. @code{gettext.sh} is a shell function library that provides the functions -@code{eval_gettext} (see @ref{eval_gettext Invocation}) and -@code{eval_ngettext} (see @ref{eval_ngettext Invocation}). +@code{eval_gettext} (see @ref{eval_gettext Invocation}), +@code{eval_ngettext} (see @ref{eval_ngettext Invocation}), +@code{eval_pgettext} (see @ref{eval_pgettext Invocation}), and +@code{eval_npgettext} (see @ref{eval_npgettext Invocation}). You have to ensure that @code{gettext.sh} can be found in the @code{PATH}. @item @@ -9759,6 +9766,12 @@ See @ref{eval_gettext Invocation}. @item eval_ngettext See @ref{eval_ngettext Invocation}. + +@item eval_pgettext +See @ref{eval_pgettext Invocation}. + +@item eval_npgettext +See @ref{eval_npgettext Invocation}. @end itemize @node gettext Invocation, ngettext Invocation, gettext.sh, sh @@ -9797,7 +9810,7 @@ This function outputs the native language translation of a textual message, performing dollar-substitution on the result. Note that only shell variables mentioned in @var{msgid} will be dollar-substituted in the result. -@node eval_ngettext Invocation, , eval_gettext Invocation, sh +@node eval_ngettext Invocation, eval_pgettext Invocation, eval_gettext Invocation, sh @subsubsection Invoking the @code{eval_ngettext} function @cindex @code{eval_ngettext} function, usage @@ -9811,6 +9824,35 @@ whose grammatical form depends on a number, performing dollar-substitution on the result. Note that only shell variables mentioned in @var{msgid} or @var{msgid-plural} will be dollar-substituted in the result. +@node eval_pgettext Invocation, eval_npgettext Invocation, eval_ngettext Invocation, sh +@subsubsection Invoking the @code{eval_pgettext} function + +@cindex @code{eval_pgettext} function, usage +@example +eval_pgettext @var{msgctxt} @var{msgid} +@end example + +@cindex lookup message translation with context +This function outputs the native language translation of a textual message +in the given context @var{msgctxt} (see @ref{Contexts}), performing +dollar-substitution on the result. Note that only shell variables mentioned +in @var{msgid} will be dollar-substituted in the result. + +@node eval_npgettext Invocation, , eval_pgettext Invocation, sh +@subsubsection Invoking the @code{eval_npgettext} function + +@cindex @code{eval_npgettext} function, usage +@example +eval_npgettext @var{msgctxt} @var{msgid} @var{msgid-plural} @var{count} +@end example + +@cindex lookup plural message translation with context +This function outputs the native language translation of a textual message +whose grammatical form depends on a number in the given context @var{msgctxt} +(see @ref{Contexts}), performing dollar-substitution on the result. Note +that only shell variables mentioned in @var{msgid} or @var{msgid-plural} +will be dollar-substituted in the result. + @node bash, Python, sh, List of Programming Languages @subsection bash - Bourne-Again Shell Script @cindex bash diff --git a/gettext-tools/doc/xgettext.texi b/gettext-tools/doc/xgettext.texi index dc67fe6c8..1072c7f1b 100644 --- a/gettext-tools/doc/xgettext.texi +++ b/gettext-tools/doc/xgettext.texi @@ -276,7 +276,8 @@ For Objective C: Like for C, and also @code{NSLocalizedString}, @code{_}, @item For Shell scripts: @code{gettext}, @code{ngettext:1,2}, @code{eval_gettext}, -@code{eval_ngettext:1,2}. +@code{eval_ngettext:1,2}, @code{eval_pgettext:1c,2}, +@code{eval_npgettext:1c,2,3}. @item For Python: @code{gettext}, @code{ugettext}, @code{dgettext:2}, diff --git a/gettext-tools/src/x-sh.c b/gettext-tools/src/x-sh.c index 76567c73e..599f40b71 100644 --- a/gettext-tools/src/x-sh.c +++ b/gettext-tools/src/x-sh.c @@ -1,5 +1,5 @@ /* xgettext sh backend. - Copyright (C) 2003, 2005-2009, 2015-2016 Free Software Foundation, Inc. + Copyright (C) 2003, 2005-2009, 2015-2016, 2018 Free Software Foundation, Inc. Written by Bruno Haible , 2003. This program is free software: you can redistribute it and/or modify @@ -112,8 +112,12 @@ init_keywords () xgettext.texi! */ x_sh_keyword ("gettext"); x_sh_keyword ("ngettext:1,2"); + /* Note: There is also special handling for 'gettext' and 'ngettext' + in read_command, below. */ x_sh_keyword ("eval_gettext"); x_sh_keyword ("eval_ngettext:1,2"); + x_sh_keyword ("eval_pgettext:1c,2"); + x_sh_keyword ("eval_npgettext:1c,2,3"); default_keywords = false; } } @@ -127,6 +131,9 @@ init_flag_table_sh () xgettext_record_flag ("eval_gettext:1:sh-format"); xgettext_record_flag ("eval_ngettext:1:sh-format"); xgettext_record_flag ("eval_ngettext:2:sh-format"); + xgettext_record_flag ("eval_pgettext:2:sh-format"); + xgettext_record_flag ("eval_npgettext:2:sh-format"); + xgettext_record_flag ("eval_npgettext:3:sh-format"); } @@ -468,6 +475,24 @@ string_of_word (const struct word *wp) return str; } +/* Convert a t_string token to a char*, ignoring the first OFFSET bytes. */ +static char * +substring_of_word (const struct word *wp, size_t offset) +{ + char *str; + int n; + + if (!(wp->type == t_string)) + abort (); + n = wp->token->charcount; + if (!(offset <= n)) + abort (); + str = XNMALLOC (n - offset + 1, char); + memcpy (str, wp->token->chars + offset, n - offset); + str[n - offset] = '\0'; + return str; +} + /* Whitespace recognition. */ @@ -1250,6 +1275,8 @@ read_command (int looking_for, flag_context_ty outer_context) } else { + bool matters_for_argparser = true; + if (argparser == NULL) { /* This is the function position. */ @@ -1282,24 +1309,67 @@ read_command (int looking_for, flag_context_ty outer_context) { /* These are the argument positions. */ if (inner.type == t_string) - arglist_parser_remember (argparser, arg, - string_of_word (&inner), - inner_context, - logical_file_name, - inner.line_number_at_start, - savable_comment); - - if (arglist_parser_decidedp (argparser, arg)) { - /* Stop looking for arguments of the last function_name. */ - /* FIXME: What about context_iter? */ - arglist_parser_done (argparser, arg); - shapes = NULL; - argparser = NULL; + bool accepts_context = + ((argparser->keyword_len == 7 + && memcmp (argparser->keyword, "gettext", 7) == 0) + || (argparser->keyword_len == 8 + && memcmp (argparser->keyword, "ngettext", 8) == 0)); + if (accepts_context && argparser->next_is_msgctxt) + { + argparser->next_is_msgctxt = false; + arglist_parser_remember_msgctxt (argparser, + string_of_word (&inner), + inner_context, + logical_file_name, + inner.line_number_at_start); + matters_for_argparser = false; + } + else if (accepts_context + && ((inner.token->charcount == 2 + && memcmp (inner.token->chars, "-c", 2) == 0) + || (inner.token->charcount == 9 + && memcmp (inner.token->chars, "--context", 9) == 0))) + { + argparser->next_is_msgctxt = true; + matters_for_argparser = false; + } + else if (accepts_context + && (inner.token->charcount >= 10 + && memcmp (inner.token->chars, "--context=", 10) == 0)) + { + argparser->next_is_msgctxt = false; + arglist_parser_remember_msgctxt (argparser, + substring_of_word (&inner, 10), + inner_context, + logical_file_name, + inner.line_number_at_start); + matters_for_argparser = false; + } + else + { + arglist_parser_remember (argparser, arg, + string_of_word (&inner), + inner_context, + logical_file_name, + inner.line_number_at_start, + savable_comment); + } } + + if (matters_for_argparser) + if (arglist_parser_decidedp (argparser, arg)) + { + /* Stop looking for arguments of the last function_name. */ + /* FIXME: What about context_iter? */ + arglist_parser_done (argparser, arg); + shapes = NULL; + argparser = NULL; + } } - arg++; + if (matters_for_argparser) + arg++; } free_word (&inner); diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c index 2943f759e..968472dac 100644 --- a/gettext-tools/src/xgettext.c +++ b/gettext-tools/src/xgettext.c @@ -2961,6 +2961,7 @@ arglist_parser_alloc (message_list_ty *mlp, const struct callshapes *shapes) ap->mlp = mlp; ap->keyword = NULL; ap->keyword_len = 0; + ap->next_is_msgctxt = false; ap->nalternatives = 0; return ap; @@ -2977,6 +2978,7 @@ arglist_parser_alloc (message_list_ty *mlp, const struct callshapes *shapes) ap->mlp = mlp; ap->keyword = shapes->keyword; ap->keyword_len = shapes->keyword_len; + ap->next_is_msgctxt = false; ap->nalternatives = shapes->nshapes; for (i = 0; i < shapes->nshapes; i++) { @@ -3023,6 +3025,7 @@ arglist_parser_clone (struct arglist_parser *ap) copy->mlp = ap->mlp; copy->keyword = ap->keyword; copy->keyword_len = ap->keyword_len; + copy->next_is_msgctxt = ap->next_is_msgctxt; copy->nalternatives = ap->nalternatives; for (i = 0; i < ap->nalternatives; i++) { @@ -3116,6 +3119,7 @@ arglist_parser_remember_literal (struct arglist_parser *ap, free (string); } + void arglist_parser_remember (struct arglist_parser *ap, int argnum, char *string, @@ -3128,6 +3132,36 @@ arglist_parser_remember (struct arglist_parser *ap, comment, LET_NONE); } + +void +arglist_parser_remember_msgctxt (struct arglist_parser *ap, + char *string, + flag_context_ty context, + char *file_name, size_t line_number) +{ + bool stored_string = false; + size_t nalternatives = ap->nalternatives; + size_t i; + + for (i = 0; i < nalternatives; i++) + { + struct partial_call *cp = &ap->alternative[i]; + + cp->msgctxt = string; + cp->msgctxt_escape = LET_NONE; + cp->msgctxt_pos.file_name = file_name; + cp->msgctxt_pos.line_number = line_number; + stored_string = true; + /* Mark msgctxt as done. */ + cp->argnumc = 0; + } + /* Note: There is a memory leak here: When string was stored but is later + not used by arglist_parser_done, we don't free it. */ + if (!stored_string) + free (string); +} + + bool arglist_parser_decidedp (struct arglist_parser *ap, int argnum) { diff --git a/gettext-tools/src/xgettext.h b/gettext-tools/src/xgettext.h index 1b6b20309..926881e37 100644 --- a/gettext-tools/src/xgettext.h +++ b/gettext-tools/src/xgettext.h @@ -1,6 +1,5 @@ /* xgettext common functions. - Copyright (C) 2001-2003, 2005-2006, 2008-2009, 2011, 2015-2016 Free Software - Foundation, Inc. + Copyright (C) 2001-2003, 2005-2006, 2008-2009, 2011, 2015-2016, 2018 Free Software Foundation, Inc. Written by Peter Miller and Bruno Haible , 2001. @@ -327,6 +326,7 @@ struct arglist_parser message_list_ty *mlp; /* list where the message shall be added */ const char *keyword; /* the keyword, not NUL terminated */ size_t keyword_len; /* the keyword's length */ + bool next_is_msgctxt; /* true if the next argument is the msgctxt */ size_t nalternatives; /* number of partial_call alternatives */ struct partial_call alternative[1]; /* partial_call alternatives */ }; @@ -361,6 +361,14 @@ extern void arglist_parser_remember_literal (struct arglist_parser *ap, char *file_name, size_t line_number, refcounted_string_list_ty *comment, enum literalstring_escape_type type); +/* Adds a string argument as msgctxt to an arglist_parser, without incrementing + the current argument number. + STRING must be malloc()ed string; its ownership is passed to the callee. + FILE_NAME must be allocated with indefinite extent. */ +extern void arglist_parser_remember_msgctxt (struct arglist_parser *ap, + char *string, + flag_context_ty context, + char *file_name, size_t line_number); /* Tests whether an arglist_parser has is not waiting for more arguments after argument ARGNUM. */ extern bool arglist_parser_decidedp (struct arglist_parser *ap, int argnum); diff --git a/gettext-tools/tests/lang-sh b/gettext-tools/tests/lang-sh index 5f0173264..8eed6ed22 100755 --- a/gettext-tools/tests/lang-sh +++ b/gettext-tools/tests/lang-sh @@ -27,6 +27,14 @@ export TEXTDOMAINDIR $echo "`gettext \"'Your command, please?', asked the waiter.\"`" $echo "`eval_ngettext \"a piece of cake\" \"\\$n pieces of cake\" $n`" + +$echo "`gettext -c File \"Open\"`" + +$echo "`gettext --context File \"Close\"`" + +$echo "`gettext --context=File \"Save\"`" + +$echo "`eval_npgettext File \"\\$n file open\" \"\\$n files open\" $n`" EOF : ${XGETTEXT=xgettext} @@ -42,6 +50,25 @@ msgid "a piece of cake" msgid_plural "$n pieces of cake" msgstr[0] "" msgstr[1] "" + +msgctxt "File" +msgid "Open" +msgstr "" + +msgctxt "File" +msgid "Close" +msgstr "" + +msgctxt "File" +msgid "Save" +msgstr "" + +#, sh-format +msgctxt "File" +msgid "$n file open" +msgid_plural "$n files open" +msgstr[0] "" +msgstr[1] "" EOF : ${DIFF=diff} @@ -62,6 +89,25 @@ msgid "a piece of cake" msgid_plural "$n pieces of cake" msgstr[0] "un morceau de gateau" msgstr[1] "$n morceaux de gateau" + +msgctxt "File" +msgid "Open" +msgstr "Ouvrir" + +msgctxt "File" +msgid "Close" +msgstr "Fermer" + +msgctxt "File" +msgid "Save" +msgstr "Sauvegarder" + +#, sh-format +msgctxt "File" +msgid "$n file open" +msgid_plural "$n files open" +msgstr[0] "$n fichier ouvert" +msgstr[1] "$n fichiers ouverts" EOF : ${MSGMERGE=msgmerge} @@ -109,10 +155,18 @@ fi cat <<\EOF > prog.ok «Votre commande, s'il vous plait», dit le garçon. 2 morceaux de gateau +Ouvrir +Fermer +Sauvegarder +2 fichiers ouverts EOF cat <<\EOF > prog.oku «Votre commande, s'il vous plait», dit le garçon. 2 morceaux de gateau +Ouvrir +Fermer +Sauvegarder +2 fichiers ouverts EOF : ${LOCALE_FR=fr_FR}