r3917 - in trunk: . po
- From: timj svn gnome org
- To: svn-commits-list gnome org
- Subject: r3917 - in trunk: . po
- Date: Thu, 28 Sep 2006 13:47:02 -0400 (EDT)
Author: timj
Date: 2006-09-28 13:46:36 -0400 (Thu, 28 Sep 2006)
New Revision: 3917
Added:
trunk/acintltool.m4
trunk/intltool-extract.in
trunk/intltool-merge.in
trunk/intltool-update.in
trunk/po/Makefile.intltool
Removed:
trunk/po/intltool-scm.diff
Modified:
trunk/ChangeLog
trunk/autogen.sh
trunk/configure.in
trunk/po/intltool-scm-35.diff
Log:
Thu Sep 28 19:35:04 2006 Tim Janik <timj gtk org>
* autogen.sh: skip checking and running intltool.
generate po/Makefile.in.in from po/Makefile.intltool.
* configure.in: read acintltool.m4, call IT_PROG_INTLTOOL.
* po/intltool-scm-35.diff: fixes for stock intltool-0.35.0.
* po/Makefile.intltool: added the Makefile.in.in from stock intltool-0.35.0.
* acintltool.m4: added the intltool.m4 from stock intltool-0.35.0.
* intltool-merge.in:
* intltool-update.in:
* intltool-extract.in: added from stock intltool-0.35.0.
* po/intltool-scm.diff: unused, removed.
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2006-09-27 23:27:03 UTC (rev 3916)
+++ trunk/ChangeLog 2006-09-28 17:46:36 UTC (rev 3917)
@@ -1,3 +1,22 @@
+Thu Sep 28 19:35:04 2006 Tim Janik <timj gtk org>
+
+ * autogen.sh: skip checking and running intltool.
+ generate po/Makefile.in.in from po/Makefile.intltool.
+
+ * configure.in: read acintltool.m4, call IT_PROG_INTLTOOL.
+
+ * po/intltool-scm-35.diff: fixes for stock intltool-0.35.0.
+
+ * po/Makefile.intltool: added the Makefile.in.in from stock intltool-0.35.0.
+
+ * acintltool.m4: added the intltool.m4 from stock intltool-0.35.0.
+
+ * intltool-merge.in:
+ * intltool-update.in:
+ * intltool-extract.in: added from stock intltool-0.35.0.
+
+ * po/intltool-scm.diff: unused, removed.
+
Wed Sep 27 21:33:48 2006 Stefan Westerfeld <stefan space twc de>
* slowtests/testresampler.cc: Trimmed default output of "filter-impl"
Added: trunk/acintltool.m4
===================================================================
--- trunk/acintltool.m4 2006-09-27 23:27:03 UTC (rev 3916)
+++ trunk/acintltool.m4 2006-09-28 17:46:36 UTC (rev 3917)
@@ -0,0 +1,204 @@
+## intltool.m4 - Configure intltool for the target system. -*-Shell-script-*-
+## Copyright (C) 2001 Eazel, Inc.
+## Author: Maciej Stachowiak <mjs noisehavoc org>
+## Kenneth Christiansen <kenneth gnu org>
+##
+## 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 2 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, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##
+## As a special exception to the GNU General Public License, if you
+## distribute this file as part of a program that contains a
+## configuration script generated by Autoconf, you may include it under
+## the same distribution terms that you use for the rest of that program.
+
+dnl IT_PROG_INTLTOOL([MINIMUM-VERSION], [no-xml])
+# serial 35 IT_PROG_INTLTOOL
+AC_DEFUN([IT_PROG_INTLTOOL],
+[AC_PREREQ([2.50])dnl
+
+case "$am__api_version" in
+ 1.[01234])
+ AC_MSG_ERROR([Automake 1.5 or newer is required to use intltool])
+ ;;
+ *)
+ ;;
+esac
+
+if test -n "$1"; then
+ AC_MSG_CHECKING(for intltool >= $1)
+
+ INTLTOOL_REQUIRED_VERSION_AS_INT=`echo $1 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'`
+ INTLTOOL_APPLIED_VERSION=`awk -F\" '/\\$VERSION / { print $ 2; }' ${ac_aux_dir}/intltool-update.in`
+ [INTLTOOL_APPLIED_VERSION_AS_INT=`awk -F\" '/\\$VERSION / { split($ 2, VERSION, "."); print VERSION[1] * 1000 + VERSION[2] * 100 + VERSION[3];}' ${ac_aux_dir}/intltool-update.in`
+ ]
+ AC_MSG_RESULT([$INTLTOOL_APPLIED_VERSION found])
+ test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" ||
+ AC_MSG_ERROR([Your intltool is too old. You need intltool $1 or later.])
+fi
+
+ INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_PROP_RULE='%.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -p $(top_srcdir)/po $< [$]@'
+ INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< [$]@'
+ INTLTOOL_XAM_RULE='%.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_KBD_RULE='%.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_SCHEMAS_RULE='%.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_THEME_RULE='%.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+ INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+
+AC_SUBST(INTLTOOL_DESKTOP_RULE)
+AC_SUBST(INTLTOOL_DIRECTORY_RULE)
+AC_SUBST(INTLTOOL_KEYS_RULE)
+AC_SUBST(INTLTOOL_PROP_RULE)
+AC_SUBST(INTLTOOL_OAF_RULE)
+AC_SUBST(INTLTOOL_PONG_RULE)
+AC_SUBST(INTLTOOL_SERVER_RULE)
+AC_SUBST(INTLTOOL_SHEET_RULE)
+AC_SUBST(INTLTOOL_SOUNDLIST_RULE)
+AC_SUBST(INTLTOOL_UI_RULE)
+AC_SUBST(INTLTOOL_XAM_RULE)
+AC_SUBST(INTLTOOL_KBD_RULE)
+AC_SUBST(INTLTOOL_XML_RULE)
+AC_SUBST(INTLTOOL_XML_NOMERGE_RULE)
+AC_SUBST(INTLTOOL_CAVES_RULE)
+AC_SUBST(INTLTOOL_SCHEMAS_RULE)
+AC_SUBST(INTLTOOL_THEME_RULE)
+AC_SUBST(INTLTOOL_SERVICE_RULE)
+
+# Use the tools built into the package, not the ones that are installed.
+AC_SUBST(INTLTOOL_EXTRACT, '$(top_builddir)/intltool-extract')
+AC_SUBST(INTLTOOL_MERGE, '$(top_builddir)/intltool-merge')
+AC_SUBST(INTLTOOL_UPDATE, '$(top_builddir)/intltool-update')
+
+AC_PATH_PROG(INTLTOOL_PERL, perl)
+if test -z "$INTLTOOL_PERL"; then
+ AC_MSG_ERROR([perl not found; required for intltool])
+fi
+if test -z "`$INTLTOOL_PERL -v | fgrep '5.' 2> /dev/null`"; then
+ AC_MSG_ERROR([perl 5.x required for intltool])
+fi
+if test "x$2" != "xno-xml"; then
+ AC_MSG_CHECKING([for XML::Parser])
+ if `$INTLTOOL_PERL -e "require XML::Parser" 2>/dev/null`; then
+ AC_MSG_RESULT([ok])
+ else
+ AC_MSG_ERROR([XML::Parser perl module is required for intltool])
+ fi
+fi
+
+AC_PATH_PROG(INTLTOOL_ICONV, iconv, iconv)
+AC_PATH_PROG(INTLTOOL_MSGFMT, msgfmt, msgfmt)
+AC_PATH_PROG(INTLTOOL_MSGMERGE, msgmerge, msgmerge)
+AC_PATH_PROG(INTLTOOL_XGETTEXT, xgettext, xgettext)
+
+# Substitute ALL_LINGUAS so we can use it in po/Makefile
+AC_SUBST(ALL_LINGUAS)
+
+IT_PO_SUBDIR([po])
+
+dnl The following is very similar to
+dnl
+dnl AC_CONFIG_FILES([intltool-extract intltool-merge intltool-update])
+dnl
+dnl with the following slight differences:
+dnl - the *.in files are in ac_aux_dir,
+dnl - if the file haven't changed upon reconfigure, it's not touched,
+dnl - the evaluation of the third parameter enables a hack which computes
+dnl the actual value of $libdir,
+dnl - the user sees "executing intltool commands", instead of
+dnl "creating intltool-extract" and such.
+dnl
+dnl Nothing crucial here, and we could use AC_CONFIG_FILES, if there were
+dnl a reason for it.
+
+AC_CONFIG_COMMANDS([intltool], [
+
+for file in intltool-extract intltool-merge intltool-update; do
+ sed -e "s|@INTLTOOL_EXTRACT@|`pwd`/intltool-extract|g" \
+ -e "s|@INTLTOOL_LIBDIR@|${INTLTOOL_LIBDIR}|g" \
+ -e "s|@INTLTOOL_ICONV@|${INTLTOOL_ICONV}|g" \
+ -e "s|@INTLTOOL_MSGFMT@|${INTLTOOL_MSGFMT}|g" \
+ -e "s|@INTLTOOL_MSGMERGE@|${INTLTOOL_MSGMERGE}|g" \
+ -e "s|@INTLTOOL_XGETTEXT@|${INTLTOOL_XGETTEXT}|g" \
+ -e "s|@INTLTOOL_PERL@|${INTLTOOL_PERL}|g" \
+ < ${ac_aux_dir}/${file}.in > ${file}.out
+ if cmp -s ${file} ${file}.out 2>/dev/null; then
+ rm -f ${file}.out
+ else
+ mv -f ${file}.out ${file}
+ fi
+ chmod ugo+x ${file}
+ chmod u+w ${file}
+done
+
+],
+[INTLTOOL_PERL='${INTLTOOL_PERL}' ac_aux_dir='${ac_aux_dir}'
+prefix="$prefix" exec_prefix="$exec_prefix" INTLTOOL_LIBDIR="$libdir"
+INTLTOOL_EXTRACT='${INTLTOOL_EXTRACT}' INTLTOOL_ICONV='${INTLTOOL_ICONV}'
+INTLTOOL_MSGFMT='${INTLTOOL_MSGFMT}' INTLTOOL_MSGMERGE='${INTLTOOL_MSGMERGE}'
+INTLTOOL_XGETTEXT='${INTLTOOL_XGETTEXT}'])
+
+])
+
+
+# IT_PO_SUBDIR(DIRNAME)
+# ---------------------
+# All po subdirs have to be declared with this macro; the subdir "po" is
+# declared by IT_PROG_INTLTOOL.
+#
+AC_DEFUN([IT_PO_SUBDIR],
+[AC_PREREQ([2.53])dnl We use ac_top_srcdir inside AC_CONFIG_COMMANDS.
+dnl
+dnl The following CONFIG_COMMANDS should be exetuted at the very end
+dnl of config.status.
+AC_CONFIG_COMMANDS_PRE([
+ AC_CONFIG_COMMANDS([$1/stamp-it], [
+ rm -f "$1/stamp-it" "$1/stamp-it.tmp" "$1/POTFILES" "$1/Makefile.tmp"
+ >"$1/stamp-it.tmp"
+ [sed '/^#/d
+ s/^[[].*] *//
+ /^[ ]*$/d
+ '"s|^| $ac_top_srcdir/|" \
+ "$srcdir/$1/POTFILES.in" | sed '$!s/$/ \\/' >"$1/POTFILES"
+ ]
+ if test ! -f "$1/Makefile"; then
+ AC_MSG_ERROR([$1/Makefile is not ready.])
+ fi
+ mv "$1/Makefile" "$1/Makefile.tmp"
+ [sed '/^POTFILES =/,/[^\\]$/ {
+ /^POTFILES =/!d
+ r $1/POTFILES
+ }
+ ' "$1/Makefile.tmp" >"$1/Makefile"]
+ rm -f "$1/Makefile.tmp"
+ mv "$1/stamp-it.tmp" "$1/stamp-it"
+ ])
+])dnl
+])
+
+
+# deprecated macros
+AU_ALIAS([AC_PROG_INTLTOOL], [IT_PROG_INTLTOOL])
+# A hint is needed for aclocal from Automake <= 1.9.4:
+# AC_DEFUN([AC_PROG_INTLTOOL], ...)
+
Modified: trunk/autogen.sh
===================================================================
--- trunk/autogen.sh 2006-09-27 23:27:03 UTC (rev 3916)
+++ trunk/autogen.sh 2006-09-28 17:46:36 UTC (rev 3917)
@@ -14,8 +14,6 @@
AUTOCONF_VERSION=2.57
AUTOHEADER=autoheader
GLIB_GETTEXTIZE=glib-gettextize
-INTLTOOLIZE=intltoolize
-INTLTOOLIZE_VERSION=0.28
LIBTOOLIZE=libtoolize
LIBTOOLIZE_VERSION=1.5.0
CONFIGURE_OPTIONS=
@@ -110,13 +108,6 @@
DIE=1
}
-# check for intltoolize
-check_version "`$INTLTOOLIZE --version 2>/dev/null | sed 1q`" $INTLTOOLIZE_VERSION || {
- echo "You need to have $INTLTOOLIZE (version >= $INTLTOOLIZE_VERSION) installed to compile $PROJECT."
- echo "Get the source tarball at http://ftp.gnu.org/gnu/"
- DIE=1
-}
-
# check for libtool
check_version "`$LIBTOOLIZE --version 2>/dev/null | sed 1q`" $LIBTOOLIZE_VERSION || {
echo "You need to have $LIBTOOLIZE (version >= $LIBTOOLIZE_VERSION) installed to compile $PROJECT."
@@ -164,17 +155,15 @@
echo "Running: $GLIB_GETTEXTIZE"
echo "no" | $GLIB_GETTEXTIZE --force || exit $?
-echo "Running: $INTLTOOLIZE"
-$INTLTOOLIZE --force --automake || exit $?
-echo "Patching intltool for SCM, LINGUAS and distfile-list:-rule"
-if egrep '\WVERSION\W[[:space:]]*=[^0-9a-zA-Z]*\W0\.33\W' -q intltool-extract.in ; then
- # detected intltool-extract.in VERSION=0.33
- patch -p0 <po/intltool-scm.diff || exit $?
-else
- # assuming intltool-extract.in >= 0.35.0
- patch -p0 <po/intltool-scm-35.diff || exit $?
-fi
+echo "Providing our own patched intltool..."
+# echo "Running: intltoolize"
+# intltoolize --force --copy || exit $?
+# echo "Patching intltool for SCM, LINGUAS and custom rules"
+# patch -p0 -b <po/intltool-scm-35.diff || exit $?
+echo "Overriding gettext po/Makefile.in.in with intltool version"
+rm -f po/Makefile.in.in && cp -v po/Makefile.intltool po/Makefile.in.in || exit $?
+
echo "Running: $ACLOCAL $ACLOCAL_FLAGS"
$ACLOCAL $ACLOCAL_FLAGS || exit $?
Modified: trunk/configure.in
===================================================================
--- trunk/configure.in 2006-09-27 23:27:03 UTC (rev 3916)
+++ trunk/configure.in 2006-09-28 17:46:36 UTC (rev 3917)
@@ -157,6 +157,8 @@
dnl #
dnl # Define package requirements.
dnl #
+dnl ## include acintltool.m4 to provide IT_PROG_INTLTOOL
+builtin(include, acintltool.m4)dnl
AC_DEFUN([AC_I18N_REQUIREMENTS],
[
ALL_LINGUAS=`cat "$srcdir/po/LINGUAS" | grep -v '^#' | xargs echo -n `
@@ -185,9 +187,9 @@
prefix="$saved_prefix"
AC_SUBST(beastlocaledir)
- dnl # do gettext checks and provide INTLLIBS
+ dnl # do gettext checks and prepare for intltool
AM_GLIB_GNU_GETTEXT
- AC_PROG_INTLTOOL
+ IT_PROG_INTLTOOL
])
AC_DEFUN([AC_SFI_REQUIREMENTS],
[
Added: trunk/intltool-extract.in
===================================================================
--- trunk/intltool-extract.in 2006-09-27 23:27:03 UTC (rev 3916)
+++ trunk/intltool-extract.in 2006-09-28 17:46:36 UTC (rev 3917)
@@ -0,0 +1,841 @@
+#! INTLTOOL_PERL@ -w
+# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+
+#
+# The Intltool Message Extractor
+#
+# Copyright (C) 2000-2001, 2003 Free Software Foundation.
+#
+# Intltool 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 2 of the
+# License, or (at your option) any later version.
+#
+# Intltool 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, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+#
+# Authors: Kenneth Christiansen <kenneth gnu org>
+# Darin Adler <darin bentspoon com>
+#
+
+## Release information
+my $PROGRAM = "intltool-extract";
+my $PACKAGE = "intltool";
+my $VERSION = "0.35.0";
+
+## Loaded modules
+use strict;
+use File::Basename;
+use Getopt::Long;
+
+## Scalars used by the option stuff
+my $TYPE_ARG = "0";
+my $LOCAL_ARG = "0";
+my $HELP_ARG = "0";
+my $VERSION_ARG = "0";
+my $UPDATE_ARG = "0";
+my $QUIET_ARG = "0";
+my $SRCDIR_ARG = ".";
+
+my $FILE;
+my $OUTFILE;
+
+my $gettext_type = "";
+my $input;
+my %messages = ();
+my %loc = ();
+my %count = ();
+my %comments = ();
+my $strcount = 0;
+
+my $XMLCOMMENT = "";
+
+## Use this instead of \w for XML files to handle more possible characters.
+my $w = "[-A-Za-z0-9._:]";
+
+## Always print first
+$| = 1;
+
+## Handle options
+GetOptions (
+ "type=s" => \$TYPE_ARG,
+ "local|l" => \$LOCAL_ARG,
+ "help|h" => \$HELP_ARG,
+ "version|v" => \$VERSION_ARG,
+ "update" => \$UPDATE_ARG,
+ "quiet|q" => \$QUIET_ARG,
+ "srcdir=s" => \$SRCDIR_ARG,
+ ) or &error;
+
+&split_on_argument;
+
+
+## Check for options.
+## This section will check for the different options.
+
+sub split_on_argument {
+
+ if ($VERSION_ARG) {
+ &version;
+
+ } elsif ($HELP_ARG) {
+ &help;
+
+ } elsif ($LOCAL_ARG) {
+ &place_local;
+ &extract;
+
+ } elsif ($UPDATE_ARG) {
+ &place_normal;
+ &extract;
+
+ } elsif (@ARGV > 0) {
+ &place_normal;
+ &message;
+ &extract;
+
+ } else {
+ &help;
+
+ }
+}
+
+sub place_normal {
+ $FILE = $ARGV[0];
+ $OUTFILE = "$FILE.h";
+}
+
+sub place_local {
+ $FILE = $ARGV[0];
+ $OUTFILE = fileparse($FILE, ());
+ if (!-e "tmp/") {
+ system("mkdir tmp/");
+ }
+ $OUTFILE = "./tmp/$OUTFILE.h"
+}
+
+sub determine_type {
+ if ($TYPE_ARG =~ /^gettext\/(.*)/) {
+ $gettext_type=$1
+ }
+}
+
+## Sub for printing release information
+sub version{
+ print <<_EOF_;
+${PROGRAM} (${PACKAGE}) $VERSION
+Copyright (C) 2000, 2003 Free Software Foundation, Inc.
+Written by Kenneth Christiansen, 2000.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+_EOF_
+ exit;
+}
+
+## Sub for printing usage information
+sub help {
+ print <<_EOF_;
+Usage: ${PROGRAM} [OPTION]... [FILENAME]
+Generates a header file from an XML source file.
+
+It grabs all strings between <_translatable_node> and its end tag in
+XML files. Read manpage (man ${PROGRAM}) for more info.
+
+ --type=TYPE Specify the file type of FILENAME. Currently supports:
+ "gettext/glade", "gettext/ini", "gettext/keys"
+ "gettext/rfc822deb", "gettext/schemas",
+ "gettext/scheme", "gettext/xml"
+ -l, --local Writes output into current working directory
+ (conflicts with --update)
+ --update Writes output into the same directory the source file
+ reside (conflicts with --local)
+ --srcdir Root of the source tree
+ -v, --version Output version information and exit
+ -h, --help Display this help and exit
+ -q, --quiet Quiet mode
+
+Report bugs to http://bugzilla.gnome.org/ (product name "$PACKAGE")
+or send email to <xml-i18n-tools\ gnome org>.
+_EOF_
+ exit;
+}
+
+## Sub for printing error messages
+sub error{
+ print STDERR "Try `${PROGRAM} --help' for more information.\n";
+ exit;
+}
+
+sub message {
+ print "Generating C format header file for translation.\n" unless $QUIET_ARG;
+}
+
+sub extract {
+ &determine_type;
+
+ &convert;
+
+ open OUT, ">$OUTFILE";
+ binmode (OUT) if $^O eq 'MSWin32';
+ &msg_write;
+ close OUT;
+
+ print "Wrote $OUTFILE\n" unless $QUIET_ARG;
+}
+
+sub convert {
+
+ ## Reading the file
+ {
+ local (*IN);
+ local $/; #slurp mode
+ open (IN, "<$SRCDIR_ARG/$FILE") || die "can't open $SRCDIR_ARG/$FILE: $!";
+ $input = <IN>;
+ }
+
+ &type_ini if $gettext_type eq "ini";
+ &type_keys if $gettext_type eq "keys";
+ &type_xml if $gettext_type eq "xml";
+ &type_glade if $gettext_type eq "glade";
+ &type_scheme if $gettext_type eq "scheme";
+ &type_schemas if $gettext_type eq "schemas";
+ &type_rfc822deb if $gettext_type eq "rfc822deb";
+}
+
+sub entity_decode_minimal
+{
+ local ($_) = @_;
+
+ s/'/'/g; # '
+ s/"/"/g; # "
+ s/&/&/g;
+
+ return $_;
+}
+
+sub entity_decode
+{
+ local ($_) = @_;
+
+ s/'/'/g; # '
+ s/"/"/g; # "
+ s/&/&/g;
+ s/</</g;
+ s/>/>/g;
+
+ return $_;
+}
+
+sub escape_char
+{
+ return '\"' if $_ eq '"';
+ return '\n' if $_ eq "\n";
+ return '\\' if $_ eq '\\';
+
+ return $_;
+}
+
+sub escape
+{
+ my ($string) = @_;
+ return join "", map &escape_char, split //, $string;
+}
+
+sub type_ini {
+ ### For generic translatable desktop files ###
+ while ($input =~ /^_.*=(.*)$/mg) {
+ $messages{$1} = [];
+ }
+}
+
+sub type_keys {
+ ### For generic translatable mime/keys files ###
+ while ($input =~ /^\s*_\w+=(.*)$/mg) {
+ $messages{$1} = [];
+ }
+}
+
+sub type_xml {
+ ### For generic translatable XML files ###
+ my $tree = readXml($input);
+ parseTree(0, $tree);
+}
+
+sub print_var {
+ my $var = shift;
+ my $vartype = ref $var;
+
+ if ($vartype =~ /ARRAY/) {
+ my @arr = @{$var};
+ print "[ ";
+ foreach my $el (@arr) {
+ print_var($el);
+ print ", ";
+ }
+ print "] ";
+ } elsif ($vartype =~ /HASH/) {
+ my %hash = %{$var};
+ print "{ ";
+ foreach my $key (keys %hash) {
+ print "$key => ";
+ print_var($hash{$key});
+ print ", ";
+ }
+ print "} ";
+ } else {
+ print $var;
+ }
+}
+
+# Same syntax as getAttributeString in intltool-merge.in.in, similar logic (look for ## differences comment)
+sub getAttributeString
+{
+ my $sub = shift;
+ my $do_translate = shift || 1;
+ my $language = shift || "";
+ my $translate = shift;
+ my $result = "";
+ foreach my $e (reverse(sort(keys %{ $sub }))) {
+ my $key = $e;
+ my $string = $sub->{$e};
+ my $quote = '"';
+
+ $string =~ s/^[\s]+//;
+ $string =~ s/[\s]+$//;
+
+ if ($string =~ /^'.*'$/)
+ {
+ $quote = "'";
+ }
+ $string =~ s/^['"]//g;
+ $string =~ s/['"]$//g;
+
+ ## differences from intltool-merge.in.in
+ if ($key =~ /^_/) {
+ $comments{entity_decode($string)} = $XMLCOMMENT if $XMLCOMMENT;
+ $messages{entity_decode($string)} = [];
+ $$translate = 2;
+ }
+ ## differences end here from intltool-merge.in.in
+ $result .= " $key=$quote$string$quote";
+ }
+ return $result;
+}
+
+# Verbatim copy from intltool-merge.in.in
+sub getXMLstring
+{
+ my $ref = shift;
+ my $spacepreserve = shift || 0;
+ my @list = @{ $ref };
+ my $result = "";
+
+ my $count = scalar(@list);
+ my $attrs = $list[0];
+ my $index = 1;
+
+ $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/));
+ $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/));
+
+ while ($index < $count) {
+ my $type = $list[$index];
+ my $content = $list[$index+1];
+ if (! $type ) {
+ # We've got CDATA
+ if ($content) {
+ # lets strip the whitespace here, and *ONLY* here
+ $content =~ s/\s+/ /gs if (!$spacepreserve);
+ $result .= $content;
+ }
+ } elsif ( "$type" ne "1" ) {
+ # We've got another element
+ $result .= "<$type";
+ $result .= getAttributeString(@{$content}[0], 0); # no nested translatable elements
+ if ($content) {
+ my $subresult = getXMLstring($content, $spacepreserve);
+ if ($subresult) {
+ $result .= ">".$subresult . "</$type>";
+ } else {
+ $result .= "/>";
+ }
+ } else {
+ $result .= "/>";
+ }
+ }
+ $index += 2;
+ }
+ return $result;
+}
+
+# Verbatim copy from intltool-merge.in.in, except for MULTIPLE_OUTPUT handling removed
+# Translate list of nodes if necessary
+sub translate_subnodes
+{
+ my $fh = shift;
+ my $content = shift;
+ my $language = shift || "";
+ my $singlelang = shift || 0;
+ my $spacepreserve = shift || 0;
+
+ my @nodes = @{ $content };
+
+ my $count = scalar(@nodes);
+ my $index = 0;
+ while ($index < $count) {
+ my $type = $nodes[$index];
+ my $rest = $nodes[$index+1];
+ traverse($fh, $type, $rest, $language, $spacepreserve);
+ $index += 2;
+ }
+}
+
+# Based on traverse() in intltool-merge.in.in
+sub traverse
+{
+ my $fh = shift; # unused, to allow us to sync code between -merge and -extract
+ my $nodename = shift;
+ my $content = shift;
+ my $language = shift || "";
+ my $spacepreserve = shift || 0;
+
+ if ($nodename && "$nodename" eq "1") {
+ $XMLCOMMENT = $content;
+ } elsif ($nodename) {
+ # element
+ my @all = @{ $content };
+ my $attrs = shift @all;
+ my $translate = 0;
+ my $outattr = getAttributeString($attrs, 1, $language, \$translate);
+
+ if ($nodename =~ /^_/) {
+ $translate = 1;
+ $nodename =~ s/^_//;
+ }
+ my $lookup = '';
+
+ $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/));
+ $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/));
+
+ if ($translate) {
+ $lookup = getXMLstring($content, $spacepreserve);
+ if (!$spacepreserve) {
+ $lookup =~ s/^\s+//s;
+ $lookup =~ s/\s+$//s;
+ }
+
+ if ($lookup && $translate != 2) {
+ $comments{$lookup} = $XMLCOMMENT if $XMLCOMMENT;
+ $messages{$lookup} = [];
+ } elsif ($translate == 2) {
+ translate_subnodes($fh, \ all, $language, 1, $spacepreserve);
+ }
+ } else {
+ $XMLCOMMENT = "";
+ my $count = scalar(@all);
+ if ($count > 0) {
+ my $index = 0;
+ while ($index < $count) {
+ my $type = $all[$index];
+ my $rest = $all[$index+1];
+ traverse($fh, $type, $rest, $language, $spacepreserve);
+ $index += 2;
+ }
+ }
+ }
+ $XMLCOMMENT = "";
+ }
+}
+
+
+# Verbatim copy from intltool-merge.in.in, $fh for compatibility
+sub parseTree
+{
+ my $fh = shift;
+ my $ref = shift;
+ my $language = shift || "";
+
+ my $name = shift @{ $ref };
+ my $cont = shift @{ $ref };
+
+ while (!$name || "$name" eq "1") {
+ $name = shift @{ $ref };
+ $cont = shift @{ $ref };
+ }
+
+ my $spacepreserve = 0;
+ my $attrs = @{$cont}[0];
+ $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/));
+
+ traverse($fh, $name, $cont, $language, $spacepreserve);
+}
+
+# Verbatim copy from intltool-merge.in.in
+sub intltool_tree_comment
+{
+ my $expat = shift;
+ my $data = $expat->original_string();
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ $data =~ s/^<!--//s;
+ $data =~ s/-->$//s;
+ push @$clist, 1 => $data;
+}
+
+# Verbatim copy from intltool-merge.in.in
+sub intltool_tree_cdatastart
+{
+ my $expat = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ push @$clist, 0 => $expat->original_string();
+}
+
+# Verbatim copy from intltool-merge.in.in
+sub intltool_tree_cdataend
+{
+ my $expat = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ $clist->[$pos] .= $expat->original_string();
+}
+
+# Verbatim copy from intltool-merge.in.in
+sub intltool_tree_char
+{
+ my $expat = shift;
+ my $text = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ # Use original_string so that we retain escaped entities
+ # in CDATA sections.
+ #
+ if ($pos > 0 and $clist->[$pos - 1] eq '0') {
+ $clist->[$pos] .= $expat->original_string();
+ } else {
+ push @$clist, 0 => $expat->original_string();
+ }
+}
+
+# Verbatim copy from intltool-merge.in.in
+sub intltool_tree_start
+{
+ my $expat = shift;
+ my $tag = shift;
+ my @origlist = ();
+
+ # Use original_string so that we retain escaped entities
+ # in attribute values. We must convert the string to an
+ # @origlist array to conform to the structure of the Tree
+ # Style.
+ #
+ my @original_array = split /\x/, $expat->original_string();
+ my $source = $expat->original_string();
+
+ # Remove leading tag.
+ #
+ $source =~ s|^\s*<\s*(\S+)||s;
+
+ # Grab attribute key/value pairs and push onto @origlist array.
+ #
+ while ($source)
+ {
+ if ($source =~ /^\s*([\w:-]+)\s*[=]\s*["]/)
+ {
+ $source =~ s|^\s*([\w:-]+)\s*[=]\s*["]([^"]*)["]||s;
+ push @origlist, $1;
+ push @origlist, '"' . $2 . '"';
+ }
+ elsif ($source =~ /^\s*([\w:-]+)\s*[=]\s*[']/)
+ {
+ $source =~ s|^\s*([\w:-]+)\s*[=]\s*[']([^']*)[']||s;
+ push @origlist, $1;
+ push @origlist, "'" . $2 . "'";
+ }
+ else
+ {
+ last;
+ }
+ }
+
+ my $ol = [ { @origlist } ];
+
+ push @{ $expat->{Lists} }, $expat->{Curlist};
+ push @{ $expat->{Curlist} }, $tag => $ol;
+ $expat->{Curlist} = $ol;
+}
+
+# Copied from intltool-merge.in.in and added comment handler.
+sub readXml
+{
+ my $xmldoc = shift || return;
+ my $ret = eval 'require XML::Parser';
+ if(!$ret) {
+ die "You must have XML::Parser installed to run $0\n\n";
+ }
+ my $xp = new XML::Parser(Style => 'Tree');
+ $xp->setHandlers(Char => \&intltool_tree_char);
+ $xp->setHandlers(Start => \&intltool_tree_start);
+ $xp->setHandlers(CdataStart => \&intltool_tree_cdatastart);
+ $xp->setHandlers(CdataEnd => \&intltool_tree_cdataend);
+
+ ## differences from intltool-merge.in.in
+ $xp->setHandlers(Comment => \&intltool_tree_comment);
+ ## differences end here from intltool-merge.in.in
+
+ my $tree = $xp->parse($xmldoc);
+ #print_var($tree);
+
+# <foo><!-- comment --><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo>
+# would be:
+# [foo, [{}, 1, "comment", head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]], bar,
+# [{}, 0, "Howdy", ref, [{}]], 0, "do" ] ]
+
+ return $tree;
+}
+
+sub type_schemas {
+ ### For schemas XML files ###
+
+ # FIXME: We should handle escaped < (less than)
+ while ($input =~ /
+ <locale\ name="C">\s*
+ (<default>\s*(?:<!--([^>]*?)-->\s*)?(.*?)\s*<\/default>\s*)?
+ (<short>\s*(?:<!--([^>]*?)-->\s*)?(.*?)\s*<\/short>\s*)?
+ (<long>\s*(?:<!--([^>]*?)-->\s*)?(.*?)\s*<\/long>\s*)?
+ <\/locale>
+ /sgx) {
+ my @totranslate = ($3,$6,$9);
+ my @eachcomment = ($2,$5,$8);
+ foreach (@totranslate) {
+ my $currentcomment = shift @eachcomment;
+ next if !$_;
+ s/\s+/ /g;
+ $messages{entity_decode_minimal($_)} = [];
+ $comments{entity_decode_minimal($_)} = $currentcomment if (defined($currentcomment));
+ }
+ }
+}
+
+sub type_rfc822deb {
+ ### For rfc822-style Debian configuration files ###
+
+ my $lineno = 1;
+ my $type = '';
+ while ($input =~ /\G(.*?)(^|\n)(_+)([^:]+):[ \t]*(.*?)(?=\n\S|$)/sg)
+ {
+ my ($pre, $newline, $underscore, $tag, $text) = ($1, $2, $3, $4, $5);
+ while ($pre =~ m/\n/g)
+ {
+ $lineno ++;
+ }
+ $lineno += length($newline);
+ my @str_list = rfc822deb_split(length($underscore), $text);
+ for my $str (@str_list)
+ {
+ $strcount++;
+ $messages{$str} = [];
+ $loc{$str} = $lineno;
+ $count{$str} = $strcount;
+ my $usercomment = '';
+ while($pre =~ s/(^|\n)#([^\n]*)$//s)
+ {
+ $usercomment = "\n" . $2 . $usercomment;
+ }
+ $comments{$str} = $tag . $usercomment;
+ }
+ $lineno += ($text =~ s/\n//g);
+ }
+}
+
+sub rfc822deb_split {
+ # Debian defines a special way to deal with rfc822-style files:
+ # when a value contain newlines, it consists of
+ # 1. a short form (first line)
+ # 2. a long description, all lines begin with a space,
+ # and paragraphs are separated by a single dot on a line
+ # This routine returns an array of all paragraphs, and reformat
+ # them.
+ # When first argument is 2, the string is a comma separated list of
+ # values.
+ my $type = shift;
+ my $text = shift;
+ $text =~ s/^[ \t]//mg;
+ return (split(/, */, $text, 0)) if $type ne 1;
+ return ($text) if $text !~ /\n/;
+
+ $text =~ s/([^\n]*)\n//;
+ my @list = ($1);
+ my $str = '';
+ for my $line (split (/\n/, $text))
+ {
+ chomp $line;
+ if ($line =~ /^\.\s*$/)
+ {
+ # New paragraph
+ $str =~ s/\s*$//;
+ push(@list, $str);
+ $str = '';
+ }
+ elsif ($line =~ /^\s/)
+ {
+ # Line which must not be reformatted
+ $str .= "\n" if length ($str) && $str !~ /\n$/;
+ $line =~ s/\s+$//;
+ $str .= $line."\n";
+ }
+ else
+ {
+ # Continuation line, remove newline
+ $str .= " " if length ($str) && $str !~ /\n$/;
+ $str .= $line;
+ }
+ }
+ $str =~ s/\s*$//;
+ push(@list, $str) if length ($str);
+ return @list;
+}
+
+sub type_glade {
+ ### For translatable Glade XML files ###
+
+ my $tags = "label|title|text|format|copyright|comments|preview_text|tooltip|message";
+
+ while ($input =~ /<($tags)>([^<]+)<\/($tags)>/sg) {
+ # Glade sometimes uses tags that normally mark translatable things for
+ # little bits of non-translatable content. We work around this by not
+ # translating strings that only includes something like label4 or window1.
+ $messages{entity_decode($2)} = [] unless $2 =~ /^(window|label|dialog)[0-9]+$/;
+ }
+
+ while ($input =~ /<items>(..[^<]*)<\/items>/sg) {
+ for my $item (split (/\n/, $1)) {
+ $messages{entity_decode($item)} = [];
+ }
+ }
+
+ ## handle new glade files
+ while ($input =~ /<(property|atkproperty)\s+[^>]*translatable\s*=\s*"yes"(?:\s+[^>]*comments\s*=\s*"([^"]*)")?[^>]*>([^<]+)<\/\1>/sg) {
+ $messages{entity_decode($3)} = [] unless $3 =~ /^(window|label)[0-9]+$/;
+ if (defined($2) and !($3 =~ /^(window|label)[0-9]+$/)) {
+ $comments{entity_decode($3)} = entity_decode($2) ;
+ }
+ }
+ while ($input =~ /<atkaction\s+action_name="([^>]*)"\s+description="([^>]+)"\/>/sg) {
+ $messages{entity_decode_minimal($2)} = [];
+ }
+}
+
+sub type_scheme {
+ my ($line, $i, $state, $str, $trcomment, $char);
+ for $line (split(/\n/, $input)) {
+ $i = 0;
+ $state = 0; # 0 - nothing, 1 - string, 2 - translatable string
+ while ($i < length($line)) {
+ if (substr($line,$i,1) eq "\"") {
+ if ($state == 2) {
+ $comments{$str} = $trcomment if ($trcomment);
+ $messages{$str} = [];
+ $str = '';
+ $state = 0; $trcomment = "";
+ } elsif ($state == 1) {
+ $str = '';
+ $state = 0; $trcomment = "";
+ } else {
+ $state = 1;
+ $str = '';
+ if ($i>0 && substr($line,$i-1,1) eq '_') {
+ $state = 2;
+ }
+ }
+ } elsif (!$state) {
+ if (substr($line,$i,1) eq ";") {
+ $trcomment = substr($line,$i+1);
+ $trcomment =~ s/^;*\s*//;
+ $i = length($line);
+ } elsif ($trcomment && substr($line,$i,1) !~ /\s|\(|\)|_/) {
+ $trcomment = "";
+ }
+ } else {
+ if (substr($line,$i,1) eq "\\") {
+ $char = substr($line,$i+1,1);
+ if ($char ne "\"" && $char ne "\\") {
+ $str = $str . "\\";
+ }
+ $i++;
+ }
+ $str = $str . substr($line,$i,1);
+ }
+ $i++;
+ }
+ }
+}
+
+sub msg_write {
+ my @msgids;
+ if (%count)
+ {
+ @msgids = sort { $count{$a} <=> $count{$b} } keys %count;
+ }
+ else
+ {
+ @msgids = sort keys %messages;
+ }
+ for my $message (@msgids)
+ {
+ my $offsetlines = 1;
+ $offsetlines++ if $message =~ /%/;
+ if (defined ($comments{$message}))
+ {
+ while ($comments{$message} =~ m/\n/g)
+ {
+ $offsetlines++;
+ }
+ }
+ print OUT "# ".($loc{$message} - $offsetlines). " \"$FILE\"\n"
+ if defined $loc{$message};
+ print OUT "/* ".$comments{$message}." */\n"
+ if defined $comments{$message};
+ print OUT "/* xgettext:no-c-format */\n" if $message =~ /%/;
+
+ my @lines = split (/\n/, $message, -1);
+ for (my $n = 0; $n < @lines; $n++)
+ {
+ if ($n == 0)
+ {
+ print OUT "char *s = N_(\"";
+ }
+ else
+ {
+ print OUT " \"";
+ }
+
+ print OUT escape($lines[$n]);
+
+ if ($n < @lines - 1)
+ {
+ print OUT "\\n\"\n";
+ }
+ else
+ {
+ print OUT "\");\n";
+ }
+ }
+ }
+}
+
Added: trunk/intltool-merge.in
===================================================================
--- trunk/intltool-merge.in 2006-09-27 23:27:03 UTC (rev 3916)
+++ trunk/intltool-merge.in 2006-09-28 17:46:36 UTC (rev 3917)
@@ -0,0 +1,1356 @@
+#! INTLTOOL_PERL@ -w
+# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+
+#
+# The Intltool Message Merger
+#
+# Copyright (C) 2000, 2003 Free Software Foundation.
+# Copyright (C) 2000, 2001 Eazel, Inc
+#
+# Intltool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 published by the Free Software Foundation.
+#
+# Intltool 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, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+#
+# Authors: Maciej Stachowiak <mjs noisehavoc org>
+# Kenneth Christiansen <kenneth gnu org>
+# Darin Adler <darin bentspoon com>
+#
+# Proper XML UTF-8'ification written by Cyrille Chepelov <chepelov calixo net>
+#
+
+## Release information
+my $PROGRAM = "intltool-merge";
+my $PACKAGE = "intltool";
+my $VERSION = "0.35.0";
+
+## Loaded modules
+use strict;
+use Getopt::Long;
+use Text::Wrap;
+use File::Basename;
+
+my $must_end_tag = -1;
+my $last_depth = -1;
+my $translation_depth = -1;
+my @tag_stack = ();
+my @entered_tag = ();
+my @translation_strings = ();
+my $leading_space = "";
+
+## Scalars used by the option stuff
+my $HELP_ARG = 0;
+my $VERSION_ARG = 0;
+my $BA_STYLE_ARG = 0;
+my $XML_STYLE_ARG = 0;
+my $KEYS_STYLE_ARG = 0;
+my $DESKTOP_STYLE_ARG = 0;
+my $SCHEMAS_STYLE_ARG = 0;
+my $RFC822DEB_STYLE_ARG = 0;
+my $QUIET_ARG = 0;
+my $PASS_THROUGH_ARG = 0;
+my $UTF8_ARG = 0;
+my $MULTIPLE_OUTPUT = 0;
+my $cache_file;
+
+## Handle options
+GetOptions
+(
+ "help" => \$HELP_ARG,
+ "version" => \$VERSION_ARG,
+ "quiet|q" => \$QUIET_ARG,
+ "oaf-style|o" => \$BA_STYLE_ARG, ## for compatibility
+ "ba-style|b" => \$BA_STYLE_ARG,
+ "xml-style|x" => \$XML_STYLE_ARG,
+ "keys-style|k" => \$KEYS_STYLE_ARG,
+ "desktop-style|d" => \$DESKTOP_STYLE_ARG,
+ "schemas-style|s" => \$SCHEMAS_STYLE_ARG,
+ "rfc822deb-style|r" => \$RFC822DEB_STYLE_ARG,
+ "pass-through|p" => \$PASS_THROUGH_ARG,
+ "utf8|u" => \$UTF8_ARG,
+ "multiple-output|m" => \$MULTIPLE_OUTPUT,
+ "cache|c=s" => \$cache_file
+ ) or &error;
+
+my $PO_DIR;
+my $FILE;
+my $OUTFILE;
+
+my %po_files_by_lang = ();
+my %translations = ();
+my $iconv = $ENV{"ICONV"} || $ENV{"INTLTOOL_ICONV"} || "@INTLTOOL_ICONV@";
+my $devnull = ($^O eq 'MSWin32' ? 'NUL:' : '/dev/null');
+
+# Use this instead of \w for XML files to handle more possible characters.
+my $w = "[-A-Za-z0-9._:]";
+
+# XML quoted string contents
+my $q = "[^\\\"]*";
+
+## Check for options.
+
+if ($VERSION_ARG)
+{
+ &print_version;
+}
+elsif ($HELP_ARG)
+{
+ &print_help;
+}
+elsif ($BA_STYLE_ARG && @ARGV > 2)
+{
+ &utf8_sanity_check;
+ &preparation;
+ &print_message;
+ &ba_merge_translations;
+ &finalize;
+}
+elsif ($XML_STYLE_ARG && @ARGV > 2)
+{
+ &utf8_sanity_check;
+ &preparation;
+ &print_message;
+ &xml_merge_output;
+ &finalize;
+}
+elsif ($KEYS_STYLE_ARG && @ARGV > 2)
+{
+ &utf8_sanity_check;
+ &preparation;
+ &print_message;
+ &keys_merge_translations;
+ &finalize;
+}
+elsif ($DESKTOP_STYLE_ARG && @ARGV > 2)
+{
+ &utf8_sanity_check;
+ &preparation;
+ &print_message;
+ &desktop_merge_translations;
+ &finalize;
+}
+elsif ($SCHEMAS_STYLE_ARG && @ARGV > 2)
+{
+ &utf8_sanity_check;
+ &preparation;
+ &print_message;
+ &schemas_merge_translations;
+ &finalize;
+}
+elsif ($RFC822DEB_STYLE_ARG && @ARGV > 2)
+{
+ &preparation;
+ &print_message;
+ &rfc822deb_merge_translations;
+ &finalize;
+}
+else
+{
+ &print_help;
+}
+
+exit;
+
+## Sub for printing release information
+sub print_version
+{
+ print <<_EOF_;
+${PROGRAM} (${PACKAGE}) ${VERSION}
+Written by Maciej Stachowiak, Darin Adler and Kenneth Christiansen.
+
+Copyright (C) 2000-2003 Free Software Foundation, Inc.
+Copyright (C) 2000-2001 Eazel, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+_EOF_
+ exit;
+}
+
+## Sub for printing usage information
+sub print_help
+{
+ print <<_EOF_;
+Usage: ${PROGRAM} [OPTION]... PO_DIRECTORY FILENAME OUTPUT_FILE
+Generates an output file that includes some localized attributes from an
+untranslated source file.
+
+Mandatory options: (exactly one must be specified)
+ -b, --ba-style includes translations in the bonobo-activation style
+ -d, --desktop-style includes translations in the desktop style
+ -k, --keys-style includes translations in the keys style
+ -s, --schemas-style includes translations in the schemas style
+ -r, --rfc822deb-style includes translations in the RFC822 style
+ -x, --xml-style includes translations in the standard xml style
+
+Other options:
+ -u, --utf8 convert all strings to UTF-8 before merging
+ (default for everything except RFC822 style)
+ -p, --pass-through deprecated, does nothing and issues a warning
+ -m, --multiple-output output one localized file per locale, instead of
+ a single file containing all localized elements
+ -c, --cache=FILE specify cache file name
+ (usually \$top_builddir/po/.intltool-merge-cache)
+ -q, --quiet suppress most messages
+ --help display this help and exit
+ --version output version information and exit
+
+Report bugs to http://bugzilla.gnome.org/ (product name "$PACKAGE")
+or send email to <xml-i18n-tools\ gnome org>.
+_EOF_
+ exit;
+}
+
+
+## Sub for printing error messages
+sub print_error
+{
+ print STDERR "Try `${PROGRAM} --help' for more information.\n";
+ exit;
+}
+
+
+sub print_message
+{
+ print "Merging translations into $OUTFILE.\n" unless $QUIET_ARG;
+}
+
+
+sub preparation
+{
+ $PO_DIR = $ARGV[0];
+ $FILE = $ARGV[1];
+ $OUTFILE = $ARGV[2];
+
+ &gather_po_files;
+ &get_translation_database;
+}
+
+# General-purpose code for looking up translations in .po files
+
+sub po_file2lang
+{
+ my ($tmp) = @_;
+ $tmp =~ s/^.*\/(.*)\.po$/$1/;
+ return $tmp;
+}
+
+sub gather_po_files
+{
+ for my $po_file (glob "$PO_DIR/*.po") {
+ $po_files_by_lang{po_file2lang($po_file)} = $po_file;
+ }
+}
+
+sub get_local_charset
+{
+ my ($encoding) = @_;
+ my $alias_file = $ENV{"G_CHARSET_ALIAS"} || "@INTLTOOL_LIBDIR@/charset.alias";
+
+ # seek character encoding aliases in charset.alias (glib)
+
+ if (open CHARSET_ALIAS, $alias_file)
+ {
+ while (<CHARSET_ALIAS>)
+ {
+ next if /^\#/;
+ return $1 if (/^\s*([-._a-zA-Z0-9]+)\s+$encoding\b/i)
+ }
+
+ close CHARSET_ALIAS;
+ }
+
+ # if not found, return input string
+
+ return $encoding;
+}
+
+sub get_po_encoding
+{
+ my ($in_po_file) = @_;
+ my $encoding = "";
+
+ open IN_PO_FILE, $in_po_file or die;
+ while (<IN_PO_FILE>)
+ {
+ ## example: "Content-Type: text/plain; charset=ISO-8859-1\n"
+ if (/Content-Type\:.*charset=([-a-zA-Z0-9]+)\\n/)
+ {
+ $encoding = $1;
+ last;
+ }
+ }
+ close IN_PO_FILE;
+
+ if (!$encoding)
+ {
+ print STDERR "Warning: no encoding found in $in_po_file. Assuming ISO-8859-1\n" unless $QUIET_ARG;
+ $encoding = "ISO-8859-1";
+ }
+
+ system ("$iconv -f $encoding -t UTF-8 <$devnull 2>$devnull");
+ if ($?) {
+ $encoding = get_local_charset($encoding);
+ }
+
+ return $encoding
+}
+
+sub utf8_sanity_check
+{
+ print STDERR "Warning: option --pass-through has been removed.\n" if $PASS_THROUGH_ARG;
+ $UTF8_ARG = 1;
+}
+
+sub get_translation_database
+{
+ if ($cache_file) {
+ &get_cached_translation_database;
+ } else {
+ &create_translation_database;
+ }
+}
+
+sub get_newest_po_age
+{
+ my $newest_age;
+
+ foreach my $file (values %po_files_by_lang)
+ {
+ my $file_age = -M $file;
+ $newest_age = $file_age if !$newest_age || $file_age < $newest_age;
+ }
+
+ $newest_age = 0 if !$newest_age;
+
+ return $newest_age;
+}
+
+sub create_cache
+{
+ print "Generating and caching the translation database\n" unless $QUIET_ARG;
+
+ &create_translation_database;
+
+ open CACHE, ">$cache_file" || die;
+ print CACHE join "\x01", %translations;
+ close CACHE;
+}
+
+sub load_cache
+{
+ print "Found cached translation database\n" unless $QUIET_ARG;
+
+ my $contents;
+ open CACHE, "<$cache_file" || die;
+ {
+ local $/;
+ $contents = <CACHE>;
+ }
+ close CACHE;
+ %translations = split "\x01", $contents;
+}
+
+sub get_cached_translation_database
+{
+ my $cache_file_age = -M $cache_file;
+ if (defined $cache_file_age)
+ {
+ if ($cache_file_age <= &get_newest_po_age)
+ {
+ &load_cache;
+ return;
+ }
+ print "Found too-old cached translation database\n" unless $QUIET_ARG;
+ }
+
+ &create_cache;
+}
+
+sub create_translation_database
+{
+ for my $lang (keys %po_files_by_lang)
+ {
+ my $po_file = $po_files_by_lang{$lang};
+
+ if ($UTF8_ARG)
+ {
+ my $encoding = get_po_encoding ($po_file);
+
+ if (lc $encoding eq "utf-8")
+ {
+ open PO_FILE, "<$po_file";
+ }
+ else
+ {
+ print "NOTICE: $po_file is not in UTF-8 but $encoding, converting...\n" unless $QUIET_ARG;;
+
+ open PO_FILE, "$iconv -f $encoding -t UTF-8 $po_file|";
+ }
+ }
+ else
+ {
+ open PO_FILE, "<$po_file";
+ }
+
+ my $nextfuzzy = 0;
+ my $inmsgid = 0;
+ my $inmsgstr = 0;
+ my $msgid = "";
+ my $msgstr = "";
+
+ while (<PO_FILE>)
+ {
+ $nextfuzzy = 1 if /^#, fuzzy/;
+
+ if (/^msgid "((\\.|[^\\])*)"/ )
+ {
+ $translations{$lang, $msgid} = $msgstr if $inmsgstr && $msgid && $msgstr;
+ $msgid = "";
+ $msgstr = "";
+
+ if ($nextfuzzy) {
+ $inmsgid = 0;
+ } else {
+ $msgid = unescape_po_string($1);
+ $inmsgid = 1;
+ }
+ $inmsgstr = 0;
+ $nextfuzzy = 0;
+ }
+
+ if (/^msgstr "((\\.|[^\\])*)"/)
+ {
+ $msgstr = unescape_po_string($1);
+ $inmsgstr = 1;
+ $inmsgid = 0;
+ }
+
+ if (/^"((\\.|[^\\])*)"/)
+ {
+ $msgid .= unescape_po_string($1) if $inmsgid;
+ $msgstr .= unescape_po_string($1) if $inmsgstr;
+ }
+ }
+ $translations{$lang, $msgid} = $msgstr if $inmsgstr && $msgid && $msgstr;
+ }
+}
+
+sub finalize
+{
+}
+
+sub unescape_one_sequence
+{
+ my ($sequence) = @_;
+
+ return "\\" if $sequence eq "\\\\";
+ return "\"" if $sequence eq "\\\"";
+ return "\n" if $sequence eq "\\n";
+ return "\r" if $sequence eq "\\r";
+ return "\t" if $sequence eq "\\t";
+ return "\b" if $sequence eq "\\b";
+ return "\f" if $sequence eq "\\f";
+ return "\a" if $sequence eq "\\a";
+ return chr(11) if $sequence eq "\\v"; # vertical tab, see ascii(7)
+
+ return chr(hex($1)) if ($sequence =~ /\\x([0-9a-fA-F]{2})/);
+ return chr(oct($1)) if ($sequence =~ /\\([0-7]{3})/);
+
+ # FIXME: Is \0 supported as well? Kenneth and Rodney don't want it, see bug #48489
+
+ return $sequence;
+}
+
+sub unescape_po_string
+{
+ my ($string) = @_;
+
+ $string =~ s/(\\x[0-9a-fA-F]{2}|\\[0-7]{3}|\\.)/unescape_one_sequence($1)/eg;
+
+ return $string;
+}
+
+## NOTE: deal with < - < but not > - > because it seems its ok to have
+## > in the entity. For further info please look at #84738.
+sub entity_decode
+{
+ local ($_) = @_;
+
+ s/'/'/g; # '
+ s/"/"/g; # "
+ s/&/&/g;
+ s/</</g;
+
+ return $_;
+}
+
+# entity_encode: (string)
+#
+# Encode the given string to XML format (encode '<' etc).
+
+sub entity_encode
+{
+ my ($pre_encoded) = @_;
+
+ my @list_of_chars = unpack ('C*', $pre_encoded);
+
+ # with UTF-8 we only encode minimalistic
+ return join ('', map (&entity_encode_int_minimalist, @list_of_chars));
+}
+
+sub entity_encode_int_minimalist
+{
+ return """ if $_ == 34;
+ return "&" if $_ == 38;
+ return "'" if $_ == 39;
+ return "<" if $_ == 60;
+ return chr $_;
+}
+
+sub entity_encoded_translation
+{
+ my ($lang, $string) = @_;
+
+ my $translation = $translations{$lang, $string};
+ return $string if !$translation;
+ return entity_encode ($translation);
+}
+
+## XML (bonobo-activation specific) merge code
+
+sub ba_merge_translations
+{
+ my $source;
+
+ {
+ local $/; # slurp mode
+ open INPUT, "<$FILE" or die "can't open $FILE: $!";
+ $source = <INPUT>;
+ close INPUT;
+ }
+
+ open OUTPUT, ">$OUTFILE" or die "can't open $OUTFILE: $!";
+ # Binmode so that selftest works ok if using a native Win32 Perl...
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+
+ while ($source =~ s|^(.*?)([ \t]*<\s*$w+\s+($w+\s*=\s*"$q"\s*)+/?>)([ \t]*\n)?||s)
+ {
+ print OUTPUT $1;
+
+ my $node = $2 . "\n";
+
+ my @strings = ();
+ $_ = $node;
+ while (s/(\s)_($w+\s*=\s*"($q)")/$1$2/s) {
+ push @strings, entity_decode($3);
+ }
+ print OUTPUT;
+
+ my %langs;
+ for my $string (@strings)
+ {
+ for my $lang (keys %po_files_by_lang)
+ {
+ $langs{$lang} = 1 if $translations{$lang, $string};
+ }
+ }
+
+ for my $lang (sort keys %langs)
+ {
+ $_ = $node;
+ s/(\sname\s*=\s*)"($q)"/$1"$2-$lang"/s;
+ s/(\s)_($w+\s*=\s*")($q)"/$1 . $2 . entity_encoded_translation($lang, $3) . '"'/seg;
+ print OUTPUT;
+ }
+ }
+
+ print OUTPUT $source;
+
+ close OUTPUT;
+}
+
+
+## XML (non-bonobo-activation) merge code
+
+
+# Process tag attributes
+# Only parameter is a HASH containing attributes -> values mapping
+sub getAttributeString
+{
+ my $sub = shift;
+ my $do_translate = shift || 0;
+ my $language = shift || "";
+ my $result = "";
+ my $translate = shift;
+ foreach my $e (reverse(sort(keys %{ $sub }))) {
+ my $key = $e;
+ my $string = $sub->{$e};
+ my $quote = '"';
+
+ $string =~ s/^[\s]+//;
+ $string =~ s/[\s]+$//;
+
+ if ($string =~ /^'.*'$/)
+ {
+ $quote = "'";
+ }
+ $string =~ s/^['"]//g;
+ $string =~ s/['"]$//g;
+
+ if ($do_translate && $key =~ /^_/) {
+ $key =~ s|^_||g;
+ if ($language) {
+ # Handle translation
+ my $decode_string = entity_decode($string);
+ my $translation = $translations{$language, $decode_string};
+ if ($translation) {
+ $translation = entity_encode($translation);
+ $string = $translation;
+ }
+ $$translate = 2;
+ } else {
+ $$translate = 2 if ($translate && (!$$translate)); # watch not to "overwrite" $translate
+ }
+ }
+
+ $result .= " $key=$quote$string$quote";
+ }
+ return $result;
+}
+
+# Returns a translatable string from XML node, it works on contents of every node in XML::Parser tree
+sub getXMLstring
+{
+ my $ref = shift;
+ my $spacepreserve = shift || 0;
+ my @list = @{ $ref };
+ my $result = "";
+
+ my $count = scalar(@list);
+ my $attrs = $list[0];
+ my $index = 1;
+
+ $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/));
+ $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/));
+
+ while ($index < $count) {
+ my $type = $list[$index];
+ my $content = $list[$index+1];
+ if (! $type ) {
+ # We've got CDATA
+ if ($content) {
+ # lets strip the whitespace here, and *ONLY* here
+ $content =~ s/\s+/ /gs if (!$spacepreserve);
+ $result .= $content;
+ }
+ } elsif ( "$type" ne "1" ) {
+ # We've got another element
+ $result .= "<$type";
+ $result .= getAttributeString(@{$content}[0], 0); # no nested translatable elements
+ if ($content) {
+ my $subresult = getXMLstring($content, $spacepreserve);
+ if ($subresult) {
+ $result .= ">".$subresult . "</$type>";
+ } else {
+ $result .= "/>";
+ }
+ } else {
+ $result .= "/>";
+ }
+ }
+ $index += 2;
+ }
+ return $result;
+}
+
+# Translate list of nodes if necessary
+sub translate_subnodes
+{
+ my $fh = shift;
+ my $content = shift;
+ my $language = shift || "";
+ my $singlelang = shift || 0;
+ my $spacepreserve = shift || 0;
+
+ my @nodes = @{ $content };
+
+ my $count = scalar(@nodes);
+ my $index = 0;
+ while ($index < $count) {
+ my $type = $nodes[$index];
+ my $rest = $nodes[$index+1];
+ if ($singlelang) {
+ my $oldMO = $MULTIPLE_OUTPUT;
+ $MULTIPLE_OUTPUT = 1;
+ traverse($fh, $type, $rest, $language, $spacepreserve);
+ $MULTIPLE_OUTPUT = $oldMO;
+ } else {
+ traverse($fh, $type, $rest, $language, $spacepreserve);
+ }
+ $index += 2;
+ }
+}
+
+sub isWellFormedXmlFragment
+{
+ my $ret = eval 'require XML::Parser';
+ if(!$ret) {
+ die "You must have XML::Parser installed to run $0\n\n";
+ }
+
+ my $fragment = shift;
+ return 0 if (!$fragment);
+
+ $fragment = "<root>$fragment</root>";
+ my $xp = new XML::Parser(Style => 'Tree');
+ my $tree = 0;
+ eval { $tree = $xp->parse($fragment); };
+ return $tree;
+}
+
+sub traverse
+{
+ my $fh = shift;
+ my $nodename = shift;
+ my $content = shift;
+ my $language = shift || "";
+ my $spacepreserve = shift || 0;
+
+ if (!$nodename) {
+ if ($content =~ /^[\s]*$/) {
+ $leading_space .= $content;
+ }
+ print $fh $content;
+ } else {
+ # element
+ my @all = @{ $content };
+ my $attrs = shift @all;
+ my $translate = 0;
+ my $outattr = getAttributeString($attrs, 1, $language, \$translate);
+
+ if ($nodename =~ /^_/) {
+ $translate = 1;
+ $nodename =~ s/^_//;
+ }
+ my $lookup = '';
+
+ $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/));
+ $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/));
+
+ print $fh "<$nodename", $outattr;
+ if ($translate) {
+ $lookup = getXMLstring($content, $spacepreserve);
+ if (!$spacepreserve) {
+ $lookup =~ s/^\s+//s;
+ $lookup =~ s/\s+$//s;
+ }
+
+ if ($lookup || $translate == 2) {
+ my $translation = $translations{$language, $lookup} if isWellFormedXmlFragment($translations{$language, $lookup});
+ if ($MULTIPLE_OUTPUT && ($translation || $translate == 2)) {
+ $translation = $lookup if (!$translation);
+ print $fh " xml:lang=\"", $language, "\"" if $language;
+ print $fh ">";
+ if ($translate == 2) {
+ translate_subnodes($fh, \ all, $language, 1, $spacepreserve);
+ } else {
+ print $fh $translation;
+ }
+ print $fh "</$nodename>";
+
+ return; # this means there will be no same translation with xml:lang="$language"...
+ # if we want them both, just remove this "return"
+ } else {
+ print $fh ">";
+ if ($translate == 2) {
+ translate_subnodes($fh, \ all, $language, 1, $spacepreserve);
+ } else {
+ print $fh $lookup;
+ }
+ print $fh "</$nodename>";
+ }
+ } else {
+ print $fh "/>";
+ }
+
+ for my $lang (sort keys %po_files_by_lang) {
+ if ($MULTIPLE_OUTPUT && $lang ne "$language") {
+ next;
+ }
+ if ($lang) {
+ # Handle translation
+ #
+ my $translate = 0;
+ my $localattrs = getAttributeString($attrs, 1, $lang, \$translate);
+ my $translation = $translations{$lang, $lookup} if isWellFormedXmlFragment($translations{$lang, $lookup});
+ if ($translate && !$translation) {
+ $translation = $lookup;
+ }
+
+ if ($translation || $translate) {
+ print $fh "\n";
+ $leading_space =~ s/.*\n//g;
+ print $fh $leading_space;
+ print $fh "<", $nodename, " xml:lang=\"", $lang, "\"", $localattrs, ">";
+ if ($translate == 2) {
+ translate_subnodes($fh, \ all, $lang, 1, $spacepreserve);
+ } else {
+ print $fh $translation;
+ }
+ print $fh "</$nodename>";
+ }
+ }
+ }
+
+ } else {
+ my $count = scalar(@all);
+ if ($count > 0) {
+ print $fh ">";
+ my $index = 0;
+ while ($index < $count) {
+ my $type = $all[$index];
+ my $rest = $all[$index+1];
+ traverse($fh, $type, $rest, $language, $spacepreserve);
+ $index += 2;
+ }
+ print $fh "</$nodename>";
+ } else {
+ print $fh "/>";
+ }
+ }
+ }
+}
+
+sub intltool_tree_comment
+{
+ my $expat = shift;
+ my $data = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ push @$clist, 1 => $data;
+}
+
+sub intltool_tree_cdatastart
+{
+ my $expat = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ push @$clist, 0 => $expat->original_string();
+}
+
+sub intltool_tree_cdataend
+{
+ my $expat = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ $clist->[$pos] .= $expat->original_string();
+}
+
+sub intltool_tree_char
+{
+ my $expat = shift;
+ my $text = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ # Use original_string so that we retain escaped entities
+ # in CDATA sections.
+ #
+ if ($pos > 0 and $clist->[$pos - 1] eq '0') {
+ $clist->[$pos] .= $expat->original_string();
+ } else {
+ push @$clist, 0 => $expat->original_string();
+ }
+}
+
+sub intltool_tree_start
+{
+ my $expat = shift;
+ my $tag = shift;
+ my @origlist = ();
+
+ # Use original_string so that we retain escaped entities
+ # in attribute values. We must convert the string to an
+ # @origlist array to conform to the structure of the Tree
+ # Style.
+ #
+ my @original_array = split /\x/, $expat->original_string();
+ my $source = $expat->original_string();
+
+ # Remove leading tag.
+ #
+ $source =~ s|^\s*<\s*(\S+)||s;
+
+ # Grab attribute key/value pairs and push onto @origlist array.
+ #
+ while ($source)
+ {
+ if ($source =~ /^\s*([\w:-]+)\s*[=]\s*["]/)
+ {
+ $source =~ s|^\s*([\w:-]+)\s*[=]\s*["]([^"]*)["]||s;
+ push @origlist, $1;
+ push @origlist, '"' . $2 . '"';
+ }
+ elsif ($source =~ /^\s*([\w:-]+)\s*[=]\s*[']/)
+ {
+ $source =~ s|^\s*([\w:-]+)\s*[=]\s*[']([^']*)[']||s;
+ push @origlist, $1;
+ push @origlist, "'" . $2 . "'";
+ }
+ else
+ {
+ last;
+ }
+ }
+
+ my $ol = [ { @origlist } ];
+
+ push @{ $expat->{Lists} }, $expat->{Curlist};
+ push @{ $expat->{Curlist} }, $tag => $ol;
+ $expat->{Curlist} = $ol;
+}
+
+sub readXml
+{
+ my $filename = shift || return;
+ if(!-f $filename) {
+ die "ERROR Cannot find filename: $filename\n";
+ }
+
+ my $ret = eval 'require XML::Parser';
+ if(!$ret) {
+ die "You must have XML::Parser installed to run $0\n\n";
+ }
+ my $xp = new XML::Parser(Style => 'Tree');
+ $xp->setHandlers(Char => \&intltool_tree_char);
+ $xp->setHandlers(Start => \&intltool_tree_start);
+ $xp->setHandlers(CdataStart => \&intltool_tree_cdatastart);
+ $xp->setHandlers(CdataEnd => \&intltool_tree_cdataend);
+ my $tree = $xp->parsefile($filename);
+
+# <foo><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo>
+# would be:
+# [foo, [{}, head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]], bar, [{},
+# 0, "Howdy", ref, [{}]], 0, "do" ] ]
+
+ return $tree;
+}
+
+sub print_header
+{
+ my $infile = shift;
+ my $fh = shift;
+ my $source;
+
+ if(!-f $infile) {
+ die "ERROR Cannot find filename: $infile\n";
+ }
+
+ print $fh qq{<?xml version="1.0" encoding="UTF-8"?>\n};
+ {
+ local $/;
+ open DOCINPUT, "<${FILE}" or die;
+ $source = <DOCINPUT>;
+ close DOCINPUT;
+ }
+ if ($source =~ /(<!DOCTYPE.*\[.*\]\s*>)/s)
+ {
+ print $fh "$1\n";
+ }
+ elsif ($source =~ /(<!DOCTYPE[^>]*>)/s)
+ {
+ print $fh "$1\n";
+ }
+}
+
+sub parseTree
+{
+ my $fh = shift;
+ my $ref = shift;
+ my $language = shift || "";
+
+ my $name = shift @{ $ref };
+ my $cont = shift @{ $ref };
+
+ while (!$name || "$name" eq "1") {
+ $name = shift @{ $ref };
+ $cont = shift @{ $ref };
+ }
+
+ my $spacepreserve = 0;
+ my $attrs = @{$cont}[0];
+ $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/));
+
+ traverse($fh, $name, $cont, $language, $spacepreserve);
+}
+
+sub xml_merge_output
+{
+ my $source;
+
+ if ($MULTIPLE_OUTPUT) {
+ for my $lang (sort keys %po_files_by_lang) {
+ if ( ! -e $lang ) {
+ mkdir $lang or die "Cannot create subdirectory $lang: $!\n";
+ }
+ open OUTPUT, ">$lang/$OUTFILE" or die "Cannot open $lang/$OUTFILE: $!\n";
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+ my $tree = readXml($FILE);
+ print_header($FILE, \*OUTPUT);
+ parseTree(\*OUTPUT, $tree, $lang);
+ close OUTPUT;
+ print "CREATED $lang/$OUTFILE\n" unless $QUIET_ARG;
+ }
+ }
+ open OUTPUT, ">$OUTFILE" or die "Cannot open $OUTFILE: $!\n";
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+ my $tree = readXml($FILE);
+ print_header($FILE, \*OUTPUT);
+ parseTree(\*OUTPUT, $tree);
+ close OUTPUT;
+ print "CREATED $OUTFILE\n" unless $QUIET_ARG;
+}
+
+sub keys_merge_translations
+{
+ open INPUT, "<${FILE}" or die;
+ open OUTPUT, ">${OUTFILE}" or die;
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+
+ while (<INPUT>)
+ {
+ if (s/^(\s*)_(\w+=(.*))/$1$2/)
+ {
+ my $string = $3;
+
+ print OUTPUT;
+
+ my $non_translated_line = $_;
+
+ for my $lang (sort keys %po_files_by_lang)
+ {
+ my $translation = $translations{$lang, $string};
+ next if !$translation;
+
+ $_ = $non_translated_line;
+ s/(\w+)=.*/[$lang]$1=$translation/;
+ print OUTPUT;
+ }
+ }
+ else
+ {
+ print OUTPUT;
+ }
+ }
+
+ close OUTPUT;
+ close INPUT;
+}
+
+sub desktop_merge_translations
+{
+ open INPUT, "<${FILE}" or die;
+ open OUTPUT, ">${OUTFILE}" or die;
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+
+ while (<INPUT>)
+ {
+ if (s/^(\s*)_(\w+=(.*))/$1$2/)
+ {
+ my $string = $3;
+
+ print OUTPUT;
+
+ my $non_translated_line = $_;
+
+ for my $lang (sort keys %po_files_by_lang)
+ {
+ my $translation = $translations{$lang, $string};
+ next if !$translation;
+
+ $_ = $non_translated_line;
+ s/(\w+)=.*/${1}[$lang]=$translation/;
+ print OUTPUT;
+ }
+ }
+ else
+ {
+ print OUTPUT;
+ }
+ }
+
+ close OUTPUT;
+ close INPUT;
+}
+
+sub schemas_merge_translations
+{
+ my $source;
+
+ {
+ local $/; # slurp mode
+ open INPUT, "<$FILE" or die "can't open $FILE: $!";
+ $source = <INPUT>;
+ close INPUT;
+ }
+
+ open OUTPUT, ">$OUTFILE" or die;
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+
+ # FIXME: support attribute translations
+
+ # Empty nodes never need translation, so unmark all of them.
+ # For example, <_foo/> is just replaced by <foo/>.
+ $source =~ s|<\s*_($w+)\s*/>|<$1/>|g;
+
+ while ($source =~ s/
+ (.*?)
+ (\s+)(<locale\ name="C">(\s*)
+ (<default>\s*(?:<!--[^>]*?-->\s*)?(.*?)\s*<\/default>)?(\s*)
+ (<short>\s*(?:<!--[^>]*?-->\s*)?(.*?)\s*<\/short>)?(\s*)
+ (<long>\s*(?:<!--[^>]*?-->\s*)?(.*?)\s*<\/long>)?(\s*)
+ <\/locale>)
+ //sx)
+ {
+ print OUTPUT $1;
+
+ my $locale_start_spaces = $2 ? $2 : '';
+ my $default_spaces = $4 ? $4 : '';
+ my $short_spaces = $7 ? $7 : '';
+ my $long_spaces = $10 ? $10 : '';
+ my $locale_end_spaces = $13 ? $13 : '';
+ my $c_default_block = $3 ? $3 : '';
+ my $default_string = $6 ? $6 : '';
+ my $short_string = $9 ? $9 : '';
+ my $long_string = $12 ? $12 : '';
+
+ print OUTPUT "$locale_start_spaces$c_default_block";
+
+ $default_string =~ s/\s+/ /g;
+ $default_string = entity_decode($default_string);
+ $short_string =~ s/\s+/ /g;
+ $short_string = entity_decode($short_string);
+ $long_string =~ s/\s+/ /g;
+ $long_string = entity_decode($long_string);
+
+ for my $lang (sort keys %po_files_by_lang)
+ {
+ my $default_translation = $translations{$lang, $default_string};
+ my $short_translation = $translations{$lang, $short_string};
+ my $long_translation = $translations{$lang, $long_string};
+
+ next if (!$default_translation && !$short_translation &&
+ !$long_translation);
+
+ print OUTPUT "\n$locale_start_spaces<locale name=\"$lang\">";
+
+ print OUTPUT "$default_spaces";
+
+ if ($default_translation)
+ {
+ $default_translation = entity_encode($default_translation);
+ print OUTPUT "<default>$default_translation</default>";
+ }
+
+ print OUTPUT "$short_spaces";
+
+ if ($short_translation)
+ {
+ $short_translation = entity_encode($short_translation);
+ print OUTPUT "<short>$short_translation</short>";
+ }
+
+ print OUTPUT "$long_spaces";
+
+ if ($long_translation)
+ {
+ $long_translation = entity_encode($long_translation);
+ print OUTPUT "<long>$long_translation</long>";
+ }
+
+ print OUTPUT "$locale_end_spaces</locale>";
+ }
+ }
+
+ print OUTPUT $source;
+
+ close OUTPUT;
+}
+
+sub rfc822deb_merge_translations
+{
+ my %encodings = ();
+ for my $lang (keys %po_files_by_lang) {
+ $encodings{$lang} = ($UTF8_ARG ? 'UTF-8' : get_po_encoding($po_files_by_lang{$lang}));
+ }
+
+ my $source;
+
+ $Text::Wrap::huge = 'overflow';
+ $Text::Wrap::break = qr/\n|\s(?=\S)/;
+
+ {
+ local $/; # slurp mode
+ open INPUT, "<$FILE" or die "can't open $FILE: $!";
+ $source = <INPUT>;
+ close INPUT;
+ }
+
+ open OUTPUT, ">${OUTFILE}" or die;
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+
+ while ($source =~ /(^|\n+)(_*)([^:\s]+)(:[ \t]*)(.*?)(?=\n[\S\n]|$)/sg)
+ {
+ my $sep = $1;
+ my $non_translated_line = $3.$4;
+ my $string = $5;
+ my $underscore = length($2);
+ next if $underscore eq 0 && $non_translated_line =~ /^#/;
+ # Remove [] dummy strings
+ my $stripped = $string;
+ $stripped =~ s/\[\s[^\[\]]*\],/,/g if $underscore eq 2;
+ $stripped =~ s/\[\s[^\[\]]*\]$//;
+ $non_translated_line .= $stripped;
+
+ print OUTPUT $sep.$non_translated_line;
+
+ if ($underscore)
+ {
+ my @str_list = rfc822deb_split($underscore, $string);
+
+ for my $lang (sort keys %po_files_by_lang)
+ {
+ my $is_translated = 1;
+ my $str_translated = '';
+ my $first = 1;
+
+ for my $str (@str_list)
+ {
+ my $translation = $translations{$lang, $str};
+
+ if (!$translation)
+ {
+ $is_translated = 0;
+ last;
+ }
+
+ # $translation may also contain [] dummy
+ # strings, mostly to indicate an empty string
+ $translation =~ s/\[\s[^\[\]]*\]$//;
+
+ if ($first)
+ {
+ if ($underscore eq 2)
+ {
+ $str_translated .= $translation;
+ }
+ else
+ {
+ $str_translated .=
+ Text::Tabs::expand($translation) .
+ "\n";
+ }
+ }
+ else
+ {
+ if ($underscore eq 2)
+ {
+ $str_translated .= ', ' . $translation;
+ }
+ else
+ {
+ $str_translated .= Text::Tabs::expand(
+ Text::Wrap::wrap(' ', ' ', $translation)) .
+ "\n .\n";
+ }
+ }
+ $first = 0;
+
+ # To fix some problems with Text::Wrap::wrap
+ $str_translated =~ s/(\n )+\n/\n .\n/g;
+ }
+ next unless $is_translated;
+
+ $str_translated =~ s/\n \.\n$//;
+ $str_translated =~ s/\s+$//;
+
+ $_ = $non_translated_line;
+ s/^(\w+):\s*.*/$sep${1}-$lang.$encodings{$lang}: $str_translated/s;
+ print OUTPUT;
+ }
+ }
+ }
+ print OUTPUT "\n";
+
+ close OUTPUT;
+ close INPUT;
+}
+
+sub rfc822deb_split
+{
+ # Debian defines a special way to deal with rfc822-style files:
+ # when a value contain newlines, it consists of
+ # 1. a short form (first line)
+ # 2. a long description, all lines begin with a space,
+ # and paragraphs are separated by a single dot on a line
+ # This routine returns an array of all paragraphs, and reformat
+ # them.
+ # When first argument is 2, the string is a comma separated list of
+ # values.
+ my $type = shift;
+ my $text = shift;
+ $text =~ s/^[ \t]//mg;
+ return (split(/, */, $text, 0)) if $type ne 1;
+ return ($text) if $text !~ /\n/;
+
+ $text =~ s/([^\n]*)\n//;
+ my @list = ($1);
+ my $str = '';
+
+ for my $line (split (/\n/, $text))
+ {
+ chomp $line;
+ if ($line =~ /^\.\s*$/)
+ {
+ # New paragraph
+ $str =~ s/\s*$//;
+ push(@list, $str);
+ $str = '';
+ }
+ elsif ($line =~ /^\s/)
+ {
+ # Line which must not be reformatted
+ $str .= "\n" if length ($str) && $str !~ /\n$/;
+ $line =~ s/\s+$//;
+ $str .= $line."\n";
+ }
+ else
+ {
+ # Continuation line, remove newline
+ $str .= " " if length ($str) && $str !~ /\n$/;
+ $str .= $line;
+ }
+ }
+
+ $str =~ s/\s*$//;
+ push(@list, $str) if length ($str);
+
+ return @list;
+}
+
Added: trunk/intltool-update.in
===================================================================
--- trunk/intltool-update.in 2006-09-27 23:27:03 UTC (rev 3916)
+++ trunk/intltool-update.in 2006-09-28 17:46:36 UTC (rev 3917)
@@ -0,0 +1,1089 @@
+#! INTLTOOL_PERL@ -w
+# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+
+#
+# The Intltool Message Updater
+#
+# Copyright (C) 2000-2003 Free Software Foundation.
+#
+# Intltool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 published by the Free Software Foundation.
+#
+# Intltool 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, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+#
+# Authors: Kenneth Christiansen <kenneth gnu org>
+# Maciej Stachowiak
+# Darin Adler <darin bentspoon com>
+
+## Release information
+my $PROGRAM = "intltool-update";
+my $VERSION = "0.35.0";
+my $PACKAGE = "intltool";
+
+## Loaded modules
+use strict;
+use Getopt::Long;
+use Cwd;
+use File::Copy;
+use File::Find;
+
+## Scalars used by the option stuff
+my $HELP_ARG = 0;
+my $VERSION_ARG = 0;
+my $DIST_ARG = 0;
+my $POT_ARG = 0;
+my $HEADERS_ARG = 0;
+my $MAINTAIN_ARG = 0;
+my $REPORT_ARG = 0;
+my $VERBOSE = 0;
+my $GETTEXT_PACKAGE = "";
+my $OUTPUT_FILE = "";
+
+my @languages;
+my %varhash = ();
+my %po_files_by_lang = ();
+
+# Regular expressions to categorize file types.
+# FIXME: Please check if the following is correct
+
+my $xml_support =
+"xml(?:\\.in)*|". # http://www.w3.org/XML/ (Note: .in is not required)
+"ui|". # Bonobo specific - User Interface desc. files
+"lang|". # ?
+"glade2?(?:\\.in)*|". # Glade specific - User Interface desc. files (Note: .in is not required)
+"scm(?:\\.in)*|". # ? (Note: .in is not required)
+"oaf(?:\\.in)+|". # DEPRECATED: Replaces by Bonobo .server files
+"etspec|". # ?
+"server(?:\\.in)+|". # Bonobo specific
+"sheet(?:\\.in)+|". # ?
+"schemas(?:\\.in)+|". # GConf specific
+"pong(?:\\.in)+|". # DEPRECATED: PONG is not used [by GNOME] any longer.
+"kbd(?:\\.in)+"; # GOK specific.
+
+my $ini_support =
+"icon(?:\\.in)+|". # http://www.freedesktop.org/Standards/icon-theme-spec
+"desktop(?:\\.in)+|". # http://www.freedesktop.org/Standards/menu-spec
+"caves(?:\\.in)+|". # GNOME Games specific
+"directory(?:\\.in)+|". # http://www.freedesktop.org/Standards/menu-spec
+"soundlist(?:\\.in)+|". # GNOME specific
+"keys(?:\\.in)+|". # GNOME Mime database specific
+"theme(?:\\.in)+|". # http://www.freedesktop.org/Standards/icon-theme-spec
+"service(?:\\.in)+"; # DBus specific
+
+my $buildin_gettext_support =
+"c|y|cs|cc|cpp|c\\+\\+|h|hh|gob|py";
+
+## Always flush buffer when printing
+$| = 1;
+
+## Sometimes the source tree will be rooted somewhere else.
+my $SRCDIR = ".";
+my $POTFILES_in;
+
+$SRCDIR = $ENV{"srcdir"} if $ENV{"srcdir"};
+$POTFILES_in = "<$SRCDIR/POTFILES.in";
+
+my $devnull = ($^O eq 'MSWin32' ? 'NUL:' : '/dev/null');
+
+## Handle options
+GetOptions
+(
+ "help" => \$HELP_ARG,
+ "version" => \$VERSION_ARG,
+ "dist|d" => \$DIST_ARG,
+ "pot|p" => \$POT_ARG,
+ "headers|s" => \$HEADERS_ARG,
+ "maintain|m" => \$MAINTAIN_ARG,
+ "report|r" => \$REPORT_ARG,
+ "verbose|x" => \$VERBOSE,
+ "gettext-package|g=s" => \$GETTEXT_PACKAGE,
+ "output-file|o=s" => \$OUTPUT_FILE,
+ ) or &Console_WriteError_InvalidOption;
+
+&Console_Write_IntltoolHelp if $HELP_ARG;
+&Console_Write_IntltoolVersion if $VERSION_ARG;
+
+my $arg_count = ($DIST_ARG > 0)
+ + ($POT_ARG > 0)
+ + ($HEADERS_ARG > 0)
+ + ($MAINTAIN_ARG > 0)
+ + ($REPORT_ARG > 0);
+
+&Console_Write_IntltoolHelp if $arg_count > 1;
+
+# --version and --help don't require a module name
+my $MODULE = $GETTEXT_PACKAGE || &FindPackageName || "unknown";
+
+if ($POT_ARG)
+{
+ &GenerateHeaders;
+ &GeneratePOTemplate;
+}
+elsif ($HEADERS_ARG)
+{
+ &GenerateHeaders;
+}
+elsif ($MAINTAIN_ARG)
+{
+ &FindLeftoutFiles;
+}
+elsif ($REPORT_ARG)
+{
+ &GenerateHeaders;
+ &GeneratePOTemplate;
+ &Console_Write_CoverageReport;
+}
+elsif ((defined $ARGV[0]) && $ARGV[0] =~ /^[a-z]/)
+{
+ my $lang = $ARGV[0];
+
+ ## Report error if the language file supplied
+ ## to the command line is non-existent
+ &Console_WriteError_NotExisting("$SRCDIR/$lang.po")
+ if ! -s "$SRCDIR/$lang.po";
+
+ if (!$DIST_ARG)
+ {
+ print "Working, please wait..." if $VERBOSE;
+ &GenerateHeaders;
+ &GeneratePOTemplate;
+ }
+ &POFile_Update ($lang, $OUTPUT_FILE);
+ &Console_Write_TranslationStatus ($lang, $OUTPUT_FILE);
+}
+else
+{
+ &Console_Write_IntltoolHelp;
+}
+
+exit;
+
+#########
+
+sub Console_Write_IntltoolVersion
+{
+ print <<_EOF_;
+${PROGRAM} (${PACKAGE}) $VERSION
+Written by Kenneth Christiansen, Maciej Stachowiak, and Darin Adler.
+
+Copyright (C) 2000-2003 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+_EOF_
+ exit;
+}
+
+sub Console_Write_IntltoolHelp
+{
+ print <<_EOF_;
+Usage: ${PROGRAM} [OPTION]... LANGCODE
+Updates PO template files and merge them with the translations.
+
+Mode of operation (only one is allowed):
+ -p, --pot generate the PO template only
+ -s, --headers generate the header files in POTFILES.in
+ -m, --maintain search for left out files from POTFILES.in
+ -r, --report display a status report for the module
+ -d, --dist merge LANGCODE.po with existing PO template
+
+Extra options:
+ -g, --gettext-package=NAME override PO template name, useful with --pot
+ -o, --output-file=FILE write merged translation to FILE
+ -x, --verbose display lots of feedback
+ --help display this help and exit
+ --version output version information and exit
+
+Examples of use:
+${PROGRAM} --pot just create a new PO template
+${PROGRAM} xy create new PO template and merge xy.po with it
+
+Report bugs to http://bugzilla.gnome.org/ (product name "$PACKAGE")
+or send email to <xml-i18n-tools\ gnome org>.
+_EOF_
+ exit;
+}
+
+sub echo_n
+{
+ my $str = shift;
+ my $ret = `echo "$str"`;
+
+ $ret =~ s/\n$//; # do we need the "s" flag?
+
+ return $ret;
+}
+
+sub POFile_DetermineType ($)
+{
+ my $type = $_;
+ my $gettext_type;
+
+ my $xml_regex = "(?:" . $xml_support . ")";
+ my $ini_regex = "(?:" . $ini_support . ")";
+ my $buildin_regex = "(?:" . $buildin_gettext_support . ")";
+
+ if ($type =~ /\[type: gettext\/([^\]].*)]/)
+ {
+ $gettext_type=$1;
+ }
+ elsif ($type =~ /schemas(\.in)+$/)
+ {
+ $gettext_type="schemas";
+ }
+ elsif ($type =~ /glade2?(\.in)*$/)
+ {
+ $gettext_type="glade";
+ }
+ elsif ($type =~ /scm(\.in)*$/)
+ {
+ $gettext_type="scheme";
+ }
+ elsif ($type =~ /keys(\.in)+$/)
+ {
+ $gettext_type="keys";
+ }
+
+ # bucket types
+
+ elsif ($type =~ /$xml_regex$/)
+ {
+ $gettext_type="xml";
+ }
+ elsif ($type =~ /$ini_regex$/)
+ {
+ $gettext_type="ini";
+ }
+ elsif ($type =~ /$buildin_regex$/)
+ {
+ $gettext_type="buildin";
+ }
+ else
+ {
+ $gettext_type="unknown";
+ }
+
+ return "gettext\/$gettext_type";
+}
+
+sub TextFile_DetermineEncoding ($)
+{
+ my $gettext_code="ASCII"; # All files are ASCII by default
+ my $filetype=`file $_ | cut -d ' ' -f 2`;
+
+ if ($? eq "0")
+ {
+ if ($filetype =~ /^(ISO|UTF)/)
+ {
+ chomp ($gettext_code = $filetype);
+ }
+ elsif ($filetype =~ /^XML/)
+ {
+ $gettext_code="UTF-8"; # We asume that .glade and other .xml files are UTF-8
+ }
+ }
+
+ return $gettext_code;
+}
+
+sub isNotValidMissing
+{
+ my ($file) = @_;
+
+ return if $file =~ /^\{arch\}\/.*$/;
+ return if $file =~ /^$varhash{"PACKAGE"}-$varhash{"VERSION"}\/.*$/;
+}
+
+sub FindLeftoutFiles
+{
+ my (@buf_i18n_plain,
+ @buf_i18n_xml,
+ @buf_i18n_xml_unmarked,
+ @buf_i18n_ini,
+ @buf_potfiles,
+ @buf_potfiles_ignore,
+ @buf_allfiles,
+ @buf_allfiles_sorted,
+ @buf_potfiles_sorted
+ );
+
+ ## Search and find all translatable files
+ find sub {
+ push @buf_i18n_plain, "$File::Find::name" if /\.($buildin_gettext_support)$/;
+ push @buf_i18n_xml, "$File::Find::name" if /\.($xml_support)$/;
+ push @buf_i18n_ini, "$File::Find::name" if /\.($ini_support)$/;
+ push @buf_i18n_xml_unmarked, "$File::Find::name" if /\.(schemas(\.in)+)$/;
+ }, "..";
+
+
+ open POTFILES, $POTFILES_in or die "$PROGRAM: there's no POTFILES.in!\n";
+ @buf_potfiles = grep !/^(#|\s*$)/, <POTFILES>;
+ close POTFILES;
+
+ foreach (@buf_potfiles) {
+ s/^\[.*]\s*//;
+ }
+
+ print "Searching for missing translatable files...\n" if $VERBOSE;
+
+ ## Check if we should ignore some found files, when
+ ## comparing with POTFILES.in
+ foreach my $ignore ("POTFILES.skip", "POTFILES.ignore")
+ {
+ (-s $ignore) or next;
+
+ if ("$ignore" eq "POTFILES.ignore")
+ {
+ print "The usage of POTFILES.ignore is deprecated. Please consider moving the\n".
+ "content of this file to POTFILES.skip.\n";
+ }
+
+ print "Found $ignore: Ignoring files...\n" if $VERBOSE;
+ open FILE, "<$ignore" or die "ERROR: Failed to open $ignore!\n";
+
+ while (<FILE>)
+ {
+ push @buf_potfiles_ignore, $_ unless /^(#|\s*$)/;
+ }
+ close FILE;
+
+ @buf_potfiles = (@buf_potfiles_ignore, @buf_potfiles);
+ }
+
+ foreach my $file (@buf_i18n_plain)
+ {
+ my $in_comment = 0;
+ my $in_macro = 0;
+
+ open FILE, "<$file";
+ while (<FILE>)
+ {
+ # Handle continued multi-line comment.
+ if ($in_comment)
+ {
+ next unless s-.*\*/--;
+ $in_comment = 0;
+ }
+
+ # Handle continued macro.
+ if ($in_macro)
+ {
+ $in_macro = 0 unless /\\$/;
+ next;
+ }
+
+ # Handle start of macro (or any preprocessor directive).
+ if (/^\s*\#/)
+ {
+ $in_macro = 1 if /^([^\\]|\\.)*\\$/;
+ next;
+ }
+
+ # Handle comments and quoted text.
+ while (m-(/\*|//|\'|\")-) # \' and \" keep emacs perl mode happy
+ {
+ my $match = $1;
+ if ($match eq "/*")
+ {
+ if (!s-/\*.*?\*/--)
+ {
+ s-/\*.*--;
+ $in_comment = 1;
+ }
+ }
+ elsif ($match eq "//")
+ {
+ s-//.*--;
+ }
+ else # ' or "
+ {
+ if (!s-$match([^\\]|\\.)*?$match-QUOTEDTEXT-)
+ {
+ warn "mismatched quotes at line $. in $file\n";
+ s-$match.*--;
+ }
+ }
+ }
+
+ if (/\.GetString ?\(QUOTEDTEXT/)
+ {
+ if (defined isNotValidMissing (unpack("x3 A*", $file))) {
+ ## Remove the first 3 chars and add newline
+ push @buf_allfiles, unpack("x3 A*", $file) . "\n";
+ }
+ last;
+ }
+
+ if (/_\(QUOTEDTEXT/)
+ {
+ if (defined isNotValidMissing (unpack("x3 A*", $file))) {
+ ## Remove the first 3 chars and add newline
+ push @buf_allfiles, unpack("x3 A*", $file) . "\n";
+ }
+ last;
+ }
+ }
+ close FILE;
+ }
+
+ foreach my $file (@buf_i18n_xml)
+ {
+ open FILE, "<$file";
+
+ while (<FILE>)
+ {
+ # FIXME: share the pattern matching code with intltool-extract
+ if (/\s_[-A-Za-z0-9._:]+\s*=\s*\"([^"]+)\"/ || /<_[^>]+>/ || /translatable=\"yes\"/)
+ {
+ if (defined isNotValidMissing (unpack("x3 A*", $file))) {
+ push @buf_allfiles, unpack("x3 A*", $file) . "\n";
+ }
+ last;
+ }
+ }
+ close FILE;
+ }
+
+ foreach my $file (@buf_i18n_ini)
+ {
+ open FILE, "<$file";
+ while (<FILE>)
+ {
+ if (/_(.*)=/)
+ {
+ if (defined isNotValidMissing (unpack("x3 A*", $file))) {
+ push @buf_allfiles, unpack("x3 A*", $file) . "\n";
+ }
+ last;
+ }
+ }
+ close FILE;
+ }
+
+ foreach my $file (@buf_i18n_xml_unmarked)
+ {
+ if (defined isNotValidMissing (unpack("x3 A*", $file))) {
+ push @buf_allfiles, unpack("x3 A*", $file) . "\n";
+ }
+ }
+
+
+ @buf_allfiles_sorted = sort (@buf_allfiles);
+ @buf_potfiles_sorted = sort (@buf_potfiles);
+
+ my %in2;
+ foreach (@buf_potfiles_sorted)
+ {
+ $in2{$_} = 1;
+ }
+
+ my @result;
+
+ foreach (@buf_allfiles_sorted)
+ {
+ if (!exists($in2{$_}))
+ {
+ push @result, $_
+ }
+ }
+
+ my @buf_potfiles_notexist;
+
+ foreach (@buf_potfiles_sorted)
+ {
+ chomp (my $dummy = $_);
+ if ("$dummy" ne "" and ! -f "../$dummy")
+ {
+ push @buf_potfiles_notexist, $_;
+ }
+ }
+
+ ## Save file with information about the files missing
+ ## if any, and give information about this procedure.
+ if (@result + @buf_potfiles_notexist > 0)
+ {
+ if (@result)
+ {
+ print "\n" if $VERBOSE;
+ unlink "missing";
+ open OUT, ">missing";
+ print OUT @result;
+ close OUT;
+ warn "\e[1mThe following files contain translations and are currently not in use. Please\e[0m\n".
+ "\e[1mconsider adding these to the POTFILES.in file, located in the po/ directory.\e[0m\n\n";
+ print STDERR @result, "\n";
+ warn "If some of these files are left out on purpose then please add them to\n".
+ "POTFILES.skip instead of POTFILES.in. A file \e[1m'missing'\e[0m containing this list\n".
+ "of left out files has been written in the current directory.\n";
+ }
+ if (@buf_potfiles_notexist)
+ {
+ unlink "notexist";
+ open OUT, ">notexist";
+ print OUT @buf_potfiles_notexist;
+ close OUT;
+ warn "\n" if ($VERBOSE or @result);
+ warn "\e[1mThe following files do not exist anymore:\e[0m\n\n";
+ warn @buf_potfiles_notexist, "\n";
+ warn "Please remove them from POTFILES.in or POTFILES.skip. A file \e[1m'notexist'\e[0m\n".
+ "containing this list of absent files has been written in the current directory.\n";
+ }
+ }
+
+ ## If there is nothing to complain about, notify the user
+ else {
+ print "\nAll files containing translations are present in POTFILES.in.\n" if $VERBOSE;
+ }
+}
+
+sub Console_WriteError_InvalidOption
+{
+ ## Handle invalid arguments
+ print STDERR "Try `${PROGRAM} --help' for more information.\n";
+ exit 1;
+}
+
+sub GenerateHeaders
+{
+ my $EXTRACT = "@INTLTOOL_EXTRACT@";
+ chomp $EXTRACT;
+
+ $EXTRACT = $ENV{"INTLTOOL_EXTRACT"} if $ENV{"INTLTOOL_EXTRACT"};
+
+ ## Generate the .h header files, so we can allow glade and
+ ## xml translation support
+ if (! -x "$EXTRACT")
+ {
+ print STDERR "\n *** The intltool-extract script wasn't found!"
+ ."\n *** Without it, intltool-update can not generate files.\n";
+ exit;
+ }
+ else
+ {
+ open (FILE, $POTFILES_in) or die "$PROGRAM: POTFILES.in not found.\n";
+
+ while (<FILE>)
+ {
+ chomp;
+ next if /^\[\s*encoding/;
+
+ ## Find xml files in POTFILES.in and generate the
+ ## files with help from the extract script
+
+ my $gettext_type= &POFile_DetermineType ($1);
+
+ if (/\.($xml_support|$ini_support)$/ || /^\[/)
+ {
+ s/^\[[^\[].*]\s*//;
+
+ my $filename = "../$_";
+
+ if ($VERBOSE)
+ {
+ system ($EXTRACT, "--update", "--srcdir=$SRCDIR",
+ "--type=$gettext_type", $filename);
+ }
+ else
+ {
+ system ($EXTRACT, "--update", "--type=$gettext_type",
+ "--srcdir=$SRCDIR", "--quiet", $filename);
+ }
+ }
+ }
+ close FILE;
+ }
+}
+
+#
+# Generate .pot file from POTFILES.in
+#
+sub GeneratePOTemplate
+{
+ my $XGETTEXT = $ENV{"XGETTEXT"} || "@INTLTOOL_XGETTEXT@";
+ my $XGETTEXT_ARGS = $ENV{"XGETTEXT_ARGS"} || '';
+ chomp $XGETTEXT;
+
+ if (! -x $XGETTEXT)
+ {
+ print STDERR " *** xgettext is not found on this system!\n".
+ " *** Without it, intltool-update can not extract strings.\n";
+ exit;
+ }
+
+ print "Building $MODULE.pot...\n" if $VERBOSE;
+
+ open INFILE, $POTFILES_in;
+ unlink "POTFILES.in.temp";
+ open OUTFILE, ">POTFILES.in.temp" or die("Cannot open POTFILES.in.temp for writing");
+
+ my $gettext_support_nonascii = 0;
+
+ # checks for GNU gettext >= 0.12
+ my $dummy = `$XGETTEXT --version --from-code=UTF-8 >$devnull 2>$devnull`;
+ if ($? == 0)
+ {
+ $gettext_support_nonascii = 1;
+ }
+ else
+ {
+ # urge everybody to upgrade gettext
+ print STDERR "WARNING: This version of gettext does not support extracting non-ASCII\n".
+ " strings. That means you should install a version of gettext\n".
+ " that supports non-ASCII strings (such as GNU gettext >= 0.12),\n".
+ " or have to let non-ASCII strings untranslated. (If there is any)\n";
+ }
+
+ my $encoding = "ASCII";
+ my $forced_gettext_code;
+ my @temp_headers;
+ my $encoding_problem_is_reported = 0;
+
+ while (<INFILE>)
+ {
+ next if (/^#/ or /^\s*$/);
+
+ chomp;
+
+ my $gettext_code;
+
+ if (/^\[\s*encoding:\s*(.*)\s*\]/)
+ {
+ $forced_gettext_code=$1;
+ }
+ elsif (/\.($xml_support|$ini_support)$/ || /^\[/)
+ {
+ s/^\[.*]\s*//;
+ print OUTFILE "../$_.h\n";
+ push @temp_headers, "../$_.h";
+ $gettext_code = &TextFile_DetermineEncoding ("../$_.h") if ($gettext_support_nonascii and not defined $forced_gettext_code);
+ }
+ else
+ {
+ if ($SRCDIR eq ".") {
+ print OUTFILE "../$_\n";
+ } else {
+ print OUTFILE "$SRCDIR/../$_\n";
+ }
+ $gettext_code = &TextFile_DetermineEncoding ("../$_") if ($gettext_support_nonascii and not defined $forced_gettext_code);
+ }
+
+ next if (! $gettext_support_nonascii);
+
+ if (defined $forced_gettext_code)
+ {
+ $encoding=$forced_gettext_code;
+ }
+ elsif (defined $gettext_code and "$encoding" ne "$gettext_code")
+ {
+ if ($encoding eq "ASCII")
+ {
+ $encoding=$gettext_code;
+ }
+ elsif ($gettext_code ne "ASCII")
+ {
+ # Only report once because the message is quite long
+ if (! $encoding_problem_is_reported)
+ {
+ print STDERR "WARNING: You should use the same file encoding for all your project files,\n".
+ " but $PROGRAM thinks that most of the source files are in\n".
+ " $encoding encoding, while \"$_\" is (likely) in\n".
+ " $gettext_code encoding. If you are sure that all translatable strings\n".
+ " are in same encoding (say UTF-8), please \e[1m*prepend*\e[0m the following\n".
+ " line to POTFILES.in:\n\n".
+ " [encoding: UTF-8]\n\n".
+ " and make sure that configure.in/ac checks for $PACKAGE >= 0.27 .\n".
+ "(such warning message will only be reported once.)\n";
+ $encoding_problem_is_reported = 1;
+ }
+ }
+ }
+ }
+
+ close OUTFILE;
+ close INFILE;
+
+ unlink "$MODULE.pot";
+ my @xgettext_argument=("$XGETTEXT",
+ "--add-comments",
+ "--directory\=\.",
+ "--output\=$MODULE\.pot",
+ "--files-from\=\.\/POTFILES\.in\.temp");
+ my $XGETTEXT_KEYWORDS = &FindPOTKeywords;
+ push @xgettext_argument, $XGETTEXT_KEYWORDS;
+ my $MSGID_BUGS_ADDRESS = &FindMakevarsBugAddress;
+ push @xgettext_argument, "--msgid-bugs-address\=$MSGID_BUGS_ADDRESS" if $MSGID_BUGS_ADDRESS;
+ push @xgettext_argument, "--from-code\=$encoding" if ($gettext_support_nonascii);
+ push @xgettext_argument, $XGETTEXT_ARGS if $XGETTEXT_ARGS;
+ my $xgettext_command = join ' ', @xgettext_argument;
+
+ # intercept xgettext error message
+ print "Running $xgettext_command\n" if $VERBOSE;
+ my $xgettext_error_msg = `$xgettext_command 2>\&1`;
+ my $command_failed = $?;
+
+ unlink "POTFILES.in.temp";
+
+ print "Removing generated header (.h) files..." if $VERBOSE;
+ unlink foreach (@temp_headers);
+ print "done.\n" if $VERBOSE;
+
+ if (! $command_failed)
+ {
+ if (! -e "$MODULE.pot")
+ {
+ print "None of the files in POTFILES.in contain strings marked for translation.\n" if $VERBOSE;
+ }
+ else
+ {
+ print "Wrote $MODULE.pot\n" if $VERBOSE;
+ }
+ }
+ else
+ {
+ if ($xgettext_error_msg =~ /--from-code/)
+ {
+ # replace non-ASCII error message with a more useful one.
+ print STDERR "ERROR: xgettext failed to generate PO template file because there is non-ASCII\n".
+ " string marked for translation. Please make sure that all strings marked\n".
+ " for translation are in uniform encoding (say UTF-8), then \e[1m*prepend*\e[0m the\n".
+ " following line to POTFILES.in and rerun $PROGRAM:\n\n".
+ " [encoding: UTF-8]\n\n";
+ }
+ else
+ {
+ print STDERR "$xgettext_error_msg";
+ if (-e "$MODULE.pot")
+ {
+ # is this possible?
+ print STDERR "ERROR: xgettext failed but still managed to generate PO template file.\n".
+ " Please consult error message above if there is any.\n";
+ }
+ else
+ {
+ print STDERR "ERROR: xgettext failed to generate PO template file. Please consult\n".
+ " error message above if there is any.\n";
+ }
+ }
+ exit (1);
+ }
+}
+
+sub POFile_Update
+{
+ -f "$MODULE.pot" or die "$PROGRAM: $MODULE.pot does not exist.\n";
+
+ my $MSGMERGE = $ENV{"MSGMERGE"} || "@INTLTOOL_MSGMERGE@";
+ my ($lang, $outfile) = @_;
+
+ print "Merging $SRCDIR/$lang.po with $MODULE.pot..." if $VERBOSE;
+
+ my $infile = "$SRCDIR/$lang.po";
+ $outfile = "$SRCDIR/$lang.po" if ($outfile eq "");
+
+ # I think msgmerge won't overwrite old file if merge is not successful
+ system ("$MSGMERGE", "-o", $outfile, $infile, "$MODULE.pot");
+}
+
+sub Console_WriteError_NotExisting
+{
+ my ($file) = @_;
+
+ ## Report error if supplied language file is non-existing
+ print STDERR "$PROGRAM: $file does not exist!\n";
+ print STDERR "Try '$PROGRAM --help' for more information.\n";
+ exit;
+}
+
+sub GatherPOFiles
+{
+ my @po_files = glob ("./*.po");
+
+ @languages = map (&POFile_GetLanguage, @po_files);
+
+ foreach my $lang (@languages)
+ {
+ $po_files_by_lang{$lang} = shift (@po_files);
+ }
+}
+
+sub POFile_GetLanguage ($)
+{
+ s/^(.*\/)?(.+)\.po$/$2/;
+ return $_;
+}
+
+sub Console_Write_TranslationStatus
+{
+ my ($lang, $output_file) = @_;
+ my $MSGFMT = $ENV{"MSGFMT"} || "@INTLTOOL_MSGFMT@";
+
+ $output_file = "$SRCDIR/$lang.po" if ($output_file eq "");
+
+ system ("$MSGFMT", "-o", "$devnull", "--verbose", $output_file);
+}
+
+sub Console_Write_CoverageReport
+{
+ my $MSGFMT = $ENV{"MSGFMT"} || "@INTLTOOL_MSGFMT@";
+
+ &GatherPOFiles;
+
+ foreach my $lang (@languages)
+ {
+ print "$lang: ";
+ &POFile_Update ($lang, "");
+ }
+
+ print "\n\n * Current translation support in $MODULE \n\n";
+
+ foreach my $lang (@languages)
+ {
+ print "$lang: ";
+ system ("$MSGFMT", "-o", "$devnull", "--verbose", "$SRCDIR/$lang.po");
+ }
+}
+
+sub SubstituteVariable
+{
+ my ($str) = @_;
+
+ # always need to rewind file whenever it has been accessed
+ seek (CONF, 0, 0);
+
+ # cache each variable. varhash is global to we can add
+ # variables elsewhere.
+ while (<CONF>)
+ {
+ if (/^(\w+)=(.*)$/)
+ {
+ ($varhash{$1} = $2) =~ s/^["'](.*)["']$/$1/;
+ }
+ }
+
+ if ($str =~ /^(.*)\${?([A-Z_]+)}?(.*)$/)
+ {
+ my $rest = $3;
+ my $untouched = $1;
+ my $sub = "";
+ # Ignore recursive definitions of variables
+ $sub = $varhash{$2} if defined $varhash{$2} and $varhash{$2} !~ /\${?$2}?/;
+
+ return SubstituteVariable ("$untouched$sub$rest");
+ }
+
+ # We're using Perl backticks ` and "echo -n" here in order to
+ # expand any shell escapes (such as backticks themselves) in every variable
+ return echo_n ($str);
+}
+
+sub CONF_Handle_Open
+{
+ my $base_dirname = getcwd();
+ $base_dirname =~ s */@@;
+
+ my ($conf_in, $src_dir);
+
+ if ($base_dirname =~ /^po(-.+)?$/)
+ {
+ if (-f "Makevars")
+ {
+ my $makefile_source;
+
+ local (*IN);
+ open (IN, "<Makevars") || die "can't open Makevars: $!";
+
+ while (<IN>)
+ {
+ if (/^top_builddir[ \t]*=/)
+ {
+ $src_dir = $_;
+ $src_dir =~ s/^top_builddir[ \t]*=[ \t]*([^ \t\n\r]*)/$1/;
+
+ chomp $src_dir;
+ if (-f "$src_dir" . "/configure.ac") {
+ $conf_in = "$src_dir" . "/configure.ac" . "\n";
+ } else {
+ $conf_in = "$src_dir" . "/configure.in" . "\n";
+ }
+ last;
+ }
+ }
+ close IN;
+
+ $conf_in || die "Cannot find top_builddir in Makevars.";
+ }
+ elsif (-f "../configure.ac")
+ {
+ $conf_in = "../configure.ac";
+ }
+ elsif (-f "../configure.in")
+ {
+ $conf_in = "../configure.in";
+ }
+ else
+ {
+ my $makefile_source;
+
+ local (*IN);
+ open (IN, "<Makefile") || return;
+
+ while (<IN>)
+ {
+ if (/^top_srcdir[ \t]*=/)
+ {
+ $src_dir = $_;
+ $src_dir =~ s/^top_srcdir[ \t]*=[ \t]*([^ \t\n\r]*)/$1/;
+
+ chomp $src_dir;
+ $conf_in = "$src_dir" . "/configure.in" . "\n";
+
+ last;
+ }
+ }
+ close IN;
+
+ $conf_in || die "Cannot find top_srcdir in Makefile.";
+ }
+
+ open (CONF, "<$conf_in");
+ }
+ else
+ {
+ print STDERR "$PROGRAM: Unable to proceed.\n" .
+ "Make sure to run this script inside the po directory.\n";
+ exit;
+ }
+}
+
+sub FindPackageName
+{
+ my $version;
+ my $domain = &FindMakevarsDomain;
+ my $name = $domain || "untitled";
+
+ &CONF_Handle_Open;
+
+ my $conf_source; {
+ local (*IN);
+ open (IN, "<&CONF") || return $name;
+ seek (IN, 0, 0);
+ local $/; # slurp mode
+ $conf_source = <IN>;
+ close IN;
+ }
+
+ # priority for getting package name:
+ # 1. GETTEXT_PACKAGE
+ # 2. first argument of AC_INIT (with >= 2 arguments)
+ # 3. first argument of AM_INIT_AUTOMAKE (with >= 2 argument)
+
+ # /^AM_INIT_AUTOMAKE\([\s\[]*([^,\)\s\]]+)/m
+ # the \s makes this not work, why?
+ if ($conf_source =~ /^AM_INIT_AUTOMAKE\(([^,\)]+),([^,\)]+)/m)
+ {
+ ($name, $version) = ($1, $2);
+ $name =~ s/[\[\]\s]//g;
+ $version =~ s/[\[\]\s]//g;
+ $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/);
+ $varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/);
+ $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/);
+ $varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/);
+ }
+
+ if ($conf_source =~ /^AC_INIT\(([^,\)]+),([^,\)]+)/m)
+ {
+ ($name, $version) = ($1, $2);
+ $name =~ s/[\[\]\s]//g;
+ $version =~ s/[\[\]\s]//g;
+ $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/);
+ $varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/);
+ $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/);
+ $varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/);
+ }
+
+ # \s makes this not work, why?
+ $name = $1 if $conf_source =~ /^GETTEXT_PACKAGE=\[?([^\n\]]+)/m;
+
+ # m4 macros AC_PACKAGE_NAME, AC_PACKAGE_VERSION etc. have same value
+ # as corresponding $PACKAGE_NAME, $PACKAGE_VERSION etc. shell variables.
+ $name =~ s/\bAC_PACKAGE_/\$PACKAGE_/g;
+
+ $name = $domain if $domain;
+
+ $name = SubstituteVariable ($name);
+ $name =~ s/^["'](.*)["']$/$1/;
+
+ return $name if $name;
+}
+
+
+sub FindPOTKeywords
+{
+
+ my $keywords = "--keyword\=\_ --keyword\=N\_ --keyword\=U\_ --keyword\=Q\_";
+ my $varname = "XGETTEXT_OPTIONS";
+ my $make_source; {
+ local (*IN);
+ open (IN, "<Makevars") || (open(IN, "<Makefile.in.in") && ($varname = "XGETTEXT_KEYWORDS")) || return $keywords;
+ seek (IN, 0, 0);
+ local $/; # slurp mode
+ $make_source = <IN>;
+ close IN;
+ }
+
+ $keywords = $1 if $make_source =~ /^$varname[ ]*=\[?([^\n\]]+)/m;
+
+ return $keywords;
+}
+
+sub FindMakevarsDomain
+{
+
+ my $domain = "";
+ my $makevars_source; {
+ local (*IN);
+ open (IN, "<Makevars") || return $domain;
+ seek (IN, 0, 0);
+ local $/; # slurp mode
+ $makevars_source = <IN>;
+ close IN;
+ }
+
+ $domain = $1 if $makevars_source =~ /^DOMAIN[ ]*=\[?([^\n\]\$]+)/m;
+ $domain =~ s/^\s+//;
+ $domain =~ s/\s+$//;
+
+ return $domain;
+}
+
+sub FindMakevarsBugAddress
+{
+
+ my $address = "";
+ my $makevars_source; {
+ local (*IN);
+ open (IN, "<Makevars") || return undef;
+ seek (IN, 0, 0);
+ local $/; # slurp mode
+ $makevars_source = <IN>;
+ close IN;
+ }
+
+ $address = $1 if $makevars_source =~ /^MSGID_BUGS_ADDRESS[ ]*=\[?([^\n\]\$]+)/m;
+ $address =~ s/^\s+//;
+ $address =~ s/\s+$//;
+
+ return $address;
+}
Added: trunk/po/Makefile.intltool
===================================================================
--- trunk/po/Makefile.intltool 2006-09-27 23:27:03 UTC (rev 3916)
+++ trunk/po/Makefile.intltool 2006-09-28 17:46:36 UTC (rev 3917)
@@ -0,0 +1,221 @@
+# Makefile for program source directory in GNU NLS utilities package.
+# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper gnu ai mit edu>
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+#
+# - Modified by Owen Taylor <otaylor redhat com> to use GETTEXT_PACKAGE
+# instead of PACKAGE and to look for po2tbl in ./ not in intl/
+#
+# - Modified by jacob berkman <jacob ximian com> to install
+# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize
+#
+# - Modified by Rodney Dawes <dobey novell com> for use with intltool
+#
+# We have the following line for use by intltoolize:
+# INTLTOOL_MAKEFILE
+
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ..
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datadir = @datadir@
+datarootdir = @datarootdir@
+libdir = @libdir@
+DATADIRNAME = @DATADIRNAME@
+itlocaledir = $(prefix)/$(DATADIRNAME)/locale
+subdir = po
+install_sh = @install_sh@
+# Automake >= 1.8 provides @mkdir_p
+# Until it can be supposed, use the safe fallback:
+mkdir_p = $(install_sh) -d
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+
+GMSGFMT = @GMSGFMT@
+MSGFMT = @MSGFMT@
+XGETTEXT = @XGETTEXT@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+MSGMERGE = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist
+GENPOT = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot
+
+ALL_LINGUAS = @ALL_LINGUAS@
+
+PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; fi)
+
+POFILES=$(shell if test -n "$(PO_LINGUAS)"; then LINGUAS="$(PO_LINGUAS)"; else LINGUAS="$(ALL_LINGUAS)"; fi; for lang in $$LINGUAS; do printf "$$lang.po "; done)
+
+DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(POFILES)
+EXTRA_DISTFILES = POTFILES.skip Makevars LINGUAS
+
+POTFILES = \
+#This Gets Replace for some reason
+
+CATALOGS=$(shell if test -n "$(PO_LINGUAS)"; then LINGUAS="$(PO_LINGUAS)"; else LINGUAS="$(ALL_LINGUAS)"; fi; for lang in $$LINGUAS; do printf "$$lang.gmo "; done)
+
+.SUFFIXES:
+.SUFFIXES: .po .pox .gmo .mo .msg .cat
+
+.po.pox:
+ $(MAKE) $(GETTEXT_PACKAGE).pot
+ $(MSGMERGE) $< $(GETTEXT_PACKAGE).pot -o $*.pox
+
+.po.mo:
+ $(MSGFMT) -o $@ $<
+
+.po.gmo:
+ file=`echo $* | sed 's,.*/,,'`.gmo \
+ && rm -f $$file && $(GMSGFMT) -o $$file $<
+
+.po.cat:
+ sed -f ../intl/po2msg.sed < $< > $*.msg \
+ && rm -f $@ && gencat $@ $*.msg
+
+
+all: all- USE_NLS@
+
+all-yes: $(CATALOGS)
+all-no:
+
+$(GETTEXT_PACKAGE).pot: $(POTFILES)
+ $(GENPOT)
+
+install: install-data
+install-data: install-data- USE_NLS@
+install-data-no: all
+install-data-yes: all
+ $(mkdir_p) $(DESTDIR)$(itlocaledir)
+ if test -n "$(PO_LINGUAS)"; then \
+ linguas="$(PO_LINGUAS)"; \
+ else \
+ linguas="$(ALL_LINGUAS)"; \
+ fi; \
+ for lang in $$linguas; do \
+ dir=$(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES; \
+ $(mkdir_p) $$dir; \
+ if test -r $$lang.gmo; then \
+ $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \
+ echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \
+ else \
+ $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \
+ echo "installing $(srcdir)/$$lang.gmo as" \
+ "$$dir/$(GETTEXT_PACKAGE).mo"; \
+ fi; \
+ if test -r $$lang.gmo.m; then \
+ $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \
+ echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \
+ else \
+ if test -r $(srcdir)/$$lang.gmo.m ; then \
+ $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \
+ $$dir/$(GETTEXT_PACKAGE).mo.m; \
+ echo "installing $(srcdir)/$$lang.gmo.m as" \
+ "$$dir/$(GETTEXT_PACKAGE).mo.m"; \
+ else \
+ true; \
+ fi; \
+ fi; \
+ done
+
+# Empty stubs to satisfy archaic automake needs
+dvi info tags TAGS ID:
+
+# Define this as empty until I found a useful application.
+installcheck:
+
+uninstall:
+ if test -n "$(PO_LINGUAS)"; then \
+ linguas="$(PO_LINGUAS)"; \
+ else \
+ linguas="$(ALL_LINGUAS)"; \
+ fi; \
+ for lang in $$linguas; do \
+ rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \
+ rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \
+ done
+
+check: all $(GETTEXT_PACKAGE).pot
+
+mostlyclean:
+ rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp
+ rm -f .intltool-merge-cache
+
+clean: mostlyclean
+
+distclean: clean
+ rm -f Makefile Makefile.in POTFILES stamp-it
+ rm -f *.mo *.msg *.cat *.cat.m *.gmo
+
+maintainer-clean: distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ rm -f Makefile.in.in
+
+distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir: $(DISTFILES)
+ dists="$(DISTFILES)"; \
+ extra_dists="$(EXTRA_DISTFILES)"; \
+ for file in $$extra_dists; do \
+ test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \
+ done; \
+ for file in $$dists; do \
+ test -f $$file || file="$(srcdir)/$$file"; \
+ ln $$file $(distdir) 2> /dev/null \
+ || cp -p $$file $(distdir); \
+ done
+
+update-po: Makefile
+ $(MAKE) $(GETTEXT_PACKAGE).pot
+ tmpdir=`pwd`; \
+ if test -n "$(PO_LINGUAS)"; then \
+ linguas="$(PO_LINGUAS)"; \
+ else \
+ linguas="$(ALL_LINGUAS)"; \
+ fi; \
+ for lang in $$linguas; do \
+ echo "$$lang:"; \
+ result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \
+ if $$result; then \
+ if cmp $(srcdir)/$$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; \
+ rm -f $$tmpdir/$$lang.new.po; \
+ exit 1; \
+ fi; \
+ fi; \
+ else \
+ echo "msgmerge for $$lang.gmo failed!"; \
+ rm -f $$tmpdir/$$lang.new.po; \
+ fi; \
+ done
+
+Makefile POTFILES: stamp-it
+ @if test ! -f $@; then \
+ rm -f stamp-it; \
+ $(MAKE) stamp-it; \
+ fi
+
+stamp-it: Makefile.in.in ../config.status POTFILES.in
+ cd .. \
+ && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \
+ $(SHELL) ./config.status
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Modified: trunk/po/intltool-scm-35.diff
===================================================================
--- trunk/po/intltool-scm-35.diff 2006-09-27 23:27:03 UTC (rev 3916)
+++ trunk/po/intltool-scm-35.diff 2006-09-28 17:46:36 UTC (rev 3917)
@@ -1,26 +1,17 @@
-diff -up po/Makefile.in.in.orig po/Makefile.in.in
---- po/Makefile.in.in.orig 2006-05-29 11:16:26.000000000 +0200
-+++ po/Makefile.in.in 2006-05-30 10:28:28.000000000 +0200
-@@ -58,7 +58,7 @@ PO_LINGUAS=$(shell if test -r $(srcdir)/
-
- POFILES=$(shell if test -n "$(PO_LINGUAS)"; then LINGUAS="$(PO_LINGUAS)"; else LINGUAS="$(ALL_LINGUAS)"; fi; for lang in $$LINGUAS; do printf "$$lang.po "; done)
-
--DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(POFILES)
-+DISTFILES = ChangeLog Makefile.in.in LINGUAS POTFILES.in $(POFILES)
- EXTRA_DISTFILES = POTFILES.skip Makevars LINGUAS
-
- POTFILES = \
-@@ -204,6 +204,7 @@ update-po: Makefile
- rm -f $$tmpdir/$$lang.new.po; \
+--- po/Makefile.in.in.orig 2006-09-28 13:10:28.000000000 +0200
++++ po/Makefile.in.in 2006-09-28 13:12:51.000000000 +0200
+@@ -205,6 +205,9 @@ update-po: Makefile
fi; \
done
-+distfile-list:
++distfile-list:
++
++
Makefile POTFILES: stamp-it
@if test ! -f $@; then \
-diff -up intltool-extract.in.orig intltool-extract.in
---- intltool-extract.in.orig 2006-05-29 11:16:26.000000000 +0200
-+++ intltool-extract.in 2006-05-30 10:27:33.000000000 +0200
+ rm -f stamp-it; \
+--- intltool-extract.in.orig 2006-09-28 13:10:28.000000000 +0200
++++ intltool-extract.in 2006-09-28 13:11:48.000000000 +0200
@@ -185,11 +185,13 @@ sub message {
sub extract {
&determine_type;
@@ -50,15 +41,15 @@
&type_ini if $gettext_type eq "ini";
&type_keys if $gettext_type eq "keys";
&type_xml if $gettext_type eq "xml";
-@@ -213,6 +220,7 @@ sub convert {
+@@ -212,6 +219,7 @@ sub convert {
+ &type_scheme if $gettext_type eq "scheme";
&type_schemas if $gettext_type eq "schemas";
&type_rfc822deb if $gettext_type eq "rfc822deb";
- &type_quoted if $gettext_type eq "quoted";
+ return 1; # need msg_write()
}
sub entity_decode_minimal
-@@ -798,6 +806,56 @@ sub type_scheme {
+@@ -786,6 +794,56 @@ sub type_scheme {
}
}
Deleted: trunk/po/intltool-scm.diff
===================================================================
--- trunk/po/intltool-scm.diff 2006-09-27 23:27:03 UTC (rev 3916)
+++ trunk/po/intltool-scm.diff 2006-09-28 17:46:36 UTC (rev 3917)
@@ -1,123 +0,0 @@
---- po/Makefile.in.in.orig 2006-04-11 19:49:55.000000000 +0200
-+++ po/Makefile.in.in 2006-05-15 19:53:32.000000000 +0200
-@@ -60,7 +60,7 @@
- SOURCES =
- POFILES = @POFILES@
- GMOFILES = @GMOFILES@
--DISTFILES = ChangeLog Makefile.in.in POTFILES.in \
-+DISTFILES = ChangeLog Makefile.in.in LINGUAS POTFILES.in \
- $(POFILES) $(GMOFILES) $(SOURCES)
-
- POTFILES = \
-@@ -227,6 +227,7 @@
- rm -f $$tmpdir/$$lang.new.po; \
- fi; \
- done
-+distfile-list:
-
- # POTFILES is created from POTFILES.in by stripping comments, empty lines
- # and Intltool tags (enclosed in square brackets), and appending a full
-@@ -239,7 +240,7 @@
- fi; \
- rm -f $ -t $@ \
- && (sed -e '/^#/d' \
-- -e "s/^\[.*\] +//" \
-+ -e "s/^\[.*\] \+//" \
- -e '/^[ ]*$$/d' \
- -e "s *@ $$posrcprefix& \\\\@" < $(srcdir)/$ in \
- | sed -e '$$s/\\$$//') > $ -t \
---- intltool-extract.in.orig 2005-01-25 23:56:20.000000000 +0100
-+++ intltool-extract.in 2005-05-21 00:32:24.695400050 +0200
-@@ -183,10 +183,12 @@ sub message {
- sub extract {
- &determine_type;
-
-- &convert;
--
- open OUT, ">$OUTFILE";
-- &msg_write;
-+
-+ my $need_msg_write;
-+ $need_msg_write = convert();
-+
-+ &msg_write if $need_msg_write;
- close OUT;
-
- print "Wrote $OUTFILE\n" unless $QUIET_ARG;
-@@ -202,6 +204,11 @@ sub convert {
- $input = <IN>;
- }
-
-+ if ($gettext_type eq "scm-funcs") {
-+ &transform_scm_funcs;
-+ return 0; # no need for msg_write()
-+ }
-+
- &type_ini if $gettext_type eq "ini";
- &type_keys if $gettext_type eq "keys";
- &type_xml if $gettext_type eq "xml";
-@@ -209,6 +216,7 @@ sub convert {
- &type_scheme if $gettext_type eq "scheme";
- &type_schemas if $gettext_type eq "schemas";
- &type_rfc822deb if $gettext_type eq "rfc822deb";
-+ return 1; # need msg_write()
- }
-
- sub entity_decode_minimal
-@@ -461,6 +469,56 @@ sub type_scheme {
- }
- }
-
-+sub transform_scm_funcs {
-+ my $scheme_subident = "abcdefghijklmnopqrstuvwxyz"."ABCDEFGHIJKLMNOPQRSTUVWXYZ".'!$%&*/:<=>?^_~'."0123456789".'+-.@';
-+ my $state = 0;
-+ my $letter = "";
-+ for (my $i = 0; $i < length($input); $i++) {
-+ my $char = substr($input,$i,1);
-+ # here, we process the input char by char
-+ # print $char;
-+ # we use a simple state machine, states:
-+ # 0 - normal state
-+ # 1 - in string
-+ # 2 - in backslash escape within string
-+ # 3 - in comment
-+ # 4 - in scheme expresssion after i18n letter
-+ # 5 - maybe reading gettext identifier
-+ # 6 - in scheme expresssion
-+ if ($state == 0) { # normal reading
-+ $letter = "";
-+ if ($char eq "'") { print OUT "&"; $state = 0; }
-+ elsif ($char eq "#") { print OUT "&"; $state = 0; }
-+ elsif ($char eq '"') { print OUT $char; $state = 1; }
-+ elsif ($char eq ";") { print OUT '/*'; $state = 3; }
-+ elsif ($char eq "(") { $state = 6; }
-+ else { print OUT $char; }
-+ } elsif ($state == 1) { # in string
-+ if ($char eq '"') { print OUT $char; $state = 0; }
-+ elsif ($char eq '\\') { print OUT $char; $state = 2; }
-+ else { print OUT $char; }
-+ } elsif ($state == 2) { # backslash escape
-+ if (1) { print OUT $char; $state = 1; }
-+ } elsif ($state == 3) { # comment
-+ if ($char eq "\n") { print OUT "*/\n"; $state = 0; }
-+ else { print OUT $char; }
-+ } elsif ($state == 4) { # expression, consumed i18n letter, unprinted: '(?'
-+ if ($char eq "_") { $state = 5; }
-+ else { print OUT "($letter"; $state = 0; $i -= 1; }
-+ } elsif ($state == 5) { # maybe gettext, unprinted: '(_' or '(?_'
-+ if (index ($scheme_subident, $char) > -1)
-+ { print OUT "($letter"."_"; $state = 0; $i -= 1; }
-+ else { print OUT "$letter"."_("; $state = 0; $i -= 1; }
-+ } elsif ($state == 6) { # expression, unprinted: '('
-+ if ($char eq "_") { $state = 5; }
-+ elsif ($char eq "N") { $letter = "N"; $state = 4; }
-+ elsif ($char eq "Q") { $letter = "Q"; $state = 4; }
-+ elsif ($char eq "U") { $letter = "U"; $state = 4; }
-+ else { print OUT "("; $state = 0; $i -= 1; }
-+ }
-+ }
-+}
-+
- sub msg_write {
- my @msgids;
- if (%count)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]