]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
po: Don't msgmerge the PO files through Makefile.in.in.
authorBruno Haible <bruno@clisp.org>
Mon, 13 Oct 2025 22:55:27 +0000 (00:55 +0200)
committerBruno Haible <bruno@clisp.org>
Mon, 13 Oct 2025 22:55:27 +0000 (00:55 +0200)
* gettext-runtime/po/Makefile.in.in (MSGMERGE_UPDATE): Remove variable.
(UPDATEPOFILES): Remove variable.
(POFILESDEPS*): Remove variables.
(.SUFFIXES): Add '.gpo'. Remove '.po-update'.
(.po.gpo): New rule.
($(POFILES)): Remove dependencies. Don't invoke MSGMERGE_UPDATE.
(mostlyclean): Add *.gpo.
(update-po): Don't make $(UPDATEPOFILES).
(.nop.po-update): Remove rule.
* gettext-runtime/po/Makevars (PO_DEPENDS_ON_POT): Remove variable.
* gettext-tools/po/Makevars (PO_DEPENDS_ON_POT): Likewise.
* gettext-tools/po/Makevars.template (PO_DEPENDS_ON_POT): Likewise.
* gettext-tools/examples/hello-c/po/Makevars (PO_DEPENDS_ON_POT): Likewise.
* gettext-tools/examples/hello-c-gnome2/po/Makevars (PO_DEPENDS_ON_POT):
Likewise.
* gettext-tools/examples/hello-c-gnome3/po/Makevars (PO_DEPENDS_ON_POT):
Likewise.
* gettext-tools/examples/hello-c-http/po/Makevars (PO_DEPENDS_ON_POT): Likewise.
* gettext-tools/examples/hello-c++/po/Makevars (PO_DEPENDS_ON_POT): Likewise.
* gettext-tools/examples/hello-c++20/po/Makevars (PO_DEPENDS_ON_POT): Likewise.
* gettext-tools/examples/hello-c++-gnome2/po/Makevars (PO_DEPENDS_ON_POT):
Likewise.
* gettext-tools/examples/hello-c++-gnome3/po/Makevars (PO_DEPENDS_ON_POT):
Likewise.
* gettext-tools/examples/hello-c++-kde/po/Makevars (PO_DEPENDS_ON_POT):
Likewise.
* gettext-tools/examples/hello-objc/po/Makevars (PO_DEPENDS_ON_POT): Likewise.
* gettext-tools/examples/hello-objc-gnome2/po/Makevars (PO_DEPENDS_ON_POT):
Likewise.
* gettext-tools/examples/hello-c++-wxwidgets/po/Makefile.am (MSGMERGE_UPDATE):
Remove variable.
(UPDATEPOFILES): Remove variable.
(.SUFFIXES): Add '.gpo'. Remove '.po-update'.
(.po.gpo): New rule.
($(POFILES)): Remove dependencies. Don't invoke MSGMERGE_UPDATE.
(MOSTLYCLEANFILES): Add *.gpo.
(update-po): Don't make $(UPDATEPOFILES).
(.nop.po-update): Remove rule.
* gettext-tools/examples/hello-python/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-guile/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-clisp/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-librep/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-rust/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-go/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-go-http/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-ruby/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-sh/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-gawk/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-pascal/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-modula2/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-d/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-ocaml/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-smalltalk/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-perl/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-php/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-ycp/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-c++-qt/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-java/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-java-awt/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-java-swing/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-java-qtjambi/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-csharp/po/Makefile.am (MSGMERGE_UPDATE): Remove
variable.
(UPDATEPOFILES): Remove variable.
(RESOURCESDLLFILES): Change emitted commands to use an intermediate .gpo file.
(.SUFFIXES): Add '.gpo'. Remove '.po-update'.
(.po.gpo): New rule.
($(POFILES)): Remove dependencies. Don't invoke MSGMERGE_UPDATE.
(MOSTLYCLEANFILES): Add *.gpo.
(update-po): Don't make $(UPDATEPOFILES).
(.nop.po-update): Remove rule.
* gettext-tools/examples/hello-csharp-forms/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-tcl/po/Makefile.am (MSGMERGE_UPDATE): Remove
variable.
(UPDATEPOFILES): Remove variable.
(MSGFILES): Change emitted commands to use an intermediate .gpo file.
(.SUFFIXES): Add '.gpo'. Remove '.po-update'.
(.po.gpo): New rule.
($(POFILES)): Remove dependencies. Don't invoke MSGMERGE_UPDATE.
(MOSTLYCLEANFILES): Add *.gpo.
(update-po): Don't make $(UPDATEPOFILES).
(.nop.po-update): Remove rule.
* gettext-tools/examples/hello-tcl-tk/po/Makefile.am: Likewise.
* gettext-tools/examples/hello-objc-gnustep/po/GNUmakefile (MSGMERGE_UPDATE):
Remove variable.
(UPDATEPOFILES): Remove variable.
(.SUFFIXES): Add '.gpo'. Remove '.po-update'.
($(POFILES)): Remove dependencies. Don't invoke MSGMERGE_UPDATE.
(update-po): Don't make $(UPDATEPOFILES).
(.nop.po-update): Remove rule.
* gettext-tools/examples/po/Makefile.am (MSGMERGE_OPTIONS): Add
--no-fuzzy-matching --quiet.
(MSGMERGE_UPDATE): Remove variable.
(UPDATEPOFILES): Remove variable.
(GPOFILES): New variable.
(.SUFFIXES): Add '.gpo'. Remove '.nop', '.po-update'.
(.po.gpo): New rule.
($(POFILES)): Remove rule.
(DISTCLEANFILES): New variable.
(update-po): Don't make $(UPDATEPOFILES). Make the small PO files.
(.nop.po-update): Remove rule.
* gettext-tools/examples/po/mmsmallpo.sh: Use $language.gpo instead of
$language.po.
* gettext-tools/doc/gettext.texi (Translations under Version Control): Remove
documentation of PO_DEPENDS_ON_POT.
(Release Management): Update wording.
* Admin/release-steps: Don't msgmerge the PO files from translationproject.org.
* NEWS: Mention the change.

