mirror of
https://https.git.savannah.gnu.org/git/gettext.git
synced 2026-01-26 07:37:57 +00:00
msgfmt: Support XML file merging
* 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.
This commit is contained in:
parent
8701164b86
commit
2d1143a6ac
@ -12286,7 +12286,18 @@ A required @code{escape} attribute with the value @code{yes} or @code{no}.
|
||||
This data category extends the standard @samp{Preserve Space} data
|
||||
category with the additional value @samp{trim}. The value means to
|
||||
remove the leading and trailing whitespaces of the content, but not to
|
||||
normalize whitespaces in the middle.
|
||||
normalize whitespaces in the middle. In the global rule, the
|
||||
@code{preserveSpaceRule} element contains the following:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
A required @code{selector} attribute. It contains an absolute selector
|
||||
that selects the nodes to which this rule applies.
|
||||
|
||||
@item
|
||||
A required @code{space} attribute with the value @code{default},
|
||||
@code{preserve}, or @code{trim}.
|
||||
@end itemize
|
||||
|
||||
@end table
|
||||
|
||||
@ -12363,6 +12374,22 @@ rule files and locating rule files must be installed in the
|
||||
properly installed, @code{xgettext} can extract translatable strings
|
||||
from the matching XML files.
|
||||
|
||||
@subsubsection Two Use-cases of Translated Strings in XML
|
||||
|
||||
For XML, there are two use-cases of translated strings. One is the case
|
||||
where the translated strings are directly consumed by programs, and the
|
||||
other is the case where the translated strings are merged back to the
|
||||
original XML document. In the former case, special characters in the
|
||||
extracted strings shouldn't be escaped, while they should in the latter
|
||||
case. To control wheter to escape special characters, the @samp{Escape
|
||||
Special Characters} data category can be used.
|
||||
|
||||
To merge the translations, the @samp{msgfmt} program can be used with
|
||||
the option @code{--xml}. @xref{msgfmt Invocation}, for more details
|
||||
about how one calls the @samp{msgfmt} program. @samp{msgfmt}'s
|
||||
@code{--xml} option doesn't perform character escaping, so translated
|
||||
strings can have arbitrary XML constructs, such as elements for markup.
|
||||
|
||||
@c This is the template for new data formats.
|
||||
@ignore
|
||||
|
||||
|
||||
@ -65,6 +65,11 @@ Qt mode: generate a Qt @file{.qm} file.
|
||||
@cindex Desktop Entry mode, and @code{msgfmt} program
|
||||
Desktop Entry mode: generate a @file{.desktop} file.
|
||||
|
||||
@item --xml
|
||||
@opindex --xml@r{, @code{msgfmt} option}
|
||||
@cindex XML mode, and @code{msgfmt} program
|
||||
XML mode: generate an XML file.
|
||||
|
||||
@end table
|
||||
|
||||
@subsection Output file location
|
||||
@ -202,11 +207,8 @@ msgfmt --desktop --template=@var{template} --locale=@var{locale} \
|
||||
-o @var{file} @var{filename}.po @dots{}
|
||||
@end example
|
||||
|
||||
On the other hand, when using msgfmt from a Makefile, it is cumbersome
|
||||
to loop over all locales under a particular directory. msgfmt
|
||||
provides a special operation mode for this use-case. To generate a
|
||||
@samp{.desktop} file from multiple @samp{.po} files under a directory,
|
||||
specify the directory with the @samp{-d} option.
|
||||
msgfmt provides a special "bulk" operation mode to process multiple
|
||||
@file{.po} files at a time.
|
||||
|
||||
@example
|
||||
msgfmt --desktop --template=@var{template} -d @var{directory} -o @var{file}
|
||||
@ -220,6 +222,55 @@ variable.
|
||||
For either operation modes, the @samp{-o} and @samp{--template}
|
||||
options are mandatory.
|
||||
|
||||
@subsection XML mode operations
|
||||
|
||||
@table @samp
|
||||
@item --template=@var{template}
|
||||
@opindex --template@r{, @code{msgfmt} option}
|
||||
Specify an XML file used as a template.
|
||||
|
||||
@item -L @var{name}
|
||||
@itemx --language=@var{name}
|
||||
@opindex -L@r{, @code{msgfmt} option}
|
||||
@opindex --language@r{, @code{msgfmt} option}
|
||||
@cindex supported languages, @code{msgfmt}
|
||||
Specifies the language of the input files.
|
||||
|
||||
@item -l @var{locale}
|
||||
@itemx --locale=@var{locale}
|
||||
@opindex -l@r{, @code{msgfmt} option}
|
||||
@opindex --locale@r{, @code{msgfmt} option}
|
||||
Specify the locale name, either a language specification of the form @var{ll}
|
||||
or a combined language and country specification of the form @var{ll_CC}.
|
||||
|
||||
@item -d @var{directory}
|
||||
@opindex -d@r{, @code{msgfmt} option}
|
||||
Specify the base directory of @file{.po} message catalogs.
|
||||
|
||||
@end table
|
||||
|
||||
To generate an XML file for a single locale, you can use it as follows.
|
||||
|
||||
@example
|
||||
msgfmt --xml --template=@var{template} --locale=@var{locale} \
|
||||
-o @var{file} @var{filename}.po @dots{}
|
||||
@end example
|
||||
|
||||
msgfmt provides a special "bulk" operation mode to process multiple
|
||||
@file{.po} files at a time.
|
||||
|
||||
@example
|
||||
msgfmt --xml --template=@var{template} -d @var{directory} -o @var{file}
|
||||
@end example
|
||||
|
||||
msgfmt first reads the @samp{LINGUAS} file under @var{directory}, and
|
||||
then processes all @samp{.po} files listed there. You can also limit
|
||||
the locales to a subset, through the @samp{LINGUAS} environment
|
||||
variable.
|
||||
|
||||
For either operation modes, the @samp{-o} and @samp{--template}
|
||||
options are mandatory.
|
||||
|
||||
@subsection Input file syntax
|
||||
|
||||
@table @samp
|
||||
|
||||
@ -51,6 +51,7 @@ read-resources.h write-resources.h \
|
||||
read-tcl.h write-tcl.h \
|
||||
write-qt.h \
|
||||
read-desktop.h write-desktop.h \
|
||||
write-xml.h \
|
||||
po-time.h plural-table.h lang-table.h format.h filters.h \
|
||||
xgettext.h x-c.h x-po.h x-sh.h x-python.h x-lisp.h x-elisp.h x-librep.h \
|
||||
x-scheme.h x-smalltalk.h x-java.h x-properties.h x-csharp.h x-awk.h x-ycp.h \
|
||||
@ -164,7 +165,8 @@ msgcmp_SOURCES += msgl-fsearch.c
|
||||
msgfmt_SOURCES = msgfmt.c
|
||||
msgfmt_SOURCES += \
|
||||
write-mo.c write-java.c write-csharp.c write-resources.c write-tcl.c \
|
||||
write-qt.c write-desktop.c ../../gettext-runtime/intl/hash-string.c
|
||||
write-qt.c write-desktop.c write-xml.c \
|
||||
../../gettext-runtime/intl/hash-string.c
|
||||
if !WOE32DLL
|
||||
msgmerge_SOURCES = msgmerge.c
|
||||
else
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -66,6 +66,18 @@ extern void its_rule_list_extract (its_rule_list_ty *rules,
|
||||
msgdomain_list_ty *mdlp,
|
||||
its_extract_callback_ty callback);
|
||||
|
||||
typedef struct its_merge_context_ty its_merge_context_ty;
|
||||
|
||||
extern its_merge_context_ty *
|
||||
its_merge_context_alloc (its_rule_list_ty *rules, const char *filename);
|
||||
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);
|
||||
|
||||
extern void its_merge_context_write (its_merge_context_ty *context,
|
||||
FILE *fp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -50,6 +50,7 @@
|
||||
#include "write-tcl.h"
|
||||
#include "write-qt.h"
|
||||
#include "write-desktop.h"
|
||||
#include "write-xml.h"
|
||||
#include "propername.h"
|
||||
#include "message.h"
|
||||
#include "open-catalog.h"
|
||||
@ -62,10 +63,14 @@
|
||||
#include "msgl-check.h"
|
||||
#include "msgl-iconv.h"
|
||||
#include "concat-filename.h"
|
||||
#include "its.h"
|
||||
#include "locating-rule.h"
|
||||
#include "gettext.h"
|
||||
|
||||
#define _(str) gettext (str)
|
||||
|
||||
#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
/* Contains exit status for case in which no premature exit occurs. */
|
||||
static int exit_status;
|
||||
|
||||
@ -111,6 +116,14 @@ static const char *desktop_base_directory;
|
||||
static hash_table desktop_keywords;
|
||||
static bool desktop_default_keywords = true;
|
||||
|
||||
/* XML mode output file specification. */
|
||||
static bool xml_mode;
|
||||
static const char *xml_locale_name;
|
||||
static const char *xml_template_name;
|
||||
static const char *xml_base_directory;
|
||||
static const char *xml_language;
|
||||
static its_rule_list_ty *xml_its_rules;
|
||||
|
||||
/* We may have more than one input file. Domains with same names in
|
||||
different files have to merged. So we need a list of tables for
|
||||
each output file. */
|
||||
@ -181,6 +194,7 @@ static const struct option long_options[] =
|
||||
{ "java", no_argument, NULL, 'j' },
|
||||
{ "java2", no_argument, NULL, CHAR_MAX + 5 },
|
||||
{ "keyword", required_argument, NULL, 'k' },
|
||||
{ "language", required_argument, NULL, 'L' },
|
||||
{ "locale", required_argument, NULL, 'l' },
|
||||
{ "no-hash", no_argument, NULL, CHAR_MAX + 6 },
|
||||
{ "output-file", required_argument, NULL, 'o' },
|
||||
@ -197,6 +211,7 @@ static const struct option long_options[] =
|
||||
{ "use-untranslated", no_argument, NULL, CHAR_MAX + 12 },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "xml", no_argument, NULL, 'x' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -216,6 +231,10 @@ static int msgfmt_desktop_bulk (const char *directory,
|
||||
const char *template_file_name,
|
||||
hash_table *keywords,
|
||||
const char *file_name);
|
||||
static int msgfmt_xml_bulk (const char *directory,
|
||||
const char *template_file_name,
|
||||
its_rule_list_ty *its_rules,
|
||||
const char *file_name);
|
||||
|
||||
|
||||
int
|
||||
@ -252,8 +271,8 @@ main (int argc, char *argv[])
|
||||
/* Ensure that write errors on stdout are detected. */
|
||||
atexit (close_stdout);
|
||||
|
||||
while ((opt = getopt_long (argc, argv, "a:cCd:D:fhjl:o:Pr:vV", long_options,
|
||||
NULL))
|
||||
while ((opt = getopt_long (argc, argv, "a:cCd:D:fhjl:L:o:Pr:vVx",
|
||||
long_options, NULL))
|
||||
!= EOF)
|
||||
switch (opt)
|
||||
{
|
||||
@ -281,6 +300,7 @@ main (int argc, char *argv[])
|
||||
csharp_base_directory = optarg;
|
||||
tcl_base_directory = optarg;
|
||||
desktop_base_directory = optarg;
|
||||
xml_base_directory = optarg;
|
||||
break;
|
||||
case 'D':
|
||||
dir_list_append (optarg);
|
||||
@ -313,6 +333,10 @@ main (int argc, char *argv[])
|
||||
csharp_locale_name = optarg;
|
||||
tcl_locale_name = optarg;
|
||||
desktop_locale_name = optarg;
|
||||
xml_locale_name = optarg;
|
||||
break;
|
||||
case 'L':
|
||||
xml_language = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
output_file_name = optarg;
|
||||
@ -333,6 +357,9 @@ main (int argc, char *argv[])
|
||||
case 'V':
|
||||
do_version = true;
|
||||
break;
|
||||
case 'x':
|
||||
xml_mode = true;
|
||||
break;
|
||||
case CHAR_MAX + 1: /* --check-accelerators */
|
||||
check_accelerators = true;
|
||||
if (optarg != NULL)
|
||||
@ -402,6 +429,7 @@ main (int argc, char *argv[])
|
||||
break;
|
||||
case CHAR_MAX + 16: /* --template=TEMPLATE */
|
||||
desktop_template_name = optarg;
|
||||
xml_template_name = optarg;
|
||||
break;
|
||||
default:
|
||||
usage (EXIT_FAILURE);
|
||||
@ -428,12 +456,16 @@ There is NO WARRANTY, to the extent permitted by law.\n\
|
||||
usage (EXIT_SUCCESS);
|
||||
|
||||
/* Test whether we have a .po file name as argument. */
|
||||
if (optind >= argc && !(desktop_mode && desktop_base_directory))
|
||||
if (optind >= argc
|
||||
&& !(desktop_mode && desktop_base_directory)
|
||||
&& !(xml_mode && xml_base_directory))
|
||||
{
|
||||
error (EXIT_SUCCESS, 0, _("no input file given"));
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
if (optind < argc && desktop_mode && desktop_base_directory)
|
||||
if (optind < argc
|
||||
&& ((desktop_mode && desktop_base_directory)
|
||||
|| (xml_mode && xml_base_directory)))
|
||||
{
|
||||
error (EXIT_SUCCESS, 0,
|
||||
_("no input file should be given if %s and %s are specified"),
|
||||
@ -449,10 +481,11 @@ There is NO WARRANTY, to the extent permitted by law.\n\
|
||||
| (csharp_resources_mode ? 4 : 0)
|
||||
| (tcl_mode ? 8 : 0)
|
||||
| (qt_mode ? 16 : 0)
|
||||
| (desktop_mode ? 32 : 0);
|
||||
| (desktop_mode ? 32 : 0)
|
||||
| (xml_mode ? 64 : 0);
|
||||
static const char *mode_options[] =
|
||||
{ "--java", "--csharp", "--csharp-resources", "--tcl", "--qt",
|
||||
"--desktop" };
|
||||
"--desktop", "--xml" };
|
||||
/* More than one bit set? */
|
||||
if (modes & (modes - 1))
|
||||
{
|
||||
@ -558,6 +591,34 @@ There is NO WARRANTY, to the extent permitted by law.\n\
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else if (xml_mode)
|
||||
{
|
||||
if (xml_template_name == NULL)
|
||||
{
|
||||
error (EXIT_SUCCESS, 0,
|
||||
_("%s requires a \"--template template\" specification"),
|
||||
"--xml");
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
if (output_file_name == NULL)
|
||||
{
|
||||
error (EXIT_SUCCESS, 0,
|
||||
_("%s requires a \"-o file\" specification"),
|
||||
"--xml");
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
if (xml_base_directory != NULL && xml_locale_name != NULL)
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("%s and %s are mutually exclusive in %s"),
|
||||
"-d", "-l", "--xml");
|
||||
if (xml_base_directory == NULL && xml_locale_name == NULL)
|
||||
{
|
||||
error (EXIT_SUCCESS, 0,
|
||||
_("%s requires a \"-l locale\" specification"),
|
||||
"--xml");
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (java_resource_name != NULL)
|
||||
@ -600,6 +661,80 @@ There is NO WARRANTY, to the extent permitted by law.\n\
|
||||
exit (exit_status);
|
||||
}
|
||||
|
||||
if (xml_mode)
|
||||
{
|
||||
const char *gettextdatadir;
|
||||
char *versioned_gettextdatadir;
|
||||
char *its_dirs[2] = { NULL, NULL };
|
||||
locating_rule_list_ty *its_locating_rules;
|
||||
const char *its_basename;
|
||||
size_t i;
|
||||
|
||||
/* Make it possible to override the locator file location. This
|
||||
is necessary for running the testsuite before "make
|
||||
install". */
|
||||
gettextdatadir = getenv ("GETTEXTDATADIR");
|
||||
if (gettextdatadir == NULL || gettextdatadir[0] == '\0')
|
||||
gettextdatadir = relocate (GETTEXTDATADIR);
|
||||
|
||||
its_dirs[0] = xconcatenated_filename (gettextdatadir, "its", NULL);
|
||||
|
||||
versioned_gettextdatadir =
|
||||
xasprintf ("%s%s", relocate (GETTEXTDATADIR), PACKAGE_SUFFIX);
|
||||
its_dirs[1] = xconcatenated_filename (versioned_gettextdatadir, "its",
|
||||
NULL);
|
||||
free (versioned_gettextdatadir);
|
||||
|
||||
its_locating_rules = locating_rule_list_alloc ();
|
||||
for (i = 0; i < SIZEOF (its_dirs); i++)
|
||||
locating_rule_list_add_from_directory (its_locating_rules, its_dirs[i]);
|
||||
|
||||
its_basename = locating_rule_list_locate (its_locating_rules,
|
||||
xml_template_name,
|
||||
xml_language);
|
||||
|
||||
if (its_basename != NULL)
|
||||
{
|
||||
size_t j;
|
||||
|
||||
xml_its_rules = its_rule_list_alloc ();
|
||||
for (j = 0; j < SIZEOF (its_dirs); j++)
|
||||
{
|
||||
char *its_filename =
|
||||
xconcatenated_filename (its_dirs[j], its_basename, NULL);
|
||||
struct stat statbuf;
|
||||
bool ok = false;
|
||||
|
||||
if (stat (its_filename, &statbuf) == 0)
|
||||
ok = its_rule_list_add_from_file (xml_its_rules, its_filename);
|
||||
free (its_filename);
|
||||
if (ok)
|
||||
break;
|
||||
}
|
||||
if (j == SIZEOF (its_dirs))
|
||||
{
|
||||
its_rule_list_free (xml_its_rules);
|
||||
xml_its_rules = NULL;
|
||||
}
|
||||
}
|
||||
locating_rule_list_free (its_locating_rules);
|
||||
|
||||
if (xml_its_rules == NULL)
|
||||
error (EXIT_FAILURE, 0, _("cannot locate ITS rules for %s"),
|
||||
xml_template_name);
|
||||
}
|
||||
|
||||
/* Bulk processing mode for XML files.
|
||||
Process all .po files in desktop_base_directory. */
|
||||
if (xml_mode && xml_base_directory)
|
||||
{
|
||||
exit_status = msgfmt_xml_bulk (xml_base_directory,
|
||||
xml_template_name,
|
||||
xml_its_rules,
|
||||
output_file_name);
|
||||
exit (exit_status);
|
||||
}
|
||||
|
||||
/* The -o option determines the name of the domain and therefore
|
||||
the output file. */
|
||||
if (output_file_name != NULL)
|
||||
@ -705,6 +840,15 @@ There is NO WARRANTY, to the extent permitted by law.\n\
|
||||
if (desktop_keywords.table != NULL)
|
||||
hash_destroy (&desktop_keywords);
|
||||
}
|
||||
else if (xml_mode)
|
||||
{
|
||||
if (msgdomain_write_xml (domain->mlp, canon_encoding,
|
||||
xml_locale_name,
|
||||
xml_template_name,
|
||||
xml_its_rules,
|
||||
domain->file_name))
|
||||
exit_status = EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (msgdomain_write_mo (domain->mlp, domain->domain_name,
|
||||
@ -810,6 +954,8 @@ Operation mode:\n"));
|
||||
--qt Qt mode: generate a Qt .qm file\n"));
|
||||
printf (_("\
|
||||
--desktop Desktop Entry mode: generate a .desktop file\n"));
|
||||
printf (_("\
|
||||
--xml XML mode: generate XML file\n"));
|
||||
printf ("\n");
|
||||
printf (_("\
|
||||
Output file location:\n"));
|
||||
@ -873,6 +1019,22 @@ Desktop Entry mode options:\n"));
|
||||
-k, --keyword do not to use default keywords\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");
|
||||
printf (_("\
|
||||
XML mode options:\n"));
|
||||
printf (_("\
|
||||
-l, --locale=LOCALE locale name, either language or language_COUNTRY\n"));
|
||||
printf (_("\
|
||||
-L, --language=NAME recognise the specified XML language\n"));
|
||||
printf (_("\
|
||||
-o, --output-file=FILE write output to specified file\n"));
|
||||
printf (_("\
|
||||
--template=TEMPLATE a .desktop file used as a template\n"));
|
||||
printf (_("\
|
||||
-d DIRECTORY base directory of .po files\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");
|
||||
printf (_("\
|
||||
@ -1519,3 +1681,37 @@ msgfmt_desktop_bulk (const char *directory,
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Helper function to support 'bulk' operation mode of --xml.
|
||||
This reads all .po files in DIRECTORY and merges them into an
|
||||
XML file FILE_NAME. Currently it does not support some
|
||||
options available in 'iterative' mode, such as --statistics. */
|
||||
static int
|
||||
msgfmt_xml_bulk (const char *directory,
|
||||
const char *template_file_name,
|
||||
its_rule_list_ty *its_rules,
|
||||
const char *file_name)
|
||||
{
|
||||
msgfmt_operand_list_ty operands;
|
||||
int nerrors, status;
|
||||
|
||||
msgfmt_operand_list_init (&operands);
|
||||
|
||||
/* Read all .po files. */
|
||||
nerrors = msgfmt_operand_list_add_from_directory (&operands, directory);
|
||||
if (nerrors > 0)
|
||||
{
|
||||
msgfmt_operand_list_destroy (&operands);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Write the messages into .xml file. */
|
||||
status = msgdomain_write_xml_bulk (&operands,
|
||||
template_file_name,
|
||||
its_rules,
|
||||
file_name);
|
||||
|
||||
msgfmt_operand_list_destroy (&operands);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
107
gettext-tools/src/write-xml.c
Normal file
107
gettext-tools/src/write-xml.c
Normal file
@ -0,0 +1,107 @@
|
||||
/* Writing XML files.
|
||||
Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014-2015
|
||||
Free Software Foundation, Inc.
|
||||
This file was written by Daiki Ueno <ueno@gnu.org>.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* Specification. */
|
||||
#include "write-xml.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "error.h"
|
||||
#include "msgl-iconv.h"
|
||||
#include "po-charset.h"
|
||||
#include "read-catalog.h"
|
||||
#include "read-po.h"
|
||||
#include "fwriteerror.h"
|
||||
#include "xalloc.h"
|
||||
#include "gettext.h"
|
||||
|
||||
#define _(str) gettext (str)
|
||||
|
||||
int
|
||||
msgdomain_write_xml_bulk (msgfmt_operand_list_ty *operands,
|
||||
const char *template_file_name,
|
||||
its_rule_list_ty *its_rules,
|
||||
const char *file_name)
|
||||
{
|
||||
its_merge_context_ty *context;
|
||||
size_t i;
|
||||
FILE *fp;
|
||||
|
||||
if (strcmp (file_name, "-") == 0)
|
||||
fp = stdout;
|
||||
else
|
||||
{
|
||||
fp = fopen (file_name, "wb");
|
||||
if (fp == NULL)
|
||||
{
|
||||
error (0, errno, _("cannot create output file \"%s\""),
|
||||
file_name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
context = its_merge_context_alloc (its_rules, template_file_name);
|
||||
for (i = 0; i < operands->nitems; i++)
|
||||
its_merge_context_merge (context,
|
||||
operands->items[i].language,
|
||||
operands->items[i].mlp);
|
||||
its_merge_context_write (context, fp);
|
||||
its_merge_context_free (context);
|
||||
|
||||
/* Make sure nothing went wrong. */
|
||||
if (fwriteerror (fp))
|
||||
{
|
||||
error (0, errno, _("error while writing \"%s\" file"),
|
||||
file_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
msgdomain_write_xml (message_list_ty *mlp,
|
||||
const char *canon_encoding,
|
||||
const char *locale_name,
|
||||
const char *template_file_name,
|
||||
its_rule_list_ty *its_rules,
|
||||
const char *file_name)
|
||||
{
|
||||
msgfmt_operand_ty operand;
|
||||
msgfmt_operand_list_ty operands;
|
||||
|
||||
/* Convert the messages to Unicode. */
|
||||
iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL);
|
||||
|
||||
/* Create a single-element operands and run the bulk operation on it. */
|
||||
operand.language = (char *) locale_name;
|
||||
operand.mlp = mlp;
|
||||
operands.nitems = 1;
|
||||
operands.items = &operand;
|
||||
|
||||
return msgdomain_write_xml_bulk (&operands,
|
||||
template_file_name,
|
||||
its_rules,
|
||||
file_name);
|
||||
}
|
||||
52
gettext-tools/src/write-xml.h
Normal file
52
gettext-tools/src/write-xml.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* Reading XML files.
|
||||
Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014-2015
|
||||
Free Software Foundation, Inc.
|
||||
This file was written by Daiki Ueno <ueno@gnu.org>.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _WRITE_XML_H
|
||||
#define _WRITE_XML_H
|
||||
|
||||
#include "its.h"
|
||||
#include "msgfmt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Write an XML file. mlp is a list containing the messages
|
||||
to be output. locale_name is the locale name. template_file_name
|
||||
is the template file. file_name is the output file. Return 0 if
|
||||
ok, nonzero on error. */
|
||||
extern int
|
||||
msgdomain_write_xml (message_list_ty *mlp,
|
||||
const char *canon_encoding,
|
||||
const char *locale_name,
|
||||
const char *template_file_name,
|
||||
its_rule_list_ty *its_rules,
|
||||
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,
|
||||
const char *file_name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _WRITE_XML_H */
|
||||
@ -51,6 +51,7 @@ TESTS = gettext-1 gettext-2 gettext-3 gettext-4 gettext-5 gettext-6 gettext-7 \
|
||||
msgfmt-properties-1 \
|
||||
msgfmt-qt-1 msgfmt-qt-2 \
|
||||
msgfmt-desktop-1 msgfmt-desktop-2 \
|
||||
msgfmt-xml-1 msgfmt-xml-2 \
|
||||
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 \
|
||||
|
||||
119
gettext-tools/tests/msgfmt-xml-1
Executable file
119
gettext-tools/tests/msgfmt-xml-1
Executable file
@ -0,0 +1,119 @@
|
||||
#! /bin/sh
|
||||
. "${srcdir=.}/init.sh"; path_prepend_ . ../src
|
||||
|
||||
# Test iterative mode of msgfmt --xml.
|
||||
|
||||
cat <<\EOF > mf.appdata.xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gnome.Characters.desktop</id>
|
||||
<name>GNOME Characters</name>
|
||||
<summary>Character map application</summary>
|
||||
<licence>CC0</licence>
|
||||
<description>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
You can also browse characters by categories, such as
|
||||
Punctuation, Pictures, etc.
|
||||
</p>
|
||||
</description>
|
||||
<url type="homepage">https://wiki.gnome.org/Design/Apps/CharacterMap</url>
|
||||
<updatecontact>dueno_at_src.gnome.org</updatecontact>
|
||||
</component>
|
||||
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 <EMAIL@ADDRESS>, 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 <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\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."
|
||||
|
||||
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."
|
||||
EOF
|
||||
|
||||
cat <<\EOF > mf.appdata.xml.ok
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gnome.Characters.desktop</id>
|
||||
<name>GNOME Characters</name>
|
||||
<summary>Character map application</summary>
|
||||
<licence>CC0</licence>
|
||||
<description>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p xml:lang="fr">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.</p>
|
||||
<p>
|
||||
You can also browse characters by categories, such as
|
||||
Punctuation, Pictures, etc.
|
||||
</p>
|
||||
<p xml:lang="fr">Vous pouvez aussi naviguer dans les caractères par catégories, comme par Ponctuation, Images, etc.</p>
|
||||
</description>
|
||||
<url type="homepage">https://wiki.gnome.org/Design/Apps/CharacterMap</url>
|
||||
<updatecontact>dueno_at_src.gnome.org</updatecontact>
|
||||
</component>
|
||||
EOF
|
||||
|
||||
# Sanity checks for contradicting options.
|
||||
|
||||
${MSGFMT} --xml --template=mf.appdata.xml -l fr fr.po \
|
||||
>/dev/null 2>/dev/null \
|
||||
&& exit 1
|
||||
|
||||
${MSGFMG} --xml --template=mf.appdata.xml fr.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 -l fr fr.po -o mf.appdata.xml.out \
|
||||
|| exit 1
|
||||
|
||||
: ${DIFF=diff}
|
||||
${DIFF} mf.appdata.xml.ok mf.appdata.xml.out
|
||||
result=$?
|
||||
test $result = 0 || exit $result
|
||||
|
||||
# Test -L option.
|
||||
cp mf.appdata.xml mf.xml
|
||||
${MSGFMT} --xml --template=mf.xml -L AppData -l fr fr.po -o mf.appdata.xml.out \
|
||||
|| exit 1
|
||||
${DIFF} mf.appdata.xml.ok mf.appdata.xml.out
|
||||
result=$?
|
||||
test $result = 0 || exit $result
|
||||
|
||||
exit $result
|
||||
203
gettext-tools/tests/msgfmt-xml-2
Executable file
203
gettext-tools/tests/msgfmt-xml-2
Executable file
@ -0,0 +1,203 @@
|
||||
#! /bin/sh
|
||||
. "${srcdir=.}/init.sh"; path_prepend_ . ../src
|
||||
|
||||
# Test 'bulk' mode of msgfmt --xml.
|
||||
|
||||
cat <<\EOF > mf.appdata.xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gnome.Characters.desktop</id>
|
||||
<name>GNOME Characters</name>
|
||||
<summary>Character map application</summary>
|
||||
<licence>CC0</licence>
|
||||
<description>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
You can also browse characters by categories, such as
|
||||
Punctuation, Pictures, etc.
|
||||
</p>
|
||||
</description>
|
||||
<url type="homepage">https://wiki.gnome.org/Design/Apps/CharacterMap</url>
|
||||
<updatecontact>dueno_at_src.gnome.org</updatecontact>
|
||||
</component>
|
||||
EOF
|
||||
|
||||
test -d po || mkdir po
|
||||
|
||||
cat <<\EOF > po/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 <EMAIL@ADDRESS>, 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 <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\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."
|
||||
|
||||
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."
|
||||
EOF
|
||||
|
||||
cat <<\EOF > po/de.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 <EMAIL@ADDRESS>, 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 <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\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 ""
|
||||
"Zeichen ist ein einfaches Hilfsprogramm zum Auffinden und Einsetzen von selten "
|
||||
"verwendeten Zeichen. Sie können schnell das gesuchte Zeichen finden, indem Sie "
|
||||
"nach Schlüsselwörtern suchen."
|
||||
|
||||
msgid ""
|
||||
"You can also browse characters by categories, such as Punctuation, Pictures, "
|
||||
"etc."
|
||||
msgstr ""
|
||||
"Sie können ebenfalls nach Kategorie suchen, wie z.B. nach Zeichensetzung oder "
|
||||
"Bildern."
|
||||
EOF
|
||||
|
||||
cat <<\EOF > mf.appdata.xml.ok
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gnome.Characters.desktop</id>
|
||||
<name>GNOME Characters</name>
|
||||
<summary>Character map application</summary>
|
||||
<licence>CC0</licence>
|
||||
<description>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p xml:lang="fr">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.</p>
|
||||
<p xml:lang="de">Zeichen ist ein einfaches Hilfsprogramm zum Auffinden und Einsetzen von selten verwendeten Zeichen. Sie können schnell das gesuchte Zeichen finden, indem Sie nach Schlüsselwörtern suchen.</p>
|
||||
<p>
|
||||
You can also browse characters by categories, such as
|
||||
Punctuation, Pictures, etc.
|
||||
</p>
|
||||
<p xml:lang="fr">Vous pouvez aussi naviguer dans les caractères par catégories, comme par Ponctuation, Images, etc.</p>
|
||||
<p xml:lang="de">Sie können ebenfalls nach Kategorie suchen, wie z.B. nach Zeichensetzung oder Bildern.</p>
|
||||
</description>
|
||||
<url type="homepage">https://wiki.gnome.org/Design/Apps/CharacterMap</url>
|
||||
<updatecontact>dueno_at_src.gnome.org</updatecontact>
|
||||
</component>
|
||||
EOF
|
||||
|
||||
cat <<\EOF > mf.appdata.xml.desired.ok
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gnome.Characters.desktop</id>
|
||||
<name>GNOME Characters</name>
|
||||
<summary>Character map application</summary>
|
||||
<licence>CC0</licence>
|
||||
<description>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p xml:lang="fr">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.</p>
|
||||
<p>
|
||||
You can also browse characters by categories, such as
|
||||
Punctuation, Pictures, etc.
|
||||
</p>
|
||||
<p xml:lang="fr">Vous pouvez aussi naviguer dans les caractères par catégories, comme par Ponctuation, Images, etc.</p>
|
||||
</description>
|
||||
<url type="homepage">https://wiki.gnome.org/Design/Apps/CharacterMap</url>
|
||||
<updatecontact>dueno_at_src.gnome.org</updatecontact>
|
||||
</component>
|
||||
EOF
|
||||
|
||||
unset LINGUAS
|
||||
|
||||
# Sanity checks for contradicting options.
|
||||
|
||||
${MSGFMT} --xml --template=mf.appdata.xml -d po -o mf.appdata.xml.out \
|
||||
>/dev/null 2>/dev/null \
|
||||
exit 1
|
||||
|
||||
test -d po/LINGUAS || mkdir po/LINGUAS
|
||||
|
||||
${MSGFMT} --xml --template=mf.appdata.xml -d po -o mf.appdata.xml.out \
|
||||
>/dev/null 2>/dev/null \
|
||||
exit 1
|
||||
|
||||
rm -fr po/LINGUAS
|
||||
|
||||
cat <<\EOF > po/LINGUAS
|
||||
de
|
||||
fr
|
||||
EOF
|
||||
|
||||
${MSGFMT} --xml --template=mf.appdata.xml -d po \
|
||||
>/dev/null 2>/dev/null \
|
||||
&& exit 1
|
||||
|
||||
${MSGFMG} --xml --template=mf.appdata.xml -d po -o mf.appdata.xml.out -l fr \
|
||||
>/dev/null 2>/dev/null \
|
||||
&& exit 1
|
||||
|
||||
${MSGFMG} --xml --template=mf.appdata.xml -d po -o mf.appdata.xml.out po/fr.po \
|
||||
>/dev/null 2>/dev/null \
|
||||
&& exit 1
|
||||
|
||||
# Proceed to the .desktop file generation.
|
||||
|
||||
${MSGFMT} --xml --template=mf.appdata.xml -d po -o mf.appdata.xml.out || exit 1
|
||||
: ${DIFF=diff}
|
||||
${DIFF} mf.appdata.xml.ok mf.appdata.xml.out
|
||||
test $? = 0 || exit 1
|
||||
|
||||
# Restrict the desired languages with the LINGUAS envvar.
|
||||
|
||||
LINGUAS="fr ja" ${MSGFMT} --xml --template=mf.appdata.xml -d po -o mf.appdata.xml.desired.out || exit 1
|
||||
|
||||
: ${DIFF=diff}
|
||||
${DIFF} mf.appdata.xml.desired.ok mf.appdata.xml.desired.out
|
||||
test $? = 0 || exit 1
|
||||
Loading…
x
Reference in New Issue
Block a user