From: Bruno Haible Date: Wed, 24 Oct 2018 23:09:38 +0000 (+0200) Subject: msgmerge: New option --for-msgfmt. X-Git-Tag: v0.20~282 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bd9c80d590b0eebdf3d67aa474d88758cabca20d;p=thirdparty%2Fgettext.git msgmerge: New option --for-msgfmt. * gettext-tools/src/msgmerge.c (for_msgfmt): New variable. (long_options): Add option --for-msgfmt. (main): Handle option --for-msgfmt. (usage): Document option --for-msgfmt. (match_domain): When --for-msgfmt is given, omit untranslated and fuzzy messages from the result. (merge): When --for-msgfmt is given, don't add obsolete messages to the result. * gettext-tools/tests/msgmerge-26: New file. * gettext-tools/tests/Makefile.am (TESTS): Add it. * gettext-tools/doc/msgmerge.texi: Mention the option --for-msgfmt. * NEWS: Mention the change. --- diff --git a/NEWS b/NEWS index 9de1cbd49..05c0ed241 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,12 @@ * Improvements for translators: - update-po target in Makefile.in.in now uses msgmerge --previous. +* Improvements for maintainers: + - msgmerge now has an option --for-msgfmt, that produces a PO file meant + for use by msgfmt only. This option saves processing time, in particular + by omitting fuzzy matching that is not useful in this situation. + - The .pot file in a 'po' directory is now erased by "make maintainer-clean". + * Programming languages support: - C, C++: xgettext now supports 'p'/'P' exponent markers in number tokens, as @@ -43,9 +49,6 @@ compliant. There is no conflict any more between these replacements and other possible replacements provided by gnulib or mingw. -* Improvements for maintainers: - - The .pot file in a 'po' directory is now erased by "make maintainer-clean". - Version 0.19.8 - June 2016 * Support for reproducible builds: diff --git a/gettext-tools/doc/msgmerge.texi b/gettext-tools/doc/msgmerge.texi index ad76f0e7d..e74541f7b 100644 --- a/gettext-tools/doc/msgmerge.texi +++ b/gettext-tools/doc/msgmerge.texi @@ -120,6 +120,14 @@ The backup suffix is @samp{~}, unless set with @code{--suffix} or the @opindex --multi-domain@r{, @code{msgmerge} option} Apply @var{ref}.pot to each of the domains in @var{def}.po. +@item --for-msgfmt +@opindex --for-msgfmt@r{, @code{msgmerge} option} +Produce a PO file meant for @code{msgfmt} only, not for a translator. +This option omits untranslated messages, fuzzy messages (except the header +entry), and obsolete messages from the output. Also, it omits translator +comments and @samp{#: @var{filename}:@var{line}} lines from the output. +In particular, this option implies @samp{--no-fuzzy-matching}. + @item -N @itemx --no-fuzzy-matching @opindex -N@r{, @code{msgmerge} option} diff --git a/gettext-tools/src/msgmerge.c b/gettext-tools/src/msgmerge.c index 90c2b69a1..60b51221a 100644 --- a/gettext-tools/src/msgmerge.c +++ b/gettext-tools/src/msgmerge.c @@ -85,6 +85,14 @@ static int force_po; /* Apply the .pot file to each of the domains in the PO file. */ static bool multi_domain_mode = false; +/* Produce output for msgfmt, not for a translator. + msgfmt ignores + - untranslated messages, + - fuzzy messages, except the header entry, + - obsolete messages. + Therefore output for msgfmt does not need to include such messages. */ +static bool for_msgfmt = false; + /* Determines whether to use fuzzy matching. */ static bool use_fuzzy_matching = true; @@ -114,6 +122,7 @@ static const struct option long_options[] = { "compendium", required_argument, NULL, 'C' }, { "directory", required_argument, NULL, 'D' }, { "escape", no_argument, NULL, 'E' }, + { "for-msgfmt", no_argument, NULL, CHAR_MAX + 12 }, { "force-po", no_argument, &force_po, 1 }, { "help", no_argument, NULL, 'h' }, { "indent", no_argument, NULL, 'i' }, @@ -344,6 +353,10 @@ main (int argc, char **argv) message_print_style_filepos (filepos_comment_none); break; + case CHAR_MAX + 12: /* --for-msgfmt */ + for_msgfmt = true; + break; + default: usage (EXIT_FAILURE); break; @@ -388,6 +401,11 @@ There is NO WARRANTY, to the extent permitted by law.\n\ error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), "--update", "--output-file"); } + if (for_msgfmt) + { + error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), + "--update", "--for-msgfmt"); + } if (color != NULL) { error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), @@ -426,6 +444,22 @@ There is NO WARRANTY, to the extent permitted by law.\n\ if (update_mode && input_syntax == &input_format_stringtable) output_syntax = &output_format_stringtable; + if (for_msgfmt) + { + /* With --for-msgfmt, no fuzzy matching. */ + use_fuzzy_matching = false; + + /* With --for-msgfmt, merging is fast, therefore no need for a progress + indicator. */ + quiet = true; + + /* With --for-msgfmt, no need for comments. */ + message_print_style_comment (false); + + /* With --for-msgfmt, no need for source location lines. */ + message_print_style_filepos (filepos_comment_none); + } + /* Merge the two files. */ result = merge (argv[optind], argv[optind + 1], input_syntax, &def); @@ -567,6 +601,9 @@ Operation modifiers:\n")); printf (_("\ -m, --multi-domain apply ref.pot to each of the domains in def.po\n")); printf (_("\ + --for-msgfmt produce output for '%s', not for a translator\n"), + "msgfmt"); + printf (_("\ -N, --no-fuzzy-matching do not use fuzzy matching\n")); printf (_("\ --previous keep previous msgids of translated messages\n")); @@ -1500,11 +1537,19 @@ match_domain (const char *fn1, const char *fn2, message_ty *mp = message_merge (defmsg, refmsg, false, &distribution); - message_list_append (resultmlp, mp); + /* When producing output for msgfmt, omit messages that are + untranslated or fuzzy (except the header entry). */ + if (!(for_msgfmt + && (mp->msgstr[0] == '\0' /* untranslated? */ + || (mp->is_fuzzy && !is_header (mp))))) /* fuzzy? */ + { + message_list_append (resultmlp, mp); + + /* Remember that this message has been used, when we scan + later to see if anything was omitted. */ + defmsg->used = 1; + } - /* Remember that this message has been used, when we scan - later to see if anything was omitted. */ - defmsg->used = 1; stats->merged++; } else if (!is_header (refmsg)) @@ -1538,6 +1583,7 @@ this message is used but not defined...")); /* Remember that this message has been used, when we scan later to see if anything was omitted. */ defmsg->used = 1; + stats->fuzzied++; if (!quiet && verbosity_level <= 1) /* Always print a dot if we handled a fuzzy match. */ @@ -1556,27 +1602,31 @@ this message is used but not defined in %s"), fn1); mp = message_copy (refmsg); - if (mp->msgid_plural != NULL) + /* Test if mp is untranslated. (It most likely is.) */ + is_untranslated = true; + for (p = mp->msgstr, pend = p + mp->msgstr_len; p < pend; p++) + if (*p != '\0') + { + is_untranslated = false; + break; + } + + if (mp->msgid_plural != NULL && is_untranslated) { - /* Test if mp is untranslated. (It most likely is.) */ - is_untranslated = true; - for (p = mp->msgstr, pend = p + mp->msgstr_len; p < pend; p++) - if (*p != '\0') - { - is_untranslated = false; - break; - } - if (is_untranslated) - { - /* Change mp->msgstr_len consecutive empty strings into - nplurals consecutive empty strings. */ - if (nplurals > mp->msgstr_len) - mp->msgstr = untranslated_plural_msgstr; - mp->msgstr_len = nplurals; - } + /* Change mp->msgstr_len consecutive empty strings into + nplurals consecutive empty strings. */ + if (nplurals > mp->msgstr_len) + mp->msgstr = untranslated_plural_msgstr; + mp->msgstr_len = nplurals; + } + + /* When producing output for msgfmt, omit messages that are + untranslated or fuzzy (except the header entry). */ + if (!(for_msgfmt && (is_untranslated || mp->is_fuzzy))) + { + message_list_append (resultmlp, mp); } - message_list_append (resultmlp, mp); stats->missing++; } } @@ -1998,48 +2048,51 @@ merge (const char *fn1, const char *fn2, catalog_input_format_ty input_syntax, definitions_destroy (&definitions); - /* Look for messages in the definition file, which are not present - in the reference file, indicating messages which defined but not - used in the program. Don't scan the compendium(s). */ - for (k = 0; k < def->nitems; ++k) + if (!for_msgfmt) { - const char *domain = def->item[k]->domain; - message_list_ty *defmlp = def->item[k]->messages; - - for (j = 0; j < defmlp->nitems; j++) + /* Look for messages in the definition file, which are not present + in the reference file, indicating messages which defined but not + used in the program. Don't scan the compendium(s). */ + for (k = 0; k < def->nitems; ++k) { - message_ty *defmsg = defmlp->item[j]; + const char *domain = def->item[k]->domain; + message_list_ty *defmlp = def->item[k]->messages; - if (!defmsg->used) + for (j = 0; j < defmlp->nitems; j++) { - /* Remember the old translation although it is not used anymore. - But we mark it as obsolete. */ - message_ty *mp; + message_ty *defmsg = defmlp->item[j]; - mp = message_copy (defmsg); - /* Clear the extracted comments. */ - if (mp->comment_dot != NULL) - { - string_list_free (mp->comment_dot); - mp->comment_dot = NULL; - } - /* Clear the file position comments. */ - if (mp->filepos != NULL) + if (!defmsg->used) { - size_t i; + /* Remember the old translation although it is not used anymore. + But we mark it as obsolete. */ + message_ty *mp; - for (i = 0; i < mp->filepos_count; i++) - free ((char *) mp->filepos[i].file_name); - mp->filepos_count = 0; - free (mp->filepos); - mp->filepos = NULL; - } - /* Mark as obsolete. */ - mp->obsolete = true; + mp = message_copy (defmsg); + /* Clear the extracted comments. */ + if (mp->comment_dot != NULL) + { + string_list_free (mp->comment_dot); + mp->comment_dot = NULL; + } + /* Clear the file position comments. */ + if (mp->filepos != NULL) + { + size_t i; - message_list_append (msgdomain_list_sublist (result, domain, true), - mp); - stats.obsolete++; + for (i = 0; i < mp->filepos_count; i++) + free ((char *) mp->filepos[i].file_name); + mp->filepos_count = 0; + free (mp->filepos); + mp->filepos = NULL; + } + /* Mark as obsolete. */ + mp->obsolete = true; + + message_list_append (msgdomain_list_sublist (result, domain, true), + mp); + stats.obsolete++; + } } } } diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am index 5a59e9979..e8a4a8207 100644 --- a/gettext-tools/tests/Makefile.am +++ b/gettext-tools/tests/Makefile.am @@ -60,7 +60,7 @@ TESTS = gettext-1 gettext-2 \ msgmerge-7 msgmerge-8 msgmerge-9 msgmerge-10 msgmerge-11 msgmerge-12 \ msgmerge-13 msgmerge-14 msgmerge-15 msgmerge-16 msgmerge-17 \ msgmerge-18 msgmerge-19 msgmerge-20 msgmerge-21 msgmerge-22 \ - msgmerge-23 msgmerge-24 msgmerge-25 \ + msgmerge-23 msgmerge-24 msgmerge-25 msgmerge-26 \ msgmerge-compendium-1 msgmerge-compendium-2 msgmerge-compendium-3 \ msgmerge-compendium-4 msgmerge-compendium-5 msgmerge-compendium-6 \ msgmerge-properties-1 msgmerge-properties-2 \ diff --git a/gettext-tools/tests/msgmerge-26 b/gettext-tools/tests/msgmerge-26 new file mode 100755 index 000000000..cd3862e33 --- /dev/null +++ b/gettext-tools/tests/msgmerge-26 @@ -0,0 +1,79 @@ +#! /bin/sh +. "${srcdir=.}/init.sh"; path_prepend_ . ../src + +# Test --for-msgfmt option. + +cat < mm-test26.in1 +#: fruits.c:14 +msgid "cherry" +msgstr "cerise" + +#: fruits.c:17 +msgid "pear" +msgstr "poire" + +#: fruits.c:19 +msgid "orange" +msgstr "" + +#, fuzzy +#: fruits.c:20 +msgid "apple" +msgstr "pommes" +EOF + +cat < mm-test26.in2 +# Fuzzy already in the PO file. +#: fruits.c:10 +msgid "apple" +msgstr "" + +# Fuzzy match to fuzzy already in the PO file. +#: fruits.c:11 +msgid "apples" +msgstr "" + +# Translated. +#: fruits.c:16 +msgid "pear" +msgstr "" + +# Fuzzy match. +#: fruits.c:17 +msgid "pears" +msgstr "" + +# Untranslated, in the PO file. +#: fruits.c:18 +msgid "orange" +msgstr "" + +# Untranslated, not in the PO file. +#: fruits.c:20 +msgid "banana" +msgstr "" + +# Translated already in the POT file. +#: fruits.c:25 +msgid "papaya" +msgstr "Papaya" +EOF + +: ${MSGMERGE=msgmerge} +${MSGMERGE} --for-msgfmt -o mm-test26.tmp mm-test26.in1 mm-test26.in2 \ + || Exit 1 +LC_ALL=C tr -d '\r' < mm-test26.tmp > mm-test26.out || Exit 1 + +cat << EOF > mm-test26.ok +msgid "pear" +msgstr "poire" + +msgid "papaya" +msgstr "Papaya" +EOF + +: ${DIFF=diff} +${DIFF} mm-test26.ok mm-test26.out +result=$? + +exit $result