50 files changed:
.gitignore
Admin/release-steps
NEWS
gettext-runtime/po/Makefile.in.in
gettext-runtime/po/Makevars
gettext-tools/doc/gettext.texi
gettext-tools/examples/hello-c++-gnome2/po/Makevars
gettext-tools/examples/hello-c++-gnome3/po/Makevars
gettext-tools/examples/hello-c++-kde/po/Makevars
gettext-tools/examples/hello-c++-qt/po/Makefile.am
gettext-tools/examples/hello-c++-wxwidgets/po/Makefile.am
gettext-tools/examples/hello-c++/po/Makevars
gettext-tools/examples/hello-c++20/po/Makevars
gettext-tools/examples/hello-c-gnome2/po/Makevars
gettext-tools/examples/hello-c-gnome3/po/Makevars
gettext-tools/examples/hello-c-http/po/Makevars
gettext-tools/examples/hello-c/po/Makevars
gettext-tools/examples/hello-clisp/po/Makefile.am
gettext-tools/examples/hello-csharp-forms/po/Makefile.am
gettext-tools/examples/hello-csharp/po/Makefile.am
gettext-tools/examples/hello-d/po/Makefile.am
gettext-tools/examples/hello-gawk/po/Makefile.am
gettext-tools/examples/hello-go-http/po/Makefile.am
gettext-tools/examples/hello-go/po/Makefile.am
gettext-tools/examples/hello-guile/po/Makefile.am
gettext-tools/examples/hello-java-awt/po/Makefile.am
gettext-tools/examples/hello-java-qtjambi/po/Makefile.am
gettext-tools/examples/hello-java-swing/po/Makefile.am
gettext-tools/examples/hello-java/po/Makefile.am
gettext-tools/examples/hello-librep/po/Makefile.am
gettext-tools/examples/hello-modula2/po/Makefile.am
gettext-tools/examples/hello-objc-gnome2/po/Makevars
gettext-tools/examples/hello-objc-gnustep/po/GNUmakefile
gettext-tools/examples/hello-objc/po/Makevars
gettext-tools/examples/hello-ocaml/po/Makefile.am
gettext-tools/examples/hello-pascal/po/Makefile.am
gettext-tools/examples/hello-perl/po/Makefile.am
gettext-tools/examples/hello-php/po/Makefile.am
gettext-tools/examples/hello-python/po/Makefile.am
gettext-tools/examples/hello-ruby/po/Makefile.am
gettext-tools/examples/hello-rust/po/Makefile.am
gettext-tools/examples/hello-sh/po/Makefile.am
gettext-tools/examples/hello-smalltalk/po/Makefile.am
gettext-tools/examples/hello-tcl-tk/po/Makefile.am
gettext-tools/examples/hello-tcl/po/Makefile.am
gettext-tools/examples/hello-ycp/po/Makefile.am
gettext-tools/examples/po/Makefile.am
gettext-tools/examples/po/mmsmallpo.sh
gettext-tools/po/Makevars
gettext-tools/po/Makevars.template

index 3d67145d369a5ed4d045d1c229317c471405b425..f0f6c678e1b53e0221c8c6b86a2a3f998183fbc9 100644 (file)
@@ -901,6 +901,7 @@ core
 /gettext-tools/doc/gettext.pgs
 /gettext-tools/doc/gettext.vr
 /gettext-tools/doc/gettext.vrs
