hgbook

changeset 657:1e020cb7d417

Remove tools
author Dongsheng Song <songdongsheng@live.cn>
date Mon Mar 30 21:36:31 2009 +0800 (2009-03-30)
parents 4e8f302ae313
children 433040113eaf
files .hgignore Makefile Makefile.vars.tmpl en/figs/kdiff3.png en/figs/note.png tools/po4a/lib/Locale/Po4a/Chooser.pm tools/po4a/lib/Locale/Po4a/Common.pm tools/po4a/lib/Locale/Po4a/Docbook.pm tools/po4a/lib/Locale/Po4a/Po.pm tools/po4a/lib/Locale/Po4a/TransTractor.pm tools/po4a/lib/Locale/Po4a/Xml.pm tools/po4a/po4a-translate tools/po4a/po4a-updatepo
line diff
     1.1 --- a/.hgignore	Mon Mar 30 17:50:48 2009 +0800
     1.2 +++ b/.hgignore	Mon Mar 30 21:36:31 2009 +0800
     1.3 @@ -23,4 +23,7 @@
     1.4  build
     1.5  en/html
     1.6  en/examples/results
     1.7 -tools
     1.8 \ No newline at end of file
     1.9 +tools
    1.10 +Makefile.vars
    1.11 +*.mo
    1.12 +*-tmp.*
     2.1 --- a/Makefile	Mon Mar 30 17:50:48 2009 +0800
     2.2 +++ b/Makefile	Mon Mar 30 21:36:31 2009 +0800
     2.3 @@ -1,6 +1,7 @@
     2.4  #
     2.5  # Makefile for the hgbook, top-level
     2.6  #
     2.7 +include Makefile.vars
     2.8  
     2.9  FORMATS=html html-single pdf
    2.10  
    2.11 @@ -8,11 +9,11 @@
    2.12  DBK_LANGUAGES := en
    2.13  LANGUAGES := $(DBK_LANGUAGES) $(PO_LANGUAGES)
    2.14  
    2.15 -UPDATEPO = PERLLIB=../tools/po4a/lib/ ../tools/po4a/po4a-updatepo -M UTF-8 \
    2.16 +UPDATEPO = PERLLIB=$(PO4A_LIB) $(PO4A_HOME)/po4a-updatepo -M UTF-8 \
    2.17  	   -f docbook -o doctype='docbook' -o includeexternal \
    2.18  	   -o nodefault='<programlisting> <screen>' \
    2.19  	   -o untranslated='<programlisting> <screen>'
    2.20 -TRANSLATE = PERLLIB=tools/po4a/lib/ tools/po4a/po4a-translate -M UTF-8 \
    2.21 +TRANSLATE = PERLLIB=$(PO4A_LIB) $(PO4A_HOME)/po4a-translate -M UTF-8 \
    2.22  	   -f docbook -o doctype='docbook' \
    2.23  	   -k 0
    2.24  
    2.25 @@ -150,6 +151,7 @@
    2.26  
    2.27  build/$(LINGUA)/source/hgbook.xml: build/en/source/hgbook.xml po/$(LINGUA).po $(images)
    2.28  	mkdir -p build/$(LINGUA)/source/figs
    2.29 +	cp en/figs/*.png build/$(LINGUA)/source/figs
    2.30  	$(TRANSLATE) -m build/en/source/hgbook.xml -p po/$(LINGUA).po -l $@.tmp
    2.31  	cat $@.tmp | sed 's/\$$rev_id\$$/${rev_id}/' > $@
    2.32  endif
    2.33 @@ -198,7 +200,7 @@
    2.34  
    2.35  build/$(LINGUA)/pdf/hgbook.pdf: build/$(LINGUA)/source/hgbook.xml stylesheets/fo.xsl stylesheets/$(LINGUA)/fo.xsl
    2.36  	mkdir -p build/$(LINGUA)/pdf
    2.37 -	java -classpath tools/fop/lib/saxon65.jar:tools/fop/lib/saxon65-dbxsl.jar:tools/fop/lib/xml-commons-resolver-1.2.jar:tools/fop/conf \
    2.38 +	java -classpath $(JAVA_SHARE)/saxon65.jar:$(JAVA_SHARE)/saxon65-dbxsl.jar:$(JAVA_SHARE)/xml-commons-resolver-1.2.jar:$(JAVA_SHARE) \
    2.39  	    com.icl.saxon.StyleSheet \
    2.40  	    -x org.apache.xml.resolver.tools.ResolvingXMLReader \
    2.41  	    -y org.apache.xml.resolver.tools.ResolvingXMLReader \
    2.42 @@ -208,7 +210,7 @@
    2.43  	    stylesheets/$(LINGUA)/fo.xsl \
    2.44  	    fop1.extensions=1
    2.45  
    2.46 -	(cd build/$(LINGUA)/source && ../../../tools/fop/fop.sh hgbook.fo ../pdf/hgbook.pdf)
    2.47 +	(cd build/$(LINGUA)/source && $(FOP_HOME)/fop.sh hgbook.fo ../pdf/hgbook.pdf)
    2.48  endif
    2.49  
    2.50  en/figs/%.png: en/figs/%.svg en/fixsvg
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/Makefile.vars.tmpl	Mon Mar 30 21:36:31 2009 +0800
     3.3 @@ -0,0 +1,20 @@
     3.4 +#
     3.5 +# Please create your Makefile.vars file from this template file.
     3.6 +#
     3.7 +# Please use absolute path, DO NOT use relative path !
     3.8 +#
     3.9 +
    3.10 +# po4a (>= 0.36.1): Only for PO based Makefile !
    3.11 +# po4A_HOME=/usr/bin
    3.12 +# PO4A_LIB=/usr/share/perl5
    3.13 +PO4A_HOME=/home/dongsheng/var/svn/i18n-zh/trunk/lib/po4a
    3.14 +PO4A_LIB=$(PO4A_HOME)/lib
    3.15 +
    3.16 +# saxon65.jar, saxon65-dbxsl.jar, xml-commons-resolver-1.2.jar: Only for pdf format !
    3.17 +JAVA_SHARE=/home/dongsheng/var/svn/i18n-zh/trunk/lib/share/java
    3.18 +
    3.19 +# fop (>= 0.9.6): Only for pdf format !
    3.20 +FOP_HOME=/home/dongsheng/var/svn/i18n-zh/trunk/lib/fop
    3.21 +
    3.22 +# docbook-xsl (>= 1.74.3): Only for ePub format !
    3.23 +DB2EPUB=/home/dongsheng/var/svn/i18n-zh/trunk/lib/docbook/docbook-xsl/epub/bin/dbtoepub
     4.1 Binary file en/figs/kdiff3.png has changed
     5.1 Binary file en/figs/note.png has changed
     6.1 --- a/tools/po4a/lib/Locale/Po4a/Chooser.pm	Mon Mar 30 17:50:48 2009 +0800
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,148 +0,0 @@
     6.4 -# Locale::Po4a::Pod -- Convert POD data to PO file, for translation.
     6.5 -# $Id: Chooser.pm,v 1.41 2008-07-20 16:31:55 nekral-guest Exp $
     6.6 -#
     6.7 -# This program is free software; you may redistribute it and/or modify it
     6.8 -# under the terms of GPL (see COPYING).
     6.9 -#
    6.10 -# This module converts POD to PO file, so that it becomes possible to 
    6.11 -# translate POD formatted documentation. See gettext documentation for
    6.12 -# more info about PO files.
    6.13 -
    6.14 -############################################################################
    6.15 -# Modules and declarations
    6.16 -############################################################################
    6.17 -
    6.18 -
    6.19 -package Locale::Po4a::Chooser;
    6.20 -
    6.21 -use 5.006;
    6.22 -use strict;
    6.23 -use warnings;
    6.24 -use Locale::Po4a::Common;
    6.25 -
    6.26 -sub new {
    6.27 -    my ($module)=shift;
    6.28 -    my (%options)=@_;
    6.29 -
    6.30 -    die wrap_mod("po4a::chooser", gettext("Need to provide a module name"))
    6.31 -      unless defined $module;
    6.32 -
    6.33 -    my $modname;
    6.34 -    if ($module eq 'kernelhelp') {
    6.35 -        $modname = 'KernelHelp';
    6.36 -    } elsif ($module eq 'newsdebian') {
    6.37 -        $modname = 'NewsDebian';
    6.38 -    } elsif ($module eq 'latex') {
    6.39 -        $modname = 'LaTeX';
    6.40 -    } elsif ($module eq 'bibtex') {
    6.41 -        $modname = 'BibTex';
    6.42 -    } elsif ($module eq 'tex') {
    6.43 -        $modname = 'TeX';
    6.44 -    } else {
    6.45 -        $modname = ucfirst($module);
    6.46 -    }
    6.47 -    if (! UNIVERSAL::can("Locale::Po4a::$modname", 'new')) {
    6.48 -        eval qq{use Locale::Po4a::$modname};
    6.49 -        if ($@) {
    6.50 -            my $error=$@;
    6.51 -            warn wrap_msg(gettext("Unknown format type: %s."), $module);
    6.52 -	    warn wrap_mod("po4a::chooser",
    6.53 -		gettext("Module loading error: %s"), $error)
    6.54 -	      if defined $options{'verbose'} && $options{'verbose'} > 0;
    6.55 -            list(1);
    6.56 -        }
    6.57 -    }
    6.58 -    return "Locale::Po4a::$modname"->new(%options);
    6.59 -}
    6.60 -
    6.61 -sub list {
    6.62 -    warn wrap_msg(gettext("List of valid formats:")
    6.63 -#	."\n  - ".gettext("bibtex: BibTex bibliography format.")
    6.64 -	."\n  - ".gettext("dia: uncompressed Dia diagrams.")
    6.65 -	."\n  - ".gettext("docbook: Docbook XML.")
    6.66 -	."\n  - ".gettext("guide: Gentoo Linux's xml documentation format.")
    6.67 -#	."\n  - ".gettext("html: HTML documents (EXPERIMENTAL).")
    6.68 -	."\n  - ".gettext("ini: .INI format.")
    6.69 -	."\n  - ".gettext("kernelhelp: Help messages of each kernel compilation option.")
    6.70 -	."\n  - ".gettext("latex: LaTeX format.")
    6.71 -	."\n  - ".gettext("man: Good old manual page format.")
    6.72 -	."\n  - ".gettext("pod: Perl Online Documentation format.")
    6.73 -	."\n  - ".gettext("sgml: either debiandoc or docbook DTD.")
    6.74 -	."\n  - ".gettext("texinfo: The info page format.")
    6.75 -	."\n  - ".gettext("tex: generic TeX documents (see also latex).")
    6.76 -	."\n  - ".gettext("text: simple text document.")
    6.77 -	."\n  - ".gettext("wml: WML documents.")
    6.78 -	."\n  - ".gettext("xhtml: XHTML documents.")
    6.79 -	."\n  - ".gettext("xml: generic XML documents (see also docbook).")
    6.80 -    );
    6.81 -    exit shift;
    6.82 -}
    6.83 -##############################################################################
    6.84 -# Module return value and documentation
    6.85 -##############################################################################
    6.86 -
    6.87 -1;
    6.88 -__END__
    6.89 -
    6.90 -=head1 NAME
    6.91 -
    6.92 -Locale::Po4a::Chooser - Manage po4a modules
    6.93 -
    6.94 -=head1 DESCRIPTION
    6.95 -
    6.96 -Locale::Po4a::Chooser is a module to manage po4a modules. Before, all po4a
    6.97 -binaries used to know all po4a modules (pod, man, sgml, etc). This made the
    6.98 -add of a new module boring, to make sure the documentation is synchronized
    6.99 -in all modules, and that each of them can access the new module.
   6.100 -
   6.101 -Now, you just have to call the Locale::Po4a::Chooser::new() function,
   6.102 -passing the name of module as argument.
   6.103 -
   6.104 -You also have the Locale::Po4a::Chooser::list() function which lists the
   6.105 -available format and exits on the value passed as argument.
   6.106 -
   6.107 -=head1 SEE ALSO
   6.108 -
   6.109 -=over 4
   6.110 -
   6.111 -=item About po4a:
   6.112 -
   6.113 -L<po4a(7)|po4a.7>, 
   6.114 -L<Locale::Po4a::TransTractor(3pm)>,
   6.115 -L<Locale::Po4a::Po(3pm)>
   6.116 -
   6.117 -=item About modules:
   6.118 -
   6.119 -L<Locale::Po4a::Dia(3pm)>,
   6.120 -L<Locale::Po4a::Docbook(3pm)>,
   6.121 -L<Locale::Po4a::Guide(3pm)>,
   6.122 -L<Locale::Po4a::Halibut(3pm)>,
   6.123 -L<Locale::Po4a::Ini(3pm)>,
   6.124 -L<Locale::Po4a::KernelHelp(3pm)>,
   6.125 -L<Locale::Po4a::LaTeX(3pm)>,
   6.126 -L<Locale::Po4a::Man(3pm)>,
   6.127 -L<Locale::Po4a::Pod(3pm)>,
   6.128 -L<Locale::Po4a::Sgml(3pm)>,
   6.129 -L<Locale::Po4a::TeX(3pm)>,
   6.130 -L<Locale::Po4a::Texinfo(3pm)>,
   6.131 -L<Locale::Po4a::Text(3pm)>,
   6.132 -L<Locale::Po4a::Wml(3pm)>.
   6.133 -L<Locale::Po4a::Xhtml(3pm)>,
   6.134 -L<Locale::Po4a::Xml(3pm)>,
   6.135 -L<Locale::Po4a::Wml(3pm)>.
   6.136 -
   6.137 -=back
   6.138 -
   6.139 -=head1 AUTHORS
   6.140 -
   6.141 - Denis Barbier <barbier@linuxfr.org>
   6.142 - Martin Quinson (mquinson#debian.org)
   6.143 -
   6.144 -=head1 COPYRIGHT AND LICENSE
   6.145 -
   6.146 -Copyright 2002,2003,2004,2005 by SPI, inc.
   6.147 -
   6.148 -This program is free software; you may redistribute it and/or modify it
   6.149 -under the terms of GPL (see the COPYING file).
   6.150 -
   6.151 -=cut
     7.1 --- a/tools/po4a/lib/Locale/Po4a/Common.pm	Mon Mar 30 17:50:48 2009 +0800
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,246 +0,0 @@
     7.4 -# Locale::Po4a::Common -- Common parts of the po4a scripts and utils
     7.5 -# $Id: Common.pm,v 1.20 2009-02-13 23:16:44 nekral-guest Exp $
     7.6 -#
     7.7 -# Copyright 2005 by Jordi Vilalta <jvprat@gmail.com>
     7.8 -#
     7.9 -# This program is free software; you may redistribute it and/or modify it
    7.10 -# under the terms of GPL (see COPYING).
    7.11 -#
    7.12 -# This module has common utilities for the various scripts of po4a
    7.13 -
    7.14 -=head1 NAME
    7.15 -
    7.16 -Locale::Po4a::Common - Common parts of the po4a scripts and utils
    7.17 -
    7.18 -=head1 DESCRIPTION
    7.19 -
    7.20 -Locale::Po4a::Common contains common parts of the po4a scripts and some useful
    7.21 -functions used along the other modules.
    7.22 -
    7.23 -In order to use Locale::Po4a programatically, one may want to disable
    7.24 -the use of Text::WrapI18N, by writing e.g.
    7.25 -
    7.26 -    use Locale::Po4a::Common qw(nowrapi18n);
    7.27 -    use Locale::Po4a::Text;
    7.28 -
    7.29 -instead of:
    7.30 -
    7.31 -    use Locale::Po4a::Text;
    7.32 -
    7.33 -Ordering is important here: as most Locale::Po4a modules themselves
    7.34 -load Locale::Po4a::Common, the first time this module is loaded
    7.35 -determines whether Text::WrapI18N is used.
    7.36 -
    7.37 -=cut
    7.38 -
    7.39 -package Locale::Po4a::Common;
    7.40 -
    7.41 -require Exporter;
    7.42 -use vars qw(@ISA @EXPORT);
    7.43 -@ISA = qw(Exporter);
    7.44 -@EXPORT = qw(wrap_msg wrap_mod wrap_ref_mod textdomain gettext dgettext);
    7.45 -
    7.46 -use 5.006;
    7.47 -use strict;
    7.48 -use warnings;
    7.49 -
    7.50 -sub import {
    7.51 -    my $class=shift;
    7.52 -
    7.53 -    my $wrapi18n=1;
    7.54 -    if (exists $_[0] && defined $_[0] && $_[0] eq 'nowrapi18n') {
    7.55 -        shift;
    7.56 -        $wrapi18n=0;
    7.57 -    }
    7.58 -    $class->export_to_level(1, $class, @_);
    7.59 -
    7.60 -    return if defined &wrapi18n;
    7.61 -
    7.62 -    if ($wrapi18n && -t STDERR && -t STDOUT && eval { require Text::WrapI18N }) {
    7.63 -    
    7.64 -        # Don't bother determining the wrap column if we cannot wrap.
    7.65 -        my $col=$ENV{COLUMNS};
    7.66 -        if (!defined $col) {
    7.67 -            my @term=eval "use Term::ReadKey; Term::ReadKey::GetTerminalSize()";
    7.68 -            $col=$term[0] if (!$@);
    7.69 -            # If GetTerminalSize() failed we will fallback to a safe default.
    7.70 -            # This can happen if Term::ReadKey is not available
    7.71 -            # or this is a terminal-less build or such strange condition.
    7.72 -        }
    7.73 -        $col=76 if (!defined $col);
    7.74 -        
    7.75 -        eval ' use Text::WrapI18N qw($columns);
    7.76 -               $columns = $col;
    7.77 -             ';
    7.78 -       
    7.79 -        eval ' sub wrapi18n($$$) { Text::WrapI18N::wrap($_[0],$_[1],$_[2]) } '
    7.80 -    } else {
    7.81 -    
    7.82 -        # If we cannot wrap, well, that's too bad. Survive anyway.
    7.83 -        eval ' sub wrapi18n($$$) { $_[0].$_[2] } '
    7.84 -    }
    7.85 -}
    7.86 -
    7.87 -sub min($$) {
    7.88 -    return $_[0] < $_[1] ? $_[0] : $_[1];
    7.89 -}
    7.90 -
    7.91 -=head1 FUNCTIONS
    7.92 -
    7.93 -=head2 Showing output messages
    7.94 -
    7.95 -=over
    7.96 -
    7.97 -=item 
    7.98 -
    7.99 -show_version($)
   7.100 -
   7.101 -Shows the current version of the script, and a short copyright message. It
   7.102 -takes the name of the script as an argument.
   7.103 -
   7.104 -=cut
   7.105 -
   7.106 -sub show_version {
   7.107 -    my $name = shift;
   7.108 -
   7.109 -    print sprintf(gettext(
   7.110 -	"%s version %s.\n".
   7.111 -	"written by Martin Quinson and Denis Barbier.\n\n".
   7.112 -	"Copyright (C) 2002, 2003, 2004 Software of Public Interest, Inc.\n".
   7.113 -	"This is free software; see source code for copying\n".
   7.114 -	"conditions. There is NO warranty; not even for\n".
   7.115 -	"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
   7.116 -	), $name, $Locale::Po4a::TransTractor::VERSION)."\n";
   7.117 -}
   7.118 -
   7.119 -=item 
   7.120 -
   7.121 -wrap_msg($@)
   7.122 -
   7.123 -This function displays a message the same way than sprintf() does, but wraps
   7.124 -the result so that they look nice on the terminal.
   7.125 -
   7.126 -=cut
   7.127 -
   7.128 -sub wrap_msg($@) {
   7.129 -    my $msg = shift;
   7.130 -    my @args = @_;
   7.131 -
   7.132 -    return wrapi18n("", "", sprintf($msg, @args))."\n";
   7.133 -}
   7.134 -
   7.135 -=item 
   7.136 -
   7.137 -wrap_mod($$@)
   7.138 -
   7.139 -This function works like wrap_msg(), but it takes a module name as the first
   7.140 -argument, and leaves a space at the left of the message.
   7.141 -
   7.142 -=cut
   7.143 -
   7.144 -sub wrap_mod($$@) {
   7.145 -    my ($mod, $msg) = (shift, shift);
   7.146 -    my @args = @_;
   7.147 -
   7.148 -    $mod .= ": ";
   7.149 -    my $spaces = " " x min(length($mod), 15);
   7.150 -    return wrapi18n($mod, $spaces, sprintf($msg, @args))."\n";
   7.151 -}
   7.152 -
   7.153 -=item 
   7.154 -
   7.155 -wrap_ref_mod($$$@)
   7.156 -
   7.157 -This function works like wrap_msg(), but it takes a file:line reference as the
   7.158 -first argument, a module name as the second one, and leaves a space at the left
   7.159 -of the message.
   7.160 -
   7.161 -=back
   7.162 -
   7.163 -=cut
   7.164 -
   7.165 -sub wrap_ref_mod($$$@) {
   7.166 -    my ($ref, $mod, $msg) = (shift, shift, shift);
   7.167 -    my @args = @_;
   7.168 -
   7.169 -    if (!$mod) {
   7.170 -	# If we don't get a module name, show the message like wrap_mod does
   7.171 -	return wrap_mod($ref, $msg, @args);
   7.172 -    } else {
   7.173 -	$ref .= ": ";
   7.174 -	my $spaces = " " x min(length($ref), 15);
   7.175 -	$msg = "$ref($mod)\n$msg";
   7.176 -	return wrapi18n("", $spaces, sprintf($msg, @args))."\n";
   7.177 -    }
   7.178 -}
   7.179 -
   7.180 -=head2 Wrappers for other modules
   7.181 -
   7.182 -=over 
   7.183 -
   7.184 -=item 
   7.185 -
   7.186 -Locale::Gettext
   7.187 -
   7.188 -When the Locale::Gettext module cannot be loaded, this module provide dummy
   7.189 -(empty) implementation of the following functions. In that case, po4a
   7.190 -messages won't get translated but the program will continue to work.
   7.191 -
   7.192 -If Locale::gettext is present, this wrapper also calls
   7.193 -setlocale(LC_MESSAGES, "") so callers don't depend on the POSIX module
   7.194 -either.
   7.195 -
   7.196 -=over
   7.197 -
   7.198 -=item 
   7.199 -
   7.200 -bindtextdomain($$)
   7.201 -
   7.202 -=item 
   7.203 -
   7.204 -textdomain($)
   7.205 -
   7.206 -=item 
   7.207 -
   7.208 -gettext($)
   7.209 -
   7.210 -=item 
   7.211 -
   7.212 -dgettext($$)
   7.213 -
   7.214 -=back
   7.215 -
   7.216 -=back
   7.217 -
   7.218 -=cut
   7.219 -
   7.220 -BEGIN {
   7.221 -    if (eval { require Locale::gettext }) {
   7.222 -       import Locale::gettext;
   7.223 -       require POSIX;
   7.224 -       POSIX::setlocale(&POSIX::LC_MESSAGES, '');
   7.225 -    } else {
   7.226 -       eval '
   7.227 -           sub bindtextdomain($$) { }
   7.228 -           sub textdomain($) { }
   7.229 -           sub gettext($) { shift }
   7.230 -           sub dgettext($$) { return $_[1] }
   7.231 -       '
   7.232 -    }
   7.233 -}
   7.234 -
   7.235 -1;
   7.236 -__END__
   7.237 -
   7.238 -=head1 AUTHORS
   7.239 -
   7.240 - Jordi Vilalta <jvprat@gmail.com>
   7.241 -
   7.242 -=head1 COPYRIGHT AND LICENSE
   7.243 -
   7.244 -Copyright 2005 by SPI, inc.
   7.245 -
   7.246 -This program is free software; you may redistribute it and/or modify it
   7.247 -under the terms of GPL (see the COPYING file).
   7.248 -
   7.249 -=cut
     8.1 --- a/tools/po4a/lib/Locale/Po4a/Docbook.pm	Mon Mar 30 17:50:48 2009 +0800
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,2040 +0,0 @@
     8.4 -#!/usr/bin/perl
     8.5 -# aptitude: cmdsynopsis => missing removal of leading spaces
     8.6 -
     8.7 -# Po4a::Docbook.pm 
     8.8 -# 
     8.9 -# extract and translate translatable strings from Docbook XML documents.
    8.10 -# 
    8.11 -# This code extracts plain text from tags and attributes on Docbook XML
    8.12 -# documents.
    8.13 -#
    8.14 -# Copyright (c) 2004 by Jordi Vilalta  <jvprat@gmail.com>
    8.15 -# Copyright (c) 2007-2009 by Nicolas François <nicolas.francois@centraliens.net>
    8.16 -#
    8.17 -# This program is free software; you can redistribute it and/or modify
    8.18 -# it under the terms of the GNU General Public License as published by
    8.19 -# the Free Software Foundation; either version 2 of the License, or
    8.20 -# (at your option) any later version.
    8.21 -#
    8.22 -# This program is distributed in the hope that it will be useful,
    8.23 -# but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.24 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.25 -# GNU General Public License for more details.
    8.26 -#
    8.27 -# You should have received a copy of the GNU General Public License
    8.28 -# along with this program; if not, write to the Free Software
    8.29 -# Foundation, Inc.,
    8.30 -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
    8.31 -#
    8.32 -########################################################################
    8.33 -
    8.34 -=head1 NAME
    8.35 -
    8.36 -Locale::Po4a::Docbook - Convert Docbook XML documents from/to PO files
    8.37 -
    8.38 -=head1 DESCRIPTION
    8.39 -
    8.40 -The po4a (po for anything) project goal is to ease translations (and more
    8.41 -interestingly, the maintenance of translations) using gettext tools on
    8.42 -areas where they were not expected like documentation.
    8.43 -
    8.44 -Locale::Po4a::Docbook is a module to help the translation of DocBook XML 
    8.45 -documents into other [human] languages.
    8.46 -
    8.47 -Please note that this module is still under heavy development, and not 
    8.48 -distributed in official po4a release since we don't feel it to be mature 
    8.49 -enough. If you insist on trying, check the CVS out.
    8.50 -
    8.51 -=head1 STATUS OF THIS MODULE
    8.52 -
    8.53 -This module is fully functional, as it relies in the L<Locale::Po4a::Xml>
    8.54 -module. This only defines the translatable tags and attributes.
    8.55 -
    8.56 -The only known issue is that it doesn't handle entities yet, and this includes
    8.57 -the file inclusion entities, but you can translate most of those files alone
    8.58 -(except the typical entities files), and it's usually better to maintain them
    8.59 -separated.
    8.60 -
    8.61 -=head1 SEE ALSO
    8.62 -
    8.63 -L<po4a(7)|po4a.7>, L<Locale::Po4a::TransTractor(3pm)>, L<Locale::Po4a::Xml(3pm)>.
    8.64 -
    8.65 -=head1 AUTHORS
    8.66 -
    8.67 - Jordi Vilalta <jvprat@gmail.com>
    8.68 -
    8.69 -=head1 COPYRIGHT AND LICENSE
    8.70 -
    8.71 - Copyright (c) 2004 by Jordi Vilalta  <jvprat@gmail.com>
    8.72 - Copyright (c) 2007-2009 by Nicolas François <nicolas.francois@centraliens.net>
    8.73 -
    8.74 -This program is free software; you may redistribute it and/or modify it
    8.75 -under the terms of GPL (see the COPYING file).
    8.76 -
    8.77 -=cut
    8.78 -
    8.79 -package Locale::Po4a::Docbook;
    8.80 -
    8.81 -use 5.006;
    8.82 -use strict;
    8.83 -use warnings;
    8.84 -
    8.85 -use Locale::Po4a::Xml;
    8.86 -
    8.87 -use vars qw(@ISA);
    8.88 -@ISA = qw(Locale::Po4a::Xml);
    8.89 -
    8.90 -sub initialize {
    8.91 -	my $self = shift;
    8.92 -	my %options = @_;
    8.93 -
    8.94 -	$self->SUPER::initialize(%options);
    8.95 -	$self->{options}{'wrap'}=1;
    8.96 -	$self->{options}{'doctype'}=$self->{options}{'doctype'} || 'docbook xml';
    8.97 -
    8.98 -# AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    8.99 -
   8.100 -	# abbrev; contains text; Formatted inline
   8.101 -	$self->{options}{'_default_translated'} .= " <abbrev>";
   8.102 -	$self->{options}{'_default_inline'} .= " <abbrev>";
   8.103 -
   8.104 -	# abstract; does not contain text; Formatted as a displayed block
   8.105 -	$self->{options}{'_default_untranslated'} .= " <abstract>";
   8.106 -	$self->{options}{'_default_break'} .= " <abstract>";
   8.107 -
   8.108 -	# accel; contains text; Formatted inline
   8.109 -	$self->{options}{'_default_translated'} .= " <accel>";
   8.110 -	$self->{options}{'_default_inline'} .= " <accel>";
   8.111 -
   8.112 -	# ackno; does not contain text; Formatted as a displayed block
   8.113 -	# Replaced by acknowledgements in Docbook v5.0
   8.114 -	$self->{options}{'_default_untranslated'} .= " <ackno>";
   8.115 -	$self->{options}{'_default_break'} .= " <ackno>";
   8.116 -	# acknowledgements; does not contain text; Formatted as a displayed block
   8.117 -	$self->{options}{'_default_untranslated'} .= " <acknowledgements>";
   8.118 -	$self->{options}{'_default_break'} .= " <acknowledgements>";
   8.119 -
   8.120 -	# acronym; contains text; Formatted inline
   8.121 -	$self->{options}{'_default_translated'} .= " <acronym>";
   8.122 -	$self->{options}{'_default_inline'} .= " <acronym>";
   8.123 -
   8.124 -	# action; contains text; Formatted inline; v4, not in v5
   8.125 -	$self->{options}{'_default_translated'} .= " <action>";
   8.126 -	$self->{options}{'_default_inline'} .= " <action>";
   8.127 -
   8.128 -	# address; contains text; Formatted as a displayed block; verbatim
   8.129 -	$self->{options}{'_default_translated'} .= " W<address>";
   8.130 -	$self->{options}{'_default_placeholder'} .= " <address>";
   8.131 -
   8.132 -	# affiliation; does not contain text; Formatted inline or as a
   8.133 -	# displayed block depending on context
   8.134 -	$self->{options}{'_default_untranslated'} .= " <affiliation>";
   8.135 -	$self->{options}{'_default_inline'} .= " <affiliation>";
   8.136 -
   8.137 -	# alt; contains text; Formatted inline or as a
   8.138 -	# displayed block depending on context
   8.139 -	$self->{options}{'_default_translated'} .= " <alt>";
   8.140 -	$self->{options}{'_default_inline'} .= " <alt>";
   8.141 -
   8.142 -	# anchor; does not contain text; Produces no output
   8.143 -	$self->{options}{'_default_untranslated'} .= " <anchor>";
   8.144 -	$self->{options}{'_default_inline'} .= " <anchor>";
   8.145 -
   8.146 -	# annotation; does not contain text;
   8.147 -	$self->{options}{'_default_untranslated'} .= " <annotation>";
   8.148 -	$self->{options}{'_default_placeholder'} .= " <annotation>";
   8.149 -
   8.150 -	# answer; does not contain text;
   8.151 -	$self->{options}{'_default_untranslated'} .= " <answer>";
   8.152 -	$self->{options}{'_default_break'} .= " <answer>";
   8.153 -
   8.154 -	# appendix; does not contain text; Formatted as a displayed block
   8.155 -	$self->{options}{'_default_untranslated'} .= " <appendix>";
   8.156 -	$self->{options}{'_default_break'} .= " <appendix>";
   8.157 -
   8.158 -	# appendixinfo; does not contain text; v4, not in v5
   8.159 -	$self->{options}{'_default_untranslated'} .= " <appendixinfo>";
   8.160 -	$self->{options}{'_default_placeholder'} .= " <appendixinfo>";
   8.161 -
   8.162 -	# application; contains text; Formatted inline
   8.163 -	$self->{options}{'_default_translated'} .= " <application>";
   8.164 -	$self->{options}{'_default_inline'} .= " <application>";
   8.165 -
   8.166 -	# arc; does not contain text;
   8.167 -	$self->{options}{'_default_untranslated'} .= " <arc>";
   8.168 -	$self->{options}{'_default_inline'} .= " <arc>";
   8.169 -
   8.170 -	# area; does not contain text;
   8.171 -	# NOTE: the area is not translatable as is, but the coords
   8.172 -	# attribute might be.
   8.173 -	$self->{options}{'_default_untranslated'} .= " <area>";
   8.174 -	$self->{options}{'_default_inline'} .= " <area>";
   8.175 -
   8.176 -	# areaset; does not contain text;
   8.177 -	# NOTE: the areaset is not translatable as is. depending on the
   8.178 -	# language there might be more or less area tags inside.
   8.179 -	$self->{options}{'_default_untranslated'} .= " <areaset>";
   8.180 -	$self->{options}{'_default_inline'} .= " <areaset>";
   8.181 -
   8.182 -	# areaspec; does not contain text;
   8.183 -	# NOTE: see area and areaset
   8.184 -	$self->{options}{'_default_translated'} .= " <areaspec>";
   8.185 -	$self->{options}{'_default_break'} .= " <areaspec>";
   8.186 -
   8.187 -	# arg; contains text; Formatted inline or as a
   8.188 -	# displayed block depending on context
   8.189 -	$self->{options}{'_default_translated'} .= " <arg>";
   8.190 -	$self->{options}{'_default_inline'} .= " <arg>";
   8.191 -
   8.192 -	# artheader; does not contain text; renamed to articleinfo in v4.0
   8.193 -	$self->{options}{'_default_untranslated'} .= " <artheader>";
   8.194 -	$self->{options}{'_default_placeholder'} .= " <artheader>";
   8.195 -
   8.196 -	# article; does not contain text; Formatted as a displayed block
   8.197 -	$self->{options}{'_default_untranslated'} .= " <article>";
   8.198 -	$self->{options}{'_default_break'} .= " <article>";
   8.199 -
   8.200 -	# articleinfo; does not contain text; v4 only
   8.201 -	$self->{options}{'_default_untranslated'} .= " <articleinfo>";
   8.202 -	$self->{options}{'_default_placeholder'} .= " <articleinfo>";
   8.203 -
   8.204 -	# artpagenums; contains text; Formatted inline
   8.205 -	# NOTE: could be in the break class
   8.206 -	$self->{options}{'_default_translated'} .= " <artpagenums>";
   8.207 -	$self->{options}{'_default_inline'} .= " <artpagenums>";
   8.208 -
   8.209 -	# attribution; contains text; Formatted inline or as a
   8.210 -	# displayed block depending on context
   8.211 -	$self->{options}{'_default_translated'} .= " <attribution>";
   8.212 -	$self->{options}{'_default_inline'} .= " <attribution>";
   8.213 -
   8.214 -	# audiodata; does not contain text;
   8.215 -	# NOTE: the attributes might be translated
   8.216 -	$self->{options}{'_default_translated'} .= " <audiodata>";
   8.217 -	$self->{options}{'_default_placeholder'} .= " <audiodata>";
   8.218 -	$self->{options}{'_default_attributes'}.=' <audiodata>fileref';
   8.219 -
   8.220 -	# audioobject; does not contain text;
   8.221 -	# NOTE: might be contaioned in a inlinemediaobject
   8.222 -	$self->{options}{'_default_translated'} .= " <audioobject>";
   8.223 -	$self->{options}{'_default_placeholder'} .= " <audioobject>";
   8.224 -
   8.225 -	# author; does not contain text; Formatted inline or as a
   8.226 -	# displayed block depending on context
   8.227 -	$self->{options}{'_default_untranslated'} .= " <author>";
   8.228 -	$self->{options}{'_default_inline'} .= " <author>";
   8.229 -
   8.230 -	# authorblurb; does not contain text; Formatted as a displayed block.
   8.231 -	# v4, not in v5
   8.232 -	$self->{options}{'_default_untranslated'} .= " <authorblurb>";
   8.233 -	$self->{options}{'_default_placeholder'} .= " <authorblurb>";
   8.234 -
   8.235 -	# authorgroup; does not contain text; Formatted inline or as a
   8.236 -	# displayed block depending on context
   8.237 -	# NOTE: given the possible parents, it is probably very rarely
   8.238 -	#       inlined
   8.239 -	$self->{options}{'_default_untranslated'} .= " <authorgroup>";
   8.240 -	$self->{options}{'_default_break'} .= " <authorgroup>";
   8.241 -
   8.242 -	# authorinitials; contains text; Formatted inline
   8.243 -	$self->{options}{'_default_translated'} .= " <authorinitials>";
   8.244 -	$self->{options}{'_default_inline'} .= " <authorinitials>";
   8.245 -
   8.246 -# BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
   8.247 -
   8.248 -	# beginpage; does not contain text; v4, not in v5
   8.249 -	$self->{options}{'_default_untranslated'} .= " <beginpage>";
   8.250 -	$self->{options}{'_default_break'} .= " <beginpage>";
   8.251 -
   8.252 -	# bibliocoverage; contains text; Formatted inline
   8.253 -	# NOTE: could be in the break class
   8.254 -	$self->{options}{'_default_translated'} .= " <bibliocoverage>";
   8.255 -	$self->{options}{'_default_inline'} .= " <bibliocoverage>";
   8.256 -
   8.257 -	# bibliodiv; does not contain text; Formatted as a displayed block
   8.258 -	$self->{options}{'_default_untranslated'} .= " <bibliodiv>";
   8.259 -	$self->{options}{'_default_break'} .= " <bibliodiv>";
   8.260 -
   8.261 -	# biblioentry; does not contain text; Formatted as a displayed block
   8.262 -	$self->{options}{'_default_untranslated'} .= " <biblioentry>";
   8.263 -	$self->{options}{'_default_break'} .= " <biblioentry>";
   8.264 -
   8.265 -	# bibliography; does not contain text; Formatted as a displayed block
   8.266 -	$self->{options}{'_default_untranslated'} .= " <bibliography>";
   8.267 -	$self->{options}{'_default_break'} .= " <bibliography>";
   8.268 -
   8.269 -	# bibliographyinfo; does not contain text; v4, not in v5
   8.270 -	$self->{options}{'_default_untranslated'} .= " <bibliographyinfo>";
   8.271 -	$self->{options}{'_default_placeholder'} .= " <bibliographyinfo>";
   8.272 -
   8.273 -	# biblioid; contains text; Formatted inline
   8.274 -	# NOTE: could be in the break class
   8.275 -	$self->{options}{'_default_translated'} .= " <biblioid>";
   8.276 -	$self->{options}{'_default_inline'} .= " <biblioid>";
   8.277 -
   8.278 -	# bibliolist; does not contain text; Formatted as a displayed block
   8.279 -	$self->{options}{'_default_untranslated'} .= " <bibliolist>";
   8.280 -	$self->{options}{'_default_break'} .= " <bibliolist>";
   8.281 -
   8.282 -	# bibliomisc; contains text; Formatted inline
   8.283 -	# NOTE: could be in the break class
   8.284 -	$self->{options}{'_default_translated'} .= " <bibliomisc>";
   8.285 -	$self->{options}{'_default_inline'} .= " <bibliomisc>";
   8.286 -
   8.287 -	# bibliomixed; contains text; Formatted as a displayed block
   8.288 -	$self->{options}{'_default_translated'} .= " <bibliomixed>";
   8.289 -	$self->{options}{'_default_placeholder'} .= " <bibliomixed>";
   8.290 -
   8.291 -	# bibliomset; contains text; Formatted as a displayed block
   8.292 -	# NOTE: content might need to be inlined, e.g. <bibliomset><title>
   8.293 -	$self->{options}{'_default_translated'} .= " <bibliomset>";
   8.294 -	$self->{options}{'_default_placeholder'} .= " <bibliomset>";
   8.295 -
   8.296 -	# biblioref; does not contain text; Formatted inline
   8.297 -	$self->{options}{'_default_untranslated'} .= " <biblioref>";
   8.298 -	$self->{options}{'_default_inline'} .= " <biblioref>";
   8.299 -
   8.300 -	# bibliorelation; does not contain text; Formatted inline
   8.301 -	$self->{options}{'_default_translated'} .= " <bibliorelation>";
   8.302 -	$self->{options}{'_default_inline'} .= " <bibliorelation>";
   8.303 -
   8.304 -	# biblioset; does not contain text; Formatted as a displayed block
   8.305 -	$self->{options}{'_default_untranslated'} .= " <biblioset>";
   8.306 -	$self->{options}{'_default_break'} .= " <biblioset>";
   8.307 -
   8.308 -	# bibliosource; contains text; Formatted inline
   8.309 -	# NOTE: could be in the break class
   8.310 -	$self->{options}{'_default_translated'} .= " <bibliosource>";
   8.311 -	$self->{options}{'_default_inline'} .= " <bibliosource>";
   8.312 -
   8.313 -	# blockinfo; does not contain text; v4.2, not in v5
   8.314 -	$self->{options}{'_default_untranslated'} .= " <blockinfo>";
   8.315 -	$self->{options}{'_default_placeholder'} .= " <blockinfo>";
   8.316 -
   8.317 -	# blockquote; does not contain text; Formatted as a displayed block
   8.318 -	$self->{options}{'_default_untranslated'} .= " <blockquote>";
   8.319 -	$self->{options}{'_default_break'} .= " <blockquote>";
   8.320 -
   8.321 -	# book; does not contain text; Formatted as a displayed block
   8.322 -	$self->{options}{'_default_untranslated'} .= " <book>";
   8.323 -	$self->{options}{'_default_break'} .= " <book>";
   8.324 -
   8.325 -	# bookbiblio; does not contain text; Formatted as a displayed block
   8.326 -	# Removed in v4.0
   8.327 -	$self->{options}{'_default_untranslated'} .= " <bookbiblio>";
   8.328 -	$self->{options}{'_default_break'} .= " <bookbiblio>";
   8.329 -
   8.330 -	# bookinfo; does not contain text; v4, not in v5
   8.331 -	$self->{options}{'_default_untranslated'} .= " <bookinfo>";
   8.332 -	$self->{options}{'_default_placeholder'} .= " <bookinfo>";
   8.333 -
   8.334 -	# bridgehead; contains text; Formatted as a displayed block
   8.335 -	$self->{options}{'_default_translated'} .= " <bridgehead>";
   8.336 -	$self->{options}{'_default_break'} .= " <bridgehead>";
   8.337 -
   8.338 -# CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
   8.339 -
   8.340 -	# callout; does not contain text; Formatted as a displayed block
   8.341 -	$self->{options}{'_default_untranslated'} .= " <callout>";
   8.342 -	$self->{options}{'_default_break'} .= " <callout>";
   8.343 -
   8.344 -	# calloutlist; does not contain text; Formatted as a displayed block
   8.345 -	$self->{options}{'_default_untranslated'} .= " <calloutlist>";
   8.346 -	$self->{options}{'_default_break'} .= " <calloutlist>";
   8.347 -
   8.348 -	# caption; does not contain text; Formatted as a displayed block
   8.349 -	$self->{options}{'_default_untranslated'} .= " <caption>";
   8.350 -	$self->{options}{'_default_break'} .= " <caption>";
   8.351 -
   8.352 -	# caption (db.html.caption); contains text; Formatted as a displayed block
   8.353 -	# TODO: Check if this works
   8.354 -	$self->{options}{'_default_translated'} .= " <table><caption>";
   8.355 -	$self->{options}{'_default_break'} .= " <table><caption>";
   8.356 -
   8.357 -	# caution; does not contain text; Formatted as a displayed block
   8.358 -	$self->{options}{'_default_untranslated'} .= " <caution>";
   8.359 -	$self->{options}{'_default_break'} .= " <caution>";
   8.360 -
   8.361 -	# chapter; does not contain text; Formatted as a displayed block
   8.362 -	$self->{options}{'_default_untranslated'} .= " <chapter>";
   8.363 -	$self->{options}{'_default_break'} .= " <chapter>";
   8.364 -
   8.365 -	# chapterinfo; does not contain text; v4, not in v5
   8.366 -	$self->{options}{'_default_untranslated'} .= " <chapterinfo>";
   8.367 -	$self->{options}{'_default_placeholder'} .= " <chapterinfo>";
   8.368 -
   8.369 -	# citation; contains text; Formatted inline
   8.370 -	$self->{options}{'_default_translated'} .= " <citation>";
   8.371 -	$self->{options}{'_default_inline'} .= " <citation>";
   8.372 -
   8.373 -	# citebiblioid; contains text; Formatted inline
   8.374 -	# NOTE: maybe untranslated?
   8.375 -	$self->{options}{'_default_translated'} .= " <citebiblioid>";
   8.376 -	$self->{options}{'_default_inline'} .= " <citebiblioid>";
   8.377 -
   8.378 -	# citerefentry; contains text; Formatted inline
   8.379 -	$self->{options}{'_default_translated'} .= " <citerefentry>";
   8.380 -	$self->{options}{'_default_inline'} .= " <citerefentry>";
   8.381 -
   8.382 -	# citetitle; contains text; Formatted inline
   8.383 -	$self->{options}{'_default_translated'} .= " <citetitle>";
   8.384 -	$self->{options}{'_default_inline'} .= " <citetitle>";
   8.385 -
   8.386 -	# city; contains text; Formatted inline
   8.387 -	$self->{options}{'_default_translated'} .= " <city>";
   8.388 -	$self->{options}{'_default_inline'} .= " <city>";
   8.389 -
   8.390 -	# classname; contains text; Formatted inline
   8.391 -	$self->{options}{'_default_translated'} .= " <classname>";
   8.392 -	$self->{options}{'_default_inline'} .= " <classname>";
   8.393 -
   8.394 -	# classsynopsis; does not contain text; may be in a para
   8.395 -	# NOTE: It may contain a classsynopsisinfo, which should be
   8.396 -	#       verbatim
   8.397 -	# XXX: since it is in untranslated class, does the W flag takes
   8.398 -	#      effect?
   8.399 -	$self->{options}{'_default_untranslated'} .= " W<classsynopsis>";
   8.400 -	$self->{options}{'_default_placeholder'} .= " <classsynopsis>";
   8.401 -
   8.402 -	# classsynopsisinfo; contains text;
   8.403 -	# NOTE: see above
   8.404 -	$self->{options}{'_default_translated'} .= " W<classsynopsisinfo>";
   8.405 -	$self->{options}{'_default_inline'} .= " <classsynopsisinfo>";
   8.406 -
   8.407 -	# cmdsynopsis; does not contain text; may be in a para
   8.408 -	# NOTE: It may be clearer as a verbatim block
   8.409 -	# XXX: since it is in untranslated class, does the W flag takes
   8.410 -	#      effect? => not completely. Rewrap afterward?
   8.411 -	$self->{options}{'_default_untranslated'} .= " W<cmdsynopsis>";
   8.412 -	$self->{options}{'_default_placeholder'} .= " <cmdsynopsis>";
   8.413 -
   8.414 -	# co; does not contain text; Formatted inline
   8.415 -	# XXX: tranlsated or not? (label attribute)
   8.416 -	$self->{options}{'_default_translated'} .= " <co>";
   8.417 -	$self->{options}{'_default_inline'} .= " <co>";
   8.418 -
   8.419 -	# code; contains text; Formatted inline
   8.420 -	$self->{options}{'_default_translated'} .= " <code>";
   8.421 -	$self->{options}{'_default_inline'} .= " <code>";
   8.422 -
   8.423 -	# col; does not contain text;
   8.424 -	# NOTE: could be translated to change the layout in a translation
   8.425 -	#       To be done on colgroup in that case.
   8.426 -	$self->{options}{'_default_untranslated'} .= " <col>";
   8.427 -	$self->{options}{'_default_break'} .= " <col>";
   8.428 -
   8.429 -	# colgroup; does not contain text;
   8.430 -	# NOTE: could be translated to change the layout in a translation
   8.431 -	$self->{options}{'_default_untranslated'} .= " <colgroup>";
   8.432 -	$self->{options}{'_default_break'} .= " <colgroup>";
   8.433 -
   8.434 -	# collab; does not contain text; Formatted inline or as a
   8.435 -	# displayed block depending on context
   8.436 -	# NOTE: could be in the break class
   8.437 -	$self->{options}{'_default_untranslated'} .= " <collab>";
   8.438 -	$self->{options}{'_default_inline'} .= " <collab>";
   8.439 -
   8.440 -	# collabname; contains text; Formatted inline or as a
   8.441 -	# displayed block depending on context; v4, not in v5
   8.442 -	$self->{options}{'_default_translated'} .= " <collabname>";
   8.443 -	$self->{options}{'_default_inline'} .= " <collabname>";
   8.444 -
   8.445 -	# colophon; does not contain text; Formatted as a displayed block
   8.446 -	$self->{options}{'_default_untranslated'} .= " <colophon>";
   8.447 -	$self->{options}{'_default_break'} .= " <colophon>";
   8.448 -
   8.449 -	# colspec; does not contain text;
   8.450 -	# NOTE: could be translated to change the layout in a translation
   8.451 -	$self->{options}{'_default_untranslated'} .= " <colspec>";
   8.452 -	$self->{options}{'_default_break'} .= " <colspec>";
   8.453 -
   8.454 -	# command; contains text; Formatted inline
   8.455 -	$self->{options}{'_default_translated'} .= " <command>";
   8.456 -	$self->{options}{'_default_inline'} .= " <command>";
   8.457 -
   8.458 -	# comment; contains text; Formatted inline or as a displayed block
   8.459 -	# Renamed to remark in v4.0
   8.460 -	$self->{options}{'_default_translated'} .= " <comment>";
   8.461 -	$self->{options}{'_default_inline'} .= " <comment>";
   8.462 -
   8.463 -	# computeroutput; contains text; Formatted inline
   8.464 -	# NOTE: "is not a verbatim environment, but an inline."
   8.465 -	$self->{options}{'_default_translated'} .= " <computeroutput>";
   8.466 -	$self->{options}{'_default_inline'} .= " <computeroutput>";
   8.467 -
   8.468 -	# confdates; contains text; Formatted inline or as a
   8.469 -	# displayed block depending on context
   8.470 -	$self->{options}{'_default_translated'} .= " <confdates>";
   8.471 -	$self->{options}{'_default_inline'} .= " <confdates>";
   8.472 -
   8.473 -	# confgroup; does not contain text; Formatted inline or as a
   8.474 -	# displayed block depending on context
   8.475 -	# NOTE: could be in the break class
   8.476 -	$self->{options}{'_default_untranslated'} .= " <confgroup>";
   8.477 -	$self->{options}{'_default_inline'} .= " <confgroup>";
   8.478 -
   8.479 -	# confnum; contains text; Formatted inline or as a
   8.480 -	# displayed block depending on context
   8.481 -	$self->{options}{'_default_translated'} .= " <confnum>";
   8.482 -	$self->{options}{'_default_inline'} .= " <confnum>";
   8.483 -
   8.484 -	# confsponsor; contains text; Formatted inline or as a
   8.485 -	# displayed block depending on context
   8.486 -	$self->{options}{'_default_translated'} .= " <confsponsor>";
   8.487 -	$self->{options}{'_default_inline'} .= " <confsponsor>";
   8.488 -
   8.489 -	# conftitle; contains text; Formatted inline or as a
   8.490 -	# displayed block depending on context
   8.491 -	$self->{options}{'_default_translated'} .= " <conftitle>";
   8.492 -	$self->{options}{'_default_inline'} .= " <conftitle>";
   8.493 -
   8.494 -	# constant; contains text; Formatted inline
   8.495 -	$self->{options}{'_default_translated'} .= " <constant>";
   8.496 -	$self->{options}{'_default_inline'} .= " <constant>";
   8.497 -
   8.498 -	# constraint; does not contain text;
   8.499 -	# NOTE: it might be better to have the production as verbatim
   8.500 -	#       Keeping the constrainst inline to have it close to the
   8.501 -	#       lhs or rhs.
   8.502 -	#       The attribute is translatable
   8.503 -	$self->{options}{'_default_untranslated'} .= " <constraint>";
   8.504 -	$self->{options}{'_default_break'} .= " <constraint>";
   8.505 -
   8.506 -	# constraintdef; does not contain text; Formatted as a displayed block
   8.507 -	$self->{options}{'_default_untranslated'} .= " <constraintdef>";
   8.508 -	$self->{options}{'_default_break'} .= " <constraintdef>";
   8.509 -
   8.510 -	# constructorsynopsis; does not contain text; may be in a para
   8.511 -	# NOTE: It may be clearer as a verbatim block
   8.512 -	# XXX: since it is in untranslated class, does the W flag takes
   8.513 -	#      effect?
   8.514 -	$self->{options}{'_default_untranslated'} .= " W<constructorsynopsis>";
   8.515 -	$self->{options}{'_default_placeholder'} .= " <constructorsynopsis>";
   8.516 -
   8.517 -	# contractnum; contains text; Formatted inline or as a displayed block
   8.518 -	# NOTE: could be in the break class
   8.519 -	$self->{options}{'_default_translated'} .= " <contractnum>";
   8.520 -	$self->{options}{'_default_inline'} .= " <contractnum>";
   8.521 -
   8.522 -	# contractsponsor; contains text; Formatted inline or as a displayed block
   8.523 -	# NOTE: could be in the break class
   8.524 -	$self->{options}{'_default_translated'} .= " <contractsponsor>";
   8.525 -	$self->{options}{'_default_inline'} .= " <contractsponsor>";
   8.526 -
   8.527 -	# contrib; contains text; Formatted inline or as a displayed block
   8.528 -	$self->{options}{'_default_translated'} .= " <contrib>";
   8.529 -	$self->{options}{'_default_inline'} .= " <contrib>";
   8.530 -
   8.531 -	# copyright; contains text; Formatted inline or as a displayed block
   8.532 -	# NOTE: could be in the break class
   8.533 -	$self->{options}{'_default_translated'} .= " <copyright>";
   8.534 -	$self->{options}{'_default_inline'} .= " <copyright>";
   8.535 -
   8.536 -	# coref; does not contain text; Formatted inline
   8.537 -	# XXX: tranlsated or not? (label attribute)
   8.538 -	$self->{options}{'_default_translated'} .= " <coref>";
   8.539 -	$self->{options}{'_default_inline'} .= " <coref>";
   8.540 -
   8.541 -	# corpauthor; contains text; Formatted inline or as a
   8.542 -	# displayed block depending on context; v4, not in v5
   8.543 -	$self->{options}{'_default_translated'} .= " <corpauthor>";
   8.544 -	$self->{options}{'_default_inline'} .= " <corpauthor>";
   8.545 -
   8.546 -	# corpcredit; contains text; Formatted inline or as a
   8.547 -	# displayed block depending on context; v4, not in v5
   8.548 -	$self->{options}{'_default_translated'} .= " <corpcredit>";
   8.549 -	$self->{options}{'_default_inline'} .= " <corpcredit>";
   8.550 -
   8.551 -	# corpname; contains text; Formatted inline or as a
   8.552 -	# displayed block depending on context; v4, not in v5
   8.553 -	$self->{options}{'_default_translated'} .= " <corpname>";
   8.554 -	$self->{options}{'_default_inline'} .= " <corpname>";
   8.555 -
   8.556 -	# country; contains text; Formatted inline
   8.557 -	$self->{options}{'_default_translated'} .= " <country>";
   8.558 -	$self->{options}{'_default_inline'} .= " <country>";
   8.559 -
   8.560 -	# cover; does not contain text; Formatted as a displayed block
   8.561 -	$self->{options}{'_default_untranslated'} .= " <cover>";
   8.562 -	$self->{options}{'_default_break'} .= " <cover>";
   8.563 -
   8.564 -# DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
   8.565 -
   8.566 -	# database; contains text; Formatted inline
   8.567 -	$self->{options}{'_default_translated'} .= " <database>";
   8.568 -	$self->{options}{'_default_inline'} .= " <database>";
   8.569 -
   8.570 -	# date; contains text; Formatted inline
   8.571 -	$self->{options}{'_default_translated'} .= " <date>";
   8.572 -	$self->{options}{'_default_inline'} .= " <date>";
   8.573 -
   8.574 -	# dedication; contains text; Formatted as a displayed block
   8.575 -	$self->{options}{'_default_translated'} .= " <dedication>";
   8.576 -	$self->{options}{'_default_break'} .= " <dedication>";
   8.577 -
   8.578 -	# destructorsynopsis; does not contain text; may be in a para
   8.579 -	# NOTE: It may be clearer as a verbatim block
   8.580 -	# XXX: since it is in untranslated class, does the W flag takes
   8.581 -	#      effect?
   8.582 -	$self->{options}{'_default_untranslated'} .= " W<destructorsynopsis>";
   8.583 -	$self->{options}{'_default_placeholder'} .= " <destructorsynopsis>";
   8.584 -
   8.585 -	# docinfo; does not contain text; removed in v4.0
   8.586 -	$self->{options}{'_default_untranslated'} .= " <docinfo>";
   8.587 -	$self->{options}{'_default_placeholder'} .= " <docinfo>";
   8.588 -
   8.589 -# EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
   8.590 -
   8.591 -	# edition; contains text; Formatted inline or as a displayed block
   8.592 -	# NOTE: could be in the break class
   8.593 -	$self->{options}{'_default_translated'} .= " <edition>";
   8.594 -	$self->{options}{'_default_inline'} .= " <edition>";
   8.595 -
   8.596 -	# editor; does not contain text; Formatted inline or as a
   8.597 -	# displayed block depending on context
   8.598 -	$self->{options}{'_default_untranslated'} .= " <editor>";
   8.599 -	$self->{options}{'_default_inline'} .= " <editor>";
   8.600 -
   8.601 -	# email; contains text; Formatted inline
   8.602 -	$self->{options}{'_default_translated'} .= " <email>";
   8.603 -	$self->{options}{'_default_inline'} .= " <email>";
   8.604 -
   8.605 -	# emphasis; contains text; Formatted inline
   8.606 -	$self->{options}{'_default_translated'} .= " <emphasis>";
   8.607 -	$self->{options}{'_default_inline'} .= " <emphasis>";
   8.608 -
   8.609 -	# entry; contains text;
   8.610 -	$self->{options}{'_default_translated'} .= " <entry>";
   8.611 -	$self->{options}{'_default_break'} .= " <entry>";
   8.612 -
   8.613 -	# entrytbl; does not contain text;
   8.614 -	$self->{options}{'_default_untranslated'} .= " <entrytbl>";
   8.615 -	$self->{options}{'_default_break'} .= " <entrytbl>";
   8.616 -
   8.617 -	# envar; contains text; Formatted inline
   8.618 -	$self->{options}{'_default_translated'} .= " <envar>";
   8.619 -	$self->{options}{'_default_inline'} .= " <envar>";
   8.620 -
   8.621 -	# epigraph; contains text; Formatted as a displayed block.
   8.622 -	# NOTE: maybe contained in a para
   8.623 -	$self->{options}{'_default_translated'} .= " <epigraph>";
   8.624 -	$self->{options}{'_default_placeholder'} .= " <epigraph>";
   8.625 -
   8.626 -	# equation; does not contain text; Formatted as a displayed block.
   8.627 -	$self->{options}{'_default_untranslated'} .= " <equation>";
   8.628 -	$self->{options}{'_default_break'} .= " <equation>";
   8.629 -
   8.630 -	# errorcode; contains text; Formatted inline
   8.631 -	$self->{options}{'_default_translated'} .= " <errorcode>";
   8.632 -	$self->{options}{'_default_inline'} .= " <errorcode>";
   8.633 -
   8.634 -	# errorname; contains text; Formatted inline
   8.635 -	$self->{options}{'_default_translated'} .= " <errorname>";
   8.636 -	$self->{options}{'_default_inline'} .= " <errorname>";
   8.637 -
   8.638 -	# errortext; contains text; Formatted inline
   8.639 -	$self->{options}{'_default_translated'} .= " <errortext>";
   8.640 -	$self->{options}{'_default_inline'} .= " <errortext>";
   8.641 -
   8.642 -	# errortype; contains text; Formatted inline
   8.643 -	$self->{options}{'_default_translated'} .= " <errortype>";
   8.644 -	$self->{options}{'_default_inline'} .= " <errortype>";
   8.645 -
   8.646 -	# example; does not contain text; Formatted as a displayed block.
   8.647 -	# NOTE: maybe contained in a para
   8.648 -	$self->{options}{'_default_untranslated'} .= " <example>";
   8.649 -	$self->{options}{'_default_placeholder'} .= " <example>";
   8.650 -
   8.651 -	# exceptionname; contains text; Formatted inline
   8.652 -	$self->{options}{'_default_translated'} .= " <exceptionname>";
   8.653 -	$self->{options}{'_default_inline'} .= " <exceptionname>";
   8.654 -
   8.655 -	# extendedlink; does not contain text;
   8.656 -	$self->{options}{'_default_untranslated'} .= " <extendedlink>";
   8.657 -	$self->{options}{'_default_inline'} .= " <extendedlink>";
   8.658 -
   8.659 -# FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
   8.660 -
   8.661 -	# fax; contains text; Formatted inline
   8.662 -	$self->{options}{'_default_translated'} .= " <fax>";
   8.663 -	$self->{options}{'_default_inline'} .= " <fax>";
   8.664 -
   8.665 -	# fieldsynopsis; does not contain text; may be in a para
   8.666 -	$self->{options}{'_default_untranslated'} .= " <fieldsynopsis>";
   8.667 -	$self->{options}{'_default_inline'} .= " <fieldsynopsis>";
   8.668 -
   8.669 -	# figure; does not contain text; Formatted as a displayed block.
   8.670 -	# NOTE: maybe contained in a para
   8.671 -	$self->{options}{'_default_untranslated'} .= " <figure>";
   8.672 -	$self->{options}{'_default_placeholder'} .= " <figure>";
   8.673 -
   8.674 -	# filename; contains text; Formatted inline
   8.675 -	$self->{options}{'_default_translated'} .= " <filename>";
   8.676 -	$self->{options}{'_default_inline'} .= " <filename>";
   8.677 -
   8.678 -	# firstname; contains text; Formatted inline
   8.679 -	$self->{options}{'_default_translated'} .= " <firstname>";
   8.680 -	$self->{options}{'_default_inline'} .= " <firstname>";
   8.681 -
   8.682 -	# firstterm; contains text; Formatted inline
   8.683 -	$self->{options}{'_default_translated'} .= " <firstterm>";
   8.684 -	$self->{options}{'_default_inline'} .= " <firstterm>";
   8.685 -
   8.686 -	# footnote; contains text;
   8.687 -	$self->{options}{'_default_translated'} .= " <footnote>";
   8.688 -	$self->{options}{'_default_placeholder'} .= " <footnote>";
   8.689 -
   8.690 -	# footnoteref; contains text;
   8.691 -	$self->{options}{'_default_translated'} .= " <footnoteref>";
   8.692 -	$self->{options}{'_default_inline'} .= " <footnoteref>";
   8.693 -
   8.694 -	# foreignphrase; contains text;
   8.695 -	$self->{options}{'_default_translated'} .= " <foreignphrase>";
   8.696 -	$self->{options}{'_default_inline'} .= " <foreignphrase>";
   8.697 -
   8.698 -	# formalpara; does not contain text; Formatted as a displayed block.
   8.699 -	$self->{options}{'_default_untranslated'} .= " <formalpara>";
   8.700 -	$self->{options}{'_default_break'} .= " <formalpara>";
   8.701 -
   8.702 -	# funcdef; contains text; Formatted inline
   8.703 -	$self->{options}{'_default_translated'} .= " <funcdef>";
   8.704 -	$self->{options}{'_default_inline'} .= " <funcdef>";
   8.705 -
   8.706 -	# funcparams; contains text; Formatted inline
   8.707 -	$self->{options}{'_default_translated'} .= " <funcparams>";
   8.708 -	$self->{options}{'_default_inline'} .= " <funcparams>";
   8.709 -
   8.710 -	# funcprototype; does not contain text;
   8.711 -	# NOTE: maybe contained in a funcsynopsis, contained in a para
   8.712 -	$self->{options}{'_default_untranslated'} .= " <funcprototype>";
   8.713 -	$self->{options}{'_default_placeholder'} .= " <funcprototype>";
   8.714 -
   8.715 -	# funcsynopsis; does not contain text;
   8.716 -	# NOTE: maybe contained in a para
   8.717 -	$self->{options}{'_default_untranslated'} .= " <funcsynopsis>";
   8.718 -	$self->{options}{'_default_placeholder'} .= " <funcsynopsis>";
   8.719 -
   8.720 -	# funcsynopsisinfo; contains text; verbatim
   8.721 -	# NOTE: maybe contained in a funcsynopsis, contained in a para
   8.722 -	$self->{options}{'_default_translated'} .= " W<funcsynopsisinfo>";
   8.723 -	$self->{options}{'_default_placeholder'} .= " <funcsynopsisinfo>";
   8.724 -
   8.725 -	# function; contains text; Formatted inline
   8.726 -	$self->{options}{'_default_translated'} .= " <function>";
   8.727 -	$self->{options}{'_default_inline'} .= " <function>";
   8.728 -
   8.729 -# GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
   8.730 -
   8.731 -	# glossary; does not contain text; Formatted as a displayed block.
   8.732 -	$self->{options}{'_default_untranslated'} .= " <glossary>";
   8.733 -	$self->{options}{'_default_break'} .= " <glossary>";
   8.734 -
   8.735 -	# glossaryinfo; does not contain text; v4, not in v5
   8.736 -	$self->{options}{'_default_untranslated'} .= " <glossaryinfo>";
   8.737 -	$self->{options}{'_default_placeholder'} .= " <glossaryinfo>";
   8.738 -
   8.739 -	# glossdef; does not contain text; Formatted as a displayed block.
   8.740 -	$self->{options}{'_default_untranslated'} .= " <glossdef>";
   8.741 -	$self->{options}{'_default_break'} .= " <glossdef>";
   8.742 -
   8.743 -	# glossdiv; does not contain text; Formatted as a displayed block.
   8.744 -	$self->{options}{'_default_untranslated'} .= " <glossdiv>";
   8.745 -	$self->{options}{'_default_break'} .= " <glossdiv>";
   8.746 -
   8.747 -	# glossentry; does not contain text; Formatted as a displayed block.
   8.748 -	$self->{options}{'_default_untranslated'} .= " <glossentry>";
   8.749 -	$self->{options}{'_default_break'} .= " <glossentry>";
   8.750 -
   8.751 -	# glosslist; does not contain text; Formatted as a displayed block.
   8.752 -	$self->{options}{'_default_untranslated'} .= " <glosslist>";
   8.753 -	$self->{options}{'_default_break'} .= " <glosslist>";
   8.754 -
   8.755 -	# glosssee; contains text; Formatted as a displayed block.
   8.756 -	$self->{options}{'_default_translated'} .= " <glosssee>";
   8.757 -	$self->{options}{'_default_break'} .= " <glosssee>";
   8.758 -
   8.759 -	# glossseealso; contains text; Formatted as a displayed block.
   8.760 -	$self->{options}{'_default_translated'} .= " <glossseealso>";
   8.761 -	$self->{options}{'_default_break'} .= " <glossseealso>";
   8.762 -
   8.763 -	# glossterm; contains text; Formatted inline
   8.764 -	$self->{options}{'_default_translated'} .= " <glossterm>";
   8.765 -	$self->{options}{'_default_inline'} .= " <glossterm>";
   8.766 -
   8.767 -	# graphic; does not contain text; Formatted as a displayed block
   8.768 -	# v4, not in v5
   8.769 -	$self->{options}{'_default_untranslated'} .= " <graphic>";
   8.770 -	$self->{options}{'_default_inline'} .= " <graphic>";
   8.771 -	$self->{options}{'_default_attributes'}.=' <graphic>fileref';
   8.772 -
   8.773 -	# graphicco; does not contain text; Formatted as a displayed block.
   8.774 -	# v4, not in v5
   8.775 -	$self->{options}{'_default_untranslated'} .= " <graphicco>";
   8.776 -	$self->{options}{'_default_placeholder'} .= " <graphicco>";
   8.777 -
   8.778 -	# group; does not contain text; Formatted inline
   8.779 -	$self->{options}{'_default_untranslated'} .= " W<group>";
   8.780 -	$self->{options}{'_default_inline'} .= " <group>";
   8.781 -
   8.782 -	# guibutton; contains text; Formatted inline
   8.783 -	$self->{options}{'_default_translated'} .= " <guibutton>";
   8.784 -	$self->{options}{'_default_inline'} .= " <guibutton>";
   8.785 -
   8.786 -	# guiicon; contains text; Formatted inline
   8.787 -	$self->{options}{'_default_translated'} .= " <guiicon>";
   8.788 -	$self->{options}{'_default_inline'} .= " <guiicon>";
   8.789 -
   8.790 -	# guilabel; contains text; Formatted inline
   8.791 -	$self->{options}{'_default_translated'} .= " <guilabel>";
   8.792 -	$self->{options}{'_default_inline'} .= " <guilabel>";
   8.793 -
   8.794 -	# guimenu; contains text; Formatted inline
   8.795 -	$self->{options}{'_default_translated'} .= " <guimenu>";
   8.796 -	$self->{options}{'_default_inline'} .= " <guimenu>";
   8.797 -
   8.798 -	# guimenuitem; contains text; Formatted inline
   8.799 -	$self->{options}{'_default_translated'} .= " <guimenuitem>";
   8.800 -	$self->{options}{'_default_inline'} .= " <guimenuitem>";
   8.801 -
   8.802 -	# guisubmenu; contains text; Formatted inline
   8.803 -	$self->{options}{'_default_translated'} .= " <guisubmenu>";
   8.804 -	$self->{options}{'_default_inline'} .= " <guisubmenu>";
   8.805 -
   8.806 -# HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
   8.807 -
   8.808 -	# hardware; contains text; Formatted inline
   8.809 -	$self->{options}{'_default_translated'} .= " <hardware>";
   8.810 -	$self->{options}{'_default_inline'} .= " <hardware>";
   8.811 -
   8.812 -	# highlights; does not contain text; Formatted inline
   8.813 -	# v4, not in v5
   8.814 -	$self->{options}{'_default_untranslated'} .= " <highlights>";
   8.815 -	$self->{options}{'_default_break'} .= " <highlights>";
   8.816 -
   8.817 -	# holder; contains text;
   8.818 -	# NOTE: may depend on the copyright container
   8.819 -	$self->{options}{'_default_translated'} .= " <holder>";
   8.820 -	$self->{options}{'_default_inline'} .= " <holder>";
   8.821 -
   8.822 -	# honorific; contains text; Formatted inline
   8.823 -	$self->{options}{'_default_translated'} .= " <honorific>";
   8.824 -	$self->{options}{'_default_inline'} .= " <honorific>";
   8.825 -
   8.826 -	# html:button; contains text; Formatted inline
   8.827 -	$self->{options}{'_default_translated'} .= " <html:button>";
   8.828 -	$self->{options}{'_default_inline'} .= " <html:button>";
   8.829 -
   8.830 -	# html:fieldset; contains text; Formatted inline
   8.831 -	$self->{options}{'_default_translated'} .= " <html:fieldset>";
   8.832 -	$self->{options}{'_default_inline'} .= " <html:fieldset>";
   8.833 -
   8.834 -	# html:form; does not contain text;
   8.835 -	$self->{options}{'_default_translated'} .= " <html:form>";
   8.836 -	$self->{options}{'_default_inline'} .= " <html:form>";
   8.837 -
   8.838 -	# html:input; does not contain text; Formatted inline
   8.839 -	# NOTE: attributes are translatable
   8.840 -	$self->{options}{'_default_translated'} .= " <html:input>";
   8.841 -	$self->{options}{'_default_inline'} .= " <html:input>";
   8.842 -
   8.843 -	# html:label; contains text; Formatted inline
   8.844 -	$self->{options}{'_default_translated'} .= " <html:label>";
   8.845 -	$self->{options}{'_default_inline'} .= " <html:label>";
   8.846 -
   8.847 -	# html:legend; contains text; Formatted inline
   8.848 -	$self->{options}{'_default_translated'} .= " <html:legend>";
   8.849 -	$self->{options}{'_default_inline'} .= " <html:legend>";
   8.850 -
   8.851 -	# html:option; contains text; Formatted inline
   8.852 -	$self->{options}{'_default_translated'} .= " <html:option>";
   8.853 -	$self->{options}{'_default_inline'} .= " <html:option>";
   8.854 -
   8.855 -	# html:select; does not contain text; Formatted inline
   8.856 -	$self->{options}{'_default_translated'} .= " <html:select>";
   8.857 -	$self->{options}{'_default_inline'} .= " <html:select>";
   8.858 -
   8.859 -	# html:textarea; contains text; Formatted as a displayed block.
   8.860 -	$self->{options}{'_default_translated'} .= " <html:textarea>";
   8.861 -	$self->{options}{'_default_placeholder'} .= " <html:textarea>";
   8.862 -
   8.863 -	# imagedata; does not contain text; May be formatted inline or
   8.864 -	# as a displayed block, depending on context
   8.865 -	$self->{options}{'_default_translated'} .= " <imagedata>";
   8.866 -	$self->{options}{'_default_inline'} .= " <imagedata>";
   8.867 -	$self->{options}{'_default_attributes'}.=' <imagedata>fileref';
   8.868 -
   8.869 -	# imageobject; does not contain text; May be formatted inline or
   8.870 -	# as a displayed block, depending on context
   8.871 -	$self->{options}{'_default_untranslated'} .= " <imageobject>";
   8.872 -	$self->{options}{'_default_inline'} .= " <imageobject>";
   8.873 -
   8.874 -	# imageobjectco; does not contain text; Formatted as a displayed block
   8.875 -	# NOTE: may be in a inlinemediaobject
   8.876 -	# TODO: check if this works when the inlinemediaobject is defined
   8.877 -	# as inline
   8.878 -	$self->{options}{'_default_untranslated'} .= " <imageobjectco>";
   8.879 -	$self->{options}{'_default_break'} .= " <imageobjectco>";
   8.880 -
   8.881 -	# important; does not contain text; Formatted as a displayed block.
   8.882 -	$self->{options}{'_default_untranslated'} .= " <important>";
   8.883 -	$self->{options}{'_default_break'} .= " <important>";
   8.884 -
   8.885 -	# index; does not contain text; Formatted as a displayed block.
   8.886 -	$self->{options}{'_default_untranslated'} .= " <index>";
   8.887 -	$self->{options}{'_default_break'} .= " <index>";
   8.888 -
   8.889 -	# indexdiv; does not contain text; Formatted as a displayed block.
   8.890 -	$self->{options}{'_default_untranslated'} .= " <indexdiv>";
   8.891 -	$self->{options}{'_default_break'} .= " <indexdiv>";
   8.892 -
   8.893 -	# indexentry; does not contain text; Formatted as a displayed block.
   8.894 -	$self->{options}{'_default_untranslated'} .= " <indexentry>";
   8.895 -	$self->{options}{'_default_break'} .= " <indexentry>";
   8.896 -
   8.897 -	# indexinfo; does not contain text; v4, not in v5
   8.898 -	$self->{options}{'_default_untranslated'} .= " <indexinfo>";
   8.899 -	$self->{options}{'_default_placeholder'} .= " <indexinfo>";
   8.900 -
   8.901 -	# indexterm; does not contain text; 
   8.902 -	$self->{options}{'_default_untranslated'} .= " <indexterm>";
   8.903 -	$self->{options}{'_default_placeholder'} .= " <indexterm>";
   8.904 -
   8.905 -	# info; does not contain text; 
   8.906 -	$self->{options}{'_default_untranslated'} .= " <info>";
   8.907 -	$self->{options}{'_default_placeholder'} .= " <info>";
   8.908 -
   8.909 -	# informalequation; does not contain text; Formatted as a displayed block.
   8.910 -	$self->{options}{'_default_untranslated'} .= " <informalequation>";
   8.911 -	$self->{options}{'_default_placeholder'} .= " <informalequation>";
   8.912 -
   8.913 -	# informalexample; does not contain text; Formatted as a displayed block.
   8.914 -	# NOTE: can be in a para
   8.915 -	$self->{options}{'_default_untranslated'} .= " <informalexample>";
   8.916 -	$self->{options}{'_default_break'} .= " <informalexample>";
   8.917 -
   8.918 -	# informalfigure; does not contain text; Formatted as a displayed block.
   8.919 -	# NOTE: can be in a para
   8.920 -	$self->{options}{'_default_untranslated'} .= " <informalfigure>";
   8.921 -	$self->{options}{'_default_break'} .= " <informalfigure>";
   8.922 -
   8.923 -	# informaltable; does not contain text; Formatted as a displayed block.
   8.924 -	# NOTE: can be in a para
   8.925 -	$self->{options}{'_default_untranslated'} .= " <informaltable>";
   8.926 -	$self->{options}{'_default_break'} .= " <informaltable>";
   8.927 -
   8.928 -	# initializer; contains text; Formatted inline
   8.929 -	$self->{options}{'_default_translated'} .= " <initializer>";
   8.930 -	$self->{options}{'_default_inline'} .= " <initializer>";
   8.931 -
   8.932 -	# inlineequation; does not contain text; Formatted inline
   8.933 -	$self->{options}{'_default_translated'} .= " W<inlineequation>";
   8.934 -	$self->{options}{'_default_placeholder'} .= " <inlineequation>";
   8.935 -
   8.936 -	# inlinegraphic; does not contain text; Formatted inline
   8.937 -	# empty; v4, not in v5
   8.938 -	$self->{options}{'_default_translated'} .= " W<inlinegraphic>";
   8.939 -	$self->{options}{'_default_inline'} .= " <inlinegraphic>";
   8.940 -
   8.941 -	# inlinemediaobject; does not contain text; Formatted inline
   8.942 -	$self->{options}{'_default_translated'} .= " <inlinemediaobject>";
   8.943 -	$self->{options}{'_default_placeholder'} .= " <inlinemediaobject>";
   8.944 -
   8.945 -	# interface; contains text; Formatted inline; v4, not in v5
   8.946 -	$self->{options}{'_default_translated'} .= " <interface>";
   8.947 -	$self->{options}{'_default_inline'} .= " <interface>";
   8.948 -
   8.949 -	# interfacedefinition; contains text; Formatted inline
   8.950 -	# Removed in v4.0
   8.951 -	$self->{options}{'_default_translated'} .= " <interfacedefinition>";
   8.952 -	$self->{options}{'_default_inline'} .= " <interfacedefinition>";
   8.953 -
   8.954 -	# interfacename; contains text; Formatted inline
   8.955 -	$self->{options}{'_default_translated'} .= " <interfacename>";
   8.956 -	$self->{options}{'_default_inline'} .= " <interfacename>";
   8.957 -
   8.958 -	# invpartnumber; contains text; Formatted inline; v4, not in v5
   8.959 -	$self->{options}{'_default_translated'} .= " <invpartnumber>";
   8.960 -	$self->{options}{'_default_inline'} .= " <invpartnumber>";
   8.961 -
   8.962 -	# isbn; contains text; Formatted inline; v4, not in v5
   8.963 -	$self->{options}{'_default_translated'} .= " <isbn>";
   8.964 -	$self->{options}{'_default_inline'} .= " <isbn>";
   8.965 -
   8.966 -	# issn; contains text; Formatted inline; v4, not in v5
   8.967 -	$self->{options}{'_default_translated'} .= " <issn>";
   8.968 -	$self->{options}{'_default_inline'} .= " <issn>";
   8.969 -
   8.970 -	# issuenum; contains text; Formatted inline or as a displayed block
   8.971 -	# NOTE: could be in the break class
   8.972 -	$self->{options}{'_default_translated'} .= " <issuenum>";
   8.973 -	$self->{options}{'_default_inline'} .= " <issuenum>";
   8.974 -
   8.975 -	# itemizedlist; does not contain text; Formatted as a displayed block.
   8.976 -	$self->{options}{'_default_untranslated'} .= " <itemizedlist>";
   8.977 -	$self->{options}{'_default_break'} .= " <itemizedlist>";
   8.978 -
   8.979 -	# itermset; does not contain text;
   8.980 -	# FIXME
   8.981 -	$self->{options}{'_default_untranslated'} .= " <itermset>";
   8.982 -	$self->{options}{'_default_inline'} .= " <itermset>";
   8.983 -
   8.984 -# JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
   8.985 -
   8.986 -	# jobtitle; contains text; Formatted inline or as a displayed block
   8.987 -	# NOTE: can be in a para
   8.988 -	$self->{options}{'_default_translated'} .= " <jobtitle>";
   8.989 -	$self->{options}{'_default_inline'} .= " <jobtitle>";
   8.990 -
   8.991 -# KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
   8.992 -
   8.993 -	# keycap; contains text; Formatted inline
   8.994 -	$self->{options}{'_default_translated'} .= " <keycap>";
   8.995 -	$self->{options}{'_default_inline'} .= " <keycap>";
   8.996 -
   8.997 -	# keycode; contains text; Formatted inline
   8.998 -	$self->{options}{'_default_translated'} .= " <keycode>";
   8.999 -	$self->{options}{'_default_inline'} .= " <keycode>";
  8.1000 -
  8.1001 -	# keycombo; does not contain text; Formatted inline
  8.1002 -	$self->{options}{'_default_translated'} .= " <keycombo>";
  8.1003 -	$self->{options}{'_default_inline'} .= " <keycombo>";
  8.1004 -
  8.1005 -	# keysym; contains text; Formatted inline
  8.1006 -	$self->{options}{'_default_translated'} .= " <keysym>";
  8.1007 -	$self->{options}{'_default_inline'} .= " <keysym>";
  8.1008 -
  8.1009 -	# keyword; contains text;
  8.1010 -	# NOTE: could be inline
  8.1011 -	$self->{options}{'_default_translated'} .= " <keyword>";
  8.1012 -	$self->{options}{'_default_break'} .= " <keyword>";
  8.1013 -
  8.1014 -	# keywordset; contains text; Formatted inline or as a displayed block
  8.1015 -	# NOTE: could be placeholder/break
  8.1016 -	$self->{options}{'_default_translated'} .= " <keywordset>";
  8.1017 -	$self->{options}{'_default_break'} .= " <keywordset>";
  8.1018 -
  8.1019 -# LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
  8.1020 -
  8.1021 -	# label; contains text; Formatted as a displayed block
  8.1022 -	$self->{options}{'_default_translated'} .= " <label>";
  8.1023 -	$self->{options}{'_default_break'} .= " <label>";
  8.1024 -
  8.1025 -	# legalnotice; contains text; Formatted as a displayed block
  8.1026 -	$self->{options}{'_default_translated'} .= " <legalnotice>";
  8.1027 -	$self->{options}{'_default_break'} .= " <legalnotice>";
  8.1028 -
  8.1029 -	# lhs; contains text; Formatted as a displayed block.
  8.1030 -	# NOTE: it might be better to have the production as verbatim
  8.1031 -	#       Keeping the constrainst inline to have it close to the
  8.1032 -	#       lhs or rhs.
  8.1033 -	$self->{options}{'_default_translated'} .= " <lhs>";
  8.1034 -	$self->{options}{'_default_break'} .= " <lhs>";
  8.1035 -
  8.1036 -	# lineage; contains text; Formatted inline
  8.1037 -	$self->{options}{'_default_translated'} .= " <lineage>";
  8.1038 -	$self->{options}{'_default_inline'} .= " <lineage>";
  8.1039 -
  8.1040 -	# lineannotation; contains text; Formatted inline
  8.1041 -	$self->{options}{'_default_translated'} .= " <lineannotation>";
  8.1042 -	$self->{options}{'_default_inline'} .= " <lineannotation>";
  8.1043 -
  8.1044 -	# link; contains text; Formatted inline
  8.1045 -	$self->{options}{'_default_translated'} .= " <link>";
  8.1046 -	$self->{options}{'_default_inline'} .= " <link>";
  8.1047 -
  8.1048 -	# listitem; does not contain text; Formatted as a displayed block.
  8.1049 -	$self->{options}{'_default_untranslated'} .= " <listitem>";
  8.1050 -	$self->{options}{'_default_break'} .= " <listitem>";
  8.1051 -
  8.1052 -	# literal; contains text; Formatted inline
  8.1053 -	$self->{options}{'_default_translated'} .= " <literal>";
  8.1054 -	$self->{options}{'_default_inline'} .= " <literal>";
  8.1055 -
  8.1056 -	# literallayout; contains text; verbatim
  8.1057 -	$self->{options}{'_default_translated'} .= " W<literallayout>";
  8.1058 -	$self->{options}{'_default_placeholder'} .= " <literallayout>";
  8.1059 -
  8.1060 -	# locator; does not contain text;
  8.1061 -	$self->{options}{'_default_untranslated'} .= " <locator>";
  8.1062 -	$self->{options}{'_default_inline'} .= " <locator>";
  8.1063 -
  8.1064 -	# lot; does not contain text; Formatted as a displayed block.
  8.1065 -	# v4, not in v5
  8.1066 -	$self->{options}{'_default_untranslated'} .= " <lot>";
  8.1067 -	$self->{options}{'_default_break'} .= " <lot>";
  8.1068 -
  8.1069 -	# lotentry; contains text; Formatted as a displayed block.
  8.1070 -	# v4, not in v5
  8.1071 -	$self->{options}{'_default_translated'} .= " <lotentry>";
  8.1072 -	$self->{options}{'_default_break'} .= " <lotentry>";
  8.1073 -
  8.1074 -# MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
  8.1075 -
  8.1076 -	# manvolnum; contains text;
  8.1077 -	$self->{options}{'_default_translated'} .= " <manvolnum>";
  8.1078 -	$self->{options}{'_default_inline'} .= " <manvolnum>";
  8.1079 -
  8.1080 -	# markup; contains text; Formatted inline
  8.1081 -	$self->{options}{'_default_translated'} .= " <markup>";
  8.1082 -	$self->{options}{'_default_inline'} .= " <markup>";
  8.1083 -
  8.1084 -	# mathphrase; contains text; Formatted inline
  8.1085 -	$self->{options}{'_default_translated'} .= " <mathphrase>";
  8.1086 -	$self->{options}{'_default_inline'} .= " <mathphrase>";
  8.1087 -
  8.1088 -	# medialabel; contains text; Formatted inline
  8.1089 -	# v4, not in v5
  8.1090 -	$self->{options}{'_default_translated'} .= " <medialabel>";
  8.1091 -	$self->{options}{'_default_inline'} .= " <medialabel>";
  8.1092 -
  8.1093 -	# mediaobject; does not contain text; Formatted as a displayed block.
  8.1094 -	$self->{options}{'_default_untranslated'} .= " <mediaobject>";
  8.1095 -	$self->{options}{'_default_placeholder'} .= " <mediaobject>";
  8.1096 -
  8.1097 -	# mediaobjectco; does not contain text; Formatted as a displayed block.
  8.1098 -	$self->{options}{'_default_untranslated'} .= " <mediaobjectco>";
  8.1099 -	$self->{options}{'_default_placeholder'} .= " <mediaobjectco>";
  8.1100 -
  8.1101 -	# member; contains text; Formatted inline
  8.1102 -	$self->{options}{'_default_translated'} .= " <member>";
  8.1103 -	$self->{options}{'_default_inline'} .= " <member>";
  8.1104 -
  8.1105 -	# menuchoice; does not contain text; Formatted inline
  8.1106 -	$self->{options}{'_default_translated'} .= " <menuchoice>";
  8.1107 -	$self->{options}{'_default_inline'} .= " <menuchoice>";
  8.1108 -
  8.1109 -	# methodname; contains text; Formatted inline
  8.1110 -	$self->{options}{'_default_translated'} .= " <methodname>";
  8.1111 -	$self->{options}{'_default_inline'} .= " <methodname>";
  8.1112 -
  8.1113 -	# methodparam; does not contain text; Formatted inline
  8.1114 -	$self->{options}{'_default_translated'} .= " <methodparam>";
  8.1115 -	$self->{options}{'_default_inline'} .= " <methodparam>";
  8.1116 -
  8.1117 -	# methodsynopsis; does not contain text; Formatted inline
  8.1118 -	$self->{options}{'_default_translated'} .= " <methodsynopsis>";
  8.1119 -	$self->{options}{'_default_inline'} .= " <methodsynopsis>";
  8.1120 -
  8.1121 -	# modifier; contains text; Formatted inline
  8.1122 -	$self->{options}{'_default_translated'} .= " <modifier>";
  8.1123 -	$self->{options}{'_default_inline'} .= " <modifier>";
  8.1124 -
  8.1125 -	# mousebutton; contains text; Formatted inline
  8.1126 -	$self->{options}{'_default_translated'} .= " <mousebutton>";
  8.1127 -	$self->{options}{'_default_inline'} .= " <mousebutton>";
  8.1128 -
  8.1129 -	# msg; does not contain text; Formatted as a displayed block.
  8.1130 -	$self->{options}{'_default_untranslated'} .= " <msg>";
  8.1131 -	$self->{options}{'_default_break'} .= " <msg>";
  8.1132 -
  8.1133 -	# msgaud; contains text; Formatted as a displayed block.
  8.1134 -	$self->{options}{'_default_translated'} .= " <msgaud>";
  8.1135 -	$self->{options}{'_default_break'} .= " <msgaud>";
  8.1136 -
  8.1137 -	# msgentry; does not contain text; Formatted as a displayed block.
  8.1138 -	$self->{options}{'_default_untranslated'} .= " <msgentry>";
  8.1139 -	$self->{options}{'_default_break'} .= " <msgentry>";
  8.1140 -
  8.1141 -	# msgexplan; does not contain text; Formatted as a displayed block.
  8.1142 -	$self->{options}{'_default_untranslated'} .= " <msgexplan>";
  8.1143 -	$self->{options}{'_default_break'} .= " <msgexplan>";
  8.1144 -
  8.1145 -	# msginfo; does not contain text; Formatted as a displayed block.
  8.1146 -	$self->{options}{'_default_untranslated'} .= " <msginfo>";
  8.1147 -	$self->{options}{'_default_break'} .= " <msginfo>";
  8.1148 -
  8.1149 -	# msglevel; contains text; Formatted as a displayed block.
  8.1150 -	$self->{options}{'_default_translated'} .= " <msglevel>";
  8.1151 -	$self->{options}{'_default_break'} .= " <msglevel>";
  8.1152 -
  8.1153 -	# msgmain; does not contain text; Formatted as a displayed block.
  8.1154 -	$self->{options}{'_default_untranslated'} .= " <msgmain>";
  8.1155 -	$self->{options}{'_default_break'} .= " <msgmain>";
  8.1156 -
  8.1157 -	# msgorig; contains text; Formatted as a displayed block.
  8.1158 -	$self->{options}{'_default_translated'} .= " <msgorig>";
  8.1159 -	$self->{options}{'_default_break'} .= " <msgorig>";
  8.1160 -
  8.1161 -	# msgrel; does not contain text; Formatted as a displayed block.
  8.1162 -	$self->{options}{'_default_untranslated'} .= " <msgrel>";
  8.1163 -	$self->{options}{'_default_break'} .= " <msgrel>";
  8.1164 -
  8.1165 -	# msgset; does not contain text; Formatted as a displayed block.
  8.1166 -	$self->{options}{'_default_untranslated'} .= " <msgset>";
  8.1167 -	$self->{options}{'_default_placeholder'} .= " <msgset>";
  8.1168 -
  8.1169 -	# msgsub; does not contain text; Formatted as a displayed block.
  8.1170 -	$self->{options}{'_default_untranslated'} .= " <msgsub>";
  8.1171 -	$self->{options}{'_default_break'} .= " <msgsub>";
  8.1172 -
  8.1173 -	# msgtext; does not contain text; Formatted as a displayed block.
  8.1174 -	$self->{options}{'_default_untranslated'} .= " <msgtext>";
  8.1175 -	$self->{options}{'_default_break'} .= " <msgtext>";
  8.1176 -
  8.1177 -# NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
  8.1178 -
  8.1179 -	# nonterminal; contains text; Formatted inline
  8.1180 -	$self->{options}{'_default_translated'} .= " <nonterminal>";
  8.1181 -	$self->{options}{'_default_inline'} .= " <nonterminal>";
  8.1182 -
  8.1183 -	# note; does not contain text; Formatted inline
  8.1184 -	# NOTE: can be in a para
  8.1185 -	$self->{options}{'_default_untranslated'} .= " <note>";
  8.1186 -	$self->{options}{'_default_inline'} .= " <note>";
  8.1187 -
  8.1188 -# OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  8.1189 -
  8.1190 -	# objectinfo; does not contain text; v3.1 -> v4, not in v5
  8.1191 -	$self->{options}{'_default_untranslated'} .= " <objectinfo>";
  8.1192 -	$self->{options}{'_default_placeholder'} .= " <objectinfo>";
  8.1193 -
  8.1194 -	# olink; contains text; Formatted inline
  8.1195 -	$self->{options}{'_default_translated'} .= " <olink>";
  8.1196 -	$self->{options}{'_default_inline'} .= " <olink>";
  8.1197 -
  8.1198 -	# ooclass; does not contain text; Formatted inline
  8.1199 -	$self->{options}{'_default_translated'} .= " <ooclass>";
  8.1200 -	$self->{options}{'_default_inline'} .= " <ooclass>";
  8.1201 -
  8.1202 -	# ooexception; contains text; Formatted inline
  8.1203 -	$self->{options}{'_default_translated'} .= " <ooexception>";
  8.1204 -	$self->{options}{'_default_inline'} .= " <ooexception>";
  8.1205 -
  8.1206 -	# oointerface; contains text; Formatted inline
  8.1207 -	$self->{options}{'_default_translated'} .= " <oointerface>";
  8.1208 -	$self->{options}{'_default_inline'} .= " <oointerface>";
  8.1209 -
  8.1210 -	# option; contains text; Formatted inline
  8.1211 -	$self->{options}{'_default_translated'} .= " <option>";
  8.1212 -	$self->{options}{'_default_inline'} .= " <option>";
  8.1213 -
  8.1214 -	# optional; contains text; Formatted inline
  8.1215 -	$self->{options}{'_default_translated'} .= " <optional>";
  8.1216 -	$self->{options}{'_default_inline'} .= " <optional>";
  8.1217 -
  8.1218 -	# orderedlist; does not contain text; Formatted as a displayed block.
  8.1219 -	$self->{options}{'_default_untranslated'} .= " <orderedlist>";
  8.1220 -	$self->{options}{'_default_placeholder'} .= " <orderedlist>";
  8.1221 -
  8.1222 -	# org; does not contain text; Formatted inline or as a
  8.1223 -	# displayed block depending on context
  8.1224 -	$self->{options}{'_default_untranslated'} .= " <org>";
  8.1225 -	$self->{options}{'_default_inline'} .= " <org>";
  8.1226 -
  8.1227 -	# orgdiv; contains text; Formatted inline
  8.1228 -	$self->{options}{'_default_translated'} .= " <orgdiv>";
  8.1229 -	$self->{options}{'_default_inline'} .= " <orgdiv>";
  8.1230 -
  8.1231 -	# orgname; contains text; Formatted inline
  8.1232 -	$self->{options}{'_default_translated'} .= " <orgname>";
  8.1233 -	$self->{options}{'_default_inline'} .= " <orgname>";
  8.1234 -
  8.1235 -	# otheraddr; contains text; Formatted inline
  8.1236 -	$self->{options}{'_default_translated'} .= " <otheraddr>";
  8.1237 -	$self->{options}{'_default_inline'} .= " <otheraddr>";
  8.1238 -
  8.1239 -	# othercredit; does not contain text; Formatted inline or as a
  8.1240 -	# displayed block depending on context
  8.1241 -	$self->{options}{'_default_untranslated'} .= " <othercredit>";
  8.1242 -	$self->{options}{'_default_inline'} .= " <othercredit>";
  8.1243 -
  8.1244 -	# othername; contains text; Formatted inline
  8.1245 -	$self->{options}{'_default_translated'} .= " <othername>";
  8.1246 -	$self->{options}{'_default_inline'} .= " <othername>";
  8.1247 -
  8.1248 -# PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
  8.1249 -
  8.1250 -	# package; contains text; Formatted inline
  8.1251 -	$self->{options}{'_default_translated'} .= " <package>";
  8.1252 -	$self->{options}{'_default_inline'} .= " <package>";
  8.1253 -
  8.1254 -	# pagenums; contains text; Formatted inline
  8.1255 -	$self->{options}{'_default_translated'} .= " <pagenums>";
  8.1256 -	$self->{options}{'_default_inline'} .= " <pagenums>";
  8.1257 -
  8.1258 -	# para; contains text; Formatted as a displayed block
  8.1259 -	$self->{options}{'_default_translated'} .= " <para>";
  8.1260 -	$self->{options}{'_default_break'} .= " <para>";
  8.1261 -
  8.1262 -	# paramdef; contains text; Formatted inline
  8.1263 -	$self->{options}{'_default_translated'} .= " <paramdef>";
  8.1264 -	$self->{options}{'_default_inline'} .= " <paramdef>";
  8.1265 -
  8.1266 -	# parameter; contains text; Formatted inline
  8.1267 -	$self->{options}{'_default_translated'} .= " <parameter>";
  8.1268 -	$self->{options}{'_default_inline'} .= " <parameter>";
  8.1269 -
  8.1270 -	# part; does not contain text; Formatted as a displayed block.
  8.1271 -	$self->{options}{'_default_untranslated'} .= " <part>";
  8.1272 -	$self->{options}{'_default_break'} .= " <part>";
  8.1273 -
  8.1274 -	# partinfo; does not contain text; v4, not in v5
  8.1275 -	$self->{options}{'_default_untranslated'} .= " <partinfo>";
  8.1276 -	$self->{options}{'_default_placeholder'} .= " <partinfo>";
  8.1277 -
  8.1278 -	# partintro; does not contain text; Formatted as a displayed block.
  8.1279 -	$self->{options}{'_default_untranslated'} .= " <partintro>";
  8.1280 -	$self->{options}{'_default_break'} .= " <partintro>";
  8.1281 -
  8.1282 -	# person; does not contain text; Formatted inline or as a
  8.1283 -	# displayed block depending on context
  8.1284 -	$self->{options}{'_default_untranslated'} .= " <person>";
  8.1285 -	$self->{options}{'_default_inline'} .= " <person>";
  8.1286 -
  8.1287 -	# personblurb; does not contain text; Formatted as a displayed block.
  8.1288 -	$self->{options}{'_default_untranslated'} .= " <personblurb>";
  8.1289 -	$self->{options}{'_default_placeholder'} .= " <personblurb>";
  8.1290 -
  8.1291 -	# personname; contains text; Formatted inline
  8.1292 -	$self->{options}{'_default_translated'} .= " <personname>";
  8.1293 -	$self->{options}{'_default_inline'} .= " <personname>";
  8.1294 -
  8.1295 -	# phone; contains text; Formatted inline
  8.1296 -	$self->{options}{'_default_translated'} .= " <phone>";
  8.1297 -	$self->{options}{'_default_inline'} .= " <phone>";
  8.1298 -
  8.1299 -	# phrase; contains text; Formatted inline
  8.1300 -	$self->{options}{'_default_translated'} .= " <phrase>";
  8.1301 -	$self->{options}{'_default_inline'} .= " <phrase>";
  8.1302 -
  8.1303 -	# pob; contains text; Formatted inline
  8.1304 -	$self->{options}{'_default_translated'} .= " <pob>";
  8.1305 -	$self->{options}{'_default_inline'} .= " <pob>";
  8.1306 -
  8.1307 -	# postcode; contains text; Formatted inline
  8.1308 -	$self->{options}{'_default_translated'} .= " <postcode>";
  8.1309 -	$self->{options}{'_default_inline'} .= " <postcode>";
  8.1310 -
  8.1311 -	# preface; does not contain text; Formatted as a displayed block.
  8.1312 -	$self->{options}{'_default_untranslated'} .= " <preface>";
  8.1313 -	$self->{options}{'_default_break'} .= " <preface>";
  8.1314 -
  8.1315 -	# prefaceinfo; does not contain text; v4, not in v5
  8.1316 -	$self->{options}{'_default_untranslated'} .= " <prefaceinfo>";
  8.1317 -	$self->{options}{'_default_placeholder'} .= " <prefaceinfo>";
  8.1318 -
  8.1319 -	# primary; contains text;
  8.1320 -	$self->{options}{'_default_translated'} .= " <primary>";
  8.1321 -	$self->{options}{'_default_break'} .= " <primary>";
  8.1322 -
  8.1323 -	# primaryie; contains text; Formatted as a displayed block.
  8.1324 -	$self->{options}{'_default_translated'} .= " <primaryie>";
  8.1325 -	$self->{options}{'_default_break'} .= " <primaryie>";
  8.1326 -
  8.1327 -	# printhistory; does not contain text; Formatted as a displayed block.
  8.1328 -	$self->{options}{'_default_untranslated'} .= " <printhistory>";
  8.1329 -	$self->{options}{'_default_break'} .= " <printhistory>";
  8.1330 -
  8.1331 -	# procedure; does not contain text; Formatted as a displayed block.
  8.1332 -	$self->{options}{'_default_untranslated'} .= " <procedure>";
  8.1333 -	$self->{options}{'_default_placeholder'} .= " <procedure>";
  8.1334 -
  8.1335 -	# production; doesnot contain text;
  8.1336 -	# NOTE: it might be better to have the production as verbatim
  8.1337 -	#       Keeping the constrainst inline to have it close to the
  8.1338 -	#       lhs or rhs.
  8.1339 -	$self->{options}{'_default_untranslated'} .= " <production>";
  8.1340 -	$self->{options}{'_default_break'} .= " <production>";
  8.1341 -
  8.1342 -	# productionrecap; does not contain text; like production
  8.1343 -	$self->{options}{'_default_untranslated'} .= " <productionrecap>";
  8.1344 -	$self->{options}{'_default_break'} .= " <productionrecap>";
  8.1345 -
  8.1346 -	# productionset; does not contain text; Formatted as a displayed block.
  8.1347 -	$self->{options}{'_default_untranslated'} .= " <productionset>";
  8.1348 -	$self->{options}{'_default_placeholder'} .= " <productionset>";
  8.1349 -
  8.1350 -	# productname; contains text; Formatted inline
  8.1351 -	$self->{options}{'_default_translated'} .= " <productname>";
  8.1352 -	$self->{options}{'_default_inline'} .= " <productname>";
  8.1353 -
  8.1354 -	# productnumber; contains text; Formatted inline
  8.1355 -	$self->{options}{'_default_translated'} .= " <productnumber>";
  8.1356 -	$self->{options}{'_default_inline'} .= " <productnumber>";
  8.1357 -
  8.1358 -	# programlisting; contains text; Formatted as a displayed block.
  8.1359 -	$self->{options}{'_default_translated'} .= " W<programlisting>";
  8.1360 -	$self->{options}{'_default_placeholder'} .= " <programlisting>";
  8.1361 -
  8.1362 -	# programlistingco; contains text; Formatted as a displayed block.
  8.1363 -	$self->{options}{'_default_untranslated'} .= " <programlistingco>";
  8.1364 -	$self->{options}{'_default_placeholder'} .= " <programlistingco>";
  8.1365 -
  8.1366 -	# prompt; contains text; Formatted inline
  8.1367 -	$self->{options}{'_default_translated'} .= " <prompt>";
  8.1368 -	$self->{options}{'_default_inline'} .= " <prompt>";
  8.1369 -
  8.1370 -	# property; contains text; Formatted inline
  8.1371 -	$self->{options}{'_default_translated'} .= " <property>";
  8.1372 -	$self->{options}{'_default_inline'} .= " <property>";
  8.1373 -
  8.1374 -	# pubdate; contains text; Formatted inline
  8.1375 -	$self->{options}{'_default_translated'} .= " <pubdate>";
  8.1376 -	$self->{options}{'_default_inline'} .= " <pubdate>";
  8.1377 -
  8.1378 -	# publisher; does not contain text; Formatted inline or as a displayed block
  8.1379 -	# NOTE: could be in the break class
  8.1380 -	$self->{options}{'_default_translated'} .= " <publisher>";
  8.1381 -	$self->{options}{'_default_inline'} .= " <publisher>";
  8.1382 -
  8.1383 -	# publishername; contains text; Formatted inline or as a displayed block
  8.1384 -	$self->{options}{'_default_translated'} .= " <publishername>";
  8.1385 -	$self->{options}{'_default_inline'} .= " <publishername>";
  8.1386 -
  8.1387 -# QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
  8.1388 -
  8.1389 -	# qandadiv; does not contain text; Formatted as a displayed block.
  8.1390 -	$self->{options}{'_default_untranslated'} .= " <qandadiv>";
  8.1391 -	$self->{options}{'_default_break'} .= " <qandadiv>";
  8.1392 -
  8.1393 -	# qandaentry; does not contain text; Formatted as a displayed block.
  8.1394 -	$self->{options}{'_default_untranslated'} .= " <qandaentry>";
  8.1395 -	$self->{options}{'_default_break'} .= " <qandaentry>";
  8.1396 -
  8.1397 -	# qandaset; does not contain text; Formatted as a displayed block.
  8.1398 -	$self->{options}{'_default_untranslated'} .= " <qandaset>";
  8.1399 -	$self->{options}{'_default_break'} .= " <qandaset>";
  8.1400 -
  8.1401 -	# question; does not contain text;
  8.1402 -	$self->{options}{'_default_untranslated'} .= " <question>";
  8.1403 -	$self->{options}{'_default_break'} .= " <question>";
  8.1404 -
  8.1405 -	# quote; contains text; Formatted inline
  8.1406 -	$self->{options}{'_default_translated'} .= " <quote>";
  8.1407 -	$self->{options}{'_default_inline'} .= " <quote>";
  8.1408 -
  8.1409 -# RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
  8.1410 -
  8.1411 -	# refclass; contains text; Formatted inline or as a displayed block
  8.1412 -	# NOTE: could be in the inline class
  8.1413 -	$self->{options}{'_default_translated'} .= " <refclass>";
  8.1414 -	$self->{options}{'_default_break'} .= " <refclass>";
  8.1415 -
  8.1416 -	# refdescriptor; contains text; Formatted inline or as a displayed block
  8.1417 -	# NOTE: could be in the inline class
  8.1418 -	$self->{options}{'_default_translated'} .= " <refdescriptor>";
  8.1419 -	$self->{options}{'_default_break'} .= " <refdescriptor>";
  8.1420 -
  8.1421 -	# refentry; does not contain text; Formatted as a displayed block
  8.1422 -	$self->{options}{'_default_untranslated'} .= " <refentry>";
  8.1423 -	$self->{options}{'_default_break'} .= " <refentry>";
  8.1424 -
  8.1425 -	# refentryinfo; does not contain text; v4, not in v5
  8.1426 -	$self->{options}{'_default_untranslated'} .= " <refentryinfo>";
  8.1427 -	$self->{options}{'_default_placeholder'} .= " <refentryinfo>";
  8.1428 -
  8.1429 -	# refentrytitle; contains text; Formatted as a displayed block
  8.1430 -# FIXME: do not seems to be a block
  8.1431 -	$self->{options}{'_default_translated'} .= " <refentrytitle>";
  8.1432 -	$self->{options}{'_default_inline'} .= " <refentrytitle>";
  8.1433 -
  8.1434 -	# reference; does not contain text; Formatted as a displayed block
  8.1435 -	$self->{options}{'_default_untranslated'} .= " <reference>";
  8.1436 -	$self->{options}{'_default_break'} .= " <reference>";
  8.1437 -
  8.1438 -	# referenceinfo; does not contain text; v4, not in v5
  8.1439 -	$self->{options}{'_default_untranslated'} .= " <referenceinfo>";
  8.1440 -	$self->{options}{'_default_placeholder'} .= " <referenceinfo>";
  8.1441 -
  8.1442 -	# refmeta; does not contains text; 
  8.1443 -	# NOTE: could be in the inline class
  8.1444 -	$self->{options}{'_default_untranslated'} .= " <refmeta>";
  8.1445 -	$self->{options}{'_default_break'} .= " <refmeta>";
  8.1446 -
  8.1447 -	# refmiscinfo; contains text; Formatted inline or as a displayed block
  8.1448 -	# NOTE: could be in the inline class
  8.1449 -	$self->{options}{'_default_translated'} .= " <refmiscinfo>";
  8.1450 -	$self->{options}{'_default_break'} .= " <refmiscinfo>";
  8.1451 -
  8.1452 -	# refname; contains text; Formatted inline or as a displayed block
  8.1453 -	# NOTE: could be in the inline class
  8.1454 -	$self->{options}{'_default_translated'} .= " <refname>";
  8.1455 -	$self->{options}{'_default_break'} .= " <refname>";
  8.1456 -
  8.1457 -	# refnamediv; does not contain text; Formatted as a displayed block
  8.1458 -	$self->{options}{'_default_untranslated'} .= " <refnamediv>";
  8.1459 -	$self->{options}{'_default_break'} .= " <refnamediv>";
  8.1460 -
  8.1461 -	# refpurpose; contains text; Formatted inline
  8.1462 -	$self->{options}{'_default_translated'} .= " <refpurpose>";
  8.1463 -	$self->{options}{'_default_inline'} .= " <refpurpose>";
  8.1464 -
  8.1465 -	# refsect1; does not contain text; Formatted as a displayed block
  8.1466 -	$self->{options}{'_default_untranslated'} .= " <refsect1>";
  8.1467 -	$self->{options}{'_default_break'} .= " <refsect1>";
  8.1468 -
  8.1469 -	# refsect1info; does not contain text; v4, not in v5
  8.1470 -	$self->{options}{'_default_untranslated'} .= " <refsect1info>";
  8.1471 -	$self->{options}{'_default_placeholder'} .= " <refsect1info>";
  8.1472 -
  8.1473 -	# refsect2; does not contain text; Formatted as a displayed block
  8.1474 -	$self->{options}{'_default_untranslated'} .= " <refsect2>";
  8.1475 -	$self->{options}{'_default_break'} .= " <refsect2>";
  8.1476 -
  8.1477 -	# refsect2info; does not contain text; v4, not in v5
  8.1478 -	$self->{options}{'_default_untranslated'} .= " <refsect2info>";
  8.1479 -	$self->{options}{'_default_placeholder'} .= " <refsect2info>";
  8.1480 -
  8.1481 -	# refsect3; does not contain text; Formatted as a displayed block
  8.1482 -	$self->{options}{'_default_untranslated'} .= " <refsect3>";
  8.1483 -	$self->{options}{'_default_break'} .= " <refsect3>";
  8.1484 -
  8.1485 -	# refsect3info; does not contain text; v4, not in v5
  8.1486 -	$self->{options}{'_default_untranslated'} .= " <refsect3info>";
  8.1487 -	$self->{options}{'_default_placeholder'} .= " <refsect3info>";
  8.1488 -
  8.1489 -	# refsection; does not contain text; Formatted as a displayed block
  8.1490 -	$self->{options}{'_default_untranslated'} .= " <refsection>";
  8.1491 -	$self->{options}{'_default_break'} .= " <refsection>";
  8.1492 -
  8.1493 -	# refsectioninfo; does not contain text; v4, not in v5
  8.1494 -	$self->{options}{'_default_untranslated'} .= " <refsectioninfo>";
  8.1495 -	$self->{options}{'_default_placeholder'} .= " <refsectioninfo>";
  8.1496 -
  8.1497 -	# refsynopsisdiv; does not contain text; Formatted as a displayed block
  8.1498 -	$self->{options}{'_default_untranslated'} .= " <refsynopsisdiv>";
  8.1499 -	$self->{options}{'_default_break'} .= " <refsynopsisdiv>";
  8.1500 -
  8.1501 -	# refsynopsisdivinfo; does not contain text; v4, not in v5
  8.1502 -	$self->{options}{'_default_untranslated'} .= " <refsynopsisdivinfo>";
  8.1503 -	$self->{options}{'_default_placeholder'} .= " <refsynopsisdivinfo>";
  8.1504 -
  8.1505 -	# releaseinfo; contains text; Formatted inline or as a displayed block
  8.1506 -	# NOTE: could be in the inline class
  8.1507 -	$self->{options}{'_default_translated'} .= " <releaseinfo>";
  8.1508 -	$self->{options}{'_default_break'} .= " <releaseinfo>";
  8.1509 -
  8.1510 -	# remark; contains text; Formatted inline or as a displayed block
  8.1511 -	$self->{options}{'_default_translated'} .= " <remark>";
  8.1512 -	$self->{options}{'_default_inline'} .= " <remark>";
  8.1513 -
  8.1514 -	# replaceable; contains text; Formatted inline
  8.1515 -	$self->{options}{'_default_translated'} .= " <replaceable>";
  8.1516 -	$self->{options}{'_default_inline'} .= " <replaceable>";
  8.1517 -
  8.1518 -	# returnvalue; contains text; Formatted inline
  8.1519 -	$self->{options}{'_default_translated'} .= " <returnvalue>";
  8.1520 -	$self->{options}{'_default_inline'} .= " <returnvalue>";
  8.1521 -
  8.1522 -	# revdescription; contains text; Formatted inline or as a displayed block
  8.1523 -	$self->{options}{'_default_translated'} .= " <revdescription>";
  8.1524 -	$self->{options}{'_default_break'} .= " <revdescription>";
  8.1525 -
  8.1526 -	# revhistory; does not contain text; Formatted as a displayed block
  8.1527 -	$self->{options}{'_default_untranslated'} .= " <revhistory>";
  8.1528 -	$self->{options}{'_default_break'} .= " <revhistory>";
  8.1529 -
  8.1530 -	# revision; does not contain text;
  8.1531 -	$self->{options}{'_default_untranslated'} .= " <revision>";
  8.1532 -	$self->{options}{'_default_break'} .= " <revision>";
  8.1533 -
  8.1534 -	# revnumber; contains text; Formatted inline
  8.1535 -	$self->{options}{'_default_translated'} .= " <revnumber>";
  8.1536 -	$self->{options}{'_default_inline'} .= " <revnumber>";
  8.1537 -
  8.1538 -	# revremark; contains text; Formatted inline or as a displayed block
  8.1539 -	$self->{options}{'_default_translated'} .= " <revremark>";
  8.1540 -	$self->{options}{'_default_break'} .= " <revremark>";
  8.1541 -
  8.1542 -	# rhs; contains text; Formatted as a displayed block.
  8.1543 -	# NOTE: it might be better to have the production as verbatim
  8.1544 -	#       Keeping the constrainst inline to have it close to the
  8.1545 -	#       lhs or rhs.
  8.1546 -	$self->{options}{'_default_translated'} .= " <rhs>";
  8.1547 -	$self->{options}{'_default_break'} .= " <rhs>";
  8.1548 -
  8.1549 -	# row; does not contain text;
  8.1550 -	$self->{options}{'_default_untranslated'} .= " <row>";
  8.1551 -	$self->{options}{'_default_break'} .= " <row>";
  8.1552 -
  8.1553 -# SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
  8.1554 -
  8.1555 -	# sbr; does not contain text; line break
  8.1556 -	$self->{options}{'_default_untranslated'} .= " <sbr>";
  8.1557 -	$self->{options}{'_default_break'} .= " <sbr>";
  8.1558 -
  8.1559 -	# screen; contains text; verbatim
  8.1560 -	$self->{options}{'_default_translated'} .= " W<screen>";
  8.1561 -	$self->{options}{'_default_placeholder'} .= " <screen>";
  8.1562 -
  8.1563 -	# screenco; does not contain text; Formatted as a displayed block.
  8.1564 -	$self->{options}{'_default_untranslated'} .= " <screenco>";
  8.1565 -	$self->{options}{'_default_placeholder'} .= " <screenco>";
  8.1566 -
  8.1567 -	# screeninfo; does not contain text; v4, not in v5
  8.1568 -	$self->{options}{'_default_untranslated'} .= " <screeninfo>";
  8.1569 -	$self->{options}{'_default_placeholder'} .= " <screeninfo>";
  8.1570 -
  8.1571 -	# screenshot; does not contain text; Formatted as a displayed block.
  8.1572 -	$self->{options}{'_default_untranslated'} .= " <screenshot>";
  8.1573 -	$self->{options}{'_default_placeholder'} .= " <screenshot>";
  8.1574 -
  8.1575 -	# secondary; contains text; 
  8.1576 -	$self->{options}{'_default_translated'} .= " <secondary>";
  8.1577 -	$self->{options}{'_default_break'} .= " <secondary>";
  8.1578 -
  8.1579 -	# secondaryie; contains text; Formatted as a displayed block.
  8.1580 -	$self->{options}{'_default_translated'} .= " <secondaryie>";
  8.1581 -	$self->{options}{'_default_break'} .= " <secondaryie>";
  8.1582 -
  8.1583 -	# sect1; does not contain text; Formatted as a displayed block.
  8.1584 -	$self->{options}{'_default_untranslated'} .= " <sect1>";
  8.1585 -	$self->{options}{'_default_break'} .= " <sect1>";
  8.1586 -
  8.1587 -	# sect1info; does not contain text; v4, not in v5
  8.1588 -	$self->{options}{'_default_untranslated'} .= " <sect1info>";
  8.1589 -	$self->{options}{'_default_placeholder'} .= " <sect1info>";
  8.1590 -
  8.1591 -	# sect2; does not contain text; Formatted as a displayed block.
  8.1592 -	$self->{options}{'_default_untranslated'} .= " <sect2>";
  8.1593 -	$self->{options}{'_default_break'} .= " <sect2>";
  8.1594 -
  8.1595 -	# sect2info; does not contain text; v4, not in v5
  8.1596 -	$self->{options}{'_default_untranslated'} .= " <sect2info>";
  8.1597 -	$self->{options}{'_default_placeholder'} .= " <sect2info>";
  8.1598 -
  8.1599 -	# sect3; does not contain text; Formatted as a displayed block.
  8.1600 -	$self->{options}{'_default_untranslated'} .= " <sect3>";
  8.1601 -	$self->{options}{'_default_break'} .= " <sect3>";
  8.1602 -
  8.1603 -	# sect3info; does not contain text; v4, not in v5
  8.1604 -	$self->{options}{'_default_untranslated'} .= " <sect3info>";
  8.1605 -	$self->{options}{'_default_placeholder'} .= " <sect3info>";
  8.1606 -
  8.1607 -	# sect4; does not contain text; Formatted as a displayed block.
  8.1608 -	$self->{options}{'_default_untranslated'} .= " <sect4>";
  8.1609 -	$self->{options}{'_default_break'} .= " <sect4>";
  8.1610 -
  8.1611 -	# sect4info; does not contain text; v4, not in v5
  8.1612 -	$self->{options}{'_default_untranslated'} .= " <sect4info>";
  8.1613 -	$self->{options}{'_default_placeholder'} .= " <sect4info>";
  8.1614 -
  8.1615 -	# sect5; does not contain text; Formatted as a displayed block.
  8.1616 -	$self->{options}{'_default_untranslated'} .= " <sect5>";
  8.1617 -	$self->{options}{'_default_break'} .= " <sect5>";
  8.1618 -
  8.1619 -	# sect5info; does not contain text; v4, not in v5
  8.1620 -	$self->{options}{'_default_untranslated'} .= " <sect5info>";
  8.1621 -	$self->{options}{'_default_placeholder'} .= " <sect5info>";
  8.1622 -
  8.1623 -	# section; does not contain text; Formatted as a displayed block.
  8.1624 -	$self->{options}{'_default_untranslated'} .= " <section>";
  8.1625 -	$self->{options}{'_default_break'} .= " <section>";
  8.1626 -
  8.1627 -	# sectioninfo; does not contain text; v3.1 -> v4, not in v5
  8.1628 -	$self->{options}{'_default_untranslated'} .= " <sectioninfo>";
  8.1629 -	$self->{options}{'_default_placeholder'} .= " <sectioninfo>";
  8.1630 -
  8.1631 -	# see; contains text; 
  8.1632 -	$self->{options}{'_default_translated'} .= " <see>";
  8.1633 -	$self->{options}{'_default_break'} .= " <see>";
  8.1634 -
  8.1635 -	# seealso; contains text; 
  8.1636 -	$self->{options}{'_default_translated'} .= " <seealso>";
  8.1637 -	$self->{options}{'_default_break'} .= " <seealso>";
  8.1638 -
  8.1639 -	# seealsoie; contains text; Formatted as a displayed block.
  8.1640 -	$self->{options}{'_default_translated'} .= " <seealsoie>";
  8.1641 -	$self->{options}{'_default_break'} .= " <seealsoie>";
  8.1642 -
  8.1643 -	# seeie; contains text; Formatted as a displayed block.
  8.1644 -	$self->{options}{'_default_translated'} .= " <seeie>";
  8.1645 -	$self->{options}{'_default_break'} .= " <seeie>";
  8.1646 -
  8.1647 -	# seg; contains text;
  8.1648 -	$self->{options}{'_default_translated'} .= " <seg>";
  8.1649 -	$self->{options}{'_default_break'} .= " <seg>";
  8.1650 -
  8.1651 -	# seglistitem; does not contain text;
  8.1652 -	$self->{options}{'_default_untranslated'} .= " <seglistitem>";
  8.1653 -	$self->{options}{'_default_break'} .= " <seglistitem>";
  8.1654 -
  8.1655 -	# segmentedlist; does not contain text;
  8.1656 -	$self->{options}{'_default_untranslated'} .= " <segmentedlist>";
  8.1657 -	$self->{options}{'_default_break'} .= " <segmentedlist>";
  8.1658 -
  8.1659 -	# segtitle; contains text;
  8.1660 -	$self->{options}{'_default_translated'} .= " <segtitle>";
  8.1661 -	$self->{options}{'_default_break'} .= " <segtitle>";
  8.1662 -
  8.1663 -	# seriesinfo; does not contain text;
  8.1664 -	# Removed in v4.0
  8.1665 -	$self->{options}{'_default_untranslated'} .= " <seriesinfo>";
  8.1666 -	$self->{options}{'_default_placeholder'} .= " <seriesinfo>";
  8.1667 -
  8.1668 -	# seriesvolnums; contains text; Formatted inline
  8.1669 -	# NOTE: could be in the break class
  8.1670 -	$self->{options}{'_default_translated'} .= " <seriesvolnums>";
  8.1671 -	$self->{options}{'_default_inline'} .= " <seriesvolnums>";
  8.1672 -
  8.1673 -	# set; does not contain text; Formatted as a displayed block.
  8.1674 -	$self->{options}{'_default_untranslated'} .= " <set>";
  8.1675 -	$self->{options}{'_default_break'} .= " <set>";
  8.1676 -
  8.1677 -	# setindex; does not contain text; Formatted as a displayed block.
  8.1678 -	$self->{options}{'_default_untranslated'} .= " <setindex>";
  8.1679 -	$self->{options}{'_default_break'} .= " <setindex>";
  8.1680 -
  8.1681 -	# setindexinfo; does not contain text; v4, not in v5
  8.1682 -	$self->{options}{'_default_untranslated'} .= " <setindexinfo>";
  8.1683 -	$self->{options}{'_default_placeholder'} .= " <setindexinfo>";
  8.1684 -
  8.1685 -	# setinfo; does not contain text; v4, not in v5
  8.1686 -	$self->{options}{'_default_untranslated'} .= " <setinfo>";
  8.1687 -	$self->{options}{'_default_placeholder'} .= " <setinfo>";
  8.1688 -
  8.1689 -	# sgmltag; contains text; Formatted inline; v4, not in v5
  8.1690 -	$self->{options}{'_default_translated'} .= " <sgmltag>";
  8.1691 -	$self->{options}{'_default_inline'} .= " <sgmltag>";
  8.1692 -
  8.1693 -	# shortaffil; contains text; Formatted inline or as a
  8.1694 -	# displayed block depending on context
  8.1695 -	$self->{options}{'_default_translated'} .= " <shortaffil>";
  8.1696 -	$self->{options}{'_default_inline'} .= " <shortaffil>";
  8.1697 -
  8.1698 -	# shortcut; does not contain text; Formatted inline
  8.1699 -	$self->{options}{'_default_untranslated'} .= " <shortcut>";
  8.1700 -	$self->{options}{'_default_inline'} .= " <shortcut>";
  8.1701 -
  8.1702 -	# sidebar; does not contain text; Formatted as a displayed block.
  8.1703 -	$self->{options}{'_default_untranslated'} .= " <sidebar>";
  8.1704 -	$self->{options}{'_default_break'} .= " <sidebar>";
  8.1705 -
  8.1706 -	# sidebarinfo; does not contain text; v4, not in v5
  8.1707 -	$self->{options}{'_default_untranslated'} .= " <sidebarinfo>";
  8.1708 -	$self->{options}{'_default_placeholder'} .= " <sidebarinfo>";
  8.1709 -
  8.1710 -	# simpara; contains text; Formatted as a displayed block.
  8.1711 -	$self->{options}{'_default_translated'} .= " <simpara>";
  8.1712 -	$self->{options}{'_default_break'} .= " <simpara>";
  8.1713 -
  8.1714 -	# simplelist; does not contain text;
  8.1715 -	$self->{options}{'_default_untranslated'} .= " <simplelist>";
  8.1716 -	$self->{options}{'_default_inline'} .= " <simplelist>";
  8.1717 -
  8.1718 -	# simplemsgentry; does not contain text; Formatted as a displayed block.
  8.1719 -	$self->{options}{'_default_untranslated'} .= " <simplemsgentry>";
  8.1720 -	$self->{options}{'_default_break'} .= " <simplemsgentry>";
  8.1721 -
  8.1722 -	# simplesect; does not contain text; Formatted as a displayed block.
  8.1723 -	$self->{options}{'_default_untranslated'} .= " <simplesect>";
  8.1724 -	$self->{options}{'_default_break'} .= " <simplesect>";
  8.1725 -
  8.1726 -	# spanspec; does not contain text; Formatted as a displayed block.
  8.1727 -	$self->{options}{'_default_untranslated'} .= " <spanspec>";
  8.1728 -	$self->{options}{'_default_break'} .= " <spanspec>";
  8.1729 -
  8.1730 -	# state; contains text; Formatted inline
  8.1731 -	$self->{options}{'_default_translated'} .= " <state>";
  8.1732 -	$self->{options}{'_default_inline'} .= " <state>";
  8.1733 -
  8.1734 -	# step; does not contain text; Formatted as a displayed block.
  8.1735 -	$self->{options}{'_default_untranslated'} .= " <step>";
  8.1736 -	$self->{options}{'_default_break'} .= " <step>";
  8.1737 -
  8.1738 -	# stepalternatives; does not contain text; Formatted as a displayed block.
  8.1739 -	$self->{options}{'_default_untranslated'} .= " <stepalternatives>";
  8.1740 -	$self->{options}{'_default_break'} .= " <stepalternatives>";
  8.1741 -
  8.1742 -	# street; contains text; Formatted inline
  8.1743 -	$self->{options}{'_default_translated'} .= " <street>";
  8.1744 -	$self->{options}{'_default_inline'} .= " <street>";
  8.1745 -
  8.1746 -	# structfield; contains text; Formatted inline; v4, not in v5
  8.1747 -	$self->{options}{'_default_translated'} .= " <structfield>";
  8.1748 -	$self->{options}{'_default_inline'} .= " <structfield>";
  8.1749 -
  8.1750 -	# structname; contains text; Formatted inline; v4, not in v5
  8.1751 -	$self->{options}{'_default_translated'} .= " <structname>";
  8.1752 -	$self->{options}{'_default_inline'} .= " <structname>";
  8.1753 -
  8.1754 -	# subject; does not contain text; Formatted inline or as a displayed block
  8.1755 -	# NOTE: could be in the inline class
  8.1756 -	$self->{options}{'_default_untranslated'} .= " <subject>";
  8.1757 -	$self->{options}{'_default_break'} .= " <subject>";
  8.1758 -
  8.1759 -	# subjectset; does not contain text; Formatted inline or as a displayed block
  8.1760 -	# NOTE: could be in the inline class
  8.1761 -	$self->{options}{'_default_untranslated'} .= " <subjectset>";
  8.1762 -	$self->{options}{'_default_break'} .= " <subjectset>";
  8.1763 -
  8.1764 -	# subjectterm; contains text; Formatted inline or as a displayed block
  8.1765 -	# NOTE: could be in the inline class
  8.1766 -	$self->{options}{'_default_translated'} .= " <subjectterm>";
  8.1767 -	$self->{options}{'_default_break'} .= " <subjectterm>";
  8.1768 -
  8.1769 -	# subscript; contains text; Formatted inline
  8.1770 -	$self->{options}{'_default_translated'} .= " <subscript>";
  8.1771 -	$self->{options}{'_default_inline'} .= " <subscript>";
  8.1772 -
  8.1773 -	# substeps; does not contain text; Formatted as a displayed block.
  8.1774 -	$self->{options}{'_default_untranslated'} .= " <substeps>";
  8.1775 -	$self->{options}{'_default_break'} .= " <substeps>";
  8.1776 -
  8.1777 -	# subtitle; contains text; Formatted as a displayed block.
  8.1778 -	$self->{options}{'_default_translated'} .= " <subtitle>";
  8.1779 -	$self->{options}{'_default_break'} .= " <subtitle>";
  8.1780 -
  8.1781 -	# superscript; contains text; Formatted inline
  8.1782 -	$self->{options}{'_default_translated'} .= " <superscript>";
  8.1783 -	$self->{options}{'_default_inline'} .= " <superscript>";
  8.1784 -
  8.1785 -	# surname; contains text; Formatted inline
  8.1786 -	$self->{options}{'_default_translated'} .= " <surname>";
  8.1787 -	$self->{options}{'_default_inline'} .= " <surname>";
  8.1788 -
  8.1789 -#svg:svg
  8.1790 -
  8.1791 -	# symbol; contains text; Formatted inline
  8.1792 -	$self->{options}{'_default_translated'} .= " <symbol>";
  8.1793 -	$self->{options}{'_default_inline'} .= " <symbol>";
  8.1794 -
  8.1795 -	# synopfragment; does not contain text; Formatted as a displayed block.
  8.1796 -	$self->{options}{'_default_untranslated'} .= " <synopfragment>";
  8.1797 -	$self->{options}{'_default_placeholder'} .= " <synopfragment>";
  8.1798 -
  8.1799 -	# synopfragmentref; contains text; Formatted inline
  8.1800 -	$self->{options}{'_default_translated'} .= " <synopfragmentref>";
  8.1801 -	$self->{options}{'_default_inline'} .= " <synopfragmentref>";
  8.1802 -
  8.1803 -	# synopsis; contains text; verbatim
  8.1804 -	$self->{options}{'_default_translated'} .= " W<synopsis>";
  8.1805 -	$self->{options}{'_default_placeholder'} .= " <synopsis>";
  8.1806 -
  8.1807 -	# systemitem; contains text; Formatted inline
  8.1808 -	$self->{options}{'_default_translated'} .= " <systemitem>";
  8.1809 -	$self->{options}{'_default_inline'} .= " <systemitem>";
  8.1810 -
  8.1811 -# TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
  8.1812 -
  8.1813 -	# table; does not contain text; Formatted as a displayed block.
  8.1814 -	$self->{options}{'_default_untranslated'} .= " <table>";
  8.1815 -	$self->{options}{'_default_placeholder'} .= " <table>";
  8.1816 -
  8.1817 -	# tag; contains text; Formatted inline
  8.1818 -	$self->{options}{'_default_translated'} .= " <tag>";
  8.1819 -	$self->{options}{'_default_inline'} .= " <tag>";
  8.1820 -
  8.1821 -	# task; does not contain text; Formatted as a displayed block.
  8.1822 -	$self->{options}{'_default_untranslated'} .= " <task>";
  8.1823 -	$self->{options}{'_default_placeholder'} .= " <task>";
  8.1824 -
  8.1825 -	# taskprerequisites; does not contain text; Formatted as a displayed block.
  8.1826 -	$self->{options}{'_default_untranslated'} .= " <taskprerequisites>";
  8.1827 -	$self->{options}{'_default_break'} .= " <taskprerequisites>";
  8.1828 -
  8.1829 -	# taskrelated; does not contain text; Formatted as a displayed block.
  8.1830 -	$self->{options}{'_default_untranslated'} .= " <taskrelated>";
  8.1831 -	$self->{options}{'_default_break'} .= " <taskrelated>";
  8.1832 -
  8.1833 -	# tasksummary; does not contain text; Formatted as a displayed block.
  8.1834 -	$self->{options}{'_default_untranslated'} .= " <tasksummary>";
  8.1835 -	$self->{options}{'_default_break'} .= " <tasksummary>";
  8.1836 -
  8.1837 -	# tbody; does not contain text;
  8.1838 -	$self->{options}{'_default_untranslated'} .= " <tbody>";
  8.1839 -	$self->{options}{'_default_break'} .= " <tbody>";
  8.1840 -
  8.1841 -	# td; contains text;
  8.1842 -	$self->{options}{'_default_translated'} .= " <td>";
  8.1843 -	$self->{options}{'_default_break'} .= " <td>";
  8.1844 -
  8.1845 -	# term; contains text; Formatted as a displayed block.
  8.1846 -	$self->{options}{'_default_translated'} .= " <term>";
  8.1847 -	$self->{options}{'_default_break'} .= " <term>";
  8.1848 -
  8.1849 -	# termdef; contains text; Formatted inline
  8.1850 -	$self->{options}{'_default_translated'} .= " <termdef>";
  8.1851 -	$self->{options}{'_default_inline'} .= " <termdef>";
  8.1852 -
  8.1853 -	# tertiary; contains text; Suppressed
  8.1854 -	$self->{options}{'_default_translated'} .= " <tertiary>";
  8.1855 -	$self->{options}{'_default_placeholder'} .= " <tertiary>";
  8.1856 -
  8.1857 -	# tertiaryie; contains text; Formatted as a displayed block.
  8.1858 -	$self->{options}{'_default_translated'} .= " <tertiaryie>";
  8.1859 -	$self->{options}{'_default_break'} .= " <tertiaryie>";
  8.1860 -
  8.1861 -	# textdata; does not contain text; Formatted inline or as a displayed block
  8.1862 -	# NOTE: could be in the inline class
  8.1863 -	$self->{options}{'_default_untranslated'} .= " <textdata>";
  8.1864 -	$self->{options}{'_default_break'} .= " <textdata>";
  8.1865 -	$self->{options}{'_default_attributes'}.=' <textdata>fileref';
  8.1866 -
  8.1867 -	# textobject; does not contain text; Formatted inline or as a displayed block
  8.1868 -	# NOTE: could be in the inline class
  8.1869 -	$self->{options}{'_default_untranslated'} .= " <textobject>";
  8.1870 -	$self->{options}{'_default_break'} .= " <textobject>";
  8.1871 -
  8.1872 -	# tfoot; does not contain text;
  8.1873 -	$self->{options}{'_default_untranslated'} .= " <tfoot>";
  8.1874 -	$self->{options}{'_default_break'} .= " <tfoot>";
  8.1875 -
  8.1876 -	# tgroup; does not contain text;
  8.1877 -	$self->{options}{'_default_untranslated'} .= " <tgroup>";
  8.1878 -	$self->{options}{'_default_break'} .= " <tgroup>";
  8.1879 -
  8.1880 -	# th; contains text;
  8.1881 -	$self->{options}{'_default_translated'} .= " <th>";
  8.1882 -	$self->{options}{'_default_break'} .= " <th>";
  8.1883 -
  8.1884 -	# thead; does not contain text;
  8.1885 -	$self->{options}{'_default_untranslated'} .= " <thead>";
  8.1886 -	$self->{options}{'_default_break'} .= " <thead>";
  8.1887 -
  8.1888 -	# tip; does not contain text; Formatted as a displayed block.
  8.1889 -	$self->{options}{'_default_untranslated'} .= " <tip>";
  8.1890 -	$self->{options}{'_default_break'} .= " <tip>";
  8.1891 -
  8.1892 -	# title; contains text; Formatted as a displayed block.
  8.1893 -	$self->{options}{'_default_translated'} .= " <title>";
  8.1894 -	$self->{options}{'_default_break'} .= " <title>";
  8.1895 -
  8.1896 -	# titleabbrev; contains text; Formatted inline or as a displayed block
  8.1897 -	# NOTE: could be in the inline class
  8.1898 -	$self->{options}{'_default_translated'} .= " <titleabbrev>";
  8.1899 -	$self->{options}{'_default_break'} .= " <titleabbrev>";
  8.1900 -
  8.1901 -	# toc; does not contain text; Formatted as a displayed block.
  8.1902 -	$self->{options}{'_default_untranslated'} .= " <toc>";
  8.1903 -	$self->{options}{'_default_break'} .= " <toc>";
  8.1904 -
  8.1905 -	# tocback; contains text; Formatted as a displayed block.
  8.1906 -	$self->{options}{'_default_translated'} .= " <tocback>";
  8.1907 -	$self->{options}{'_default_break'} .= " <tocback>";
  8.1908 -
  8.1909 -	# tocchap; does not contain text; Formatted as a displayed block.
  8.1910 -	$self->{options}{'_default_translated'} .= " <tocchap>";
  8.1911 -	$self->{options}{'_default_break'} .= " <tocchap>";
  8.1912 -
  8.1913 -	# tocdiv; does not contain text; Formatted as a displayed block.
  8.1914 -	$self->{options}{'_default_untranslated'} .= " <tocdiv>";
  8.1915 -	$self->{options}{'_default_break'} .= " <tocdiv>";
  8.1916 -
  8.1917 -	# tocentry; contains text; Formatted as a displayed block.
  8.1918 -	$self->{options}{'_default_translated'} .= " <tocentry>";
  8.1919 -	$self->{options}{'_default_break'} .= " <tocentry>";
  8.1920 -
  8.1921 -	# tocfront; does not contain text; Formatted as a displayed block.
  8.1922 -	$self->{options}{'_default_translated'} .= " <tocfront>";
  8.1923 -	$self->{options}{'_default_break'} .= " <tocfront>";
  8.1924 -
  8.1925 -	# toclevel1; does not contain text; Formatted as a displayed block.
  8.1926 -	$self->{options}{'_default_untranslated'} .= " <toclevel1>";
  8.1927 -	$self->{options}{'_default_break'} .= " <toclevel1>";
  8.1928 -
  8.1929 -	# toclevel2; does not contain text; Formatted as a displayed block.
  8.1930 -	$self->{options}{'_default_untranslated'} .= " <toclevel2>";
  8.1931 -	$self->{options}{'_default_break'} .= " <toclevel2>";
  8.1932 -
  8.1933 -	# toclevel3; does not contain text; Formatted as a displayed block.
  8.1934 -	$self->{options}{'_default_untranslated'} .= " <toclevel3>";
  8.1935 -	$self->{options}{'_default_break'} .= " <toclevel3>";
  8.1936 -
  8.1937 -	# toclevel4; does not contain text; Formatted as a displayed block.
  8.1938 -	$self->{options}{'_default_untranslated'} .= " <toclevel4>";
  8.1939 -	$self->{options}{'_default_break'} .= " <toclevel4>";
  8.1940 -
  8.1941 -	# toclevel5; does not contain text; Formatted as a displayed block.
  8.1942 -	$self->{options}{'_default_untranslated'} .= " <toclevel5>";
  8.1943 -	$self->{options}{'_default_break'} .= " <toclevel5>";
  8.1944 -
  8.1945 -	# tocpart; does not contain text; Formatted as a displayed block.
  8.1946 -	$self->{options}{'_default_untranslated'} .= " <tocpart>";
  8.1947 -	$self->{options}{'_default_break'} .= " <tocpart>";
  8.1948 -
  8.1949 -	# token; contains text; Formatted inline
  8.1950 -	$self->{options}{'_default_translated'} .= " <token>";
  8.1951 -	$self->{options}{'_default_inline'} .= " <token>";
  8.1952 -
  8.1953 -	# tr; does not contain text;
  8.1954 -	$self->{options}{'_default_untranslated'} .= " <tr>";
  8.1955 -	$self->{options}{'_default_break'} .= " <tr>";
  8.1956 -
  8.1957 -	# trademark; contains text; Formatted inline
  8.1958 -	$self->{options}{'_default_translated'} .= " <trademark>";
  8.1959 -	$self->{options}{'_default_inline'} .= " <trademark>";
  8.1960 -
  8.1961 -	# type; contains text; Formatted inline
  8.1962 -	$self->{options}{'_default_translated'} .= " <type>";
  8.1963 -	$self->{options}{'_default_inline'} .= " <type>";
  8.1964 -
  8.1965 -# UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
  8.1966 -
  8.1967 -	# ulink; contains text; Formatted inline; v4, not in v5
  8.1968 -	$self->{options}{'_default_translated'} .= " <ulink>";
  8.1969 -	$self->{options}{'_default_inline'} .= " <ulink>";
  8.1970 -
  8.1971 -	# uri; contains text; Formatted inline
  8.1972 -	$self->{options}{'_default_translated'} .= " <uri>";
  8.1973 -	$self->{options}{'_default_inline'} .= " <uri>";
  8.1974 -
  8.1975 -	# userinput; contains text; Formatted inline
  8.1976 -	$self->{options}{'_default_translated'} .= " <userinput>";
  8.1977 -	$self->{options}{'_default_inline'} .= " <userinput>";
  8.1978 -
  8.1979 -# VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
  8.1980 -
  8.1981 -	# varargs; empty element;
  8.1982 -	$self->{options}{'_default_untranslated'} .= " <varargs>";
  8.1983 -	$self->{options}{'_default_inline'} .= " <varargs>";
  8.1984 -
  8.1985 -	# variablelist; does not contain text; Formatted as a displayed block.
  8.1986 -	$self->{options}{'_default_untranslated'} .= " <variablelist>";
  8.1987 -	$self->{options}{'_default_placeholder'} .= " <variablelist>";
  8.1988 -
  8.1989 -	# varlistentry; does not contain text; Formatted as a displayed block.
  8.1990 -	$self->{options}{'_default_untranslated'} .= " <varlistentry>";
  8.1991 -	$self->{options}{'_default_break'} .= " <varlistentry>";
  8.1992 -
  8.1993 -	# varname; contains text; Formatted inline
  8.1994 -	$self->{options}{'_default_translated'} .= " <varname>";
  8.1995 -	$self->{options}{'_default_inline'} .= " <varname>";
  8.1996 -
  8.1997 -	# videodata; contains text; Formatted inline or as a displayed block
  8.1998 -	$self->{options}{'_default_untranslated'} .= " <videodata>";
  8.1999 -	$self->{options}{'_default_break'} .= " <videodata>";
  8.2000 -	$self->{options}{'_default_attributes'}.=' <videodata>fileref';
  8.2001 -
  8.2002 -	# videoobject; contains text; Formatted inline or as a displayed block
  8.2003 -	$self->{options}{'_default_untranslated'} .= " <videoobject>";
  8.2004 -	$self->{options}{'_default_break'} .= " <videoobject>";
  8.2005 -
  8.2006 -	# void; empty element;
  8.2007 -	$self->{options}{'_default_untranslated'} .= " <void>";
  8.2008 -	$self->{options}{'_default_inline'} .= " <void>";
  8.2009 -
  8.2010 -	# volumenum; contains text; Formatted inline
  8.2011 -	$self->{options}{'_default_translated'} .= " <volumenum>";
  8.2012 -	$self->{options}{'_default_inline'} .= " <volumenum>";
  8.2013 -
  8.2014 -# WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
  8.2015 -
  8.2016 -	# warning; does not contain text; Formatted as a displayed block.
  8.2017 -	$self->{options}{'_default_untranslated'} .= " <warning>";
  8.2018 -	$self->{options}{'_default_break'} .= " <warning>";
  8.2019 -
  8.2020 -	# wordasword; contains text; Formatted inline
  8.2021 -	$self->{options}{'_default_translated'} .= " <wordasword>";
  8.2022 -	$self->{options}{'_default_inline'} .= " <wordasword>";
  8.2023 -
  8.2024 -# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  8.2025 -
  8.2026 -	# xref; empty element;
  8.2027 -	$self->{options}{'_default_untranslated'} .= " <xref>";
  8.2028 -	$self->{options}{'_default_inline'} .= " <xref>";
  8.2029 -
  8.2030 -# YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
  8.2031 -
  8.2032 -	# year; contains text; Formatted inline
  8.2033 -	$self->{options}{'_default_translated'} .= " <year>";
  8.2034 -	$self->{options}{'_default_inline'} .= " <year>";
  8.2035 -
  8.2036 -# ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
  8.2037 -
  8.2038 -	$self->{options}{'_default_attributes'}.='
  8.2039 -		lang
  8.2040 -		xml:lang';
  8.2041 -
  8.2042 -	$self->treat_options;
  8.2043 -}
     9.1 --- a/tools/po4a/lib/Locale/Po4a/Po.pm	Mon Mar 30 17:50:48 2009 +0800
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,1580 +0,0 @@
     9.4 -# Locale::Po4a::Po -- manipulation of po files
     9.5 -# $Id: Po.pm,v 1.95 2009-02-28 22:18:39 nekral-guest Exp $
     9.6 -#
     9.7 -# This program is free software; you may redistribute it and/or modify it
     9.8 -# under the terms of GPL (see COPYING).
     9.9 -
    9.10 -############################################################################
    9.11 -# Modules and declarations
    9.12 -############################################################################
    9.13 -
    9.14 -=head1 NAME
    9.15 -
    9.16 -Locale::Po4a::Po - po file manipulation module
    9.17 -
    9.18 -=head1 SYNOPSIS
    9.19 -
    9.20 -    use Locale::Po4a::Po;
    9.21 -    my $pofile=Locale::Po4a::Po->new();
    9.22 -
    9.23 -    # Read po file
    9.24 -    $pofile->read('file.po');
    9.25 -
    9.26 -    # Add an entry
    9.27 -    $pofile->push('msgid' => 'Hello', 'msgstr' => 'bonjour',
    9.28 -                  'flags' => "wrap", 'reference'=>'file.c:46');
    9.29 -
    9.30 -    # Extract a translation
    9.31 -    $pofile->gettext("Hello"); # returns 'bonjour'
    9.32 -
    9.33 -    # Write back to a file
    9.34 -    $pofile->write('otherfile.po');
    9.35 -
    9.36 -=head1 DESCRIPTION
    9.37 -
    9.38 -Locale::Po4a::Po is a module that allows you to manipulate message
    9.39 -catalogs. You can load and write from/to a file (which extension is often
    9.40 -I<po>), you can build new entries on the fly or request for the translation
    9.41 -of a string.
    9.42 -
    9.43 -For a more complete description of message catalogs in the po format and
    9.44 -their use, please refer to the documentation of the gettext program.
    9.45 -
    9.46 -This module is part of the PO4A project, which objective is to use po files
    9.47 -(designed at origin to ease the translation of program messages) to
    9.48 -translate everything, including documentation (man page, info manual),
    9.49 -package description, debconf templates, and everything which may benefit
    9.50 -from this.
    9.51 -
    9.52 -=head1 OPTIONS ACCEPTED BY THIS MODULE
    9.53 -
    9.54 -=over 4
    9.55 -
    9.56 -=item porefs
    9.57 -
    9.58 -This specifies the reference format. It can be one of 'none' to not produce
    9.59 -any reference, 'noline' to not specify the line number, and 'full' to
    9.60 -include complete references.
    9.61 -
    9.62 -=back
    9.63 -
    9.64 -=cut
    9.65 -
    9.66 -use IO::File;
    9.67 -
    9.68 -
    9.69 -require Exporter;
    9.70 -
    9.71 -package Locale::Po4a::Po;
    9.72 -use DynaLoader;
    9.73 -
    9.74 -use Locale::Po4a::Common qw(wrap_msg wrap_mod wrap_ref_mod dgettext);
    9.75 -
    9.76 -use subs qw(makespace);
    9.77 -use vars qw(@ISA @EXPORT_OK);
    9.78 -@ISA = qw(Exporter DynaLoader);
    9.79 -@EXPORT = qw(%debug);
    9.80 -@EXPORT_OK = qw(&move_po_if_needed);
    9.81 -
    9.82 -use Locale::Po4a::TransTractor;
    9.83 -# Try to use a C extension if present.
    9.84 -eval("bootstrap Locale::Po4a::Po $Locale::Po4a::TransTractor::VERSION");
    9.85 -
    9.86 -use 5.006;
    9.87 -use strict;
    9.88 -use warnings;
    9.89 -
    9.90 -use Carp qw(croak);
    9.91 -use File::Path; # mkdir before write
    9.92 -use File::Copy; # move
    9.93 -use POSIX qw(strftime floor);
    9.94 -use Time::Local;
    9.95 -
    9.96 -use Encode;
    9.97 -
    9.98 -my @known_flags=qw(wrap no-wrap c-format fuzzy);
    9.99 -
   9.100 -our %debug=('canonize'  => 0,
   9.101 -            'quote'     => 0,
   9.102 -            'escape'    => 0,
   9.103 -            'encoding'  => 0,
   9.104 -            'filter'    => 0);
   9.105 -
   9.106 -=head1 Functions about whole message catalogs
   9.107 -
   9.108 -=over 4
   9.109 -
   9.110 -=item new()
   9.111 -
   9.112 -Creates a new message catalog. If an argument is provided, it's the name of
   9.113 -a po file we should load.
   9.114 -
   9.115 -=cut
   9.116 -
   9.117 -sub new {
   9.118 -    my ($this, $options) = (shift, shift);
   9.119 -    my $class = ref($this) || $this;
   9.120 -    my $self = {};
   9.121 -    bless $self, $class;
   9.122 -    $self->initialize($options);
   9.123 -
   9.124 -    my $filename = shift;
   9.125 -    $self->read($filename) if defined($filename) && length($filename);
   9.126 -    return $self;
   9.127 -}
   9.128 -
   9.129 -# Return the numerical timezone (e.g. +0200)
   9.130 -# Neither the %z nor the %s formats of strftime are portable:
   9.131 -# '%s' is not supported on Solaris and '%z' indicates
   9.132 -# "2006-10-25 19:36E. Europe Standard Time" on MS Windows.
   9.133 -sub timezone {
   9.134 -    my @g = gmtime();
   9.135 -    my @l = localtime();
   9.136 -
   9.137 -    my $diff;
   9.138 -    $diff  = floor(timelocal(@l)/60 +0.5);
   9.139 -    $diff -= floor(timelocal(@g)/60 +0.5);
   9.140 -
   9.141 -    my $h = floor($diff / 60) + $l[8]; # $l[8] indicates if we are currently
   9.142 -                                       # in a daylight saving time zone
   9.143 -    my $m = $diff%60;
   9.144 -
   9.145 -    return sprintf "%+03d%02d\n", $h, $m;
   9.146 -}
   9.147 -
   9.148 -sub initialize {
   9.149 -    my ($self, $options) = (shift, shift);
   9.150 -    my $date = strftime("%Y-%m-%d %H:%M", localtime).timezone();
   9.151 -    chomp $date;
   9.152 -#    $options = ref($options) || $options;
   9.153 -
   9.154 -    $self->{options}{'porefs'}= 'full';
   9.155 -    $self->{options}{'msgid-bugs-address'}= undef;
   9.156 -    $self->{options}{'copyright-holder'}= "Free Software Foundation, Inc.";
   9.157 -    $self->{options}{'package-name'}= "PACKAGE";
   9.158 -    $self->{options}{'package-version'}= "VERSION";
   9.159 -    foreach my $opt (keys %$options) {
   9.160 -        if ($options->{$opt}) {
   9.161 -            die wrap_mod("po4a::po",
   9.162 -                         dgettext ("po4a", "Unknown option: %s"), $opt)
   9.163 -                unless exists $self->{options}{$opt};
   9.164 -            $self->{options}{$opt} = $options->{$opt};
   9.165 -        }
   9.166 -    }
   9.167 -    $self->{options}{'porefs'} =~ /^(full|noline|none)$/ ||
   9.168 -        die wrap_mod("po4a::po",
   9.169 -                     dgettext ("po4a",
   9.170 -                               "Invalid value for option 'porefs' ('%s' is ".
   9.171 -                               "not one of 'full', 'noline' or 'none')"),
   9.172 -                     $self->{options}{'porefs'});
   9.173 -
   9.174 -    $self->{po}=();
   9.175 -    $self->{count}=0;  # number of msgids in the PO
   9.176 -    # count_doc: number of strings in the document
   9.177 -    # (duplicate strings counted multiple times)
   9.178 -    $self->{count_doc}=0;
   9.179 -    $self->{header_comment}=
   9.180 -                     " SOME DESCRIPTIVE TITLE\n"
   9.181 -                    ." Copyright (C) YEAR ".
   9.182 -                     $self->{options}{'copyright-holder'}."\n"
   9.183 -                    ." This file is distributed under the same license ".
   9.184 -                     "as the ".$self->{options}{'package-name'}." package.\n"
   9.185 -                    ." FIRST AUTHOR <EMAIL\@ADDRESS>, YEAR.\n"
   9.186 -                    ."\n"
   9.187 -                    .", fuzzy";
   9.188 -#    $self->header_tag="fuzzy";
   9.189 -    $self->{header}=escape_text("Project-Id-Version: ".
   9.190 -                                $self->{options}{'package-name'}." ".
   9.191 -                                $self->{options}{'package-version'}."\n".
   9.192 -                        ((defined $self->{options}{'msgid-bugs-address'})?
   9.193 -        "Report-Msgid-Bugs-To: ".$self->{options}{'msgid-bugs-address'}."\n":
   9.194 -                                "").
   9.195 -                                "POT-Creation-Date: $date\n".
   9.196 -                                "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n".
   9.197 -                                "Last-Translator: FULL NAME <EMAIL\@ADDRESS>\n".
   9.198 -                                "Language-Team: LANGUAGE <LL\@li.org>\n".
   9.199 -                                "MIME-Version: 1.0\n".
   9.200 -                                "Content-Type: text/plain; charset=CHARSET\n".
   9.201 -                                "Content-Transfer-Encoding: ENCODING");
   9.202 -
   9.203 -    $self->{encoder}=find_encoding("ascii");
   9.204 -
   9.205 -    # To make stats about gettext hits
   9.206 -    $self->stats_clear();
   9.207 -}
   9.208 -
   9.209 -=item read($)
   9.210 -
   9.211 -Reads a po file (which name is given as argument).  Previously existing
   9.212 -entries in self are not removed, the new ones are added to the end of the
   9.213 -catalog.
   9.214 -
   9.215 -=cut
   9.216 -
   9.217 -sub read {
   9.218 -    my $self=shift;
   9.219 -    my $filename=shift
   9.220 -        or croak wrap_mod("po4a::po",
   9.221 -                          dgettext("po4a",
   9.222 -                                   "Please provide a non-null filename"));
   9.223 -
   9.224 -    my $fh;
   9.225 -    if ($filename eq '-') {
   9.226 -        $fh=*STDIN;
   9.227 -    } else {
   9.228 -        open $fh,"<$filename"
   9.229 -            or croak wrap_mod("po4a::po",
   9.230 -                              dgettext("po4a", "Can't read from %s: %s"),
   9.231 -                              $filename, $!);
   9.232 -    }
   9.233 -
   9.234 -    ## Read paragraphs line-by-line
   9.235 -    my $pofile="";
   9.236 -    my $textline;
   9.237 -    while (defined ($textline = <$fh>)) {
   9.238 -        $pofile .= $textline;
   9.239 -    }
   9.240 -#    close INPUT
   9.241 -#        or croak (sprintf(dgettext("po4a",
   9.242 -#                                   "Can't close %s after reading: %s"),
   9.243 -#                          $filename,$!)."\n");
   9.244 -
   9.245 -    my $linenum=0;
   9.246 -
   9.247 -    foreach my $msg (split (/\n\n/,$pofile)) {
   9.248 -        my ($msgid,$msgstr,$comment,$automatic,$reference,$flags,$buffer);
   9.249 -        my ($msgid_plural, $msgstr_plural);
   9.250 -        foreach my $line (split (/\n/,$msg)) {
   9.251 -            $linenum++;
   9.252 -            if ($line =~ /^#\. ?(.*)$/) {  # Automatic comment
   9.253 -                $automatic .= (defined($automatic) ? "\n" : "").$1;
   9.254 -
   9.255 -            } elsif ($line =~ /^#: ?(.*)$/) { # reference
   9.256 -                $reference .= (defined($reference) ? "\n" : "").$1;
   9.257 -
   9.258 -            } elsif ($line =~ /^#, ?(.*)$/) { # flags
   9.259 -                $flags .= (defined($flags) ? "\n" : "").$1;
   9.260 -
   9.261 -            } elsif ($line =~ /^#(.*)$/) {  # Translator comments
   9.262 -                $comment .= (defined($comment) ? "\n" : "").($1||"");
   9.263 -
   9.264 -            } elsif ($line =~ /^msgid (".*")$/) { # begin of msgid
   9.265 -                $buffer = $1;
   9.266 -
   9.267 -            } elsif ($line =~ /^msgid_plural (".*")$/) {
   9.268 -                # begin of msgid_plural, end of msgid
   9.269 -
   9.270 -                $msgid = $buffer;
   9.271 -                $buffer = $1;
   9.272 -
   9.273 -            } elsif ($line =~ /^msgstr (".*")$/) {
   9.274 -                # begin of msgstr, end of msgid
   9.275 -
   9.276 -                $msgid = $buffer;
   9.277 -                $buffer = "$1";
   9.278 -
   9.279 -            } elsif ($line =~ /^msgstr\[([0-9]+)\] (".*")$/) {
   9.280 -                # begin of msgstr[x], end of msgid_plural or msgstr[x-1]
   9.281 -
   9.282 -                # Note: po4a cannot uses plural forms
   9.283 -                # (no integer to use the plural form)
   9.284 -                #   * drop the msgstr[x] where x >= 2
   9.285 -                #   * use msgstr[0] as the translation of msgid
   9.286 -                #   * use msgstr[1] as the translation of msgid_plural
   9.287 -
   9.288 -                if ($1 eq "0") {
   9.289 -                    $msgid_plural = $buffer;
   9.290 -                    $buffer = "$2";
   9.291 -                } elsif ($1 eq "1") {
   9.292 -                    $msgstr = $buffer;
   9.293 -                    $buffer = "$2";
   9.294 -                } elsif ($1 eq "2") {
   9.295 -                    $msgstr_plural = $buffer;
   9.296 -                    warn wrap_ref_mod("$filename:$linenum",
   9.297 -                                      "po4a::po",
   9.298 -                                      dgettext("po4a", "Messages with more than 2 plural forms are not supported."));
   9.299 -                }
   9.300 -            } elsif ($line =~ /^(".*")$/) {
   9.301 -                # continuation of a line
   9.302 -                $buffer .= "\n$1";
   9.303 -
   9.304 -            } else {
   9.305 -                warn wrap_ref_mod("$filename:$linenum",
   9.306 -                                  "po4a::po",
   9.307 -                                  dgettext("po4a", "Strange line: -->%s<--"),
   9.308 -                                  $line);
   9.309 -            }
   9.310 -        }
   9.311 -        $linenum++;
   9.312 -        if (defined $msgid_plural) {
   9.313 -            $msgstr_plural=$buffer;
   9.314 -
   9.315 -            $msgid = unquote_text($msgid) if (defined($msgid));
   9.316 -            $msgstr = unquote_text($msgstr) if (defined($msgstr));
   9.317 -
   9.318 -            $self->push_raw ('msgid'     => $msgid,
   9.319 -                             'msgstr'    => $msgstr,
   9.320 -                             'reference' => $reference,
   9.321 -                             'flags'     => $flags,
   9.322 -                             'comment'   => $comment,
   9.323 -                             'automatic' => $automatic,
   9.324 -                             'plural'    => 0);
   9.325 -
   9.326 -            $msgid_plural = unquote_text($msgid_plural)
   9.327 -                if (defined($msgid_plural));
   9.328 -            $msgstr_plural = unquote_text($msgstr_plural)
   9.329 -                if (defined($msgstr_plural));
   9.330 -
   9.331 -            $self->push_raw ('msgid'     => $msgid_plural,
   9.332 -                             'msgstr'    => $msgstr_plural,
   9.333 -                             'reference' => $reference,
   9.334 -                             'flags'     => $flags,
   9.335 -                             'comment'   => $comment,
   9.336 -                             'automatic' => $automatic,
   9.337 -                             'plural'    => 1);
   9.338 -        } else {
   9.339 -            $msgstr=$buffer;
   9.340 -
   9.341 -            $msgid = unquote_text($msgid) if (defined($msgid));
   9.342 -            $msgstr = unquote_text($msgstr) if (defined($msgstr));
   9.343 -
   9.344 -            $self->push_raw ('msgid'     => $msgid,
   9.345 -                             'msgstr'    => $msgstr,
   9.346 -                             'reference' => $reference,
   9.347 -                             'flags'     => $flags,
   9.348 -                             'comment'   => $comment,
   9.349 -                             'automatic' => $automatic);
   9.350 -        }
   9.351 -    }
   9.352 -}
   9.353 -
   9.354 -=item write($)
   9.355 -
   9.356 -Writes the current catalog to the given file.
   9.357 -
   9.358 -=cut
   9.359 -
   9.360 -sub write{
   9.361 -    my $self=shift;
   9.362 -    my $filename=shift
   9.363 -        or croak dgettext("po4a","Can't write to a file without filename")."\n";
   9.364 -
   9.365 -    my $fh;
   9.366 -    if ($filename eq '-') {
   9.367 -        $fh=\*STDOUT;
   9.368 -    } else {
   9.369 -        # make sure the directory in which we should write the localized
   9.370 -        # file exists
   9.371 -        my $dir = $filename;
   9.372 -        if ($dir =~ m|/|) {
   9.373 -            $dir =~ s|/[^/]*$||;
   9.374 -
   9.375 -            File::Path::mkpath($dir, 0, 0755) # Croaks on error
   9.376 -                if (length ($dir) && ! -e $dir);
   9.377 -        }
   9.378 -        open $fh,">$filename"
   9.379 -            or croak wrap_mod("po4a::po",
   9.380 -                              dgettext("po4a", "Can't write to %s: %s"),
   9.381 -                              $filename, $!);
   9.382 -    }
   9.383 -
   9.384 -    print $fh "".format_comment($self->{header_comment},"")
   9.385 -        if defined($self->{header_comment}) && length($self->{header_comment});
   9.386 -
   9.387 -    print $fh "msgid \"\"\n";
   9.388 -    print $fh "msgstr ".quote_text($self->{header})."\n\n";
   9.389 -
   9.390 -
   9.391 -    my $buf_msgstr_plural; # USed to keep the first msgstr of plural forms
   9.392 -    my $first=1;
   9.393 -    foreach my $msgid ( sort { ($self->{po}{"$a"}{'pos'}) <=>
   9.394 -                               ($self->{po}{"$b"}{'pos'})
   9.395 -                             }  keys %{$self->{po}}) {
   9.396 -        my $output="";
   9.397 -
   9.398 -        if ($first) {
   9.399 -            $first=0;
   9.400 -        } else {
   9.401 -            $output .= "\n";
   9.402 -        }
   9.403 -
   9.404 -        $output .= format_comment($self->{po}{$msgid}{'comment'},"")
   9.405 -            if    defined($self->{po}{$msgid}{'comment'})
   9.406 -               && length ($self->{po}{$msgid}{'comment'});
   9.407 -        if (   defined($self->{po}{$msgid}{'automatic'})
   9.408 -            && length ($self->{po}{$msgid}{'automatic'})) {
   9.409 -            foreach my $comment (split(/\\n/,$self->{po}{$msgid}{'automatic'}))
   9.410 -            {
   9.411 -                $output .= format_comment($comment, ". ")
   9.412 -            }
   9.413 -        }
   9.414 -        $output .= format_comment($self->{po}{$msgid}{'type'},". type: ")
   9.415 -            if    defined($self->{po}{$msgid}{'type'})
   9.416 -               && length ($self->{po}{$msgid}{'type'});
   9.417 -        $output .= format_comment($self->{po}{$msgid}{'reference'},": ")
   9.418 -            if    defined($self->{po}{$msgid}{'reference'})
   9.419 -               && length ($self->{po}{$msgid}{'reference'});
   9.420 -        $output .= "#, ". join(", ", sort split(/\s+/,$self->{po}{$msgid}{'flags'}))."\n"
   9.421 -            if    defined($self->{po}{$msgid}{'flags'})
   9.422 -               && length ($self->{po}{$msgid}{'flags'});
   9.423 -
   9.424 -        if (exists $self->{po}{$msgid}{'plural'}) {
   9.425 -            if ($self->{po}{$msgid}{'plural'} == 0) {
   9.426 -                if ($self->get_charset =~ /^utf-8$/i) {
   9.427 -                    my $msgstr = Encode::decode_utf8($self->{po}{$msgid}{'msgstr'});
   9.428 -                    $msgid = Encode::decode_utf8($msgid);
   9.429 -                    $output .= Encode::encode_utf8("msgid ".quote_text($msgid)."\n");
   9.430 -                    $buf_msgstr_plural = Encode::encode_utf8("msgstr[0] ".quote_text($msgstr)."\n");
   9.431 -                } else {
   9.432 -                    $output = "msgid ".quote_text($msgid)."\n";
   9.433 -                    $buf_msgstr_plural = "msgstr[0] ".quote_text($self->{po}{$msgid}{'msgstr'})."\n";
   9.434 -                }
   9.435 -            } elsif ($self->{po}{$msgid}{'plural'} == 1) {
   9.436 -# TODO: there may be only one plural form
   9.437 -                if ($self->get_charset =~ /^utf-8$/i) {
   9.438 -                    my $msgstr = Encode::decode_utf8($self->{po}{$msgid}{'msgstr'});
   9.439 -                    $msgid = Encode::decode_utf8($msgid);
   9.440 -                    $output = Encode::encode_utf8("msgid_plural ".quote_text($msgid)."\n");
   9.441 -                    $output .= $buf_msgstr_plural;
   9.442 -                    $output .= Encode::encode_utf8("msgstr[1] ".quote_text($msgstr)."\n");
   9.443 -                    $buf_msgstr_plural = "";
   9.444 -                } else {
   9.445 -                    $output = "msgid_plural ".quote_text($msgid)."\n";
   9.446 -                    $output .= $buf_msgstr_plural;
   9.447 -                    $output .= "msgstr[1] ".quote_text($self->{po}{$msgid}{'msgstr'})."\n";
   9.448 -                }
   9.449 -            } else {
   9.450 -                die wrap_msg(dgettext("po4a","Can't write PO files with more than two plural forms."));
   9.451 -            }
   9.452 -        } else {
   9.453 -            if ($self->get_charset =~ /^utf-8$/i) {
   9.454 -                my $msgstr = Encode::decode_utf8($self->{po}{$msgid}{'msgstr'});
   9.455 -                $msgid = Encode::decode_utf8($msgid);
   9.456 -                $output .= Encode::encode_utf8("msgid ".quote_text($msgid)."\n");
   9.457 -                $output .= Encode::encode_utf8("msgstr ".quote_text($msgstr)."\n");
   9.458 -            } else {
   9.459 -                $output .= "msgid ".quote_text($msgid)."\n";
   9.460 -                $output .= "msgstr ".quote_text($self->{po}{$msgid}{'msgstr'})."\n";
   9.461 -            }
   9.462 -        }
   9.463 -
   9.464 -        print $fh $output;
   9.465 -    }
   9.466 -#    print STDERR "$fh";
   9.467 -#    if ($filename ne '-') {
   9.468 -#        close $fh
   9.469 -#            or croak (sprintf(dgettext("po4a",
   9.470 -#                                       "Can't close %s after writing: %s\n"),
   9.471 -#                              $filename,$!));
   9.472 -#    }
   9.473 -}
   9.474 -
   9.475 -=item write_if_needed($$)
   9.476 -
   9.477 -Like write, but if the PO or POT file already exists, the object will be
   9.478 -written in a temporary file which will be compared with the existing file
   9.479 -to check that the update is needed (this avoids to change a POT just to
   9.480 -update a line reference or the POT-Creation-Date field).
   9.481 -
   9.482 -=cut
   9.483 -
   9.484 -sub move_po_if_needed {
   9.485 -    my ($new_po, $old_po, $backup) = (shift, shift, shift);
   9.486 -    my $diff;
   9.487 -
   9.488 -    if (-e $old_po) {
   9.489 -        my $diff_ignore = "-I'^#:' "
   9.490 -                         ."-I'^\"POT-Creation-Date:' "
   9.491 -                         ."-I'^\"PO-Revision-Date:'";
   9.492 -        $diff = qx(diff -q $diff_ignore $old_po $new_po);
   9.493 -        if ( $diff eq "" ) {
   9.494 -            unlink $new_po
   9.495 -                or die wrap_msg(dgettext("po4a","Can't unlink %s: %s."),
   9.496 -                                $new_po, $!);
   9.497 -            # touch the old PO
   9.498 -            my ($atime, $mtime) = (time,time);
   9.499 -            utime $atime, $mtime, $old_po;
   9.500 -        } else {
   9.501 -            if ($backup) {
   9.502 -                copy $old_po, $old_po."~"
   9.503 -                    or die wrap_msg(dgettext("po4a","Can't copy %s to %s: %s."),
   9.504 -                                    $old_po, $old_po."~", $!);
   9.505 -            } else {
   9.506 -            }
   9.507 -            move $new_po, $old_po
   9.508 -                or die wrap_msg(dgettext("po4a","Can't move %s to %s: %s."),
   9.509 -                                $new_po, $old_po, $!);
   9.510 -        }
   9.511 -    } else {
   9.512 -        move $new_po, $old_po
   9.513 -            or die wrap_msg(dgettext("po4a","Can't move %s to %s: %s."),
   9.514 -                            $new_po, $old_po, $!);
   9.515 -    }
   9.516 -}
   9.517 -
   9.518 -sub write_if_needed {
   9.519 -    my $self=shift;
   9.520 -    my $filename=shift
   9.521 -        or croak dgettext("po4a","Can't write to a file without filename")."\n";
   9.522 -
   9.523 -    if (-e $filename) {
   9.524 -        my ($tmp_filename);
   9.525 -        (undef,$tmp_filename)=File::Temp->tempfile($filename."XXXX",
   9.526 -                                                   DIR    => "/tmp",
   9.527 -                                                   OPEN   => 0,
   9.528 -                                                   UNLINK => 0);
   9.529 -        $self->write($tmp_filename);
   9.530 -        move_po_if_needed($tmp_filename, $filename);
   9.531 -    } else {
   9.532 -        $self->write($filename);
   9.533 -    }
   9.534 -}
   9.535 -
   9.536 -=item gettextize($$)
   9.537 -
   9.538 -This function produces one translated message catalog from two catalogs, an
   9.539 -original and a translation. This process is described in L<po4a(7)|po4a.7>,
   9.540 -section I<Gettextization: how does it work?>.
   9.541 -
   9.542 -=cut
   9.543 -
   9.544 -sub gettextize {
   9.545 -    my $this = shift;
   9.546 -    my $class = ref($this) || $this;
   9.547 -    my ($poorig,$potrans)=(shift,shift);
   9.548 -
   9.549 -    my $pores=Locale::Po4a::Po->new();
   9.550 -
   9.551 -    my $please_fail = 0;
   9.552 -    my $toobad = dgettext("po4a",
   9.553 -        "\nThe gettextization failed (once again). Don't give up, ".
   9.554 -        "gettextizing is a subtle art, but this is only needed once ".
   9.555 -        "to convert a project to the gorgeous luxus offered by po4a ".
   9.556 -        "to translators.".
   9.557 -        "\nPlease refer to the po4a(7) documentation, the section ".
   9.558 -        "\"HOWTO convert a pre-existing translation to po4a?\" ".
   9.559 -        "contains several hints to help you in your task");
   9.560 -
   9.561 -    # Don't fail right now when the entry count does not match. Instead, give
   9.562 -    # it a try so that the user can see where we fail (which is probably where
   9.563 -    # the problem is).
   9.564 -    if ($poorig->count_entries_doc() > $potrans->count_entries_doc()) {
   9.565 -        warn wrap_mod("po4a gettextize", dgettext("po4a",
   9.566 -            "Original has more strings than the translation (%d>%d). ".
   9.567 -            "Please fix it by editing the translated version to add ".
   9.568 -            "some dummy entry."),
   9.569 -                      $poorig->count_entries_doc(),
   9.570 -                      $potrans->count_entries_doc());
   9.571 -        $please_fail = 1;
   9.572 -    } elsif ($poorig->count_entries_doc() < $potrans->count_entries_doc()) {
   9.573 -        warn wrap_mod("po4a gettextize", dgettext("po4a",
   9.574 -            "Original has less strings than the translation (%d<%d). ".
   9.575 -            "Please fix it by removing the extra entry from the ".
   9.576 -            "translated file. You may need an addendum (cf po4a(7)) ".
   9.577 -            "to reput the chunk in place after gettextization. A ".
   9.578 -            "possible cause is that a text duplicated in the original ".
   9.579 -            "is not translated the same way each time. Remove one of ".
   9.580 -            "the translations, and you're fine."),
   9.581 -                      $poorig->count_entries_doc(),
   9.582 -                      $potrans->count_entries_doc());
   9.583 -        $please_fail = 1;
   9.584 -    }
   9.585 -
   9.586 -    if ( $poorig->get_charset =~ /^utf-8$/i ) {
   9.587 -        $potrans->to_utf8;
   9.588 -        $pores->set_charset("utf-8");
   9.589 -    } else {
   9.590 -        if ($potrans->get_charset eq "CHARSET") {
   9.591 -            $pores->set_charset("ascii");
   9.592 -        } else {
   9.593 -            $pores->set_charset($potrans->get_charset);
   9.594 -        }
   9.595 -    }
   9.596 -    print "Po character sets:\n".
   9.597 -        "  original=".$poorig->get_charset."\n".
   9.598 -        "  translated=".$potrans->get_charset."\n".
   9.599 -        "  result=".$pores->get_charset."\n"
   9.600 -            if $debug{'encoding'};
   9.601 -
   9.602 -    for (my ($o,$t)=(0,0) ;
   9.603 -         $o<$poorig->count_entries_doc() && $t<$potrans->count_entries_doc();
   9.604 -         $o++,$t++) {
   9.605 -        #
   9.606 -        # Extract some informations
   9.607 -
   9.608 -        my ($orig,$trans)=($poorig->msgid_doc($o),$potrans->msgid_doc($t));
   9.609 -#       print STDERR "Matches [[$orig]]<<$trans>>\n";
   9.610 -
   9.611 -        my ($reforig,$reftrans)=($poorig->{po}{$orig}{'reference'},
   9.612 -                                 $potrans->{po}{$trans}{'reference'});
   9.613 -        my ($typeorig,$typetrans)=($poorig->{po}{$orig}{'type'},
   9.614 -                                   $potrans->{po}{$trans}{'type'});
   9.615 -
   9.616 -        #
   9.617 -        # Make sure the type of both string exist
   9.618 -        #
   9.619 -        die wrap_mod("po4a gettextize",
   9.620 -                     "Internal error: type of original string number %s ".
   9.621 -                     "isn't provided", $o)
   9.622 -            if ($typeorig eq '');
   9.623 -
   9.624 -        die wrap_mod("po4a gettextize",
   9.625 -                     "Internal error: type of translated string number %s ".
   9.626 -                     "isn't provided", $o)
   9.627 -            if ($typetrans eq '');
   9.628 -
   9.629 -        #
   9.630 -        # Make sure both type are the same
   9.631 -        #
   9.632 -        if ($typeorig ne $typetrans){
   9.633 -            $pores->write("gettextization.failed.po");
   9.634 -            die wrap_msg(dgettext("po4a",
   9.635 -                         "po4a gettextization: Structure disparity between ".
   9.636 -                         "original and translated files:\n".
   9.637 -                         "msgid (at %s) is of type '%s' while\n".
   9.638 -                         "msgstr (at %s) is of type '%s'.\n".
   9.639 -                         "Original text: %s\n".
   9.640 -                         "Translated text: %s\n".
   9.641 -                         "(result so far dumped to gettextization.failed.po)").
   9.642 -                         "%s",
   9.643 -                         $reforig, $typeorig,
   9.644 -                         $reftrans, $typetrans,
   9.645 -                         $orig,
   9.646 -                         $trans,
   9.647 -                         $toobad);
   9.648 -        }
   9.649 -
   9.650 -        #
   9.651 -        # Push the entry
   9.652 -        #
   9.653 -        my $flags;
   9.654 -        if (defined $poorig->{po}{$orig}{'flags'}) {
   9.655 -            $flags = $poorig->{po}{$orig}{'flags'}." fuzzy";
   9.656 -        } else {
   9.657 -            $flags = "fuzzy";
   9.658 -        }
   9.659 -        $pores->push_raw('msgid'     => $orig,
   9.660 -                         'msgstr'    => $trans,
   9.661 -                         'flags'     => $flags,
   9.662 -                         'type'      => $typeorig,
   9.663 -                         'reference' => $reforig,
   9.664 -                         'conflict'  => 1,
   9.665 -                         'transref'  => $potrans->{po}{$trans}{'reference'})
   9.666 -            unless (defined($pores->{po}{$orig})
   9.667 -                    and ($pores->{po}{$orig}{'msgstr'} eq $trans))
   9.668 -        # FIXME: maybe we should be smarter about what reference should be
   9.669 -        #        sent to push_raw.
   9.670 -    }
   9.671 -
   9.672 -    # make sure we return a useful error message when entry count differ
   9.673 -    die "$toobad\n" if $please_fail;
   9.674 -
   9.675 -    return $pores;
   9.676 -}
   9.677 -
   9.678 -=item filter($)
   9.679 -
   9.680 -This function extracts a catalog from an existing one. Only the entries having
   9.681 -a reference in the given file will be placed in the resulting catalog.
   9.682 -
   9.683 -This function parses its argument, converts it to a perl function definition,
   9.684 -eval this definition and filter the fields for which this function returns
   9.685 -true.
   9.686 -
   9.687 -I love perl sometimes ;)
   9.688 -
   9.689 -=cut
   9.690 -
   9.691 -sub filter {
   9.692 -    my $self=shift;
   9.693 -    our $filter=shift;
   9.694 -
   9.695 -    my $res;
   9.696 -    $res = Locale::Po4a::Po->new();
   9.697 -
   9.698 -    # Parse the filter
   9.699 -    our $code="sub apply { return ";
   9.700 -    our $pos=0;
   9.701 -    our $length = length $filter;
   9.702 -
   9.703 -    # explode chars to parts. How to subscript a string in Perl?
   9.704 -    our @filter = split(//,$filter);
   9.705 -
   9.706 -    sub gloups {
   9.707 -        my $fmt=shift;
   9.708 -        my $space = "";
   9.709 -        for (1..$pos){
   9.710 -            $space .= ' ';
   9.711 -        }
   9.712 -        die wrap_msg("$fmt\n$filter\n$space^ HERE");
   9.713 -    }
   9.714 -    sub showmethecode {
   9.715 -        return unless $debug{'filter'};
   9.716 -        my $fmt=shift;
   9.717 -        my $space="";
   9.718 -        for (1..$pos){
   9.719 -            $space .= ' ';
   9.720 -        }
   9.721 -        print STDERR "$filter\n$space^ $fmt\n";#"$code\n";
   9.722 -    }
   9.723 -
   9.724 -    # I dream of a lex in perl :-/
   9.725 -    sub parse_expression {
   9.726 -        showmethecode("Begin expression")
   9.727 -            if $debug{'filter'};
   9.728 -
   9.729 -        gloups("Begin of expression expected, got '%s'",$filter[$pos])
   9.730 -            unless ($filter[$pos] eq '(');
   9.731 -        $pos ++; # pass the '('
   9.732 -        if ($filter[$pos] eq '&') {
   9.733 -            # AND
   9.734 -            $pos++;
   9.735 -            showmethecode("Begin of AND")
   9.736 -                if $debug{'filter'};
   9.737 -            $code .= "(";
   9.738 -            while (1) {
   9.739 -                gloups ("Unfinished AND statement.")
   9.740 -                    if ($pos == $length);
   9.741 -                parse_expression();
   9.742 -                if ($filter[$pos] eq '(') {
   9.743 -                    $code .= " && ";
   9.744 -                } elsif ($filter[$pos] eq ')') {
   9.745 -                    last; # do not eat that char
   9.746 -                } else {
   9.747 -                    gloups("End of AND or begin of sub-expression expected, got '%s'", $filter[$pos]);
   9.748 -                }
   9.749 -            }
   9.750 -            $code .= ")";
   9.751 -        } elsif ($filter[$pos] eq '|') {
   9.752 -            # OR
   9.753 -            $pos++;
   9.754 -            $code .= "(";
   9.755 -            while (1) {
   9.756 -                gloups("Unfinished OR statement.")
   9.757 -                    if ($pos == $length);
   9.758 -                parse_expression();
   9.759 -                if ($filter[$pos] eq '(') {
   9.760 -                    $code .= " || ";
   9.761 -                } elsif ($filter[$pos] eq ')') {
   9.762 -                    last; # do not eat that char
   9.763 -                } else {
   9.764 -                    gloups("End of OR or begin of sub-expression expected, got '%s'",$filter[$pos]);
   9.765 -                }
   9.766 -            }
   9.767 -            $code .= ")";
   9.768 -        } elsif ($filter[$pos] eq '!') {
   9.769 -            # NOT
   9.770 -            $pos++;
   9.771 -            $code .= "(!";
   9.772 -            gloups("Missing sub-expression in NOT statement.")
   9.773 -                if ($pos == $length);
   9.774 -            parse_expression();
   9.775 -            $code .= ")";
   9.776 -        } else {
   9.777 -            # must be an equal. Let's get field and argument
   9.778 -            my ($field,$arg,$done);
   9.779 -            $field = substr($filter,$pos);
   9.780 -            gloups("EQ statement contains no '=' or invalid field name")
   9.781 -                unless ($field =~ /([a-z]*)=/i);
   9.782 -            $field = lc($1);
   9.783 -            $pos += (length $field) + 1;
   9.784 -
   9.785 -            # check that we've got a valid field name,
   9.786 -            # and the number it referes to
   9.787 -            # DO NOT CHANGE THE ORDER
   9.788 -            my @names=qw(msgid msgstr reference flags comment automatic);
   9.789 -            my $fieldpos;
   9.790 -            for ($fieldpos = 0;
   9.791 -                 $fieldpos < scalar @names && $field ne $names[$fieldpos];
   9.792 -                 $fieldpos++) {}
   9.793 -            gloups("Invalid field name: %s",$field)
   9.794 -                if $fieldpos == scalar @names; # not found
   9.795 -
   9.796 -            # Now, get the argument value. It has to be between quotes,
   9.797 -            # which can be escaped
   9.798 -            # We point right on the first char of the argument
   9.799 -            # (first quote already eaten)
   9.800 -            my $escaped = 0;
   9.801 -            my $quoted = 0;
   9.802 -            if ($filter[$pos] eq '"') {
   9.803 -                $pos++;
   9.804 -                $quoted = 1;
   9.805 -            }
   9.806 -            showmethecode(($quoted?"Quoted":"Unquoted")." argument of field '$field'")
   9.807 -                if $debug{'filter'};
   9.808 -
   9.809 -            while (!$done) {
   9.810 -                gloups("Unfinished EQ argument.")
   9.811 -                    if ($pos == $length);
   9.812 -
   9.813 -                if ($quoted) {
   9.814 -                    if ($filter[$pos] eq '\\') {
   9.815 -                        if ($escaped) {
   9.816 -                            $arg .= '\\';
   9.817 -                            $escaped = 0;
   9.818 -                        } else {
   9.819 -                            $escaped = 1;
   9.820 -                        }
   9.821 -                    } elsif ($escaped) {
   9.822 -                        if ($filter[$pos] eq '"') {
   9.823 -                            $arg .= '"';
   9.824 -                            $escaped = 0;
   9.825 -                        } else {
   9.826 -                            gloups("Invalid escape sequence in argument: '\\%s'",$filter[$pos]);
   9.827 -                        }
   9.828 -                    } else {
   9.829 -                        if ($filter[$pos] eq '"') {
   9.830 -                            $done = 1;
   9.831 -                        } else {
   9.832 -                            $arg .= $filter[$pos];
   9.833 -                        }
   9.834 -                    }
   9.835 -                } else {
   9.836 -                    if ($filter[$pos] eq ')') {
   9.837 -                        # counter the next ++ since we don't want to eat
   9.838 -                        # this char
   9.839 -                        $pos--;
   9.840 -                        $done = 1;
   9.841 -                    } else {
   9.842 -                        $arg .= $filter[$pos];
   9.843 -                    }
   9.844 -                }
   9.845 -                $pos++;
   9.846 -            }
   9.847 -            # and now, add the code to check this equality
   9.848 -            $code .= "(\$_[$fieldpos] =~ m/$arg/)";
   9.849 -
   9.850 -        }
   9.851 -        showmethecode("End of expression")
   9.852 -            if $debug{'filter'};
   9.853 -        gloups("Unfinished statement.")
   9.854 -            if ($pos == $length);
   9.855 -        gloups("End of expression expected, got '%s'",$filter[$pos])
   9.856 -            unless ($filter[$pos] eq ')');
   9.857 -        $pos++;
   9.858 -    }
   9.859 -    # And now, launch the beast, finish the function and use eval
   9.860 -    # to construct this function.
   9.861 -    # Ok, the lack of lexer is a fair price for the eval ;)
   9.862 -    parse_expression();
   9.863 -    gloups("Garbage at the end of the expression")
   9.864 -        if ($pos != $length);
   9.865 -    $code .= "; }";
   9.866 -    print STDERR "CODE = $code\n"
   9.867 -        if $debug{'filter'};
   9.868 -    eval $code;
   9.869 -    die wrap_mod("po4a::po", dgettext("po4a", "Eval failure: %s"), $@)
   9.870 -        if $@;
   9.871 -
   9.872 -    for (my $cpt=(0) ;
   9.873 -         $cpt<$self->count_entries();
   9.874 -         $cpt++) {
   9.875 -
   9.876 -        my ($msgid,$ref,$msgstr,$flags,$type,$comment,$automatic);
   9.877 -
   9.878 -        $msgid = $self->msgid($cpt);
   9.879 -        $ref=$self->{po}{$msgid}{'reference'};
   9.880 -
   9.881 -        $msgstr= $self->{po}{$msgid}{'msgstr'};
   9.882 -        $flags =  $self->{po}{$msgid}{'flags'};
   9.883 -        $type = $self->{po}{$msgid}{'type'};
   9.884 -        $comment = $self->{po}{$msgid}{'comment'};
   9.885 -        $automatic = $self->{po}{$msgid}{'automatic'};
   9.886 -
   9.887 -        # DO NOT CHANGE THE ORDER
   9.888 -        $res->push_raw('msgid' => $msgid,
   9.889 -                       'msgstr' => $msgstr,
   9.890 -                       'flags' => $flags,
   9.891 -                       'type'  => $type,
   9.892 -                       'reference' => $ref,
   9.893 -                       'comment' => $comment,
   9.894 -                       'automatic' => $automatic)
   9.895 -               if (apply($msgid,$msgstr,$ref,$flags,$comment,$automatic));
   9.896 -    }
   9.897 -    # delete the apply subroutine
   9.898 -    # otherwise it will be redefined.
   9.899 -    undef &apply;
   9.900 -    return $res;
   9.901 -}
   9.902 -
   9.903 -=item to_utf8()
   9.904 -
   9.905 -Recodes to utf-8 the po's msgstrs. Does nothing if the charset is not
   9.906 -specified in the po file ("CHARSET" value), or if it's already utf-8 or
   9.907 -ascii.
   9.908 -
   9.909 -=cut
   9.910 -
   9.911 -sub to_utf8 {
   9.912 -    my $this = shift;
   9.913 -    my $charset = $this->get_charset();
   9.914 -
   9.915 -    unless ($charset eq "CHARSET" or
   9.916 -            $charset =~ /^ascii$/i or
   9.917 -            $charset =~ /^utf-8$/i) {
   9.918 -        foreach my $msgid ( keys %{$this->{po}} ) {
   9.919 -            Encode::from_to($this->{po}{$msgid}{'msgstr'}, $charset, "utf-8");
   9.920 -        }
   9.921 -        $this->set_charset("utf-8");
   9.922 -    }
   9.923 -}
   9.924 -
   9.925 -=back
   9.926 -
   9.927 -=head1 Functions to use a message catalog for translations
   9.928 -
   9.929 -=over 4
   9.930 -
   9.931 -=item gettext($%)
   9.932 -
   9.933 -Request the translation of the string given as argument in the current catalog.
   9.934 -The function returns the original (untranslated) string if the string was not
   9.935 -found.
   9.936 -
   9.937 -After the string to translate, you can pass a hash of extra
   9.938 -arguments. Here are the valid entries:
   9.939 -
   9.940 -=over
   9.941 -
   9.942 -=item wrap
   9.943 -
   9.944 -boolean indicating whether we can consider that whitespaces in string are
   9.945 -not important. If yes, the function canonizes the string before looking for
   9.946 -a translation, and wraps the result.
   9.947 -
   9.948 -=item wrapcol
   9.949 -
   9.950 -The column at which we should wrap (default: 76).
   9.951 -
   9.952 -=back
   9.953 -
   9.954 -=cut
   9.955 -
   9.956 -sub gettext {
   9.957 -    my $self=shift;
   9.958 -    my $text=shift;
   9.959 -    my (%opt)=@_;
   9.960 -    my $res;
   9.961 -
   9.962 -    return "" unless defined($text) && length($text); # Avoid returning the header.
   9.963 -    my $validoption="reference wrap wrapcol";
   9.964 -    my %validoption;
   9.965 -
   9.966 -    map { $validoption{$_}=1 } (split(/ /,$validoption));
   9.967 -    foreach (keys %opt) {
   9.968 -        Carp::confess "internal error:  unknown arg $_.\n".
   9.969 -                      "Here are the valid options: $validoption.\n"
   9.970 -            unless $validoption{$_};
   9.971 -    }
   9.972 -
   9.973 -    $text=canonize($text)
   9.974 -        if ($opt{'wrap'});
   9.975 -
   9.976 -    my $esc_text=escape_text($text);
   9.977 -
   9.978 -    $self->{gettextqueries}++;
   9.979 -
   9.980 -    if (    defined $self->{po}{$esc_text}
   9.981 -        and defined $self->{po}{$esc_text}{'msgstr'}
   9.982 -        and length $self->{po}{$esc_text}{'msgstr'}
   9.983 -        and (   not defined $self->{po}{$esc_text}{'flags'}
   9.984 -             or $self->{po}{$esc_text}{'flags'} !~ /fuzzy/)) {
   9.985 -
   9.986 -        $self->{gettexthits}++;
   9.987 -        $res = unescape_text($self->{po}{$esc_text}{'msgstr'});
   9.988 -        if (defined $self->{po}{$esc_text}{'plural'}) {
   9.989 -            if ($self->{po}{$esc_text}{'plural'} eq "0") {
   9.990 -                warn wrap_mod("po4a gettextize", dgettext("po4a",
   9.991 -                              "'%s' is the singular form of a message, ".
   9.992 -                              "po4a will use the msgstr[0] translation (%s)."),
   9.993 -                              $esc_text, $res);
   9.994 -            } else {
   9.995 -                warn wrap_mod("po4a gettextize", dgettext("po4a",
   9.996 -                              "'%s' is the plural form of a message, ".
   9.997 -                              "po4a will use the msgstr[1] translation (%s)."),
   9.998 -                              $esc_text, $res);
   9.999 -            }
  9.1000 -        }
  9.1001 -    } else {
  9.1002 -        $res = $text;
  9.1003 -    }
  9.1004 -
  9.1005 -    if ($opt{'wrap'}) {
  9.1006 -        if ($self->get_charset =~ /^utf-8$/i) {
  9.1007 -            $res=Encode::decode_utf8($res);
  9.1008 -            $res=wrap ($res, $opt{'wrapcol'} || 76);
  9.1009 -            $res=Encode::encode_utf8($res);
  9.1010 -        } else {
  9.1011 -            $res=wrap ($res, $opt{'wrapcol'} || 76);
  9.1012 -        }
  9.1013 -    }
  9.1014 -#    print STDERR "Gettext >>>$text<<<(escaped=$esc_text)=[[[$res]]]\n\n";
  9.1015 -    return $res;
  9.1016 -}
  9.1017 -
  9.1018 -=item stats_get()
  9.1019 -
  9.1020 -Returns statistics about the hit ratio of gettext since the last time that
  9.1021 -stats_clear() was called. Please note that it's not the same
  9.1022 -statistics than the one printed by msgfmt --statistic. Here, it's statistics
  9.1023 -about recent usage of the po file, while msgfmt reports the status of the
  9.1024 -file.  Example of use:
  9.1025 -
  9.1026 -    [some use of the po file to translate stuff]
  9.1027 -
  9.1028 -    ($percent,$hit,$queries) = $pofile->stats_get();
  9.1029 -    print "So far, we found translations for $percent\%  ($hit of $queries) of strings.\n";
  9.1030 -
  9.1031 -=cut
  9.1032 -
  9.1033 -sub stats_get() {
  9.1034 -    my $self=shift;
  9.1035 -    my ($h,$q)=($self->{gettexthits},$self->{gettextqueries});
  9.1036 -    my $p = ($q == 0 ? 100 : int($h/$q*10000)/100);
  9.1037 -
  9.1038 -#    $p =~ s/\.00//;
  9.1039 -#    $p =~ s/(\..)0/$1/;
  9.1040 -
  9.1041 -    return ( $p,$h,$q );
  9.1042 -}
  9.1043 -
  9.1044 -=item stats_clear()
  9.1045 -
  9.1046 -Clears the statistics about gettext hits.
  9.1047 -
  9.1048 -=cut
  9.1049 -
  9.1050 -sub stats_clear {
  9.1051 -    my $self = shift;
  9.1052 -    $self->{gettextqueries} = 0;
  9.1053 -    $self->{gettexthits} = 0;
  9.1054 -}
  9.1055 -
  9.1056 -=back
  9.1057 -
  9.1058 -=head1 Functions to build a message catalog
  9.1059 -
  9.1060 -=over 4
  9.1061 -
  9.1062 -=item push(%)
  9.1063 -
  9.1064 -Push a new entry at the end of the current catalog. The arguments should
  9.1065 -form a hash table. The valid keys are:
  9.1066 -
  9.1067 -=over 4
  9.1068 -
  9.1069 -=item msgid
  9.1070 -
  9.1071 -the string in original language.
  9.1072 -
  9.1073 -=item msgstr
  9.1074 -
  9.1075 -the translation.
  9.1076 -
  9.1077 -=item reference
  9.1078 -
  9.1079 -an indication of where this string was found. Example: file.c:46 (meaning
  9.1080 -in 'file.c' at line 46). It can be a space-separated list in case of
  9.1081 -multiple occurrences.
  9.1082 -
  9.1083 -=item comment
  9.1084 -
  9.1085 -a comment added here manually (by the translators). The format here is free.
  9.1086 -
  9.1087 -=item automatic
  9.1088 -
  9.1089 -a comment which was automatically added by the string extraction
  9.1090 -program. See the I<--add-comments> option of the B<xgettext> program for
  9.1091 -more information.
  9.1092 -
  9.1093 -=item flags
  9.1094 -
  9.1095 -space-separated list of all defined flags for this entry.
  9.1096 -
  9.1097 -Valid flags are: c-text, python-text, lisp-text, elisp-text, librep-text,
  9.1098 -smalltalk-text, java-text, awk-text, object-pascal-text, ycp-text,
  9.1099 -tcl-text, wrap, no-wrap and fuzzy.
  9.1100 -
  9.1101 -See the gettext documentation for their meaning.
  9.1102 -
  9.1103 -=item type
  9.1104 -
  9.1105 -This is mostly an internal argument: it is used while gettextizing
  9.1106 -documents. The idea here is to parse both the original and the translation
  9.1107 -into a po object, and merge them, using one's msgid as msgid and the
  9.1108 -other's msgid as msgstr. To make sure that things get ok, each msgid in po
  9.1109 -objects are given a type, based on their structure (like "chapt", "sect1",
  9.1110 -"p" and so on in docbook). If the types of strings are not the same, that
  9.1111 -means that both files do not share the same structure, and the process
  9.1112 -reports an error.
  9.1113 -
  9.1114 -This information is written as automatic comment in the po file since this
  9.1115 -gives to translators some context about the strings to translate.
  9.1116 -
  9.1117 -=item wrap
  9.1118 -
  9.1119 -boolean indicating whether whitespaces can be mangled in cosmetic
  9.1120 -reformattings. If true, the string is canonized before use.
  9.1121 -
  9.1122 -This information is written to the po file using the 'wrap' or 'no-wrap' flag.
  9.1123 -
  9.1124 -=item wrapcol
  9.1125 -
  9.1126 -The column at which we should wrap (default: 76).
  9.1127 -
  9.1128 -This information is not written to the po file.
  9.1129 -
  9.1130 -=back
  9.1131 -
  9.1132 -=cut
  9.1133 -
  9.1134 -sub push {
  9.1135 -    my $self=shift;
  9.1136 -    my %entry=@_;
  9.1137 -
  9.1138 -    my $validoption="wrap wrapcol type msgid msgstr automatic flags reference";
  9.1139 -    my %validoption;
  9.1140 -
  9.1141 -    map { $validoption{$_}=1 } (split(/ /,$validoption));
  9.1142 -    foreach (keys %entry) {
  9.1143 -        Carp::confess "internal error:  unknown arg $_.\n".
  9.1144 -                      "Here are the valid options: $validoption.\n"
  9.1145 -            unless $validoption{$_};
  9.1146 -    }
  9.1147 -
  9.1148 -    unless ($entry{'wrap'}) {
  9.1149 -        $entry{'flags'} .= " no-wrap";
  9.1150 -    }
  9.1151 -    if (defined ($entry{'msgid'})) {
  9.1152 -        $entry{'msgid'} = canonize($entry{'msgid'})
  9.1153 -            if ($entry{'wrap'});
  9.1154 -
  9.1155 -        $entry{'msgid'} = escape_text($entry{'msgid'});
  9.1156 -    }
  9.1157 -    if (defined ($entry{'msgstr'})) {
  9.1158 -        $entry{'msgstr'} = canonize($entry{'msgstr'})
  9.1159 -            if ($entry{'wrap'});
  9.1160 -
  9.1161 -        $entry{'msgstr'} = escape_text($entry{'msgstr'});
  9.1162 -    }
  9.1163 -
  9.1164 -    $self->push_raw(%entry);
  9.1165 -}
  9.1166 -
  9.1167 -# The same as push(), but assuming that msgid and msgstr are already escaped
  9.1168 -sub push_raw {
  9.1169 -    my $self=shift;
  9.1170 -    my %entry=@_;
  9.1171 -    my ($msgid,$msgstr,$reference,$comment,$automatic,$flags,$type,$transref)=
  9.1172 -        ($entry{'msgid'},$entry{'msgstr'},
  9.1173 -         $entry{'reference'},$entry{'comment'},$entry{'automatic'},
  9.1174 -         $entry{'flags'},$entry{'type'},$entry{'transref'});
  9.1175 -    my $keep_conflict = $entry{'conflict'};
  9.1176 -
  9.1177 -#    print STDERR "Push_raw\n";
  9.1178 -#    print STDERR " msgid=>>>$msgid<<<\n" if $msgid;
  9.1179 -#    print STDERR " msgstr=[[[$msgstr]]]\n" if $msgstr;
  9.1180 -#    Carp::cluck " flags=$flags\n" if $flags;
  9.1181 -
  9.1182 -    return unless defined($entry{'msgid'});
  9.1183 -
  9.1184 -    #no msgid => header definition
  9.1185 -    unless (length($entry{'msgid'})) {
  9.1186 -#       if (defined($self->{header}) && $self->{header} =~ /\S/) {
  9.1187 -#           warn dgettext("po4a","Redefinition of the header. ".
  9.1188 -#                                "The old one will be discarded\n");
  9.1189 -#       } FIXME: do that iff the header isn't the default one.
  9.1190 -        $self->{header}=$msgstr;
  9.1191 -        $self->{header_comment}=$comment;
  9.1192 -        my $charset = $self->get_charset;
  9.1193 -        if ($charset ne "CHARSET") {
  9.1194 -            $self->{encoder}=find_encoding($charset);
  9.1195 -        } else {
  9.1196 -            $self->{encoder}=find_encoding("ascii");
  9.1197 -        }
  9.1198 -        return;
  9.1199 -    }
  9.1200 -
  9.1201 -    if ($self->{options}{'porefs'} eq "none") {
  9.1202 -        $reference = "";
  9.1203 -    } elsif ($self->{options}{'porefs'} eq "noline") {
  9.1204 -        $reference =~ s/:[0-9]*/:1/g;
  9.1205 -    }
  9.1206 -
  9.1207 -    if (defined($self->{po}{$msgid})) {
  9.1208 -        warn wrap_mod("po4a::po",
  9.1209 -                      dgettext("po4a","msgid defined twice: %s"),
  9.1210 -                      $msgid)
  9.1211 -            if (0); # FIXME: put a verbose stuff
  9.1212 -        if (    defined $msgstr
  9.1213 -            and defined $self->{po}{$msgid}{'msgstr'}
  9.1214 -            and $self->{po}{$msgid}{'msgstr'} ne $msgstr) {
  9.1215 -            my $txt=quote_text($msgid);
  9.1216 -            my ($first,$second)=
  9.1217 -                (format_comment(". ",$self->{po}{$msgid}{'reference'}).
  9.1218 -                 quote_text($self->{po}{$msgid}{'msgstr'}),
  9.1219 -
  9.1220 -                 format_comment(". ",$reference).
  9.1221 -                 quote_text($msgstr));
  9.1222 -
  9.1223 -            if ($keep_conflict) {
  9.1224 -                if ($self->{po}{$msgid}{'msgstr'} =~ m/^#-#-#-#-#  .*  #-#-#-#-#\\n/s) {
  9.1225 -                    $msgstr = $self->{po}{$msgid}{'msgstr'}.
  9.1226 -                              "\\n#-#-#-#-#  $transref  #-#-#-#-#\\n".
  9.1227 -                              $msgstr;
  9.1228 -                } else {
  9.1229 -                    $msgstr = "#-#-#-#-#  ".
  9.1230 -                              $self->{po}{$msgid}{'transref'}.
  9.1231 -                              "  #-#-#-#-#\\n".
  9.1232 -                              $self->{po}{$msgid}{'msgstr'}."\\n".
  9.1233 -                              "#-#-#-#-#  $transref  #-#-#-#-#\\n".
  9.1234 -                              $msgstr;
  9.1235 -                }
  9.1236 -                # Every msgid will have the same list of references.
  9.1237 -                # Only keep the last list.
  9.1238 -                $self->{po}{$msgid}{'reference'} = "";
  9.1239 -            } else {
  9.1240 -            warn wrap_msg(dgettext("po4a",
  9.1241 -                                   "Translations don't match for:\n".
  9.1242 -                                   "%s\n".
  9.1243 -                                   "-->First translation:\n".
  9.1244 -                                   "%s\n".
  9.1245 -                                   " Second translation:\n".
  9.1246 -                                   "%s\n".
  9.1247 -                                   " Old translation discarded."),
  9.1248 -                          $txt,$first,$second);
  9.1249 -            }
  9.1250 -        }
  9.1251 -    }
  9.1252 -    if (defined $transref) {
  9.1253 -        $self->{po}{$msgid}{'transref'} = $transref;
  9.1254 -    }
  9.1255 -    if (defined $reference) {
  9.1256 -        if (defined $self->{po}{$msgid}{'reference'}) {
  9.1257 -            $self->{po}{$msgid}{'reference'} .= " ".$reference;
  9.1258 -        } else {
  9.1259 -            $self->{po}{$msgid}{'reference'} = $reference;
  9.1260 -        }
  9.1261 -    }
  9.1262 -    $self->{po}{$msgid}{'msgstr'} = $msgstr;
  9.1263 -    $self->{po}{$msgid}{'comment'} = $comment;
  9.1264 -    $self->{po}{$msgid}{'automatic'} = $automatic;
  9.1265 -    if (defined($self->{po}{$msgid}{'pos_doc'})) {
  9.1266 -        $self->{po}{$msgid}{'pos_doc'} .= " ".$self->{count_doc}++;
  9.1267 -    } else {
  9.1268 -        $self->{po}{$msgid}{'pos_doc'}  = $self->{count_doc}++;
  9.1269 -    }
  9.1270 -    unless (defined($self->{po}{$msgid}{'pos'})) {
  9.1271 -        $self->{po}{$msgid}{'pos'} = $self->{count}++;
  9.1272 -    }
  9.1273 -    $self->{po}{$msgid}{'type'} = $type;
  9.1274 -    $self->{po}{$msgid}{'plural'} = $entry{'plural'}
  9.1275 -        if defined $entry{'plural'};
  9.1276 -
  9.1277 -    if (defined($flags)) {
  9.1278 -        $flags = " $flags ";
  9.1279 -        $flags =~ s/,/ /g;
  9.1280 -        foreach my $flag (@known_flags) {
  9.1281 -            if ($flags =~ /\s$flag\s/) { # if flag to be set
  9.1282 -                unless (   defined($self->{po}{$msgid}{'flags'})
  9.1283 -                        && $self->{po}{$msgid}{'flags'} =~ /\b$flag\b/) {
  9.1284 -                    # flag not already set
  9.1285 -                    if (defined $self->{po}{$msgid}{'flags'}) {
  9.1286 -                        $self->{po}{$msgid}{'flags'} .= " ".$flag;
  9.1287 -                    } else {
  9.1288 -                        $self->{po}{$msgid}{'flags'} = $flag;
  9.1289 -                    }
  9.1290 -                }
  9.1291 -            }
  9.1292 -        }
  9.1293 -    }
  9.1294 -#    print STDERR "stored ((($msgid)))=>(((".$self->{po}{$msgid}{'msgstr'}.")))\n\n";
  9.1295 -
  9.1296 -}
  9.1297 -
  9.1298 -=back
  9.1299 -
  9.1300 -=head1 Miscellaneous functions
  9.1301 -
  9.1302 -=over 4
  9.1303 -
  9.1304 -=item count_entries()
  9.1305 -
  9.1306 -Returns the number of entries in the catalog (without the header).
  9.1307 -
  9.1308 -=cut
  9.1309 -
  9.1310 -sub count_entries($) {
  9.1311 -    my $self=shift;
  9.1312 -    return $self->{count};
  9.1313 -}
  9.1314 -
  9.1315 -=item count_entries_doc()
  9.1316 -
  9.1317 -Returns the number of entries in document. If a string appears multiple times
  9.1318 -in the document, it will be counted multiple times
  9.1319 -
  9.1320 -=cut
  9.1321 -
  9.1322 -sub count_entries_doc($) {
  9.1323 -    my $self=shift;
  9.1324 -    return $self->{count_doc};
  9.1325 -}
  9.1326 -
  9.1327 -=item msgid($)
  9.1328 -
  9.1329 -Returns the msgid of the given number.
  9.1330 -
  9.1331 -=cut
  9.1332 -
  9.1333 -sub msgid($$) {
  9.1334 -    my $self=shift;
  9.1335 -    my $num=shift;
  9.1336 -
  9.1337 -    foreach my $msgid ( keys %{$self->{po}} ) {
  9.1338 -        return $msgid if ($self->{po}{$msgid}{'pos'} eq $num);
  9.1339 -    }
  9.1340 -    return undef;
  9.1341 -}
  9.1342 -
  9.1343 -=item msgid_doc($)
  9.1344 -
  9.1345 -Returns the msgid with the given position in the document.
  9.1346 -
  9.1347 -=cut
  9.1348 -
  9.1349 -sub msgid_doc($$) {
  9.1350 -    my $self=shift;
  9.1351 -    my $num=shift;
  9.1352 -
  9.1353 -    foreach my $msgid ( keys %{$self->{po}} ) {
  9.1354 -        foreach my $pos (split / /, $self->{po}{$msgid}{'pos_doc'}) {
  9.1355 -            return $msgid if ($pos eq $num);
  9.1356 -        }
  9.1357 -    }
  9.1358 -    return undef;
  9.1359 -}
  9.1360 -
  9.1361 -=item get_charset()
  9.1362 -
  9.1363 -Returns the character set specified in the po header. If it hasn't been
  9.1364 -set, it will return "CHARSET".
  9.1365 -
  9.1366 -=cut
  9.1367 -
  9.1368 -sub get_charset() {
  9.1369 -    my $self=shift;
  9.1370 -
  9.1371 -    $self->{header} =~ /charset=(.*?)[\s\\]/;
  9.1372 -
  9.1373 -    if (defined $1) {
  9.1374 -        return $1;
  9.1375 -    } else {
  9.1376 -        return "CHARSET";
  9.1377 -    }
  9.1378 -}
  9.1379 -
  9.1380 -=item set_charset($)
  9.1381 -
  9.1382 -This sets the character set of the po header to the value specified in its
  9.1383 -first argument. If you never call this function (and no file with a specified
  9.1384 -character set is read), the default value is left to "CHARSET". This value
  9.1385 -doesn't change the behavior of this module, it's just used to fill that field
  9.1386 -in the header, and to return it in get_charset().
  9.1387 -
  9.1388 -=cut
  9.1389 -
  9.1390 -sub set_charset() {
  9.1391 -    my $self=shift;
  9.1392 -
  9.1393 -    my ($newchar,$oldchar);
  9.1394 -    $newchar = shift;
  9.1395 -    $oldchar = $self->get_charset();
  9.1396 -
  9.1397 -    $self->{header} =~ s/$oldchar/$newchar/;
  9.1398 -    $self->{encoder}=find_encoding($newchar);
  9.1399 -}
  9.1400 -
  9.1401 -#----[ helper functions ]---------------------------------------------------
  9.1402 -
  9.1403 -# transforme the string from its po file representation to the form which
  9.1404 -#   should be used to print it
  9.1405 -sub unescape_text {
  9.1406 -    my $text = shift;
  9.1407 -
  9.1408 -    print STDERR "\nunescape [$text]====" if $debug{'escape'};
  9.1409 -    $text = join("",split(/\n/,$text));
  9.1410 -    $text =~ s/\\"/"/g;
  9.1411 -    # unescape newlines
  9.1412 -    #   NOTE on \G:
  9.1413 -    #   The following regular expression introduce newlines.
  9.1414 -    #   Thus, ^ doesn't match all beginnings of lines.
  9.1415 -    #   \G is a zero-width assertion that matches the position
  9.1416 -    #   of the previous substitution with s///g. As every
  9.1417 -    #   substitution ends by a newline, it always matches a
  9.1418 -    #   position just after a newline.
  9.1419 -    $text =~ s/(           # $1:
  9.1420 -                (\G|[^\\]) #    beginning of the line or any char
  9.1421 -                           #    different from '\'
  9.1422 -                (\\\\)*    #    followed by any even number of '\'
  9.1423 -               )\\n        # and followed by an escaped newline
  9.1424 -              /$1\n/sgx;   # single string, match globally, allow comments
  9.1425 -    # unescape tabulations
  9.1426 -    $text =~ s/(          # $1:
  9.1427 -                (\G|[^\\])#    beginning of the line or any char
  9.1428 -                          #    different from '\'
  9.1429 -                (\\\\)*   #    followed by any even number of '\'
  9.1430 -               )\\t       # and followed by an escaped tabulation
  9.1431 -              /$1\t/mgx;  # multilines string, match globally, allow comments
  9.1432 -    # and unescape the escape character
  9.1433 -    $text =~ s/\\\\/\\/g;
  9.1434 -    print STDERR ">$text<\n" if $debug{'escape'};
  9.1435 -
  9.1436 -    return $text;
  9.1437 -}
  9.1438 -
  9.1439 -# transform the string to its representation as it should be written in po
  9.1440 -# files
  9.1441 -sub escape_text {
  9.1442 -    my $text = shift;
  9.1443 -
  9.1444 -    print STDERR "\nescape [$text]====" if $debug{'escape'};
  9.1445 -    $text =~ s/\\/\\\\/g;
  9.1446 -    $text =~ s/"/\\"/g;
  9.1447 -    $text =~ s/\n/\\n/g;
  9.1448 -    $text =~ s/\t/\\t/g;
  9.1449 -    print STDERR ">$text<\n" if $debug{'escape'};
  9.1450 -
  9.1451 -    return $text;
  9.1452 -}
  9.1453 -
  9.1454 -# put quotes around the string on each lines (without escaping it)
  9.1455 -# It does also normalize the text (ie, make sure its representation is wraped
  9.1456 -#   on the 80th char, but without changing the meaning of the string)
  9.1457 -sub quote_text {
  9.1458 -    my $string = shift;
  9.1459 -
  9.1460 -    return '""' unless defined($string) && length($string);
  9.1461 -
  9.1462 -    print STDERR "\nquote [$string]====" if $debug{'quote'};
  9.1463 -    # break lines on newlines, if any
  9.1464 -    # see unescape_text for an explanation on \G
  9.1465 -    $string =~ s/(           # $1:
  9.1466 -                  (\G|[^\\]) #    beginning of the line or any char
  9.1467 -                             #    different from '\'
  9.1468 -                  (\\\\)*    #    followed by any even number of '\'
  9.1469 -                 \\n)        # and followed by an escaped newline
  9.1470 -                /$1\n/sgx;   # single string, match globally, allow comments
  9.1471 -    $string = wrap($string);
  9.1472 -    my @string = split(/\n/,$string);
  9.1473 -    $string = join ("\"\n\"",@string);
  9.1474 -    $string = "\"$string\"";
  9.1475 -    if (scalar @string > 1 && $string[0] ne '') {
  9.1476 -        $string = "\"\"\n".$string;
  9.1477 -    }
  9.1478 -
  9.1479 -    print STDERR ">$string<\n" if $debug{'quote'};
  9.1480 -    return $string;
  9.1481 -}
  9.1482 -
  9.1483 -# undo the work of the quote_text function
  9.1484 -sub unquote_text {
  9.1485 -    my $string = shift;
  9.1486 -    print STDERR "\nunquote [$string]====" if $debug{'quote'};
  9.1487 -    $string =~ s/^""\\n//s;
  9.1488 -    $string =~ s/^"(.*)"$/$1/s;
  9.1489 -    $string =~ s/"\n"//gm;
  9.1490 -    # Note: an even number of '\' could precede \\n, but I could not build a
  9.1491 -    # document to test this
  9.1492 -    $string =~ s/([^\\])\\n\n/$1!!DUMMYPOPM!!/gm;
  9.1493 -    $string =~ s|!!DUMMYPOPM!!|\\n|gm;
  9.1494 -    print STDERR ">$string<\n" if $debug{'quote'};
  9.1495 -    return $string;
  9.1496 -}
  9.1497 -
  9.1498 -# canonize the string: write it on only one line, changing consecutive
  9.1499 -# whitespace to only one space.
  9.1500 -# Warning, it changes the string and should only be called if the string is
  9.1501 -# plain text
  9.1502 -sub canonize {
  9.1503 -    my $text=shift;
  9.1504 -    print STDERR "\ncanonize [$text]====" if $debug{'canonize'};
  9.1505 -    $text =~ s/^ *//s;
  9.1506 -    $text =~ s/^[ \t]+/  /gm;
  9.1507 -    # if ($text eq "\n"), it messed up the first string (header)
  9.1508 -    $text =~ s/\n/  /gm if ($text ne "\n");
  9.1509 -    $text =~ s/([.)])  +/$1  /gm;
  9.1510 -    $text =~ s/([^.)])  */$1 /gm;
  9.1511 -    $text =~ s/ *$//s;
  9.1512 -    print STDERR ">$text<\n" if $debug{'canonize'};
  9.1513 -    return $text;
  9.1514 -}
  9.1515 -
  9.1516 -# wraps the string. We don't use Text::Wrap since it mangles whitespace at
  9.1517 -# the end of splited line
  9.1518 -sub wrap {
  9.1519 -    my $text=shift;
  9.1520 -    return "0" if ($text eq '0');
  9.1521 -    my $col=shift || 76;
  9.1522 -    my @lines=split(/\n/,"$text");
  9.1523 -    my $res="";
  9.1524 -    my $first=1;
  9.1525 -    while (defined(my $line=shift @lines)) {
  9.1526 -        if ($first && length($line) > $col - 10) {
  9.1527 -            unshift @lines,$line;
  9.1528 -            $first=0;
  9.1529 -            next;
  9.1530 -        }
  9.1531 -        if (length($line) > $col) {
  9.1532 -            my $pos=rindex($line," ",$col);
  9.1533 -            while (substr($line,$pos-1,1) eq '.' && $pos != -1) {
  9.1534 -                $pos=rindex($line," ",$pos-1);
  9.1535 -            }
  9.1536 -            if ($pos == -1) {
  9.1537 -                # There are no spaces in the first $col chars, pick-up the
  9.1538 -                # first space
  9.1539 -                $pos = index($line," ");
  9.1540 -            }
  9.1541 -            if ($pos != -1) {
  9.1542 -                my $end=substr($line,$pos+1);
  9.1543 -                $line=substr($line,0,$pos+1);
  9.1544 -                if ($end =~ s/^( +)//) {
  9.1545 -                    $line .= $1;
  9.1546 -                }
  9.1547 -                unshift @lines,$end;
  9.1548 -            }
  9.1549 -        }
  9.1550 -        $first=0;
  9.1551 -        $res.="$line\n";
  9.1552 -    }
  9.1553 -    # Restore the original trailing spaces
  9.1554 -    $res =~ s/\s+$//s;
  9.1555 -    if ($text =~ m/(\s+)$/s) {
  9.1556 -        $res .= $1;
  9.1557 -    }
  9.1558 -    return $res;
  9.1559 -}
  9.1560 -
  9.1561 -# outputs properly a '# ... ' line to be put in the po file
  9.1562 -sub format_comment {
  9.1563 -    my $comment=shift;
  9.1564 -    my $char=shift;
  9.1565 -    my $result = "#". $char . $comment;
  9.1566 -    $result =~ s/\n/\n#$char/gs;
  9.1567 -    $result =~ s/^#$char$/#/gm;
  9.1568 -    $result .= "\n";
  9.1569 -    return $result;
  9.1570 -}
  9.1571 -
  9.1572 -
  9.1573 -1;
  9.1574 -__END__
  9.1575 -
  9.1576 -=back
  9.1577 -
  9.1578 -=head1 AUTHORS
  9.1579 -
  9.1580 - Denis Barbier <barbier@linuxfr.org>
  9.1581 - Martin Quinson (mquinson#debian.org)
  9.1582 -
  9.1583 -=cut
    10.1 --- a/tools/po4a/lib/Locale/Po4a/TransTractor.pm	Mon Mar 30 17:50:48 2009 +0800
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,1100 +0,0 @@
    10.4 -#!/usr/bin/perl -w
    10.5 -
    10.6 -require Exporter;
    10.7 -
    10.8 -package Locale::Po4a::TransTractor;
    10.9 -use DynaLoader;
   10.10 -
   10.11 -use 5.006;
   10.12 -use strict;
   10.13 -use warnings;
   10.14 -
   10.15 -use subs qw(makespace);
   10.16 -use vars qw($VERSION @ISA @EXPORT);
   10.17 -$VERSION="0.36";
   10.18 -@ISA = qw(DynaLoader);
   10.19 -@EXPORT = qw(new process translate 
   10.20 -             read write readpo writepo
   10.21 -             getpoout setpoout);
   10.22 -
   10.23 -# Try to use a C extension if present.
   10.24 -eval("bootstrap Locale::Po4a::TransTractor $VERSION");
   10.25 -
   10.26 -use Carp qw(croak);
   10.27 -use Locale::Po4a::Po;
   10.28 -use Locale::Po4a::Common;
   10.29 -
   10.30 -use File::Path; # mkdir before write
   10.31 -
   10.32 -use Encode;
   10.33 -use Encode::Guess;
   10.34 -
   10.35 -=head1 NAME
   10.36 -
   10.37 -Locale::Po4a::TransTractor - Generic trans(lator ex)tractor.
   10.38 -
   10.39 -=head1 DESCRIPTION
   10.40 -
   10.41 -The po4a (po for anything) project goal is to ease translations (and more
   10.42 -interestingly, the maintenance of translations) using gettext tools on
   10.43 -areas where they were not expected like documentation.
   10.44 -
   10.45 -This class is the ancestor of every po4a parsers used to parse a document to
   10.46 -search translatable strings, extract them to a po file and replace them by
   10.47 -their translation in the output document. 
   10.48 -
   10.49 -More formally, it takes the following arguments as input:
   10.50 -
   10.51 -=over 2
   10.52 -
   10.53 -=item -
   10.54 -
   10.55 -a document to translate ;
   10.56 -
   10.57 -=item -
   10.58 -
   10.59 -a po file containing the translations to use.
   10.60 -
   10.61 -=back
   10.62 -
   10.63 -As output, it produces:
   10.64 -
   10.65 -=over 2
   10.66 -
   10.67 -=item -
   10.68 -
   10.69 -another po file, resulting of the extraction of translatable strings from
   10.70 -the input document ;
   10.71 -
   10.72 -=item -
   10.73 -
   10.74 -a translated document, with the same structure than the one in input, but
   10.75 -with all translatable strings replaced with the translations found in the
   10.76 -po file provided in input.
   10.77 -
   10.78 -=back
   10.79 -
   10.80 -Here is a graphical representation of this:
   10.81 -
   10.82 -   Input document --\                             /---> Output document
   10.83 -                     \                           /       (translated)
   10.84 -                      +-> parse() function -----+
   10.85 -                     /                           \
   10.86 -   Input po --------/                             \---> Output po
   10.87 -                                                         (extracted)
   10.88 -
   10.89 -=head1 FUNCTIONS YOUR PARSER SHOULD OVERRIDE
   10.90 -
   10.91 -=over 4
   10.92 -
   10.93 -=item parse()
   10.94 -
   10.95 -This is where all the work takes place: the parsing of input documents, the
   10.96 -generation of output, and the extraction of the translatable strings. This
   10.97 -is pretty simple using the provided functions presented in the section
   10.98 -"INTERNAL FUNCTIONS" below. See also the synopsis, which present an
   10.99 -example.
  10.100 -
  10.101 -This function is called by the process() function bellow, but if you choose
  10.102 -to use the new() function, and to add content manually to your document,
  10.103 -you will have to call this function yourself.
  10.104 -
  10.105 -=item docheader()
  10.106 -
  10.107 -This function returns the header we should add to the produced document,
  10.108 -quoted properly to be a comment in the target language.  See the section
  10.109 -"Educating developers about translations", from L<po4a(7)|po4a.7>, for what
  10.110 -it is good for.
  10.111 -
  10.112 -=back
  10.113 -
  10.114 -=cut
  10.115 -
  10.116 -sub docheader {}
  10.117 -
  10.118 -sub parse {}
  10.119 -
  10.120 -=head1 SYNOPSIS
  10.121 -
  10.122 -The following example parses a list of paragraphs beginning with "<p>". For the sake
  10.123 -of simplicity, we assume that the document is well formatted, i.e. that '<p>'
  10.124 -tags are the only tags present, and that this tag is at the very beginning
  10.125 -of each paragraph.
  10.126 -
  10.127 - sub parse {
  10.128 -   my $self = shift;
  10.129 -
  10.130 -   PARAGRAPH: while (1) {
  10.131 -       my ($paragraph,$pararef)=("","");
  10.132 -       my $first=1;
  10.133 -       my ($line,$lref)=$self->shiftline();
  10.134 -       while (defined($line)) {
  10.135 -	   if ($line =~ m/<p>/ && !$first--; ) {
  10.136 -	       # Not the first time we see <p>. 
  10.137 -	       # Reput the current line in input,
  10.138 -	       #  and put the built paragraph to output
  10.139 -	       $self->unshiftline($line,$lref);
  10.140 -	      
  10.141 -	       # Now that the document is formed, translate it:
  10.142 -	       #   - Remove the leading tag
  10.143 -	       $paragraph =~ s/^<p>//s;
  10.144 -
  10.145 -	       #   - push to output the leading tag (untranslated) and the
  10.146 -	       #     rest of the paragraph (translated)
  10.147 -	       $self->pushline(  "<p>"
  10.148 -                               . $document->translate($paragraph,$pararef)
  10.149 -                               );
  10.150 -
  10.151 - 	       next PARAGRAPH;
  10.152 -	   } else {
  10.153 -	       # Append to the paragraph
  10.154 -	       $paragraph .= $line;
  10.155 -	       $pararef = $lref unless(length($pararef));
  10.156 -	   }
  10.157 -
  10.158 -           # Reinit the loop
  10.159 -           ($line,$lref)=$self->shiftline();
  10.160 -       }
  10.161 -       # Did not get a defined line? End of input file.
  10.162 -       return;
  10.163 -   }
  10.164 - } 
  10.165 -
  10.166 -Once you've implemented the parse function, you can use your document
  10.167 -class, using the public interface presented in the next section.
  10.168 -
  10.169 -=head1 PUBLIC INTERFACE for scripts using your parser
  10.170 -
  10.171 -=head2 Constructor
  10.172 -
  10.173 -=over 4
  10.174 -
  10.175 -=item process(%)
  10.176 -
  10.177 -This function can do all you need to do with a po4a document in one
  10.178 -invocation. Its arguments must be packed as a hash. ACTIONS:
  10.179 -
  10.180 -=over 3
  10.181 -
  10.182 -=item a.
  10.183 -
  10.184 -Reads all the po files specified in po_in_name
  10.185 -
  10.186 -=item b.
  10.187 -
  10.188 -Reads all original documents specified in file_in_name
  10.189 -
  10.190 -=item c.
  10.191 -
  10.192 -Parses the document
  10.193 -
  10.194 -=item d.
  10.195 -
  10.196 -Reads and applies all the addenda specified
  10.197 -
  10.198 -=item e.
  10.199 -
  10.200 -Writes the translated document to file_out_name (if given)
  10.201 -
  10.202 -=item f.
  10.203 -
  10.204 -Writes the extracted po file to po_out_name (if given)
  10.205 -
  10.206 -=back
  10.207 -
  10.208 -ARGUMENTS, beside the ones accepted by new() (with expected type):
  10.209 -
  10.210 -=over 4
  10.211 -
  10.212 -=item file_in_name (@)
  10.213 -
  10.214 -List of filenames where we should read the input document.
  10.215 -
  10.216 -=item file_in_charset ($)
  10.217 -
  10.218 -Charset used in the input document (if it isn't specified, it will try
  10.219 -to detect it from the input document).
  10.220 -
  10.221 -=item file_out_name ($)
  10.222 -
  10.223 -Filename where we should write the output document.
  10.224 -
  10.225 -=item file_out_charset ($)
  10.226 -
  10.227 -Charset used in the output document (if it isn't specified, it will use
  10.228 -the po file charset).
  10.229 -
  10.230 -=item po_in_name (@)
  10.231 -
  10.232 -List of filenames where we should read the input po files from, containing
  10.233 -the translation which will be used to translate the document.
  10.234 -
  10.235 -=item po_out_name ($)
  10.236 -
  10.237 -Filename where we should write the output po file, containing the strings
  10.238 -extracted from the input document.
  10.239 -
  10.240 -=item addendum (@)
  10.241 -
  10.242 -List of filenames where we should read the addenda from.
  10.243 -
  10.244 -=item addendum_charset ($)
  10.245 -
  10.246 -Charset for the addenda.
  10.247 -
  10.248 -=back
  10.249 -
  10.250 -=item new(%)
  10.251 -
  10.252 -Create a new Po4a document. Accepted options (but be in a hash):
  10.253 -
  10.254 -=over 4
  10.255 -
  10.256 -=item verbose ($)
  10.257 -
  10.258 -Sets the verbosity.
  10.259 -
  10.260 -=item debug ($)
  10.261 -
  10.262 -Sets the debugging.
  10.263 -
  10.264 -=back
  10.265 -
  10.266 -=cut
  10.267 -
  10.268 -sub process {
  10.269 -    ## Determine if we were called via an object-ref or a classname
  10.270 -    my $self = shift;
  10.271 -
  10.272 -    ## Any remaining arguments are treated as initial values for the
  10.273 -    ## hash that is used to represent this object.
  10.274 -    my %params = @_;
  10.275 -    
  10.276 -    # Build the args for new()
  10.277 -    my %newparams = ();
  10.278 -    foreach (keys %params) {
  10.279 -	next if ($_ eq 'po_in_name' ||
  10.280 -		 $_ eq 'po_out_name' ||
  10.281 -		 $_ eq 'file_in_name' ||
  10.282 -		 $_ eq 'file_in_charset' ||
  10.283 -		 $_ eq 'file_out_name' ||
  10.284 -		 $_ eq 'file_out_charset' ||
  10.285 -		 $_ eq 'addendum' ||
  10.286 -		 $_ eq 'addendum_charset');
  10.287 -	$newparams{$_}=$params{$_};
  10.288 -    }
  10.289 -
  10.290 -    $self->detected_charset($params{'file_in_charset'});
  10.291 -    $self->{TT}{'file_out_charset'}=$params{'file_out_charset'};
  10.292 -    if (defined($self->{TT}{'file_out_charset'}) and
  10.293 -	length($self->{TT}{'file_out_charset'})) {
  10.294 -	$self->{TT}{'file_out_encoder'} = find_encoding($self->{TT}{'file_out_charset'});
  10.295 -    }
  10.296 -    $self->{TT}{'addendum_charset'}=$params{'addendum_charset'};
  10.297 -
  10.298 -    foreach my $file (@{$params{'po_in_name'}}) {
  10.299 -	print STDERR "readpo($file)... " if $self->debug();
  10.300 -	$self->readpo($file);
  10.301 -	print STDERR "done.\n" if $self->debug()
  10.302 -    }
  10.303 -    foreach my $file (@{$params{'file_in_name'}}) {
  10.304 -	print STDERR "read($file)..." if $self->debug();
  10.305 -	$self->read($file);
  10.306 -	print STDERR "done.\n"  if $self->debug();
  10.307 -    }
  10.308 -    print STDERR "parse..." if $self->debug();
  10.309 -    $self->parse();
  10.310 -    print STDERR "done.\n" if $self->debug();
  10.311 -    foreach my $file (@{$params{'addendum'}}) {
  10.312 -	print STDERR "addendum($file)..." if $self->debug();
  10.313 -	$self->addendum($file) || die "An addendum failed\n";
  10.314 -	print STDERR "done.\n" if $self->debug();
  10.315 -    }
  10.316 -    if (defined $params{'file_out_name'}) {
  10.317 -	print STDERR "write(".$params{'file_out_name'}.")... " 
  10.318 -	    if $self->debug();
  10.319 -	$self->write($params{'file_out_name'});
  10.320 -	print STDERR "done.\n" if $self->debug();
  10.321 -    }
  10.322 -    if (defined $params{'po_out_name'}) {
  10.323 -	print STDERR "writepo(".$params{'po_out_name'}.")... "
  10.324 -	     if $self->debug();
  10.325 -	$self->writepo($params{'po_out_name'});
  10.326 -	print STDERR "done.\n" if $self->debug();
  10.327 -    }
  10.328 -    return $self;
  10.329 -}
  10.330 -
  10.331 -sub new {
  10.332 -    ## Determine if we were called via an object-ref or a classname
  10.333 -    my $this = shift;
  10.334 -    my $class = ref($this) || $this;
  10.335 -    my $self = { };
  10.336 -    my %options=@_;
  10.337 -    ## Bless ourselves into the desired class and perform any initialization
  10.338 -    bless $self, $class;
  10.339 -    
  10.340 -    ## initialize the plugin
  10.341 -    # prevent the plugin from croaking on the options intended for Po.pm
  10.342 -    $self->{options}{'porefs'} = '';
  10.343 -    # let the plugin parse the options and such
  10.344 -    $self->initialize(%options);
  10.345 -
  10.346 -    ## Create our private data
  10.347 -    my %po_options;
  10.348 -    $po_options{'porefs'} = $self->{options}{'porefs'};
  10.349 -    
  10.350 -    # private data
  10.351 -    $self->{TT}=(); 
  10.352 -    $self->{TT}{po_in}=Locale::Po4a::Po->new();
  10.353 -    $self->{TT}{po_out}=Locale::Po4a::Po->new(\%po_options);
  10.354 -    # Warning, this is an array of array:
  10.355 -    #  The document is splited on lines, and for each
  10.356 -    #  [0] is the line content, [1] is the reference [2] the type
  10.357 -    $self->{TT}{doc_in}=();
  10.358 -    $self->{TT}{doc_out}=();
  10.359 -    if (defined $options{'verbose'}) {
  10.360 -	$self->{TT}{verbose}  =  $options{'verbose'};
  10.361 -    }
  10.362 -    if (defined $options{'debug'}) {
  10.363 -	$self->{TT}{debug}  =  $options{'debug'};
  10.364 -    }
  10.365 -    # Input document is in ascii until we prove the opposite (in read())
  10.366 -    $self->{TT}{ascii_input}=1;
  10.367 -    # We try not to use utf unless it's forced from the outside (in case the
  10.368 -    # document isn't in ascii)
  10.369 -    $self->{TT}{utf_mode}=0;
  10.370 -
  10.371 -    
  10.372 -    return $self;
  10.373 -}
  10.374 -
  10.375 -=back
  10.376 -
  10.377 -=head2 Manipulating document files
  10.378 -
  10.379 -=over 4
  10.380 -
  10.381 -=item read($)
  10.382 -
  10.383 -Add another input document at the end of the existing one. The argument is
  10.384 -the filename to read. 
  10.385 -
  10.386 -Please note that it does not parse anything. You should use the parse()
  10.387 -function when you're done with packing input files into the document. 
  10.388 -
  10.389 -=cut
  10.390 -
  10.391 -#'
  10.392 -sub read() {
  10.393 -    my $self=shift;
  10.394 -    my $filename=shift
  10.395 -	or croak wrap_msg(dgettext("po4a", "Can't read from file without having a filename"));
  10.396 -    my $linenum=0;
  10.397 -
  10.398 -    open INPUT,"<$filename" 
  10.399 -	or croak wrap_msg(dgettext("po4a", "Can't read from %s: %s"), $filename, $!);
  10.400 -    while (defined (my $textline = <INPUT>)) {
  10.401 -	$linenum++;
  10.402 -	my $ref="$filename:$linenum";
  10.403 -	my @entry=($textline,$ref);
  10.404 -	push @{$self->{TT}{doc_in}}, @entry;
  10.405 -
  10.406 -	if (!defined($self->{TT}{'file_in_charset'})) {
  10.407 -	    # Detect if this file has non-ascii characters
  10.408 -	    if($self->{TT}{ascii_input}) {
  10.409 -		my $decoder = guess_encoding($textline);
  10.410 -		if (!ref($decoder) or $decoder !~ /Encode::XS=/) {
  10.411 -		    # We have detected a non-ascii line
  10.412 -		    $self->{TT}{ascii_input} = 0;
  10.413 -		    # Save the reference for future error message
  10.414 -		    $self->{TT}{non_ascii_ref} ||= $ref;
  10.415 -		}
  10.416 -	    }
  10.417 -	}
  10.418 -    }
  10.419 -    close INPUT 
  10.420 -	or croak wrap_msg(dgettext("po4a", "Can't close %s after reading: %s"), $filename, $!);
  10.421 -
  10.422 -}
  10.423 -
  10.424 -=item write($)
  10.425 -
  10.426 -Write the translated document to the given filename.
  10.427 -
  10.428 -=cut
  10.429 -
  10.430 -sub write {
  10.431 -    my $self=shift;
  10.432 -    my $filename=shift
  10.433 -	or croak wrap_msg(dgettext("po4a", "Can't write to a file without filename"));
  10.434 -
  10.435 -    my $fh;
  10.436 -    if ($filename eq '-') {
  10.437 -	$fh=\*STDOUT;
  10.438 -    } else {
  10.439 -	# make sure the directory in which we should write the localized file exists
  10.440 -	my $dir = $filename;
  10.441 -	if ($dir =~ m|/|) {
  10.442 -	    $dir =~ s|/[^/]*$||;
  10.443 -	
  10.444 -	    File::Path::mkpath($dir, 0, 0755) # Croaks on error
  10.445 -	      if (length ($dir) && ! -e $dir);
  10.446 -	}
  10.447 -	open $fh,">$filename"
  10.448 -	    or croak wrap_msg(dgettext("po4a", "Can't write to %s: %s"), $filename, $!);
  10.449 -    }
  10.450 -    
  10.451 -    map { print $fh $_ } $self->docheader();
  10.452 -    map { print $fh $_ } @{$self->{TT}{doc_out}};
  10.453 -
  10.454 -    if ($filename ne '-') {
  10.455 -	close $fh or croak wrap_msg(dgettext("po4a", "Can't close %s after writing: %s"), $filename, $!);
  10.456 -    }
  10.457 -
  10.458 -}
  10.459 -
  10.460 -=back
  10.461 -
  10.462 -=head2 Manipulating po files
  10.463 -
  10.464 -=over 4 
  10.465 -
  10.466 -=item readpo($)
  10.467 -
  10.468 -Add the content of a file (which name is passed in argument) to the
  10.469 -existing input po. The old content is not discarded.
  10.470 -
  10.471 -=item writepo($)
  10.472 -
  10.473 -Write the extracted po file to the given filename.
  10.474 -
  10.475 -=item stats()
  10.476 -
  10.477 -Returns some statistics about the translation done so far. Please note that
  10.478 -it's not the same statistics than the one printed by msgfmt
  10.479 ---statistic. Here, it's stats about recent usage of the po file, while
  10.480 -msgfmt reports the status of the file. It is a wrapper to the
  10.481 -Locale::Po4a::Po::stats_get function applied to the input po file. Example
  10.482 -of use:
  10.483 -
  10.484 -    [normal use of the po4a document...]
  10.485 -
  10.486 -    ($percent,$hit,$queries) = $document->stats();
  10.487 -    print "We found translations for $percent\%  ($hit from $queries) of strings.\n";
  10.488 -
  10.489 -=back
  10.490 -
  10.491 -=cut
  10.492 -
  10.493 -sub getpoout {
  10.494 -    return $_[0]->{TT}{po_out};
  10.495 -}
  10.496 -sub setpoout {
  10.497 -    $_[0]->{TT}{po_out} = $_[1];
  10.498 -}
  10.499 -sub readpo  { 
  10.500 -    $_[0]->{TT}{po_in}->read($_[1]);        
  10.501 -}
  10.502 -sub writepo { 
  10.503 -    $_[0]->{TT}{po_out}->write( $_[1] );    
  10.504 -}
  10.505 -sub stats   { 
  10.506 -    return $_[0]->{TT}{po_in}->stats_get(); 
  10.507 -}
  10.508 -
  10.509 -=head2 Manipulating addenda
  10.510 -
  10.511 -=over 4
  10.512 -
  10.513 -=item addendum($)
  10.514 -
  10.515 -Please refer to L<po4a(7)|po4a.7> for more information on what addenda are,
  10.516 -and how translators should write them. To apply an addendum to the translated
  10.517 -document, simply pass its filename to this function and you are done ;)
  10.518 -
  10.519 -This function returns a non-null integer on error.
  10.520 -
  10.521 -=cut
  10.522 -
  10.523 -# Internal function to read the header.
  10.524 -sub addendum_parse {
  10.525 -    my ($filename,$header)=shift;
  10.526 -
  10.527 -    my ($errcode,$mode,$position,$boundary,$bmode,$content)=
  10.528 -	(1,"","","","","");
  10.529 -
  10.530 -    unless (open (INS, "<$filename")) {
  10.531 -	warn wrap_msg(dgettext("po4a", "Can't read from %s: %s"), $filename, $!);
  10.532 -	goto END_PARSE_ADDFILE;
  10.533 -    } 
  10.534 -
  10.535 -    unless (defined ($header=<INS>) && $header)  {
  10.536 -	warn wrap_msg(dgettext("po4a", "Can't read Po4a header from %s."), $filename);
  10.537 -	goto END_PARSE_ADDFILE;
  10.538 -    }
  10.539 -
  10.540 -    unless ($header =~ s/PO4A-HEADER://i) {
  10.541 -	warn wrap_msg(dgettext("po4a", "First line of %s does not look like a Po4a header."), $filename);
  10.542 -	goto END_PARSE_ADDFILE;
  10.543 -    }
  10.544 -    foreach my $part (split(/;/,$header)) {
  10.545 -	unless ($part =~ m/^\s*([^=]*)=(.*)$/) {
  10.546 -	    warn wrap_msg(dgettext("po4a", "Syntax error in Po4a header of %s, near \"%s\""), $filename, $part);
  10.547 -	    goto END_PARSE_ADDFILE;
  10.548 -	}
  10.549 -	my ($key,$value)=($1,$2);
  10.550 -	$key=lc($key);
  10.551 -  	     if ($key eq 'mode')     {  $mode=lc($value);
  10.552 -	} elsif ($key eq 'position') {  $position=$value;
  10.553 -	} elsif ($key eq 'endboundary') {  
  10.554 -	    $boundary=$value;
  10.555 -	    $bmode='after';
  10.556 -	} elsif ($key eq 'beginboundary') {  
  10.557 -	    $boundary=$value;
  10.558 -	    $bmode='before';
  10.559 -	} else { 
  10.560 -	    warn wrap_msg(dgettext("po4a", "Invalid argument in the Po4a header of %s: %s"), $filename, $key);
  10.561 -	    goto END_PARSE_ADDFILE;
  10.562 -	}
  10.563 -    }
  10.564 -
  10.565 -    unless (length($mode)) {
  10.566 -	warn wrap_msg(dgettext("po4a", "The Po4a header of %s does not define the mode."), $filename);
  10.567 -	goto END_PARSE_ADDFILE;
  10.568 -    }
  10.569 -    unless ($mode eq "before" || $mode eq "after") {
  10.570 -	warn wrap_msg(dgettext("po4a", "Mode invalid in the Po4a header of %s: should be 'before' or 'after' not %s."), $filename, $mode);
  10.571 -	goto END_PARSE_ADDFILE;
  10.572 -    }
  10.573 -
  10.574 -    unless (length($position)) {
  10.575 -	warn wrap_msg(dgettext("po4a", "The Po4a header of %s does not define the position."), $filename);
  10.576 -	goto END_PARSE_ADDFILE;
  10.577 -    }
  10.578 -    unless ($mode eq "before" || length($boundary)) {
  10.579 -    	warn wrap_msg(dgettext("po4a", "No ending boundary given in the Po4a header, but mode=after."));
  10.580 -	goto END_PARSE_ADDFILE;
  10.581 -    }
  10.582 -
  10.583 -    while (defined(my $line = <INS>)) {
  10.584 -	$content .= $line;
  10.585 -    }
  10.586 -    close INS;
  10.587 -
  10.588 -    $errcode=0;
  10.589 -  END_PARSE_ADDFILE: 
  10.590 -      return ($errcode,$mode,$position,$boundary,$bmode,$content);
  10.591 -}
  10.592 -
  10.593 -sub mychomp {
  10.594 -    my ($str) = shift;
  10.595 -    chomp($str);
  10.596 -    return $str;
  10.597 -}
  10.598 -
  10.599 -sub addendum {
  10.600 -    my ($self,$filename) = @_;
  10.601 -
  10.602 -    print STDERR "Apply addendum $filename..." if $self->debug();
  10.603 -    unless ($filename) {
  10.604 -	warn wrap_msg(dgettext("po4a",
  10.605 -	    "Can't apply addendum when not given the filename"));
  10.606 -	return 0;
  10.607 -    }
  10.608 -    die wrap_msg(dgettext("po4a", "Addendum %s does not exist."), $filename)
  10.609 -      unless -e $filename;
  10.610 -  
  10.611 -    my ($errcode,$mode,$position,$boundary,$bmode,$content)=
  10.612 -	addendum_parse($filename);
  10.613 -    return 0 if ($errcode);
  10.614 -
  10.615 -    print STDERR "mode=$mode;pos=$position;bound=$boundary;bmode=$bmode;ctn=$content\n"
  10.616 -      if $self->debug();
  10.617 -    
  10.618 -    # We only recode the addendum if an origin charset is specified, else we
  10.619 -    # suppose it's already in the output document's charset
  10.620 -    if (defined($self->{TT}{'addendum_charset'}) &&
  10.621 -        length($self->{TT}{'addendum_charset'})) {
  10.622 -	Encode::from_to($content,$self->{TT}{'addendum_charset'},
  10.623 -	    $self->get_out_charset);
  10.624 -    }
  10.625 -
  10.626 -    my $found = scalar grep { /$position/ } @{$self->{TT}{doc_out}};
  10.627 -    if ($found == 0) {
  10.628 -	warn wrap_msg(dgettext("po4a",
  10.629 -	    "No candidate position for the addendum %s."), $filename);
  10.630 -	return 0;
  10.631 -    }
  10.632 -    if ($found > 1) {
  10.633 -	warn wrap_msg(dgettext("po4a",
  10.634 -	    "More than one candidate position found for the addendum %s."), $filename);
  10.635 -	return 0;
  10.636 -    }
  10.637 -
  10.638 -    if ($mode eq "before") {
  10.639 -	if ($self->verbose() > 1 || $self->debug() ) {
  10.640 -	    map { print STDERR wrap_msg(dgettext("po4a", "Addendum '%s' applied before this line: %s"), $filename, $_) if (/$position/);
  10.641 - 	        } @{$self->{TT}{doc_out}};
  10.642 -	}
  10.643 -	@{$self->{TT}{doc_out}} = map { /$position/ ? ($content,$_) : $_ 
  10.644 -                                        }  @{$self->{TT}{doc_out}};
  10.645 -    } else {
  10.646 -	my @newres=();
  10.647 -
  10.648 -	do {
  10.649 -	    # make sure it doesnt whine on empty document
  10.650 -	    my $line = scalar @{$self->{TT}{doc_out}} ? shift @{$self->{TT}{doc_out}} : "";
  10.651 -	    push @newres,$line;
  10.652 -	    my $outline=mychomp($line);
  10.653 -	    $outline =~ s/^[ \t]*//;
  10.654 -	      
  10.655 -	    if ($line =~ m/$position/) {
  10.656 -		while ($line=shift @{$self->{TT}{doc_out}}) {
  10.657 -		    last if ($line=~/$boundary/);
  10.658 -		    push @newres,$line;
  10.659 -		}
  10.660 -		if (defined $line) {
  10.661 -		    if ($bmode eq 'before') {
  10.662 -			print wrap_msg(dgettext("po4a",
  10.663 -			    "Addendum '%s' applied before this line: %s"),
  10.664 -			    $filename, $outline)
  10.665 -			  if ($self->verbose() > 1 || $self->debug());
  10.666 -			push @newres,$content;
  10.667 -			push @newres,$line;
  10.668 -		    } else {
  10.669 -			print wrap_msg(dgettext("po4a",
  10.670 -			    "Addendum '%s' applied after the line: %s."),
  10.671 -			    $filename, $outline)
  10.672 -			  if ($self->verbose() > 1 || $self->debug());
  10.673 -			push @newres,$line;
  10.674 -			push @newres,$content;
  10.675 -		    }
  10.676 -		} else {
  10.677 -		    print wrap_msg(dgettext("po4a", "Addendum '%s' applied at the end of the file."), $filename)
  10.678 -		      if ($self->verbose() > 1 || $self->debug());
  10.679 -		    push @newres,$content;
  10.680 -		}
  10.681 -	    }
  10.682 -	} while (scalar @{$self->{TT}{doc_out}});
  10.683 -	@{$self->{TT}{doc_out}} = @newres;
  10.684 -    }
  10.685 -    print STDERR "done.\n" if $self->debug();
  10.686 -    return 1;
  10.687 -}
  10.688 -
  10.689 -=back
  10.690 -
  10.691 -=head1 INTERNAL FUNCTIONS used to write derivated parsers
  10.692 -
  10.693 -=head2 Getting input, providing output
  10.694 -
  10.695 -Four functions are provided to get input and return output. They are very
  10.696 -similar to shift/unshift and push/pop. The first pair is about input, while
  10.697 -the second is about output. Mnemonic: in input, you are interested in the
  10.698 -first line, what shift gives, and in output you want to add your result at
  10.699 -the end, like push does.
  10.700 -
  10.701 -=over 4
  10.702 -
  10.703 -=item shiftline()
  10.704 -
  10.705 -This function returns the next line of the doc_in to be parsed and its
  10.706 -reference (packed as an array).
  10.707 -
  10.708 -=item unshiftline($$)
  10.709 -
  10.710 -Unshifts a line of the input document and its reference. 
  10.711 -
  10.712 -=item pushline($)
  10.713 -
  10.714 -Push a new line to the doc_out.
  10.715 -
  10.716 -=item popline()
  10.717 -
  10.718 -Pop the last pushed line from the doc_out.
  10.719 -
  10.720 -=back
  10.721 -
  10.722 -=cut
  10.723 -
  10.724 -sub shiftline   {  
  10.725 -    my ($line,$ref)=(shift @{$_[0]->{TT}{doc_in}},
  10.726 -		     shift @{$_[0]->{TT}{doc_in}}); 
  10.727 -    return ($line,$ref);
  10.728 -}
  10.729 -sub unshiftline {
  10.730 -	my $self = shift;
  10.731 -	unshift @{$self->{TT}{doc_in}},@_;
  10.732 -}
  10.733 -
  10.734 -sub pushline    {  push @{$_[0]->{TT}{doc_out}}, $_[1] if defined $_[1]; }
  10.735 -sub popline     {  return pop @{$_[0]->{TT}{doc_out}};            }
  10.736 -
  10.737 -=head2 Marking strings as translatable
  10.738 -
  10.739 -One function is provided to handle the text which should be translated. 
  10.740 -
  10.741 -=over 4
  10.742 -
  10.743 -=item translate($$$)
  10.744 -
  10.745 -Mandatory arguments:
  10.746 -
  10.747 -=over 2
  10.748 -
  10.749 -=item -
  10.750 -
  10.751 -A string to translate
  10.752 -
  10.753 -=item -
  10.754 -
  10.755 -The reference of this string (ie, position in inputfile)
  10.756 -
  10.757 -=item -
  10.758 -
  10.759 -The type of this string (ie, the textual description of its structural role
  10.760 -; used in Locale::Po4a::Po::gettextization() ; see also L<po4a(7)|po4a.7>,
  10.761 -section I<Gettextization: how does it work?>)
  10.762 -
  10.763 -=back
  10.764 -
  10.765 -This function can also take some extra arguments. They must be organized as
  10.766 -a hash. For example:
  10.767 -
  10.768 -  $self->translate("string","ref","type",
  10.769 -		   'wrap' => 1);
  10.770 -
  10.771 -=over
  10.772 -
  10.773 -=item wrap
  10.774 -
  10.775 -boolean indicating whether we can consider that whitespaces in string are
  10.776 -not important. If yes, the function canonizes the string before looking for
  10.777 -a translation or extracting it, and wraps the translation.
  10.778 -
  10.779 -=item wrapcol
  10.780 -
  10.781 -The column at which we should wrap (default: 76).
  10.782 -
  10.783 -=item comment
  10.784 -
  10.785 -An extra comment to add to the entry.
  10.786 -
  10.787 -=back
  10.788 -
  10.789 -Actions:
  10.790 -
  10.791 -=over 2
  10.792 -
  10.793 -=item -
  10.794 -
  10.795 -Pushes the string, reference and type to po_out.
  10.796 -
  10.797 -=item -
  10.798 -
  10.799 -Returns the translation of the string (as found in po_in) so that the
  10.800 -parser can build the doc_out.
  10.801 -
  10.802 -=item -
  10.803 -
  10.804 -Handles the charsets to recode the strings before sending them to
  10.805 -po_out and before returning the translations.
  10.806 -
  10.807 -=back
  10.808 -
  10.809 -=back
  10.810 -
  10.811 -=cut
  10.812 -
  10.813 -sub translate {
  10.814 -    my $self=shift;
  10.815 -    my ($string,$ref,$type)=(shift,shift,shift);
  10.816 -    my (%options)=@_;
  10.817 -
  10.818 -    # my $validoption="wrap wrapcol";
  10.819 -    # my %validoption;
  10.820 -
  10.821 -    return "" unless defined($string) && length($string);
  10.822 -
  10.823 -    # map { $validoption{$_}=1 } (split(/ /,$validoption));
  10.824 -    # foreach (keys %options) {
  10.825 -    #	Carp::confess "internal error: translate() called with unknown arg $_. Valid options: $validoption"
  10.826 -    #	    unless $validoption{$_};
  10.827 -    # }
  10.828 -
  10.829 -    my $in_charset;
  10.830 -    if ($self->{TT}{ascii_input}) {
  10.831 -	$in_charset = "ascii";
  10.832 -    } else {
  10.833 -	if (defined($self->{TT}{'file_in_charset'}) and
  10.834 -	    length($self->{TT}{'file_in_charset'}) and
  10.835 -	    $self->{TT}{'file_in_charset'} !~ m/ascii/i) {
  10.836 -	    $in_charset=$self->{TT}{'file_in_charset'};
  10.837 -	} else {
  10.838 -	    # FYI, the document charset have to be determined *before* we see the first
  10.839 -	    # string to recode.
  10.840 -	    die wrap_mod("po4a", dgettext("po4a", "Couldn't determine the input document's charset. Please specify it on the command line. (non-ascii char at %s)"), $self->{TT}{non_ascii_ref})
  10.841 -	}
  10.842 -    }
  10.843 -
  10.844 -    if ($self->{TT}{po_in}->get_charset ne "CHARSET") {
  10.845 -	$string = encode_from_to($string,
  10.846 -	                         $self->{TT}{'file_in_encoder'},
  10.847 -	                         $self->{TT}{po_in}{encoder});
  10.848 -    }
  10.849 -
  10.850 -    if (defined $options{'wrapcol'} && $options{'wrapcol'} < 0) {
  10.851 -# FIXME: should be the parameter given with --width
  10.852 -        $options{'wrapcol'} = 76 + $options{'wrapcol'};
  10.853 -    }
  10.854 -    my $transstring = $self->{TT}{po_in}->gettext($string,
  10.855 -					'wrap'      => $options{'wrap'}||0,
  10.856 -					'wrapcol'   => $options{'wrapcol'});
  10.857 -
  10.858 -    if ($self->{TT}{po_in}->get_charset ne "CHARSET") {
  10.859 -	my $out_encoder = $self->{TT}{'file_out_encoder'};
  10.860 -	unless (defined $out_encoder) {
  10.861 -	    $out_encoder = find_encoding($self->get_out_charset)
  10.862 -	}
  10.863 -	$transstring = encode_from_to($transstring,
  10.864 -	                              $self->{TT}{po_in}{encoder},
  10.865 -	                              $out_encoder);
  10.866 -    }
  10.867 -
  10.868 -    # If the input document isn't completely in ascii, we should see what to
  10.869 -    # do with the current string
  10.870 -    unless ($self->{TT}{ascii_input}) {
  10.871 -        my $out_charset = $self->{TT}{po_out}->get_charset;
  10.872 -	# We set the output po charset 
  10.873 -        if ($out_charset eq "CHARSET") {
  10.874 -	    if ($self->{TT}{utf_mode}) {
  10.875 -		$out_charset="utf-8";
  10.876 -	    } else {
  10.877 -		$out_charset=$in_charset;
  10.878 -	    }
  10.879 -	    $self->{TT}{po_out}->set_charset($out_charset);
  10.880 -	}
  10.881 -	if ( $in_charset !~ /^$out_charset$/i ) {
  10.882 -	    Encode::from_to($string,$in_charset,$out_charset);
  10.883 -	    if (defined($options{'comment'}) and length($options{'comment'})) {
  10.884 -		Encode::from_to($options{'comment'},$in_charset,$out_charset);
  10.885 -	    }
  10.886 -	}
  10.887 -    }
  10.888 -
  10.889 -    # the comments provided by the modules are automatic comments from the PO point of view
  10.890 -    $self->{TT}{po_out}->push('msgid'     => $string,
  10.891 -			      'reference' => $ref,
  10.892 -			      'type'      => $type,
  10.893 -	                      'automatic' => $options{'comment'},
  10.894 -			      'wrap'      => $options{'wrap'}||0,
  10.895 -			      'wrapcol'   => $options{'wrapcol'});
  10.896 -
  10.897 -#    if ($self->{TT}{po_in}->get_charset ne "CHARSET") {
  10.898 -#	Encode::from_to($transstring,$self->{TT}{po_in}->get_charset,
  10.899 -#	    $self->get_out_charset);
  10.900 -#    }
  10.901 -
  10.902 -    if ($options{'wrap'}||0) {
  10.903 -        $transstring =~ s/( *)$//s;
  10.904 -        my $trailing_spaces = $1||"";
  10.905 -        $transstring =~ s/ *$//gm;
  10.906 -        $transstring .= $trailing_spaces;
  10.907 -    }
  10.908 -
  10.909 -    return $transstring;
  10.910 -}
  10.911 -
  10.912 -=head2 Misc functions
  10.913 -
  10.914 -=over 4
  10.915 -
  10.916 -=item verbose()
  10.917 -
  10.918 -Returns if the verbose option was passed during the creation of the
  10.919 -TransTractor.
  10.920 -
  10.921 -=cut
  10.922 -
  10.923 -sub verbose {
  10.924 -    if (defined $_[1]) {
  10.925 -	$_[0]->{TT}{verbose} = $_[1];
  10.926 -    } else {
  10.927 -	return $_[0]->{TT}{verbose} || 0; # undef and 0 have the same meaning, but one generates warnings
  10.928 -    }
  10.929 -}
  10.930 -
  10.931 -=item debug()
  10.932 -
  10.933 -Returns if the debug option was passed during the creation of the
  10.934 -TransTractor.
  10.935 -
  10.936 -=cut
  10.937 -
  10.938 -sub debug {
  10.939 -    return $_[0]->{TT}{debug};
  10.940 -}
  10.941 -
  10.942 -=item detected_charset($)
  10.943 -
  10.944 -This tells TransTractor that a new charset (the first argument) has been
  10.945 -detected from the input document. It can usually be read from the document
  10.946 -header. Only the first charset will remain, coming either from the
  10.947 -process() arguments or detected from the document.
  10.948 -
  10.949 -=cut
  10.950 -
  10.951 -sub detected_charset {
  10.952 -    my ($self,$charset)=(shift,shift);
  10.953 -    unless (defined($self->{TT}{'file_in_charset'}) and
  10.954 -            length($self->{TT}{'file_in_charset'}) ) {
  10.955 -        $self->{TT}{'file_in_charset'}=$charset;
  10.956 -        if (defined $charset) {
  10.957 -            $self->{TT}{'file_in_encoder'}=find_encoding($charset);
  10.958 -        }
  10.959 -    }
  10.960 -
  10.961 -    if (defined $self->{TT}{'file_in_charset'} and
  10.962 -        length $self->{TT}{'file_in_charset'} and
  10.963 -        $self->{TT}{'file_in_charset'} !~ m/ascii/i) {
  10.964 -	$self->{TT}{ascii_input}=0;
  10.965 -    }
  10.966 -}
  10.967 -
  10.968 -=item get_out_charset()
  10.969 -
  10.970 -This function will return the charset that should be used in the output
  10.971 -document (usually useful to substitute the input document's detected charset
  10.972 -where it has been found).
  10.973 -
  10.974 -It will use the output charset specified in the command line. If it wasn't
  10.975 -specified, it will use the input po's charset, and if the input po has the
  10.976 -default "CHARSET", it will return the input document's charset, so that no
  10.977 -encoding is performed.
  10.978 -
  10.979 -=cut
  10.980 -
  10.981 -sub get_out_charset {
  10.982 -    my $self=shift;
  10.983 -    my $charset;
  10.984 -
  10.985 -    # Use the value specified at the command line
  10.986 -    if (defined($self->{TT}{'file_out_charset'}) and
  10.987 -	length($self->{TT}{'file_out_charset'})) {
  10.988 -	$charset=$self->{TT}{'file_out_charset'};
  10.989 -    } else {
  10.990 -	if ($self->{TT}{utf_mode} && $self->{TT}{ascii_input}) {
  10.991 -	    $charset="utf-8";
  10.992 -	} else {
  10.993 -	    $charset=$self->{TT}{po_in}->get_charset;
  10.994 -	    $charset=$self->{TT}{'file_in_charset'}
  10.995 -		if $charset eq "CHARSET" and
  10.996 -		    defined($self->{TT}{'file_in_charset'}) and
  10.997 -		    length($self->{TT}{'file_in_charset'});
  10.998 -	    $charset="ascii"
  10.999 -		if $charset eq "CHARSET";
 10.1000 -	}
 10.1001 -    }
 10.1002 -    return $charset;
 10.1003 -}
 10.1004 -
 10.1005 -=item recode_skipped_text($)
 10.1006 -
 10.1007 -This function returns the recoded text passed as argument, from the input
 10.1008 -document's charset to the output document's one. This isn't needed when
 10.1009 -translating a string (translate() recodes everything itself), but it is when
 10.1010 -you skip a string from the input document and you want the output document to
 10.1011 -be consistent with the global encoding.
 10.1012 -
 10.1013 -=cut
 10.1014 -
 10.1015 -sub recode_skipped_text {
 10.1016 -    my ($self,$text)=(shift,shift);
 10.1017 -    unless ($self->{TT}{'ascii_input'}) {
 10.1018 -	if(defined($self->{TT}{'file_in_charset'}) and
 10.1019 -	    length($self->{TT}{'file_in_charset'}) ) {
 10.1020 -	    $text = encode_from_to($text,
 10.1021 -	                           $self->{TT}{'file_in_encoder'},
 10.1022 -	                           find_encoding($self->get_out_charset));
 10.1023 -	} else {
 10.1024 -	    die wrap_mod("po4a", dgettext("po4a", "Couldn't determine the input document's charset. Please specify it on the command line. (non-ascii char at %s)"), $self->{TT}{non_ascii_ref})
 10.1025 -	}
 10.1026 -    }
 10.1027 -    return $text;
 10.1028 -}
 10.1029 -
 10.1030 -
 10.1031 -# encode_from_to($,$,$)
 10.1032 -#
 10.1033 -# Encode the given text from one encoding to another one.
 10.1034 -# It differs from Encode::from_to because it does not take the name of the
 10.1035 -# encoding in argument, but the encoders (as returned by the
 10.1036 -# Encode::find_encoding(<name>) method). Thus it permits to save a bunch
 10.1037 -# of call to find_encoding.
 10.1038 -#
 10.1039 -# If the "from" encoding is undefined, it is considered as UTF-8 (or
 10.1040 -# ascii).
 10.1041 -# If the "to" encoding is undefined, it is considered as UTF-8.
 10.1042 -#
 10.1043 -sub encode_from_to {
 10.1044 -    my ($text,$from,$to) = (shift,shift,shift);
 10.1045 -
 10.1046 -    if (not defined $from) {
 10.1047 -        # for ascii and UTF-8, no conversion needed to get an utf-8
 10.1048 -        # string.
 10.1049 -    } else {
 10.1050 -        $text = $from->decode($text, 0);
 10.1051 -    }
 10.1052 -
 10.1053 -    if (not defined $to) {
 10.1054 -        # Already in UTF-8, no conversion needed
 10.1055 -    } else {
 10.1056 -        $text = $to->encode($text, 0);
 10.1057 -    }
 10.1058 -
 10.1059 -    return $text;
 10.1060 -}
 10.1061 -
 10.1062 -=back
 10.1063 -
 10.1064 -=head1 FUTURE DIRECTIONS
 10.1065 -
 10.1066 -One shortcoming of the current TransTractor is that it can't handle
 10.1067 -translated document containing all languages, like debconf templates, or
 10.1068 -.desktop files.
 10.1069 -
 10.1070 -To address this problem, the only interface changes needed are:
 10.1071 -
 10.1072 -=over 2
 10.1073 -
 10.1074 -=item -
 10.1075 -
 10.1076 -take a hash as po_in_name (a list per language)
 10.1077 -
 10.1078 -=item -
 10.1079 -
 10.1080 -add an argument to translate to indicate the target language
 10.1081 -
 10.1082 -=item -
 10.1083 -
 10.1084 -make a pushline_all function, which would make pushline of its content for
 10.1085 -all language, using a map-like syntax:
 10.1086 -
 10.1087 -    $self->pushline_all({ "Description[".$langcode."]=".
 10.1088 -			  $self->translate($line,$ref,$langcode) 
 10.1089 -		        });
 10.1090 -
 10.1091 -=back
 10.1092 -
 10.1093 -Will see if it's enough ;)
 10.1094 -
 10.1095 -=head1 AUTHORS
 10.1096 -
 10.1097 - Denis Barbier <barbier@linuxfr.org>
 10.1098 - Martin Quinson (mquinson#debian.org)
 10.1099 - Jordi Vilalta <jvprat@gmail.com>
 10.1100 -
 10.1101 -=cut
 10.1102 -
 10.1103 -1;
    11.1 --- a/tools/po4a/lib/Locale/Po4a/Xml.pm	Mon Mar 30 17:50:48 2009 +0800
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,1973 +0,0 @@
    11.4 -#!/usr/bin/perl
    11.5 -
    11.6 -# Po4a::Xml.pm 
    11.7 -# 
    11.8 -# extract and translate translatable strings from XML documents.
    11.9 -# 
   11.10 -# This code extracts plain text from tags and attributes from generic
   11.11 -# XML documents, and it can be used as a base to build modules for
   11.12 -# XML-based documents.
   11.13 -#
   11.14 -# Copyright (c) 2004 by Jordi Vilalta  <jvprat@gmail.com>
   11.15 -# Copyright (c) 2008-2009 by Nicolas François  <nicolas.francois@centraliens.net>
   11.16 -#
   11.17 -# This program is free software; you can redistribute it and/or modify
   11.18 -# it under the terms of the GNU General Public License as published by
   11.19 -# the Free Software Foundation; either version 2 of the License, or
   11.20 -# (at your option) any later version.
   11.21 -#
   11.22 -# This program is distributed in the hope that it will be useful,
   11.23 -# but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.24 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.25 -# GNU General Public License for more details.
   11.26 -#
   11.27 -# You should have received a copy of the GNU General Public License
   11.28 -# along with this program; if not, write to the Free Software
   11.29 -# Foundation, Inc.,
   11.30 -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   11.31 -#
   11.32 -########################################################################
   11.33 -
   11.34 -=head1 NAME
   11.35 -
   11.36 -Locale::Po4a::Xml - Convert XML documents and derivates from/to PO files
   11.37 -
   11.38 -=head1 DESCRIPTION
   11.39 -
   11.40 -The po4a (po for anything) project goal is to ease translations (and more
   11.41 -interestingly, the maintenance of translations) using gettext tools on
   11.42 -areas where they were not expected like documentation.
   11.43 -
   11.44 -Locale::Po4a::Xml is a module to help the translation of XML documents into
   11.45 -other [human] languages. It can also be used as a base to build modules for
   11.46 -XML-based documents.
   11.47 -
   11.48 -=cut
   11.49 -
   11.50 -package Locale::Po4a::Xml;
   11.51 -
   11.52 -use 5.006;
   11.53 -use strict;
   11.54 -use warnings;
   11.55 -
   11.56 -require Exporter;
   11.57 -use vars qw(@ISA @EXPORT);
   11.58 -@ISA = qw(Locale::Po4a::TransTractor);
   11.59 -@EXPORT = qw(new initialize @tag_types);
   11.60 -
   11.61 -use Locale::Po4a::TransTractor;
   11.62 -use Locale::Po4a::Common;
   11.63 -use Carp qw(croak);
   11.64 -use File::Basename;
   11.65 -use File::Spec;
   11.66 -
   11.67 -#It will mantain the path from the root tag to the current one
   11.68 -my @path;
   11.69 -
   11.70 -#It will contain a list of external entities and their attached paths
   11.71 -my %entities;
   11.72 -
   11.73 -my @comments;
   11.74 -
   11.75 -sub shiftline {
   11.76 -    my $self = shift;
   11.77 -    # call Transtractor's shiftline
   11.78 -    my ($line,$ref) = $self->SUPER::shiftline();
   11.79 -    return ($line,$ref) if (not defined $line);
   11.80 -
   11.81 -    for my $k (keys %entities) {
   11.82 -        if ($line =~ m/^(.*?)&$k;(.*)$/s) {
   11.83 -            my ($before, $after) = ($1, $2);
   11.84 -            my $linenum=0;
   11.85 -            my @textentries;
   11.86 -
   11.87 -            open (my $in, $entities{$k})
   11.88 -                or croak wrap_mod("po4a::xml",
   11.89 -                                  dgettext("po4a", "Can't read from %s: %s"),
   11.90 -                                  $entities{$k}, $!);
   11.91 -            while (defined (my $textline = <$in>)) {
   11.92 -                $linenum++;
   11.93 -                my $textref=$entities{$k}.":$linenum";
   11.94 -                push @textentries, ($textline,$textref);
   11.95 -            }
   11.96 -            close $in
   11.97 -                or croak wrap_mod("po4a::xml",
   11.98 -                          dgettext("po4a", "Can't close %s after reading: %s"),
   11.99 -                                  $entities{$k}, $!);
  11.100 -
  11.101 -            push @textentries, ($after, $ref);
  11.102 -            $line = $before.(shift @textentries);
  11.103 -            $ref .= " ".(shift @textentries);
  11.104 -            $self->unshiftline(@textentries);
  11.105 -        }
  11.106 -    }
  11.107 -
  11.108 -    return ($line,$ref);
  11.109 -}
  11.110 -
  11.111 -sub read {
  11.112 -	my ($self,$filename)=@_;
  11.113 -	push @{$self->{DOCPOD}{infile}}, $filename;
  11.114 -	$self->Locale::Po4a::TransTractor::read($filename);
  11.115 -}
  11.116 -
  11.117 -sub parse {
  11.118 -	my $self=shift;
  11.119 -	map {$self->parse_file($_)} @{$self->{DOCPOD}{infile}};
  11.120 -}
  11.121 -
  11.122 -# @save_holders is a stack of references to ('paragraph', 'translation',
  11.123 -# 'sub_translations', 'open', 'close', 'folded_attributes') hashes, where:
  11.124 -# paragraph         is a reference to an array (see paragraph in the
  11.125 -#                   treat_content() subroutine) of strings followed by
  11.126 -#                   references.  It contains the @paragraph array as it was
  11.127 -#                   before the processing was interrupted by a tag instroducing
  11.128 -#                   a placeholder.
  11.129 -# translation       is the translation of this level up to now
  11.130 -# sub_translations  is a reference to an array of strings containing the
  11.131 -#                   translations which must replace the placeholders.
  11.132 -# open              is the tag which opened the placeholder.
  11.133 -# close             is the tag which closed the placeholder.
  11.134 -# folded_attributes is an hash of tags with their attributes (<tag attrs=...>
  11.135 -#                   strings), referenced by the folded tag id, which should
  11.136 -#                   replace the <tag po4a-id=id> strings in the current
  11.137 -#                   translation.
  11.138 -#
  11.139 -# If @save_holders only has 1 holder, then we are not processing the
  11.140 -# content of an holder, we are translating the document.
  11.141 -my @save_holders;
  11.142 -
  11.143 -
  11.144 -# If we are at the bottom of the stack and there is no <placeholder ...> in
  11.145 -# the current translation, we can push the translation in the translated
  11.146 -# document.
  11.147 -# Otherwise, we keep the translation in the current holder.
  11.148 -sub pushline {
  11.149 -	my ($self, $line) = (shift, shift);
  11.150 -
  11.151 -	my $holder = $save_holders[$#save_holders];
  11.152 -	my $translation = $holder->{'translation'};
  11.153 -	$translation .= $line;
  11.154 -
  11.155 -	while (    %{$holder->{folded_attributes}}
  11.156 -	       and $translation =~ m/^(.*)<([^>]+?)\s+po4a-id=([0-9]+)>(.*)$/s) {
  11.157 -		my $begin = $1;
  11.158 -		my $tag = $2;
  11.159 -		my $id = $3;
  11.160 -		my $end = $4;
  11.161 -		if (defined $holder->{folded_attributes}->{$id}) {
  11.162 -			# TODO: check if the tag is the same
  11.163 -			$translation = $begin.$holder->{folded_attributes}->{$id}.$end;
  11.164 -			delete $holder->{folded_attributes}->{$id};
  11.165 -		} else {
  11.166 -			# TODO: It will be hard to identify the location.
  11.167 -			#       => find a way to retrieve the reference.
  11.168 -			die wrap_mod("po4a::xml", dgettext("po4a", "'po4a-id=%d' in the translation does not exist in the original string (or 'po4a-id=%d' used twice in the translation)."), $id, $id);
  11.169 -		}
  11.170 -	}
  11.171 -# TODO: check that %folded_attributes is empty at some time
  11.172 -# => in translate_paragraph?
  11.173 -
  11.174 -	if (   ($#save_holders > 0)
  11.175 -	    or ($translation =~ m/<placeholder\s+type="[^"]+"\s+id="(\d+)"\s*\/>/s)) {
  11.176 -		$holder->{'translation'} = $translation;
  11.177 -	} else {
  11.178 -		$self->SUPER::pushline($translation);
  11.179 -		$holder->{'translation'} = '';
  11.180 -	}
  11.181 -}
  11.182 -
  11.183 -=head1 TRANSLATING WITH PO4A::XML
  11.184 -
  11.185 -This module can be used directly to handle generic XML documents.  This will
  11.186 -extract all tag's content, and no attributes, since it's where the text is
  11.187 -written in most XML based documents.
  11.188 -
  11.189 -There are some options (described in the next section) that can customize
  11.190 -this behavior.  If this doesn't fit to your document format you're encouraged
  11.191 -to write your own module derived from this, to describe your format's details.
  11.192 -See the section "Writing derivate modules" below, for the process description.
  11.193 -
  11.194 -=cut
  11.195 -
  11.196 -#
  11.197 -# Parse file and translate it
  11.198 -#
  11.199 -sub parse_file {
  11.200 -	my ($self,$filename) = @_;
  11.201 -	my $eof = 0;
  11.202 -
  11.203 -	while (!$eof) {
  11.204 -		# We get all the text until the next breaking tag (not
  11.205 -		# inline) and translate it
  11.206 -		$eof = $self->treat_content;
  11.207 -		if (!$eof) {
  11.208 -			# And then we treat the following breaking tag
  11.209 -			$eof = $self->treat_tag;
  11.210 -		}
  11.211 -	}
  11.212 -}
  11.213 -
  11.214 -=head1 OPTIONS ACCEPTED BY THIS MODULE
  11.215 -
  11.216 -The global debug option causes this module to show the excluded strings, in
  11.217 -order to see if it skips something important.
  11.218 -
  11.219 -These are this module's particular options:
  11.220 -
  11.221 -=over 4
  11.222 -
  11.223 -=item B<nostrip>
  11.224 -
  11.225 -Prevents it to strip the spaces around the extracted strings.
  11.226 -
  11.227 -=item B<wrap>
  11.228 -
  11.229 -Canonizes the string to translate, considering that whitespaces are not
  11.230 -important, and wraps the translated document. This option can be overridden
  11.231 -by custom tag options. See the "tags" option below.
  11.232 -
  11.233 -=item B<caseinsensitive>
  11.234 -
  11.235 -It makes the tags and attributes searching to work in a case insensitive
  11.236 -way.  If it's defined, it will treat E<lt>BooKE<gt>laNG and E<lt>BOOKE<gt>Lang as E<lt>bookE<gt>lang.
  11.237 -
  11.238 -=item B<includeexternal>
  11.239 -
  11.240 -When defined, external entities are included in the generated (translated)
  11.241 -document, and for the extraction of strings.  If it's not defined, you
  11.242 -will have to translate external entities separately as independent
  11.243 -documents.
  11.244 -
  11.245 -=item B<ontagerror>
  11.246 -
  11.247 -This option defines the behavior of the module when it encounter a invalid
  11.248 -Xml syntax (a closing tag which does not match the last opening tag, or a
  11.249 -tag's attribute without value).
  11.250 -It can take the following values:
  11.251 -
  11.252 -=over
  11.253 -
  11.254 -=item I<fail>
  11.255 -
  11.256 -This is the default value.
  11.257 -The module will exit with an error.
  11.258 -
  11.259 -=item I<warn>
  11.260 -
  11.261 -The module will continue, and will issue a warning.
  11.262 -
  11.263 -=item I<silent>
  11.264 -
  11.265 -The module will continue without any warnings.
  11.266 -
  11.267 -=back
  11.268 -
  11.269 -Be careful when using this option.
  11.270 -It is generally recommended to fix the input file.
  11.271 -
  11.272 -=item B<tagsonly>
  11.273 -
  11.274 -Extracts only the specified tags in the "tags" option.  Otherwise, it
  11.275 -will extract all the tags except the ones specified.
  11.276 -
  11.277 -Note: This option is deprecated.
  11.278 -
  11.279 -=item B<doctype>
  11.280 -
  11.281 -String that will try to match with the first line of the document's doctype
  11.282 -(if defined). If it doesn't, a warning will indicate that the document
  11.283 -might be of a bad type.
  11.284 -
  11.285 -=item B<tags>
  11.286 -
  11.287 -Space-separated list of tags you want to translate or skip.  By default,
  11.288 -the specified tags will be excluded, but if you use the "tagsonly" option,
  11.289 -the specified tags will be the only ones included.  The tags must be in the
  11.290 -form E<lt>aaaE<gt>, but you can join some (E<lt>bbbE<gt>E<lt>aaaE<gt>) to say that the content of
  11.291 -the tag E<lt>aaaE<gt> will only be translated when it's into a E<lt>bbbE<gt> tag.
  11.292 -
  11.293 -You can also specify some tag options putting some characters in front of
  11.294 -the tag hierarchy. For example, you can put 'w' (wrap) or 'W' (don't wrap)
  11.295 -to override the default behavior specified by the global "wrap" option.
  11.296 -
  11.297 -Example: WE<lt>chapterE<gt>E<lt>titleE<gt>
  11.298 -
  11.299 -Note: This option is deprecated.
  11.300 -You should use the B<translated> and B<untranslated> options instead.
  11.301 -
  11.302 -=item B<attributes>
  11.303 -
  11.304 -Space-separated list of tag's attributes you want to translate.  You can
  11.305 -specify the attributes by their name (for example, "lang"), but you can
  11.306 -prefix it with a tag hierarchy, to specify that this attribute will only be
  11.307 -translated when it's into the specified tag. For example: E<lt>bbbE<gt>E<lt>aaaE<gt>lang
  11.308 -specifies that the lang attribute will only be translated if it's into an
  11.309 -E<lt>aaaE<gt> tag, and it's into a E<lt>bbbE<gt> tag.
  11.310 -
  11.311 -=item B<foldattributes>
  11.312 -
  11.313 -Do not translate attributes in inline tags.
  11.314 -Instead, replace all attributes of a tag by po4a-id=<id>.
  11.315 -
  11.316 -This is useful when attributes shall not be translated, as this simplifies the
  11.317 -strings for translators, and avoids typos.
  11.318 -
  11.319 -=item B<break>
  11.320 -
  11.321 -Space-separated list of tags which should break the sequence.
  11.322 -By default, all tags break the sequence.
  11.323 -
  11.324 -The tags must be in the form <aaa>, but you can join some
  11.325 -(<bbb><aaa>), if a tag (<aaa>) should only be considered 
  11.326 -when it's into another tag (<bbb>).
  11.327 -
  11.328 -=item B<inline>
  11.329 -
  11.330 -Space-separated list of tags which should be treated as inline.
  11.331 -By default, all tags break the sequence.
  11.332 -
  11.333 -The tags must be in the form <aaa>, but you can join some
  11.334 -(<bbb><aaa>), if a tag (<aaa>) should only be considered 
  11.335 -when it's into another tag (<bbb>).
  11.336 -
  11.337 -=item B<placeholder>
  11.338 -
  11.339 -Space-separated list of tags which should be treated as placeholders.
  11.340 -Placeholders do not break the sequence, but the content of placeholders is
  11.341 -translated separately.
  11.342 -
  11.343 -The location of the placeholder in its blocks will be marked with a string
  11.344 -similar to:
  11.345 -
  11.346 -  <placeholder type=\"footnote\" id=\"0\"/>
  11.347 -
  11.348 -The tags must be in the form <aaa>, but you can join some
  11.349 -(<bbb><aaa>), if a tag (<aaa>) should only be considered 
  11.350 -when it's into another tag (<bbb>).
  11.351 -
  11.352 -=item B<nodefault>
  11.353 -
  11.354 -Space separated list of tags that the module should not try to set by
  11.355 -default in any category.
  11.356 -
  11.357 -=item B<cpp>
  11.358 -
  11.359 -Support C preprocessor directives.
  11.360 -When this option is set, po4a will consider preprocessor directives as
  11.361 -paragraph separators.
  11.362 -This is important if the XML file must be preprocessed because otherwise
  11.363 -the directives may be inserted in the middle of lines if po4a consider it
  11.364 -belong to the current paragraph, and they won't be recognized by the
  11.365 -preprocessor.
  11.366 -Note: the preprocessor directives must only appear between tags
  11.367 -(they must not break a tag).
  11.368 -
  11.369 -=item B<translated>
  11.370 -
  11.371 -Space-separated list of tags you want to translate.
  11.372 -
  11.373 -The tags must be in the form <aaa>, but you can join some
  11.374 -(<bbb><aaa>), if a tag (<aaa>) should only be considered 
  11.375 -when it's into another tag (<bbb>).
  11.376 -
  11.377 -You can also specify some tag options putting some characters in front of
  11.378 -the tag hierarchy. For example, you can put 'w' (wrap) or 'W' (don't wrap)
  11.379 -to overide the default behavior specified by the global "wrap" option.
  11.380 -
  11.381 -Example: WE<lt>chapterE<gt>E<lt>titleE<gt>
  11.382 -
  11.383 -=item B<untranslated>
  11.384 -
  11.385 -Space-separated list of tags you do not want to translate.
  11.386 -
  11.387 -The tags must be in the form <aaa>, but you can join some
  11.388 -(<bbb><aaa>), if a tag (<aaa>) should only be considered 
  11.389 -when it's into another tag (<bbb>).
  11.390 -
  11.391 -=item B<defaulttranslateoption>
  11.392 -
  11.393 -The default categories for tags that are not in any of the translated,
  11.394 -untranslated, break, inline, or placeholder.
  11.395 -
  11.396 -This is a set of letters:
  11.397 -
  11.398 -=over
  11.399 -
  11.400 -=item I<w>
  11.401 -
  11.402 -Tags should be translated and content can be re-wrapped.
  11.403 -
  11.404 -=item I<W>
  11.405 -
  11.406 -Tags should be translated and content should not be re-wrapped.
  11.407 -
  11.408 -=item I<i>
  11.409 -
  11.410 -Tags should be translated inline.
  11.411 -
  11.412 -=item I<p>
  11.413 -
  11.414 -Tags should be translated as placeholders.
  11.415 -
  11.416 -=back
  11.417 -
  11.418 -=back
  11.419 -
  11.420 -=cut
  11.421 -# TODO: defaulttranslateoption
  11.422 -# w => indicate that it is only valid for translatable tags and do not
  11.423 -#      care about inline/break/placeholder?
  11.424 -# ...
  11.425 -
  11.426 -sub initialize {
  11.427 -	my $self = shift;
  11.428 -	my %options = @_;
  11.429 -
  11.430 -	# Reset the path
  11.431 -	@path = ();
  11.432 -
  11.433 -	# Initialize the stack of holders
  11.434 -	my @paragraph = ();
  11.435 -	my @sub_translations = ();
  11.436 -	my %folded_attributes;
  11.437 -	my %holder = ('paragraph' => \@paragraph,
  11.438 -	              'translation' => "",
  11.439 -	              'sub_translations' => \@sub_translations,
  11.440 -	              'folded_attributes' => \%folded_attributes);
  11.441 -	@save_holders = (\%holder);
  11.442 -
  11.443 -	$self->{options}{'nostrip'}=0;
  11.444 -	$self->{options}{'wrap'}=0;
  11.445 -	$self->{options}{'caseinsensitive'}=0;
  11.446 -	$self->{options}{'tagsonly'}=0;
  11.447 -	$self->{options}{'tags'}='';
  11.448 -	$self->{options}{'break'}='';
  11.449 -	$self->{options}{'translated'}='';
  11.450 -	$self->{options}{'untranslated'}='';
  11.451 -	$self->{options}{'defaulttranslateoption'}='';
  11.452 -	$self->{options}{'attributes'}='';
  11.453 -	$self->{options}{'foldattributes'}=0;
  11.454 -	$self->{options}{'inline'}='';
  11.455 -	$self->{options}{'placeholder'}='';
  11.456 -	$self->{options}{'doctype'}='';
  11.457 -	$self->{options}{'nodefault'}='';
  11.458 -	$self->{options}{'includeexternal'}=0;
  11.459 -	$self->{options}{'ontagerror'}="fail";
  11.460 -	$self->{options}{'cpp'}=0;
  11.461 -
  11.462 -	$self->{options}{'verbose'}='';
  11.463 -	$self->{options}{'debug'}='';
  11.464 -
  11.465 -	foreach my $opt (keys %options) {
  11.466 -		if ($options{$opt}) {
  11.467 -			die wrap_mod("po4a::xml",
  11.468 -				dgettext("po4a", "Unknown option: %s"), $opt)
  11.469 -				unless exists $self->{options}{$opt};
  11.470 -			$self->{options}{$opt} = $options{$opt};
  11.471 -		}
  11.472 -	}
  11.473 -	# Default options set by modules. Forbidden for users.
  11.474 -	$self->{options}{'_default_translated'}='';
  11.475 -	$self->{options}{'_default_untranslated'}='';
  11.476 -	$self->{options}{'_default_break'}='';
  11.477 -	$self->{options}{'_default_inline'}='';
  11.478 -	$self->{options}{'_default_placeholder'}='';
  11.479 -	$self->{options}{'_default_attributes'}='';
  11.480 -
  11.481 -	#It will maintain the list of the translatable tags
  11.482 -	$self->{tags}=();
  11.483 -	$self->{translated}=();
  11.484 -	$self->{untranslated}=();
  11.485 -	#It will maintain the list of the translatable attributes
  11.486 -	$self->{attributes}=();
  11.487 -	#It will maintain the list of the breaking tags
  11.488 -	$self->{break}=();
  11.489 -	#It will maintain the list of the inline tags
  11.490 -	$self->{inline}=();
  11.491 -	#It will maintain the list of the placeholder tags
  11.492 -	$self->{placeholder}=();
  11.493 -	#list of the tags that must not be set in the tags or inline category
  11.494 -	#by this module or sub-module (unless specified in an option)
  11.495 -	$self->{nodefault}=();
  11.496 -
  11.497 -	$self->treat_options;
  11.498 -}
  11.499 -
  11.500 -=head1 WRITING DERIVATE MODULES
  11.501 -
  11.502 -=head2 DEFINE WHAT TAGS AND ATTRIBUTES TO TRANSLATE
  11.503 -
  11.504 -The simplest customization is to define which tags and attributes you want
  11.505 -the parser to translate.  This should be done in the initialize function.
  11.506 -First you should call the main initialize, to get the command-line options,
  11.507 -and then, append your custom definitions to the options hash.  If you want
  11.508 -to treat some new options from command line, you should define them before
  11.509 -calling the main initialize:
  11.510 -
  11.511 -  $self->{options}{'new_option'}='';
  11.512 -  $self->SUPER::initialize(%options);
  11.513 -  $self->{options}{'_default_translated'}.=' <p> <head><title>';
  11.514 -  $self->{options}{'attributes'}.=' <p>lang id';
  11.515 -  $self->{options}{'_default_inline'}.=' <br>';
  11.516 -  $self->treat_options;
  11.517 -
  11.518 -You should use the B<_default_inline>, B<_default_break>,
  11.519 -B<_default_placeholder>, B<_default_translated>, B<_default_untranslated>,
  11.520 -and B<_default_attributes> options in derivated modules. This allow users
  11.521 -to override the default behavior defined in your module with command line
  11.522 -options.
  11.523 -
  11.524 -=head2 OVERRIDING THE found_string FUNCTION
  11.525 -
  11.526 -Another simple step is to override the function "found_string", which
  11.527 -receives the extracted strings from the parser, in order to translate them.
  11.528 -There you can control which strings you want to translate, and perform
  11.529 -transformations to them before or after the translation itself.
  11.530 -
  11.531 -It receives the extracted text, the reference on where it was, and a hash
  11.532 -that contains extra information to control what strings to translate, how
  11.533 -to translate them and to generate the comment.
  11.534 -
  11.535 -The content of these options depends on the kind of string it is (specified in an 
  11.536 -entry of this hash):
  11.537 -
  11.538 -=over
  11.539 -
  11.540 -=item type="tag"
  11.541 -
  11.542 -The found string is the content of a translatable tag. The entry "tag_options"
  11.543 -contains the option characters in front of the tag hierarchy in the module
  11.544 -"tags" option.
  11.545 -
  11.546 -=item type="attribute"
  11.547 -
  11.548 -Means that the found string is the value of a translatable attribute. The
  11.549 -entry "attribute" has the name of the attribute.
  11.550 -
  11.551 -=back
  11.552 -
  11.553 -It must return the text that will replace the original in the translated
  11.554 -document. Here's a basic example of this function:
  11.555 -
  11.556 -  sub found_string {
  11.557 -    my ($self,$text,$ref,$options)=@_;
  11.558 -    $text = $self->translate($text,$ref,"type ".$options->{'type'},
  11.559 -      'wrap'=>$self->{options}{'wrap'});
  11.560 -    return $text;
  11.561 -  }
  11.562 -
  11.563 -There's another simple example in the new Dia module, which only filters
  11.564 -some strings.
  11.565 -
  11.566 -=cut
  11.567 -
  11.568 -sub found_string {
  11.569 -	my ($self,$text,$ref,$options)=@_;
  11.570 -
  11.571 -	if ($text =~ m/^\s*$/s) {
  11.572 -		return $text;
  11.573 -	}
  11.574 -
  11.575 -	my $comment;
  11.576 -	my $wrap = $self->{options}{'wrap'};
  11.577 -
  11.578 -	if ($options->{'type'} eq "tag") {
  11.579 -		$comment = "Content of: ".$self->get_path;
  11.580 -
  11.581 -		if($options->{'tag_options'} =~ /w/) {
  11.582 -			$wrap = 1;
  11.583 -		}
  11.584 -		if($options->{'tag_options'} =~ /W/) {
  11.585 -			$wrap = 0;
  11.586 -		}
  11.587 -	} elsif ($options->{'type'} eq "attribute") {
  11.588 -		$comment = "Attribute '".$options->{'attribute'}."' of: ".$self->get_path;
  11.589 -	} elsif ($options->{'type'} eq "CDATA") {
  11.590 -		$comment = "CDATA";
  11.591 -		$wrap = 0;
  11.592 -	} else {
  11.593 -		die wrap_ref_mod($ref, "po4a::xml", dgettext("po4a", "Internal error: unknown type identifier '%s'."), $options->{'type'});
  11.594 -	}
  11.595 -	$text = $self->translate($text,$ref,$comment,'wrap'=>$wrap, comment => $options->{'comments'});
  11.596 -	return $text;
  11.597 -}
  11.598 -
  11.599 -=head2 MODIFYING TAG TYPES (TODO)
  11.600 -
  11.601 -This is a more complex one, but it enables a (almost) total customization.
  11.602 -It's based in a list of hashes, each one defining a tag type's behavior. The
  11.603 -list should be sorted so that the most general tags are after the most
  11.604 -concrete ones (sorted first by the beginning and then by the end keys). To
  11.605 -define a tag type you'll have to make a hash with the following keys:
  11.606 -
  11.607 -=over 4
  11.608 -
  11.609 -=item beginning
  11.610 -
  11.611 -Specifies the beginning of the tag, after the "E<lt>".
  11.612 -
  11.613 -=item end
  11.614 -
  11.615 -Specifies the end of the tag, before the "E<gt>".
  11.616 -
  11.617 -=item breaking
  11.618 -
  11.619 -It says if this is a breaking tag class.  A non-breaking (inline) tag is one
  11.620 -that can be taken as part of the content of another tag.  It can take the
  11.621 -values false (0), true (1) or undefined.  If you leave this undefined, you'll
  11.622 -have to define the f_breaking function that will say whether a concrete tag of
  11.623 -this class is a breaking tag or not.
  11.624 -
  11.625 -=item f_breaking
  11.626 -
  11.627 -It's a function that will tell if the next tag is a breaking one or not.  It
  11.628 -should be defined if the "breaking" option is not.
  11.629 -
  11.630 -=item f_extract
  11.631 -
  11.632 -If you leave this key undefined, the generic extraction function will have to
  11.633 -extract the tag itself.  It's useful for tags that can have other tags or
  11.634 -special structures in them, so that the main parser doesn't get mad.  This
  11.635 -function receives a boolean that says if the tag should be removed from the
  11.636 -input stream or not.
  11.637 -
  11.638 -=item f_translate
  11.639 -
  11.640 -This function receives the tag (in the get_string_until() format) and returns
  11.641 -the translated tag (translated attributes or all needed transformations) as a
  11.642 -single string.
  11.643 -
  11.644 -=back
  11.645 -
  11.646 -=cut
  11.647 -
  11.648 -##### Generic XML tag types #####' 
  11.649 -
  11.650 -our @tag_types = ( 
  11.651 -	{	beginning	=> "!--#",
  11.652 -		end		=> "--",
  11.653 -		breaking	=> 0,
  11.654 -		f_extract	=> \&tag_extract_comment,
  11.655 -		f_translate	=> \&tag_trans_comment},
  11.656 -	{	beginning	=> "!--",
  11.657 -		end		=> "--",
  11.658 -		breaking	=> 0,
  11.659 -		f_extract	=> \&tag_extract_comment,
  11.660 -		f_translate	=> \&tag_trans_comment},
  11.661 -	{	beginning	=> "?xml",
  11.662 -		end		=> "?",
  11.663 -		breaking	=> 1,
  11.664 -		f_translate	=> \&tag_trans_xmlhead},
  11.665 -	{	beginning	=> "?",
  11.666 -		end		=> "?",
  11.667 -		breaking	=> 1,
  11.668 -		f_translate	=> \&tag_trans_procins},
  11.669 -	{	beginning	=> "!DOCTYPE",
  11.670 -		end		=> "",
  11.671 -		breaking	=> 1,
  11.672 -		f_extract	=> \&tag_extract_doctype,
  11.673 -		f_translate	=> \&tag_trans_doctype},
  11.674 -	{	beginning	=> "![CDATA[",
  11.675 -		end		=> "",
  11.676 -		breaking	=> 1,
  11.677 -		f_extract	=> \&CDATA_extract,
  11.678 -		f_translate	=> \&CDATA_trans},
  11.679 -	{	beginning	=> "/",
  11.680 -		end		=> "",
  11.681 -		f_breaking	=> \&tag_break_close,
  11.682 -		f_translate	=> \&tag_trans_close},
  11.683 -	{	beginning	=> "",
  11.684 -		end		=> "/",
  11.685 -		f_breaking	=> \&tag_break_alone,
  11.686 -		f_translate	=> \&tag_trans_alone},
  11.687 -	{	beginning	=> "",
  11.688 -		end		=> "",
  11.689 -		f_breaking	=> \&tag_break_open,
  11.690 -		f_translate	=> \&tag_trans_open}
  11.691 -);
  11.692 -
  11.693 -sub tag_extract_comment {
  11.694 -	my ($self,$remove)=(shift,shift);
  11.695 -	my ($eof,@tag)=$self->get_string_until('-->',{include=>1,remove=>$remove});
  11.696 -	return ($eof,@tag);
  11.697 -}
  11.698 -
  11.699 -sub tag_trans_comment {
  11.700 -	my ($self,@tag)=@_;
  11.701 -	return $self->join_lines(@tag);
  11.702 -}
  11.703 -
  11.704 -sub tag_trans_xmlhead {
  11.705 -	my ($self,@tag)=@_;
  11.706 -
  11.707 -	# We don't have to translate anything from here: throw away references
  11.708 -	my $tag = $self->join_lines(@tag);
  11.709 -	$tag =~ /encoding=(("|')|)(.*?)(\s|\2)/s;
  11.710 -	my $in_charset=$3;
  11.711 -	$self->detected_charset($in_charset);
  11.712 -	my $out_charset=$self->get_out_charset;
  11.713 -
  11.714 -	if (defined $in_charset) {
  11.715 -		$tag =~ s/$in_charset/$out_charset/;
  11.716 -	} else {
  11.717 -		if ($tag =~ m/standalone/) {
  11.718 -			$tag =~ s/(standalone)/encoding="$out_charset" $1/;
  11.719 -		} else {
  11.720 -			$tag.= " encoding=\"$out_charset\"";
  11.721 -		}
  11.722 -	}
  11.723 -
  11.724 -	return $tag;
  11.725 -}
  11.726 -
  11.727 -sub tag_trans_procins {
  11.728 -	my ($self,@tag)=@_;
  11.729 -	return $self->join_lines(@tag);
  11.730 -}
  11.731 -
  11.732 -sub tag_extract_doctype {
  11.733 -	my ($self,$remove)=(shift,shift);
  11.734 -
  11.735 -	# Check if there is an internal subset (between []).
  11.736 -	my ($eof,@tag)=$self->get_string_until('>',{include=>1,unquoted=>1});
  11.737 -	my $parity = 0;
  11.738 -	my $paragraph = "";
  11.739 -	map { $parity = 1 - $parity; $paragraph.= $parity?$_:""; } @tag;
  11.740 -	my $found = 0;
  11.741 -	if ($paragraph =~ m/<.*\[.*</s) {
  11.742 -		$found = 1
  11.743 -	}
  11.744 -
  11.745 -	if (not $found) {
  11.746 -		($eof,@tag)=$self->get_string_until('>',{include=>1,remove=>$remove,unquoted=>1});
  11.747 -	} else {
  11.748 -		($eof,@tag)=$self->get_string_until(']\s*>',{include=>1,remove=>$remove,unquoted=>1,regex=>1});
  11.749 -	}
  11.750 -	return ($eof,@tag);
  11.751 -}
  11.752 -
  11.753 -sub tag_trans_doctype {
  11.754 -# This check is not really reliable.  There are system and public
  11.755 -# identifiers.  Only the public one could be checked reliably.
  11.756 -	my ($self,@tag)=@_;
  11.757 -	if (defined $self->{options}{'doctype'} ) {
  11.758 -		my $doctype = $self->{options}{'doctype'};
  11.759 -		if ( $tag[0] !~ /\Q$doctype\E/i ) {
  11.760 -			warn wrap_ref_mod($tag[1], "po4a::xml", dgettext("po4a", "Bad document type. '%s' expected. You can fix this warning with a -o doctype option, or ignore this check with -o doctype=\"\"."), $doctype);
  11.761 -		}
  11.762 -	}
  11.763 -	my $i = 0;
  11.764 -	my $basedir = $tag[1];
  11.765 -	$basedir =~ s/:[0-9]+$//;
  11.766 -	$basedir = dirname($basedir);
  11.767 -
  11.768 -	while ( $i < $#tag ) {
  11.769 -		my $t = $tag[$i];
  11.770 -		my $ref = $tag[$i+1];
  11.771 -		if ( $t =~ /^(\s*<!ENTITY\s+)(.*)$/is ) {
  11.772 -			my $part1 = $1;
  11.773 -			my $part2 = $2;
  11.774 -			my $includenow = 0;
  11.775 -			my $file = 0;
  11.776 -			my $name = "";
  11.777 -			if ($part2 =~ /^(%\s+)(.*)$/s ) {
  11.778 -				$part1.= $1;
  11.779 -				$part2 = $2;
  11.780 -				$includenow = 1;
  11.781 -			}
  11.782 -			$part2 =~ /^(\S+)(\s+)(.*)$/s;
  11.783 -			$name = $1;
  11.784 -			$part1.= $1.$2;
  11.785 -			$part2 = $3;
  11.786 -			if ( $part2 =~ /^(SYSTEM\s+)(.*)$/is ) {
  11.787 -				$part1.= $1;
  11.788 -				$part2 = $2;
  11.789 -				$file = 1;
  11.790 -				if ($self->{options}{'includeexternal'}) {
  11.791 -					$entities{$name} = $part2;
  11.792 -					$entities{$name} =~ s/^"?(.*?)".*$/$1/s;
  11.793 -					$entities{$name} = File::Spec->catfile($basedir, $entities{$name});
  11.794 -				}
  11.795 -			}
  11.796 -			if ((not $file) and (not $includenow)) {
  11.797 -			    if ($part2 =~ m/^\s*(["'])(.*)\1(\s*>.*)$/s) {
  11.798 -				my $comment = "Content of the $name entity";
  11.799 -				my $quote = $1;
  11.800 -				my $text = $2;
  11.801 -				$part2 = $3;
  11.802 -				$text = $self->translate($text,
  11.803 -				                         $ref,
  11.804 -				                         $comment,
  11.805 -				                         'wrap'=>1);
  11.806 -				$t = $part1."$quote$text$quote$part2";
  11.807 -			    }
  11.808 -			}
  11.809 -#			print $part1."\n";
  11.810 -#			print $name."\n";
  11.811 -#			print $part2."\n";
  11.812 -		}
  11.813 -		$tag[$i] = $t;
  11.814 -		$i += 2;
  11.815 -	}
  11.816 -	return $self->join_lines(@tag);
  11.817 -}
  11.818 -
  11.819 -sub tag_break_close {
  11.820 -	my ($self,@tag)=@_;
  11.821 -	my $struct = $self->get_path;
  11.822 -	my $options = $self->get_translate_options($struct);
  11.823 -	if ($options =~ m/[ip]/) {
  11.824 -		return 0;
  11.825 -	} else {
  11.826 -		return 1;
  11.827 -	}
  11.828 -}
  11.829 -
  11.830 -sub tag_trans_close {
  11.831 -	my ($self,@tag)=@_;
  11.832 -	my $name = $self->get_tag_name(@tag);
  11.833 -
  11.834 -	my $test = pop @path;
  11.835 -	if (!defined($test) || $test ne $name ) {
  11.836 -		my $ontagerror = $self->{options}{'ontagerror'};
  11.837 -		if ($ontagerror eq "warn") {
  11.838 -			warn wrap_ref_mod($tag[1], "po4a::xml", dgettext("po4a", "Unexpected closing tag </%s> found. The main document may be wrong.  Continuing..."), $name);
  11.839 -		} elsif ($ontagerror ne "silent") {
  11.840 -			die wrap_ref_mod($tag[1], "po4a::xml", dgettext("po4a", "Unexpected closing tag </%s> found. The main document may be wrong."), $name);
  11.841 -		}
  11.842 -	}
  11.843 -	return $self->join_lines(@tag);
  11.844 -}
  11.845 -
  11.846 -sub CDATA_extract {
  11.847 -	my ($self,$remove)=(shift,shift);
  11.848 -        my ($eof, @tag) = $self->get_string_until(']]>',{include=>1,unquoted=>0,remove=>$remove});
  11.849 -
  11.850 -	return ($eof, @tag);
  11.851 -}
  11.852 -
  11.853 -sub CDATA_trans {
  11.854 -	my ($self,@tag)=@_;
  11.855 -	return $self->found_string($self->join_lines(@tag),
  11.856 -	                           $tag[1],
  11.857 -	                           {'type' => "CDATA"});
  11.858 -}
  11.859 -
  11.860 -sub tag_break_alone {
  11.861 -	my ($self,@tag)=@_;
  11.862 -	my $struct = $self->get_path($self->get_tag_name(@tag));
  11.863 -	if ($self->get_translate_options($struct) =~ m/i/) {
  11.864 -		return 0;
  11.865 -	} else {
  11.866 -		return 1;
  11.867 -	}
  11.868 -}
  11.869 -
  11.870 -sub tag_trans_alone {
  11.871 -	my ($self,@tag)=@_;
  11.872 -	my $name = $self->get_tag_name(@tag);
  11.873 -	push @path, $name;
  11.874 -
  11.875 -	$name = $self->treat_attributes(@tag);
  11.876 -
  11.877 -	pop @path;
  11.878 -	return $name;
  11.879 -}
  11.880 -
  11.881 -sub tag_break_open {
  11.882 -	my ($self,@tag)=@_;
  11.883 -	my $struct = $self->get_path($self->get_tag_name(@tag));
  11.884 -	my $options = $self->get_translate_options($struct);
  11.885 -	if ($options =~ m/[ip]/) {
  11.886 -		return 0;
  11.887 -	} else {
  11.888 -		return 1;
  11.889 -	}
  11.890 -}
  11.891 -
  11.892 -sub tag_trans_open {
  11.893 -	my ($self,@tag)=@_;
  11.894 -	my $name = $self->get_tag_name(@tag);
  11.895 -	push @path, $name;
  11.896 -
  11.897 -	$name = $self->treat_attributes(@tag);
  11.898 -
  11.899 -	return $name;
  11.900 -}
  11.901 -
  11.902 -##### END of Generic XML tag types #####
  11.903 -
  11.904 -=head1 INTERNAL FUNCTIONS used to write derivated parsers
  11.905 -
  11.906 -=head2 WORKING WITH TAGS
  11.907 -
  11.908 -=over 4
  11.909 -
  11.910 -=item get_path()
  11.911 -
  11.912 -This function returns the path to the current tag from the document's root,
  11.913 -in the form E<lt>htmlE<gt>E<lt>bodyE<gt>E<lt>pE<gt>.
  11.914 -
  11.915 -An additional array of tags (without brackets) can be passed in argument.
  11.916 -These path elements are added to the end of the current path.
  11.917 -
  11.918 -=cut
  11.919 -
  11.920 -sub get_path {
  11.921 -	my $self = shift;
  11.922 -	my @add = @_;
  11.923 -	if ( @path > 0 or @add > 0 ) {
  11.924 -		return "<".join("><",@path,@add).">";
  11.925 -	} else {
  11.926 -		return "outside any tag (error?)";
  11.927 -	}
  11.928 -}
  11.929 -
  11.930 -=item tag_type()
  11.931 -
  11.932 -This function returns the index from the tag_types list that fits to the next
  11.933 -tag in the input stream, or -1 if it's at the end of the input file.
  11.934 -
  11.935 -=cut
  11.936 -
  11.937 -sub tag_type {
  11.938 -	my $self = shift;
  11.939 -	my ($line,$ref) = $self->shiftline();
  11.940 -	my ($match1,$match2);
  11.941 -	my $found = 0;
  11.942 -	my $i = 0;
  11.943 -
  11.944 -	if (!defined($line)) { return -1; }
  11.945 -
  11.946 -	$self->unshiftline($line,$ref);
  11.947 -	my ($eof,@lines) = $self->get_string_until(">",{include=>1,unquoted=>1});
  11.948 -	my $line2 = $self->join_lines(@lines);
  11.949 -	while (!$found && $i < @tag_types) {
  11.950 -		($match1,$match2) = ($tag_types[$i]->{beginning},$tag_types[$i]->{end});
  11.951 -		if ($line =~ /^<\Q$match1\E/) {
  11.952 -			if (!defined($tag_types[$i]->{f_extract})) {
  11.953 -#print substr($line2,length($line2)-1-length($match2),1+length($match2))."\n";
  11.954 -				if (defined($line2) and $line2 =~ /\Q$match2\E>$/) {
  11.955 -					$found = 1;
  11.956 -#print "YES: <".$match1." ".$match2.">\n";
  11.957 -				} else {
  11.958 -#print "NO: <".$match1." ".$match2.">\n";
  11.959 -					$i++;
  11.960 -				}
  11.961 -			} else {
  11.962 -				$found = 1;
  11.963 -			}
  11.964 -		} else {
  11.965 -			$i++;
  11.966 -		}
  11.967 -	}
  11.968 -	if (!$found) {
  11.969 -		#It should never enter here, unless you undefine the most
  11.970 -		#general tags (as <...>)
  11.971 -		die "po4a::xml: Unknown tag type: ".$line."\n";
  11.972 -	} else {
  11.973 -		return $i;
  11.974 -	}
  11.975 -}
  11.976 -
  11.977 -=item extract_tag($$)
  11.978 -
  11.979 -This function returns the next tag from the input stream without the beginning
  11.980 -and end, in an array form, to maintain the references from the input file.  It
  11.981 -has two parameters: the type of the tag (as returned by tag_type) and a
  11.982 -boolean, that indicates if it should be removed from the input stream.
  11.983 -
  11.984 -=cut
  11.985 -
  11.986 -sub extract_tag {
  11.987 -	my ($self,$type,$remove) = (shift,shift,shift);
  11.988 -	my ($match1,$match2) = ($tag_types[$type]->{beginning},$tag_types[$type]->{end});
  11.989 -	my ($eof,@tag);
  11.990 -	if (defined($tag_types[$type]->{f_extract})) {
  11.991 -		($eof,@tag) = &{$tag_types[$type]->{f_extract}}($self,$remove);
  11.992 -	} else {
  11.993 -		($eof,@tag) = $self->get_string_until($match2.">",{include=>1,remove=>$remove,unquoted=>1});
  11.994 -	}
  11.995 -	$tag[0] =~ /^<\Q$match1\E(.*)$/s;
  11.996 -	$tag[0] = $1;
  11.997 -	$tag[$#tag-1] =~ /^(.*)\Q$match2\E>$/s;
  11.998 -	$tag[$#tag-1] = $1;
  11.999 -	return ($eof,@tag);
 11.1000 -}
 11.1001 -
 11.1002 -=item get_tag_name(@)
 11.1003 -
 11.1004 -This function returns the name of the tag passed as an argument, in the array
 11.1005 -form returned by extract_tag.
 11.1006 -
 11.1007 -=cut
 11.1008 -
 11.1009 -sub get_tag_name {
 11.1010 -	my ($self,@tag)=@_;
 11.1011 -	$tag[0] =~ /^(\S*)/;
 11.1012 -	return $1;
 11.1013 -}
 11.1014 -
 11.1015 -=item breaking_tag()
 11.1016 -
 11.1017 -This function returns a boolean that says if the next tag in the input stream
 11.1018 -is a breaking tag or not (inline tag).  It leaves the input stream intact.
 11.1019 -
 11.1020 -=cut
 11.1021 -
 11.1022 -sub breaking_tag {
 11.1023 -	my $self = shift;
 11.1024 -	my $break;
 11.1025 -
 11.1026 -	my $type = $self->tag_type;
 11.1027 -	if ($type == -1) { return 0; }
 11.1028 -
 11.1029 -#print "TAG TYPE = ".$type."\n";
 11.1030 -	$break = $tag_types[$type]->{breaking};
 11.1031 -	if (!defined($break)) {
 11.1032 -		# This tag's breaking depends on its content
 11.1033 -		my ($eof,@lines) = $self->extract_tag($type,0);
 11.1034 -		$break = &{$tag_types[$type]->{f_breaking}}($self,@lines);
 11.1035 -	}
 11.1036 -#print "break = ".$break."\n";
 11.1037 -	return $break;
 11.1038 -}
 11.1039 -
 11.1040 -=item treat_tag()
 11.1041 -
 11.1042 -This function translates the next tag from the input stream.  Using each
 11.1043 -tag type's custom translation functions.
 11.1044 -
 11.1045 -=cut
 11.1046 -
 11.1047 -sub treat_tag {
 11.1048 -	my $self = shift;
 11.1049 -	my $type = $self->tag_type;
 11.1050 -
 11.1051 -	my ($match1,$match2) = ($tag_types[$type]->{beginning},$tag_types[$type]->{end});
 11.1052 -	my ($eof,@lines) = $self->extract_tag($type,1);
 11.1053 -
 11.1054 -	$lines[0] =~ /^(\s*)(.*)$/s;
 11.1055 -	my $space1 = $1;
 11.1056 -	$lines[0] = $2;
 11.1057 -	$lines[$#lines-1] =~ /^(.*?)(\s*)$/s;
 11.1058 -	my $space2 = $2;
 11.1059 -	$lines[$#lines-1] = $1;
 11.1060 -
 11.1061 -	# Calling this tag type's specific handling (translation of
 11.1062 -	# attributes...)
 11.1063 -	my $line = &{$tag_types[$type]->{f_translate}}($self,@lines);
 11.1064 -	$self->pushline("<".$match1.$space1.$line.$space2.$match2.">");
 11.1065 -	return $eof;
 11.1066 -}
 11.1067 -
 11.1068 -=item tag_in_list($@)
 11.1069 -
 11.1070 -This function returns a string value that says if the first argument (a tag
 11.1071 -hierarchy) matches any of the tags from the second argument (a list of tags
 11.1072 -or tag hierarchies). If it doesn't match, it returns 0. Else, it returns the
 11.1073 -matched tag's options (the characters in front of the tag) or 1 (if that tag
 11.1074 -doesn't have options).
 11.1075 -
 11.1076 -=back
 11.1077 -
 11.1078 -=cut
 11.1079 -sub tag_in_list ($$$) {
 11.1080 -	my ($self,$path,$list) = @_;
 11.1081 -	if ($self->{options}{'caseinsensitive'}) {
 11.1082 -		$path = lc $path;
 11.1083 -	}
 11.1084 -
 11.1085 -	while (1) {
 11.1086 -		if (defined $list->{$path}) {
 11.1087 -			if (length $list->{$path}) {
 11.1088 -				return $list->{$path};
 11.1089 -			} else {
 11.1090 -				return 1;
 11.1091 -			}
 11.1092 -		}
 11.1093 -		last unless ($path =~ m/</);
 11.1094 -		$path =~ s/^<.*?>//;
 11.1095 -	} 
 11.1096 -
 11.1097 -	return 0;
 11.1098 -}
 11.1099 -
 11.1100 -=head2 WORKING WITH ATTRIBUTES
 11.1101 -
 11.1102 -=over 4
 11.1103 -
 11.1104 -=item treat_attributes(@)
 11.1105 -
 11.1106 -This function handles the translation of the tags' attributes. It receives the tag
 11.1107 -without the beginning / end marks, and then it finds the attributes, and it
 11.1108 -translates the translatable ones (specified by the module option "attributes").
 11.1109 -This returns a plain string with the translated tag.
 11.1110 -
 11.1111 -=back
 11.1112 -
 11.1113 -=cut
 11.1114 -
 11.1115 -sub treat_attributes {
 11.1116 -	my ($self,@tag)=@_;
 11.1117 -
 11.1118 -	$tag[0] =~ /^(\S*)(.*)/s;
 11.1119 -	my $text = $1;
 11.1120 -	$tag[0] = $2;
 11.1121 -
 11.1122 -	while (@tag) {
 11.1123 -		my $complete = 1;
 11.1124 -
 11.1125 -		$text .= $self->skip_spaces(\@tag);
 11.1126 -		if (@tag) {
 11.1127 -			# Get the attribute's name
 11.1128 -			$complete = 0;
 11.1129 -
 11.1130 -			$tag[0] =~ /^([^\s=]+)(.*)/s;
 11.1131 -			my $name = $1;
 11.1132 -			my $ref = $tag[1];
 11.1133 -			$tag[0] = $2;
 11.1134 -			$text .= $name;
 11.1135 -			$text .= $self->skip_spaces(\@tag);
 11.1136 -			if (@tag) {
 11.1137 -				# Get the '='
 11.1138 -				if ($tag[0] =~ /^=(.*)/s) {
 11.1139 -					$tag[0] = $1;
 11.1140 -					$text .= "=";
 11.1141 -					$text .= $self->skip_spaces(\@tag);
 11.1142 -					if (@tag) {
 11.1143 -						# Get the value
 11.1144 -						my $value="";
 11.1145 -						$ref=$tag[1];
 11.1146 -						my $quot=substr($tag[0],0,1);
 11.1147 -						if ($quot ne "\"" and $quot ne "'") {
 11.1148 -							# Unquoted value
 11.1149 -							$quot="";
 11.1150 -							$tag[0] =~ /^(\S+)(.*)/s;
 11.1151 -							$value = $1;
 11.1152 -							$tag[0] = $2;
 11.1153 -						} else {
 11.1154 -							# Quoted value
 11.1155 -							$text .= $quot;
 11.1156 -							$tag[0] =~ /^\Q$quot\E(.*)/s;
 11.1157 -							$tag[0] = $1;
 11.1158 -							while ($tag[0] !~ /\Q$quot\E/) {
 11.1159 -								$value .= $tag[0];
 11.1160 -								shift @tag;
 11.1161 -								shift @tag;
 11.1162 -							}
 11.1163 -							$tag[0] =~ /^(.*?)\Q$quot\E(.*)/s;
 11.1164 -							$value .= $1;
 11.1165 -							$tag[0] = $2;
 11.1166 -						}
 11.1167 -						$complete = 1;
 11.1168 -						if ($self->tag_in_list($self->get_path.$name,$self->{attributes})) {
 11.1169 -							$text .= $self->found_string($value, $ref, { type=>"attribute", attribute=>$name });
 11.1170 -						} else {
 11.1171 -							print wrap_ref_mod($ref, "po4a::xml", dgettext("po4a", "Content of attribute %s excluded: %s"), $self->get_path.$name, $value)
 11.1172 -							       if $self->debug();
 11.1173 -							$text .= $self->recode_skipped_text($value);
 11.1174 -						}
 11.1175 -						$text .= $quot;
 11.1176 -					}
 11.1177 -				}
 11.1178 -			}
 11.1179 -          
 11.1180 -			unless ($complete) {
 11.1181 -				my $ontagerror = $self->{options}{'ontagerror'};
 11.1182 -				if ($ontagerror eq "warn") {
 11.1183 -					warn wrap_ref_mod($ref, "po4a::xml", dgettext ("po4a", "Bad attribute syntax.  Continuing..."));
 11.1184 -				} elsif ($ontagerror ne "silent") {
 11.1185 -					die wrap_ref_mod($ref, "po4a::xml", dgettext ("po4a", "Bad attribute syntax"));
 11.1186 -				}
 11.1187 -			}
 11.1188 -		}
 11.1189 -	}
 11.1190 -	return $text;
 11.1191 -}
 11.1192 -
 11.1193 -# Returns an empty string if the content in the $path should not be
 11.1194 -# translated.
 11.1195 -#
 11.1196 -# Otherwise, returns the set of options for translation:
 11.1197 -#   w: the content shall be re-wrapped
 11.1198 -#   W: the content shall not be re-wrapped
 11.1199 -#   i: the tag shall be inlined
 11.1200 -#   p: a placeholder shall replace the tag (and its content)
 11.1201 -#
 11.1202 -# A translatable inline tag in an untranslated tag is treated as a translatable breaking tag.
 11.1203 -my %translate_options_cache;
 11.1204 -sub get_translate_options {
 11.1205 -	my $self = shift;
 11.1206 -	my $path = shift;
 11.1207 -
 11.1208 -	if (defined $translate_options_cache{$path}) {
 11.1209 -		return $translate_options_cache{$path};
 11.1210 -	}
 11.1211 -
 11.1212 -	my $options = "";
 11.1213 -	my $translate = 0;
 11.1214 -	my $usedefault = 1;
 11.1215 -
 11.1216 -	my $inlist = 0;
 11.1217 -	my $tag = $self->get_tag_from_list($path, $self->{tags});
 11.1218 -	if (defined $tag) {
 11.1219 -		$inlist = 1;
 11.1220 -	}
 11.1221 -	if ($self->{options}{'tagsonly'} eq $inlist) {
 11.1222 -		$usedefault = 0;
 11.1223 -		if (defined $tag) {
 11.1224 -			$options = $tag;
 11.1225 -			$options =~ s/<.*$//;
 11.1226 -		} else {
 11.1227 -			if ($self->{options}{'wrap'}) {
 11.1228 -				$options = "w";
 11.1229 -			} else {
 11.1230 -				$options = "W";
 11.1231 -			}
 11.1232 -		}
 11.1233 -		$translate = 1;
 11.1234 -	}
 11.1235 -
 11.1236 -# TODO: a less precise set of tags should not override a more precise one
 11.1237 -	# The tags and tagsonly options are deprecated.
 11.1238 -	# The translated and untranslated options have an higher priority.
 11.1239 -	$tag = $self->get_tag_from_list($path, $self->{translated});
 11.1240 -	if (defined $tag) {
 11.1241 -		$usedefault = 0;
 11.1242 -		$options = $tag;
 11.1243 -		$options =~ s/<.*$//;
 11.1244 -		$translate = 1;
 11.1245 -	}
 11.1246 -
 11.1247 -	if ($translate and $options !~ m/w/i) {
 11.1248 -		$options .= ($self->{options}{'wrap'})?"w":"W";
 11.1249 -	}
 11.1250 -
 11.1251 -	if (not defined $tag) {
 11.1252 -		$tag = $self->get_tag_from_list($path, $self->{untranslated});
 11.1253 -		if (defined $tag) {
 11.1254 -			$usedefault = 0;
 11.1255 -			$options = "";
 11.1256 -			$translate = 0;
 11.1257 -		}
 11.1258 -	}
 11.1259 -
 11.1260 -	$tag = $self->get_tag_from_list($path, $self->{inline});
 11.1261 -	if (defined $tag) {
 11.1262 -		$usedefault = 0;
 11.1263 -		$options .= "i";
 11.1264 -	} else {
 11.1265 -		$tag = $self->get_tag_from_list($path, $self->{placeholder});
 11.1266 -		if (defined $tag) {
 11.1267 -			$usedefault = 0;
 11.1268 -			$options .= "p";
 11.1269 -		}
 11.1270 -	}
 11.1271 -
 11.1272 -	if ($usedefault) {
 11.1273 -		$options = $self->{options}{'defaulttranslateoption'};
 11.1274 -	}
 11.1275 -
 11.1276 -	# A translatable inline tag in an untranslated tag is treated as a
 11.1277 -	# translatable breaking tag.
 11.1278 -	if ($options =~ m/i/) {
 11.1279 -		my $ppath = $path;
 11.1280 -		$ppath =~ s/<[^>]*>$//;
 11.1281 -		my $poptions = $self->get_translate_options ($ppath);
 11.1282 -		if ($poptions eq "") {
 11.1283 -			$options =~ s/i//;
 11.1284 -		}
 11.1285 -	}
 11.1286 -
 11.1287 -	if ($options =~ m/i/ and $self->{options}{'foldattributes'}) {
 11.1288 -		$options .= "f";
 11.1289 -	}
 11.1290 -
 11.1291 -	$translate_options_cache{$path} = $options;
 11.1292 -	return $options;
 11.1293 -}
 11.1294 -
 11.1295 -
 11.1296 -# Return the tag (or biggest set of tags) of a list which matches with the
 11.1297 -# given path.
 11.1298 -#
 11.1299 -# The tag (or set of tags) is returned with its options.
 11.1300 -#
 11.1301 -# If no tags could match the path, undef is returned.
 11.1302 -sub get_tag_from_list ($$$) {
 11.1303 -	my ($self,$path,$list) = @_;
 11.1304 -	if ($self->{options}{'caseinsensitive'}) {
 11.1305 -		$path = lc $path;
 11.1306 -	}
 11.1307 -
 11.1308 -	while (1) {
 11.1309 -		if (defined $list->{$path}) {
 11.1310 -			return $list->{$path}.$path;
 11.1311 -		}
 11.1312 -		last unless ($path =~ m/</);
 11.1313 -		$path =~ s/^<.*?>//;
 11.1314 -	}
 11.1315 -
 11.1316 -	return undef;
 11.1317 -}
 11.1318 -
 11.1319 -
 11.1320 -
 11.1321 -sub treat_content {
 11.1322 -	my $self = shift;
 11.1323 -	my $blank="";
 11.1324 -	# Indicates if the paragraph will have to be translated
 11.1325 -	my $translate = "";
 11.1326 -
 11.1327 -	my ($eof,@paragraph)=$self->get_string_until('<',{remove=>1});
 11.1328 -
 11.1329 -	while (!$eof and !$self->breaking_tag) {
 11.1330 -	NEXT_TAG:
 11.1331 -		my @text;
 11.1332 -		my $type = $self->tag_type;
 11.1333 -		my $f_extract = $tag_types[$type]->{'f_extract'};
 11.1334 -		if (    defined($f_extract)
 11.1335 -		    and $f_extract eq \&tag_extract_comment) {
 11.1336 -			# Remove the content of the comments
 11.1337 -			($eof, @text) = $self->extract_tag($type,1);
 11.1338 -			$text[$#text-1] .= "\0";
 11.1339 -			if ($tag_types[$type]->{'beginning'} eq "!--#") {
 11.1340 -				$text[0] = "#".$text[0];
 11.1341 -			}
 11.1342 -			push @comments, @text;
 11.1343 -		} else {
 11.1344 -			my ($tmpeof, @tag) = $self->extract_tag($type,0);
 11.1345 -			# Append the found inline tag
 11.1346 -			($eof,@text)=$self->get_string_until('>',
 11.1347 -			                                     {include=>1,
 11.1348 -			                                      remove=>1,
 11.1349 -			                                      unquoted=>1});
 11.1350 -			# Append or remove the opening/closing tag from
 11.1351 -			# the tag path
 11.1352 -			if ($tag_types[$type]->{'end'} eq "") {
 11.1353 -				if ($tag_types[$type]->{'beginning'} eq "") {
 11.1354 -					# Opening inline tag
 11.1355 -					my $cur_tag_name = $self->get_tag_name(@tag);
 11.1356 -					my $t_opts = $self->get_translate_options($self->get_path($cur_tag_name));
 11.1357 -					if ($t_opts =~ m/p/) {
 11.1358 -						# We enter a new holder.
 11.1359 -						# Append a <placeholder ...> tag to the current
 11.1360 -						# paragraph, and save the @paragraph in the
 11.1361 -						# current holder.
 11.1362 -						my $last_holder = $save_holders[$#save_holders];
 11.1363 -						my $placeholder_str = "<placeholder type=\"".$cur_tag_name."\" id=\"".($#{$last_holder->{'sub_translations'}}+1)."\"/>";
 11.1364 -						push @paragraph, ($placeholder_str, $text[1]);
 11.1365 -						my @saved_paragraph = @paragraph;
 11.1366 -
 11.1367 -						$last_holder->{'paragraph'} = \@saved_paragraph;
 11.1368 -
 11.1369 -						# Then we must push a new holder
 11.1370 -						my @new_paragraph = ();
 11.1371 -						my @sub_translations = ();
 11.1372 -						my %folded_attributes;
 11.1373 -						my %new_holder = ('paragraph' => \@new_paragraph,
 11.1374 -						                  'open' => $text[0],
 11.1375 -						                  'translation' => "",
 11.1376 -						                  'close' => undef,
 11.1377 -						                  'sub_translations' => \@sub_translations,
 11.1378 -						                  'folded_attributes' => \%folded_attributes);
 11.1379 -						push @save_holders, \%new_holder;
 11.1380 -						@text = ();
 11.1381 -
 11.1382 -						# The current @paragraph
 11.1383 -						# (for the current holder)
 11.1384 -						# is empty.
 11.1385 -						@paragraph = ();
 11.1386 -					} elsif ($t_opts =~ m/f/) {
 11.1387 -						my $tag_full = $self->join_lines(@text);
 11.1388 -						my $tag_ref = $text[1];
 11.1389 -						if ($tag_full =~ m/^<\s*\S+\s+\S.*>$/s) {
 11.1390 -							my $holder = $save_holders[$#save_holders];
 11.1391 -							my $id = 0;
 11.1392 -							foreach (keys %{$holder->{folded_attributes}}) {
 11.1393 -								$id = $_ + 1 if ($_ >= $id);
 11.1394 -							}
 11.1395 -							$holder->{folded_attributes}->{$id} = $tag_full;
 11.1396 -
 11.1397 -							@text = ("<$cur_tag_name po4a-id=$id>", $tag_ref);
 11.1398 -						}
 11.1399 -					}
 11.1400 -					push @path, $cur_tag_name;
 11.1401 -				} elsif ($tag_types[$type]->{'beginning'} eq "/") {
 11.1402 -					# Closing inline tag
 11.1403 -
 11.1404 -					# Check if this is closing the
 11.1405 -					# last opening tag we detected.
 11.1406 -					my $test = pop @path;
 11.1407 -					my $name = $self->get_tag_name(@tag);
 11.1408 -					if (!defined($test) ||
 11.1409 -					    $test ne $name ) {
 11.1410 -						my $ontagerror = $self->{options}{'ontagerror'};
 11.1411 -						if ($ontagerror eq "warn") {
 11.1412 -							warn wrap_ref_mod($tag[1], "po4a::xml", dgettext("po4a", "Unexpected closing tag </%s> found. The main document may be wrong.  Continuing..."), $name);
 11.1413 -						} elsif ($ontagerror ne "silent") {
 11.1414 -							die wrap_ref_mod($tag[1], "po4a::xml", dgettext("po4a", "Unexpected closing tag </%s> found. The main document may be wrong."), $name);
 11.1415 -						}
 11.1416 -					}
 11.1417 -
 11.1418 -					if ($self->get_translate_options($self->get_path($self->get_tag_name(@tag))) =~ m/p/) {
 11.1419 -						# This closes the current holder.
 11.1420 -
 11.1421 -						push @path, $self->get_tag_name(@tag);
 11.1422 -						# Now translate this paragraph if needed.
 11.1423 -						# This will call pushline and append the
 11.1424 -						# translation to the current holder's translation.
 11.1425 -						$self->translate_paragraph(@paragraph);
 11.1426 -						pop @path;
 11.1427 -
 11.1428 -						# Now that this holder is closed, we can remove
 11.1429 -						# the holder from the stack.
 11.1430 -						my $holder = pop @save_holders;
 11.1431 -						# We need to keep the translation of this holder
 11.1432 -						my $translation = $holder->{'open'}.$holder->{'translation'}.$text[0];
 11.1433 -						# FIXME: @text could be multilines.
 11.1434 -
 11.1435 -						@text = ();
 11.1436 -
 11.1437 -						# Then we store the translation in the previous
 11.1438 -						# holder's sub_translations array
 11.1439 -						my $previous_holder = $save_holders[$#save_holders];
 11.1440 -						push @{$previous_holder->{'sub_translations'}}, $translation;
 11.1441 -						# We also need to restore the @paragraph array, as
 11.1442 -						# it was before we encountered the holder.
 11.1443 -						@paragraph = @{$previous_holder->{'paragraph'}};
 11.1444 -					}
 11.1445 -				}
 11.1446 -			}
 11.1447 -			push @paragraph, @text;
 11.1448 -		}
 11.1449 -
 11.1450 -		# Next tag
 11.1451 -		($eof,@text)=$self->get_string_until('<',{remove=>1});
 11.1452 -		if ($#text > 0) {
 11.1453 -			# Check if text (extracted after the inline tag)
 11.1454 -			# has to be translated
 11.1455 -			push @paragraph, @text;
 11.1456 -		}
 11.1457 -	}
 11.1458 -
 11.1459 -	# This strips the extracted strings
 11.1460 -	# (only if you don't specify the 'nostrip' option, and if the
 11.1461 -	# paragraph can be re-wrapped)
 11.1462 -	$translate = $self->get_translate_options($self->get_path);
 11.1463 -	if (!$self->{options}{'nostrip'} and $translate !~ m/W/) {
 11.1464 -		my $clean = 0;
 11.1465 -		# Clean the beginning
 11.1466 -		while (!$clean and $#paragraph > 0) {
 11.1467 -			$paragraph[0] =~ /^(\s*)(.*)/s;
 11.1468 -			my $match = $1;
 11.1469 -			if ($paragraph[0] eq $match) {
 11.1470 -				if ($match ne "") {
 11.1471 -					$self->pushline($match);
 11.1472 -				}
 11.1473 -				shift @paragraph;
 11.1474 -				shift @paragraph;
 11.1475 -			} else {
 11.1476 -				$paragraph[0] = $2;
 11.1477 -				if ($match ne "") {
 11.1478 -					$self->pushline($match);
 11.1479 -				}
 11.1480 -				$clean = 1;
 11.1481 -			}
 11.1482 -		}
 11.1483 -		$clean = 0;
 11.1484 -		# Clean the end
 11.1485 -		while (!$clean and $#paragraph > 0) {
 11.1486 -			$paragraph[$#paragraph-1] =~ /^(.*?)(\s*)$/s;
 11.1487 -			my $match = $2;
 11.1488 -			if ($paragraph[$#paragraph-1] eq $match) {
 11.1489 -				if ($match ne "") {
 11.1490 -					$blank = $match.$blank;
 11.1491 -				}
 11.1492 -				pop @paragraph;
 11.1493 -				pop @paragraph;
 11.1494 -			} else {
 11.1495 -				$paragraph[$#paragraph-1] = $1;
 11.1496 -				if ($match ne "") {
 11.1497 -					$blank = $match.$blank;
 11.1498 -				}
 11.1499 -				$clean = 1;
 11.1500 -			}
 11.1501 -		}
 11.1502 -	}
 11.1503 -
 11.1504 -	# Translate the string when needed
 11.1505 -	# This will either push the translation in the translated document or
 11.1506 -	# in the current holder translation.
 11.1507 -	$self->translate_paragraph(@paragraph);
 11.1508 -
 11.1509 -	# Push the trailing blanks
 11.1510 -	if ($blank ne "") {
 11.1511 -		$self->pushline($blank);
 11.1512 -	}
 11.1513 -	return $eof;
 11.1514 -}
 11.1515 -
 11.1516 -# Translate a @paragraph array of (string, reference).
 11.1517 -# The $translate argument indicates if the strings must be translated or
 11.1518 -# just pushed
 11.1519 -sub translate_paragraph {
 11.1520 -	my $self = shift;
 11.1521 -	my @paragraph = @_;
 11.1522 -	my $translate = $self->get_translate_options($self->get_path);
 11.1523 -
 11.1524 -	while (    (scalar @paragraph)
 11.1525 -	       and ($paragraph[0] =~ m/^\s*\n/s)) {
 11.1526 -		$self->pushline($paragraph[0]);
 11.1527 -		shift @paragraph;
 11.1528 -		shift @paragraph;
 11.1529 -	}
 11.1530 -
 11.1531 -	my $comments;
 11.1532 -	while (@comments) {
 11.1533 -		my ($comment,$eoc);
 11.1534 -		do {
 11.1535 -			my ($t,$l) = (shift @comments, shift @comments);
 11.1536 -			$t =~ s/\n?(\0)?$//;
 11.1537 -			$eoc = $1;
 11.1538 -			$comment .= "\n" if defined $comment;
 11.1539 -			$comment .= $t;
 11.1540 -		} until ($eoc);
 11.1541 -		$comments .= "\n" if defined $comments;
 11.1542 -		$comments .= $comment;
 11.1543 -		$self->pushline("<!--".$comment."-->\n") if defined $comment;
 11.1544 -	}
 11.1545 -	@comments = ();
 11.1546 -
 11.1547 -	if ($self->{options}{'cpp'}) {
 11.1548 -		my @tmp = @paragraph;
 11.1549 -		@paragraph = ();
 11.1550 -		while (@tmp) {
 11.1551 -			my ($t,$l) = (shift @tmp, shift @tmp);
 11.1552 -			# #include can be followed by a filename between
 11.1553 -			# <> brackets. In that case, the argument won't be
 11.1554 -			# handled in the same call to translate_paragraph.
 11.1555 -			# Thus do not try to match "include ".
 11.1556 -			if ($t =~ m/^#[ \t]*(if |endif|undef |include|else|ifdef |ifndef |define )/si) {
 11.1557 -				if (@paragraph) {
 11.1558 -					$self->translate_paragraph(@paragraph);
 11.1559 -					@paragraph = ();
 11.1560 -					$self->pushline("\n");
 11.1561 -				}
 11.1562 -				$self->pushline($t);
 11.1563 -			} else {
 11.1564 -				push @paragraph, ($t,$l);
 11.1565 -			}
 11.1566 -		}
 11.1567 -	}
 11.1568 -
 11.1569 -	my $para = $self->join_lines(@paragraph);
 11.1570 -	if ( length($para) > 0 ) {
 11.1571 -		if ($translate ne "") {
 11.1572 -			# This tag should be translated
 11.1573 -			$self->pushline($self->found_string(
 11.1574 -				$para,
 11.1575 -				$paragraph[1], {
 11.1576 -					type=>"tag",
 11.1577 -					tag_options=>$translate,
 11.1578 -					comments=>$comments
 11.1579 -				}));
 11.1580 -		} else {
 11.1581 -			# Inform that this tag isn't translated in debug mode
 11.1582 -			print wrap_ref_mod($paragraph[1], "po4a::xml", dgettext ("po4a", "Content of tag %s excluded: %s"), $self->get_path, $para)
 11.1583 -			       if $self->debug();
 11.1584 -			$self->pushline($self->recode_skipped_text($para));
 11.1585 -		}
 11.1586 -	}
 11.1587 -	# Now the paragraph is fully translated.
 11.1588 -	# If we have all the holders' translation, we can replace the
 11.1589 -	# placeholders by their translations.
 11.1590 -	# We must wait to have all the translations because the holders are
 11.1591 -	# numbered.
 11.1592 -	{
 11.1593 -		my $holder = $save_holders[$#save_holders];
 11.1594 -		my $translation = $holder->{'translation'};
 11.1595 -
 11.1596 -		# Count the number of <placeholder ...> in $translation
 11.1597 -		my $count = 0;
 11.1598 -		my $str = $translation;
 11.1599 -		while (    (defined $str)
 11.1600 -		       and ($str =~ m/^.*?<placeholder\s+type="[^"]+"\s+id="(\d+)"\s*\/>(.*)$/s)) {
 11.1601 -			$count += 1;
 11.1602 -			$str = $2;
 11.1603 -			if ($holder->{'sub_translations'}->[$1] =~ m/<placeholder\s+type="[^"]+"\s+id="(\d+)"\s*\/>/s) {
 11.1604 -				$count = -1;
 11.1605 -				last;
 11.1606 -			}
 11.1607 -		}
 11.1608 -
 11.1609 -		if (    (defined $translation)
 11.1610 -		    and (scalar(@{$holder->{'sub_translations'}}) == $count)) {
 11.1611 -			# OK, all the holders of the current paragraph are
 11.1612 -			# closed (and translated).
 11.1613 -			# Replace them by their translation.
 11.1614 -			while ($translation =~ m/^(.*?)<placeholder\s+type="[^"]+"\s+id="(\d+)"\s*\/>(.*)$/s) {
 11.1615 -				# FIXME: we could also check that
 11.1616 -				#          * the holder exists
 11.1617 -				#          * all the holders are used
 11.1618 -				$translation = $1.$holder->{'sub_translations'}->[$2].$3;
 11.1619 -			}
 11.1620 -			# We have our translation
 11.1621 -			$holder->{'translation'} = $translation;
 11.1622 -			# And there is no need for any holder in it.
 11.1623 -			my @sub_translations = ();
 11.1624 -			$holder->{'sub_translations'} = \@sub_translations;
 11.1625 -		}
 11.1626 -	}
 11.1627 -
 11.1628 -}
 11.1629 -
 11.1630 -
 11.1631 -
 11.1632 -=head2 WORKING WITH THE MODULE OPTIONS
 11.1633 -
 11.1634 -=over 4
 11.1635 -
 11.1636 -=item treat_options()
 11.1637 -
 11.1638 -This function fills the internal structures that contain the tags, attributes
 11.1639 -and inline data with the options of the module (specified in the command-line
 11.1640 -or in the initialize function).
 11.1641 -
 11.1642 -=back
 11.1643 -
 11.1644 -=cut
 11.1645 -
 11.1646 -sub treat_options {
 11.1647 -	my $self = shift;
 11.1648 -
 11.1649 -	if ($self->{options}{'caseinsensitive'}) {
 11.1650 -		$self->{options}{'nodefault'}             = lc $self->{options}{'nodefault'};
 11.1651 -		$self->{options}{'tags'}                  = lc $self->{options}{'tags'};
 11.1652 -		$self->{options}{'break'}                 = lc $self->{options}{'break'};
 11.1653 -		$self->{options}{'_default_break'}        = lc $self->{options}{'_default_break'};
 11.1654 -		$self->{options}{'translated'}            = lc $self->{options}{'translated'};
 11.1655 -		$self->{options}{'_default_translated'}   = lc $self->{options}{'_default_translated'};
 11.1656 -		$self->{options}{'untranslated'}          = lc $self->{options}{'untranslated'};
 11.1657 -		$self->{options}{'_default_untranslated'} = lc $self->{options}{'_default_untranslated'};
 11.1658 -		$self->{options}{'attributes'}            = lc $self->{options}{'attributes'};
 11.1659 -		$self->{options}{'_default_attributes'}   = lc $self->{options}{'_default_attributes'};
 11.1660 -		$self->{options}{'inline'}                = lc $self->{options}{'inline'};
 11.1661 -		$self->{options}{'_default_inline'}       = lc $self->{options}{'_default_inline'};
 11.1662 -		$self->{options}{'placeholder'}           = lc $self->{options}{'placeholder'};
 11.1663 -		$self->{options}{'_default_placeholder'}  = lc $self->{options}{'_default_placeholder'};
 11.1664 -	}
 11.1665 -
 11.1666 -	$self->{options}{'nodefault'} =~ /^\s*(.*)\s*$/s;
 11.1667 -	my %list_nodefault;
 11.1668 -	foreach (split(/\s+/s,$1)) {
 11.1669 -		$list_nodefault{$_} = 1;
 11.1670 -	}
 11.1671 -	$self->{nodefault} = \%list_nodefault;
 11.1672 -
 11.1673 -	$self->{options}{'tags'} =~ /^\s*(.*)\s*$/s;
 11.1674 -	if (length $self->{options}{'tags'}) {
 11.1675 -		warn wrap_mod("po4a::xml",
 11.1676 -		             dgettext("po4a",
 11.1677 -		                      "The '%s' option is deprecated. Please use the translated/untranslated and/or break/inline/placeholder categories."), "tags");
 11.1678 -	}
 11.1679 -	foreach (split(/\s+/s,$1)) {
 11.1680 -		$_ =~ m/^(.*?)(<.*)$/;
 11.1681 -		$self->{tags}->{$2} = $1 || "";
 11.1682 -	}
 11.1683 -
 11.1684 -	if ($self->{options}{'tagsonly'}) {
 11.1685 -		warn wrap_mod("po4a::xml",
 11.1686 -		             dgettext("po4a",
 11.1687 -		                      "The '%s' option is deprecated. Please use the translated/untranslated and/or break/inline/placeholder categories."), "tagsonly");
 11.1688 -	}
 11.1689 -
 11.1690 -	$self->{options}{'break'} =~ /^\s*(.*)\s*$/s;
 11.1691 -	foreach my $tag (split(/\s+/s,$1)) {
 11.1692 -		$tag =~ m/^(.*?)(<.*)$/;
 11.1693 -		$self->{break}->{$2} = $1 || "";
 11.1694 -	}
 11.1695 -	$self->{options}{'_default_break'} =~ /^\s*(.*)\s*$/s;
 11.1696 -	foreach my $tag (split(/\s+/s,$1)) {
 11.1697 -		$tag =~ m/^(.*?)(<.*)$/;
 11.1698 -		$self->{break}->{$2} = $1 || ""
 11.1699 -			unless    $list_nodefault{$2}
 11.1700 -			       or defined $self->{break}->{$2};
 11.1701 -	}
 11.1702 -
 11.1703 -	$self->{options}{'translated'} =~ /^\s*(.*)\s*$/s;
 11.1704 -	foreach my $tag (split(/\s+/s,$1)) {
 11.1705 -		$tag =~ m/^(.*?)(<.*)$/;
 11.1706 -		$self->{translated}->{$2} = $1 || "";
 11.1707 -	}
 11.1708 -	$self->{options}{'_default_translated'} =~ /^\s*(.*)\s*$/s;
 11.1709 -	foreach my $tag (split(/\s+/s,$1)) {
 11.1710 -		$tag =~ m/^(.*?)(<.*)$/;
 11.1711 -		$self->{translated}->{$2} = $1 || ""
 11.1712 -			unless    $list_nodefault{$2}
 11.1713 -			       or defined $self->{translated}->{$2};
 11.1714 -	}
 11.1715 -
 11.1716 -	$self->{options}{'untranslated'} =~ /^\s*(.*)\s*$/s;
 11.1717 -	foreach my $tag (split(/\s+/s,$1)) {
 11.1718 -		$tag =~ m/^(.*?)(<.*)$/;
 11.1719 -		$self->{untranslated}->{$2} = $1 || "";
 11.1720 -	}
 11.1721 -	$self->{options}{'_default_untranslated'} =~ /^\s*(.*)\s*$/s;
 11.1722 -	foreach my $tag (split(/\s+/s,$1)) {
 11.1723 -		$tag =~ m/^(.*?)(<.*)$/;
 11.1724 -		$self->{untranslated}->{$2} = $1 || ""
 11.1725 -			unless    $list_nodefault{$2}
 11.1726 -			       or defined $self->{untranslated}->{$2};
 11.1727 -	}
 11.1728 -
 11.1729 -	$self->{options}{'attributes'} =~ /^\s*(.*)\s*$/s;
 11.1730 -	foreach my $tag (split(/\s+/s,$1)) {
 11.1731 -		if ($tag =~ m/^(.*?)(<.*)$/) {
 11.1732 -			$self->{attributes}->{$2} = $1 || "";
 11.1733 -		} else {
 11.1734 -			$self->{attributes}->{$tag} = "";
 11.1735 -		}
 11.1736 -	}
 11.1737 -	$self->{options}{'_default_attributes'} =~ /^\s*(.*)\s*$/s;
 11.1738 -	foreach my $tag (split(/\s+/s,$1)) {
 11.1739 -		if ($tag =~ m/^(.*?)(<.*)$/) {
 11.1740 -			$self->{attributes}->{$2} = $1 || ""
 11.1741 -				unless    $list_nodefault{$2}
 11.1742 -				       or defined $self->{attributes}->{$2};
 11.1743 -		} else {
 11.1744 -			$self->{attributes}->{$tag} = ""
 11.1745 -				unless    $list_nodefault{$tag}
 11.1746 -				       or defined $self->{attributes}->{$tag};
 11.1747 -		}
 11.1748 -	}
 11.1749 -
 11.1750 -	my @list_inline;
 11.1751 -	$self->{options}{'inline'} =~ /^\s*(.*)\s*$/s;
 11.1752 -	foreach my $tag (split(/\s+/s,$1)) {
 11.1753 -		$tag =~ m/^(.*?)(<.*)$/;
 11.1754 -		$self->{inline}->{$2} = $1 || "";
 11.1755 -	}
 11.1756 -	$self->{options}{'_default_inline'} =~ /^\s*(.*)\s*$/s;
 11.1757 -	foreach my $tag (split(/\s+/s,$1)) {
 11.1758 -		$tag =~ m/^(.*?)(<.*)$/;
 11.1759 -		$self->{inline}->{$2} = $1 || ""
 11.1760 -			unless    $list_nodefault{$2}
 11.1761 -			       or defined $self->{inline}->{$2};
 11.1762 -	}
 11.1763 -
 11.1764 -	$self->{options}{'placeholder'} =~ /^\s*(.*)\s*$/s;
 11.1765 -	foreach my $tag (split(/\s+/s,$1)) {
 11.1766 -		$tag =~ m/^(.*?)(<.*)$/;
 11.1767 -		$self->{placeholder}->{$2} = $1 || "";
 11.1768 -	}
 11.1769 -	$self->{options}{'_default_placeholder'} =~ /^\s*(.*)\s*$/s;
 11.1770 -	foreach my $tag (split(/\s+/s,$1)) {
 11.1771 -		$tag =~ m/^(.*?)(<.*)$/;
 11.1772 -		$self->{placeholder}->{$2} = $1 || ""
 11.1773 -			unless    $list_nodefault{$2}
 11.1774 -			       or defined $self->{placeholder}->{$2};
 11.1775 -	}
 11.1776 -
 11.1777 -	# There should be no translated and untranslated tags
 11.1778 -	foreach my $tag (keys %{$self->{translated}}) {
 11.1779 -		die wrap_mod("po4a::xml",
 11.1780 -		             dgettext("po4a",
 11.1781 -		                      "Tag '%s' both in the %s and %s categories."), $tag, "translated", "untranslated")
 11.1782 -			if defined $self->{untranslated}->{$tag};
 11.1783 -	}
 11.1784 -	# There should be no inline, break, and placeholder tags
 11.1785 -	foreach my $tag (keys %{$self->{inline}}) {
 11.1786 -		die wrap_mod("po4a::xml",
 11.1787 -		             dgettext("po4a",
 11.1788 -		                      "Tag '%s' both in the %s and %s categories."), $tag, "inline", "break")
 11.1789 -			if defined $self->{break}->{$tag};
 11.1790 -		die wrap_mod("po4a::xml",
 11.1791 -		             dgettext("po4a",
 11.1792 -		                      "Tag '%s' both in the %s and %s categories."), $tag, "inline", "placeholder")
 11.1793 -			if defined $self->{placeholder}->{$tag};
 11.1794 -	}
 11.1795 -	foreach my $tag (keys %{$self->{break}}) {
 11.1796 -		die wrap_mod("po4a::xml",
 11.1797 -		             dgettext("po4a",
 11.1798 -		                      "Tag '%s' both in the %s and %s categories."), $tag, "break", "placeholder")
 11.1799 -			if defined $self->{placeholder}->{$tag};
 11.1800 -	}
 11.1801 -}
 11.1802 -
 11.1803 -=head2 GETTING TEXT FROM THE INPUT DOCUMENT
 11.1804 -
 11.1805 -=over
 11.1806 -
 11.1807 -=item get_string_until($%)
 11.1808 -
 11.1809 -This function returns an array with the lines (and references) from the input
 11.1810 -document until it finds the first argument.  The second argument is an options
 11.1811 -hash. Value 0 means disabled (the default) and 1, enabled.
 11.1812 -
 11.1813 -The valid options are:
 11.1814 -
 11.1815 -=over 4
 11.1816 -
 11.1817 -=item include
 11.1818 -
 11.1819 -This makes the returned array to contain the searched text
 11.1820 -
 11.1821 -=item remove
 11.1822 -
 11.1823 -This removes the returned stream from the input
 11.1824 -
 11.1825 -=item unquoted
 11.1826 -
 11.1827 -This ensures that the searched text is outside any quotes
 11.1828 -
 11.1829 -=back
 11.1830 -
 11.1831 -=cut
 11.1832 -
 11.1833 -sub get_string_until {
 11.1834 -	my ($self,$search) = (shift,shift);
 11.1835 -	my $options = shift;
 11.1836 -	my ($include,$remove,$unquoted, $regex) = (0,0,0,0);
 11.1837 -
 11.1838 -	if (defined($options->{include})) { $include = $options->{include}; }
 11.1839 -	if (defined($options->{remove})) { $remove = $options->{remove}; }
 11.1840 -	if (defined($options->{unquoted})) { $unquoted = $options->{unquoted}; }
 11.1841 -	if (defined($options->{regex})) { $regex = $options->{regex}; }
 11.1842 -
 11.1843 -	my ($line,$ref) = $self->shiftline();
 11.1844 -	my (@text,$paragraph);
 11.1845 -	my ($eof,$found) = (0,0);
 11.1846 -
 11.1847 -	$search = "\Q$search\E" unless $regex;
 11.1848 -	while (defined($line) and !$found) {
 11.1849 -		push @text, ($line,$ref);
 11.1850 -		$paragraph .= $line;
 11.1851 -		if ($unquoted) {
 11.1852 -			if ( $paragraph =~ /^((\".*?\")|(\'.*?\')|[^\"\'])*$search/s ) {
 11.1853 -				$found = 1;
 11.1854 -			}
 11.1855 -		} else {
 11.1856 -			if ( $paragraph =~ /$search/s ) {
 11.1857 -				$found = 1;
 11.1858 -			}
 11.1859 -		}
 11.1860 -		if (!$found) {
 11.1861 -			($line,$ref)=$self->shiftline();
 11.1862 -		}
 11.1863 -	}
 11.1864 -
 11.1865 -	if (!defined($line)) { $eof = 1; }
 11.1866 -
 11.1867 -	if ( $found ) {
 11.1868 -		$line = "";
 11.1869 -		if($unquoted) {
 11.1870 -			$paragraph =~ /^(?:(?:\".*?\")|(?:\'.*?\')|[^\"\'])*?$search(.*)$/s;
 11.1871 -			$line = $1;
 11.1872 -			$text[$#text-1] =~ s/\Q$line\E$//s;
 11.1873 -		} else {
 11.1874 -			$paragraph =~ /$search(.*)$/s;
 11.1875 -			$line = $1;
 11.1876 -			$text[$#text-1] =~ s/\Q$line\E$//s;
 11.1877 -		}
 11.1878 -		if(!$include) {
 11.1879 -			$text[$#text-1] =~ /^(.*)($search.*)$/s;
 11.1880 -			$text[$#text-1] = $1;
 11.1881 -			$line = $2.$line;
 11.1882 -		}
 11.1883 -		if (defined($line) and ($line ne "")) {
 11.1884 -			$self->unshiftline ($line,$text[$#text]);
 11.1885 -		}
 11.1886 -	}
 11.1887 -	if (!$remove) {
 11.1888 -		$self->unshiftline (@text);
 11.1889 -	}
 11.1890 -
 11.1891 -	#If we get to the end of the file, we return the whole paragraph
 11.1892 -	return ($eof,@text);
 11.1893 -}
 11.1894 -
 11.1895 -=item skip_spaces(\@)
 11.1896 -
 11.1897 -This function receives as argument the reference to a paragraph (in the format
 11.1898 -returned by get_string_until), skips his heading spaces and returns them as
 11.1899 -a simple string.
 11.1900 -
 11.1901 -=cut
 11.1902 -
 11.1903 -sub skip_spaces {
 11.1904 -	my ($self,$pstring)=@_;
 11.1905 -	my $space="";
 11.1906 -
 11.1907 -	while (@$pstring and (@$pstring[0] =~ /^(\s+)(.*)$/s or @$pstring[0] eq "")) {
 11.1908 -		if (@$pstring[0] ne "") {
 11.1909 -			$space .= $1;
 11.1910 -			@$pstring[0] = $2;
 11.1911 -		}
 11.1912 -
 11.1913 -		if (@$pstring[0] eq "") {
 11.1914 -			shift @$pstring;
 11.1915 -			shift @$pstring;
 11.1916 -		}
 11.1917 -	}
 11.1918 -	return $space;
 11.1919 -}
 11.1920 -
 11.1921 -=item join_lines(@)
 11.1922 -
 11.1923 -This function returns a simple string with the text from the argument array
 11.1924 -(discarding the references).
 11.1925 -
 11.1926 -=cut
 11.1927 -
 11.1928 -sub join_lines {
 11.1929 -	my ($self,@lines)=@_;
 11.1930 -	my ($line,$ref);
 11.1931 -	my $text = "";
 11.1932 -	while ($#lines > 0) {
 11.1933 -		($line,$ref) = (shift @lines,shift @lines);
 11.1934 -		$text .= $line;
 11.1935 -	}
 11.1936 -	return $text;
 11.1937 -}
 11.1938 -
 11.1939 -=back
 11.1940 -
 11.1941 -=head1 STATUS OF THIS MODULE
 11.1942 -
 11.1943 -This module can translate tags and attributes.
 11.1944 -
 11.1945 -=head1 TODO LIST
 11.1946 -
 11.1947 -DOCTYPE (ENTITIES)
 11.1948 -
 11.1949 -There is a minimal support for the translation of entities. They are
 11.1950 -translated as a whole, and tags are not taken into account. Multilines
 11.1951 -entities are not supported and entities are always rewrapped during the
 11.1952 -translation.
 11.1953 -
 11.1954 -MODIFY TAG TYPES FROM INHERITED MODULES
 11.1955 -(move the tag_types structure inside the $self hash?)
 11.1956 -
 11.1957 -=head1 SEE ALSO
 11.1958 -
 11.1959 -L<po4a(7)|po4a.7>, L<Locale::Po4a::TransTractor(3pm)|Locale::Po4a::TransTractor>.
 11.1960 -
 11.1961 -=head1 AUTHORS
 11.1962 -
 11.1963 - Jordi Vilalta <jvprat@gmail.com>
 11.1964 - Nicolas François <nicolas.francois@centraliens.net>
 11.1965 -
 11.1966 -=head1 COPYRIGHT AND LICENSE
 11.1967 -
 11.1968 - Copyright (c) 2004 by Jordi Vilalta  <jvprat@gmail.com>
 11.1969 - Copyright (c) 2008-2009 by Nicolas François <nicolas.francois@centraliens.net>
 11.1970 -
 11.1971 -This program is free software; you may redistribute it and/or modify it
 11.1972 -under the terms of GPL (see the COPYING file).
 11.1973 -
 11.1974 -=cut
 11.1975 -
 11.1976 -1;
    12.1 --- a/tools/po4a/po4a-translate	Mon Mar 30 17:50:48 2009 +0800
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,257 +0,0 @@
    12.4 -#! /usr/bin/env perl
    12.5 -eval 'exec perl -S $0 ${1+"$@"}'
    12.6 -    if $running_under_some_shell;
    12.7 -
    12.8 -# po4a-translate -- translate doc files using a message catalog(ie, po file)
    12.9 -# $Id: po4a-translate,v 1.41 2009-03-07 12:33:10 nekral-guest Exp $
   12.10 -#
   12.11 -# Copyright 2002, 2003, 2004 by Martin Quinson (mquinson#debian.org)
   12.12 -#
   12.13 -# This program is free software; you can redistribute it and/or modify it
   12.14 -# under the terms of GPL (see COPYING).
   12.15 -
   12.16 -=head1 NAME
   12.17 -
   12.18 -po4a-translate - convert a po file back to documentation format
   12.19 -
   12.20 -=head1 SYNOPSIS
   12.21 -
   12.22 -po4a-translate -f E<lt>fmtE<gt> -m E<lt>master.docE<gt> -p E<lt>XX.poE<gt> -l E<lt>XX.docE<gt>
   12.23 -
   12.24 -(XX.doc is the output, all others are inputs)
   12.25 -
   12.26 -=head1 DESCRIPTION
   12.27 -
   12.28 -The po4a (po for anything) project goal is to ease translations (and more
   12.29 -interestingly, the maintenance of translations) using gettext tools on
   12.30 -areas where they were not expected like documentation.
   12.31 -
   12.32 -The C<po4a-translate> script is in charge of converting the translation
   12.33 -(which was done in a po file) under the documentation format back. The
   12.34 -provided C<po> file should be the translation of the C<pot> file which were
   12.35 -produced by po4a-gettextize(1).
   12.36 -
   12.37 -=head1 OPTIONS
   12.38 -
   12.39 -=over 4
   12.40 -
   12.41 -=item -f, --format
   12.42 -
   12.43 -Format of the documentation you want to handle. Use the --help-format
   12.44 -option to see the list of available formats.
   12.45 -
   12.46 -=item -a, --addendum
   12.47 -
   12.48 -Add a file to the resulting file (to put translator's name or a section
   12.49 -"About this translation", for example). The first line of the file to insert
   12.50 -should be a PO4A header indicating where it should be added (see section
   12.51 -I<HOWTO add extra text to translations> in po4a(7)).
   12.52 -
   12.53 -=item -A, --addendum-charset
   12.54 -
   12.55 -Charset of the addenda. Note that all the addenda should be in the same
   12.56 -charset.
   12.57 -
   12.58 -=item -m, --master
   12.59 -
   12.60 -File containing the master document to translate.
   12.61 -
   12.62 -=item -M, --master-charset
   12.63 -
   12.64 -Charset of the file containing the document to translate.
   12.65 -
   12.66 -=item -l, --localized
   12.67 -
   12.68 -File where the localized (translated) document should be written.
   12.69 -
   12.70 -=item -L, --localized-charset
   12.71 -
   12.72 -Charset of the file containing the localized document.
   12.73 -
   12.74 -=item -p, --po
   12.75 -
   12.76 -File from which the message catalog should be read.
   12.77 -
   12.78 -=item -o, --option
   12.79 -
   12.80 -Extra option(s) to pass to the format plugin. Specify each option in the
   12.81 -'name=value' format. See the documentation of each plugin for more
   12.82 -information about the valid options and their meanings.
   12.83 -
   12.84 -=item -k, --keep
   12.85 -
   12.86 -Minimal threshold for translation percentage to keep (ie, write) the
   12.87 -resulting file (default: 80). Ie, by default, files have to be translated
   12.88 -at at least 80% to get written.
   12.89 -
   12.90 -=item -w, --width
   12.91 -
   12.92 -Column at which we should wrap the resulting file.
   12.93 -
   12.94 -=item -h, --help
   12.95 -
   12.96 -Show a short help message.
   12.97 -
   12.98 -=item --help-format
   12.99 -
  12.100 -List the documentation format understood by po4a.
  12.101 -
  12.102 -=item -V, --version
  12.103 -
  12.104 -Display the version of the script and exit.
  12.105 -
  12.106 -=item -v, --verbose
  12.107 -
  12.108 -Increase the verbosity of the program.
  12.109 -
  12.110 -=item -d, --debug
  12.111 -
  12.112 -Output some debugging information.
  12.113 -
  12.114 -=back
  12.115 -
  12.116 -=head1 Adding content (beside translations) to generated files
  12.117 -
  12.118 -To add some extra content to the generated document beside what you
  12.119 -translated (like the name of the translator, or a "about this translation"
  12.120 -section), you should use the C<--addendum> option. 
  12.121 -
  12.122 -The first line of the addendum must be a header indicating where to put
  12.123 -it in the document (it can be before or after a given part of the
  12.124 -document).  The rest of the file will be added verbatim to the resulting
  12.125 -file without further processing.
  12.126 -
  12.127 -Note that if po4a-translate fails to add one of the given files, it discards
  12.128 -the whole translation (because the missing file could be the one indicating
  12.129 -the author, what would prevent the users to contact him to report bugs in
  12.130 -the translation).
  12.131 -
  12.132 -The header has a pretty rigid syntax. For more information on how to use
  12.133 -this feature and how it works, please refer to the po4a(7) man page.
  12.134 -
  12.135 -=head1 SEE ALSO
  12.136 -
  12.137 -L<po4a(7)>, L<po4a-gettextize(1)>, L<po4a-updatepo(1)>, L<po4a-normalize(1)>.
  12.138 -
  12.139 -
  12.140 -=head1 AUTHORS
  12.141 -
  12.142 - Denis Barbier <barbier@linuxfr.org>
  12.143 - Martin Quinson (mquinson#debian.org)
  12.144 -
  12.145 -=head1 COPYRIGHT AND LICENSE
  12.146 -
  12.147 -Copyright 2002, 2003, 2004 by SPI, inc.
  12.148 -
  12.149 -This program is free software; you may redistribute it and/or modify it
  12.150 -under the terms of GPL (see the COPYING file).
  12.151 -
  12.152 -=cut
  12.153 -
  12.154 -use 5.006;
  12.155 -use strict;
  12.156 -use warnings;
  12.157 -
  12.158 -use Locale::Po4a::Chooser;
  12.159 -use Locale::Po4a::TransTractor;
  12.160 -use Locale::Po4a::Common;
  12.161 -
  12.162 -use Pod::Usage qw(pod2usage);
  12.163 -use Getopt::Long qw(GetOptions);
  12.164 -
  12.165 -Locale::Po4a::Common::textdomain("po4a");
  12.166 -
  12.167 -sub show_version {
  12.168 -    Locale::Po4a::Common::show_version("po4a-translate");
  12.169 -    exit 0;
  12.170 -}
  12.171 -
  12.172 -
  12.173 -Getopt::Long::Configure('no_auto_abbrev','no_ignore_case');
  12.174 -my ($outfile,$width,$threshold)=('-',80,80);
  12.175 -my ($help,$help_fmt,@verbose,$debug,@addfiles,$format,@options);
  12.176 -my ($master_filename,$po_filename);
  12.177 -my ($mastchar,$locchar,$addchar);
  12.178 -GetOptions(
  12.179 -	'help|h'        => \$help,
  12.180 -	'help-format'   => \$help_fmt,
  12.181 -
  12.182 -	'master|m=s'    => \$master_filename,
  12.183 -	'localized|l=s' => \$outfile,
  12.184 -	'po|p=s'        => \$po_filename,
  12.185 -	'addendum|a=s'  => \@addfiles,
  12.186 -	'format|f=s'    => \$format,
  12.187 -
  12.188 -	'master-charset|M=s'    => \$mastchar,
  12.189 -	'localized-charset|L=s' => \$locchar,
  12.190 -	'addendum-charset|A=s' => \$addchar,
  12.191 -
  12.192 -	'option|o=s'    => \@options,
  12.193 -
  12.194 -	'width|w=s'     => \$width,
  12.195 -	'verbose|v'     => \@verbose,
  12.196 -	'debug|d'       => \$debug,
  12.197 -	'keep|k=s'      => \$threshold,
  12.198 -
  12.199 -	'version|V'     => \&show_version
  12.200 -) or pod2usage();
  12.201 -
  12.202 -$help && pod2usage(-verbose => 1, -exitval => 0);
  12.203 -$help_fmt && Locale::Po4a::Chooser::list(0);
  12.204 -
  12.205 -(defined($master_filename) && length($master_filename))||pod2usage();
  12.206 -(defined($po_filename)     && length($po_filename))    ||pod2usage();
  12.207 --e $master_filename || die wrap_msg(gettext("File %s does not exist."), $master_filename);
  12.208 --e $po_filename || die wrap_msg(gettext("File %s does not exist."), $po_filename);
  12.209 -
  12.210 -my (@pos,@masters);
  12.211 -push @pos,$po_filename;
  12.212 -push @masters,$master_filename;
  12.213 -
  12.214 -my %options = (
  12.215 -    "verbose" => scalar @verbose,
  12.216 -    "debug" => $debug);
  12.217 -
  12.218 -foreach (@options) {
  12.219 -    if (m/^([^=]*)=(.*)$/) {
  12.220 -	$options{$1}="$2";
  12.221 -    } else {
  12.222 -	$options{$_}=1;
  12.223 -    }
  12.224 -}
  12.225 -# parser
  12.226 -my $doc=Locale::Po4a::Chooser::new($format,%options);
  12.227 -
  12.228 -
  12.229 -# Prepare the document to be used as translator, but not parser
  12.230 -$doc->process('po_in_name'       => \@pos,
  12.231 -	      'file_in_name'     => \@masters,
  12.232 -	      'file_in_charset'  => $mastchar,
  12.233 -	      'file_out_charset' => $locchar,
  12.234 -	      'addendum_charset' => $addchar);
  12.235 -
  12.236 -my ($percent,$hit,$queries) = $doc->stats();
  12.237 -my $error=0;
  12.238 -
  12.239 -print STDERR wrap_msg(gettext("%s is %s%% translated (%s of %s strings)."),
  12.240 -    $master_filename, $percent, $hit, $queries)
  12.241 -  if (scalar @verbose) && ($percent>=$threshold);
  12.242 -
  12.243 -
  12.244 -if ($percent<$threshold)  {
  12.245 -    print STDERR wrap_msg(gettext("Discard the translation of %s (only %s%% translated; need %s%%)."),
  12.246 -	$master_filename, $percent, $threshold);
  12.247 -    unlink($outfile) if (-e $outfile);
  12.248 -} else {
  12.249 -    foreach my $add (@addfiles) {
  12.250 -	unless ($doc->addendum($add)) {
  12.251 -	    unlink($outfile) if (-e $outfile);
  12.252 -	    die wrap_msg(gettext("Discard the translation of %s (addendum %s does not apply)."),
  12.253 -		$master_filename, $add);
  12.254 -	}
  12.255 -    }
  12.256 -    $doc->write($outfile);
  12.257 -}
  12.258 -
  12.259 -1;
  12.260 -
    13.1 --- a/tools/po4a/po4a-updatepo	Mon Mar 30 17:50:48 2009 +0800
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,235 +0,0 @@
    13.4 -#! /usr/bin/env perl
    13.5 -eval 'exec perl -S $0 ${1+"$@"}'
    13.6 -    if $running_under_some_shell;
    13.7 -
    13.8 -# pod-updatepo -- Update the po translation of POD data.
    13.9 -# $Id: po4a-updatepo,v 1.44 2009-03-07 12:33:10 nekral-guest Exp $
   13.10 -#
   13.11 -# Copyright 2002, 2003, 2004 by Martin Quinson (mquinson#debian.org)
   13.12 -#
   13.13 -# This program is free software; you can redistribute it and/or modify it
   13.14 -# under the terms of GPL (see COPYING).
   13.15 -
   13.16 -=head1 NAME
   13.17 -
   13.18 -po4a-updatepo - update the translation (in po format) of documentation
   13.19 -
   13.20 -=head1 SYNOPSIS
   13.21 -
   13.22 -po4a-updatepo -f E<lt>fmtE<gt> (-m E<lt>master.docE<gt>)+ (-p E<lt>XX.poE<gt>)+
   13.23 -
   13.24 -(XX.po are the outputs, all others are inputs)
   13.25 -
   13.26 -=head1 DESCRIPTION
   13.27 -
   13.28 -The po4a (po for anything) project goal is to ease translations (and more
   13.29 -interestingly, the maintenance of translations) using gettext tools on
   13.30 -areas where they were not expected like documentation.
   13.31 -
   13.32 -The C<po4a-updatepo> script is in charge of updating po files to make
   13.33 -them reflect the changes made to the original documentation file. For that,
   13.34 -it converts the documentation file to a pot file, and call L<msgmerge(1)>
   13.35 -on this new pot and on the provided po files.
   13.36 -
   13.37 -It is possible to give more than one po file (if you want to update several
   13.38 -languages at once), and several documentation files (if you want to store
   13.39 -the translations of several documents in the same po file).
   13.40 -
   13.41 -If the master document has non-ascii characters, it will convert the po files
   13.42 -to utf-8 (if they weren't already), in order to allow non-standard characters
   13.43 -in a culture independent way.
   13.44 -
   13.45 -=head1 COMMAND-LINE OPTIONS
   13.46 -
   13.47 -=over 4
   13.48 -
   13.49 -=item -f, --format
   13.50 -
   13.51 -Format of the documentation you want to handle. Use the --help-format
   13.52 -option to see the list of available formats.
   13.53 -
   13.54 -=item -m, --master
   13.55 -
   13.56 -File(s) containing the master document to translate.
   13.57 -
   13.58 -=item -M, --master-charset
   13.59 -
   13.60 -Charset of the files containing the document to translate. Note that all
   13.61 -files must have the same charset.
   13.62 -
   13.63 -=item -p, --po
   13.64 -
   13.65 -Po file(s) to update. If these files do not exist, they are created by
   13.66 -C<po4a-updatepo>.
   13.67 -
   13.68 -=item -o, --option
   13.69 -
   13.70 -Extra option(s) to pass to the format plugin and other po4a internal module.
   13.71 -Specify each option in the 'name=value' format. See the documentation of
   13.72 -each plugin for more information about the valid options and their meanings.
   13.73 -
   13.74 -=item --previous
   13.75 -
   13.76 -This option adds '--previous' to the options passed to msgmerge.
   13.77 -It requires gettext 0.16 or later.
   13.78 -
   13.79 -=item --msgmerge-opt options
   13.80 -
   13.81 -Extra options for msgmerge.
   13.82 -
   13.83 -=item -h, --help
   13.84 -
   13.85 -Show a short help message.
   13.86 -
   13.87 -=item --help-format
   13.88 -
   13.89 -List the documentation format handled by po4a.
   13.90 -
   13.91 -=item -V, --version
   13.92 -
   13.93 -Display the version of the script and exit.
   13.94 -
   13.95 -=item -v, --verbose
   13.96 -
   13.97 -Increase the verbosity of the program.
   13.98 -
   13.99 -=item -d, --debug
  13.100 -
  13.101 -Output some debugging information.
  13.102 -
  13.103 -=back
  13.104 -
  13.105 -=head1 SEE ALSO
  13.106 -
  13.107 -L<po4a(7)>, L<po4a-gettextize(1)>, L<po4a-translate(1)>, L<po4a-normalize(1)>.
  13.108 -
  13.109 -=head1 AUTHORS
  13.110 -
  13.111 - Denis Barbier <barbier@linuxfr.org>
  13.112 - Martin Quinson (mquinson#debian.org)
  13.113 -
  13.114 -=head1 COPYRIGHT AND LICENSE
  13.115 -
  13.116 -Copyright 2002, 2003, 2004, 2005 by SPI, inc.
  13.117 -
  13.118 -This program is free software; you may redistribute it and/or modify it
  13.119 -under the terms of GPL (see the COPYING file).
  13.120 -
  13.121 -=cut
  13.122 -
  13.123 -use 5.006;
  13.124 -use strict;
  13.125 -use warnings;
  13.126 -
  13.127 -use Getopt::Long qw(GetOptions);
  13.128 -use Locale::Po4a::Po;
  13.129 -
  13.130 -use Locale::Po4a::Chooser;
  13.131 -use Locale::Po4a::TransTractor;
  13.132 -use Locale::Po4a::Common;
  13.133 -
  13.134 -use Pod::Usage qw(pod2usage);
  13.135 -
  13.136 -use File::Temp;
  13.137 -
  13.138 -Locale::Po4a::Common::textdomain('po4a');
  13.139 -
  13.140 -sub show_version {
  13.141 -    Locale::Po4a::Common::show_version("po4a-updatepo");
  13.142 -    exit 0;
  13.143 -}
  13.144 -
  13.145 -
  13.146 -# init commandline parser
  13.147 -Getopt::Long::config('bundling', 'no_getopt_compat', 'no_auto_abbrev');
  13.148 -
  13.149 -# Parse our options
  13.150 -my (@masterfiles,@pofiles);
  13.151 -my ($help,$help_fmt,$verbose,$debug,$format,@options);
  13.152 -my $mastchar;
  13.153 -my $previous;
  13.154 -my $msgmerge_opt = "";
  13.155 -GetOptions('help|h'      => \$help,
  13.156 -	   'help-format' => \$help_fmt,
  13.157 -
  13.158 -	   'master|m=s'  => \@masterfiles,
  13.159 -	   'po|p=s'      => \@pofiles,
  13.160 -	   'format|f=s'  => \$format,
  13.161 -
  13.162 -	   'master-charset|M=s' => \$mastchar,
  13.163 -
  13.164 -	   'option|o=s'  => \@options,
  13.165 -
  13.166 -	   'previous'    => \$previous,
  13.167 -	   'msgmerge-opt=s' => \$msgmerge_opt,
  13.168 -    
  13.169 -	   'verbose|v'   => \$verbose,
  13.170 -	   'debug|d'     => \$debug,
  13.171 -	   'version|V'   => \&show_version)
  13.172 -    or pod2usage();
  13.173 -
  13.174 -$help && pod2usage (-verbose => 1, -exitval => 0);
  13.175 -$help_fmt && Locale::Po4a::Chooser::list(0);
  13.176 -pod2usage () if scalar @masterfiles < 1 || scalar @pofiles < 1;
  13.177 -
  13.178 -$msgmerge_opt .= " --previous" if $previous;
  13.179 -
  13.180 -my %options = (
  13.181 -    "verbose" => $verbose,
  13.182 -    "debug" => $debug);
  13.183 -
  13.184 -foreach (@options) {
  13.185 -    if (m/^([^=]*)=(.*)$/) {
  13.186 -	$options{$1}="$2";
  13.187 -    } else {
  13.188 -	$options{$_}=1;
  13.189 -    }
  13.190 -}
  13.191 -
  13.192 -# parser
  13.193 -my ($doc)=Locale::Po4a::Chooser::new($format,%options);
  13.194 -
  13.195 -map { -e $_ || die wrap_msg(gettext("File %s does not exist."), $_) } @masterfiles;
  13.196 -map { die wrap_msg(gettext("po4a-updatepo can't take the input po from stdin."))
  13.197 -	if $_ eq '-'  && !-e '-'} @pofiles;
  13.198 -
  13.199 -my ($pot_filename);
  13.200 -(undef,$pot_filename)=File::Temp->tempfile("po4a-updatepoXXXX",
  13.201 -					   DIR    => "/tmp",
  13.202 -					   SUFFIX => ".pot",
  13.203 -					   OPEN   => 0,
  13.204 -					   UNLINK => 0)
  13.205 -    or die wrap_msg(gettext("Can't create a temporary pot file: %s"), $!);
  13.206 -
  13.207 -
  13.208 -print STDERR wrap_msg(gettext("Parse input files... ")) if $verbose;
  13.209 -
  13.210 -$doc->{TT}{utf_mode} = 1;
  13.211 -
  13.212 -$doc->process('file_in_name'    => \@masterfiles,
  13.213 -	      'file_in_charset' => $mastchar,
  13.214 -	      'po_out_name'     => $pot_filename,
  13.215 -	      'debug'           => $debug,
  13.216 -	      'verbose'         => $verbose);
  13.217 -
  13.218 -print STDERR wrap_msg(gettext("done.")) if $verbose;
  13.219 -
  13.220 -
  13.221 -while (my $po_filename=shift @pofiles) {
  13.222 -    if (-e $po_filename) {
  13.223 -	print STDERR wrap_msg(gettext("Updating %s:"), $po_filename)
  13.224 -	    if $verbose;
  13.225 -	my $cmd = "msgmerge $msgmerge_opt -U $po_filename $pot_filename";
  13.226 -	system ($cmd) == 0
  13.227 -	    or die wrap_msg(gettext("Error while running msgmerge: %s"), $!);
  13.228 -	system "msgfmt --statistics -v -o /dev/null $po_filename"
  13.229 -	  if $verbose;
  13.230 -    } else {
  13.231 -	print STDERR wrap_msg(gettext("Creating %s:"), $po_filename)
  13.232 -	    if $verbose;
  13.233 -	system ("cp",$pot_filename,$po_filename) == 0
  13.234 -	    or die wrap_msg(gettext("Error while copying the po file: %s"), $!);
  13.235 -    }
  13.236 -}
  13.237 -
  13.238 -unlink($pot_filename);