chiark / gitweb /
i18n: po4a: Introduce machinery
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 3 Oct 2018 23:56:49 +0000 (00:56 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 4 Oct 2018 01:01:52 +0000 (02:01 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
po4a/.gitignore [new file with mode: 0644]
po4a/Makefile [new file with mode: 0644]
po4a/install-documents [new file with mode: 0755]
po4a/list-documents [new file with mode: 0755]

diff --git a/po4a/.gitignore b/po4a/.gitignore
new file mode 100644 (file)
index 0000000..e640b7e
--- /dev/null
@@ -0,0 +1,5 @@
+translated
+preview.*
+.*.po4a.cfg
+.*.translated
+*.tmp
diff --git a/po4a/Makefile b/po4a/Makefile
new file mode 100644 (file)
index 0000000..3a3310d
--- /dev/null
@@ -0,0 +1,131 @@
+# dgit document translation machinery
+#
+# Translators: there is no need to look at this file.  It contains
+# complicated machinery which you do not need to understand :-).
+# See po/README instead.
+
+# Copyright (C)2018 Ian Jackson
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# ----- devel docs (translators, pleaee ignore all this) -----
+#
+# We use po4a for everything.
+#
+# po4a is nicely automatic for all the po handling, and the config
+# file makes nice documentation, but it really really likes to dirty
+# the tree.  And we want to automatically list the documents and the
+# translation languages which it doesn't make easy.
+#
+# The approach I have chosen is as follows:
+#
+# po4a.cfg
+#
+#   This is autogenerated.  But also, we invite translators to add
+#   their own language to it.  The resulting merge
+#   conflict/discrepancy will be just an alphabetical ordering
+#   discrepancy, since our generation script scans the available po
+#   files.
+#
+#   Generation is done by a shell script, ./list-documents.
+#
+#   make targets:  po4a.cfg           # many others imply this
+#                  po4a.cfg.check     # fails if out of date
+#
+# *.pot, *.po
+#
+#   As far as translators are concerned, generated and maintained by
+#   po4a and committed to git.  As for the developers, we update this
+#   occasionally just by running po4a.
+#
+#   make targets:  default           } mean
+#                  pofiles           }  the same
+#
+# Translations for translators:
+#
+#   make targets:  preview.LANG
+#                  translated
+#
+# Translated document source-language files (eg, translated pod):
+#
+#   Like with normal po things, the tools don't like to generate
+#   output without updating (dirtying) the .po files.  But with po4a
+#   this is really hard to avoid.  So we use a linkfarming technique.
+#
+#   make targets:  translated-only
+#
+# Translated output files (roff format, from pod2man):
+#
+#   We have sort of lost the usual make rule information by now
+#   about targets and what to build.  Only po4a knows which
+#   translated files are supposed to exist.  So we have a shell
+#   script which reuses the top-level Makefile to run pod2man
+#   where appropriate, and generate a further even-more-output-ish
+#   tree.
+#
+#   make targets:  install
+
+
+default: pofiles
+
+all: translated-always
+
+pofiles: po4a.cfg
+       po4a --no-translations $<
+
+e=set -e; exec >$@.tmp
+f=mv -f $@.tmp $@
+o= >$@.tmp && $f
+
+S=@
+# Set S='' to see commands being run
+
+translated: po4a.cfg
+       po4a $<
+
+po4a.cfg: list-documents
+       ./$< $o
+
+po4a.cfg.check: list-documents
+       ./$< >$@.tmp
+       diff po4a.cfg $@.tmp
+
+t = ../.po4a.translated-only
+p = ../po4a
+
+translated-only: po4a.cfg
+       rm -rf $t && mkdir $t
+       cd $t && ln -s $p/*.po $p/*.pot $p/po4a.cfg .
+       cd $t && po4a po4a.cfg
+       ! test -d $t/translated || \
+       cp -al --remove-destination $t/translated .
+
+.po4a.%.cfg: po4a.cfg Makefile
+       $S perl -p -e 's{^(\[po4a_langs\]).*}{$$1 $*};' \
+               -e 's{:translated/man}{:.$*.translated/man}' \
+               $< $o
+
+.PRECIOUS: .po4a.%.cfg
+
+preview.%: .po4a.%.cfg
+       $S po4a $<
+       $S ./install-documents >/dev/null .$*.translated $@
+       @ echo '# runes to preview the various final tranlated manpages:'
+       $S find $@ -type f -printf 'man -l %p\n'
+
+# We can't really use timestamps to drive po4a
+.PHONY: preview.% translated
+
+install: translated-only
+       ./install-documents translated $(DESTDIR)
diff --git a/po4a/install-documents b/po4a/install-documents
new file mode 100755 (executable)
index 0000000..138c88e
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/bash
+set -e
+
+srcdir=$1; shift
+destdir=$1; shift
+
+mkdir -p "$srcdir"
+
+docs=( $( ( cd "$srcdir" && find man -type f ) | sed 's#\.pod$##' ) )
+
+echo ${docs[*]}
+
+x () {
+       echo "+ $*";
+       "$@"
+}
+
+if [ "${#docs}" = 0 ]; then exit 0; fi
+
+x ${MAKE-make} -s -C "$srcdir" -f ../../Makefile ${docs[@]}
+
+mandest=$destdir/usr/share
+
+for f in "${docs[@]}"; do
+       mkdir -p "$mandest/${f%/*}"
+       x cp "$srcdir/$f" "$mandest/$f"
+done
diff --git a/po4a/list-documents b/po4a/list-documents
new file mode 100755 (executable)
index 0000000..ca17ec5
--- /dev/null
@@ -0,0 +1,45 @@
+#!/bin/bash
+set -e
+set -o pipefail
+
+fail () { "echo >&2 $0: $*"; exit 1; }
+
+langs=( $( { ! test -f *.po || ls *.po; } \
+          | sed 's#\.po$##; s#.*\.##' \
+           | LC_COLLATE=C.UTF-8 sort -u) )
+
+cat <<END
+[po4a_langs] $langs
+# ^ add your language here (separate with spaces)
+
+# Do not edit the rest of this file.  It is automatically maintained.
+[options] opt:"-MUTF-8" opt:"-k50"
+[po4a_paths] \$master.pot \$lang:\$master.\$lang.po
+END
+
+for manpage in $(cd .. && env -u MAKELEVEL -u MAKEFLAGS make list-manpages); do
+       manpage_done=false
+
+       try_manpage () {
+               if $manpage_done; then return; fi
+
+               type=$1; ext=$2
+
+               src=../$manpage$ext
+               if ! [ -f $src ]; then return; fi
+
+               section=${manpage##*.}
+               base=${manpage%.*}
+               page=$base.$section 
+
+               cat <<END
+[type: $type] $src \$lang:translated/man/\$lang/man$section/$page$ext master:file=${base}_${section}
+END
+
+               manpage_done=true
+       }               
+
+       try_manpage pod .pod
+       try_manpage man ''
+       $manpage_done || fail "no source for $manpage"
+done