+/gettext-tools/examples/po/*.gpo
 /gettext-tools/libgettextpo/config.h
 /gettext-tools/libgettextpo/alloca.h
 /gettext-tools/libgettextpo/assert.h
index a0fc0c7c80418c96e437d5634a6cdcf452fe4d88..b10de4ac949f05191bc2c6fe2fb24c1ad9d544e8 100644 (file)
@@ -171,31 +171,22 @@ We assume that the following environment variables are set:
          https://translationproject.org/latest/gettext-runtime/
   Optionally merge:
     cd gettext-runtime/po
-    make update-po
-    cd new
-    for f in *.po; do msgmerge --update --lang=${f%.po} --previous --width=80 $f ../gettext-runtime.pot; done
-    mv *.po ../
-    cd ..; rm -rf new
+    mv new/*.po .
+    rm -rf new
 
     wget --mirror --level=1 -nd -nv -A.po -P gettext-tools/po/new \
          https://translationproject.org/latest/gettext-tools/
   Optionally merge:
     cd gettext-tools/po
-    make update-po
-    cd new
-    for f in *.po; do msgmerge --update --lang=${f%.po} --previous --width=80 $f ../gettext-tools.pot; done
-    mv *.po ../
-    cd ..; rm -rf new
+    mv new/*.po .
+    rm -rf new
 
     wget --mirror --level=1 -nd -nv -A.po -P gettext-tools/examples/po/new \
          https://translationproject.org/latest/gettext-examples/
   Optionally merge:
     cd gettext-tools/examples/po
-    make update-po
-    cd new
-    for f in *.po; do msgmerge --update --lang=${f%.po} --previous --width=80 $f ../gettext-examples.pot; done
-    mv *.po ../
-    cd ..; rm -rf new
+    mv new/*.po .
+    rm -rf new
 
   Adjust LINGUAS files if any of the languages has been added or
   removed since the last release.  Commit the changes.
diff --git a/NEWS b/NEWS
index bb7c4dc778bd851f4c9ee71bda5847e94158dfb7..3b192432f49e3b627a0f98945d09c7da777908e5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,26 @@
-Version 0.27 - October 2025
+Version 1.0 - October 2025
+
+# Improvements for maintainers and distributors:
+  * In a po/ directory, the PO files are now exactly those that the
+    translators submitted or committed in version control, or a
+    translation project's daemon committed on behalf of the translators.
+    They are no longer regularly updated with respect to the POT file
+    in the same directory.
+
+    The advantage for maintainers is that the maintainer may commit the
+    PO files in version control, without getting
+      - lots of modified files shown by "git status",
+      - frequent merge conflicts when merging between branches,
+      - a voluminous version control history.
+
+    The advantage for distributors is that the role of files in a
+    release tarball are clearer: The PO files are source code, whereas
+    the POT file and the *.gmo files are generated files.
+
+    ATTENTION translators!
+    Translators who work directly on a package's source code (without
+    going through a translation project) now need to run "msginit"
+    before starting work on a PO file.
 
 # Improvements for translators:
   * msginit:
index c4a828b0741d9f71e444d47d7b304c0b4f94c62d..f0ef23ae1ae87bb1c1bc7b754aeb4e2c48558fad 100644 (file)
@@ -70,7 +70,6 @@ XGETTEXT_no = @XGETTEXT@
 XGETTEXT_yes = @XGETTEXT_015@
 XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT))
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -91,8 +90,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -131,11 +128,6 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-POFILESDEPS_ = $(srcdir)/$(DOMAIN).pot
-POFILESDEPS_yes = $(POFILESDEPS_)
-POFILESDEPS_no =
-POFILESDEPS = $(POFILESDEPS_$(PO_DEPENDS_ON_POT))
-
 DISTFILESDEPS_ = update-po
 DISTFILESDEPS_yes = $(DISTFILESDEPS_)
 DISTFILESDEPS_no =
@@ -148,8 +140,63 @@ all: all-@USE_NLS@
 
 
 .SUFFIXES:
-.SUFFIXES: .po .gmo .nop .po-create .po-update
+.SUFFIXES: .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -160,10 +207,16 @@ all: all-@USE_NLS@
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -200,8 +253,12 @@ CHECK_MACRO_VERSION = \
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        @$(CHECK_MACRO_VERSION)
        test ! -f $(srcdir)/$(DOMAIN).pot || \
@@ -288,27 +345,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS) $(srcdir)/POTFILES.in
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(POFILESDEPS)
-       @test -f $(srcdir)/$(DOMAIN).pot || $(MAKE) $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         if test "$(PACKAGE)" = "gettext-tools" && test "$(CROSS_COMPILING)" != "yes"; then PATH=`pwd`/../src:$$PATH; fi; \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -445,7 +486,7 @@ install-dvi install-ps install-pdf install-html:
 
 mostlyclean:
        rm -f $(srcdir)/stamp-poT
-       rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+       rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
        rm -fr *.o
 
 clean: mostlyclean
@@ -493,9 +534,11 @@ dist2: $(srcdir)/stamp-po $(DISTFILES)
          fi; \
        done
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -505,42 +548,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       if test "$(PACKAGE)" = "gettext-tools" && test "$(CROSS_COMPILING)" != "yes"; then PATH=`pwd`/../src:$$PATH; fi; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 3cd4ded67b6029b98f94a62fdfb3356bc1af538c..bf501d01a95648f20b6498b2e68263bf3a9f2065 100644 (file)
@@ -72,12 +72,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index 7b31eeceb57f437c6c2ca5a8189f6a08295cd62c..71b55d88ae5fcee2ff76d1b4a00084d4058f0da5 100644 (file)
@@ -9983,13 +9983,6 @@ $(DOMAIN).pot-update}, and commit it at certain point.
 Special advices for particular version control systems:
 
 @itemize @bullet
-@item
-Recent version control systems, Git for instance, ignore file's
-timestamp.  In that case, PO files can be accidentally updated even if
-a POT file is not updated.  To prevent this, you can set
-@samp{PO_DEPENDS_ON_POT} variable to @code{no} in the @file{Makevars}
-file and do @code{make update-po} manually.
-
 @item
 Location comments such as @code{#: lib/error.c:116} are sometimes
 annoying, since these comments are volatile and may introduce unwanted
@@ -10016,7 +10009,8 @@ recover the location comments by running @code{msgmerge} again.
 @cindex distribution tarball
 In projects that use GNU @code{automake}, the usual commands for creating
 a distribution tarball, @samp{make dist} or @samp{make distcheck},
-automatically update the PO files as needed.
+automatically update the generated files in the @file{po/} directories
+as needed.
 
 If GNU @code{automake} is not used, the maintainer needs to perform this
 update before making a release:
index c3f465c6825fc1a1d5a5cc56fbf52ae4727db0a3..895aef2ebd37763efde4c4d3b031745ee857db2c 100644 (file)
@@ -82,12 +82,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index c3f465c6825fc1a1d5a5cc56fbf52ae4727db0a3..895aef2ebd37763efde4c4d3b031745ee857db2c 100644 (file)
@@ -82,12 +82,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index 225e74167331e19ef518f81bd5f4bb9be79b3b86..b656a9aa21d92f7cde7cd198dc5b1eeed60bd293 100644 (file)
@@ -78,12 +78,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index 9a0c28404dd5692194d5fbee0eb259e4026aa04a..a405151a0cdc086083a7962194bd22f4e5bec646 100644 (file)
@@ -65,7 +65,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -82,8 +81,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
                fi
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).qm)
@@ -111,8 +108,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).qm)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.qm; done
 
-SUFFIXES = .po .qm .nop .po-create .po-update
+SUFFIXES = .po .qm .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .qm files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .qm files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .qm files, and it would be a bad
+#     idea to include the (generated) .qm files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .qm files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -123,10 +175,16 @@ SUFFIXES = .po .qm .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .qm conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(QMFILES): $(srcdir)/$(DOMAIN).pot
 .po.qm:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -157,8 +215,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(QMFILES)" || $(MAKE) $(QMFILES)
@@ -244,25 +306,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -298,7 +346,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(QMFILES)
@@ -322,9 +370,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -334,41 +384,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(QMFILES)
index 0243bf6be82986e32f87082f4882a2cf37a90cbb..848fd7c5ea56418c6806c19ff2b79206ca6258fe 100644 (file)
@@ -68,7 +68,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -87,8 +86,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -114,8 +111,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -126,10 +178,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -160,8 +218,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -247,25 +309,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -363,7 +411,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -387,9 +435,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -399,41 +449,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 307bf0336ca3176369ba3720d52122b43c967657..e0527a338a4b64f3a0f225205ec02199dde8d34d 100644 (file)
@@ -71,12 +71,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index 307bf0336ca3176369ba3720d52122b43c967657..e0527a338a4b64f3a0f225205ec02199dde8d34d 100644 (file)
@@ -71,12 +71,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index c3f465c6825fc1a1d5a5cc56fbf52ae4727db0a3..895aef2ebd37763efde4c4d3b031745ee857db2c 100644 (file)
@@ -82,12 +82,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index c3f465c6825fc1a1d5a5cc56fbf52ae4727db0a3..895aef2ebd37763efde4c4d3b031745ee857db2c 100644 (file)
@@ -82,12 +82,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index 097db7f958cc1e42df4500f9bc82f318f196456a..62edf52ae993de3bfdb0577eb75b668d9ddb8f3b 100644 (file)
@@ -70,12 +70,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index 097db7f958cc1e42df4500f9bc82f318f196456a..62edf52ae993de3bfdb0577eb75b668d9ddb8f3b 100644 (file)
@@ -70,12 +70,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index bcc190bd58bc06cad89da591620e349c6d01cc4f..ff21c1cd986ce0c2c1e73e248da9ef7db0181364 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 3d2b1934efec02c2d7ab649749cee26189ebb038..e90ade6860786c28c9325fd91cb5325c75aec50b 100644 (file)
@@ -60,7 +60,6 @@ MSGINIT_OPTIONS =
 pkglibdir = $(libdir)/$(PACKAGE)
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -77,8 +76,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
                fi
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang))/$(DOMAIN).resources.dll)
@@ -86,9 +83,9 @@ DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 RESOURCESDLLFILES != tab=`printf '\t'`; \
                      for lang in $(ALL_LINGUAS); do \
                        frobbedlang=`echo $$lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$$/-Latn/' -e 's/@cyrillic$$/-Cyrl/' -e 's/^sr-SP$$/sr-SP-Latn/' -e 's/^uz-UZ$$/uz-UZ-Latn/'`; \
-                       echo 1>&3 "$$frobbedlang/\$$(DOMAIN).resources.dll: $$lang.po"; \
-                       echo 1>&3 "$${tab}@echo \"\$$(MSGFMT) -c --csharp -d \$$(srcdir) -l $$lang \$$(srcdir)/$$lang.po -r \$$(DOMAIN)\"; \\"; \
-                       echo 1>&3 "$${tab}\$$(MSGFMT) -c --csharp -d \"\$$(srcdir)\" -l $$lang \$$(srcdir)/$$lang.po -r \"\$$(DOMAIN)\" || { rm -f \"\$$(srcdir)/$$frobbedlang/\$$(DOMAIN).resources.dll\"; exit 1; }"; \
+                       echo 1>&3 "$$frobbedlang/\$$(DOMAIN).resources.dll: $$lang.po \$$(srcdir)/\$$(DOMAIN).pot"; \
+                       echo 1>&3 "$${tab}@echo \"\$$(MSGMERGE) \$$(MSGMERGE_FOR_MSGFMT_OPTION) -o $$lang.gpo \$$(srcdir)/$$lang.po \$$(srcdir)/\$$(DOMAIN).pot && \$$(MSGFMT) -c --csharp -d \$$(srcdir) -l $$lang $$lang.gpo -r \$$(DOMAIN); rm -f $$lang.gpo\"; \\"; \
+                       echo 1>&3 "$${tab}\$$(MSGMERGE) \$$(MSGMERGE_FOR_MSGFMT_OPTION) -o $$lang.gpo \$$(srcdir)/$$lang.po \$$(srcdir)/\$$(DOMAIN).pot && \$$(MSGFMT) -c --csharp -d \"\$$(srcdir)\" -l $$lang $$lang.gpo -r \"\$$(DOMAIN)\" || { rm -f \"\$$(srcdir)/$$frobbedlang/\$$(DOMAIN).resources.dll\"; exit 1; }; rm -f $$lang.gpo"; \
                        echo $(srcdir)/$$frobbedlang/$(DOMAIN).resources.dll; \
                      done 3> .csharp-rules
 # Include the generated rules that cannot be formulated as a simple rule.
@@ -119,11 +116,65 @@ CATALOGS != for lang in $(INST_LINGUAS); do \
               echo $$lang/$(DOMAIN).resources.dll; \
             done
 
-SUFFIXES = .nop .po-create .po-update
+SUFFIXES = .po .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .resources.dll files appear in release tarballs, because the GNU Coding
+# Standards say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .resources.dll files.  The only way to achieve this is to include
+# them in the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .resources.dll files, and it would
+#     be a bad idea to include the (generated) .resources.dll files without
+#     their corresponding source code. Even if the .po files can be found on
+#     some translation project's site or in some separate git repository, users
+#     and distributors should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .resources.dll files appear in release
-# tarballs.
-# The GNU Coding Standards say in
+# tarballs. The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
 #   "GNU distributions usually contain some files which are not source files
 #    ... . Since these files normally appear in the source directory, they
@@ -132,6 +183,13 @@ SUFFIXES = .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 
 all-local: all-local-@USE_NLS@
 
@@ -150,8 +208,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(RESOURCESDLLFILES)" || $(MAKE) $(RESOURCESDLLFILES)
@@ -237,25 +299,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -296,7 +344,7 @@ DISTCLEANFILES = .csharp-rules
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po
 maintainer-clean-local:
@@ -327,9 +375,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-resourcesdll
 
 # General rule for creating PO files.
@@ -339,41 +389,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-resourcesdll: Makefile $(RESOURCESDLLFILES)
index 3d2b1934efec02c2d7ab649749cee26189ebb038..e90ade6860786c28c9325fd91cb5325c75aec50b 100644 (file)
@@ -60,7 +60,6 @@ MSGINIT_OPTIONS =
 pkglibdir = $(libdir)/$(PACKAGE)
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -77,8 +76,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
                fi
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang))/$(DOMAIN).resources.dll)
@@ -86,9 +83,9 @@ DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 RESOURCESDLLFILES != tab=`printf '\t'`; \
                      for lang in $(ALL_LINGUAS); do \
                        frobbedlang=`echo $$lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$$/-Latn/' -e 's/@cyrillic$$/-Cyrl/' -e 's/^sr-SP$$/sr-SP-Latn/' -e 's/^uz-UZ$$/uz-UZ-Latn/'`; \
-                       echo 1>&3 "$$frobbedlang/\$$(DOMAIN).resources.dll: $$lang.po"; \
-                       echo 1>&3 "$${tab}@echo \"\$$(MSGFMT) -c --csharp -d \$$(srcdir) -l $$lang \$$(srcdir)/$$lang.po -r \$$(DOMAIN)\"; \\"; \
-                       echo 1>&3 "$${tab}\$$(MSGFMT) -c --csharp -d \"\$$(srcdir)\" -l $$lang \$$(srcdir)/$$lang.po -r \"\$$(DOMAIN)\" || { rm -f \"\$$(srcdir)/$$frobbedlang/\$$(DOMAIN).resources.dll\"; exit 1; }"; \
+                       echo 1>&3 "$$frobbedlang/\$$(DOMAIN).resources.dll: $$lang.po \$$(srcdir)/\$$(DOMAIN).pot"; \
+                       echo 1>&3 "$${tab}@echo \"\$$(MSGMERGE) \$$(MSGMERGE_FOR_MSGFMT_OPTION) -o $$lang.gpo \$$(srcdir)/$$lang.po \$$(srcdir)/\$$(DOMAIN).pot && \$$(MSGFMT) -c --csharp -d \$$(srcdir) -l $$lang $$lang.gpo -r \$$(DOMAIN); rm -f $$lang.gpo\"; \\"; \
+                       echo 1>&3 "$${tab}\$$(MSGMERGE) \$$(MSGMERGE_FOR_MSGFMT_OPTION) -o $$lang.gpo \$$(srcdir)/$$lang.po \$$(srcdir)/\$$(DOMAIN).pot && \$$(MSGFMT) -c --csharp -d \"\$$(srcdir)\" -l $$lang $$lang.gpo -r \"\$$(DOMAIN)\" || { rm -f \"\$$(srcdir)/$$frobbedlang/\$$(DOMAIN).resources.dll\"; exit 1; }; rm -f $$lang.gpo"; \
                        echo $(srcdir)/$$frobbedlang/$(DOMAIN).resources.dll; \
                      done 3> .csharp-rules
 # Include the generated rules that cannot be formulated as a simple rule.
@@ -119,11 +116,65 @@ CATALOGS != for lang in $(INST_LINGUAS); do \
               echo $$lang/$(DOMAIN).resources.dll; \
             done
 
-SUFFIXES = .nop .po-create .po-update
+SUFFIXES = .po .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .resources.dll files appear in release tarballs, because the GNU Coding
+# Standards say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .resources.dll files.  The only way to achieve this is to include
+# them in the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .resources.dll files, and it would
+#     be a bad idea to include the (generated) .resources.dll files without
+#     their corresponding source code. Even if the .po files can be found on
+#     some translation project's site or in some separate git repository, users
+#     and distributors should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .resources.dll files appear in release
-# tarballs.
-# The GNU Coding Standards say in
+# tarballs. The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
 #   "GNU distributions usually contain some files which are not source files
 #    ... . Since these files normally appear in the source directory, they
@@ -132,6 +183,13 @@ SUFFIXES = .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 
 all-local: all-local-@USE_NLS@
 
@@ -150,8 +208,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(RESOURCESDLLFILES)" || $(MAKE) $(RESOURCESDLLFILES)
@@ -237,25 +299,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -296,7 +344,7 @@ DISTCLEANFILES = .csharp-rules
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po
 maintainer-clean-local:
@@ -327,9 +375,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-resourcesdll
 
 # General rule for creating PO files.
@@ -339,41 +389,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-resourcesdll: Makefile $(RESOURCESDLLFILES)
index cc988084daf8207975f7c17095ce2795b2f59c89..927f0c921b0161c2878df23fcc6166f8a3aeb50c 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 6f2038ce494957002719acddeda21b791d84bb73..5ddb939fbd075e25d2aa4ac1be70a2b7b577476d 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 4460d506014addc0134eed336a6ac472a939ea60..f106f8cc7c44a47450708700644a800ad47b75ef 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 25470f2143bdf908cd5b29ff3ea64ddf6ecc8a1c..970badb3c70b6a9e4f290a90fe83e757b2cfd882 100644 (file)
@@ -65,7 +65,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -84,8 +83,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -111,8 +108,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -123,10 +175,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -157,8 +215,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -244,25 +306,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -360,7 +408,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -384,9 +432,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -396,41 +446,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 38a52b3502fed4f20efd459fd5a1d0b2f5920aa0..9d7264e30c757ddb1c56ac0ca6df57ee1c657ded 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 3c08f83236dc3e6d04338a23ba4203c33edf6fe3..e4b41b36b87108017778ea891819d873e7c1479f 100644 (file)
@@ -58,7 +58,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGCAT = msgcat
 MSGINIT = msginit
@@ -76,8 +75,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
                fi
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(DOMAIN)_$(lang).properties)
@@ -107,8 +104,64 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(DOMAIN)_$(lang).properties)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $(DOMAIN)_$$lang.properties; done
 
-SUFFIXES = .po .nop .po-create .po-update
+SUFFIXES = .po .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .properties or .class files appear in release tarballs, because the GNU
+# Coding Standards say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .properties or .class files.  The only way to achieve this is to
+# include them in the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .properties or .class files, and
+#     it would be a bad idea to include the (generated) .properties or .class
+#     files without their corresponding source code. Even if the .po files can
+#     be found on some translation project's site or in some separate git
+#     repository, users and distributors should not have to go that far, to hunt
+#     them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .properties or .class files appear
 # in release tarballs. The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -119,6 +172,13 @@ SUFFIXES = .po .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 
 all-local: $(srcdir)/stamp-po
 
@@ -134,8 +194,12 @@ all-local: $(srcdir)/stamp-po
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          $(MAKE) update-properties
@@ -221,25 +285,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -249,7 +299,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 
 MAINTAINERCLEANFILES = \
   $(DOMAIN).pot stamp-po \
@@ -274,9 +324,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-properties
 
 # General rule for creating PO files.
@@ -286,47 +338,11 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 # During .po -> .properties or .class conversion, take into account the most
 # recent changes to the .pot file. This eliminates the need to update the .po
-# files when the .pot file has changed, which would be troublesome if the .po
-# files are put under version control.
+# files when the .pot file has changed (see above).
 
 update-properties: Makefile $(srcdir)/$(DOMAIN).pot $(POFILES)
        @echo "$(MSGINIT) -i $(srcdir)/$(DOMAIN).pot --no-translator -l en --properties-output -o $(srcdir)/$(DOMAIN).properties"; \
index 3c08f83236dc3e6d04338a23ba4203c33edf6fe3..e4b41b36b87108017778ea891819d873e7c1479f 100644 (file)
@@ -58,7 +58,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGCAT = msgcat
 MSGINIT = msginit
@@ -76,8 +75,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
                fi
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(DOMAIN)_$(lang).properties)
@@ -107,8 +104,64 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(DOMAIN)_$(lang).properties)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $(DOMAIN)_$$lang.properties; done
 
-SUFFIXES = .po .nop .po-create .po-update
+SUFFIXES = .po .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .properties or .class files appear in release tarballs, because the GNU
+# Coding Standards say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .properties or .class files.  The only way to achieve this is to
+# include them in the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .properties or .class files, and
+#     it would be a bad idea to include the (generated) .properties or .class
+#     files without their corresponding source code. Even if the .po files can
+#     be found on some translation project's site or in some separate git
+#     repository, users and distributors should not have to go that far, to hunt
+#     them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .properties or .class files appear
 # in release tarballs. The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -119,6 +172,13 @@ SUFFIXES = .po .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 
 all-local: $(srcdir)/stamp-po
 
@@ -134,8 +194,12 @@ all-local: $(srcdir)/stamp-po
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          $(MAKE) update-properties
@@ -221,25 +285,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -249,7 +299,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 
 MAINTAINERCLEANFILES = \
   $(DOMAIN).pot stamp-po \
@@ -274,9 +324,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-properties
 
 # General rule for creating PO files.
@@ -286,47 +338,11 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 # During .po -> .properties or .class conversion, take into account the most
 # recent changes to the .pot file. This eliminates the need to update the .po
-# files when the .pot file has changed, which would be troublesome if the .po
-# files are put under version control.
+# files when the .pot file has changed (see above).
 
 update-properties: Makefile $(srcdir)/$(DOMAIN).pot $(POFILES)
        @echo "$(MSGINIT) -i $(srcdir)/$(DOMAIN).pot --no-translator -l en --properties-output -o $(srcdir)/$(DOMAIN).properties"; \
index 3c08f83236dc3e6d04338a23ba4203c33edf6fe3..e4b41b36b87108017778ea891819d873e7c1479f 100644 (file)
@@ -58,7 +58,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGCAT = msgcat
 MSGINIT = msginit
@@ -76,8 +75,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
                fi
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(DOMAIN)_$(lang).properties)
@@ -107,8 +104,64 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(DOMAIN)_$(lang).properties)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $(DOMAIN)_$$lang.properties; done
 
-SUFFIXES = .po .nop .po-create .po-update
+SUFFIXES = .po .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .properties or .class files appear in release tarballs, because the GNU
+# Coding Standards say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .properties or .class files.  The only way to achieve this is to
+# include them in the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .properties or .class files, and
+#     it would be a bad idea to include the (generated) .properties or .class
+#     files without their corresponding source code. Even if the .po files can
+#     be found on some translation project's site or in some separate git
+#     repository, users and distributors should not have to go that far, to hunt
+#     them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .properties or .class files appear
 # in release tarballs. The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -119,6 +172,13 @@ SUFFIXES = .po .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 
 all-local: $(srcdir)/stamp-po
 
@@ -134,8 +194,12 @@ all-local: $(srcdir)/stamp-po
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          $(MAKE) update-properties
@@ -221,25 +285,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -249,7 +299,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 
 MAINTAINERCLEANFILES = \
   $(DOMAIN).pot stamp-po \
@@ -274,9 +324,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-properties
 
 # General rule for creating PO files.
@@ -286,47 +338,11 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 # During .po -> .properties or .class conversion, take into account the most
 # recent changes to the .pot file. This eliminates the need to update the .po
-# files when the .pot file has changed, which would be troublesome if the .po
-# files are put under version control.
+# files when the .pot file has changed (see above).
 
 update-properties: Makefile $(srcdir)/$(DOMAIN).pot $(POFILES)
        @echo "$(MSGINIT) -i $(srcdir)/$(DOMAIN).pot --no-translator -l en --properties-output -o $(srcdir)/$(DOMAIN).properties"; \
index 3c08f83236dc3e6d04338a23ba4203c33edf6fe3..e4b41b36b87108017778ea891819d873e7c1479f 100644 (file)
@@ -58,7 +58,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGCAT = msgcat
 MSGINIT = msginit
@@ -76,8 +75,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
                fi
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(DOMAIN)_$(lang).properties)
@@ -107,8 +104,64 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(DOMAIN)_$(lang).properties)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $(DOMAIN)_$$lang.properties; done
 
-SUFFIXES = .po .nop .po-create .po-update
+SUFFIXES = .po .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .properties or .class files appear in release tarballs, because the GNU
+# Coding Standards say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .properties or .class files.  The only way to achieve this is to
+# include them in the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .properties or .class files, and
+#     it would be a bad idea to include the (generated) .properties or .class
+#     files without their corresponding source code. Even if the .po files can
+#     be found on some translation project's site or in some separate git
+#     repository, users and distributors should not have to go that far, to hunt
+#     them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .properties or .class files appear
 # in release tarballs. The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -119,6 +172,13 @@ SUFFIXES = .po .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 
 all-local: $(srcdir)/stamp-po
 
@@ -134,8 +194,12 @@ all-local: $(srcdir)/stamp-po
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          $(MAKE) update-properties
@@ -221,25 +285,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -249,7 +299,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 
 MAINTAINERCLEANFILES = \
   $(DOMAIN).pot stamp-po \
@@ -274,9 +324,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-properties
 
 # General rule for creating PO files.
@@ -286,47 +338,11 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 # During .po -> .properties or .class conversion, take into account the most
 # recent changes to the .pot file. This eliminates the need to update the .po
-# files when the .pot file has changed, which would be troublesome if the .po
-# files are put under version control.
+# files when the .pot file has changed (see above).
 
 update-properties: Makefile $(srcdir)/$(DOMAIN).pot $(POFILES)
        @echo "$(MSGINIT) -i $(srcdir)/$(DOMAIN).pot --no-translator -l en --properties-output -o $(srcdir)/$(DOMAIN).properties"; \
index 03e90b5ab7adfcba965d4baa544bf566b0d6f175..e31baf86a24513a770854b7d958daf541f38cc5f 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index a1282f20d7308158e86467d0be52f582f69ff0a0..2d9eb0b88e6b42430bb44b73fbee0dd4c29fb4e9 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index c3f465c6825fc1a1d5a5cc56fbf52ae4727db0a3..895aef2ebd37763efde4c4d3b031745ee857db2c 100644 (file)
@@ -82,12 +82,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index 5479b2024ab148a7e32a2e794af0ca867fd610d5..eb9ffa6978f9de6ffca1f0b740017a91062c4b8a 100644 (file)
@@ -68,7 +68,6 @@ PACKAGE_VERSION = 0
 
 XGETTEXT = xgettext
 MSGMERGE = msgmerge
-MSGMERGE_UPDATE = msgmerge --update
 MSGMERGE_FOR_MSGFMT_OPTION = --for-msgfmt
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -85,13 +84,19 @@ include LocaleAliases
 
 POTFILES_DEPS = $(foreach file, $(POTFILES), $(top_srcdir)/$(file))
 POFILES = $(foreach lang, $(LINGUAS), $(lang).po)
-UPDATEPOFILES = $(foreach lang, $(LINGUAS), $(lang).po-update)
 DUMMYPOFILES = $(foreach lang, $(LINGUAS), $(lang).nop)
 STRINGSFILES = $(foreach lang, $(LINGUAS), $(top_srcdir)/$(NSLOCALE_$(lang)).lproj/Localizable.strings)
 ENSTRINGSFILES = $(foreach lang, $(ENLINGUAS), $(top_srcdir)/$(NSLOCALE_$(lang)).lproj/Localizable.strings)
 CATALOGS = $(STRINGSFILES) $(ENSTRINGSFILES)
 
-.SUFFIXES: .po .nop .po-create .po-update
+.SUFFIXES: .po .gpo .nop .po-create
+
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $${lang}.po $(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $${lang}.po $(DOMAIN).pot
 
 
 internal-all:: all-local-$(USE_NLS)
@@ -171,29 +176,20 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
-       if test -f $${lang}.po; then \
-         echo "$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-           '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-             $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-           0.1[1-5] | 0.1[1-5].*) \
-             $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-           0.1[6-7] | 0.1[6-7].*) \
-             $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-           *) \
-             $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-         esac; \
+       if test -f "$${lang}.po"; then \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po:
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-strings
 
 # General rule for creating PO files.
@@ -203,37 +199,6 @@ update-po:
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       echo "$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-7] | 0.1[1-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 
index 097db7f958cc1e42df4500f9bc82f318f196456a..62edf52ae993de3bfdb0577eb75b668d9ddb8f3b 100644 (file)
@@ -70,12 +70,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index 6759d699c50223d21099beca0681981d1980cb23..b14be32ef260705eac54b9ff17f7a4bdcc30043c 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 0d0de0720b6b1b5ff78cca003699350b382f7c8f..f9d70377eed54a60cb3fecd70a62b5e808ec7a6d 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 0e3b0ca27fbc27798c3ddb6860388899e9f48367..7dd4265f185bffc51023450d6aa9380ffa2724e9 100644 (file)
@@ -72,7 +72,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -91,8 +90,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -118,8 +115,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -130,10 +182,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -164,8 +222,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -251,25 +313,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -367,7 +415,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -391,9 +439,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -403,41 +453,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index b9cb205d4268e715f8c6f59ac7693a5cf881b887..32e97bf843ee183aea07daab518a57e74fa0fa3d 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index d1d82a688c029abb80fa345075e462913869cb2f..8afec3d0c8b03ef9de5eb345d0d0e5e2e5e34557 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index a5492990f688df2a0a01b167dc0f986f04412a3a..1a20e34d9f24a33313a214f8800211f0458ee357 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 29d4e014afa0762e74e486cdef6a03ab2fd89543..e1e13c25be1a25ec0e97e472ecc4a3d80665be5f 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 131be9267972cc21aab40c60b3f859677feee52e..0b1e69365c73a53ea3d80495c9e705d104d1a650 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index f6cd3e3b6492ccb97f0c235df30fff5bb6d9df9d..f75c386b7a4bcee1716925c004d460fb3f11f228 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index 2eac096975f2fd566203e20122ced5bc594b0f8e..88873929f1fe4dc4f4475f028b4d76f2e2bff25f 100644 (file)
@@ -58,7 +58,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -75,8 +74,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
                fi
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang)).msg)
@@ -84,9 +81,9 @@ DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 MSGFILES != tab=`printf '\t'`; \
             for lang in $(ALL_LINGUAS); do \
               frobbedlang=`echo $$lang | sed -e 's/\..*$$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`; \
-              echo 1>&3 "$$frobbedlang.msg: $$lang.po"; \
-              echo 1>&3 "$${tab}@echo \"\$$(MSGFMT) -c --tcl -d \$$(srcdir) -l $$lang \$$(srcdir)/$$lang.po\"; \\"; \
-              echo 1>&3 "$${tab}\$$(MSGFMT) -c --tcl -d \"\$$(srcdir)\" -l $$lang \$$(srcdir)/$$lang.po || { rm -f \"\$$(srcdir)/$$frobbedlang.msg\"; exit 1; }"; \
+              echo 1>&3 "$$frobbedlang.msg: $$lang.po \$$(srcdir)/\$$(DOMAIN).pot"; \
+              echo 1>&3 "$${tab}@echo \"\$$(MSGMERGE) \$$(MSGMERGE_FOR_MSGFMT_OPTION) -o $$lang.gpo \$$(srcdir)/$$lang.po \$$(srcdir)/\$$(DOMAIN).pot && \$$(MSGFMT) -c --tcl -d \$$(srcdir) -l $$lang $$lang.gpo; rm -f $$lang.gpo\"; \\"; \
+              echo 1>&3 "$${tab}\$$(MSGMERGE) \$$(MSGMERGE_FOR_MSGFMT_OPTION) -o $$lang.gpo \$$(srcdir)/$$lang.po \$$(srcdir)/\$$(DOMAIN).pot && \$$(MSGFMT) -c --tcl -d \"\$$(srcdir)\" -l $$lang $$lang.gpo || { rm -f \"\$$(srcdir)/$$frobbedlang.msg\"; exit 1; }; rm -f $$lang.gpo"; \
               echo $(srcdir)/$$frobbedlang.msg; \
             done 3> .tcl-rules
 # Include the generated rules that cannot be formulated as a simple rule.
@@ -117,8 +114,63 @@ CATALOGS != for lang in $(INST_LINGUAS); do \
               echo $$frobbedlang.msg; \
             done
 
-SUFFIXES = .nop .po-create .po-update
+SUFFIXES = .po .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .msg files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .msg files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .msg files, and it would be a bad
+#     idea to include the (generated) .msg files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .msg files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -129,6 +181,13 @@ SUFFIXES = .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 
 all-local: all-local-@USE_NLS@
 
@@ -147,8 +206,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(MSGFILES)" || $(MAKE) $(MSGFILES)
@@ -234,25 +297,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -290,7 +339,7 @@ DISTCLEANFILES = .tcl-rules
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(MSGFILES)
@@ -314,9 +363,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-msg
 
 # General rule for creating PO files.
@@ -326,41 +377,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-msg: Makefile $(MSGFILES)
index 2eac096975f2fd566203e20122ced5bc594b0f8e..88873929f1fe4dc4f4475f028b4d76f2e2bff25f 100644 (file)
@@ -58,7 +58,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -75,8 +74,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
                fi
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang)).msg)
@@ -84,9 +81,9 @@ DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 MSGFILES != tab=`printf '\t'`; \
             for lang in $(ALL_LINGUAS); do \
               frobbedlang=`echo $$lang | sed -e 's/\..*$$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`; \
-              echo 1>&3 "$$frobbedlang.msg: $$lang.po"; \
-              echo 1>&3 "$${tab}@echo \"\$$(MSGFMT) -c --tcl -d \$$(srcdir) -l $$lang \$$(srcdir)/$$lang.po\"; \\"; \
-              echo 1>&3 "$${tab}\$$(MSGFMT) -c --tcl -d \"\$$(srcdir)\" -l $$lang \$$(srcdir)/$$lang.po || { rm -f \"\$$(srcdir)/$$frobbedlang.msg\"; exit 1; }"; \
+              echo 1>&3 "$$frobbedlang.msg: $$lang.po \$$(srcdir)/\$$(DOMAIN).pot"; \
+              echo 1>&3 "$${tab}@echo \"\$$(MSGMERGE) \$$(MSGMERGE_FOR_MSGFMT_OPTION) -o $$lang.gpo \$$(srcdir)/$$lang.po \$$(srcdir)/\$$(DOMAIN).pot && \$$(MSGFMT) -c --tcl -d \$$(srcdir) -l $$lang $$lang.gpo; rm -f $$lang.gpo\"; \\"; \
+              echo 1>&3 "$${tab}\$$(MSGMERGE) \$$(MSGMERGE_FOR_MSGFMT_OPTION) -o $$lang.gpo \$$(srcdir)/$$lang.po \$$(srcdir)/\$$(DOMAIN).pot && \$$(MSGFMT) -c --tcl -d \"\$$(srcdir)\" -l $$lang $$lang.gpo || { rm -f \"\$$(srcdir)/$$frobbedlang.msg\"; exit 1; }; rm -f $$lang.gpo"; \
               echo $(srcdir)/$$frobbedlang.msg; \
             done 3> .tcl-rules
 # Include the generated rules that cannot be formulated as a simple rule.
@@ -117,8 +114,63 @@ CATALOGS != for lang in $(INST_LINGUAS); do \
               echo $$frobbedlang.msg; \
             done
 
-SUFFIXES = .nop .po-create .po-update
+SUFFIXES = .po .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .msg files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .msg files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .msg files, and it would be a bad
+#     idea to include the (generated) .msg files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .msg files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -129,6 +181,13 @@ SUFFIXES = .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 
 all-local: all-local-@USE_NLS@
 
@@ -147,8 +206,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(MSGFILES)" || $(MAKE) $(MSGFILES)
@@ -234,25 +297,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -290,7 +339,7 @@ DISTCLEANFILES = .tcl-rules
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(MSGFILES)
@@ -314,9 +363,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-msg
 
 # General rule for creating PO files.
@@ -326,41 +377,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-msg: Makefile $(MSGFILES)
index 657a3345739979ef761f95ad2b6da417169aac3b..b14304827b21e8e61b98984fddcdf6bd87d40dbb 100644 (file)
@@ -62,7 +62,6 @@ MSGMERGE_OPTIONS =
 MSGINIT_OPTIONS =
 
 MSGMERGE = @MSGMERGE@
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
 MSGINIT = msginit
 MSGCONV = msgconv
@@ -81,8 +80,6 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
 GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
@@ -108,8 +105,63 @@ INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \
 # This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo)
 CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done
 
-SUFFIXES = .po .gmo .nop .po-create .po-update
+SUFFIXES = .po .gmo .gpo .nop .po-create
 
+# Which files appear in release tarballs?
+#
+# The .gmo files appear in release tarballs, because the GNU Coding Standards
+# say in
+# <https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html>:
+#   "The configure script and the Makefile rules for building and installation
+#    should not use any utilities directly except these:
+#      awk ... true"
+# and 'msgfmt' is not in this list.  In other words, when a user - who does not
+# have the GNU gettext tools installed - does "make && make install", it should
+# install the .gmo files.  The only way to achieve this is to include them in
+# the release tarballs.
+#
+# The .pot file appears in release tarballs, because it is needed when a
+# translator runs "msginit" to start working on a PO file or when a web-based
+# PO editor prepares the initial PO file for a translator.  Translators and
+# translation projects should not have to run 'xgettext' on some source code;
+# that's not their business, and they would not be in a good position to deal
+# with errors.
+#
+# The .po files appear in release tarballs, because
+#   - They are part of the source code of the .gmo files, and it would be a bad
+#     idea to include the (generated) .gmo files without their corresponding
+#     source code. Even if the .po files can be found on some translation
+#     project's site or in some separate git repository, users and distributors
+#     should not have to go that far, to hunt them down.
+#   - The .po file is needed when a translator runs "msginit" to continue
+#     working on a PO file (in packages that do not use a web-based translation
+#     project).
+# These .po files are those that the translators submitted or committed in
+# version control, or a translation project's daemon committed on behalf of the
+# translators.
+# Up until 2025, we included the *merged* .po files in the release tarballs.
+# These merged .po files, that we now name .gpo files in this Makefile,
+# are neither source code nor entirely generated files: They are a mix of
+# source code (from the translators) and generated parts (from the .pot file).
+# This caused two problems:
+#   * Regarding the tarballs: They are "non-source" files in the sense of
+#     <https://www.gnu.org/prep/standards/html_node/Releases.html>.
+#     Distributors who want to make sure that they rebuild everything from
+#     source had a problem here.
+#     Also, small changes in the package caused massive line number changes
+#     in the .po files.
+#   * Regarding version control:
+#     Packages that put the .po files under version control had changes in
+#     all .po files nearly each time "make dist" was invoked. Leading to
+#       - Lots of modified files shown by "git status",
+#       - Frequent merge conflicts when merging between branches,
+#       - A voluminous version control history.
+#     Whereas packages that do not put the .po files under version control
+#     had to fetch them from somewhere (usually a translation project),
+#     meaning that an 'autopull.sh' step was needed before the 'autogen.sh'
+#     step of the package's build system.
+# Instead, now, we include the original .po files in the release tarballs.
+#
 # The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
 # The GNU Coding Standards say in
 # <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
@@ -120,10 +172,16 @@ SUFFIXES = .po .gmo .nop .po-create .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file (mostly for debugging purposes).
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 # During .po -> .gmo conversion, take into account the most recent changes to
 # the .pot file. This eliminates the need to update the .po files when the
-# .pot file has changed, which would be troublesome if the .po files are put
-# under version control.
+# .pot file has changed (see above).
 $(GMOFILES): $(srcdir)/$(DOMAIN).pot
 .po.gmo:
        @lang=`echo $* | sed -e 's,.*/,,'`; \
@@ -154,8 +212,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        test ! -f $(srcdir)/$(DOMAIN).pot || \
          test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@@ -241,25 +303,11 @@ $(DOMAIN).pot-update: $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
