1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
#!/usr/bin/env perl
# implements xgettext for Log::Report only, using Log::Report::Extract::PPI
# Options like GNU's xgettext
use warnings;
use strict;
use Log::Report 'log-report';
use Getopt::Long qw/:config no_ignore_case bundling/;
use File::Find qw/find/;
use Pod::Usage qw/pod2usage/;
my $lang = 'perl';
my $version = 0;
my $help = 0;
my $cleanup = 1;
my ($from, $output, $fn_match, %configs);
my ($char_in, $char_out) = ('utf-8', 'utf-8');
my ($default_domain, $mode, $template);
GetOptions
'cleanup!' => $cleanup # kill transl from removed files, def true
, 'config|c=s' => \%configs # domain configurations
, 'domain|d=s' => \$default_domain # for templates
, 'files-from|f=s' => \$from # file with filenames (MANIFEST?) or '-'
, 'files-match|m=s' => \$fn_match # select filename is dir
, 'from-code=s' => \$char_in
, 'help|h' => \$help
, 'language|L=s' => \$lang
, 'mode=s' => \$mode
, 'output-dir|p=s' => \$output
, 'template|t=s' => \$template # pattern in ::Template
, 'to-code=s' => \$char_out # missing in xgettext?
, 'verbose=i' => \$mode
, 'version|V' => \$version
, 'v+' => \$mode
or pod2usage(1);
if($version)
{ print "Log::Report $Log::Report::VERSION\n";
exit 0;
}
$help && podusage(0);
# Load domain information, for instance defining context_rules. The
# definitions are global, so automatically find their way in the Log::Report
# internals.
# --config domain1=filename domain2=filename
# --config domain1=filename --config domain2=filename
while(my ($domain, $fn) = each %configs)
{ trace "configuring domain $domain from $fn";
textdomain $domain, config => $fn;
}
# all output to stderr
dispatcher FILE => stderr => to => \*STDERR
, mode => $mode, format => sub {shift};
dispatcher close => 'default';
$template || $lang eq 'perl'
or error __x"programming language {lang} not supported", lang => $lang;
defined $output
or error __"explicit output directory (-p) required";
-d $output or mkdir $output
or fault __x"cannot create output directory {dir}", dir => $output;
my @filenames;
if(defined $from)
{ !@ARGV
or error __x"do not combine command-line filenames with --files-from";
if($from eq '-')
{ @filenames = <STDIN>;
}
else
{ open FILENAMES, '<:raw', $from
or fault __x"cannot read filename list from {fn}", fn => $from;
@filenames = <FILENAMES>;
close FILENAMES;
}
chomp(@filenames);
}
elsif(@ARGV)
{ find sub { push @filenames, $File::Find::name if -f }, @ARGV;
}
else
{ error "give --files-from or directories to be processed";
}
my $extr;
my %processed;
if($template)
{ # process from template
eval "require Log::Report::Extract::Template";
panic $@ if $@;
$default_domain
or error __x"specify a text-domain (-d) for the templates";
$extr = Log::Report::Extract::Template->new
( lexicon => $output
, charset => $char_out
, domain => $default_domain
, pattern => $template
);
$fn_match ||= qr/\.tt2?$/i;
foreach my $filename (@filenames)
{ unless($filename =~ $fn_match)
{ info __x"skipping (not a template) {fn}", fn => $filename;
next;
}
$extr->process($filename, charset => $char_in);
$processed{$filename}++;
}
}
else
{ # process the pm files
eval "require Log::Report::Extract::PerlPPI";
error $@ if $@;
$extr = Log::Report::Extract::PerlPPI->new
( lexicon => $output
, charset => $char_out
);
$fn_match ||= qr/\.p[lm]$/i;
foreach my $filename (@filenames)
{ unless($filename =~ $fn_match)
{ info __x"skipping (not perl) {fn}", fn => $filename;
next;
}
$extr->process($filename, charset => $char_in);
$processed{$filename}++;
}
}
$extr->cleanup(keep => \%processed)
if $cleanup;
$extr->showStats;
$extr->write;
__END__
=head1 NAME
xgettext-perl - extract translatable strings
=head1 SYNOPSIS
xgettext-perl [GENERIC OPTIONS][SCRIPT OPTIONS] directories
xgettext-perl [GENERIC OPTIONS][TEMPLATE OPTIONS] directories
GENERIC OPTIONS
--config -c %config domain configuration
--files-from -f $filename source of filenames to be processed
--from-code $charset used by input files (default utf-8)
--no-cleanup keep unprocessed files in po table
--output-dir -p $directory location of lexicons (required)
--to-code $charset charset of po files (default utf-8)
--version -V show version of this script
--verbose=3 -v -vv -vvv debug mode
TEMPLATE OPTIONS
--domain -d $domain domain to be used
--template -t $notation how to recognize the strings to be taken
--files-match -m $regex filter filenames, default .pm and .pl
SCRIPT OPTIONS
--language -L $proglang programming language syntax (now only perl)
--files-match -m $regex filter filenames, default .tt and .tt2
=head1 DESCRIPTION
This script will maintain PO-files: translation files. On the moment, the
number of syntaxes is quite limited (see below)
There is no restrain on syntaxes which can be supported: there just was no
practical use to implement it yet.
=head2 Complex options
=over 4
=item --config %config
Log::Report translations supports complex additional features, like
context sensitive translations, which require a configuration file.
See Log::Report::Context
Say, your scripts and templates use textdomain name-spaces C<domain1>
and C<domain2> (plase use better names), then you can pass their
respective configuration files as:
--config domain1=filename domain2=filename # or
--config domain1=filename --config domain2=filename
=item --cleanup --no-cleanup
You should scan all script or template files in one go, because PO records
from files which are not mentioned will get removed. That's the clean-up.
However, when you need more scans for a full update, you need to use this
option. This also implies possible polution of your translation tables.
=back
=head2 Extracting from Perl with Log::Report syntax
When no --template notation is given, the provided file-names are expected
to contain program text. Only Perl5 programs using the Log::Report msgid
notation (with leading '__' to mean gettext)
=head2 Extracting from Template::Toolkit
See L<Log::Report::Extract::Template>
=cut
|