1 /* Concatenates several translation catalogs.
2 Copyright (C) 2001-2007, 2009-2015 Free Software Foundation,
4 Written by Bruno Haible <haible@clisp.cons.org>, 2001.
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
33 #include "file-list.h"
35 #include "error-progname.h"
37 #include "relocatable.h"
40 #include "read-catalog.h"
42 #include "read-properties.h"
43 #include "read-stringtable.h"
44 #include "write-catalog.h"
46 #include "write-properties.h"
47 #include "write-stringtable.h"
50 #include "msgl-header.h"
51 #include "propername.h"
54 #define _(str) gettext (str)
57 /* Force output of PO file even if empty. */
60 /* Target encoding. */
61 static const char *to_code;
64 static const struct option long_options[] =
66 { "add-location", optional_argument, NULL, 'n' },
67 { "color", optional_argument, NULL, CHAR_MAX + 5 },
68 { "directory", required_argument, NULL, 'D' },
69 { "escape", no_argument, NULL, 'E' },
70 { "files-from", required_argument, NULL, 'f' },
71 { "force-po", no_argument, &force_po, 1 },
72 { "help", no_argument, NULL, 'h' },
73 { "indent", no_argument, NULL, 'i' },
74 { "lang", required_argument, NULL, CHAR_MAX + 7 },
75 { "no-escape", no_argument, NULL, 'e' },
76 { "no-location", no_argument, NULL, CHAR_MAX + 8 },
77 { "no-wrap", no_argument, NULL, CHAR_MAX + 2 },
78 { "output-file", required_argument, NULL, 'o' },
79 { "properties-input", no_argument, NULL, 'P' },
80 { "properties-output", no_argument, NULL, 'p' },
81 { "sort-by-file", no_argument, NULL, 'F' },
82 { "sort-output", no_argument, NULL, 's' },
83 { "strict", no_argument, NULL, 'S' },
84 { "stringtable-input", no_argument, NULL, CHAR_MAX + 3 },
85 { "stringtable-output", no_argument, NULL, CHAR_MAX + 4 },
86 { "style", required_argument, NULL, CHAR_MAX + 6 },
87 { "to-code", required_argument, NULL, 't' },
88 { "unique", no_argument, NULL, 'u' },
89 { "use-first", no_argument, NULL, CHAR_MAX + 1 },
90 { "version", no_argument, NULL, 'V' },
91 { "width", required_argument, NULL, 'w', },
92 { "more-than", required_argument, NULL, '>', },
93 { "less-than", required_argument, NULL, '<', },
98 /* Forward declaration of local functions. */
99 static void usage (int status)
100 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
101 __attribute__ ((noreturn))
107 main (int argc, char **argv)
114 const char *files_from;
115 string_list_ty *file_list;
116 msgdomain_list_ty *result;
117 catalog_input_format_ty input_syntax = &input_format_po;
118 catalog_output_format_ty output_syntax = &output_format_po;
119 bool sort_by_msgid = false;
120 bool sort_by_filepos = false;
121 /* Language (ISO-639 code) and optional territory (ISO-3166 code). */
122 const char *catalogname = NULL;
124 /* Set program name for messages. */
125 set_program_name (argv[0]);
126 error_print_progname = maybe_print_progname;
128 #ifdef HAVE_SETLOCALE
129 /* Set locale via LC_ALL. */
130 setlocale (LC_ALL, "");
133 /* Set the text message domain. */
134 bindtextdomain (PACKAGE, relocate (LOCALEDIR));
135 bindtextdomain ("bison-runtime", relocate (BISON_LOCALEDIR));
136 textdomain (PACKAGE);
138 /* Ensure that write errors on stdout are detected. */
139 atexit (close_stdout);
141 /* Set default values for variables. */
150 while ((optchar = getopt_long (argc, argv, "<:>:D:eEf:Fhino:pPst:uVw:",
151 long_options, NULL)) != EOF)
154 case '\0': /* Long option. */
161 value = strtol (optarg, &endp, 10);
171 value = strtol (optarg, &endp, 10);
178 dir_list_append (optarg);
182 message_print_style_escape (false);
186 message_print_style_escape (true);
194 sort_by_filepos = true;
202 message_print_style_indent ();
206 if (handle_filepos_comment_option (optarg))
207 usage (EXIT_FAILURE);
211 output_file = optarg;
215 output_syntax = &output_format_properties;
219 input_syntax = &input_format_properties;
223 sort_by_msgid = true;
227 message_print_style_uniforum ();
246 value = strtol (optarg, &endp, 10);
248 message_page_width_set (value);
256 case CHAR_MAX + 2: /* --no-wrap */
257 message_page_width_ignore ();
260 case CHAR_MAX + 3: /* --stringtable-input */
261 input_syntax = &input_format_stringtable;
264 case CHAR_MAX + 4: /* --stringtable-output */
265 output_syntax = &output_format_stringtable;
268 case CHAR_MAX + 5: /* --color */
269 if (handle_color_option (optarg))
270 usage (EXIT_FAILURE);
273 case CHAR_MAX + 6: /* --style */
274 handle_style_option (optarg);
277 case CHAR_MAX + 7: /* --lang */
278 catalogname = optarg;
281 case CHAR_MAX + 8: /* --no-location */
282 message_print_style_filepos (filepos_comment_none);
286 usage (EXIT_FAILURE);
290 /* Version information requested. */
293 printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
294 /* xgettext: no-wrap */
295 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
296 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
297 This is free software: you are free to change and redistribute it.\n\
298 There is NO WARRANTY, to the extent permitted by law.\n\
301 printf (_("Written by %s.\n"), proper_name ("Bruno Haible"));
305 /* Help is requested. */
307 usage (EXIT_SUCCESS);
315 /* Verify selected options. */
316 if (sort_by_msgid && sort_by_filepos)
317 error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
318 "--sort-output", "--sort-by-file");
320 /* Check the message selection criteria for sanity. */
321 if (more_than >= less_than || less_than < 2)
322 error (EXIT_FAILURE, 0,
323 _("impossible selection criteria specified (%d < n < %d)"),
324 more_than, less_than);
326 /* Determine list of files we have to process. */
327 if (files_from != NULL)
328 file_list = read_names_from_file (files_from);
330 file_list = string_list_alloc ();
331 /* Append names from command line. */
332 for (cnt = optind; cnt < argc; ++cnt)
333 string_list_append_unique (file_list, argv[cnt]);
335 /* Read input files, then filter, convert and merge messages. */
337 catenate_msgdomain_list (file_list, input_syntax,
338 output_syntax->requires_utf8 ? "UTF-8" : to_code);
340 string_list_free (file_list);
342 /* Sorting the list of messages. */
344 msgdomain_list_sort_by_filepos (result);
345 else if (sort_by_msgid)
346 msgdomain_list_sort_by_msgid (result);
348 /* Set the Language field in the header. */
349 if (catalogname != NULL)
350 msgdomain_list_set_header_field (result, "Language:", catalogname);
352 /* Write the PO file. */
353 msgdomain_list_print (result, output_file, output_syntax, force_po, false);
359 /* Display usage information and exit. */
363 if (status != EXIT_SUCCESS)
364 fprintf (stderr, _("Try '%s --help' for more information.\n"),
369 Usage: %s [OPTION] [INPUTFILE]...\n\
372 /* xgettext: no-wrap */
374 Concatenates and merges the specified PO files.\n\
375 Find messages which are common to two or more of the specified PO files.\n\
376 By using the --more-than option, greater commonality may be requested\n\
377 before messages are printed. Conversely, the --less-than option may be\n\
378 used to specify less commonality before messages are printed (i.e.\n\
379 --less-than=2 will only print the unique messages). Translations,\n\
380 comments, extracted comments, and file positions will be cumulated, except\n\
381 that if --use-first is specified, they will be taken from the first PO file\n\
386 Mandatory arguments to long options are mandatory for short options too.\n"));
389 Input file location:\n"));
391 INPUTFILE ... input files\n"));
393 -f, --files-from=FILE get list of input files from FILE\n"));
395 -D, --directory=DIRECTORY add DIRECTORY to list for input files search\n"));
397 If input file is -, standard input is read.\n"));
400 Output file location:\n"));
402 -o, --output-file=FILE write output to specified file\n"));
404 The results are written to standard output if no output file is specified\n\
408 Message selection:\n"));
410 -<, --less-than=NUMBER print messages with less than this many\n\
411 definitions, defaults to infinite if not set\n"));
413 ->, --more-than=NUMBER print messages with more than this many\n\
414 definitions, defaults to 0 if not set\n"));
416 -u, --unique shorthand for --less-than=2, requests\n\
417 that only unique messages be printed\n"));
420 Input file syntax:\n"));
422 -P, --properties-input input files are in Java .properties syntax\n"));
424 --stringtable-input input files are in NeXTstep/GNUstep .strings\n\
428 Output details:\n"));
430 -t, --to-code=NAME encoding for output\n"));
432 --use-first use first available translation for each\n\
433 message, don't merge several translations\n"));
435 --lang=CATALOGNAME set 'Language' field in the header entry\n"));
437 --color use colors and other text attributes always\n\
438 --color=WHEN use colors and other text attributes if WHEN.\n\
439 WHEN may be 'always', 'never', 'auto', or 'html'.\n"));
441 --style=STYLEFILE specify CSS style rule file for --color\n"));
443 -e, --no-escape do not use C escapes in output (default)\n"));
445 -E, --escape use C escapes in output, no extended chars\n"));
447 --force-po write PO file even if empty\n"));
449 -i, --indent write the .po file using indented style\n"));
451 --no-location do not write '#: filename:line' lines\n"));
453 -n, --add-location generate '#: filename:line' lines (default)\n"));
455 --strict write out strict Uniforum conforming .po file\n"));
457 -p, --properties-output write out a Java .properties file\n"));
459 --stringtable-output write out a NeXTstep/GNUstep .strings file\n"));
461 -w, --width=NUMBER set output page width\n"));
463 --no-wrap do not break long message lines, longer than\n\
464 the output page width, into several lines\n"));
466 -s, --sort-output generate sorted output\n"));
468 -F, --sort-by-file sort output by file location\n"));
471 Informative output:\n"));
473 -h, --help display this help and exit\n"));
475 -V, --version output version information and exit\n"));
477 /* TRANSLATORS: The placeholder indicates the bug-reporting address
478 for this package. Please add _another line_ saying
479 "Report translation bugs to <...>\n" with the address for translation
480 bugs (typically your translation team's web or email address). */
481 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),