+# This target attempts to build a PO file.
+$(POFILES):
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        if test -f "$(srcdir)/$${lang}.po"; then \
-         test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-         echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-         cd $(srcdir) \
-           && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-                  '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                    $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[1-5] | 0.1[1-5].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
-                  0.1[6-7] | 0.1[6-7].*) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
-                  *) \
-                    $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
-                esac; \
-              }; \
+         : ; \
        else \
          $(MAKE) $${lang}.po-create; \
        fi
@@ -357,7 +405,7 @@ html ID:
 
 MOSTLYCLEANFILES =
 MOSTLYCLEANFILES += stamp-poT
-MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.gpo *.new.po
 MOSTLYCLEANFILES += *.o
 
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES)
@@ -381,9 +429,11 @@ distdir1:
          esac; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
        $(MAKE) update-gmo
 
 # General rule for creating PO files.
@@ -393,41 +443,6 @@ update-po: Makefile
        echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
        exit 1
 
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       cd $(srcdir); \
-       if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
-              '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \
-                $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[1-5] | 0.1[1-5].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              0.1[6-7] | 0.1[6-7].*) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-              *) \
-                $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
-            esac; \
-          }; then \
-         if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-           rm -f $$tmpdir/$$lang.new.po; \
-         else \
-           if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-             :; \
-           else \
-             echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-             exit 1; \
-           fi; \
-         fi; \
-       else \
-         echo "msgmerge for $$lang.po failed!" 1>&2; \
-         rm -f $$tmpdir/$$lang.new.po; \
-       fi
-
 $(DUMMYPOFILES):
 
 update-gmo: Makefile $(GMOFILES)
