Sindbad~EG File Manager

Current Path : /usr/bin/
Upload File :
Current File : //usr/bin/debconf-gettextize

#!/usr/bin/perl -w

=head1 NAME

debconf-gettextize - convert master and localized templates files to PO files

=cut

use strict;
use Debconf::Template::Transient;
use Getopt::Long;
use Text::Wrap;
use Text::Tabs;
use File::Spec;
use File::Path;
use File::Temp;

sub usage {
        print STDERR <<EOF;
Usage: debconf-gettextize [OPTIONS] master [master ...]
Options:
  -h,  --help          display this help message
  -v,  --verbose       enable verbose mode
       --podir=DIR     specify PO output directory
                       (Default: <master directory>/po)
       --choices       prepend two underscores before Choices fields
       --merge         merge extracted strings with existing PO files
EOF
        exit $_[0];
}

# Ignore the users locale settings.
Debconf::Template::Transient->i18n(0);

# Prevent a wrapped line from beginning with a space
$Text::Wrap::break = qr/\n|\s(?=\S)/;

my $help = 0;
my $verbose = 0;
my $podir = "";
my $choices = 0;
my $merge = 0;
GetOptions(
        'podir=s' => \$podir,
        'choices' => \$choices,
        'merge' => \$merge,
        'verbose|v' => \$verbose,
        'help|h' => \$help,
) or usage(1);
$help && usage(0);
$#ARGV >= 0 || usage(1);

$ENV{PODEBCONF_ENCODINGS} ||= "/usr/share/po-debconf/encodings";
$ENV{PODEBCONF_HEADER} ||= "/usr/share/po-debconf/pot-header";

if ($podir eq '') {
        $podir = $ARGV[0];
        if ($podir =~ m#/#) {
                $podir =~ s{/[^/]*$}{/po};
        } else {
                $podir = 'po';
        }
}

my $tmpdir = '';
my $oldpodir = '';
if ($merge) {
        die "Error: $podir subdirectory does not exist ...exiting\n"
                unless -d $podir;
        $oldpodir = $podir;
        $tmpdir = File::Temp::tempdir() or die "tmpdir() failed: $!\n";
        print STDERR "Running po2debconf --podir=$podir -e po -o $tmpdir/templates $ARGV[0]\n" if $verbose;
        system("po2debconf", "--podir=$podir", "-e", "po", "-o", $tmpdir."/templates", $ARGV[0]) == 0
                or die "po2debconf failed: $? $!\n";
        shift @ARGV;
        for (@ARGV) {
                system("po2debconf", "--podir=$podir", "-e", "po", "-o", $tmpdir."/templates.tmp", $_) == 0
                        or die "po2debconf failed: $!\n";
                local $/ = undef;
                open (IN, "<", $tmpdir."/templates.tmp");
                my $add = <IN>;
                close (IN);
                open (OUT, ">>", $tmpdir."/templates");
                print OUT "\n".$add;
                close (OUT);
                unlink $tmpdir."/templates.tmp";
        }
        @ARGV = ($tmpdir."/templates");
        $podir = $tmpdir."/po";
} else {
        die "Error: $podir subdirectory already exist ...exiting\n"
                if -d $podir;
}

#   Hacked version of the stringify routine from Debconf/Template.pm
#   It prepends an underscore to translatable entries
sub new_stringify {
        my $template = shift;
        my @needfields = @_;

        my @templatestrings;
        my $transfields = ','.join(',', @needfields).',';
        foreach (($template)) {
                my $data='';
                # Order the fields with Template and Type the top and the
                # rest sorted.
                foreach my $key ('template', 'type',
                        (grep { $_ ne 'template' && $_ ne 'type'} sort $_->fields)) {
                        next if $key=~/^extended_/;
                        # Do not output localized fields.
                        next if $key =~ m/-/;

                        if ($transfields =~ m/,$key,/) {
                                $data.='_';
                                $data.='_' if ($key eq 'choices' && $choices);
                        }
                        $data.=ucfirst($key).": ".$_->$key."\n";
                        my $e="extended_$key";
                        my $ext=$_->$e;
                        if (defined $ext) {
                                # Add extended field.
                                my $extended=expand(wrap(' ', ' ', $ext));
                                # The word wrapper sometimes outputs multiple
                                # " \n" lines, so collapse those into one.
                                $extended=~s/(\n )+\n/\n .\n/g;
                                $data.=$extended."\n" if length $extended;
                        }
                }
                push @templatestrings, $data;
        }
        return join("\n", @templatestrings);
}

sub escape_po {
        my $txt = shift;

        $txt =~ s/\\/\\\\/g;
        $txt =~ s/\n/\\n/g;
        $txt =~ s/"/\\"/g;

        return $txt;
}

my %out = ();
my %enc = ();
my %txt = ();
my @obsolete = ();
my @files = @ARGV;

