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

Contents of /webwml/check_trans.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.57 - (hide annotations) (download)
Fri Jul 4 21:49:58 2003 UTC (9 years, 11 months ago) by peterk
Branch: MAIN
Changes since 1.56: +68 -5 lines
File MIME type: text/plain
Added support for checking for how long a translation has been outdated.
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     use Date::Manip;
128     }
129    
130 joy 1.28 die "you can't have both verbose and quiet, doh!\n" if (($opt_v) && ($opt_Q));
131 joy 1.56 die "you can't have both very verbose and quiet, doh!\n" if (($opt_V) && ($opt_Q));
132    
133     $opt_v = 1 if ($opt_V);
134 italian 1.1
135 joy 1.23 warn "Checking subtree $opt_s only\n" if (($opt_v) && ($opt_s));
136 italian 1.1
137     # include only files matching $filename
138 peterk 1.57 my $filename = $opt_p || '(\.wml$)|(\.html$)|(\.src$)';
139 barbier 1.36
140 barbier 1.43 # Go to desired directory
141     chdir($opt_C) || die "Cannot go to $opt_C\n";
142    
143 barbier 1.36 my $cvs = Local::Cvsinfo->new();
144     $cvs->options(
145     recursive => 1,
146     matchfile => [ $filename ],
147     skipdir => [ "template" ],
148     );
149     # This object is used to retrieve information when original is
150     # not English
151     my $altcvs = $cvs->new();
152    
153     # Global .transignore
154     my $globtrans = Webwml::TransIgnore->new(".");
155 barbier 1.31
156 joy 1.28 # language configuration
157 peterk 1.53 my $defaultlanguage = '';
158 peterk 1.50 if (exists $ENV{DWWW_LANG})
159 alfie 1.44 {
160     $defaultlanguage = $ENV{DWWW_LANG};
161 peterk 1.50 }
162 alfie 1.44 elsif (open CONF, "<language.conf")
163 swedish 1.6 {
164     $defaultlanguage = <CONF>;
165     chomp $defaultlanguage;
166     close CONF;
167     }
168    
169 joy 1.28 my $from = 'english';
170     my $to = shift || $defaultlanguage;
171     $to =~ s%/$%%; # Remove slash from the end
172 italian 1.1
173 peterk 1.53 if ($to eq '')
174     {
175 peterk 1.55 die "Language not defined in DWWW_LANG, language.conf or on command line\n";
176 peterk 1.53 }
177    
178 joy 1.28 my $langto = $to;
179 french 1.13 $langto =~ s,^([^/]*).*$,$1,;
180 peterk 1.50 if (-e "./$langto/international/$langto/current_status.pl" &&
181 french 1.13 -e "./$langto/international/$langto/translator.db.pl") {
182     print "READ PAGES DB: $langto/international/$langto/current_status.pl\n"
183     if $opt_v;
184     push(@INC,"./$langto/international/$langto");
185     require 'current_status.pl';
186     print "READ TRANSLATOR DB: $langto/international/$langto/translator.db.pl\n"
187     if $opt_v;
188     require 'translator.db.pl';
189     %translators=%{init_translators()};
190 barbier 1.46 if (defined($translators{default})) {
191     my @field_list = keys %{$translators{default}};
192     foreach my $user (keys %translators) {
193     next unless $user =~ m/ /;
194     foreach my $f (@field_list) {
195     $translators{$user}{$f} = $translators{default}{$f}
196     unless defined($translators{$user}{$f});
197     }
198     }
199     }
200 french 1.13 } else {
201     die "I need my DBs to send mails !\n Please read the comments in the script and try again\n" if $opt_m;
202     }
203    
204     if ($opt_m) {
205     unless ($opt_n =~ m,[123],) {
206     die "Invalid priority. Please set -n value to 1, 2 or 3.\n".
207     "(assuming you know what you're doing)\n";
208     }
209     }
210    
211 italian 1.1 $from = "$from/$opt_s";
212     $to = "$to/$opt_s";
213    
214 french 1.13 init_mails();
215 barbier 1.31
216     print "\$translations = {\n" if $opt_t eq 'perl';
217    
218 peterk 1.49 # Check the files in the English directory
219    
220 joy 1.56 my $V = $opt_V ? 1 : 0;
221     $cvs->readinfo($from, verbose => $V );
222 barbier 1.36 foreach my $path (@{$cvs->dirs()}) {
223     my $tpath = $path;
224     $tpath =~ s/^$from/$to/o;
225     my $transignore = Webwml::TransIgnore->new($tpath);
226     next unless $transignore->found();
227     warn "Loading $tpath/.transignore\n" if $opt_v;
228     foreach (@{$transignore->local()}) {
229     s/^$to/$from/o;
230     $cvs->removefile($_);
231     }
232     }
233    
234 peterk 1.49 my %checkedfile;
235    
236 barbier 1.36 foreach (sort @{$cvs->files()}) {
237 barbier 1.31 my ($path, $tpath);
238 italian 1.1 $path = $_;
239     $tpath = $path;
240     $tpath =~ s/^$from/$to/o;
241 peterk 1.49 $checkedfile{$tpath} = 1; # Remember which files we found here
242 french 1.41 check_file($tpath,
243     $cvs->revision($path),
244     str2time($cvs->date($path)),
245     get_translators_from_db($tpath));
246 french 1.13 }
247    
248 peterk 1.49 # Now check all the files in the translated directory as well, there may be
249     # some files that are not available in the English version.
250    
251     $cvs->reset();
252 joy 1.56 $cvs->readinfo($to, verbose => $V );
253 peterk 1.49 foreach my $tpath (@{$cvs->dirs()})
254     {
255     my $transignore = Webwml::TransIgnore->new($tpath);
256     next unless $transignore->found();
257     warn "Loading $tpath/.transignore\n" if $opt_v;
258     foreach (@{$transignore->local()})
259     {
260     s/^$to/$from/o;
261     $cvs->removefile($_);
262     }
263     }
264    
265     foreach (sort @{$cvs->files()})
266     {
267     my $tpath = $_;
268     next if defined $checkedfile{$tpath}; # Don't look at a file twice
269     warn "$tpath does not match anything in English\n" if $opt_v;
270     check_file($tpath, undef, undef, get_translators_from_db($tpath));
271     }
272    
273 barbier 1.31 print "}; 1;\n" if $opt_t eq 'perl';
274    
275 french 1.13 send_mails();
276 peterk 1.21
277 french 1.41 if ($opt_M) {
278 joy 1.32 foreach my $makefile (split(/\n/, `find $from -name Makefile -print`)) {
279 peterk 1.21 my $destination = $makefile;
280     $destination =~ s/^$from/$to/o;
281     if (-e $destination) {
282 peterk 1.53 # First check if the destination makefile simply includes the english
283     # version
284     my $includes = 0;
285     if (open MK, "<$destination")
286     {
287     my $firstline = <MK>;
288     close MK;
289     $includes = 1 if $firstline =~ m'^include.*subst webwml/.*,webwml/english,.*CURDIR.*Makefile';
290     }
291     else
292     {
293     warn "Cannot read $from: $!\n";
294     }
295     unless ($includes)
296     {
297     # Otherwise show any differences
298     STDOUT->flush;
299     system("diff -u $destination $makefile");
300     STDOUT->flush;
301     }
302 peterk 1.21 }
303     }
304     }
305 french 1.13
306     sub verify_send {
307 joy 1.15 return 1 unless ($opt_m);
308 french 1.13 # returns true whether we have to send this part to this guy
309     my $name=shift;
310     my $part=shift;
311     $name =~ s,<.*?>,,;
312     $name =~ s,^ *(.*?) *$,$1,;
313     print "$name is unknown\n" unless defined($translators{$name});
314     # print "pri=$opt_n ; maint_pri=${translators{$name}{$part}}\n";
315     return $opt_m # if we have to send any mail
316     && defined($translators{$name}) # if this guy is known
317     && defined($translators{$name}{$part}) # we know something about the wanted frequency
318     && ($opt_n <= $translators{$name}{$part}); # check if the frequency is ok
319     }
320    
321     sub get_translators_from_db {
322     my $id=shift;
323     my $res='';
324    
325     $id=~ s,^$langto/,,;
326     $id=~ s/\.wml$//;
327     if (defined(%{$$translations_status{$id}})
328     && defined ($$translations_status{$id}{'translation_maintainer'})) {
329     foreach my $n (sort @{$$translations_status{$id}{'translation_maintainer'}}) {
330     $res .= " $n";
331     }
332     } else {
333     $res = "";
334     }
335     return $res;
336     }
337    
338     sub init_mails {
339     return unless $opt_m;
340 joy 1.16 eval q{use MIME::Lite};
341 french 1.13 foreach my $name (keys %translators) {
342     return if defined $translators{$name}{"msg"};
343 barbier 1.46 next if $name eq 'default' || $translators{$name}{email} eq '';
344 french 1.13 $translators{$name}{"msg"} = MIME::Lite->new(
345     From => "Script watching translation state <$maintainer>",
346     To => ($opt_g ? $opt_m : $translators{$name}{"email"}),
347 barbier 1.46 Subject => $translators{$name}{mailsubject},
348 french 1.13 Type => 'multipart/mixed');
349 barbier 1.46 my $str;
350     {
351     open (MAIL, "< $translators{$name}{mailbody}")
352     or die "$name: Unable to read \`$translators{$name}{mailbody}'";
353     local $/ = undef;
354     $str= <MAIL>;
355     close (MAIL);
356     }
357     1 while ($str =~ s/#(.*?)#/eval $1/ge);
358 french 1.13
359 barbier 1.48 my $part = MIME::Lite->new(
360 french 1.13 Type => 'TEXT',
361     Data => $str);
362 barbier 1.48 $part->attr('content-type.charset' => $opt_c) if $opt_c;
363     $translators{$name}{"msg"}->attach($part);
364 french 1.13 $translators{$name}{"send"}=0;
365     }
366     }
367    
368     sub send_mails {
369     #Makes the mails and send them
370     return unless $opt_m;
371     foreach my $name (sort keys %translators) {
372 barbier 1.46 next if $name eq 'default' || $translators{$name}{email} eq '';
373 french 1.13 $translators{$name}{"msg"}->attach(
374     Type => 'TEXT',
375     Filename => 'NeedToUpdate_summary',
376     Data => $translators{$name}{"part_summary"})
377     if defined($translators{$name}{"part_summary"});
378     $translators{$name}{"msg"}->attach(
379     Type => 'TEXT',
380     Filename => 'Missing_summary',
381     Data => $translators{$name}{"part_missing"})
382     if defined($translators{$name}{"part_missing"});
383 peterk 1.50 foreach my $part (qw (file logs diff tdiff)) {
384 french 1.13 if (defined($translators{$name}{"part_$part"})) {
385     foreach my $file (sort keys %{$translators{$name}{"part_$part"}}) {
386     $translators{$name}{"msg"}->attach(
387     Type => 'TEXT',
388     Filename => "$file.$part",
389     Data => $translators{$name}{"part_$part"}{$file});
390     }
391     }
392 italian 1.1 }
393 french 1.13 if ($translators{$name}{"send"}) {
394 barbier 1.47 print "send mail to $name\n" unless $opt_Q;
395 french 1.13 if (($name =~ m,mquinson,) || ($opt_g && $opt_m eq $maintainer)) {
396 barbier 1.47 print "Well, detourned to $maintainer\n" unless $opt_Q;
397 french 1.13 $translators{$name}{"msg"}->send;
398     }
399     # $translators{$name}{"msg"}->print_header;
400     $translators{$name}{"msg"}->send;
401     } else {
402 barbier 1.47 print "didn't send mail to $name: nothing to say to him\n" unless $opt_Q;
403 peterk 1.50 }
404 french 1.41 }
405 italian 1.1 }
406    
407 french 1.13 sub add_part {
408     my $name = shift;
409     my $part = shift;
410 peterk 1.50 my $txt = shift;
411 french 1.13 $name =~ s,<.*?>,,;
412     $name =~ s,^ *(.*?) *$,$1,;
413     if (verify_send($name,$part)) {
414     $translators{$name}{"part_$part"}.=$txt;
415     $translators{$name}{"send"}=1;
416     }
417     }
418 joy 1.28
419 french 1.13 sub add_sub_part {
420     my $name = shift;
421     my $part = shift;
422     my $subpart=shift;
423 french 1.41 my $txt = shift;
424 french 1.13 $name =~ s,<.*?>,,;
425     $name =~ s,^ *(.*?) *$,$1,;
426 french 1.42 # print "add_sub_part($name)(part=$part)($subpart):$txt" if $opt_v;
427 french 1.41 STDOUT->flush;
428 french 1.13 if (verify_send($name,$part)) {
429     # print "YES\n";
430 french 1.41 $translators{$name}{"part_$part"}{$subpart}.= "$txt";
431 french 1.13 $translators{$name}{"send"}=1;
432     }
433     # print "no\n";
434     }
435    
436 french 1.41 sub get_diff_txt {
437     my ($oldr, $revision, $oldname, $name) = @_;
438     my $cmd;
439    
440     # Get old revision file
441 french 1.42 $cmd = "cvs -z3 update -r $oldr -p $oldname 2>/dev/null";
442 french 1.41 # print "!get_diff_txt: cvs -z3 update -r ".$oldr." -p ".$oldname."\n";
443     my @old_rev_file_lines = qx($cmd);
444    
445     # Get translation file
446     open (FILE,"$name") || die ("Can't open `$name' for read");
447     my @translation_file_lines;
448     while (<FILE>) {
449     $translation_file_lines[scalar @translation_file_lines] = $_;
450     }
451     close FILE || die ("Can't close $name after reading");
452    
453     # Get diff lines
454 french 1.42 $cmd = "cvs -z3 diff -u -r$oldr -r $revision $oldname 2>/dev/null";
455     # print "get_diff_txt: $cmd: cvs -z3 diff -u -r$oldr -r $revision $oldname\n";
456 french 1.41 my @diff_lines = qx($cmd);
457    
458     my $txt = Local::WmlDiffTrans::find_trans_parts(\@old_rev_file_lines,
459     \@translation_file_lines,
460     \@diff_lines);
461    
462     return $txt;
463     }
464 french 1.13
465 italian 1.1 sub check_file {
466 barbier 1.31 my ($name, $revision, $mtime, $translator) = @_;
467 barbier 1.54 $revision ||= 'n/a';
468 peterk 1.51 my ($oldr, $oldname, $original, $fromname);
469 joy 1.28 warn "Checking $name, English revision $revision\n" if $opt_v;
470 barbier 1.31 my $docname = $name;
471     $docname =~ s#^$langto/##;
472     $docname =~ s#\.wml$##;
473 italian 1.1 unless (-r $name) {
474 peterk 1.52 (my $iname = $name) =~ s/^$to//o;
475 barbier 1.40 if (!$globtrans->is_global($iname)) {
476 joy 1.28 unless (($opt_q) || ($opt_Q)) {
477 barbier 1.31 if ($opt_t eq 'perl') {
478     print "'$docname' => {\n\t'type' => 'Web',\n";
479     print "\t'revision' => '$revision',\n";
480 barbier 1.54 print "\t'mtime' => '$mtime',\n" if $mtime;
481 barbier 1.31 print "\t'status' => 1,\n";
482     print "},\n";
483     } else {
484     print "Missing $name version $revision\n";
485     }
486 barbier 1.46 add_part("untranslated","missing","Missing $name version $revision\n");
487 joy 1.22 }
488 joy 1.28 } else {
489     warn "Ignored $name\n" if $opt_v;
490 french 1.13 }
491 italian 1.1 return;
492     }
493 barbier 1.36 my $transcheck = Webwml::TransCheck->new($name);
494 barbier 1.38 $oldr = $transcheck->revision() || 0;
495     if (!$oldr && ($name =~ m#$langto/international/$langto#i)) {
496     # This document is original, check for
497     # english/international/$langto...
498     $name =~ s{^$to}{$from};
499     $transcheck = Webwml::TransCheck->new($name);
500     $oldr = $transcheck->revision() || 0;
501     }
502 barbier 1.36 $translator = $transcheck->maintainer() || "";
503     $original = $transcheck->original();
504     warn "Found translation for $oldr\n" if $opt_v and $oldr;
505     warn "Translated by $translator\n" if $opt_v and $translator;
506     warn "Original is $original\n" if $opt_v and $original;
507     if ($original) {
508 peterk 1.51 my ($fromdir);
509 barbier 1.36 $fromname = $name;
510     $fromname =~ s{^[^/]+}{$original};
511     $fromdir = $fromname;
512     $fromdir =~ s{/+[^/]+$}{};
513     $altcvs->reset();
514     $altcvs->readinfo($fromdir, matchfile => [$fromname]);
515     $revision = $altcvs->revision($fromname);
516     warn "Original is $original, revision $revision\n" if $opt_v;
517 joy 1.24 }
518    
519 barbier 1.36 $translator =~ s/^\s+//;
520     $translator =~ s/\s+$//;
521 french 1.13
522 joy 1.18 my $str;
523 peterk 1.49 my $status = 8; # Unknown
524     (my $numrev) = $revision =~ m/^1\.(\d+)$/; $numrev ||= "0";
525     (my $numoldr) = $oldr =~ m/^1\.(\d+)$/; $numoldr ||= "0";
526    
527     if ($revision ne 'n/a')
528     {
529     # The original version of this file exists (English or otherwise)
530     # - compare the translated version number to the original
531     if (!$oldr) {
532 peterk 1.57 if ($name =~ /^english/)
533     {
534     # This is the original file
535     $status = 4; # Up-to-date
536     $oldr = $revision;
537     }
538     else
539     {
540     $oldr = '1.0';
541     $str = "Unknown status of $name (revision should be $revision)";
542     }
543 peterk 1.49 } elsif ($oldr eq $revision) {
544     $status = 4; # Up-to-date
545     } elsif ($numoldr > $numrev) {
546     $str = "Broken revision number $oldr for $name, it should be $revision";
547     } else {
548     $str = "NeedToUpdate $name from version $oldr to version $revision";
549     $status = 3; # Needs update
550     }
551     }
552     else
553     {
554     # There is no English file matching this one.
555     if ($oldr eq '0')
556     {
557     # There is no translation-check header, so it must be the
558     # original version, and is thus always up-to-date.
559     $status = 4; # Up-to-date
560     }
561     else
562     {
563     # There is a translation-check header referencing an English
564     # version, which means that the English file has been removed.
565     $status = 7; # Obsolete
566     $str = "Obsolete $name";
567     }
568     }
569    
570 french 1.13 $str .= " (maintainer: $translator)" if $translator;
571 barbier 1.31 if ($opt_t eq 'perl') {
572     print "'$docname' => {\n\t'type' => 'Web',\n";
573     print "\t'revision' => '$revision',\n";
574 barbier 1.54 print "\t'mtime' => '$mtime',\n" if $mtime;
575 barbier 1.31 print "\t'base_revision' => '$oldr',\n";
576     print "\t'translation_maintainer' => ['$translator'],\n" if $translator;
577     print "\t'status' => $status,\n";
578     print "},\n";
579     } elsif ($str && $oldr ne $revision) {
580 joy 1.23 $str .= "\n";
581     print $str unless ($opt_Q);
582     }
583    
584 peterk 1.50 # Return if we're up-to-date or the original is missing
585     return if (defined($oldr) && ($oldr eq $revision || $revision eq 'n/a'));
586 barbier 1.31
587 peterk 1.51 if ($original)
588     {
589     # Source is non-English, use name we set up above
590     $oldname = $fromname;
591     }
592     else
593     {
594     # Source is English
595     $oldname = $name;
596     $oldname =~ s/^$to/$from/;
597     }
598 peterk 1.17
599     my @logrev = split(/\./, $oldr);
600     $logrev[$#logrev] ++;
601     my $logoldr = join('.', @logrev);
602 barbier 1.46 my $maxdelta = $transcheck->maxdelta() || $translators{maxdelta}{maxdelta} || 5;
603 peterk 1.17
604 french 1.13 if ($opt_m) {
605 barbier 1.46 my @list_tr;
606     if ($translator eq "") {
607     if ($numrev - $numoldr >= $maxdelta) {
608     @list_tr = ("maxdelta");
609     } else {
610     @list_tr = ("unmaintained");
611     }
612     } elsif ($numrev - $numoldr >= $maxdelta) {
613     @list_tr = ($translator, "maxdelta");
614     } else {
615     @list_tr = ($translator);
616     }
617     foreach my $tname (@list_tr) {
618     add_part($tname,"summary",$str);
619     add_sub_part($tname,"diff",$name,
620     join("",qx(cvs -z3 diff -u -r'$oldr' -r $revision $oldname)));
621     add_sub_part($tname,"tdiff",$name,
622     get_diff_txt("$oldr","$revision","$oldname","$name"));
623    
624     add_sub_part($tname,"logs",$name,
625     join("",qx(cvs -z3 log -r$logoldr:$revision $oldname)));
626     add_sub_part($tname,"file",$name,
627     join("",qx(cat $name)));
628     }
629 french 1.13 }
630 peterk 1.50
631 italian 1.1 if ($opt_d) {
632 swedish 1.2 STDOUT->flush;
633 barbier 1.31 my $cvsline = "cvs -z3 log -r'$logoldr:$revision' '$oldname'";
634 joy 1.32 warn "Running $cvsline\n" if (($opt_v) && ($opt_l));
635     system($cvsline) if $opt_l;
636     STDOUT->flush if $opt_l;
637 joy 1.25 $cvsline = "cvs -z3 diff -u -r '$oldr' -r '$revision' '$oldname'";
638     warn "Running $cvsline\n" if $opt_v;
639     system($cvsline);
640 swedish 1.2 STDOUT->flush;
641 peterk 1.50 }
642 peterk 1.57
643     if (3 == $status && $opt_a) {
644     # Check the age of this translation
645     STDOUT->flush;
646     my $cvsline = "cvs -z3 log -r'$logoldr' '$oldname'";
647     if (open CVSLOG, '-|', $cvsline)
648     {
649     CVSDATA: while (<CVSLOG>)
650     {
651     last CVSDATA if /^date:/;
652     }
653     close CVSLOG;
654     if (/^date: ([\d]{4}.[\d]{2}.[\d]{2})/)
655     {
656     # Got the date of the last translation
657     my $agestring = &DateCalc($1, 'today', 1, 1);
658     die "CVS date is in the future" if $agestring =~ /^\-/;
659     my ($years, $months, $weeks, $undef) = split /:/, substr($agestring, 1), 4;
660     my ($yearstring, $monthstring, $weekstring) = ('', '', '');
661     if ($years)
662     {
663     $yearstring = "$years year";
664     $yearstring .= 's' unless 1 == $years;
665     }
666     if ($months)
667     {
668     $monthstring = "$months month";
669     $monthstring .= 's' unless 1 == $months;
670     }
671     if ($weeks)
672     {
673     $weekstring = "$weeks week";
674     $weekstring .= 's' unless 1 == $weeks;
675     }
676    
677     if ($weeks > 2 || $months || $years)
678     {
679     $monthstring .= ', '
680     if $monthstring ne '' && $weekstring ne '';
681     $yearstring .= ', '
682     if $yearstring ne '' && ($monthstring ne '' || $weekstring ne '');
683     print "$name is outdated by $yearstring$monthstring$weekstring\n";
684     }
685     }
686     }
687     STDOUT->flush;
688     }
689 french 1.41
690 french 1.42 if ($opt_T) {
691 french 1.41 print get_diff_txt("$oldr", "$revision", "$oldname", "$name")."\n";
692     }
693 italian 1.1 }

  ViewVC Help
Powered by ViewVC 1.1.5