index e440e3684d2823bd884627eae3453ed68a09192a..4b18600190460b93d9eb80804dd8bbc5333b7f8d 100644 (file)
@@ -164,10 +164,9 @@ EXTRA_LOCALE_CATEGORIES =
 # These options get passed to msgmerge.
 # Useful options are in particular:
 #   --previous            to keep previous msgids of translated messages
-MSGMERGE_OPTIONS =
+MSGMERGE_OPTIONS = --no-fuzzy-matching --quiet
 
 MSGMERGE = msgmerge
-MSGMERGE_UPDATE = @MSGMERGE@ --update
 MSGINIT = msginit
 MSGCONV = msgconv
 MSGFILTER = msgfilter
@@ -183,12 +182,12 @@ ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \
                fi
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
 POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done
-# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
-UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done
+# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).gpo)
+GPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.gpo; done
 # This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
 DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done
 
-SUFFIXES = .po .nop .po-update
+SUFFIXES = .po .gpo
 
 # The .pot file, stamp-po, and .po files appear in release tarballs.
 # The GNU Coding Standards say in
@@ -200,6 +199,14 @@ SUFFIXES = .po .nop .po-update
 #    source directory."
 # Therefore we put these files in the source directory, not the build directory.
 
+# This target creates a merged PO file.
+$(GPOFILES): $(srcdir)/$(DOMAIN).pot
+.po.gpo:
+       @lang=`echo $* | sed -e 's,.*/,,'`; \
+       echo "rm -f $${lang}.gpo && $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot"; \
+       rm -f $${lang}.gpo && \
+       $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $${lang}.gpo $(srcdir)/$${lang}.po $(srcdir)/$(DOMAIN).pot
+
 
 all-local: all-local-@USE_NLS@
 