#     Initialization
foreach my $master (@ARGV) {
        die "Invalid master file: $master ...exiting\n".
  "templates.* file names are reserved for localized templates files, you\n".
  "should rename master files before running debconf-gettextize.\n".
  "When finished, you can rename new master files into templates.in and\n".
  "update POTFILES.in accordingly.\n\n"
                if $master =~ m#templates\.([^./]+)$#;
        die "File $master.old already exist ...exiting\n"
                if -e "$master.old";
        push (@obsolete, "$master.old");
        push (@files, glob ("$master.?? $master.??_??"));
        push (@obsolete, glob ("$master.?? $master.??_??"));
}

-d $podir || mkdir ($podir, 0755) || die "Can't create directory $podir: $!\n";

#     Fix relative links
foreach (@ARGV) {
        $_ = File::Spec->abs2rel($_, $podir);
        s/^\.\.\///;
}

#     Load master files
my %templates = ();
foreach my $fn (@files) {
        next if $fn =~ m#templates\.([^./]+)$#;
        $txt{$fn} = '';
        my %master = map { $_->template => $_ } Debconf::Template::Transient->load($fn);
        foreach (keys %master) {
                $templates{$_} = $master{$_};
        }
}

#     Parse master and localized templates files
foreach my $fn (@files) {
        print STDERR "Reading $fn\n" if $verbose;

        my $filelang = ($fn=~m#templates\.([^./]+)$# ? lc($1) : undef);
        foreach my $in (Debconf::Template::Transient->load($fn)) {
                next unless exists $templates{$in->template};
                my $master=$templates{$in->template};

                # Work out what fields need to be translated.
                my @needfields=qw{description extended_description};
                if ($master->type !~ /^((multi)?select|note|boolean)$/) {
                        push @needfields, 'default' if defined $master->default;
                }
                if ($master->type =~ /(multi)?select/) {
                        push @needfields, 'choices';
                }

                # Parse the translated material
                foreach my $field ($in->fields) {
                        next if $field eq 'template';
                        if ($field =~ m/^(.*?)-(.+)$/) {
                                my $origin_field=$1;
                                my $lang=$2;
                                if ($lang =~ s/\.(.*)//) {
                                        die "Multiple encoding found for language: $lang ... exiting\n"
                                                if (defined ($enc{$lang}) && $enc{$lang} ne uc ($1));
                                        $enc{$lang} = uc ($1);
                                }
                                # Skip fields that are for some other language.
                                if (!defined($filelang) || $lang eq $filelang) {
                                        $out{$lang} = []
                                                unless (defined($out{$lang}));

                                        my $label = $origin_field;
                                        $label =~ s/extended_//;
                                        $label = ucfirst($label);
                                        my $origmaster = $master->$origin_field || '';
                                        my @orig = split(/\n\n+/, $origmaster);
                                        my $orignew = $in->$origin_field || '';
                                        my @trans = split(/\n\n+/, $in->$field());
                                        if ($label eq 'Choices' && $choices) {
                                                @orig = ();
                                                for my $value (split(/(?<!\\), */, $origmaster, 0))
                                                {
                                                        $value =~ s/\\,/,/g;
                                                        push @orig, $value;
                                                }
                                                @trans = ();
                                                for my $value (split(/(?<!\\), */, $in->$field(), 0))
                                                {
                                                        $value =~ s/\\,/,/g;
                                                        push @trans, $value;
                                                }
                                        }
                                        $origmaster =~ s/[\n\s]+//g;
                                        $orignew =~ s/[\n\s]+//g;
                                        my $fuzzy = ($origmaster ne $orignew) || (scalar @orig != scalar @trans);
                                        if (scalar @orig <= scalar @trans) {
                                                foreach (@orig) {
                                                        push @{$out{$lang}}, $label, $fuzzy, $_, shift(@trans);
                                                }
                                        } else {
                                                foreach (@trans) {
                                                        push @{$out{$lang}}, $label, 1, shift(@orig), $_;
                                                }
                                                foreach (@orig) {
                                                        push @{$out{$lang}}, $label, 1, $_, '';
                                                }
                                        }
                                }
                        }
                }

                $txt{$fn} .= new_stringify($in, @needfields)."\n"
                        unless defined $filelang;
        }
        $txt{$fn} =~ s/\s*$/\n/s unless defined $filelang;
}

if (-f $ENV{PODEBCONF_ENCODINGS}) {
        open(ENC, "<", $ENV{PODEBCONF_ENCODINGS})
                || die "Can't open $ENV{PODEBCONF_ENCODINGS} for reading: $!\n";
        while (<ENC>) {
                chomp;
                next unless s/^([a-z][a-z](_[A-Z][A-Z])?)\s+//;
                $enc{lc $1} ||= $_;
        }
        close(ENC);
}
foreach my $lang (sort keys %out) {
        $enc{$lang} ||= 'CHARSET';
}

my $unknown_encoding = 0;
foreach my $lang (sort keys %out) {
        my $polang = $lang;
        $polang =~ s/_(..)$/_\U$1\E/;
        $polang .= '.po';
        print STDERR "Creating $podir/$polang\n" if $verbose;

        my $header = '';
        unless (-e "$podir/$polang") {
                if (open (TOP, "<", $ENV{PODEBCONF_HEADER})) {
                        while (<TOP>) {
                                $header .= $_;
                        }
                        close (TOP);
                }
                $header .= "#\n"
                 ."#, fuzzy\n"
                 ."msgid \"\"\n"
                 ."msgstr \"\"\n"
                 ."\"Project-Id-Version: PACKAGE VERSION\\n\"\n"
                 ."\"Report-Msgid-Bugs-To: \\n\"\n"
                 ."\"POT-Creation-Date: ".localtime()."\\n\"\n"
                 ."\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n"
                 ."\"Last-Translator: FULL NAME <EMAIL\@ADDRESS>\\n\"\n"
                 ."\"Language-Team: LANGUAGE <LL\@li.org>\\n\"\n"
                 ."\"MIME-Version: 1.0\\n\"\n"
                 ."\"Content-Type: text/plain; charset=".$enc{$lang}."\\n\"\n"
                 ."\"Content-Transfer-Encoding: 8bit\\n\"\n\n";
        }

        open (OUT, ">>", "$podir/$polang")
                || die "Can't open $podir/$polang for writing: $!\n";
        binmode(OUT);
        print OUT $header;
        while (@{$out{$lang}}) {
                print OUT "#: ".(shift @{$out{$lang}})."\n";
                print OUT "#, fuzzy\n" if (shift @{$out{$lang}});
                print OUT "msgid \"".
                          escape_po(shift @{$out{$lang}}).
                          "\"\n";
                print OUT "msgstr \"".
                          escape_po(shift @{$out{$lang}}).
                          "\"\n\n";
        }
        close (OUT) || die "Can't write $podir/$polang: $!\n";
        if ($enc{$lang} eq 'CHARSET') {
                $unknown_encoding = 1;
                warn "Warning: Encoding for language $lang is unknown.\n".
                     "Warning: This must be fixed before running po2debconf, so\n".
                     "Warning:   $podir/$polang is renamed into $podir/$polang.unknown\n".
                     "Warning: in order not to break other languages.\n".
                     "Warning: Do not forget to rename it after having fixed its ".
                     "encoding declaration!\n";
                rename "$podir/$polang", "$podir/$polang.unknown";
        } else {
                system("msguniq", "--use-first", "-o", "$podir/$polang.tmp", "$podir/$polang") == 0 or die "msguniq failed: $!\n";
                rename "$podir/$polang.tmp", "$podir/$polang";
        }
}

foreach my $master (keys %txt) {
        rename $master, "$master.old"
                or die "Unable to rename $master into $master.old\n";
        print STDERR "Creating $master\n" if $verbose;
        open (NEW, ">", $master) ||
                die "Can't open $master for writing: $!\n";
        print NEW $txt{$master};
        close (NEW);
}

my $current = '';
if (-e "$podir/POTFILES.in") {
        local $/ = undef;
        open (LIST, "<",  "$podir/POTFILES.in") ||
                die "Can't read $podir/POTFILES.in: $!\n";
        $current = <LIST>;
        close (LIST);
}
print STDERR "Create $podir/POTFILES.in\n" if $verbose;
open (LIST, ">", "$podir/POTFILES.in") ||
        die "Can't open $podir/POTFILES.in for writing: $!\n";
print LIST $current;
foreach (@ARGV) {
        print LIST "[type: gettext/rfc822deb] $_\n"
                unless $current =~ m/ $_\b/m;
}
close (LIST) || die "Can't open write $podir/POTFILES.in$!\n";

if ($merge) {
        foreach my $lang (keys %out) {
                my $polang = $lang;
                $polang =~ s/_(..)$/_\U$1\E/;
                if (-f "$oldpodir/$polang.po") {
                        unlink "$podir/temp";
                        system("msgcat", "--use-first", "-o", "$podir/temp", "$oldpodir/$polang.po", "$podir/$polang.po") == 0 && system("cp", "$podir/temp", "$oldpodir/$polang.po");
                } else {
                        system("cp", "$podir/$polang.po", "$oldpodir/$polang.po");
                }
        }
        File::Path::rmtree($tmpdir, 0, 1);
        print "\n".
                "  To complete conversion, you must:\n".
                "    a. Adjust _Choices or __Choices fields in master templates file.\n".
                "    b. Run debconf-updatepo\n";
} else {
        print STDERR "Running debconf-updatepo --podir=$podir\n" if $verbose;
        system("debconf-updatepo", "--podir=$podir");

        print "\n".
                "  To complete conversion, you must:\n".
                "    a. Check that new templates files contain all the localized fields\n".
                "    b. Add po-debconf to Build-Depends or Build-Depends-Indep in debian/control\n".
                "    c. Remove obsolete files:\n".
                wrap('         ', '         ', join(' ', @obsolete))."\n".
                "    d. Edit debian/rules to generate the localized templates file, either\n".
                "       with dh_installdebconf or directly with po2debconf\n";
        print   "    e. Check encoding in $podir/*.po.unknown files\n"
                if ($unknown_encoding);
}

exit 0;

=head1 AUTHORS

Martin Quinson <martin.quinson@ens-lyon.fr>
Denis Barbier <barbier@linuxfr.org>

=cut

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists