From: Bruno Haible Date: Sun, 6 Oct 2024 07:43:43 +0000 (+0200) Subject: msgfmt: New option --replace-text. X-Git-Tag: v0.23~82 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7d975b67084a329a68484d23e51819b1501f6d7f;p=thirdparty%2Fgettext.git msgfmt: New option --replace-text. Reported by Asterix at . * gettext-tools/src/its.h (its_merge_context_merge): Add parameter replace_text. * gettext-tools/src/its.c (its_merge_context_merge_node): Add parameter replace_text. (its_merge_context_merge): Likewise. * gettext-tools/src/write-xml.h (msgdomain_write_xml, msgdomain_write_xml_bulk): Add parameter replace_text. * gettext-tools/src/write-xml.c (msgdomain_write_xml_bulk): Add parameter replace_text. (msgdomain_write_xml): Likewise. * gettext-tools/src/msgfmt.c (xml_replace_text): New variable. (long_options): Add --replace-text. (main): Handle --replace-text. (usage): Document option --replace-text. * gettext-tools/tests/msgfmt-xml-4: New file, based on gettext-tools/tests/msgfmt-xml-1. * gettext-tools/tests/Makefile.am (TESTS): Add it. * gettext-tools/doc/msgfmt.texi: Document option --replace-text. * NEWS: Mention the change. --- diff --git a/NEWS b/NEWS index 4421854b5..46e57bee8 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -Version 0.23 - September 2024 +Version 0.23 - October 2024 * Programming languages support: - XML: @@ -14,6 +14,8 @@ Version 0.23 - September 2024 o XML schemas for .its and .loc files are now provided. o The value of the xml:lang attribute, inserted by msgfmt, now conforms to W3C standards. + o 'msgfmt --xml' accept an option --replace-text, that causes the output + to be a mono-lingual XML file instead of a multi-lingual XML file. - Python: o xgettext now assumes source code for Python 3 rather than Python 2. This affects the interpretation of escape sequences in string literals. diff --git a/gettext-tools/doc/msgfmt.texi b/gettext-tools/doc/msgfmt.texi index aeb204f10..9485c40fc 100644 --- a/gettext-tools/doc/msgfmt.texi +++ b/gettext-tools/doc/msgfmt.texi @@ -176,7 +176,7 @@ Specify the base directory of @file{.msg} message catalogs. The @samp{-l} and @samp{-d} options are mandatory. The @file{.msg} file is written in the specified directory. -@subsection Desktop Entry mode operations +@subsection Desktop Entry mode options @table @samp @item --template=@var{template} @@ -227,7 +227,7 @@ variable. For either operation modes, the @samp{-o} and @samp{--template} options are mandatory. -@subsection XML mode operations +@subsection XML mode options @table @samp @item --template=@var{template} @@ -252,6 +252,12 @@ or a combined language and country specification of the form @var{ll_CC}. @opindex -d@r{, @code{msgfmt} option} Specify the base directory of @file{.po} message catalogs. +@item --replace-text +@opindex --replace-text@r{, @code{msgfmt} option} +Output XML with translated text replacing the original text, +not augmenting the original text. +With this option, @code{msgfmt} produces a mono-lingual XML file. +Without this option, it produces a multi-lingual XML file. @end table To generate an XML file for a single locale, you can use it as follows. diff --git a/gettext-tools/src/its.c b/gettext-tools/src/its.c index 98521c5b2..0aabb6e9a 100644 --- a/gettext-tools/src/its.c +++ b/gettext-tools/src/its.c @@ -2079,7 +2079,8 @@ static void its_merge_context_merge_node (struct its_merge_context_ty *context, xmlNode *node, const char *language, - message_list_ty *mlp) + message_list_ty *mlp, + bool replace_text) { if (node->type == XML_ELEMENT_NODE) { @@ -2147,9 +2148,19 @@ its_merge_context_merge_node (struct its_merge_context_ty *context, xmlNode *translated; char language_bcp47[BCP47_MAX]; - /* Create a new element node, of the same name, with the same - attributes. */ - translated = _its_copy_node_with_attributes (node); + if (replace_text) + { + /* Reuse the node. But first, clear its text content and all + its children nodes (except the attributes). */ + xmlNodeSetContent (node, NULL); + translated = node; + } + else + { + /* Create a new element node, of the same name, with the same + attributes. */ + translated = _its_copy_node_with_attributes (node); + } /* Set the xml:lang attribute. @@ -2202,7 +2213,8 @@ its_merge_context_merge_node (struct its_merge_context_ty *context, free (middle_ground); } - xmlAddNextSibling (node, translated); + if (!replace_text) + xmlAddNextSibling (node, translated); } } free (msgctxt); @@ -2213,14 +2225,16 @@ its_merge_context_merge_node (struct its_merge_context_ty *context, void its_merge_context_merge (its_merge_context_ty *context, const char *language, - message_list_ty *mlp) + message_list_ty *mlp, + bool replace_text) { size_t i; for (i = 0; i < context->nodes.nitems; i++) its_merge_context_merge_node (context, context->nodes.items[i], language, - mlp); + mlp, + replace_text); } struct its_merge_context_ty * diff --git a/gettext-tools/src/its.h b/gettext-tools/src/its.h index 9fe03e1dd..f5221ef49 100644 --- a/gettext-tools/src/its.h +++ b/gettext-tools/src/its.h @@ -84,7 +84,8 @@ extern its_merge_context_ty * extern void its_merge_context_free (its_merge_context_ty *context); extern void its_merge_context_merge (its_merge_context_ty *context, const char *language, - message_list_ty *mlp); + message_list_ty *mlp, + bool replace_text); extern void its_merge_context_write (its_merge_context_ty *context, FILE *fp); diff --git a/gettext-tools/src/msgfmt.c b/gettext-tools/src/msgfmt.c index 0ea1fde4a..b26f5c080 100644 --- a/gettext-tools/src/msgfmt.c +++ b/gettext-tools/src/msgfmt.c @@ -120,6 +120,7 @@ static bool desktop_default_keywords = true; /* XML mode output file specification. */ static bool xml_mode; +static bool xml_replace_text; static const char *xml_locale_name; static const char *xml_template_name; static const char *xml_base_directory; @@ -204,6 +205,7 @@ static const struct option long_options[] = { "output-file", required_argument, NULL, 'o' }, { "properties-input", no_argument, NULL, 'P' }, { "qt", no_argument, NULL, CHAR_MAX + 9 }, + { "replace-text", no_argument, NULL, CHAR_MAX + 19 }, { "resource", required_argument, NULL, 'r' }, { "source", no_argument, NULL, CHAR_MAX + 14 }, { "statistics", no_argument, &do_statistics, 1 }, @@ -434,6 +436,9 @@ main (int argc, char *argv[]) case CHAR_MAX + 18: /* --no-redundancy */ no_redundancy = true; break; + case CHAR_MAX + 19: /* --replace-text */ + xml_replace_text = true; + break; default: usage (EXIT_FAILURE); break; @@ -508,6 +513,12 @@ There is NO WARRANTY, to the extent permitted by law.\n\ first_option, second_option); } } + if (!xml_mode && xml_replace_text) + { + error (EXIT_SUCCESS, 0, _("%s is only valid with %s"), + "--replace-text", "--xml"); + usage (EXIT_FAILURE); + } if (java_mode) { if (output_file_name != NULL) @@ -611,6 +622,10 @@ There is NO WARRANTY, to the extent permitted by law.\n\ "--xml"); usage (EXIT_FAILURE); } + if (xml_replace_text && xml_base_directory != NULL) + error (EXIT_FAILURE, 0, + _("%s and %s are mutually exclusive in %s"), + "--replace-text", "-d", "--xml"); if (xml_base_directory != NULL && xml_locale_name != NULL) error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive in %s"), @@ -850,6 +865,7 @@ There is NO WARRANTY, to the extent permitted by law.\n\ xml_locale_name, xml_template_name, xml_its_rules, + xml_replace_text, domain->file_name)) exit_status = EXIT_FAILURE; } @@ -1024,6 +1040,9 @@ XML mode options:\n")); printf (_("\ -d DIRECTORY base directory of .po files\n")); printf (_("\ + --replace-text output XML with translated text replacing the\n\ + original text, not augmenting the original text\n")); + printf (_("\ The -l, -o, and --template options are mandatory. If -D is specified, input\n\ files are read from the directory instead of the command line arguments.\n")); printf ("\n"); @@ -1694,6 +1713,7 @@ msgfmt_xml_bulk (const char *directory, status = msgdomain_write_xml_bulk (&operands, template_file_name, its_rules, + false, file_name); msgfmt_operand_list_destroy (&operands); diff --git a/gettext-tools/src/write-xml.c b/gettext-tools/src/write-xml.c index 6c94d7cad..948594123 100644 --- a/gettext-tools/src/write-xml.c +++ b/gettext-tools/src/write-xml.c @@ -44,6 +44,7 @@ int msgdomain_write_xml_bulk (msgfmt_operand_list_ty *operands, const char *template_file_name, its_rule_list_ty *its_rules, + bool replace_text, const char *file_name) { its_merge_context_ty *context; @@ -67,7 +68,8 @@ msgdomain_write_xml_bulk (msgfmt_operand_list_ty *operands, for (i = 0; i < operands->nitems; i++) its_merge_context_merge (context, operands->items[i].language, - operands->items[i].mlp); + operands->items[i].mlp, + replace_text); its_merge_context_write (context, fp); its_merge_context_free (context); @@ -88,6 +90,7 @@ msgdomain_write_xml (message_list_ty *mlp, const char *locale_name, const char *template_file_name, its_rule_list_ty *its_rules, + bool replace_text, const char *file_name) { msgfmt_operand_ty operand; @@ -110,5 +113,6 @@ msgdomain_write_xml (message_list_ty *mlp, return msgdomain_write_xml_bulk (&operands, template_file_name, its_rules, + replace_text, file_name); } diff --git a/gettext-tools/src/write-xml.h b/gettext-tools/src/write-xml.h index 5b80ac4b7..5f9343642 100644 --- a/gettext-tools/src/write-xml.h +++ b/gettext-tools/src/write-xml.h @@ -1,5 +1,5 @@ /* Writing XML files. - Copyright (C) 2024 Free Software Foundation, Inc. + Copyright (C) 2015-2024 Free Software Foundation, Inc. This file was written by Daiki Ueno . This program is free software: you can redistribute it and/or modify @@ -35,12 +35,14 @@ extern int const char *locale_name, const char *template_file_name, its_rule_list_ty *its_rules, + bool replace_text, const char *file_name); extern int msgdomain_write_xml_bulk (msgfmt_operand_list_ty *operands, const char *template_file_name, its_rule_list_ty *its_rules, + bool replace_text, const char *file_name); #ifdef __cplusplus diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am index 9c7b3276e..cad3a3d77 100644 --- a/gettext-tools/tests/Makefile.am +++ b/gettext-tools/tests/Makefile.am @@ -57,7 +57,7 @@ TESTS = gettext-1 gettext-2 \ msgfmt-tcl-1 msgfmt-tcl-2 \ msgfmt-qt-1 msgfmt-qt-2 \ msgfmt-desktop-1 msgfmt-desktop-2 msgfmt-desktop-3 \ - msgfmt-xml-1 msgfmt-xml-2 msgfmt-xml-3 \ + msgfmt-xml-1 msgfmt-xml-2 msgfmt-xml-3 msgfmt-xml-4 \ msggrep-1 msggrep-2 msggrep-3 msggrep-4 msggrep-5 msggrep-6 msggrep-7 \ msggrep-8 msggrep-9 msggrep-10 msggrep-11 \ msginit-1 msginit-2 msginit-3 msginit-4 \ diff --git a/gettext-tools/tests/msgfmt-xml-4 b/gettext-tools/tests/msgfmt-xml-4 new file mode 100755 index 000000000..b83a8937a --- /dev/null +++ b/gettext-tools/tests/msgfmt-xml-4 @@ -0,0 +1,144 @@ +#! /bin/sh +. "${srcdir=.}/init.sh"; path_prepend_ . ../src + +# Test msgfmt --xml: --replace-text option + +cat <<\EOF > mf.appdata.xml + + + + +]> + + org.gnome.Characters.desktop + GNOME Characters + Character map application + CC0 + +

+ Characters is a simple utility application to find and insert + unusual characters. It allows you to quickly find the character + you are looking for by searching for keywords. +

+

+ You can also browse characters by categories, such as + Punctuation, Pictures, etc. +

+

+ Did you know that the copyright sign (©, U+00A9) can be written in HTML + as &#xa9;, + as &#169;, + or as &copy;? +

+

Written by &author1;, &author2;, and &author3;.

+

Escape gallery: operator x&y, standard XML entities & " ' & < >, character reference ©, escaped character reference &#xa9;, entity references © &author1;

+

Escape gallery: operator x&y, standard XML entities & " ' & < >, character reference ©, escaped character reference &#xa9;, entity references © &author1;

+
+ https://wiki.gnome.org/Design/Apps/CharacterMap + dueno_at_src.gnome.org +
+EOF + +cat <<\EOF > fr.po +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-03-17 07:36+0900\n" +"PO-Revision-Date: 2014-03-17 08:40+0900\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "" +"Characters is a simple utility application to find and insert unusual " +"characters. It allows you to quickly find the character you are looking for " +"by searching for keywords." +msgstr "" +"Caractères est un utilitaire pour chercher et insérer des caractères " +"inhabituels. Il vous permet de trouver rapidement le caractère que vous " +"cherchez par le biais de mots-clés." + +#, fuzzy +msgid "" +"You can also browse characters by categories, such as Punctuation, Pictures, " +"etc." +msgstr "" +"Vous pouvez aussi naviguer dans les caractères par catégories, comme par " +"Ponctuation, Images, etc." + +msgid "" +"Did you know that the copyright sign (©, U+00A9) can be written in HTML as " +"©, as ©, or as ©?" +msgstr "" +"Saviez-vous que le signe de copyright (©, U+00A9) peut être écrit en HTML " +"comme ©, comme © ou comme © ?" + +msgid "Written by &author1;, &author2;, and &author3;." +msgstr "Écrit par &author1;, &author2;, et &author3;." + +msgid "" +"Escape gallery: operator x&y, standard XML entities & \" ' & < >, character " +"reference ©, escaped character reference ©, entity references © " +"&author1;" +msgstr "" +"Exposition d'échappements: operateur x&y, entités XML standard & \" ' & < >, " +"caractère ©, caractère échappé ©, entités © &author1;" +EOF + +cat <<\EOF > mf.appdata.xml.ok + + + + +]> + + org.gnome.Characters.desktop + GNOME Characters + Character map application + CC0 + +

Caractères est un utilitaire pour chercher et insérer des caractères inhabituels. Il vous permet de trouver rapidement le caractère que vous cherchez par le biais de mots-clés.

+

+ You can also browse characters by categories, such as + Punctuation, Pictures, etc. +

+

Saviez-vous que le signe de copyright (©, U+00A9) peut être écrit en HTML comme &#xa9;, comme &#169; ou comme &copy; ?

+

Écrit par &author1;, &author2;, et &author3;.

+

Exposition d'échappements: operateur x&y, entités XML standard & " ' & < >, caractère ©, caractère échappé &#xa9;, entités © &author1;

+

Exposition d'échappements: operateur x&y, entités XML standard & " ' & < >, caractère ©, caractère échappé &#xa9;, entités &copy; &author1;

+
+ https://wiki.gnome.org/Design/Apps/CharacterMap + dueno_at_src.gnome.org +
+EOF + +# Sanity checks for contradicting options. + +${MSGFMT} --replace-text fr.po \ + >/dev/null 2>/dev/null \ + && Exit 1 + +${MSGFMT} --xml --template=mf.appdata.xml --replace-text -d po -o mf.appdata.xml.out \ + >/dev/null 2>/dev/null \ + && Exit 1 + +# Proceed to the XML file generation. + +${MSGFMT} --xml --template=mf.appdata.xml --replace-text -l fr fr.po -o mf.appdata.xml.out \ + || Exit 1 + +: ${DIFF=diff} +${DIFF} mf.appdata.xml.ok mf.appdata.xml.out +test $? = 0 || Exit 1