@@ -218,8 +225,12 @@ all-local-no:
 # file is not under version control, "make" will update the $(DOMAIN).pot and
 # the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
 # timestamp would not be necessary if updating the $(CATALOGS) would always
-# touch them; however, the rule for $(POFILES) has been designed to not touch
-# files that don't need to be changed.
+# touch them; however, the rule for $(DOMAIN).pot-update has been designed to
+# not touch $(srcdir)/$(DOMAIN).pot if it doesn't need to be changed.
+#
+# Note: The name 'stamp-po' is a bit misleading. It does *not* designate a
+# timestamp for the *.po files. Rather it is a timestamp for all generated
+# files in this directory.
 $(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
        @test ! -f $(srcdir)/$(DOMAIN).pot || { \
          echo "touch $(srcdir)/stamp-po" && \
@@ -394,14 +405,6 @@ hello-ycp.pot : $(POTFILES_DEPS)
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
-# This target rebuilds a PO file if $(DOMAIN).pot has changed.
-# Note that a PO file is not touched if it doesn't need to be changed.
-$(POFILES): $(srcdir)/$(DOMAIN).pot
-       @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
-       cd $(srcdir) && $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot
-
 
 html ID:
 
@@ -410,6 +413,8 @@ MOSTLYCLEANFILES += stamp-poT
 MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
 MOSTLYCLEANFILES += *.o
 
+DISTCLEANFILES = $(GPOFILES)
+
 MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(SMALLPOTS)
 
 EXTRA_DIST = remove-potcdate.sed xsmallpot.sh mmsmallpo.sh LINGUAS \
@@ -425,36 +430,16 @@ distdir1: $(srcdir)/$(DOMAIN).pot
          done; \
        fi
 
+# This rule updates all generated files in this directory.
+# Note: The name 'update-po' is a bit misleading. It does *not* modify the *.po
+# files. But we can't rename it easily, because it's a documented target.
 update-po: Makefile
        $(MAKE) $(DOMAIN).pot-update
-       test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
-
-# General rule for updating PO files.
-
-.nop.po-update:
-       @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
-       tmpdir=`pwd`; \
-       echo "$$lang:"; \
-       test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
-       echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
-       (cd $(srcdir) && \
-        if $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $$lang.po $(DOMAIN).pot -o $$tmpdir/$$lang.new.po; then \
-          if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
-            rm -f $$tmpdir/$$lang.new.po; \
-          else \
-            if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
-              :; \
-            else \
-              echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
-              exit 1; \
-            fi; \
-          fi; \
-        else \
-          echo "msgmerge for $$lang.po failed!" 1>&2; \
-          rm -f $$tmpdir/$$lang.new.po; \
-          exit 1; \
-        fi) && \
-       $(MAKE) $(SMALLPOFILES_FOR_lang) LL=$$lang
+       test -z "$(GPOFILES)" || $(MAKE) $(GPOFILES)
+       for file in $(GPOFILES); do \
+         lang=`echo $$file | sed -e 's,.*/,,' -e 's,\.gpo$$,,'`; \
+         $(MAKE) $(SMALLPOFILES_FOR_lang) LL=$$lang || exit 1; \
+       done
 
 $(DUMMYPOFILES):
 
index c268684f1192c6ebe4efc31fa2d8c859b618412c..ebf6be2ebcba95a5657d66b658ef75e191857aa4 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (C) 2003-2004, 2009 Free Software Foundation, Inc.
+# Copyright (C) 2003-2025 Free Software Foundation, Inc.
 #
 # 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
@@ -23,7 +23,7 @@ test $# = 2  || { echo "Usage: mmsmallpo.sh hello-foo ll" 1>&2; exit 1; }
 directory=$1
 language=$2
 
-msgmerge --quiet --force-po $language.po $directory.pot -o - | \
+msgmerge --quiet --force-po $language.gpo $directory.pot -o - | \
 msgattrib --no-obsolete | \
 sed -e "s, $directory/, ,g" | sed -e "s,gettext-examples,$directory," | \
 sed -e '/^"POT-Creation-Date: .*"$/{
index 3df320a358f8c83085cd218b8e86dd3f0eb20d38..d612bb0dbb04ef3ad7e085036a55075f33e4bfe0 100644 (file)
@@ -77,12 +77,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained
index d1532a95c9f28a3187c1a33b375100d80d96b1c5..e2117b867c2f8dbd3defe3bd0829428098a42d0d 100644 (file)
@@ -69,12 +69,6 @@ MSGMERGE_OPTIONS =
 # MSGINIT_OPTIONS.
 MSGINIT_OPTIONS =
 
-# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
-# has changed.  Possible values are "yes" and "no".  Set this to no if
-# the POT file is checked in the repository and the version control
-# program ignores timestamps.
-PO_DEPENDS_ON_POT = yes
-
 # This tells whether or not to forcibly update $(DOMAIN).pot and
 # regenerate PO files on "make dist".  Possible values are "yes" and
 # "no".  Set this to no if the POT file and PO files are maintained