1 /* Concatenates several translation catalogs.
2 Copyright (C) 2001-2007, 2009-2010 Free Software Foundation, Inc.
3 Written by Bruno Haible <haible@clisp.cons.org>, 2001.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
32 #include "file-list.h"
34 #include "error-progname.h"
36 #include "relocatable.h"
39 #include "read-catalog.h"
41 #include "read-properties.h"
42 #include "read-stringtable.h"
43 #include "write-catalog.h"
45 #include "write-properties.h"
46 #include "write-stringtable.h"
49 #include "msgl-header.h"
50 #include "propername.h"
53 #define _(str) gettext (str)
56 /* Force output of PO file even if empty. */
59 /* Target encoding. */
60 static const char *to_code;
63 static const struct option long_options[] =
65 { "add-location", no_argument, &line_comment, 1 },
66 { "color", optional_argument, NULL, CHAR_MAX + 5 },
67 { "directory", required_argument, NULL, 'D' },
68 { "escape", no_argument, NULL, 'E' },
69 { "files-from", required_argument, NULL, 'f' },
70 { "force-po", no_argument, &force_po, 1 },
71 { "help", no_argument, NULL, 'h' },
72 { "indent", no_argument, NULL, 'i' },
73 { "lang", required_argument, NULL, CHAR_MAX + 7 },
74 { "no-escape", no_argument, NULL, 'e' },
75 { "no-location", no_argument, &line_comment, 0 },
76 { "no-wrap", no_argument, NULL, CHAR_MAX + 2 },
77 { "output-file", required_argument, NULL, 'o' },
78 { "properties-input", no_argument, NULL, 'P' },
79 { "properties-output", no_argument, NULL, 'p' },
80 { "sort-by-file", no_argument, NULL, 'F' },
81 { "sort-output", no_argument, NULL, 's' },
82 { "strict", no_argument, NULL, 'S' },
83 { "stringtable-input", no_argument, NULL, CHAR_MAX + 3 },
84 { "stringtable-output", no_argument, NULL, CHAR_MAX + 4 },
85 { "style", required_argument, NULL, CHAR_MAX + 6 },
86 { "to-code", required_argument, NULL, 't' },
87 { "unique", no_argument, NULL, 'u' },
88 { "use-first", no_argument, NULL, CHAR_MAX + 1 },
89 { "version", no_argument, NULL, 'V' },
90 { "width", required_argument, NULL, 'w', },
91 { "more-than", required_argument, NULL, '>', },
92 { "less-than", required_argument, NULL, '<', },
97 /* Forward declaration of local functions. */
98 static void usage (int status)
99 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
100 __attribute__ ((noreturn))
106 main (int argc, char **argv)
113 const char *files_from;
114 string_list_ty *file_list;
115 msgdomain_list_ty *result;
116 catalog_input_format_ty input_syntax = &input_format_po;
117 catalog_output_format_ty output_syntax = &output_format_po;
118 bool sort_by_msgid = false;
119 bool sort_by_filepos = false;
120 /* Language (ISO-639 code) and optional territory (ISO-3166 code). */
121 const char *catalogname = NULL;
123 /* Set program name for messages. */
124 set_program_name (argv[0]);
125 error_print_progname = maybe_print_progname;
127 #ifdef HAVE_SETLOCALE
128 /* Set locale via LC_ALL. */
129 setlocale (LC_ALL, "");
132 /* Set the text message domain. */
133 bindtextdomain (PACKAGE, relocate (LOCALEDIR));
134 bindtextdomain ("bison-runtime", relocate (BISON_LOCALEDIR));
135 textdomain (PACKAGE);
137 /* Ensure that write errors on stdout are detected. */
138 atexit (close_stdout);
140 /* Set default values for variables. */
149 while ((optchar = getopt_long (argc, argv, "<:>:D:eEf:Fhino:pPst:uVw:",
150 long_options, NULL)) != EOF)
153 case '\0': /* Long option. */
160 value = strtol (optarg, &endp, 10);
170 value = strtol (optarg, &endp, 10);
177 dir_list_append (optarg);
181 message_print_style_escape (false);
185 message_print_style_escape (true);
193 sort_by_filepos = true;
201 message_print_style_indent ();
209 output_file = optarg;
213 output_syntax = &output_format_properties;
217 input_syntax = &input_format_properties;
221 sort_by_msgid = true;
225 message_print_style_uniforum ();
244 value = strtol (optarg, &endp, 10);
246 message_page_width_set (value);
254 case CHAR_MAX + 2: /* --no-wrap */
255 message_page_width_ignore ();
258 case CHAR_MAX + 3: /* --stringtable-input */
259 input_syntax = &input_format_stringtable;
262 case CHAR_MAX + 4: /* --stringtable-output */
263 output_syntax = &output_format_stringtable;
266 case CHAR_MAX + 5: /* --color */
267 if (handle_color_option (optarg))
268 usage (EXIT_FAILURE);
271 case CHAR_MAX + 6: /* --style */
272 handle_style_option (optarg);
275 case CHAR_MAX + 7: /* --lang */
276 catalogname = optarg;
280 usage (EXIT_FAILURE);
284 /* Version information requested. */
287 printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
288 /* xgettext: no-wrap */
289 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
290 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
291 This is free software: you are free to change and redistribute it.\n\
292 There is NO WARRANTY, to the extent permitted by law.\n\
295 printf (_("Written by %s.\n"), proper_name ("Bruno Haible"));
299 /* Help is requested. */
301 usage (EXIT_SUCCESS);
309 /* Verify selected options. */
310 if (!line_comment && sort_by_filepos)
311 error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
312 "--no-location", "--sort-by-file");
314 if (sort_by_msgid && sort_by_filepos)
315 error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
316 "--sort-output", "--sort-by-file");
318 /* Check the message selection criteria for sanity. */
319 if (more_than >= less_than || less_than < 2)
320 error (EXIT_FAILURE, 0,
321 _("impossible selection criteria specified (%d < n < %d)"),
322 more_than, less_than);
324 /* Determine list of files we have to process. */
325 if (files_from != NULL)
326 file_list = read_names_from_file (files_from);
328 file_list = string_list_alloc ();
329 /* Append names from command line. */
330 for (cnt = optind; cnt < argc; ++cnt)
331 string_list_append_unique (file_list, argv[cnt]);
333 /* Read input files, then filter, convert and merge messages. */
335 catenate_msgdomain_list (file_list, input_syntax,
336 output_syntax->requires_utf8 ? "UTF-8" : to_code);
338 string_list_free (file_list);
340 /* Sorting the list of messages. */
342 msgdomain_list_sort_by_filepos (result);
343 else if (sort_by_msgid)
344 msgdomain_list_sort_by_msgid (result);
346 /* Set the Language field in the header. */
347 if (catalogname != NULL)
348 msgdomain_list_set_header_field (result, "Language:", catalogname);
350 /* Write the PO file. */
351 msgdomain_list_print (result, output_file, output_syntax, force_po, false);
357 /* Display usage information and exit. */
361 if (status != EXIT_SUCCESS)
362 fprintf (stderr, _("Try `%s --help' for more information.\n"),
367 Usage: %s [OPTION] [INPUTFILE]...\n\
370 /* xgettext: no-wrap */
372 Concatenates and merges the specified PO files.\n\
373 Find messages which are common to two or more of the specified PO files.\n\
374 By using the --more-than option, greater commonality may be requested\n\
375 before messages are printed. Conversely, the --less-than option may be\n\
376 used to specify less commonality before messages are printed (i.e.\n\
377 --less-than=2 will only print the unique messages). Translations,\n\
378 comments and extract comments will be cumulated, except that if --use-first\n\
379 is specified, they will be taken from the first PO file to define them.\n\
380 File positions from all PO files will be cumulated.\n\
384 Mandatory arguments to long options are mandatory for short options too.\n"));
387 Input file location:\n"));
389 INPUTFILE ... input files\n"));
391 -f, --files-from=FILE get list of input files from FILE\n"));
393 -D, --directory=DIRECTORY add DIRECTORY to list for input files search\n"));
395 If input file is -, standard input is read.\n"));
398 Output file location:\n"));
400 -o, --output-file=FILE write output to specified file\n"));
402 The results are written to standard output if no output file is specified\n\
406 Message selection:\n"));
408 -<, --less-than=NUMBER print messages with less than this many\n\
409 definitions, defaults to infinite if not set\n"));
411 ->, --more-than=NUMBER print messages with more than this many\n\
412 definitions, defaults to 0 if not set\n"));
414 -u, --unique shorthand for --less-than=2, requests\n\
415 that only unique messages be printed\n"));
418 Input file syntax:\n"));
420 -P, --properties-input input files are in Java .properties syntax\n"));
422 --stringtable-input input files are in NeXTstep/GNUstep .strings\n\
426 Output details:\n"));
428 -t, --to-code=NAME encoding for output\n"));
430 --use-first use first available translation for each\n\
431 message, don't merge several translations\n"));
433 --lang=CATALOGNAME set 'Language' field in the header entry\n"));
435 --color use colors and other text attributes always\n\
436 --color=WHEN use colors and other text attributes if WHEN.\n\
437 WHEN may be 'always', 'never', 'auto', or 'html'.\n"));
439 --style=STYLEFILE specify CSS style rule file for --color\n"));
441 -e, --no-escape do not use C escapes in output (default)\n"));
443 -E, --escape use C escapes in output, no extended chars\n"));
445 --force-po write PO file even if empty\n"));
447 -i, --indent write the .po file using indented style\n"));
449 --no-location do not write '#: filename:line' lines\n"));
451 -n, --add-location generate '#: filename:line' lines (default)\n"));
453 --strict write out strict Uniforum conforming .po file\n"));
455 -p, --properties-output write out a Java .properties file\n"));
457 --stringtable-output write out a NeXTstep/GNUstep .strings file\n"));
459 -w, --width=NUMBER set output page width\n"));
461 --no-wrap do not break long message lines, longer than\n\
462 the output page width, into several lines\n"));
464 -s, --sort-output generate sorted output\n"));
466 -F, --sort-by-file sort output by file location\n"));
469 Informative output:\n"));
471 -h, --help display this help and exit\n"));
473 -V, --version output version information and exit\n"));
475 /* TRANSLATORS: The placeholder indicates the bug-reporting address
476 for this package. Please add _another line_ saying
477 "Report translation bugs to <...>\n" with the address for translation
478 bugs (typically your translation team's web or email address). */
479 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),