The default value is empty, which means that translators will be clueless!
Don't forget to specify this option.
+@item --generated=@var{file}
+@opindex --generated@r{, @code{xgettext} option}
+
+Declares that the given @var{file} is generated
+and therefore should not have
+an influence on the @samp{POT-Creation-Date} field in the output.
+
+When you specify this option,
+you should also specify one or @code{--reference} options,
+to indicate the files from which the given @var{file} was generated.
+
@item --reference=@var{file}
@opindex --reference@r{, @code{xgettext} option}
-Declares that the output depends on the contents of the given FILE.
+Declares that the output depends on the contents of the given @var{file}.
This has an influence on the @samp{POT-Creation-Date} field in the output.
By default, @code{xgettext} determines the @samp{POT-Creation-Date} as
#include "dir-list.h"
#include "file-list.h"
#include "str-list.h"
+#include "gl_set.h"
+#include "gl_xset.h"
+#include "gl_hash_set.h"
+#include "hashkey-string.h"
#include "error-progname.h"
#include "progname.h"
#include "relocatable.h"
/* The file names whose version-controlled modification times shall be
considered. */
static string_list_ty files_for_vc_mtime;
+/* The file names whose (possibly version-controlled) modification times
+ shall be ignored. */
+static gl_set_t generated_files;
/* Long options. */
static const struct option long_options[] =
{ "force-po", no_argument, &force_po, 1 },
{ "foreign-user", no_argument, NULL, CHAR_MAX + 2 },
{ "from-code", required_argument, NULL, CHAR_MAX + 3 },
+ { "generated", required_argument, NULL, CHAR_MAX + 24 },
{ "help", no_argument, NULL, 'h' },
{ "indent", no_argument, NULL, 'i' },
{ "its", required_argument, NULL, CHAR_MAX + 20 },
/* Set initial value of variables. */
default_domain = MESSAGE_DOMAIN_DEFAULT;
string_list_init (&files_for_vc_mtime);
+ generated_files =
+ gl_set_create_empty (GL_HASH_SET,
+ hashkey_string_equals, hashkey_string_hash, NULL);
xgettext_global_source_encoding = NULL;
init_flag_table_c ();
init_flag_table_objc ();
xgettext_no_git = true;
break;
+ case CHAR_MAX + 24: /* --generated */
+ gl_set_add (generated_files, optarg);
+ break;
+
default:
usage (EXIT_FAILURE);
/* NOTREACHED */
printf (_("\
--msgid-bugs-address=EMAIL@ADDRESS set report address for msgid bugs\n"));
printf (_("\
+ --generated=FILE Declares that the given FILE is generated and\n\
+ therefore should not have an influence on the\n\
+ 'POT-Creation-Date' field in the output.\n"));
+ printf (_("\
--reference=FILE Declares that the output depends on the contents\n\
of the given FILE. This has an influence on the\n\
'POT-Creation-Date' field in the output.\n"));
{
/* Set the POT-Creation-Date field. */
{
+ /* First, filter out the generated files. */
+ const char **filenames;
+ size_t nfiles;
+ {
+ const char **all_files = files_for_vc_mtime.item;
+ size_t num_all_files = files_for_vc_mtime.nitems;
+ filenames = XNMALLOC (num_all_files, const char *);
+ nfiles = 0;
+ for (size_t i = 0; i < num_all_files; i++)
+ {
+ const char *file = all_files[i];
+ if (!gl_set_search (generated_files, file))
+ filenames[nfiles++] = file;
+ }
+ }
+
+ /* Then, take the maximum of the (possibly version-controlled) modification
+ times of these files. */
time_t stamp;
struct timespec max_of_mtimes;
- if (files_for_vc_mtime.nitems > 0
- && max_mtime (&max_of_mtimes,
- files_for_vc_mtime.nitems, files_for_vc_mtime.item)
- == 0)
+ if (nfiles > 0 && max_mtime (&max_of_mtimes, nfiles, filenames) == 0)
/* Use the maximum of the encountered mtimes. */
stamp = max_of_mtimes.tv_sec;
else
/* Use the current time. */
time (&stamp);
+ free (filenames);
+
char *timestring = po_strftime (&stamp);
msgdomain_list_set_header_field (mdlp, "POT-Creation-Date:", timestring);
free (timestring);
: ${DIFF=diff}
${DIFF} xg-gi-test1-h.ok xg-gi-test1-h.pot || Exit 1
+
+# ------------------------------------------------------------------------------
+# Verify that a file specified through --generated is ignored in the
+# POT-Creation-Date computation.
+
+TZ=UTC0 \
+${XGETTEXT} -o xg-gi-test1-i.tmp --no-location \
+ --generated='Hadschi Halef Omar/ben/Hadschi Abul Abbas/ibn/Hadschi Dawuhd al Gossarah'/sequence999.c \
+ 'Hadschi Halef Omar/ben/Hadschi Abul Abbas/ibn/Hadschi Dawuhd al Gossarah'/sequence{000,999}.c
+LC_ALL=C tr -d '\r' < xg-gi-test1-i.tmp > xg-gi-test1-i.pot || Exit 1
+
+cat <<\EOF > xg-gi-test1-i.ok
+# 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: 2025-05-01 20:51+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\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 "Hello, world!"
+msgstr ""
+EOF
+
+: ${DIFF=diff}
+${DIFF} xg-gi-test1-i.ok xg-gi-test1-i.pot || Exit 1