/[webwml]/webwml/check_trans.pl
ViewVC logotype

Contents of /webwml/check_trans.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.59 - (hide annotations) (download)
Sat Aug 7 21:01:16 2004 UTC (8 years, 9 months ago) by kraai
Branch: MAIN
Changes since 1.58: +6 -2 lines
File MIME type: text/plain
Skip comments in language.conf, thanks to Luca Monducci.
1 italian 1.1 #!/usr/bin/perl -w
2    
3 joy 1.28 # This is a little utility designed to keep track of translations
4     # in the Debian web site CVS repository.
5    
6     # For information about translation revisions please see
7     # http://www.debian.org/devel/website/uptodate
8    
9 french 1.41 # This is GPL'ed code.
10     # Copyright 1998 Paolo Molaro <lupus@debian.org>.
11 peterk 1.55 # Copyright 1999-2003 Peter Karlsson <peterk@debian.org>.
12 french 1.41 # Copyright 2000,2001 Martin Quinson <mquinson@ens-lyon.fr>.
13 italian 1.1
14 joy 1.28 # Invocation:
15 joy 1.34 # check_trans.pl [-vqdlM] [-C dir] [-p pattern] [-s subtree]
16 barbier 1.48 # [-m email -n N] [-c charset] [-g] [-t outputtype]
17 joy 1.28 # [language]
18    
19     # It needs to be run from the top level webwml directory.
20     # If you don't specify a language on the command line, the language name
21     # will be loaded from a file called language.conf, if such a file exists.
22    
23     # For example:
24     # $ check_trans.pl -v italian
25 italian 1.1 # You may also check only some subtrees as in:
26 joy 1.28 # $ check_trans.pl -s devel italian
27 italian 1.1
28 joy 1.28 # Options:
29 joy 1.56 # -Q enable really quiet mode
30     # -q just don't whine about missing files
31 joy 1.28 # -v enable verbose mode
32 joy 1.56 # -V enable very verbose mode
33 barbier 1.31 # -C <dir> go to <dir> directory before running this script
34 joy 1.28 # -d output CVS diffs
35     # -l output CVS log messages
36 french 1.42 # -T output translated diffs
37 joy 1.28 # -p <pattern> include only files matching <pattern>,
38 french 1.41 # default is *.html|*.wml
39 joy 1.28 # -s <subtree> check only that subtree
40 barbier 1.31 # -t <type> choose output type (default is `text')
41 joy 1.28 # -M display differences for all 'Makefile's
42 peterk 1.57 # -a output age of translation (if older than 2 months)
43 joy 1.28
44     # Options useful when sending mails:
45     # -m <email> sends mails to translation maintainers
46     # PLEASE CAREFULLY READ THE BELOW TEXT ABOUT MAKING MAILS!
47     # <email> is the default recipient
48     # (it should be the list used for organisation,
49     # e.g. debian-l10n-french@lists.debian.org)
50     # -g debuG
51 barbier 1.48 # -c <charset> charset used in mails
52 joy 1.28 # -n <1|2|3> send mails of priority upper or equal to
53     # 1 (monthly), 2 (weekly) or 3 (daily)
54 french 1.13
55     # Making Mails
56     # If you want to, this script send mails to the maintainer of the mails.
57 joy 1.28 # BEWARE, SOME PEOPLE DO NOT LIKE TO RECEIVE AUTOMATIC MAILS!
58    
59     # PREREQUISITES:
60 french 1.41 # You will need two databases:
61 joy 1.28 # - one in which to see which translator maintains which file
62 french 1.13 # it must be named "./$langto/international/$langto/current_status.pl"
63 joy 1.28 # (where $langto equals "french", "italian" or so)
64     # See webwml/french/international/french/current_status.pl" for example.
65     # - one in which to get info about translators and the frequency at
66     # which they want to get mails. It must be named
67     # webwml/$langto/international/$langto/translator.db.pl
68     # Please refer to the French one for more info.
69    
70 french 1.13 # USAGE:
71 french 1.41 # If you give the "-g" option, all mails are sent to the default addressee
72 joy 1.28 # (i.e. the one given as value to the -m option), without respect to their
73     # normal addressee. It is useful if you want to run it for yourself,
74     # and for debugging.
75 french 1.41 # Without that option, it sends real mails to real addresses.
76     # MAKE SURE THE ADDRESSEES REALLY WANT TO GET THESE MAILS
77 italian 1.1
78 joy 1.32 use strict;
79 italian 1.1 use Getopt::Std;
80 swedish 1.2 use IO::Handle;
81 barbier 1.31 use Date::Parse;
82    
83 barbier 1.36 # These modules reside under webwml/Perl
84     use lib ($0 =~ m|(.*)/|, $1 or ".") ."/Perl";
85     use Local::Cvsinfo;
86 french 1.41 use Local::WmlDiffTrans;
87 barbier 1.36 use Webwml::TransCheck;
88     use Webwml::TransIgnore;
89    
90 joy 1.28 # TODO:
91     # get the revisions from $lang/intl/$lang so diffing works
92     # need to quote dirnames?
93     # use a file to bind a file to a translator?
94 french 1.13
95 joy 1.32 # global db variables
96 french 1.13 my $translations_status;
97     my $translators;# the ref resulting of require
98     my %translators;# the real hash
99    
100 joy 1.32 # misc hardcoded things
101     my $maintainer = "mquinson\@ens-lyon.fr"; # the default e-mail at which to bitch :-)
102 italian 1.1
103 joy 1.32 # options (note: with perl 5.6, this could change to our())
104 peterk 1.57 use vars qw($opt_C $opt_M $opt_Q $opt_c $opt_d $opt_g $opt_l $opt_m $opt_n
105     $opt_p $opt_q $opt_s $opt_t $opt_T $opt_v $opt_V $opt_a);
106 joy 1.32 $opt_n = 5; # an invalid default
107 joy 1.28 $opt_s = '';
108 barbier 1.31 $opt_C = '.';
109     $opt_t = 'text';
110 joy 1.28
111 peterk 1.57 unless (getopts('vgdqQC:m:c:s:Tt:p:ln:MVa'))
112 peterk 1.21 {
113     open SELF, "<$0" or die "Unable to display help: $!\n";
114     HELP: while (<SELF>)
115     {
116     print, next if /^$/;
117     last HELP if (/^use/);
118     s/^# ?//;
119 joy 1.28 next if /^!/;
120 peterk 1.21 print;
121     }
122     exit;
123     }
124 joy 1.32
125 peterk 1.57 if ($opt_a)
126     {
127 peterk 1.58 require Date::Manip;
128     import Date::Manip;
129 peterk 1.57 }
130    
131 joy 1.28 die "you can't have both verbose and quiet, doh!\n" if (($opt_v) && ($opt_Q));
132 joy 1.56 die "you can't have both very verbose and quiet, doh!\n" if (($opt_V) && ($opt_Q));
133    
134     $opt_v = 1 if ($opt_V);
135 italian 1.1
136 joy 1.23 warn "Checking subtree $opt_s only\n" if (($opt_v) && ($opt_s));
137 italian 1.1
138     # include only files matching $filename
139 peterk 1.57 my $filename = $opt_p || '(\.wml$)|(\.html$)|(\.src$)';
140 barbier 1.36
141 barbier 1.43 # Go to desired directory
142     chdir($opt_C) || die "Cannot go to $opt_C\n";
143    
144 barbier 1.36 my $cvs = Local::Cvsinfo->new();
145     $cvs->options(
146     recursive => 1,
147     matchfile => [ $filename ],
148     skipdir => [ "template" ],
149     );
150     # This object is used to retrieve information when original is
151     # not English
152     my $altcvs = $cvs->new();
153    
154     # Global .transignore
155     my $globtrans = Webwml::TransIgnore->new(".");
156 barbier 1.31
157 joy 1.28 # language configuration
158 peterk 1.53 my $defaultlanguage = '';
159 peterk 1.50 if (exists $ENV{DWWW_LANG})
160 alfie 1.44 {
161     $defaultlanguage = $ENV{DWWW_LANG};
162 peterk 1.50 }
163 alfie 1.44 elsif (open CONF, "<language.conf")
164 swedish 1.6 {
165 kraai 1.59 while (<CONF>)
166     {
167     next if /^#/;
168     $defaultlanguage = <CONF>;
169     chomp $defaultlanguage;
170     }
171 swedish 1.6 close CONF;
172     }
173    
174 joy 1.28 my $from = 'english';
175     my $to = shift || $defaultlanguage;
176     $to =~ s%/$%%; # Remove slash from the end
177 italian 1.1
178 peterk 1.53 if ($to eq '')
179     {
180 peterk 1.55 die "Language not defined in DWWW_LANG, language.conf or on command line\n";
181 peterk 1.53 }
182    
183 joy 1.28 my $langto = $to;
184 french 1.13 $langto =~ s,^([^/]*).*$,$1,;
185 peterk 1.50 if (-e "./$langto/international/$langto/current_status.pl" &&
186 french 1.13 -e "./$langto/international/$langto/translator.db.pl") {
187     print "READ PAGES DB: $langto/international/$langto/current_status.pl\n"
188     if $opt_v;
189     push(@INC,"./$langto/international/$langto");
190     require 'current_status.pl';
191     print "READ TRANSLATOR DB: $langto/international/$langto/translator.db.pl\n"
192     if $opt_v;
193     require 'translator.db.pl';
194     %translators=%{init_translators()};
195 barbier 1.46 if (defined($translators{default})) {
196     my @field_list = keys %{$translators{default}};
197     foreach my $user (keys %translators) {
198     next unless $user =~ m/ /;
199     foreach my $f (@field_list) {
200     $translators{$user}{$f} = $translators{default}{$f}
201     unless defined($translators{$user}{$f});
202     }
203     }
204     }
205 french 1.13 } else {
206     die "I need my DBs to send mails !\n Please read the comments in the script and try again\n" if $opt_m;
207     }
208    
209     if ($opt_m) {
210     unless ($opt_n =~ m,[123],) {
211     die "Invalid priority. Please set -n value to 1, 2 or 3.\n".
212     "(assuming you know what you're doing)\n";
213     }
214     }
215    
216 italian 1.1 $from = "$from/$opt_s";
217     $to = "$to/$opt_s";
218    
219 french 1.13 init_mails();
220 barbier 1.31
221     print "\$translations = {\n" if $opt_t eq 'perl';
222    
223 peterk 1.49 # Check the files in the English directory
224    
225 joy 1.56 my $V = $opt_V ? 1 : 0;
226     $cvs->readinfo($from, verbose => $V );
227 barbier 1.36 foreach my $path (@{$cvs->dirs()}) {
228     my $tpath = $path;
229     $tpath =~ s/^$from/$to/o;
230     my $transignore = Webwml::TransIgnore->new($tpath);
231     next unless $transignore->found();
232     warn "Loading $tpath/.transignore\n" if $opt_v;
233     foreach (@{$transignore->local()}) {
234     s/^$to/$from/o;
235     $cvs->removefile($_);
236     }
237     }
238    
239 peterk 1.49 my %checkedfile;
240    
241 barbier 1.36 foreach (sort @{$cvs->files()}) {
242 barbier 1.31 my ($path, $tpath);
243 italian 1.1 $path = $_;
244     $tpath = $path;
245     $tpath =~ s/^$from/$to/o;
246 peterk 1.49 $checkedfile{$tpath} = 1; # Remember which files we found here
247 french 1.41 check_file($tpath,
248     $cvs->revision($path),
249     str2time($cvs->date($path)),
250     get_translators_from_db($tpath));
251 french 1.13 }
252    
253 peterk 1.49 # Now check all the files in the translated directory as well, there may be
254     # some files that are not available in the English version.
255    
256     $cvs->reset();
257 joy 1.56 $cvs->readinfo($to, verbose => $V );
258 peterk 1.49 foreach my $tpath (@{$cvs->dirs()})
259     {
260     my $transignore = Webwml::TransIgnore->new($tpath);
261     next unless $transignore->found();
262     warn "Loading $tpath/.transignore\n" if $opt_v;
263     foreach (@{$transignore->local()})
264     {
265     s/^$to/$from/o;
266     $cvs->removefile($_);
267     }
268     }
269    
270     foreach (sort @{$cvs->files()})
271     {
272     my $tpath = $_;
273     next if defined $checkedfile{$tpath}; # Don't look at a file twice
274     warn "$tpath does not match anything in English\n" if $opt_v;
275     check_file($tpath, undef, undef, get_translators_from_db($tpath));
276     }
277    
278 barbier 1.31 print "}; 1;\n" if $opt_t eq 'perl';
279    
280 french 1.13 send_mails();
281 peterk 1.21
282 french 1.41 if ($opt_M) {
283 joy 1.32 foreach my $makefile (split(/\n/, `find $from -name Makefile -print`)) {
284 peterk 1.21 my $destination = $makefile;
285     $destination =~ s/^$from/$to/o;
286     if (-e $destination) {
287 peterk 1.53 # First check if the destination makefile simply includes the english
288     # version
289     my $includes = 0;
290     if (open MK, "<$destination")
291     {
292     my $firstline = <MK>;
293     close MK;
294     $includes = 1 if $firstline =~ m'^include.*subst webwml/.*,webwml/english,.*CURDIR.*Makefile';
295     }
296     else
297     {
298     warn "Cannot read $from: $!\n";
299     }
300     unless ($includes)
301     {
302     # Otherwise show any differences
303     STDOUT->flush;
304     system("diff -u $destination $makefile");
305     STDOUT->flush;
306     }
307 peterk 1.21 }
308     }
309     }
310 french 1.13
311     sub verify_send {
312 joy 1.15 return 1 unless ($opt_m);
313 french 1.13 # returns true whether we have to send this part to this guy
314     my $name=shift;
315     my $part=shift;
316     $name =~ s,<.*?>,,;
317     $name =~ s,^ *(.*?) *$,$1,;
318     print "$name is unknown\n" unless defined($translators{$name});
319     # print "pri=$opt_n ; maint_pri=${translators{$name}{$part}}\n";
320     return $opt_m # if we have to send any mail
321     && defined($translators{$name}) # if this guy is known
322     && defined($translators{$name}{$part}) # we know something about the wanted frequency
323     && ($opt_n <= $translators{$name}{$part}); # check if the frequency is ok
324     }
325    
326     sub get_translators_from_db {
327     my $id=shift;
328     my $res='';
329    
330     $id=~ s,^$langto/,,;
331     $id=~ s/\.wml$//;
332     if (defined(%{$$translations_status{$id}})
333     && defined ($$translations_status{$id}{'translation_maintainer'})) {
334     foreach my $n (sort @{$$translations_status{$id}{'translation_maintainer'}}) {
335     $res .= " $n";
336     }
337     } else {
338     $res = "";
339     }
340     return $res;
341     }
342    
343     sub init_mails {
344     return unless $opt_m;
345 joy 1.16 eval q{use MIME::Lite};
346 french 1.13 foreach my $name (keys %translators) {
347     return if defined $translators{$name}{"msg"};
348 barbier 1.46 next if $name eq 'default' || $translators{$name}{email} eq '';
349 french 1.13 $translators{$name}{"msg"} = MIME::Lite->new(
350     From => "Script watching translation state <$maintainer>",
351     To => ($opt_g ? $opt_m : $translators{$name}{"email"}),
352 barbier 1.46 Subject => $translators{$name}{mailsubject},
353 french 1.13 Type => 'multipart/mixed');
354 barbier 1.46 my $str;
355     {
356     open (MAIL, "< $translators{$name}{mailbody}")
357     or die "$name: Unable to read \`$translators{$name}{mailbody}'";
358     local $/ = undef;
359     $str= <MAIL>;
360     close (MAIL);
361     }
362     1 while ($str =~ s/#(.*?)#/eval $1/ge);
363 french 1.13
364 barbier 1.48 my $part = MIME::Lite->new(
365 french 1.13 Type => 'TEXT',
366     Data => $str);
367 barbier 1.48 $part->attr('content-type.charset' => $opt_c) if $opt_c;
368     $translators{$name}{"msg"}->attach($part);
369 french 1.13 $translators{$name}{"send"}=0;
370     }
371     }
372    
373     sub send_mails {
374     #Makes the mails and send them
375     return unless $opt_m;
376     foreach my $name (sort keys %translators) {
377 barbier 1.46 next if $name eq 'default' || $translators{$name}{email} eq '';
378 french 1.13 $translators{$name}{"msg"}->attach(
379     Type => 'TEXT',
380     Filename => 'NeedToUpdate_summary',
381     Data => $translators{$name}{"part_summary"})
382     if defined($translators{$name}{"part_summary"});
383     $translators{$name}{"msg"}->attach(
384     Type => 'TEXT',
385     Filename => 'Missing_summary',
386     Data => $translators{$name}{"part_missing"})
387     if defined($translators{$name}{"part_missing"});
388 peterk 1.50 foreach my $part (qw (file logs diff tdiff)) {
389 french 1.13 if (defined($translators{$name}{"part_$part"})) {
390     foreach my $file (sort keys %{$translators{$name}{"part_$part"}}) {
391     $translators{$name}{"msg"}->attach(
392     Type => 'TEXT',
393     Filename => "$file.$part",
394     Data => $translators{$name}{"part_$part"}{$file});
395     }
396     }
397 italian 1.1 }
398 french 1.13 if ($translators{$name}{"send"}) {
399 barbier 1.47 print "send mail to $name\n" unless $opt_Q;
400 french 1.13 if (($name =~ m,mquinson,) || ($opt_g && $opt_m eq $maintainer)) {
401 barbier 1.47 print "Well, detourned to $maintainer\n" unless $opt_Q;
402 french 1.13 $translators{$name}{"msg"}->send;
403     }
404     # $translators{$name}{"msg"}->print_header;
405     $translators{$name}{"msg"}->send;
406     } else {
407 barbier 1.47 print "didn't send mail to $name: nothing to say to him\n" unless $opt_Q;
408 peterk 1.50 }
409 french 1.41 }
410 italian 1.1 }
411    
412 french 1.13 sub add_part {
413     my $name = shift;
414     my $part = shift;
415 peterk 1.50 my $txt = shift;
416 french 1.13 $name =~ s,<.*?>,,;
417     $name =~ s,^ *(.*?) *$,$1,;
418     if (verify_send($name,$part)) {
419     $translators{$name}{"part_$part"}.=$txt;
420     $translators{$name}{"send"}=1;
421     }
422     }
423 joy 1.28
424 french 1.13 sub add_sub_part {
425     my $name = shift;
426     my $part = shift;
427     my $subpart=shift;
428 french 1.41 my $txt = shift;
429 french 1.13 $name =~ s,<.*?>,,;
430     $name =~ s,^ *(.*?) *$,$1,;
431 french 1.42 # print "add_sub_part($name)(part=$part)($subpart):$txt" if $opt_v;
432 french 1.41 STDOUT->flush;
433 french 1.13 if (verify_send($name,$part)) {
434     # print "YES\n";
435 french 1.41 $translators{$name}{"part_$part"}{$subpart}.= "$txt";
436 french 1.13 $translators{$name}{"send"}=1;
437     }
438     # print "no\n";
439     }
440    
441 french 1.41 sub get_diff_txt {
442     my ($oldr, $revision, $oldname, $name) = @_;
443     my $cmd;
444    
445     # Get old revision file
446 french 1.42 $cmd = "cvs -z3 update -r $oldr -p $oldname 2>/dev/null";
447 french 1.41 # print "!get_diff_txt: cvs -z3 update -r ".$oldr." -p ".$oldname."\n";
448     my @old_rev_file_lines = qx($cmd);
449    
450     # Get translation file
451     open (FILE,"$name") || die ("Can't open `$name' for read");
452     my @translation_file_lines;
453     while (<FILE>) {
454     $translation_file_lines[scalar @translation_file_lines] = $_;
455     }
456     close FILE || die ("Can't close $name after reading");
457    
458     # Get diff lines
459 french 1.42 $cmd = "cvs -z3 diff -u -r$oldr -r $revision $oldname 2>/dev/null";
460     # print "get_diff_txt: $cmd: cvs -z3 diff -u -r$oldr -r $revision $oldname\n";
461 french 1.41 my @diff_lines = qx($cmd);
462    
463     my $txt = Local::WmlDiffTrans::find_trans_parts(\@old_rev_file_lines,
464     \@translation_file_lines,
465     \@diff_lines);
466    
467     return $txt;
468     }
469 french 1.13
470 italian 1.1 sub check_file {
471 barbier 1.31 my ($name, $revision, $mtime, $translator) = @_;
472 barbier 1.54 $revision ||= 'n/a';
473 peterk 1.51 my ($oldr, $oldname, $original, $fromname);
474 joy 1.28 warn "Checking $name, English revision $revision\n" if $opt_v;
475 barbier 1.31 my $docname = $name;
476     $docname =~ s#^$langto/##;
477     $docname =~ s#\.wml$##;
478 italian 1.1 unless (-r $name) {
479 peterk 1.52 (my $iname = $name) =~ s/^$to//o;
480 barbier 1.40 if (!$globtrans->is_global($iname)) {
481 joy 1.28 unless (($opt_q) || ($opt_Q)) {
482 barbier 1.31 if ($opt_t eq 'perl') {
483     print "'$docname' => {\n\t'type' => 'Web',\n";
484     print "\t'revision' => '$revision',\n";
485 barbier 1.54 print "\t'mtime' => '$mtime',\n" if $mtime;
486 barbier 1.31 print "\t'status' => 1,\n";
487     print "},\n";
488     } else {
489     print "Missing $name version $revision\n";
490     }
491 barbier 1.46 add_part("untranslated","missing","Missing $name version $revision\n");
492 joy 1.22 }
493 joy 1.28 } else {
494     warn "Ignored $name\n" if $opt_v;
495 french 1.13 }
496 italian 1.1 return;
497     }
498 barbier 1.36 my $transcheck = Webwml::TransCheck->new($name);
499 barbier 1.38 $oldr = $transcheck->revision() || 0;
500     if (!$oldr && ($name =~ m#$langto/international/$langto#i)) {
501     # This document is original, check for
502     # english/international/$langto...
503     $name =~ s{^$to}{$from};
504     $transcheck = Webwml::TransCheck->new($name);
505     $oldr = $transcheck->revision() || 0;
506     }
507 barbier 1.36 $translator = $transcheck->maintainer() || "";
508     $original = $transcheck->original();
509     warn "Found translation for $oldr\n" if $opt_v and $oldr;
510     warn "Translated by $translator\n" if $opt_v and $translator;
511     warn "Original is $original\n" if $opt_v and $original;
512     if ($original) {
513 peterk 1.51 my ($fromdir);
514 barbier 1.36 $fromname = $name;
515     $fromname =~ s{^[^/]+}{$original};
516     $fromdir = $fromname;
517     $fromdir =~ s{/+[^/]+$}{};
518     $altcvs->reset();
519     $altcvs->readinfo($fromdir, matchfile => [$fromname]);
520     $revision = $altcvs->revision($fromname);
521     warn "Original is $original, revision $revision\n" if $opt_v;
522 joy 1.24 }
523    
524 barbier 1.36 $translator =~ s/^\s+//;
525     $translator =~ s/\s+$//;
526 french 1.13
527 joy 1.18 my $str;
528 peterk 1.49 my $status = 8; # Unknown
529     (my $numrev) = $revision =~ m/^1\.(\d+)$/; $numrev ||= "0";
530     (my $numoldr) = $oldr =~ m/^1\.(\d+)$/; $numoldr ||= "0";
531    
532     if ($revision ne 'n/a')
533     {
534     # The original version of this file exists (English or otherwise)
535     # - compare the translated version number to the original
536     if (!$oldr) {
537 peterk 1.57 if ($name =~ /^english/)
538     {
539     # This is the original file
540     $status = 4; # Up-to-date
541     $oldr = $revision;
542     }
543     else
544     {
545     $oldr = '1.0';
546     $str = "Unknown status of $name (revision should be $revision)";
547     }
548 peterk 1.49 } elsif ($oldr eq $revision) {
549     $status = 4; # Up-to-date
550     } elsif ($numoldr > $numrev) {
551     $str = "Broken revision number $oldr for $name, it should be $revision";
552     } else {
553     $str = "NeedToUpdate $name from version $oldr to version $revision";
554     $status = 3; # Needs update
555     }
556     }
557     else
558     {
559     # There is no English file matching this one.
560     if ($oldr eq '0')
561     {
562     # There is no translation-check header, so it must be the
563     # original version, and is thus always up-to-date.
564     $status = 4; # Up-to-date
565     }
566     else
567     {
568     # There is a translation-check header referencing an English
569     # version, which means that the English file has been removed.
570     $status = 7; # Obsolete
571     $str = "Obsolete $name";
572     }
573     }
574    
575 french 1.13 $str .= " (maintainer: $translator)" if $translator;
576 barbier 1.31 if ($opt_t eq 'perl') {
577     print "'$docname' => {\n\t'type' => 'Web',\n";
578     print "\t'revision' => '$revision',\n";
579 barbier 1.54 print "\t'mtime' => '$mtime',\n" if $mtime;
580 barbier 1.31 print "\t'base_revision' => '$oldr',\n";
581     print "\t'translation_maintainer' => ['$translator'],\n" if $translator;
582     print "\t'status' => $status,\n";
583     print "},\n";
584     } elsif ($str && $oldr ne $revision) {
585 joy 1.23 $str .= "\n";
586     print $str unless ($opt_Q);
587     }
588    
589 peterk 1.50 # Return if we're up-to-date or the original is missing
590     return if (defined($oldr) && ($oldr eq $revision || $revision eq 'n/a'));
591 barbier 1.31
592 peterk 1.51 if ($original)
593     {
594     # Source is non-English, use name we set up above
595     $oldname = $fromname;
596     }
597     else
598     {
599     # Source is English
600     $oldname = $name;
601     $oldname =~ s/^$to/$from/;
602     }
603 peterk 1.17
604     my @logrev = split(/\./, $oldr);
605     $logrev[$#logrev] ++;
606     my $logoldr = join('.', @logrev);
607 barbier 1.46 my $maxdelta = $transcheck->maxdelta() || $translators{maxdelta}{maxdelta} || 5;
608 peterk 1.17
609 french 1.13 if ($opt_m) {
610 barbier 1.46 my @list_tr;
611     if ($translator eq "") {
612     if ($numrev - $numoldr >= $maxdelta) {
613     @list_tr = ("maxdelta");
614     } else {
615     @list_tr = ("unmaintained");
616     }
617     } elsif ($numrev - $numoldr >= $maxdelta) {
618     @list_tr = ($translator, "maxdelta");
619     } else {
620     @list_tr = ($translator);
621     }
622     foreach my $tname (@list_tr) {
623     add_part($tname,"summary",$str);
624     add_sub_part($tname,"diff",$name,
625     join("",qx(cvs -z3 diff -u -r'$oldr' -r $revision $oldname)));
626     add_sub_part($tname,"tdiff",$name,
627     get_diff_txt("$oldr","$revision","$oldname","$name"));
628    
629     add_sub_part($tname,"logs",$name,
630     join("",qx(cvs -z3 log -r$logoldr:$revision $oldname)));
631     add_sub_part($tname,"file",$name,
632     join("",qx(cat $name)));
633     }
634 french 1.13 }
635 peterk 1.50
636 italian 1.1 if ($opt_d) {
637 swedish 1.2 STDOUT->flush;
638 barbier 1.31 my $cvsline = "cvs -z3 log -r'$logoldr:$revision' '$oldname'";
639 joy 1.32 warn "Running $cvsline\n" if (($opt_v) && ($opt_l));
640     system($cvsline) if $opt_l;
641     STDOUT->flush if $opt_l;
642 joy 1.25 $cvsline = "cvs -z3 diff -u -r '$oldr' -r '$revision' '$oldname'";
643     warn "Running $cvsline\n" if $opt_v;
644     system($cvsline);
645 swedish 1.2 STDOUT->flush;
646 peterk 1.50 }
647 peterk 1.57
648     if (3 == $status && $opt_a) {
649     # Check the age of this translation
650     STDOUT->flush;
651     my $cvsline = "cvs -z3 log -r'$logoldr' '$oldname'";
652     if (open CVSLOG, '-|', $cvsline)
653     {
654     CVSDATA: while (<CVSLOG>)
655     {
656     last CVSDATA if /^date:/;
657     }
658     close CVSLOG;
659     if (/^date: ([\d]{4}.[\d]{2}.[\d]{2})/)
660     {
661     # Got the date of the last translation
662     my $agestring = &DateCalc($1, 'today', 1, 1);
663     die "CVS date is in the future" if $agestring =~ /^\-/;
664     my ($years, $months, $weeks, $undef) = split /:/, substr($agestring, 1), 4;
665     my ($yearstring, $monthstring, $weekstring) = ('', '', '');
666     if ($years)
667     {
668     $yearstring = "$years year";
669     $yearstring .= 's' unless 1 == $years;
670     }
671     if ($months)
672     {
673     $monthstring = "$months month";
674     $monthstring .= 's' unless 1 == $months;
675     }
676     if ($weeks)
677     {
678     $weekstring = "$weeks week";
679     $weekstring .= 's' unless 1 == $weeks;
680     }
681    
682     if ($weeks > 2 || $months || $years)
683     {
684     $monthstring .= ', '
685     if $monthstring ne '' && $weekstring ne '';
686     $yearstring .= ', '
687     if $yearstring ne '' && ($monthstring ne '' || $weekstring ne '');
688     print "$name is outdated by $yearstring$monthstring$weekstring\n";
689     }
690     }
691     }
692     STDOUT->flush;
693     }
694 french 1.41
695 french 1.42 if ($opt_T) {
696 french 1.41 print get_diff_txt("$oldr", "$revision", "$oldname", "$name")."\n";
697     }
698 italian 1.1 }

  ViewVC Help
Powered by ViewVC 1.1.5