po4a-0.45000755001750001750 012205217330 12477 5ustar00barbierbarbier000000000000po4a-0.45/po4a000555001750001750 16153712205217330 13502 0ustar00barbierbarbier000000000000#! /usr/bin/env perl eval 'exec perl -S $0 ${1+"$@"}' if $running_under_some_shell; # po4a -- Update both the po files and translated documents in one shoot # # Copyright 2002-2012 by SPI, inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of GPL (see COPYING). =encoding UTF-8 =head1 NAME po4a - update both the PO files and translated documents in one shot =head1 SYNOPSIS B [I] I =head1 DESCRIPTION The po4a (PO for anything) project goal is to ease translations (and more interestingly, the maintenance of translations) using gettext tools on areas where they were not expected like documentation. The B program is useful if you want to avoid calling L, L, and L in complex Makefiles when you have multiple files to translate, different format, or need to specify different options for different documents. =head1 Table of content This document is organized as follow: =head2 DESCRIPTION =head2 INTRODUCTION =head2 CONFIGURATION FILE SYNTAX =head3 Specifying the template languages =head3 Specifying the paths to translator inputs =head3 Autodetection of the paths and languages =head3 Specifying the documents to translate =head3 Specifying options for the modules =head3 Specifying aliases =head3 Split mode =head2 OPTIONS =head2 EXAMPLE =head2 SHORTCOMINGS =head2 SEE ALSO =head2 AUTHORS =head2 COPYRIGHT AND LICENSE =head3 =head1 INTRODUCTION The B program is in charge of updating both the PO files (to sync them to the original documents) and the translated documents (to sync them to the PO files). The main point is to make the use of po4a easier without having to remember of the command line options. It also allows you to mix documents having different formats into the same POT file so that you can have only one such file per project. This behaviour can be mimicked by the other tools of the po4a suite (for example with Makefiles), but it is rather difficult to do, and exhausting to redo the same complicated Makefiles for each project using po4a. The dataflow can be summarized as follow. Any changes to the master document will be reflected in the PO files, and all changes to the PO files (either manual or caused by previous step) will be reflected in translation documents. master document --> PO files --> translations The dataflow cannot be inversed in this tool, and changes in translations are overwritten by the content of the PO files. As a matter of fact, this tool cannot be used to convert existing translations to the po4a system. For that task, please refer to L. =head1 CONFIGURATION FILE SYNTAX The (mandatory) argument is the path to the configuration file to use. Its syntax aims at being simple and close to the configuration files used by the intl-tools projects. Comments in this files are noted by the char '#'. It comments everything until the end of the line. Lines can be continued by escaping the end of line. All non blank lines must begin with a [] command, followed by its arguments. (sound difficult said that way, but it is rather easy, I hope ;) =head2 Specifying the template languages B It is recommended to use B<[po_directory]> rather than B<[po4a_langs]> and B<[po4a_paths]>. See section B below. This is an optional command that can simplify the whole config file, and will make it more scalable. You have to specify a list of the languages in which you want to translate the documents. This is as simple as: [po4a_langs] fr de This will enable you to expand B<$lang> to all the specified languages in the rest of the config file. =head2 Specifying the paths to translator inputs B It is recommended to use B<[po_directory]> rather than B<[po4a_langs]> and B<[po4a_paths]>. See section B below. First, you have to specify where the translator input files (i.e. the files used by translators to do their job) are located. It can be done by such a line: [po4a_paths] doc/l10n/project.doc.pot \ fr:doc/l10n/fr.po de:doc/l10n/de.po The command is thus B<[po4a_paths]>. The first argument is the path to the POT file to use. All subsequent arguments are of the self-explanatory form: : If you've defined the template languages, you can rewrite the line above this way: [po4a_paths] doc/l10n/project.doc.pot $lang:doc/l10n/$lang.po You can also use B<$master> to refer to the document filename. In this case, B will use a split mode: one POT and one PO (for each language) will be created for each document specified in the B configuration file. See the B section. [po4a_paths] doc/$master/$master.pot $lang:doc/$master/$lang.po =head2 Autodetection of the paths and languages Another command can be used to specify the name of a directory where the PO and POT files are located. When it is used, B will detect the POT file as the only F<*.pot> file from the specified directory. B will also use the list of F<*.po> files to define the list of languages (by stripping out the extension). These languages will be used for the substitution of the B<$lang> variable in the rest of the configuration file. This command should not be used together with the B<[po4a_langs]> or B<[po4a_paths]> commands. When using this command, you have to create an empty POT file on the first invocation of B to let it know the name of the POT file. [po_directory] po4a/po/ =head2 Specifying the documents to translate You now naturally have to specify which documents are translated, their format, and where to put the translations. It can be made by such lines: [type: sgml] doc/my_stuff.sgml fr:doc/fr/mon_truc.sgml \ de:doc/de/mein_kram.sgml [type: pod] script fr:doc/fr/script.1 de:doc/de/script.1 \ add_fr:doc/l10n/script.fr.add This should be rather self-explanatory also. Note that in the second case, F is an addendum to add to the French version of this document. Please refer to L for more information about the addenda. More formally, the format is: [type: ] (:)* \ (add_:*)* If there is no modifier, I is a path to an addendum. Modifiers are =over 2 =item B Include I if this file does exist, otherwise do nothing. =item B<@> I is not a regular addendum but a file containg a list of addenda, one by line. Each addendum may be preceded by modifiers. =item B I is discarded, it is not loaded and will not be loaded by any further addendum specification. =back If you've defined the template languages, you can rewrite the line above this way: [type: pod] script $lang:doc/$lang/script.1 \ add_fr:doc/l10n/script.fr.add If all the languages had addenda with similar paths, you could also write something like: [type: pod] script $lang:doc/$lang/script.1 \ add_$lang:doc/l10n/script.$lang.add =head2 Specifying options for the modules B accepts options that will be passed to the module. These options are module specific and are specified with the B<-o> switch. If you need a specific option for one of the document you want to translate, you can also specify it in the configuration file. Options are introduced by the B keyword. The argument of the B keyword must be quoted with double quotes if it contains a space (e.g. if you specify multiple options, or an option with an argument). You can also specify options that will only apply to a specific language by using the BI keyword. Here is an example: [type:man] data-05/test2_man.1 $lang:tmp/test2_man.$lang.1 \ opt:"-k 75" opt_it:"-L UTF-8" opt_fr:-v Arguments may contain spaces if you use single quotes or escaped double quotes: [po4a_alias:man] man opt:"-o \"mdoc=NAME,SEE ALSO\" -k 20" If you want to specify the same options for many documents, you may want to use an alias (see the B section below). You can also set options for all the documents specified in the configuration file: [options] opt:"..." opt_fr:"..." =head2 Specifying aliases If you must specify the same options for multiple files, you may be interested in defining a module alias. This can be done this way: [po4a_alias:test] man opt:"-k 21" opt_es:"-o debug=splitargs" This defines a module alias named B, based on the B module, with the B<-k 21> applied to all the languages and with B<-o debug=splitargs> applied to the Spanish translation. This module alias can then be use like a regular module: [type:test] data-05/test2_man.1 $lang:tmp/test2_man.$lang.1 \ opt_it:"-L UTF-8" opt_fr:-v Note that you can specify additional options on a per file basis. =head2 Split mode The split mode is used when B<$master> is used in the B<[po4a_paths]> line. When the split mode is used, a temporary big POT and temporary big POs are used. This permits to share the translations between all the POs. If two POs have different translations for the same string, B will mark this string as fuzzy and will submit both translations in all the POs which contain this string. Then, when a translator updates the translation and removes the fuzzy tag in one PO, the translation of this string will be updated in every POs automatically. If there are name conflicts because several files have the same filename, the name of the master file can be specified by adding a CI option: [po4a_langs] de fr ja [po4a_paths] l10n/po/$master.pot $lang:l10n/po/$master.$lang.po [type: xml] foo/gui.xml $lang:foo/gui.$lang.xml master:file=foo-gui [type: xml] bar/gui.xml $lang:bar/gui.$lang.xml master:file=bar-gui =head1 OPTIONS =over 4 =item B<-k>, B<--keep> Minimal threshold for translation percentage to keep (i.e. write) the resulting file (default: 80). I.e. by default, files have to be translated at at least 80% to get written. =item B<-h>, B<--help> Show a short help message. =item B<-M>, B<--master-charset> Charset of the files containing the documents to translate. Note that all master documents must use the same charset for now. This is a known limitation, and we are working on solving this. =item B<-L>, B<--localized-charset> Charset of the files containing the localized documents. Note that all translated documents will use the same charset for now. This is a known limitation, and we are working on solving this. =item B<-A>, B<--addendum-charset> Charset of the addenda. Note that all the addenda should be in the same charset. =item B<-V>, B<--version> Display the version of the script and exit. =item B<-v>, B<--verbose> Increase the verbosity of the program. =item B<-q>, B<--quiet> Decrease the verbosity of the program. =item B<-d>, B<--debug> Output some debugging information. =item B<-o>, B<--option> Extra option(s) to pass to the format plugin. Specify each option in the 'IB<=>I' format. See the documentation of each plugin for more information about the valid options and their meanings. =item B<-f>, B<--force> Always generate the POT and PO files, even if B considers it is not necessary. The default behavior (when B<--force> is not specified) is the following: =over If the POT file already exists, it is regenerated if a master document or the configuration file is more recent. The POT file is also written in a temporary document and B verifies that the changes are really needed. Also, a translation is regenerated only if its master document, the PO file, one of its addenda or the configuration file is more recent. To avoid trying to regenerate translations which do not pass the threshold test (see B<--keep>), a file with the F<.po4a-stamp> extension can be created (see B<--stamp>). =back If a master document includes files, you should use the B<--force> flag because the modification time of these included files are not taken into account. The PO files are always re-generated based on the POT with B. =item B<--stamp> Tells B to create stamp files when a translation is not generated because it does not reach the threshold. These stamp files are named according to the expected translated document, with the F<.po4a-stamp> extension. Note: This only activates the creation of the F<.po4a-stamp> files. The stamp files are always used if they exist, and they are removed with B<--rm-translations> or when the file is finally translated. =item B<--no-translations> Do not generate the translated documents, only update the POT and PO files. =item B<--rm-translations> Remove the translated files (implies B<--no-translations>). =item B<--no-backups> This flag does nothing since 0.41, and may be removed in later releases. =item B<--rm-backups> This flag does nothing since 0.41, and may be removed in later releases. =item B<--translate-only> I Translate only the specified file. It may be useful to speed up processing if a configuration file contains a lot of files. Note that this option does not update PO and POT files. This option can be used multiple times. =item B<--variable> IB<=>I Define a variable that will be expanded in the B configuration file. Every occurrence of I<$(var)> will be replaced by I. This option can be used multiple times. =item B<--srcdir> I Set the base directory for all input documents specified in the B configuration file. =item B<--destdir> I Set the base directory for all the output documents specified in the B configuration file. =back =head2 OPTIONS WHICH MODIFY POT HEADER =over 4 =item B I[,B|B] Specify the reference format. Argument I can be one of B to not produce any reference, B to not specify the line number (more accurately all line numbers are replaced by 1), B to replace line number by an increasing counter, and B to include complete references. Argument can be followed by a comma and either B or B keyword. References are written by default on a single line. The B option wraps references on several lines, to mimic B tools (B and B). This option will become the default in a future release, because it is more sensible. The B option is available so that users who want to keep the old behavior can do so. =item B<--msgid-bugs-address> I Set the report address for msgid bugs. By default, the created POT files have no Report-Msgid-Bugs-To fields. =item B<--copyright-holder> I Set the copyright holder in the POT header. The default value is "Free Software Foundation, Inc." =item B<--package-name> I Set the package name for the POT header. The default is "PACKAGE". =item B<--package-version> I Set the package version for the POT header. The default is "VERSION". =back =head2 OPTIONS TO MODIFY PO FILES =over 4 =item B<--msgmerge-opt> I Extra options for B. Note: B<$lang> will be extended to the current language. =item B<--no-previous> This option removes B<--previous> from the options passed to B. This permits to support versions of B earlier than 0.16. =item B<--previous> This option adds B<--previous> to the options passed to B. It requires B 0.16 or later, and is activated by default. =back =head2 EXAMPLE Let's assume you maintain a program named B which has a man page F which naturally is maintained in English only. Now you as the upstream or downstream maintainer want to create and maintain the translation. First you need to create the POT file necessary to send to translators using L. So for our case we would call cd man && po4a-gettextize -f man -m foo.1 -p foo.pot You would then send this file to the appropriate language lists or offer it for download somewhere on your website. Now let's assume you received three translations before your next release: F (including an addendum F), F and F. Since you don't want to change your F(s) whenever a new translation arrives you can use B with an appropriate configuration file in your F. Let's call it F. In our example it would look like the following: [po_directory] man/po4a/po/ [type: man] man/foo.1 $lang:man/translated/$lang/foo.1 \ add_$lang:?man/po4a/add_$lang/$lang.add opt:"-k 80" In this example we assume that your generated man pages (and all PO and addenda files) should be stored in F (respectively in F and F) below the current directory. In our example the F directory would include F, F and F, and the F directory would include F. Note the use of the modifier B as only the German translation (F) is accompanied by an addendum. To actually build the translated man pages you would then (once!) add the following line in the B target of the appropriate F: po4a po4a.cfg Once this is set up you don't need to touch the F when a new translation arrives, i.e. if the French team sends you F and F then you simply drop them respectively in F and F and the next time the programm is build the French translation is automatically build as well in F. Note that you still need an appropriate target to install localized manual pages with English ones. Finally if you do not store generated files into your version control system, you will need a line in your B target as well: -rm -rf man/translated =head1 SHORTCOMINGS =over 4 =item Duplicates some code with the BI<*> programs. =back Patch welcome ;) =head1 SEE ALSO L, L, L, L, L, L, L =head1 AUTHORS Denis Barbier Nicolas François Martin Quinson (mquinson#debian.org) =head1 COPYRIGHT AND LICENSE Copyright 2002-2012 by SPI, inc. This program is free software; you may redistribute it and/or modify it under the terms of GPL (see the COPYING file). =cut use 5.006; use strict; use warnings; use Getopt::Long qw(GetOptions); use Locale::Po4a::Chooser; use Locale::Po4a::TransTractor; use Locale::Po4a::Common; use Locale::Po4a::Po qw(move_po_if_needed); use Pod::Usage qw(pod2usage); use File::Temp; use File::Basename; use File::Copy; use File::Spec; use Fcntl; # sysopen flags use Cwd; # cwd use Config; Locale::Po4a::Common::textdomain('po4a'); sub show_version { Locale::Po4a::Common::show_version("po4a"); exit 0; } # keep the command line arguments my @ORIGINAL_ARGV = @ARGV; # Parse the options provided on the command line, or in argument sub get_options { if (defined $_[0]) { @ARGV = @_; } else { @ARGV = @ORIGINAL_ARGV; } # temporary array for GetOptions my @verbose = (); my @options = (); my @variables = (); my $previous; my $noprevious; my %opts = ( "help" => 0, "type" => "", "debug" => 0, "verbose" => 0, "quiet" => 0, "no-translations" => 0, "rm-translations" => 0, "no-backups" => 0, "rm-backups" => 0, "threshold" => 80, "mastchar" => "", "locchar" => "", "addchar" => "", "options" => {"verbose" => 0, "debug" => 0}, "variables" => {}, "partial" => [], "porefs" => "full", "copyright-holder"=> undef, "msgid-bugs-address"=> undef, "package-name" => undef, "package-version" => undef, "msgmerge-opt" => "", "srcdir" => undef, "destdir" => undef, "calldir" => cwd() ); Getopt::Long::config('bundling', 'no_getopt_compat', 'no_auto_abbrev'); GetOptions( 'help|h' => \$opts{"help"}, 'master-charset|M=s' => \$opts{"mastchar"}, 'localized-charset|L=s' => \$opts{"locchar"}, 'addendum-charset|A=s' => \$opts{"addchar"}, 'verbose|v' => \@verbose, 'debug|d' => \$opts{"debug"}, 'force|f' => \$opts{"force"}, 'stamp' => \$opts{"stamp"}, 'quiet|q' => \$opts{"quiet"}, 'keep|k=s' => \$opts{"threshold"}, 'no-translations' => \$opts{"no-translations"}, 'rm-translations' => \$opts{"rm-translations"}, 'translate-only=s' => \@{$opts{"partial"}}, 'no-backups' => \$opts{"no-backups"}, 'rm-backups' => \$opts{"rm-backups"}, 'version|V' => \&show_version, 'option|o=s' => \@options, 'variable=s' => \@variables, 'porefs=s' => \$opts{"porefs"}, 'copyright-holder=s' => \$opts{"copyright-holder"}, 'msgid-bugs-address=s' => \$opts{"msgid-bugs-address"}, 'package-name=s' => \$opts{"package-name"}, 'package-version=s' => \$opts{"package-version"}, 'no-previous' => \$noprevious, 'previous' => \$previous, 'msgmerge-opt=s' => \$opts{"msgmerge-opt"}, 'srcdir=s' => \$opts{"srcdir"}, 'destdir=s' => \$opts{"destdir"} ) or pod2usage(); $opts{"verbose"} = scalar @verbose; $opts{"verbose"} = 0 if $opts{"quiet"}; $opts{"verbose"} ||= 1 if $opts{"debug"}; $opts{"msgmerge-opt"} .= " --previous" unless $noprevious; # options to transmit to the modules $opts{"options"} = { "verbose" => $opts{"verbose"}, "debug" => $opts{"debug"} }; foreach (@options) { if (m/^([^=]*)=(.*)$/) { $opts{"options"}{$1}="$2"; } else { $opts{"options"}{$_}=1; } } foreach (@variables) { if (m/^([^=]*)=(.*)$/) { $opts{"variables"}{$1}="$2"; } } # The rm- options imply the no- $opts{"no-translations"} = 1 if $opts{"rm-translations"}; if (defined $opts{"srcdir"} and not -d $opts{"srcdir"}) { die wrap_msg(gettext("Invalid %s. Directory %s does not exist."), "srcdir", $opts{"srcdir"}); } if (defined $opts{"destdir"} and not -d $opts{"destdir"}) { die wrap_msg(gettext("Invalid %s. Directory %s does not exist."), "destdir", $opts{"destdir"}); } return %opts; } # Parse a config line and extract the parameters that correspond to options. # These options are appended to the options provided in argument (as a # reference to an hash). The options are sorted by category in this hash. # The categories are: global and the various languages. sub parse_config_options { my $ref = shift; # a line reference for the die messages my $line = shift; # the line to parse my $orig_line = $line; # keep the original line for die messages my $options = shift; # reference to an hash of options while (defined $line and $line !~ m/^\s*$/) { if ($line =~ m/^\s*opt(?:_(.+?))?:\s*(.+?)\s*$/) { my $lang = $1; $line = $2; my $opt = ""; if ($line =~ m/^\s*"(.+?(?{$lang}) { $options->{$lang} = $opt; } else { $options->{$lang} .= " $opt"; } } else { last; } } $line = "" unless defined $line; return $line; } my %po4a_opts = get_options(@ARGV); # Argument check $po4a_opts{"help"} && pod2usage (-verbose => 1, -exitval => 0); sub run_cmd { my $cmd = shift; print $cmd."\n" if $po4a_opts{"debug"}; my $out = qx/$cmd 2>&1/; print $out if ($po4a_opts{"verbose"}); unless ($? == 0) { my $err = ""; if ($? == -1) { $err = sprintf(gettext("failed to execute '%s': %s."), $cmd, $!); } elsif ($? & 127) { if ($? & 128) { $err = sprintf(gettext("'%s' died with signal %d, ". "with coredump."), $cmd, $? & 127); } else { $err = sprintf(gettext("'%s' died with signal %d, ". "without coredump."), $cmd, $? & 127); } } else { $err = sprintf(gettext("'%s' exited with value %d."), $cmd, $? >> 8); } die wrap_msg(gettext("Error: %s"), $err); } } my $config_file= shift(@ARGV) || pod2usage(); # Check file existence -e $config_file || die wrap_msg(gettext("File %s does not exist."), $config_file); # Parse the config file my (@langs); my (%aliases); # module aliases ([po4a_alias:...] my ($pot_filename) = ""; my (%po_filename); # po_files: '$lang'=>'$path' my (%document); # '$master'=> {'format'=>'$format'; '$lang'=>'$path'; 'add_$lang'=>('$path','$path') } my $doc_count = 0; my %partial = ( 'master' => {}, 'files' => {}, 'lang' => {} ); open CONFIG,"<","$config_file" or die wrap_msg(gettext("Can't open %s: %s"), $config_file, $!); my ($line,$nb) = ("",0); while () { $nb++; s/#.*//; $line.=$_; $line =~ s/\t/ /g; $line =~ s/ +/ /g; while ($line =~ m/\$\((\w+)\)/) { if (defined $po4a_opts{"variables"}{$1}) { $line =~ s/\$\((\Q$1\E)\)/$po4a_opts{"variables"}{$1}/g; } else { die wrap_ref_mod("$config_file:$nb", "", gettext("Unknown variable: %s"), $1); } } $line =~ s/^ //; $line =~ s/ $//; chomp($line); next if ($line =~ s/\\$//); next unless ($line =~ /\S/); my $args = $line; die wrap_ref_mod("$config_file:$nb", "", gettext("Syntax error: %s"), $line) unless ($args =~ s/^\[([^\]]*)\] *//); my $cmd = $1; my $main = ($args=~ s/^(\S+) *// ? $1 : ""); if (@langs) { # Expand the $lang templates my($args2) = ""; foreach my $arg (split(/ /,$args)) { if ( $arg =~ /\$lang\b/ ) { # Expand for all the langs foreach my $lang (@langs) { my($arg2) = $arg; $arg2 =~ s/\$lang\b/$lang/g; $args2 .= $arg2." "; } } else { # Leave the argument as is $args2 .= $arg." "; } } $args = $args2; } print "cmd=[$cmd]; main=$main; args=\"$args\"\n" if $po4a_opts{"debug"}; if ($cmd eq "po4a_paths") { die wrap_ref_mod("$config_file:$nb", "", gettext("'%s' redeclared"), "po4a_path") if (length $pot_filename); $pot_filename = $main; foreach my $arg (split(/ /,$args)) { die wrap_ref_mod("$config_file:$nb", "", gettext("Unparsable argument '%s'."), $arg) unless ($arg =~ /^([^:]*):(.*)/); $po_filename{$1}=$2 if $1 ne '$lang'; } } elsif ($cmd eq "po4a_langs") { die wrap_ref_mod("$config_file:$nb", "", gettext("'%s' redeclared"), "po4a_langs") if (@langs); @langs = split(/ /,$main." ".$args); } elsif ($cmd eq "po_directory") { die wrap_ref_mod("$config_file:$nb", "", gettext("The list of languages cannot be set twice.")) if scalar @langs; die wrap_ref_mod("$config_file:$nb", "", gettext("The POT file cannot be set twice.")) if length $pot_filename; chdir $po4a_opts{"srcdir"} if (defined $po4a_opts{"srcdir"}); my $po_directory = $main; die wrap_ref_mod("$config_file:$nb", "", gettext("'%s' is not a directory"), $po_directory) unless (-d $po_directory); opendir PO_DIR, $po_directory or die wrap_ref_mod("$config_file:$nb", "", gettext("Cannot list the '%s' directory"), $po_directory); foreach my $f (readdir PO_DIR) { next unless -f "$po_directory/$f"; if ($f =~ m/^(.*)\.po$/) { push @langs, $1; $po_filename{$1} = "$po_directory/$f"; } if ($f =~ m/\.pot$/) { if (length $pot_filename) { die wrap_ref_mod("$config_file:$nb", "", gettext("too many POT files: %s %s"), $pot_filename, "$po_directory/$f"); } else { $pot_filename = "$po_directory/$f"; } } } if (not @langs) { warn wrap_ref_mod("$config_file:$nb", "", gettext("no PO files found in %s"), $po_directory); } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); } elsif ($cmd =~ m/type: *(.*)/) { chdir $po4a_opts{"srcdir"} if (defined $po4a_opts{"srcdir"}); if (defined $document{$main}{'format'}) { warn wrap_ref_mod("$config_file:$nb", "", gettext("The '%s' master file was specified earlier in the ". "configuration file. This may cause problems with ". "options."), $main) unless ($po4a_opts{"quiet"}); } elsif (not -e $main) { die wrap_ref_mod("$config_file:$nb", "", gettext("The '%s' master file does not exist."), $main); } if (scalar @{$po4a_opts{"partial"}}) { foreach my $file (@{$po4a_opts{"partial"}}) { if ($args =~ m/(\S+):\Q$file\E\b/) { $partial{'lang'}{$1} = 1; $partial{'master'}{$main} = 1; $partial{'files'}{$file} = 1; last; } } } $document{$main}{'format'} = $1; $document{$main}{'pos'} = $doc_count; $doc_count++; # Options my %options; # 1. Use the global options ([opt] ...) %options = %{$document{''}{'options'}} if defined $document{''}{'options'}; # 2. Merge the alias options if (defined $aliases{$1}) { $document{$main}{'format'} = $aliases{$1}{"module"}; if (defined $aliases{$1}{"options"}) { %options = %{$aliases{$1}{"options"}}; # XXX not a merge, but overwrite } } # 3. If this file was already specified, reuse the previous # options (no merge) %options = %{$document{$main}{'options'}} if defined $document{$main}{'options'}; # 4. Handle "master:file=" flags for "$master" substitution in strings if ($args =~ s/ +master:file=(\S+)//) { $document{$main}{'master'} = $1; } # 5. Merge the document specific options # separate the end of the line, which contains options. # Something more clever could be done to allow options in the # middle of a line. if ($args =~ m/^(.*?) +(opt(_.+)?:(.*))$/) { $args = $1; $args = "" unless defined $args; $args .= " ".parse_config_options("$config_file:$nb", $2, \%options); } %{$document{$main}{'options'}} = %options; my %discarded = (); my @remaining_args = split(/ /,$args); while (@remaining_args) { my $arg = shift(@remaining_args); die wrap_ref_mod("$config_file:$nb", "", gettext("Unparsable argument '%s' (%s)."), $arg, $line) unless ($arg =~ /^([^:]*):(.*)/); my ($lang,$trans)=($1,$2); die wrap_ref_mod("$config_file:$nb", "", gettext("The translated and master file are the same.")) if ($main eq $trans); if ($lang =~ /^add_/) { my $modifiers; $trans =~ s/^([@!?]+)// and $modifiers = $1; next if defined($discarded{$trans}); if (defined $modifiers) { if ($modifiers =~ m/!/) { $discarded{$trans} = 1; next; } next if ($modifiers =~ m/\?/ and not -e $trans); if ($modifiers =~ m/@/) { open LIST,"<","$trans" or die wrap_msg(gettext("Can't open %s: %s"), $trans, $!); my @new_list = (); while() { chomp; s/\s+$//; next if length($_) == 0 or $_ =~ m/^\s*#/; while (m/\$\((\w+)\)/) { if (defined $po4a_opts{"variables"}{$1}) { s/\$\((\Q$1\E)\)/$po4a_opts{"variables"}{$1}/g; } else { die wrap_ref_mod("$config_file:$nb", "", gettext("Unknown variable: %s"), $1); } } push(@new_list, "$lang:$_"); } close LIST; unshift(@remaining_args, @new_list); } else { push @{$document{$main}{$lang}},$trans; } } else { push @{$document{$main}{$lang}},$trans; } } else { die wrap_ref_mod("$config_file:$nb", "", gettext("Translation of %s in %s redefined"), $main, $lang) if (defined $document{$main}{$lang}); $document{$main}{$lang} = $trans; } } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); } elsif ($cmd =~ m/po4a_alias: *(.*)/) { my $name = $1; my %alias = (); $alias{"module"} = $main; my %options; $args = parse_config_options("$config_file:$nb", $args, \%options); %{$alias{"options"}} = %options; %{$aliases{$name}} = %alias; } elsif ($cmd eq "options") { my %options; my $o = $line; $o =~ s/.*?\[options\] +//; if (defined $document{''}{"options"}) { %options = %{$document{''}{"options"}}; } parse_config_options("$config_file:$nb", $o, \%options); %{$document{''}{"options"}} = %options; } else { die wrap_ref_mod("$config_file:$nb", "", gettext("Unparsable command '%s'."), $cmd); } $line = ""; } close CONFIG; # don't care about error here die wrap_msg(gettext("po4a_paths not declared. Dunno where to find the POT and PO files")) unless (length $pot_filename); sub split_opts { my $options = shift; my $options_orig = $options; my @opts = (); $options =~ s/\\"/"/g; while (length $options) { my $o = ""; while (length $options and $options !~ /^ /s) { if ( ($options =~ m/^(["'])/) and ($options !~ m/^(["'])(?:\\.|(?!\1)[^\\])*\1/)) { die wrap_msg(gettext("Cannot parse option line (missing >%s '$path' my %split_pot; # pot_files: '$master' => '$path' # make a big pot my $update_pot_file = 0; if ($pot_filename =~ m/\$master/) { print wrap_msg(gettext("Split mode, creating a temporary POT")."\n") if $po4a_opts{"verbose"}; if (scalar @{$po4a_opts{"partial"}}) { print wrap_msg(gettext("Disabling --translate-only option, it is not supported in split mode")."\n"); $po4a_opts{"partial"} = []; } foreach my $master (keys %document) { next if ($master eq ''); my $m = $document{$master}{"master"} || basename $master; my $master_pot = $pot_filename; $master_pot =~ s/\$master/$m/g; $split_pot{$master} = $master_pot; } # The POT needs to be generated anyway. $update_pot_file = 1; $po4a_opts{"split"} = 1; } else { if (scalar @{$po4a_opts{"partial"}}) { # Skip documents not specified, strings are read directly from POT file foreach my $master (keys %document) { next unless length $master; delete $document{$master} unless exists $partial{'master'}{$master}; } # Do not read PO files if no file is processed for this language foreach my $lang (keys %po_filename) { delete $po_filename{$lang} unless exists $partial{'lang'}{$lang}; } } if (not scalar @{$po4a_opts{"partial"}}) { chdir $po4a_opts{"srcdir"} if (defined $po4a_opts{"srcdir"}); if (-e $pot_filename) { my $modtime = (stat $pot_filename)[9]; # The POT needs to be re-generated if a master document is more recent # than the POT. foreach my $master (keys %document) { next if ($master eq ''); if ((stat $master)[9] >= $modtime) { $update_pot_file = 1; last; } } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); if ((stat $config_file)[9] > $modtime) { # The configuration file was modified after the POT. # Maybe a new document, or new options $update_pot_file = 1; } if ($po4a_opts{"force"}) { $update_pot_file = 1; } print wrap_msg(gettext("Updating %s:"), $pot_filename) if ($update_pot_file and $po4a_opts{"verbose"}); } else { print wrap_msg(gettext("Creating %s:"), $pot_filename) if $po4a_opts{"verbose"}; $update_pot_file = 1; } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); } } if ($update_pot_file) { chdir $po4a_opts{"srcdir"} if (defined $po4a_opts{"srcdir"}); my %pot_options; foreach (qw(porefs msgid-bugs-address copyright-holder package-name package-version)) { if (defined $po4a_opts{$_}) { $pot_options{$_} = $po4a_opts{$_}; } } my $potfile=Locale::Po4a::Po->new(\%pot_options); chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); foreach my $master (sort { return -1 if ($a eq ""); return 1 if ($b eq ""); $document{$a}{'pos'} <=> $document{$b}{'pos'} } keys %document) { next if ($master eq ''); my %file_opts = %po4a_opts; my $options = $document{$master}{"options"}{"global"}; if (defined $options) { %file_opts = get_options(@ORIGINAL_ARGV, split_opts($options)); } my $doc=Locale::Po4a::Chooser::new($document{$master}{'format'}, %{$file_opts{"options"}}); # We ensure that the generated po will be in utf-8 if the input document # isn't entirely in ascii $doc->{TT}{utf_mode} = 1; $doc->setpoout($potfile); my @file_in_name; push @file_in_name, $master; $doc->process('file_in_name' => \@file_in_name, 'file_in_charset' => $file_opts{"mastchar"}, 'srcdir' => $po4a_opts{"srcdir"}, 'destdir' => $po4a_opts{"destdir"}, 'calldir' => $po4a_opts{"calldir"}); $potfile = $doc->getpoout(); } chdir $po4a_opts{"srcdir"} if (defined $po4a_opts{"srcdir"}); if ($po4a_opts{"split"}) { (undef,$pot_filename)=File::Temp::tempfile("po4aXXXX", DIR => $ENV{TMPDIR} || "/tmp", SUFFIX => ".pot", OPEN => 0, UNLINK => 0) or die wrap_msg(gettext("Can't create a temporary POT file: %s"), $!); $potfile->write($pot_filename); } else { if ($po4a_opts{"force"}) { $potfile->write($pot_filename); } else { $potfile->write_if_needed($pot_filename); } } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); print wrap_msg(gettext(" (%d entries)"), $potfile->count_entries()) unless ($po4a_opts{"quiet"}); } if ($po4a_opts{"split"}) { # Generate a .pot for each document foreach my $master (keys %document) { next if ($master eq ''); my $tmp_file; # Create a temporary POT, and check if the old one needs to be # updated (unless --force was specified). unless ($po4a_opts{"force"}) { (undef,$tmp_file)=File::Temp::tempfile("po4aXXXX", DIR => $ENV{TMPDIR} || "/tmp", SUFFIX => ".pot", OPEN => 0, UNLINK => 0) or die wrap_msg(gettext("Can't create a temporary POT file: %s"), $!); } chdir $po4a_opts{"srcdir"} if (defined $po4a_opts{"srcdir"}); my $dir = dirname($split_pot{$master}); if (not -d $dir) { mkdir $dir or die wrap_msg(gettext("Can't create directory '%s': %s"), $dir, $!); } my $cmd = "msggrep".$Config{_exe}." -N '$master' -o ". ($po4a_opts{"force"}?$split_pot{$master}:$tmp_file). " $pot_filename"; run_cmd($cmd); unless ($po4a_opts{"force"}) { move_po_if_needed($tmp_file, $split_pot{$master}, 0); } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); } # Generate a complete .po foreach my $lang (sort keys %po_filename) { my $tmp_bigpo; (undef,$tmp_bigpo)=File::Temp::tempfile("po4aXXXX", DIR => $ENV{TMPDIR} || "/tmp", SUFFIX => "-$lang.po", OPEN => 0, UNLINK => 0) or die wrap_msg(gettext("Can't create a temporary PO file: %s"), $!); my $cmd_cat = ""; foreach my $master (keys %document) { next if ($master eq ''); my $m = $document{$master}{"master"} || basename $master; my $master_po = $po_filename{$lang}; $master_po =~ s/\$master/$m/g; if (-e "$master_po") { $cmd_cat .= " $master_po"; } $split_po{$lang}{$master} = $master_po; } if (length $cmd_cat) { $cmd_cat = "msgcat".$Config{_exe}." -o $tmp_bigpo $cmd_cat"; run_cmd($cmd_cat); } # We do not need to keep the original name with $master $po_filename{$lang} = $tmp_bigpo; } } # update all po files my $lang; if (not scalar @{$po4a_opts{"partial"}}) { foreach $lang (sort keys %po_filename) { chdir $po4a_opts{"srcdir"} if (defined $po4a_opts{"srcdir"}); if (-e $po_filename{$lang}) { print wrap_msg(gettext("Updating %s:")." ", $po_filename{$lang}) if ($po4a_opts{"verbose"}); my $msgmerge_opt = $po4a_opts{"msgmerge-opt"}; $msgmerge_opt =~ s/\$lang\b/$lang/g if scalar @langs; my $cmd = "msgmerge".$Config{_exe}." -U ".$po_filename{$lang}." $pot_filename ".$msgmerge_opt." --backup=none"; run_cmd($cmd); my @cmd = ("msgfmt".$Config{_exe}, "--statistics", "-v", "-o", File::Spec->devnull(), $po_filename{$lang}); system (@cmd) if $po4a_opts{"verbose"}; } else { print wrap_msg(gettext("Creating %s:"), $po_filename{$lang}) if $po4a_opts{"verbose"}; my $cmd = "msginit".$Config{_exe}." -i $pot_filename --locale $lang -o ".$po_filename{$lang}." --no-translator"; run_cmd($cmd); } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); } } if ($po4a_opts{"split"}) { chdir $po4a_opts{"srcdir"} if (defined $po4a_opts{"srcdir"}); # We don't need the tmp big POT anymore unlink($pot_filename); # Split the complete PO in multiple POs foreach $lang (sort keys %po_filename) { foreach my $master (keys %document) { next if ($master eq ''); my $tmp_file; # Create a temporary PO, and check if the old one needs to be # updated (unless --force was specified). (undef,$tmp_file)=File::Temp::tempfile("po4aXXXX", DIR => $ENV{TMPDIR} || "/tmp", SUFFIX => ".po", OPEN => 0, UNLINK => 0) or die wrap_msg( gettext("Can't create a temporary POT file: %s"), $!); my $cmd; # Create an empty PO or copy the original PO header. # This permits to keep the header. if (-f $split_po{$lang}{$master}) { $cmd = "msggrep".$Config{_exe}." --force-po -v -K -e '.'". " -o ".$tmp_file. " ".$split_po{$lang}{$master}; } else { $cmd = "msginit".$Config{_exe}." --no-translator -l ".$lang. " -i ".$split_pot{$master}. " -o ".$tmp_file; } run_cmd($cmd); # Update the PO according to the new POT and to the big PO # (compendium). $cmd = "msgmerge".$Config{_exe}." -U -C ".$po_filename{$lang}. " --backup=none ".$po4a_opts{"msgmerge-opt"}. " $tmp_file ".$split_pot{$master}; run_cmd($cmd); my $dir = dirname($split_po{$lang}{$master}); if (not -d $dir) { mkdir $dir or die wrap_msg(gettext("Can't create directory '%s': %s"), $dir, $!); } unless ($po4a_opts{"force"}) { move_po_if_needed($tmp_file, $split_po{$lang}{$master}, 0); } else { move $tmp_file, $split_po{$lang}{$master} or die wrap_msg(dgettext("po4a", "Can't move %s to %s: %s."), $tmp_file, $split_po{$lang}{$master}, $!); } } } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); } if (not $po4a_opts{"no-translations"}) { # update all translations foreach $lang (sort keys %po_filename) { # Read the $lang PO once, no options for the creation my $po = Locale::Po4a::Po->new(); chdir $po4a_opts{"srcdir"} if (defined $po4a_opts{"srcdir"}); $po->read($po_filename{$lang}); chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); DOC: foreach my $master (sort { return -1 if ($a eq ""); return 1 if ($b eq ""); $document{$a}{'pos'} <=> $document{$b}{'pos'} } keys %document) { next if ($master eq ''); next unless defined $document{$master}{$lang}; if (scalar @{$po4a_opts{"partial"}}) { next unless defined $partial{'files'}{$document{$master}{$lang}}; } unless ($po4a_opts{"force"}) { chdir $po4a_opts{"destdir"} if (defined $po4a_opts{"destdir"}); my $stampfile = $document{$master}{$lang}; unless (-e $document{$master}{$lang}) { $stampfile = $document{$master}{$lang}.".po4a-stamp"; } $stampfile = File::Spec->rel2abs($stampfile); chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"destdir"}); my @files = ($master, $po_filename{$lang}, File::Spec->rel2abs($config_file)); if (defined $document{$master}{"add_$lang"}) { push @files, @{$document{$master}{"add_$lang"}}; } chdir $po4a_opts{"srcdir"} if (defined $po4a_opts{"srcdir"}); unless (is_older($stampfile, @files)) { print wrap_msg(gettext("%s doesn't need to be updated."), $document{$master}{$lang}) if ($po4a_opts{"verbose"}); chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); next DOC; } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); } my %file_opts = %po4a_opts; my $options = ""; if (defined $document{$master}{"options"}{"global"}) { $options .= $document{$master}{"options"}{"global"}; } # append the language options if (defined $document{$master}{"options"}{$lang}) { $options .= " ".$document{$master}{"options"}{$lang}; } if (defined $options) { # also use the options provided on the command line %file_opts = get_options(@ORIGINAL_ARGV, split_opts($options)); } my $doc=Locale::Po4a::Chooser::new($document{$master}{'format'}, %{$file_opts{"options"}}); my @file_in_name; push @file_in_name, $master; # Reuse the already parsed PO, do not use the po_in_name # option of process. $doc->{TT}{po_in} = $po; $doc->{TT}{po_in}->stats_clear(); $doc->process('file_in_name' => \@file_in_name, 'file_out_name' => $document{$master}{$lang}, 'file_in_charset' => $file_opts{"mastchar"}, 'file_out_charset' => $file_opts{"locchar"}, 'addendum_charset' => $file_opts{"addchar"}, 'srcdir' => $po4a_opts{"srcdir"}, 'destdir' => $po4a_opts{"destdir"}, 'calldir' => $po4a_opts{"calldir"}); my ($percent,$hit,$queries) = $doc->stats(); if ($percent<$file_opts{"threshold"}) { print wrap_msg(gettext("Discard %s (%s of %s strings; only %s%% translated; need %s%%)."), $document{$master}{$lang}, $hit, $queries, $percent, $file_opts{"threshold"}); chdir $po4a_opts{"destdir"} if (defined $po4a_opts{"destdir"}); unlink($document{$master}{$lang}) if (-e $document{$master}{$lang}); unless ($po4a_opts{"force"}) { if ($po4a_opts{"stamp"}) { touch($document{$master}{$lang}.".po4a-stamp"); print wrap_msg(gettext("Timestamp %s created."), $document{$master}{$lang}.".po4a-stamp") if ($po4a_opts{"verbose"}); } } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"destdir"}); next DOC; } unless ($po4a_opts{"force"}) { chdir $po4a_opts{"destdir"} if (defined $po4a_opts{"destdir"}); if (-e $document{$master}{$lang}.".po4a-stamp") { unlink $document{$master}{$lang}.".po4a-stamp"; print wrap_msg(gettext("Timestamp %s removed."), $document{$master}{$lang}.".po4a-stamp") if ($po4a_opts{"verbose"}); } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"destdir"}); } if (defined ($document{$master}{"add_$lang"})) { chdir $po4a_opts{"srcdir"} if (defined $po4a_opts{"srcdir"}); foreach my $add (@{$document{$master}{"add_$lang"}}) { if ( !$doc->addendum($add) ) { die wrap_msg(gettext("Addendum %s does NOT apply to %s (translation discarded)."), $add, $document{$master}{$lang}); chdir $po4a_opts{"destdir"} if (defined $po4a_opts{"destdir"}); unlink($document{$master}{$lang}) if (-e $document{$master}{$lang}); chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"destdir"}); next DOC; } } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); } if ($file_opts{"verbose"}) { if ($percent == 100) { print wrap_msg(gettext("%s is %s%% translated (%s strings)."), $document{$master}{$lang}, $percent, $queries); } else { print wrap_msg(gettext("%s is %s%% translated (%s of %s strings)."), $document{$master}{$lang}, $percent, $hit, $queries); } } chdir $po4a_opts{"destdir"} if (defined $po4a_opts{"destdir"}); $doc->write($document{$master}{$lang}); chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"destdir"}); } } } if ($po4a_opts{"split"}) { chdir $po4a_opts{"srcdir"} if (defined $po4a_opts{"srcdir"}); # We don't need the tmp big POs anymore foreach $lang (keys %po_filename) { unlink $po_filename{$lang}; } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"srcdir"}); } if ($po4a_opts{"rm-translations"}) { # Delete the translated documents chdir $po4a_opts{"destdir"} if (defined $po4a_opts{"destdir"}); foreach $lang (keys %po_filename) { foreach my $master (keys %document) { next if ($master eq ''); unlink $document{$master}{$lang}; unlink $document{$master}{$lang}.".po4a-stamp"; } } chdir $po4a_opts{"calldir"} if (defined $po4a_opts{"destdir"}); } sub touch { my $file = shift; if (-e $file) { utime undef, undef, $file; } else { sysopen(FH,$file,O_WRONLY|O_CREAT|O_NONBLOCK|O_NOCTTY) or croak("Can't create $file : $!"); close FH or croak("Can't close $file : $!"); } } sub is_older { my $file = shift; my @files = @_; return 1 unless (-e $file); my $older = 0; my $modtime = (stat $file)[9]; for my $f (@files) { if (-e $f and (stat $f)[9] > $modtime) { $older = 1; last; } } return $older; } __END__ po4a-0.45/MANIFEST000444001750001750 2100112205217330 13777 0ustar00barbierbarbier000000000000Build.PL changelog COPYING doc/addendum.ca doc/addendum.es doc/addendum.fr doc/addendum.it doc/addendum.ja doc/addendum.pl doc/addendum_man.de doc/addendum_man.es doc/addendum_man.fr doc/addendum_man.ja doc/addendum_man.pl doc/po4a-build.conf.5.pod doc/po4a-runtime.7.pod doc/po4a.7.pod lib/Locale/Po4a/AsciiDoc.pm lib/Locale/Po4a/BibTeX.pm lib/Locale/Po4a/Chooser.pm lib/Locale/Po4a/Common.pm lib/Locale/Po4a/Dia.pm lib/Locale/Po4a/Docbook.pm lib/Locale/Po4a/Guide.pm lib/Locale/Po4a/Halibut.pm lib/Locale/Po4a/Ini.pm lib/Locale/Po4a/KernelHelp.pm lib/Locale/Po4a/LaTeX.pm lib/Locale/Po4a/Man.pm lib/Locale/Po4a/Po.pm lib/Locale/Po4a/Pod.pm lib/Locale/Po4a/Sgml.pm lib/Locale/Po4a/TeX.pm lib/Locale/Po4a/Texinfo.pm lib/Locale/Po4a/Text.pm lib/Locale/Po4a/TransTractor.pm lib/Locale/Po4a/Wml.pm lib/Locale/Po4a/Xhtml.pm lib/Locale/Po4a/Xml.pm MANIFEST This list of files META.json META.yml NEWS po/bin/af.po po/bin/ca.po po/bin/cs.po po/bin/da.po po/bin/de.po po/bin/eo.po po/bin/es.po po/bin/et.po po/bin/eu.po po/bin/fr.po po/bin/hr.po po/bin/id.po po/bin/it.po po/bin/ja.po po/bin/kn.po po/bin/ko.po po/bin/nb.po po/bin/nl.po po/bin/pl.po po/bin/po4a.pot po/bin/pt.po po/bin/pt_BR.po po/bin/ru.po po/bin/sl.po po/bin/sv.po po/bin/uk.po po/bin/vi.po po/bin/zh_CN.po po/bin/zh_HK.po po/pod.cfg po/pod/ca.po po/pod/de.po po/pod/es.po po/pod/fr.po po/pod/it.po po/pod/ja.po po/pod/pl.po po/pod/po4a-pod.pot po/pod/pt.po po/pod/ru.po po4a po4a-build.conf po4a-gettextize po4a-normalize po4a-translate po4a-updatepo Po4aBuilder.pm README README.maintainers README.tests README.translators scripts/msgsearch scripts/msguntypot scripts/po4aman-display-po scripts/po4apod-display-po share/doc/po4a-build.xml share/doc/po4aman-display-po.xml share/doc/po4apod-display-po.xml share/Makevars-perl.example share/Makevars-shell.example share/po4a-build share/po4a-build.conf.example share/po4a-build.make share/README t/01-classes.t t/02-TransTractors.t t/03-addendums.t t/04-charsets.t t/05-config.t t/06-addendums.t t/10-discard-fuzzy.t t/11-plural.t t/12-porefs.t t/20-sgml.t t/21-dia.t t/23-man.t t/24-tex.t t/25-xhtml.t t/26-ini.t t/27-xml.t t/28-msguntypot.t t/29-wml.t t/30-asciidoc.t t/compare-po.pl t/data-02/man t/data-02/man.fr t/data-02/man.fr-normalized t/data-02/man.po t/data-02/man.po-empty t/data-02/man.po-ok t/data-02/pod t/data-02/pod.fr t/data-02/pod.fr-normalized t/data-02/pod.po t/data-02/pod.po-empty t/data-02/pod.po-ok t/data-03/man t/data-03/man.addendum1 t/data-03/man.addendum2 t/data-03/man.addendum3 t/data-03/man.addendum4 t/data-03/man.fr t/data-03/man.fr.add1 t/data-03/man.fr.add2 t/data-03/man.fr.add3 t/data-03/man.fr.add4 t/data-03/man.po-ok t/data-04/ascii-iso8859.po-ok t/data-04/ascii.po-ok t/data-04/iso8859.po-ok t/data-04/text-ascii.pod t/data-04/text-iso8859.pod t/data-04/text-iso8859.pod-ok t/data-04/text-iso8859_.pod t/data-04/trans.po t/data-04/utf.po t/data-04/utf.po-ok t/data-04/utf.pod-ok t/data-05/test0.conf t/data-05/test0.err t/data-05/test0.fr.po t/data-05/test0.fr.po-empty t/data-05/test0.pot t/data-05/test0_man.1 t/data-05/test0_man.fr.1 t/data-05/test1.err t/data-05/test2.conf t/data-05/test2.de.po t/data-05/test2.de.po-empty t/data-05/test2.err t/data-05/test2.es.po t/data-05/test2.es.po-empty t/data-05/test2.fr.po t/data-05/test2.fr.po-empty t/data-05/test2.it.po t/data-05/test2.it.po-empty t/data-05/test2.pot t/data-05/test2_man.1 t/data-05/test2_man.de.1 t/data-05/test2_man.es.1 t/data-05/test2_man.fr.1 t/data-05/test2_man.it.1 t/data-05/test3.conf t/data-05/test3.err t/data-05/test4.conf t/data-05/test4.err t/data-05/test5.conf t/data-05/test6.err t/data-05/test7.err t/data-05/test8.conf t/data-06/addendum1 t/data-06/addendum123.list t/data-06/addendum123.list2 t/data-06/addendum2 t/data-06/addendum3 t/data-06/test0.conf t/data-06/test1.conf t/data-06/test2.conf t/data-06/test3.conf t/data-06/test4.conf t/data-06/Titles.asciidoc t/data-06/Titles.trans.add1 t/data-06/Titles.trans.add123 t/data-06/Titles.trans.add13 t/data-10/pod t/data-10/pod.fr t/data-10/pod.po t/data-11/err1 t/data-11/pod1 t/data-11/pod1.fr t/data-11/pod1.po t/data-11/pod2 t/data-11/pod2.fr t/data-11/pod2.po t/data-11/pod3 t/data-11/pod3.fr t/data-11/pod4 t/data-11/pod4.fr t/data-12/counter.de.po t/data-12/counter.fr.po t/data-12/counter.pot t/data-12/counter_wrap.de.po t/data-12/counter_wrap.fr.po t/data-12/counter_wrap.pot t/data-12/full.de.po t/data-12/full.fr.po t/data-12/full.pot t/data-12/full_wrap.de.po t/data-12/full_wrap.fr.po t/data-12/full_wrap.pot t/data-12/man02 t/data-12/man03 t/data-12/noline.de.po t/data-12/noline.fr.po t/data-12/noline.pot t/data-12/noline_wrap.de.po t/data-12/noline_wrap.fr.po t/data-12/noline_wrap.pot t/data-12/none.de.po t/data-12/none.fr.po t/data-12/none.pot t/data-12/test1.conf t/data-12/test1.err t/data-20/test2-normalized.sgml t/data-20/test2.pot t/data-20/test2.sgml t/data-20/text.xml t/data-20/xml.po t/data-21/extract.dia t/data-21/extract.po-ok t/data-21/transl.dia t/data-21/transl.dia-ok t/data-21/transl.po t/data-23/dot1 t/data-23/dot1.fr t/data-23/dot1.fr.po t/data-23/dot1.pot t/data-23/dot2 t/data-23/dot2.err t/data-23/dot3 t/data-23/dot3.err t/data-23/dot4 t/data-23/dot4.err t/data-23/dot5 t/data-23/dot5.it t/data-23/dot5.it.po t/data-23/dot5.pot t/data-23/escapes1 t/data-23/escapes1.it t/data-23/escapes1.it.po t/data-23/escapes1.pot t/data-23/fonts t/data-23/fonts.en t/data-23/fonts.en.po t/data-23/fonts.pot t/data-23/hyphens.1 t/data-23/hyphens.translate.fr t/data-23/hyphens.translate.fr.po t/data-23/hyphens.translate.pot t/data-23/hyphens.verbatim.fr t/data-23/hyphens.verbatim.fr.po t/data-23/hyphens.verbatim.pot t/data-23/mdoc.1 t/data-23/mdoc.fr t/data-23/mdoc.fr.po t/data-23/mdoc.pot t/data-23/mixed.cfg t/data-23/mixed.fr.po t/data-23/mixed.pot t/data-23/mixed1 t/data-23/mixed1.fr t/data-23/mixed2 t/data-23/mixed2.fr t/data-23/mixed3 t/data-23/mixed3.fr t/data-23/mixed4 t/data-23/mixed4.fr t/data-23/null t/data-23/null.fr t/data-23/null.fr.po t/data-23/null.pot t/data-23/quotes t/data-23/quotes.fr t/data-23/quotes.fr.po t/data-23/quotes.pot t/data-23/spaces t/data-23/spaces.fr_latin1 t/data-23/spaces.fr_latin1.po t/data-23/spaces.fr_utf8 t/data-23/spaces.fr_utf8.po t/data-23/spaces.ja t/data-23/spaces.ja.po t/data-23/spaces.pot t/data-24/simple-gettextize.out t/data-24/simple-translate.out t/data-24/simple-updatepo.out t/data-24/simple.fr.po t/data-24/simple.fr.tex t/data-24/simple.pot t/data-24/simple.tex t/data-24/theorem.pot t/data-24/theorem.tex t/data-25/includessi.html t/data-25/includessi.po t/data-25/includessi_normalized.html t/data-25/xhtml.html t/data-25/xhtml.po t/data-25/xhtml_normalized.html t/data-26/test1.ini t/data-26/test1.po t/data-27/cdata.po t/data-27/cdata.xml t/data-27/comments-normalized.xml t/data-27/comments.po t/data-27/comments.xml t/data-27/general-normalized.xml t/data-27/general.po t/data-27/general.xml t/data-27/options-normalized.xml t/data-27/options.po t/data-27/options.xml t/data-28/test1.new.po t/data-28/test1.new.pot t/data-28/test1.old.pot t/data-28/test1.po t/data-28/test2.new.po t/data-28/test2.new.pot t/data-28/test2.old.pot t/data-28/test2.po t/data-28/test3.new.po t/data-28/test3.new.pot t/data-28/test3.old.pot t/data-28/test3.po t/data-28/test4.new.po t/data-28/test4.new.pot t/data-28/test4.old.pot t/data-28/test4.po t/data-28/test5.new.po t/data-28/test5.new.pot t/data-28/test5.old.pot t/data-28/test5.po t/data-28/test6.new.po t/data-28/test6.new.pot t/data-28/test6.old.pot t/data-28/test6.po t/data-28/test7.new.po t/data-28/test7.new.pot t/data-28/test7.old.pot t/data-28/test7.po t/data-28/test8.new.po t/data-28/test8.new.pot t/data-28/test8.old.pot t/data-28/test8.po t/data-29/general-normalized.wml t/data-29/general.po t/data-29/general.wml t/data-30/Attributes.asciidoc t/data-30/Attributes.out t/data-30/Attributes.po t/data-30/BlockId.asciidoc t/data-30/BlockId.out t/data-30/BlockId.po t/data-30/BlockTitles.asciidoc t/data-30/BlockTitles.out t/data-30/BlockTitles.po t/data-30/Callouts.asciidoc t/data-30/Callouts.out t/data-30/Callouts.po t/data-30/Comments.asciidoc t/data-30/Comments.out t/data-30/Comments.po t/data-30/DelimitedBlocks.asciidoc t/data-30/DelimitedBlocks.out t/data-30/DelimitedBlocks.po t/data-30/Footnotes.asciidoc t/data-30/Footnotes.out t/data-30/Footnotes.po t/data-30/Lists.asciidoc t/data-30/Lists.out t/data-30/Lists.po t/data-30/Paragraphs.asciidoc t/data-30/Paragraphs.out t/data-30/Paragraphs.po t/data-30/Tables.asciidoc t/data-30/Tables.out t/data-30/Tables.po t/data-30/Titles.asciidoc t/data-30/Titles.out t/data-30/Titles.po t/data-30/TitlesLatin1.asciidoc t/data-30/TitlesLatin1.po t/data-30/TitlesUTF8.asciidoc t/data-30/TitlesUTF8.po TODO po4a-0.45/po4a-gettextize000555001750001750 1744012205217330 15645 0ustar00barbierbarbier000000000000#! /usr/bin/env perl eval 'exec perl -S $0 ${1+"$@"}' if $running_under_some_shell; # po4a-gettextize -- convert an original file to a PO file # # Copyright 2002-2012 by SPI, inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of GPL (see COPYING). =encoding UTF-8 =head1 NAME po4a-gettextize - convert an original file (and its translation) to a PO file =head1 SYNOPSIS B B<-f> I B<-m> I [B<-l> I] B<-p> I (I is the output, all others are inputs) =head1 DESCRIPTION The po4a (PO for anything) project goal is to ease translations (and more interestingly, the maintenance of translations) using gettext tools on areas where they were not expected like documentation. The B script is in charge of converting documentation files to PO files. If you start a new translation, B will extract the translatable strings from the documentation file and write a POT file from it. If you already have a translated file, B will try to extract the translations it contains and put them in place in the written PO file. Be warned that very few intelligence is used in this process: the Nth string of the translated file is supposed to be the translation of the Nth string in the original. If it's not the case, you're dead. That's why it is very important that both files share exactly the same structure. However, B will diagnose your death by detecting any desynchronisation between files, and reporting where they occur. In that case, you should edit manually the files to solve the reported disparity. Even if no error were reported, you should check carefully that the generated PO file is correct (i.e. that each msgstr is the translation of the associated msgid, and not the one before or after). Even if the script manages to do its job without any apparent problem, it still marks all extracted translations as fuzzy, to make sure that the translator will have a look at them, and detect any remaining problem. If the master document has non-ASCII characters, the new generated PO file will be in UTF-8, in order to allow non-standard characters in a culture independent way. Else (if the master document is completely in ASCII), the generated PO will use the encoding of the translated input document. =head1 OPTIONS =over 4 =item B<-f>, B<--format> Format of the documentation you want to handle. Use the B<--help-format> option to see the list of available formats. =item B<-m>, B<--master> File containing the master document to translate. You can use this option multiple times if you want to gettextize multiple documents. =item B<-M>, B<--master-charset> Charset of the file containing the document to translate. =item B<-l>, B<--localized> File containing the localized (translated) document. If you provided multiple master files, you may wish to provide multiple localized file by using this option more than once. =item B<-L>, B<--localized-charset> Charset of the file containing the localized document. =item B<-p>, B<--po> File where the message catalog should be written. If not given, the message catalog will be written to the standard output. =item B<-o>, B<--option> Extra option(s) to pass to the format plugin. Specify each option in the 'IB<=>I' format. See the documentation of each plugin for more information about the valid options and their meanings. =item B<-h>, B<--help> Show a short help message. =item B<--help-format> List the documentation formats understood by po4a. =item B<-V>, B<--version> Display the version of the script and exit. =item B<-v>, B<--verbose> Increase the verbosity of the program. =item B<-d>, B<--debug> Output some debugging information. =item B<--msgid-bugs-address> I Set the report address for msgid bugs. By default, the created POT files have no Report-Msgid-Bugs-To fields. =item B<--copyright-holder> I Set the copyright holder in the POT header. The default value is "Free Software Foundation, Inc." =item B<--package-name> I Set the package name for the POT header. The default is "PACKAGE". =item B<--package-version> I Set the package version for the POT header. The default is "VERSION". =back =head1 SEE ALSO L, L, L, L =head1 AUTHORS Denis Barbier Nicolas François Martin Quinson (mquinson#debian.org) =head1 COPYRIGHT AND LICENSE Copyright 2002-2012 by SPI, inc. This program is free software; you may redistribute it and/or modify it under the terms of GPL (see the COPYING file). =cut use 5.006; use strict; use warnings; use Getopt::Long qw(GetOptions); use Locale::Po4a::Chooser; use Locale::Po4a::TransTractor; use Locale::Po4a::Common; use Pod::Usage qw(pod2usage); Locale::Po4a::Common::textdomain('po4a'); sub show_version { Locale::Po4a::Common::show_version("po4a-gettextize"); exit 0; } my %opts = ( "verbose" => 0, "debug" => 0, "copyright-holder" => undef, "msgid-bugs-address" => undef, "package-name" => undef, "package-version" => undef); my ($pofile)=('-'); my (@masterfile,@locfile,$help_fmt,$help,$type,@options); my ($mastchar,$locchar); Getopt::Long::config('bundling', 'no_getopt_compat', 'no_auto_abbrev'); GetOptions( 'help|h' => \$help, 'help-format' => \$help_fmt, 'master|m=s' => \@masterfile, 'localized|l=s' => \@locfile, 'po|p=s' => \$pofile, 'format|f=s' => \$type, 'master-charset|M=s' => \$mastchar, 'localized-charset|L=s' => \$locchar, 'option|o=s' => \@options, 'copyright-holder=s' => \$opts{"copyright-holder"}, 'msgid-bugs-address=s' => \$opts{"msgid-bugs-address"}, 'package-name=s' => \$opts{"package-name"}, 'package-version=s' => \$opts{"package-version"}, 'verbose|v' => \$opts{"verbose"}, 'debug|d' => \$opts{"debug"}, 'version|V' => \&show_version ) or pod2usage(); # Argument check $help && pod2usage (-verbose => 1, -exitval => 0); $help_fmt && Locale::Po4a::Chooser::list(0); pod2usage () if (scalar @ARGV > 1) || (scalar @masterfile < 1); foreach (@options) { if (m/^([^=]*)=(.*)$/) { $opts{$1}="$2"; } else { $opts{$_}=1; } } # Check file existence foreach my $file (@masterfile, @locfile) { $file eq '-' || -e $file || die wrap_msg(gettext("File %s does not exist."), $file); } # Declare the TransTractor parsers my ($mastertt,$transtt)=(Locale::Po4a::Chooser::new($type,%opts), Locale::Po4a::Chooser::new($type,%opts)); # Parse master file forcing conversion to utf if it's not in ascii foreach my $file (@masterfile) { $mastertt->read($file); } $mastertt->{TT}{utf_mode} = 1; if ($mastertt->{TT}{ascii_input}) { $mastertt->detected_charset('ascii'); } elsif (defined($mastchar)) { $mastertt->detected_charset($mastchar); $mastertt->{TT}{po_in}->set_charset($mastchar); } $mastertt->parse; unless (scalar @locfile >= 1) { # Ok, outputing the pot extracted from original is enough $mastertt->writepo($pofile); } else { # We have to merge two transtractor files foreach my $file (@locfile) { $transtt->read($file); } # We force the conversion to utf if the master document wasn't in ascii $transtt->{TT}{utf_mode} = !$mastertt->{TT}{ascii_input}; $transtt->detected_charset($locchar); $transtt->{TT}{po_in}->set_charset($locchar); $transtt->parse; my $mergedpo = Locale::Po4a::Po->gettextize($mastertt->getpoout(), $transtt->getpoout()); $mergedpo->write($pofile); } __END__ po4a-0.45/po4a-normalize000555001750001750 1072112205217330 15444 0ustar00barbierbarbier000000000000#! /usr/bin/env perl eval 'exec perl -S $0 ${1+"$@"}' if $running_under_some_shell; # po4a-normalize -- normalize documentation files # # Copyright 2002-2012 by SPI, inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of GPL (see COPYING). =encoding UTF-8 =head1 NAME po4a-normalize - normalize a documentation file by parsing it in po4a, and writing it back =head1 SYNOPSIS B B<-f> I I =head1 DESCRIPTION The po4a (PO for anything) project goal is to ease translations (and more interestingly, the maintenance of translations) using gettext tools on areas where they were not expected like documentation. The B script is a debugging tool used to make sure that po4a don't change the document when it's not supposed to. Only use it if you're developing a new module, or if you doubt the sanity of the tools. The generated document will be written to F while the generated PO file will be written to F. No way to change that ;) =head1 OPTIONS =over 4 =item B<-o>, B<--option> Extra option(s) to pass to the format plugin. Specify each option in the 'IB<=>I' format. See the documentation of each plugin for more information about the valid options and their meanings. =item B<-b>, B<--blank> Create an blank translated document. The generated translated document will be generated assuming all messages are translated by a space or new line. This is useful to check what parts of the document cannot be translated. =item B<-h>, B<--help> Show a short help message. =item B<--help-format> List the documentation formats understood by po4a. =item B<-f>, B<--format> Format of the documentation you want to handle. Use the B<--help-format> option to see the list of available formats. =item B<-M>, B<--master-charset> Charset of the file containing the document to translate. =item B<-V>, B<--version> Display the version of the script and exit. =back =head1 SEE ALSO L, L, L, L =head1 AUTHORS Denis Barbier Nicolas François Martin Quinson (mquinson#debian.org) =head1 COPYRIGHT AND LICENSE Copyright 2002-2012 by SPI, inc. This program is free software; you may redistribute it and/or modify it under the terms of GPL (see the COPYING file). =cut use 5.006; use strict; use warnings; use Locale::Po4a::Chooser; use Locale::Po4a::TransTractor; use Locale::Po4a::Common; use Getopt::Long qw(GetOptions); use Pod::Usage qw(pod2usage); Locale::Po4a::Common::textdomain('po4a'); sub show_version { Locale::Po4a::Common::show_version("po4a-normalize"); exit 0; } my ($blank,$help_fmt,$help,$type,$debug,$verbose,@options); my ($mastchar); Getopt::Long::Configure('no_auto_abbrev','no_ignore_case'); GetOptions( 'help|h' => \$help, 'help-format' => \$help_fmt, 'format|f=s' => \$type, 'blank|b' => \$blank, 'master-charset|M=s' => \$mastchar, 'option|o=s' => \@options, 'verbose|v' => \$verbose, 'debug|d' => \$debug, 'version|V' => \&show_version ) or pod2usage(); $help && pod2usage (-verbose => 1, -exitval => 0); $help_fmt && Locale::Po4a::Chooser::list(0); pod2usage () unless scalar @ARGV == 1; my %options = ( "verbose" => $verbose, "debug" => $debug); foreach (@options) { if (m/^([^=]*)=(.*)$/) { $options{$1}="$2"; } else { $options{$_}=1; } } my $parser=Locale::Po4a::Chooser::new($type,%options); my $filename = shift || pod2usage(1); $filename eq '-' || -e $filename || die wrap_msg(gettext("File %s does not exist."), $filename); $parser->read($filename); $parser->{TT}{utf_mode} = 1; $parser->{TT}{file_in_charset} = $mastchar; $parser->parse(); if ($blank) { foreach my $msgid (keys %{$parser->{TT}{po_out}{po}}) { if ($msgid =~ m/\n$/s) { $parser->{TT}{po_out}{po}{$msgid}{'msgstr'} = "\n"; } else { $parser->{TT}{po_out}{po}{$msgid}{'msgstr'} = " "; } } my $empty_po = $parser->{TT}{po_out}; $parser = Locale::Po4a::Chooser::new($type,%options); $parser->{TT}{po_in} = $empty_po; $parser->read($filename); $parser->{TT}{utf_mode} = 1; $parser->{TT}{file_in_charset} = $mastchar; $parser->parse(); } $parser->write('po4a-normalize.output'); $parser->writepo('po4a-normalize.po'); __END__ po4a-0.45/TODO000444001750001750 362312205217330 13330 0ustar00barbierbarbier000000000000******** * TODO * ******** * Update README.translators * Add the addenda to the manpages with po4a-build * Update the PO files in the build/dist process Check xml2rfc Better error handling (errno, errstr) > >What we really need is a function embeeding the call to warn and sprintf, > >and reputting the module in front of it and the "\n" afterward (but not the > >dgettext since it has to be there to be able to extract the strings). It > >would help making the code more readable. We could also implement a sort of > >wrapping function setting the module name in front of every line. There is > >a module for that in Perl. > > I thought about it some time ago. It would be nice :) ** TransTractor.pm - process(): $self->addendum($file) || die "An addendum failed\n"; - poheader() >> +$parser->{TT}{utf_mode} = 1; >> +$parser->{TT}{file_in_charset} = $mastchar; > What about a function in transtractor allowing to set the mastchar ? I'd > prefer to leave the modification of the {TT} internals to the library code, > not the binaries one. ** po-debconf: - change the pot header as documented in po4a(7) ** Po.pm - close filehandle in write (and same in TransTractor.pm). - verbose => type in automatic comments ** Sgml.pm - get ride of nsgml - move the tag lists to an external file ** Man.pm: - handle .ce (11 pages need it) >>> Text lines can be centered by using the ce' request. The line after `ce' is centered (horizontally) on the page. To center more than one line, use `.ce N' (where N is the number of lines to center), followed by the N lines. To center many lines without counting them, type: .ce 1000 lines to center .ce 0 The .ce 0' request tells groff' to center zero more lines, in other words, stop centering. <<< The problem is that the number of lines may change during the translation... - same story about .ul N (underline N lines) po4a-0.45/po4a-build.conf000444001750001750 243112205217330 15443 0ustar00barbierbarbier000000000000# po4a-build.conf configuration file # Any empty values can be omitted. # # name and location of the config file CONFIG="_build/po4a.config" # po directory for manpages/docs PODIR="po/pod" # POT file path POTFILE="po/pod/po4a-pod.pot" # base directory for generated files, e.g. doc BASEDIR="_build" # binary packages that will contain generated manpages BINARIES="po4a" # DocBook XML files for section 3 XMLMAN3="" # binary packages using DocBook XML & xsltproc XMLPACKAGES="po4a" # DocBook XML files for section 1 XMLMAN1="po4a-build.xml po4aman-display-po.xml po4apod-display-po.xml" # pattern to find the XML files XMLDIR="share/doc/" # pattern to find the .docbook files DOCBOOKDIR="" # POD files for section 1 PODFILE="po4a po4a-gettextize po4a-normalize po4a-translate po4a-updatepo scripts/msguntypot" # POD files for section 3 - module names regenerated from the path PODMODULES="lib/Locale/Po4a/*.pm" # POD files for section 5 POD5FILES="doc/po4a-build.conf.5.pod" # POD files for section 7 POD7FILES="doc/po4a.7.pod doc/po4a-runtime.7.pod" # binary packages using POD PODPACKAGES="po4a" # HTML output (subdirectory of BASEDIR) HTMLDIR="" # HTML DocBook file HTMLFILE="" # minimal threshold for translation percentage to keep KEEP= # reserved value only for internal builds USE_INTERNAL_PO4A=yes po4a-0.45/README000444001750001750 507212205217330 13520 0ustar00barbierbarbier000000000000Introduction to Po4a ==================== The po4a (PO for anything) project goal is to ease translations (and more interestingly, the maintenance of translations) using gettext tools on areas where they were not expected like documentation. In po4a each documentation format is handled by a module. For now, we have a module for the POD format (in which the perl documentation is written), the good old man pages, and the documentation of the kernel compilation options. Some other modules are underway, like for sgml, xml or texinfo. INSTALLATION To install this module type the following: perl Build.PL ./Build ./Build install USE WITHOUT INSTALLATION If you want to use a version without installing it (such as the CVS one), use the PERLLIB environment variable is such construction: PERLLIB=~/svn-checkouts/po4a/lib ~/svn-checkouts/po4a/po4a-gettextize [usual args] PO4A DEPENDENCIES Locale::gettext (v1.01): This module being itself internationalized, it needs the Locale::gettext library to translate its own messages. If it is not present, then po4a's messages won't be translated, but po4a will remain fully functional. Text::WrapI18N: This module is used to format po4a's warnings and error messages. It permits to wrap long error messages without splitting words. If it is not present, the formatting of messages will be different, but po4a will remain fully functional. Term::ReadKey: This module is used to retrieve the terminal's line width. It is not used if Text::WrapI18N is not available. If it is not present, the line width can be specified with the COLUMN environment variable. SGML MODULE SPECIFIC DEPENDENCIES SGMLS (1.03ii): This is a set of Perl5 routines for processing the output from the sgmls and nsgmls SGML parsers. sp (1.3.4): James Clark's SGML parsing tools This is the parser we use. http://www.jclark.com/sp/ TEXT MODULE SPECIFIC DEPENDENCIES Unicode::GCString: This module is used to compute text width; it is needed by AsciiDoc to determine two line titles in encodings different from ASCII. http://hatuka.nezumi.nu/repos/Unicode-LineBreak/ PROJECT WEB PAGE You can find more information and report bugs at the po4a project web page: http://po4a.alioth.debian.org COPYRIGHT AND LICENSE This program is free software; you may redistribute it and/or modify it under the terms of GPL (see COPYING file). Copyright (C) 2002-2O12 by SPI, inc. Authors: Denis Barbier Martin Quinson (mquinson#debian.org) po4a-0.45/Build.PL000444001750001750 311712205217330 14132 0ustar00barbierbarbier000000000000#!/usr/bin/perl use lib q('.'); use Po4aBuilder; my $build = Po4aBuilder->new ( module_name => 'po4a', license => 'gpl', dist_version_from => 'lib/Locale/Po4a/TransTractor.pm', # finds $VERSION requires => {}, recommends => {'Text::WrapI18N' => 0, # Only used for wrapping long # error/wraning lines. 'Term::ReadKey' => 0, # Needed to detect terminal # width. Not needed if you # don't have Text::WrapI18N. 'SGMLS' => 0, # Needed for the Sgml module. 'Unicode::GCString' => 0, # Used by the Text module (asciidoc) 'Locale::gettext' => '1.01', # Only used for # translating the # po4a's messages. }, script_files => ['po4a-gettextize', 'po4a-updatepo', 'po4a-translate', 'po4a-normalize', 'po4a', 'scripts/msguntypot', 'scripts/po4aman-display-po', 'scripts/po4apod-display-po', 'share/po4a-build'], add_to_cleanup => ['t/tmp','po/bin/*.gmo', 'blib', '_build'], dist_abstract => 'Tools for helping translation of documentation', dist_author => ['Martin Quinson (mquinson#debian.org)', 'Denis Barbier ', 'Nicolas Francois ', 'Neil Williams '] ); $build->create_build_script; po4a-0.45/po4a-updatepo000555001750001750 2102412205217330 15263 0ustar00barbierbarbier000000000000#! /usr/bin/env perl eval 'exec perl -S $0 ${1+"$@"}' if $running_under_some_shell; # pod-updatepo -- update the PO translation of POD data. # # Copyright 2002-2012 by SPI, inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of GPL (see COPYING). =encoding UTF-8 =head1 NAME po4a-updatepo - update the translation (in PO format) of documentation =head1 SYNOPSIS B B<-f> I (B<-m> I)+ (B<-p> I)+ (I are the outputs, all others are inputs) =head1 DESCRIPTION The po4a (PO for anything) project goal is to ease translations (and more interestingly, the maintenance of translations) using gettext tools on areas where they were not expected like documentation. The B script is in charge of updating PO files to make them reflect the changes made to the original documentation file. For that, it converts the documentation file to a POT file, and call L on this new POT and on the provided PO files. It is possible to give more than one PO file (if you want to update several languages at once), and several documentation files (if you want to store the translations of several documents in the same PO file). If the master document has non-ASCII characters, it will convert the PO files to UTF-8 (if they weren't already), in order to allow non-standard characters in a culture independent way. =head1 OPTIONS =over 4 =item B<-f>, B<--format> Format of the documentation you want to handle. Use the B<--help-format> option to see the list of available formats. =item B<-m>, B<--master> File(s) containing the master document to translate. =item B<-M>, B<--master-charset> Charset of the files containing the document to translate. Note that all files must have the same charset. =item B<-p>, B<--po> PO file(s) to update. If these files do not exist, they are created by B. =item B<-o>, B<--option> Extra option(s) to pass to the format plugin and other po4a internal module. Specify each option in the 'IB<=>I' format. See the documentation of each plugin for more information about the valid options and their meanings. =item B<--no-previous> This option removes B<--previous> from the options passed to B. This permits to support versions of B earlier than 0.16. =item B<--previous> This option adds B<--previous> to the options passed to B. It requires B 0.16 or later, and is activated by default. =item B<--msgmerge-opt> I Extra options for B. =item B<-h>, B<--help> Show a short help message. =item B<--help-format> List the documentation formats understood by po4a. =item B<-V>, B<--version> Display the version of the script and exit. =item B<-v>, B<--verbose> Increase the verbosity of the program. =item B<-d>, B<--debug> Output some debugging information. =item B I[,B|B] Specify the reference format. Argument I can be one of B to not produce any reference, B to not specify the line number (more accurately all line numbers are replaced by 1), B to replace line number by an increasing counter, and B to include complete references. Argument can be followed by a comma and either B or B keyword. References are written by default on a single line. The B option wraps references on several lines, to mimic B tools (B and B). This option will become the default in a future release, because it is more sensible. The B option is available so that users who want to keep the old behavior can do so. =item B<--msgid-bugs-address> I Set the report address for msgid bugs. By default, the created POT files have no Report-Msgid-Bugs-To fields. =item B<--copyright-holder> I Set the copyright holder in the POT header. The default value is "Free Software Foundation, Inc." =item B<--package-name> I Set the package name for the POT header. The default is "PACKAGE". =item B<--package-version> I Set the package version for the POT header. The default is "VERSION". =back =head1 SEE ALSO L, L, L, L =head1 AUTHORS Denis Barbier Nicolas François Martin Quinson (mquinson#debian.org) =head1 COPYRIGHT AND LICENSE Copyright 2002-2012 by SPI, inc. This program is free software; you may redistribute it and/or modify it under the terms of GPL (see the COPYING file). =cut use 5.006; use strict; use warnings; use Getopt::Long qw(GetOptions); use Locale::Po4a::Po; use Locale::Po4a::Chooser; use Locale::Po4a::TransTractor; use Locale::Po4a::Common; use Pod::Usage qw(pod2usage); use File::Temp; use File::Copy qw(copy); use Config; Locale::Po4a::Common::textdomain('po4a'); sub show_version { Locale::Po4a::Common::show_version("po4a-updatepo"); exit 0; } # init commandline parser Getopt::Long::config('bundling', 'no_getopt_compat', 'no_auto_abbrev'); # Parse our options my (@masterfiles,@pofiles); my ($help,$help_fmt,$verbose,$debug,$format,@options); my ($copyright_holder, $msgid_bugs_address, $package_name, $package_version); my $mastchar; my $previous; my $noprevious; my $msgmerge_opt = ""; GetOptions('help|h' => \$help, 'help-format' => \$help_fmt, 'master|m=s' => \@masterfiles, 'po|p=s' => \@pofiles, 'format|f=s' => \$format, 'master-charset|M=s' => \$mastchar, 'option|o=s' => \@options, 'no-previous' => \$noprevious, 'previous' => \$previous, 'msgmerge-opt=s' => \$msgmerge_opt, 'copyright-holder=s' => \$copyright_holder, 'msgid-bugs-address=s'=> \$msgid_bugs_address, 'package-name=s' => \$package_name, 'package-version=s' => \$package_version, 'verbose|v' => \$verbose, 'debug|d' => \$debug, 'version|V' => \&show_version) or pod2usage(); $help && pod2usage (-verbose => 1, -exitval => 0); $help_fmt && Locale::Po4a::Chooser::list(0); pod2usage () if scalar @masterfiles < 1 || scalar @pofiles < 1; $msgmerge_opt .= " --previous" unless $noprevious; $msgmerge_opt =~ s/^\s+//; my %options = ( "verbose" => $verbose, "debug" => $debug, "copyright-holder" => $copyright_holder, "msgid-bugs-address" => $msgid_bugs_address, "package-name" => $package_name, "package-version" => $package_version); foreach (@options) { if (m/^([^=]*)=(.*)$/) { $options{$1}="$2"; } else { $options{$_}=1; } } # parser my ($doc)=Locale::Po4a::Chooser::new($format,%options); map { -e $_ || die wrap_msg(gettext("File %s does not exist."), $_) } @masterfiles; map { die wrap_msg(gettext("po4a-updatepo can't take the input PO from stdin.")) if $_ eq '-' && !-e '-'} @pofiles; my ($pot_filename); (undef,$pot_filename)=File::Temp::tempfile("po4a-updatepoXXXX", DIR => $ENV{TMPDIR} || "/tmp", SUFFIX => ".pot", OPEN => 0, UNLINK => 0) or die wrap_msg(gettext("Can't create a temporary POT file: %s"), $!); print STDERR wrap_msg(gettext("Parse input files... ")) if $verbose; $doc->{TT}{utf_mode} = 1; $doc->process('file_in_name' => \@masterfiles, 'file_in_charset' => $mastchar, 'po_out_name' => $pot_filename, 'debug' => $debug, 'verbose' => $verbose); print STDERR wrap_msg(gettext("done.")) if $verbose; while (my $po_filename=shift @pofiles) { if (-e $po_filename) { print STDERR wrap_msg(gettext("Updating %s:"), $po_filename) if $verbose; my @cmd = ("msgmerge".$Config{_exe}); push (@cmd, split(/\s+/, $msgmerge_opt)) if length($msgmerge_opt); push @cmd, ("-U", $po_filename, $pot_filename); system (@cmd) == 0 or die wrap_msg(gettext("Error while running msgmerge: %s"), $!); @cmd = ("msgfmt".$Config{_exe}, "--statistics", "-v", "-o", File::Spec->devnull(), $po_filename); system (@cmd) if $verbose; } else { print STDERR wrap_msg(gettext("Creating %s:"), $po_filename) if $verbose; copy ($pot_filename,$po_filename) or die wrap_msg(gettext("Error while copying the PO file: %s"), $!); } } unlink($pot_filename); po4a-0.45/META.yml000444001750001750 447112205217330 14113 0ustar00barbierbarbier000000000000--- abstract: 'Tools for helping translation of documentation' author: - 'Martin Quinson (mquinson#debian.org)' - 'Denis Barbier ' - 'Nicolas Francois ' - 'Neil Williams ' build_requires: {} configure_requires: Module::Build: 0.38 dynamic_config: 1 generated_by: 'Module::Build version 0.38, CPAN::Meta::Converter version 2.110440' license: gpl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: po4a provides: Locale::Po4a::AsciiDoc: file: lib/Locale/Po4a/AsciiDoc.pm version: 0 Locale::Po4a::BibTeX: file: lib/Locale/Po4a/BibTeX.pm version: 0 Locale::Po4a::Chooser: file: lib/Locale/Po4a/Chooser.pm version: 0 Locale::Po4a::Common: file: lib/Locale/Po4a/Common.pm version: 0 Locale::Po4a::Dia: file: lib/Locale/Po4a/Dia.pm version: 0 Locale::Po4a::Docbook: file: lib/Locale/Po4a/Docbook.pm version: 0 Locale::Po4a::Guide: file: lib/Locale/Po4a/Guide.pm version: 0 Locale::Po4a::Halibut: file: lib/Locale/Po4a/Halibut.pm version: 0 Locale::Po4a::Ini: file: lib/Locale/Po4a/Ini.pm version: 0 Locale::Po4a::KernelHelp: file: lib/Locale/Po4a/KernelHelp.pm version: 0 Locale::Po4a::LaTeX: file: lib/Locale/Po4a/LaTeX.pm version: 0 Locale::Po4a::Man: file: lib/Locale/Po4a/Man.pm version: 0 Locale::Po4a::Po: file: lib/Locale/Po4a/Po.pm version: 0 Locale::Po4a::Pod: file: lib/Locale/Po4a/Pod.pm version: 0 Locale::Po4a::Sgml: file: lib/Locale/Po4a/Sgml.pm version: 0 Locale::Po4a::TeX: file: lib/Locale/Po4a/TeX.pm version: 0 Locale::Po4a::Texinfo: file: lib/Locale/Po4a/Texinfo.pm version: 0 Locale::Po4a::Text: file: lib/Locale/Po4a/Text.pm version: 0 Locale::Po4a::TransTractor: file: lib/Locale/Po4a/TransTractor.pm version: 0.45 Locale::Po4a::Wml: file: lib/Locale/Po4a/Wml.pm version: 0 Locale::Po4a::Xhtml: file: lib/Locale/Po4a/Xhtml.pm version: 0 Locale::Po4a::Xml: file: lib/Locale/Po4a/Xml.pm version: 0 recommends: Locale::gettext: 1.01 SGMLS: 0 Term::ReadKey: 0 Text::WrapI18N: 0 Unicode::GCString: 0 resources: license: http://www.gnu.org/licenses/old-licenses/gpl-1.0.txt version: 0.45 po4a-0.45/NEWS000444001750001750 5012312205217330 13354 0ustar00barbierbarbier000000000000po4a NEWS ======================================================================= * Major changes in release 0.45 (2013-08-21) po4a: * Fix usage of File::Temp::tempfile to allow using Perl >= 5.18. Asciidoc: * Make it a standalone format. Docbook: * Make inline. Ini: * Add key parameter as an automatic comment. This allows using po4a-gettextize on ini files. LaTeX: * Fix handling of optional parameters in newtheorem command. Po: * Fix computation of timezone written into PO files. Sgml: * Fix failing tests with recent Docbook DTD. ======================================================================= * Major changes in release 0.44 (2012-10-21) translations: * Start of Portuguese translation ======================================================================= * Major changes in release 0.43 (2012-10-17) po4a: * Add --porefs option to change how file locations are written into the POT file (and thus into the PO files also). po4a-updatepo po4a Po: * Extend the --porefs option, add a new 'counter' value to replace line number by an increasing counter. An optional ",nowrap" or ",wrap" specifier can be added to tell whether file locations are written on a single line or wrapped on several lines. Default is ",nowrap", it will be changed to ",wrap" in a future release. Man: * Make .UR/.UE macros inline. * Add macros used in several NetBSD man pages: %I %U Brc Bro Lp Lk Text: * Fix two line titles in AsciiDoc format. * Let AsciiDoc format handle many more styles. * Add support for automatic comments in AsciiDoc format. ======================================================================= * Major changes in release 0.42 (2012-05-16) po4a: * Allow adding command-line options after config file. Text: * Add support for control files. msguntypot: * Do not remove obsolete entries from PO files. documentation translations: * New German translations * Updated Spanish translations * Updated French translations * Updated Japanese translations * Updated Polish translations ======================================================================= * Major changes in release 0.41 (2010-12-01) po4a-updatepo: * --previous flag was not passed to msgmerge po4a: * Do no more generate backups for PO files. * Fix the --srcdir option, master file was not found. * Expand variables when reading @-prefixed addenda files. Text: * Remove trailing newline in titles from PO files Packaging: * Remove Makefile, all processing is performed by Build.PL ======================================================================= * Major changes in release 0.40.2 (2010-11-30) documentation: * Improve English style (following recommendations from man(7)) translations: * Start of Danish translation * Removal of Arabic translation, only one string was translated * Updated Vietnamese translation * Updated Slovenian translation * Updated Basque translation * Updated French translation * Updated Japanese translation * Updated Czech translation * Updated German translation * Updated Ukrainian translation * Updated Esperanto translation * Updated Estonian translation * Updated Russian translation documentation translations: * Updated Spanish translations * Updated French translations * Updated Japanese translations * Updated Polish translations ======================================================================= * Major changes in release 0.40.1 (2010-08-25) Po: * Change header entry to be consistent with xgettext when creating POT files: replace Content-Transfer-Encoding: ENCODING" by "Content-Transfer-Encoding: 8bit\n" and add a Language field. documentation: * Improve English style (proper casing, replace cvs by VCS, etc). translations: * Updated French translations * Updated Spanish translations * Updated Japanese translations * Updated Esperanto translations * Updated Swedish translations * Updated Russian translations * Updated Estonian translations * Updated Ukrainian translations * Updated Czech translations * Updated Portuguese translations * Updated German translations Project resources: * We migrated from CVS to SVN. All CVS history has been converted. See http://svn.debian.org/viewsvn/po4a/ The standard SVN layout is used (with top-level /trunk, /branches and /tags directories), and the files to generate the website (html/, po/html.cfg and po/www) are moved into a new /web top-level directory. ======================================================================= * Major changes in release 0.40 (2010-07-27) po4a-gettextize: * When it fails, recode msgstr into current charset before printing it. Text: * Fix failures "Unknown option: copyright-holder" Man: * Support font modifiers in the form \f(XX and \f[FONT-NAME] ======================================================================= * Major changes in release 0.39 (2010-02-02) po4a * New syntax for addenda, path may be preceded by modifiers. ======================================================================= * Major changes in release 0.38 (2010-01-14) po4a * Exit with an error if master file specified in a po4a configuration file does not exist. po4a, po4a-updatepo: * --previous is activated by default. * Use --no-previous to support versions of gettext earlier than 0.16. Xml: * Fix handling of multi-lines placeholder tags. * New option addlang. Pod: * Detect the encoding based on the input's =encoding line. ======================================================================= * Major changes in release 0.37.1 (2009-11-22) po4a-build: * Fix UTF8 handling and names of perl modules for section 3. * Fix bug that caused translated manpages to be overwritten. ======================================================================= * Major changes in release 0.37.0 (2009-11-20) po4a-build: * New script for one-stop generation of untranslated and translated documentation from DocBook XML and POD sources. translations: * Updated Spanish translations. =============================================================================== * Major changes in release 0.36.6 (2009-11-07) Text: * Added options breaks and tabs. po4aman-display-po * Fixed bashism. translations: * Added Vietnamese translation * Updated Czech translation * Updated Spanish translation of the documentation =============================================================================== * Major changes in release 0.36.5 (2009-09-10) Sgml: * Fix detection of entities in the prolog. translations: * Updated German translation * Updated Portuguese translation =============================================================================== * Major changes in release 0.36.4 (2009-08-30) po4a * Added options --srcdir and --destdir. They permit to strip the base directory for the input and output documents (in the config file and in the references generated in the PO files). po4a-updatepo * Added options --msgid-bugs-address, --copyright-holder, --package-name, --package-version to control the generation of the PO header. translations: * Updated Basque translation * Updated Czech translation * Updated Esperanto translation * Improved Estonian translation. * Updated French translation * Updated Russian translation * Updated Spanish translation. * Updated Swedish translation. =============================================================================== * Major changes in release 0.36.3 (2009-07-22) Bug fix release. po4a-gettextize's new options were rejected by the modules. =============================================================================== * Major changes in release 0.36.2 (2009-07-21) po4apod-display-po * New script to display previews of POD translations. po4a-gettextize * Added options --msgid-bugs-address, --copyright-holder, --package-name, --package-version to control the generation of the PO header. Text: * Avoid the translation of some markups: title and horizontal rules. * Improved Markdown support. Xml: * New option customtag for inline tags that should not be treated as a tag (e.g. they do not need to be closed). Wml: * Fix handling of non ASCII input documents. =============================================================================== * Major changes in release 0.36.1 (2009-04-05) TeX: * Fix support for inline customization of separators. * Fix support for double escapes, which should not introduce commands. LaTeX: * Added support for the tabularx environment. Xml: * Do not include commented out external entities (when includeexternal is used). Pod: * Do not add an =encoding header if the encoding is empty. =============================================================================== * Major changes in release 0.36 (2009-03-15) general: * The "type:" comments in the PO files are now tagged as extracted comments (starting with #.). This changes all the PO files generated by po4a. Maintainers should just let these changes pass through. Translator may want to remove the comment lines starting with '# type:' as they will be duplicates with the '#. type:' comments. Xml: * Placeholders are presented with a type and have a more valid XML representation. This changes the PO files, but translations could be updated automatically. * Do not fail when the doctype does not match the expected one. Only issue a warning. * The tags and tagsonly options are deprecated. Use the translated/untranslated and break/inline/placeholder options instead. * Added foldattributes option. Useful to simplify strings and avoid typos when attributes shall not be translated. Man: * Better handling of spaces in command arguments. TeX: * Included files are searched with kpsewhich instead of using TEXINPUTS directly. =============================================================================== * Major changes in release 0.35 (2009-02-10) po4a * Added support for the [po_directory] command in the configuration file. It permits to avoid listing the supported languages. Simply dropping a new PO file should be sufficient. It should be preferred over the po4a_langs and po4a_paths commands. po4a-normalize: * Added option -b, --blank to check which parts of a document are not translated. po4a-gettextize: * Improved conflict handling: indicate the reference of the alternatives when the same string has different translations. general: * Added support for a nowrapi18n option in Locale::Po4a::Common in order to use Locale::Po4a programatically. packaging: * Manpages are generated in utf-8. This requires a recent Pod::Man with support for the utf8 option. Docbook: * Improved support for Docbook 5 and Docbook 4, based on the official documentation of the Docbook tags. Pod: * Announce the encoding in the POD header. Sgml: * Add support for recursive inclusion. Text: * Added option asciidoc Xhtml: * Improvements for the tag. xml: * Fix the nodefault option. Derivative modules should use _default_tags and _default_inline to define the default behavior of their module-specific tags (instead of tags and inline). * Speed improvements. * Added support for placeholders. =============================================================================== * Major changes in release 0.34 (2008-07-20) ** New features general: * Do not end re-wrapped lines with a space. halibut: * Added support for the Halibut format. sgml: * Fix failures with big sgml documents ("broken pipe" received from nsgmls -p). text: * Added support for the Markdown format, as used with Ikiwiki. * Make sure files are not mixed together when gettextized at the same time. packaging: * Fix build failures with old versions of Module::Build. =============================================================================== * Major changes in release 0.33.3 (2008-04-02) po4a: * Add options --package-name and --package-version (similar to xgettext's options). translations: * Actually ship Japanese translations. =============================================================================== * Major changes in release 0.33.2 (2008-04-01) text: * Added support for the fortunes format. translations: * New Japanese translation. * The manpages are generated in UTF-8. =============================================================================== * Major changes in release 0.33.1 (2008-03-16) This is a bug fix release. man: * Do not translate - to \- inside \*[...], \(.., \H'...', or \Z'...'. xml: * Do not translate SSI comments by default. packaging: * Fix the installation path of manpages and .mo files. =============================================================================== * Major changes in release 0.33 (2008-03-03) Notes to packagers: Since 0.31, some tests in the sgml testsuite require the docbook sgml DTD. If you run the testsuite at build time you must have these DTD in your build dependencies or you must disable these tests cases in the testsuite. ** New features general: Support for PO files with plural forms. Po4a does not generate such PO files, but it can receive one in input. In such case, po4a cannot choose between the (singular and) plural forms. It will consider that msgstr[0] is the translation of msgid and msgstr[1] is the translation of msgid_plural, which may be wrong. Thus, a warning will be issued if po4a is asked to translate the singular or plural form of a message with plural forms. texinfo: Major changes. Tested on the elisp documentation. sgml: Fail if nsgmls cannot validate the input file. This can be turned off with the "force" option. xml: New option "cpp" to support C preprocessor directives (this avoids re-wrapping lines with preprocessor directives). xml: New options "translated" and "untranslated" that should allow an easier configuration of Xml (and derivative module) xml: Avoid duplicated newlines at the end of lines of multi-lines comments. xml: Paragraphs which only consist in an inline tag are now extracted. This makes a lot of string to available for translation in the PO file. docbook: Tested on the Docbook testsuite. Lots of tag added. po4a: Fix failures with perl 5.10. Thanks to Roderich Schupp msguntypot: Fix handling of the comment of the PO header. =============================================================================== * Major changes in release 0.32 (2007-08-15) ** Security fix Fix a symlink attack caused by the /tmp/gettextization.failed.po temporary file. (CVE-2007-4462) ** Bug fixes sgml: The handling of newlines was broken in no-wrap sections in 0.31 xhtml: The module is now distributed as the other modules. texinfo: Fix infinite loop when a command parameter ends with \ (as in @samp{\}) ** New features xml: New option includeexternal to support external entities. texinfo: Added support for many commands and environment (see changelog). xhtml: New option includessi, which adds supports for Server Side Includes include element (). xml: New option ontagerror to control the behavior of the module in case of error. This permits to support files that the module would consider invalid otherwise. ** Translations New translations (Bengali, Estonian, Croatian, Indonesian, Kannada, Korean, Occitan, Uzbek, Simplified Chinese, Chinese from Hong Kong) and many updates. =============================================================================== * Major changes in release 0.31 (2007-05-07) ** Dependencies po4a, po4a-updatepo: New option --previous requires gettext 0.16. ** Bug fixes general: Don't hang when running in background with redirected stdout. Thanks to Jim Meyering. ** New features general: po4a now uses timestamps to avoid re-generating a translation if no changes are expected: if a translation is more recent than its associated PO, master document, addenda or configuration file, then there is no need to update it. For the documents which do not pass the translation threshold, a --stamp option was added to tell po4a to create files with a .po4a-stamp extension (you can also create them manually). This can save a lot of time when po4a knows that the translation will not be generated because there were no changes since the last po4a run. general: Beginning of a C extension. This provides speedup. Testers are welcomed. po4a: New options: --msgid-bugs-address and --copyright-holder. po4a: Add new tag: [options] to set global options (i.e. for every documents in the configuration file). po4a: Update translations based on modification times. Use timestamp to avoid retrying generate uncompleted translations. man: New 'unknown_macros' option to specify the behavior of po4a with unknown groff macros. man: Reset the configuration between two runs. This permits to define different options for different files in a config file with the opt:"..." parameters. =============================================================================== * Major changes in release 0.30 (2007-01-05) ** Bug fixes man: Recode the text which is skipped, like comments. This kind of issue may also appear on other modules. A better solution would be to always use UTF-8 internally. distribution: Some unit tests were missing. Also, the dependencies have been simplified. Locale::gettext, Text::WrapI18N, Term::ReadKey and SGMLS are still recommended, but no more required. The BibTex module is now distributed. sgml: The module should be more friendly with XML files. po4a: When po4a creates a new PO file, it now uses msginit. This may change the header of created PO files. guide: Major update of the tag definitions. Thanks to Azamat H. Hackimov. Po: use strftime instead of date because date is not available on every platform. tests: rename the XML testsuite to SGML, since it was testing the Sgml module, and add a new testsuite for the Xml module (it currently tests the Guide module). ** Translations Updated Russian translation. =============================================================================== * Major changes in release 0.29 (2006-10-15) ** New features ** Bug fixes sgml: Remove the tags from the default categories when they are defined by the user. This changes the behavior of the Sgml module's options. sgml: Better line references in the generated PO. sgml: Support for '/>' (empty XML tag closure) when an xml prologue is found (). po4a: When po4a create new PO files, it now uses msginit instead of copying the POT file. =============================================================================== * Major changes in release 0.29 (2006-10-15) ** New features New module for .INI files. Thanks to Costin Stroie. New module for BibTeX bibliographies. man: New mdoc option for stricter support of mdoc pages (NAME section not translated). text: Support for underlined text. text: Support for bulleted paragraphs (can be deactivated with -o nobullets). ** Bug fixes man: Keep empty commented lines. man: Do not add spaces at the end of lines. man: Languages without non breaking space could not use question marks. sgml: Better support for verbatim sections, and consider as verbatim. and