diff options
author | Daiki Ueno <ueno@gnu.org> | 2015-10-05 17:18:41 +0900 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2015-10-15 13:09:43 +0900 |
commit | 2d1143a6ac1d52a6d946eefe9ae31cfecc9e371e (patch) | |
tree | 96946aecb67f956fa50f2b1cd1b986089fd4eb09 /gettext-tools/src/its.c | |
parent | 8701164b866f926568dad22eb221fea8438fb9f1 (diff) | |
download | gettext-wip/ueno/its2.tar.gz |
msgfmt: Support XML file mergingwip/ueno/its2
* gettext-tools/src/Makefile.am (noinst_HEADERS): Add write-xml.h.
(msgfmt_SOURCES): Add write-xml.c.
* gettext-tools/src/its.c (its_merge_context_merge_node): New function.
(its_merge_context_merge): New function.
(its_merge_context_alloc): New function.
(its_merge_context_write): New function.
(its_merge_context_free): New function.
* gettext-tools/src/its.h (its_merge_context_ty): New type.
* gettext-tools/src/msgfmt.c: Include "its.h", "locating-rule.h", and
"write-xml.h".
(SIZEOF): New macro.
(xml_mode, xml_locale_name, xml_template_name, xml_base_directory,
xml_language, xml_its_rules): New variable.
(long_options): Add --language and --xml.
(main): Handle new options.
(usage): Document new options.
(msgfmt_xml_bulk): New function.
* gettext-tools/src/write-xml.c: New file.
* gettext-tools/src/write-xml.h: New file.
* gettext-tools/doc/gettext.texi: Mention XML file merging use-case.
* gettext-tools/doc/msgfmt.texi: Mention --xml option.
* gettext-tools/tests/msgfmt-xml-1: New file.
* gettext-tools/tests/msgfmt-xml-2: New file.
* gettext-tools/tests/Makefile.am (TESTS): Add new tests.
Diffstat (limited to 'gettext-tools/src/its.c')
-rw-r--r-- | gettext-tools/src/its.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/gettext-tools/src/its.c b/gettext-tools/src/its.c index 585e9845a..6843aac7f 100644 --- a/gettext-tools/src/its.c +++ b/gettext-tools/src/its.c @@ -1810,3 +1810,134 @@ its_rule_list_extract (its_rule_list_ty *rules, free (nodes.items); xmlFreeDoc (doc); } + +struct its_merge_context_ty +{ + its_rule_list_ty *rules; + xmlDoc *doc; + struct its_node_list_ty nodes; +}; + +static void +its_merge_context_merge_node (struct its_merge_context_ty *context, + xmlNode *node, + const char *language, + message_list_ty *mlp) +{ + if (node->type == XML_ELEMENT_NODE) + { + struct its_value_list_ty *values; + const char *value; + char *msgid = NULL, *msgctxt = NULL; + enum its_whitespace_type_ty whitespace; + bool no_escape; + + values = its_rule_list_eval (context->rules, node); + + value = its_value_list_get_value (values, "space"); + if (value && strcmp (value, "preserve") == 0) + whitespace = ITS_WHITESPACE_PRESERVE; + else if (value && strcmp (value, "trim") == 0) + whitespace = ITS_WHITESPACE_TRIM; + else + whitespace = ITS_WHITESPACE_NORMALIZE; + + value = its_value_list_get_value (values, "escape"); + no_escape = value != NULL && strcmp (value, "no") == 0; + + value = its_value_list_get_value (values, "contextPointer"); + if (value) + msgctxt = _its_get_content (context->rules, node, value, + ITS_WHITESPACE_PRESERVE, no_escape); + + value = its_value_list_get_value (values, "textPointer"); + if (value) + msgid = _its_get_content (context->rules, node, value, + ITS_WHITESPACE_PRESERVE, no_escape); + its_value_list_destroy (values); + free (values); + + if (msgid == NULL) + msgid = _its_collect_text_content (node, whitespace, no_escape); + if (*msgid != '\0') + { + message_ty *mp; + + mp = message_list_search (mlp, msgctxt, msgid); + if (mp && *mp->msgstr != '\0') + { + xmlNode *translated; + + translated = xmlNewNode (node->ns, node->name); + xmlSetProp (translated, BAD_CAST "xml:lang", BAD_CAST language); + + xmlNodeAddContent (translated, BAD_CAST mp->msgstr); + xmlAddNextSibling (node, translated); + } + } + free (msgctxt); + free (msgid); + } +} + +void +its_merge_context_merge (its_merge_context_ty *context, + const char *language, + message_list_ty *mlp) +{ + size_t i; + + for (i = 0; i < context->nodes.nitems; i++) + its_merge_context_merge_node (context, context->nodes.items[i], + language, + mlp); +} + +struct its_merge_context_ty * +its_merge_context_alloc (its_rule_list_ty *rules, + const char *filename) +{ + xmlDoc *doc; + struct its_merge_context_ty *result; + + doc = xmlReadFile (filename, NULL, + XML_PARSE_NONET + | XML_PARSE_NOWARNING + | XML_PARSE_NOBLANKS + | XML_PARSE_NOERROR); + if (doc == NULL) + { + xmlError *err = xmlGetLastError (); + error (0, 0, _("cannot read %s: %s"), filename, err->message); + return NULL; + } + + its_rule_list_apply (rules, doc); + + result = XMALLOC (struct its_merge_context_ty); + result->rules = rules; + result->doc = doc; + + /* Collect translatable nodes. */ + memset (&result->nodes, 0, sizeof (struct its_node_list_ty)); + its_rule_list_extract_nodes (result->rules, + &result->nodes, + xmlDocGetRootElement (result->doc)); + + return result; +} + +void +its_merge_context_write (struct its_merge_context_ty *context, + FILE *fp) +{ + xmlDocFormatDump (fp, context->doc, 1); +} + +void +its_merge_context_free (struct its_merge_context_ty *context) +{ + xmlFreeDoc (context->doc); + free (context->nodes.items); + free (context); +} |