#! /usr/bin/perl # This script is still used in 2024 # webwml-stattrans - Debian web site translation statistics # Copyright (c) 2001 Martin Schulze and others # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. use POSIX qw(strftime); use Getopt::Std; # These modules reside under webwml/Perl use lib ($0 =~ m|(.*)/|, $1 or ".") ."/Perl"; use Local::VCS ':all'; use Webwml::Langs; use Webwml::TransCheck; use Webwml::TransIgnore; use Debian::L10n::Db ('%LanguageList'); use Net::Domain qw(hostfqdn); use Data::Dumper; use JSON; $| = 1; $opt_h = "/srv/www.debian.org/webwml/english/devel/website/stats"; $opt_w = "/srv/www.debian.org/webwml"; $opt_p = "*.(wml|src)"; $opt_t = ''; $opt_v = 0; $opt_d = "u"; $opt_l = undef; $opt_b = ""; # Base URL, if not debian.org # Should we try to repair any broken translation hash references? $opt_r = 0; # path of web stats JSON data $opt_f = "/srv/www.debian.org/webwml/stats.json"; getopts('h:w:b:p:t:vd:l:f:r') || die; # Replace filename globbing by Perl regexps $opt_p =~ s/\./\\./g; $opt_p =~ s/\?/./g; $opt_p =~ s/\*/.*/g; $opt_p =~ s/$/\$/g; %config = ( 'htmldir' => $opt_h, 'wmldir' => $opt_w, 'wmlpat' => $opt_p, 'title' => $opt_t, 'verbose' => $opt_v, 'difftype'=> $opt_d, 'hit_file'=> $opt_f, 'repair' => $opt_r, ); my $VCSHOST = "salsa"; my $VCSBASE = "https://salsa.debian.org/webmaster-team/webwml"; my $l = Webwml::Langs->new($opt_w); my %langs = $l->name_iso(); my $VCS = Local::VCS->new(); if ($config{verbose}) { print "Caching VCS for performance...\n"; } $VCS->cache_repo(); if ($config{verbose}) { print " ...done\n"; } my $transignore = Webwml::TransIgnore->new($opt_w); chdir($config{'wmldir'}) or die "Can't chdir to $config{'wmldir'}: $!\n"; my %rev_info = $VCS->path_info("english", 'recursive' => 1, 'match_pat' => $config{'wmlpat'}, 'skip_pat' => "(template|/devel/website/stats/)"); my $cnt = scalar(keys %rev_info); foreach (@{$transignore->global()}) { delete $rev_info{"english/$_"}; } $max_versions_default = 5; $min_versions_default = 1; $date = strftime "%a %b %e %H:%M:%S %Y %z", localtime; my %original; my %transversion; my %version; my %files; my %sizes; my %min_versions; my %max_versions; print "Loading the coordination status databases\n" if ($config{verbose}); my %status_db = (); opendir (DATADIR, "english/international/l10n/data") or die "Cannot open directory english/international/l10n/data: $!\n"; foreach (readdir (DATADIR)) { # Only check the status files next unless ($_ =~ m/^status\.(.*)$/); my $l = $1; next if (!defined $LanguageList{uc $l}); if (-r "english/international/l10n/data/status.$l") { $status_db{$LanguageList{uc $l}} = Debian::L10n::Db->new(); $status_db{$LanguageList{uc $l}}->read("english/international/l10n/data/status.$l", 0); } } closedir (DATADIR); sub linklist { my ($file, $lang) = @_; my $add = ""; if ($status_db{$lang}->has_package('www.debian.org') and $status_db{$lang}->has_status('www.debian.org')) { foreach my $statusline (@{$status_db{$lang}->status('www.debian.org')}) { my ($type, $statfile, $date, $status, $translator, $list, $url, $bug_nb) = @{$statusline}; if ($file eq $statfile) { $date =~ s/\s*\+0000$//; $list =~ /^(\d\d\d\d)-(\d\d)-(\d\d\d\d\d)$/; $add = "$status"; $add = "$add$translator$date"; } } } $add = '' if (!length $add); return $add; } # Count wml files in given directory # sub getwmlfiles { my $lang = shift; my $dir = "$lang"; # my $cutfrom = length ($config{'wmldir'})+length($lang)+2; my $count = 0; my $size = 0; my $is_english = ($lang eq "english")?1:0; my ( $file, $v ); my @listfiles; my %altrev_info; if (! -d "$dir") { print "$0: can't find $dir! Skipping ...\n"; return; } if ($is_english) { @listfiles = sort keys(%rev_info); } else { %altrev_info = $VCS->path_info($dir, 'recursive' => 1, 'match_pat' => $config{'wmlpat'}, 'skip_pat' => "template"); @listfiles = sort keys(%altrev_info); } # print "cutfrom is $cutfrom\n"; # print "Looking at @listfiles\n"; # open (LIST, ">$config{'htmldir'}/$lang.list") # || die "Can't open $config{'htmldir'}/$lang.list"; foreach my $file (@listfiles) { # print LIST "$file\n"; # $file = substr ($f, $cutfrom); # print "looking at $file\n"; next if $transignore->is_global($file); $files{$file} = 1; $wmlfiles{$lang} .= " " . $file; my $transcheck = Webwml::TransCheck->new("$dir/$file"); if ($transcheck->revision()) { $transversion{"$lang/$file"} = $transcheck->revision(); $original{"$lang/$file"} ||= $transcheck->original(); $min_versions{"$lang/$file"} = $transcheck->mindelta() || $min_versions_default; $max_versions{"$lang/$file"} = $transcheck->maxdelta() || $max_versions_default; } if ($is_english) { $version{"$lang/$file"} = $rev_info{"$file"}{'cmt_rev'}; } else { $version{"$lang/$file"} = $altrev_info{"$file"}{'cmt_rev'}; if (!$transcheck->revision()) { $transcheckenglish = Webwml::TransCheck->new("english/$file"); if (!$transcheckenglish->revision() and (-e "english/$file")) { $transversion{"$lang/$file"} = $VCS->get_oldest_revision("english/$file"); $original{"$lang/$file"} = "english"; } else { $original{"english/$file"} = $lang; $transversion{"english/$file"} = $VCS->get_oldest_revision("$lang/$file"); } } } if ($transcheck->maintainer()) { # Escape HTML special characters to make the resulting page valid. # This is needed for maintainers who use their e-mail address # within angle brackets. my %_escape_table = ( '&' => '&', '>' => '>', '<' => '<', q{"} => '"', q{'} => ''', q{`} => '`', '{' => '{', '}' => '}' ); $maintainer{"$lang/$file"} = $transcheck->maintainer(); $maintainer{"$lang/$file"} =~ s/([&><"'`{}])/$_escape_table{$1}/ge; } $count++; $sizes{$file} = (stat "".($original{"english/$file"}||"english")."/".$file)[7]; $size += $sizes{$file}; } # close LIST; $wmlfiles{$lang} .= " "; $wml{$lang} = $count; $wml_s{$lang} = $size; if ($config{verbose}) { print " $lang: $count wml files, $size bytes\n"; } } sub get_color { my $percent = shift; if ($percent < 50) { return sprintf ("#FF%02x00", (255/50) * $percent); } else { return sprintf ("#%02xFF00", (255/50) * (100 - $percent)); } } # Update the translation-check metadata header in a wml file sub update_file_metadata { my $file = shift; my $revision = shift; my $hash = shift; my $text = ""; open (IN, "< $file") or die "Can't open $file for reading: $!\n"; while () { if (m/^#use wml::debian::translation-check/) { s/(translation="?)($revision)("?)/$1$hash$3/; } $text .= $_; } close(IN); open(OUT, "> $file") or die "Can't open $file for writing: $!\n"; print OUT $text; close OUT; } sub check_translation { my ($translation, $version, $file, $orig_file, $min_versions, $max_versions) = @_; my ( @version_numbers, $major_number, $last_number ); # print " check_translation: looking at translation $translation, english version $version, file $file, orig_file $orig_file\n"; if ( $version && $translation ) { # Here we compare the original version with the translated one and print # a note for the user if their first or last numbers are too far apart # From translation-check.wml my $version_diff = $VCS->count_changes($orig_file, $translation, $version); if (!defined $version_diff) { print "check_translation: error from count_changes() for orig_file $orig_file, file $file\n"; if ($config{'repair'}) { # Replace the translation reference with the most # recent version of the original? Yes, they're all # either really old or files with only one commit... my $latest_rev_orig = $VCS->get_newest_revision($orig_file); print " fixing: using rev $latest_rev_orig instead of $translation\n"; update_file_metadata($file, $translation, $latest_rev_orig); } } else { if ($version_diff < 0) { return 'Wrong translation version'; } elsif ( $version_diff >= $max_versions ) { return 'This translation is too out of date'; } elsif ( $version_diff >= $min_versions ) { return 'The original is newer than this translation'; } } } elsif ( !$version && $translation) { return 'The original no longer exists'; } return ""; } print "Collecting data:\n" if ($config{'verbose'}); if ($opt_l) { getwmlfiles ($opt_l); getwmlfiles ('english'); } else { foreach $lang (sort keys %langs) { getwmlfiles ($lang); } } print "\n" if ($config{'verbose'}); my @search_in; if ($opt_l) { @search_in = ( 'english', $opt_l ); } else { @search_in = sort keys %langs; } # Compute stats about gettext files print "Computing statistics in gettext files... " if ($config{'verbose'}); my ( %po_translated, %po_fuzzy, %po_untranslated, %po_total ); my ( %percent_po_t, %percent_po_u, %percent_po_f ); foreach $lang (@search_in) { next if $lang eq 'english'; $po_translated{"total"}{$lang} = $po_fuzzy{"total"}{$lang} = $po_untranslated{"total"}{$lang} = 0; $percent_po_t{'total'}{$lang} = 0; $percent_po_f{'total'}{$lang} = 0; $percent_po_u{'total'}{$lang} = 100; if (! -d "$lang/po") { print "$0: can't find $lang/po! Skipping ...\n"; next; } my @status = qx,LC_ALL=C make -C $lang/po stats 2>&1,; foreach $line (@status) { chomp $line; next if($line =~ /make: (Enter|Leav)ing directory/); ($domain = $line) =~ s/\..*//; $po_translated{$domain}{$lang} = ($line =~ /(\d+) translated/ ? $1 : "0"); $po_fuzzy{$domain}{$lang} = ($line =~ /(\d+) fuzzy/ ? $1 : "0"); $po_untranslated{$domain}{$lang} = ($line =~ /(\d+) untranslated/ ? $1 : "0"); $po_total{$domain} = $po_translated{$domain}{$lang} + $po_fuzzy{$domain}{$lang} + $po_untranslated{$domain}{$lang}; $po_translated{"total"}{$lang} += $po_translated{$domain}{$lang}; $po_fuzzy{"total"}{$lang} += $po_fuzzy{$domain}{$lang}; $po_untranslated{"total"}{$lang} += $po_untranslated{$domain}{$lang}; if ($po_total{$domain} > 0) { $percent_po_t{$domain}{$lang} = int ($po_translated{$domain}{$lang}/$po_total{$domain} * 100 + .5); $percent_po_f{$domain}{$lang} = int ($po_fuzzy{$domain}{$lang}/$po_total{$domain} * 100 + .5); $percent_po_u{$domain}{$lang} = int ($po_untranslated{$domain}{$lang}/$po_total{$domain} * 100 + .5); } else { $percent_po_t{$domain}{$lang} = 0; $percent_po_f{$domain}{$lang} = 0; $percent_po_u{$domain}{$lang} = 0; # or 100 if po/ doesn't exist } } $po_total{"total"} = $po_translated{"total"}{$lang} + $po_fuzzy{"total"}{$lang} + $po_untranslated{"total"}{$lang}; if ($po_total{'total'} > 0) { $percent_po_t{'total'}{$lang} = int ($po_translated{'total'}{$lang}/$po_total{'total'} * 100 + .5); $percent_po_f{'total'}{$lang} = int ($po_fuzzy{'total'}{$lang}/$po_total{'total'} * 100 + .5); $percent_po_u{'total'}{$lang} = int ($po_untranslated{'total'}{$lang}/$po_total{'total'} * 100 + .5); } } print "done.\n" if ($config{'verbose'}); # =============== Create HTML files =============== mkdir ($config{'htmldir'}, 02775) if (! -d $config{'htmldir'}); # Read website hit statistics, if available my %hits; my $file_sorter = sub($$) { $_[0] cmp $_[1] }; if ($config{'hit_file'}) { printf("Retrieving hit data from [%s].\n", $config{'hit_file'}) if ($config{'verbose'}); open( my $fh, '<', $config{'hit_file'} ); local $/; my $json = <$fh>; close $fh; if ($json) { my $perl = JSON::from_json($json, {utf8 => 1}); foreach my $e (@{$perl}) { my ($count, $url) = @$e; last if $count < 3; # URLS with 2 or 1 hits are most likely mistakes; let's not waste RAM on them $hits{substr($url, 1)} = $count; } } if (%hits) { $file_sorter = sub($$) { my ($a, $b) = @_; $a =~ s/\.wml$//o; $b =~ s/\.wml$//o; $hits{$b} <=> $hits{$a} }; } else { print "Tables will be sorted alphabetically.\n" if ($config{'verbose'}); } } else { print "No hit file specified. Tables will be sorted alphabetically.\n" if ($config{'verbose'}); } my @filenames = sort $file_sorter keys %files; my $nfiles = scalar @filenames; $nsize += $sizes{$_} foreach (@filenames); # 'u' == 'unidiff', 'h' == 'colored diff' my $firstdifftype; my $seconddifftype; if ($config{'difftype'} eq 'u') { $firstdifftype = 'u'; $seconddifftype = 'h'; } else { $firstdifftype = 'h'; $seconddifftype = 'u'; } sub vcs_log_url { my ($path, $rev) = @_; if ($VCSHOST =~ m/salsa/) { return "$VCSBASE/commits/$rev/$path"; } else { die "Unknown/unsupported VCSHOST $VCSHOST - ABORT\n"; } } sub vcs_diff_url { my ( $path, $r1, $r2, $diff_format ) = @_; if ($VCSHOST =~ m/salsa/) { return "$VCSBASE/compare?from=$r1&to=$r2"; } else { die "Unknown/unsupported VCSHOST $VCSHOST - ABORT\n"; } } sub vcs_view_url { my ($path) = @_; if ($VCSHOST =~ m/salsa/) { return "$VCSBASE/blob/master/$path"; } else { die "Unknown/unsupported VCSHOST $VCSHOST - ABORT\n"; } } sub vcs_raw_url { my ($path) = @_; if ($VCSHOST =~ m/salsa/) { return "$VCSBASE/raw/master/$path"; } else { die "Unknown/unsupported VCSHOST $VCSHOST - ABORT\n"; } } # Return a shortened version string to make things less unwieldy sub short { my $in = shift; if ($VCSHOST =~ m/salsa/) { return substr $in, 0, 12; # 12 is a common length people use for git } else { return $in; } } print "Creating files: " if ($config{'verbose'}); foreach $lang (@search_in) { my @processed_langs = ($langs{$lang}); @processed_langs = ("zh-cn", "zh-tw") if $langs{$lang} eq "zh"; foreach $l (sort @processed_langs) { print "$l.wml " if ($config{'verbose'}); $t_body = $u_body = $ui_body = $un_body = $uu_body = $o_body = ""; $translated{$lang} = $outdated{$lang} = $untranslated{$lang} = 0; # get stats about files foreach $file (@filenames) { next if ($file eq ""); (my $base = $file) =~ s/\.wml$//; my $hits = exists $hits{$base} ? $hits{$base}.' hits' : 'hit count N/A'; my $todo = ''; $todo = linklist($file, $lang) if defined $status_db{$lang}; # Translated pages or already WIP in translation list if ((index ($wmlfiles{$lang}, " $file ") >= 0) or (($todo ne '') and ($transversion{"$lang/$file"} ne $version{"$orig/$file"}))) { $translated{$lang}++; $translated_s{$lang} += $sizes{$file}; $orig = $original{"$lang/$file"} || "english"; # Outdated translations $msg = check_translation ($transversion{"$lang/$file"}, $version{"$orig/$file"}, "$lang/$file", "$orig/$file", $min_versions{"$lang/$file"}, $max_versions{"$lang/$file"}); if (length ($msg) or (($todo ne '') and ($transversion{"$lang/$file"} ne $version{"$orig/$file"}))) { $o_body .= ""; if (($file !~ /\.wml$/) || ($file eq "devel/wnpp/wnpp.wml")) { $o_body .= sprintf "%s", $file; } else { $o_body .= sprintf "%s", $hits, $base, $base; } if (!defined $status_db{$lang}) { $o_body .= sprintf "%s", $msg; } if ($msg eq 'Wrong translation version' || $msg eq 'The original no longer exists') { if (defined $status_db{$lang}) { $o_body .= sprintf "%d (%.2f ‰)", $sizes{$file}, $sizes{$file}/$nsize * 1000; } else { $o_body .= ""; } } else { if (defined $status_db{$lang}) { if ($transversion{"$lang/$file"} ne ''){ $o_body .= sprintf "git diff %s..%s -- %s", short($transversion{"$lang/$file"}), short($version{"$orig/$file"}), "$orig/$file"; } else { $o_body .= sprintf "%d (%.2f ‰)", $sizes{$file}, $sizes{$file}/$nsize * 1000; } } else { $o_body .= sprintf "git diff %s..%s -- %s", short($transversion{"$lang/$file"}), short($version{"$orig/$file"}), "$orig/$file"; } } $o_body .= sprintf "[L]", $msg, vcs_log_url("$orig/$file", $version{"$orig/$file"}); $o_body .= sprintf "[V]\ ", vcs_view_url("$lang/$file"); $o_body .= sprintf "[F]", vcs_raw_url("$lang/$file"); $o_body .= sprintf "%s", $maintainer{"$lang/$file"} || ""; $o_body .= $todo if (defined $status_db{$lang}); $o_body .= "\n"; $outdated{$lang}++; $outdated_s{$lang} += $sizes{$file}; # Up-to-date translations } else { if (($file !~ /\.wml$/) || ($file eq "devel/wnpp/wnpp.wml")) { $t_body .= sprintf "
  • %s
  • \n", $file; } else { $t_body .= sprintf "
  • %s
  • \n", $hits, $base, $l, $base; } } } # Untranslated pages else { my $u_tmp; if (($file !~ /\.wml$/) || ($file eq "devel/wnpp/wnpp.wml")) { $u_tmp = sprintf "%s \n", $file; } else { $u_tmp = sprintf "%s  (%s)%d(%.2f ‰)\n", $hits, $base, $base, $version{"$orig/$file"}, $sizes{$file}, $sizes{$file}/$nsize * 1000; } if (($file =~ /international\//) && ($file !~ /international\/index.wml$/) && ($file !~ /international\/l10n\//)) { $ui_body .=$u_tmp; } elsif (($file =~ /(News|events|security|vote)\/[0-9]{4}\//) || ($file =~ /(News\/weekly\/[0-9]{4}\/|security\/undated)/)) { $un_body .= $u_tmp; } elsif ($file =~ /(consultants|users\/(com|edu|gov|org))\//) { $uu_body .=$u_tmp; } else { $u_body .= $u_tmp; } $untranslated{$lang}++; $untranslated_s{$lang} += $sizes{$file}; } } # this is where we discard the files that the translation directory contains # but which don't exist in the English directory # print "extra files: ".$wml{$lang}-$translated{$lang}."\n"; $wml{$lang} = $translated{$lang}; $wml_s{$lang} = $translated_s{$lang}; $translated{$lang} = $translated{$lang} - $outdated{$lang}; $translated_s{$lang} = $translated_s{$lang} - $outdated_s{$lang}; if ($nfiles > 0) { $percent_a{$lang} = $wml{$lang}/$nfiles * 100; } else { $percent_a{$lang} = 0; } if ($nsize > 0) { $percent_as{$lang} = $wml_s{$lang}/$nsize * 100; } else { $percent_as{$lang} = 0; } if ($wml{$lang} > 0) { $percent_t{$lang} = $translated{$lang}/$wml{$lang} * 100; } else { $percent_t{$lang} = 0; } if ($wml_s{$lang} > 0) { $percent_ts{$lang} = $translated_s{$lang}/$wml_s{$lang} * 100; } else { $percent_ts{$lang} = 0; } $percent_o{$lang} = 100 - $percent_t{$lang}; $percent_os{$lang} = 100 - $percent_ts{$lang}; $percent_u{$lang} = 100 - $percent_a{$lang}; $percent_us{$lang} = 100 - $percent_as{$lang}; if (open (HTML, ">$config{'htmldir'}/$l.wml")) { printf HTML "#use wml::debian::template title=\"<:=\$trans{\$CUR_ISO_LANG}{%s}:>\"\n", $lang; print HTML "#use wml::debian::toc\n"; printf HTML qq|webwml-stattrans\n|, vcs_view_url('stattrans.pl'); print HTML "
    \n"; print HTML 'Created with '; print HTML "
    \n"; print HTML "\n\n"; $color = get_color ($percent_a{$lang}); printf HTML 'Translation summary for <:=$trans{$CUR_ISO_LANG}{'.$lang.'} :>" style="background-color: %s; width: 100%; font-weight: bold; margin: 0; text-align: center;">'."\n", $color; print HTML "\n"; print HTML ''."\n\n"; printf HTML '', $wml{$lang}, $percent_a{$lang}; printf HTML '', $translated{$lang}, $percent_t{$lang}; printf HTML '', $outdated{$lang}, $percent_o{$lang}; printf HTML '', $untranslated{$lang}, $percent_u{$lang}; print HTML "\n"; print HTML "\n"; printf HTML '', $wml_s{$lang}, $percent_as{$lang}; printf HTML '', $translated_s{$lang}, $percent_ts{$lang}; printf HTML '', $outdated_s{$lang}, $percent_os{$lang}; printf HTML '', $nsize-$wml_s{$lang}, $percent_us{$lang}; print HTML "\n"; print HTML "
    TranslatedUp to dateOutdatedNot translated
    %d files (%.1f%%)%d files (%.1f%%)%d files (%.1f%%)%d files (%.1f%%)
    %d bytes (%.1f%%)%d bytes (%.1f%%)%d bytes (%.1f%%)%d bytes (%.1f%%)
    \n"; # Make the table of content print HTML "\n"; if (%hits) { print HTML '

    Note: the lists of pages are sorted by popularity. Hover over the page name to see the number of hits.'; print HTML "

    \n"; } # outputs the content if ($o_body) { print HTML 'Outdated translations'."\n"; print HTML "\n"; print HTML ''."\n"; if (defined $status_db{$lang}) { print HTML ''; } else { print HTML ''."\n"; print HTML ''; } print HTML ''; print HTML ''; print HTML ''; if (defined $status_db{$lang}) { print HTML ''; print HTML ''; print HTML ''; } print HTML "\n"; print HTML $o_body; print HTML "
    FileDiffCommentGit command lineLogTranslationMaintainerStatusTranslatorDate
    \n"; } if ($u_body) { print HTML 'General pages not translated'."\n"; print HTML 'Untranslated general pages">'."\n"; print HTML $u_body; print HTML "
    \n"; } if ($un_body) { print HTML 'News items not translated (low priority)'."\n"; print HTML 'Untranslated news items">'."\n"; print HTML $un_body; print HTML "
    \n"; } if ($uu_body) { print HTML 'Consultant/user pages not translated (low priority)'."\n"; print HTML 'Untranslated consultant/user pages">'."\n"; print HTML $uu_body; print HTML "
    \n"; } if ($ui_body) { print HTML 'International pages not translated (very low priority)'."\n"; print HTML 'Untranslated international pages">'."\n"; print HTML $ui_body; print HTML "
    \n"; } if ($t_body) { print HTML 'Translated pages (up-to-date)'."\n"; print HTML "
      \n"; print HTML $t_body; print HTML "
    \n"; } # outputs the gettext stats if ($lang ne 'english') { print HTML 'Translated templates (PO files)'."\n"; print HTML 'PO Translation Statistics" width="100%">'."\n"; print HTML ''."\n"; print HTML ''."\n"; print HTML ''."\n"; print HTML ''."\n"; print HTML ''."\n"; foreach my $domain (sort keys %po_total) { next if $domain eq 'total'; print HTML ""; $color_t = get_color ($percent_po_t{$domain}{$lang}); $color_f = get_color (100 - $percent_po_f{$domain}{$lang}); $color_u = get_color (100 - $percent_po_u{$domain}{$lang}); print HTML ""; printf HTML "", $color_t, $po_translated{$domain}{$lang}, $percent_po_t{$domain}{$lang}; printf HTML "", $color_f, $po_fuzzy{$domain}{$lang}, $percent_po_f{$domain}{$lang}; printf HTML "", $color_u, $po_untranslated{$domain}{$lang}, $percent_po_u{$domain}{$lang}; printf HTML "", $po_total{$domain}; print HTML "\n"; } print HTML "\n"; print HTML ''; $color_t = get_color ($percent_po_t{'total'}{$lang}); $color_f = get_color (100 - $percent_po_f{'total'}{$lang}); $color_u = get_color (100 - $percent_po_u{'total'}{$lang}); printf HTML "", $color_t, $po_translated{'total'}{$lang}, $percent_po_t{'total'}{$lang}; printf HTML "", $color_f, $po_fuzzy{'total'}{$lang}, $percent_po_f{'total'}{$lang}; printf HTML "", $color_u, $po_untranslated{'total'}{$lang}, $percent_po_u{'total'}{$lang}; printf HTML "", $po_total{'total'}; print HTML "\n"; print HTML "
    FileUp to dateFuzzyUntranslatedTotal
    $domain.$langs{$lang}.po%d (%s%%)%d (%s%%)%d (%s%%)%d
         
    Total:%d (%d%%)%d (%d%%)%d (%d%%)%d
    \n"; } print HTML "\n"; close (HTML); } else { print "Can't open $config{'htmldir'}/$l.wml\n"; } } } print "\n" if ($config{'verbose'}); # =============== Creating index.html =============== print "Creating index.wml... " if ($config{'verbose'}); open (HTMLI, ">$config{'htmldir'}/index.wml") || die "Can't open $config{'htmldir'}/index.wml"; print HTMLI "#use wml::debian::stats_tags\n"; printf HTMLI "#use wml::debian::template title=\"%s\"\n\n", $config{'title'}; printf HTMLI qq|webwml-stattrans\n|, vcs_view_url('stattrans.pl'); print HTMLI "
    \n"; print HTMLI 'Created with '; print HTMLI "
    \n"; print HTMLI '

    Translated web pages

    '."\n"; printf HTMLI "

    \n",($wml{'english'}+$untranslated{'english'}); print HTMLI 'Translation Statistics by Page Count" class="stattrans">'."\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI ""; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI ""; print HTMLI ""; print HTMLI ''."\n"; print HTMLI ''."\n"; print HTMLI ''."\n"; print HTMLI ''."\n"; print HTMLI ''."\n"; print HTMLI ""; print HTMLI ""; foreach $lang (@search_in) { my @processed_langs = ($langs{$lang}); @processed_langs = ("zh-cn", "zh-tw") if $langs{$lang} eq "zh"; foreach $l (@processed_langs) { $color_a = get_color ($percent_a{$lang}); $color_t = get_color ($percent_t{$lang}); $color_o = get_color (100 - $percent_o{$lang}); $color_u = get_color (100 - $percent_u{$lang}); print HTMLI ""; printf HTMLI "", $l, $lang, $l; printf HTMLI "", $color_a, $wml{$lang}, $percent_a{$lang}; printf HTMLI "", $color_t, $translated{$lang}, $percent_t{$lang}; printf HTMLI "", $color_o, $outdated{$lang}, $percent_o{$lang}; printf HTMLI "", $color_u, $untranslated{$lang}, $percent_u{$lang}; print HTMLI "\n"; } } print HTMLI ""; print HTMLI "
    LanguageTranslationsUp to dateOutdatedNot translated
    <:=\$trans{\$CUR_ISO_LANG}{%s} :> (%s)%d(%.1f%%)%d(%.1f%%)%d(%.1f%%)%d(%.1f%%)
    \n"; print HTMLI '

    Translated web pages (by size)

    '."\n"; printf HTMLI "

    \n",($wml_s{'english'}+$untranslated_s{'english'}); print HTMLI 'Translation Statistics by Page Size" class="stattrans">'."\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI ""; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI ""; print HTMLI ""; print HTMLI ''."\n"; print HTMLI ''."\n"; print HTMLI ''."\n"; print HTMLI ''."\n"; print HTMLI ''."\n"; print HTMLI ""; print HTMLI ""; foreach $lang (@search_in) { my @processed_langs = ($langs{$lang}); @processed_langs = ("zh-cn", "zh-tw") if $langs{$lang} eq "zh"; foreach $l (@processed_langs) { $color_a = get_color ($percent_a{$lang}); $color_t = get_color ($percent_t{$lang}); $color_o = get_color (100 - $percent_o{$lang}); $color_u = get_color (100 - $percent_u{$lang}); print HTMLI ""; printf HTMLI "", $l, $lang, $l; printf HTMLI "", $color_a, $wml_s{$lang}, $percent_as{$lang}; printf HTMLI "", $color_t, $translated_s{$lang}, $percent_ts{$lang}; printf HTMLI "", $color_o, $outdated_s{$lang}, $percent_os{$lang}; printf HTMLI "", $color_u, $wml_s{"english"}+$untranslated_s{'english'}-$wml_s{$lang}, $percent_us{$lang}; print HTMLI "\n"; } } print HTMLI ""; print HTMLI "
    LanguageTranslationsUp to dateOutdatedNot translated
    <:=\$trans{\$CUR_ISO_LANG}{%s} :> (%s)%d(%.1f%%)%d(%.1f%%)%d(%.1f%%)%d(%.1f%%)
    \n"; print HTMLI '

    Translated templates (PO files)

    '."\n"; printf HTMLI "

    \n",$po_total{'total'}; print HTMLI 'PO Translation Statistics" class="stattrans">'."\n"; print HTMLI "\n"; print HTMLI ""; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI "\n"; print HTMLI ""; print HTMLI ""; print HTMLI ''."\n"; print HTMLI ''."\n"; print HTMLI ''."\n"; print HTMLI ''."\n"; print HTMLI ""; print HTMLI ""; foreach $lang (@search_in) { next if $lang eq 'english'; my @processed_langs = ($langs{$lang}); @processed_langs = ("zh-cn", "zh-tw") if $langs{$lang} eq "zh"; foreach $l (@processed_langs) { print HTMLI ""; printf HTMLI "", $l, $lang, $l; $color_t = get_color ($percent_po_t{'total'}{$lang}); $color_f = get_color (100 - $percent_po_f{'total'}{$lang}); $color_u = get_color (100 - $percent_po_u{'total'}{$lang}); printf HTMLI "", $color_t, $po_translated{'total'}{$lang}, $percent_po_t{'total'}{$lang}; printf HTMLI "", $color_f, $po_fuzzy{'total'}{$lang}, $percent_po_f{'total'}{$lang}; printf HTMLI "", $color_u, $po_untranslated{'total'}{$lang}, $percent_po_u{'total'}{$lang}; print HTMLI "\n"; } } print HTMLI ""; print HTMLI "
    LanguageUp to dateFuzzyNot translated
    <:=\$trans{\$CUR_ISO_LANG}{%s} :> (%s)%d(%d%%)%d(%d%%)%d(%d%%)
    \n"; print HTMLI "\n"; close (HTMLI); print "done.\n" if ($config{'verbose'}); # Note: # Translated pages on ll.html may be higher than in index.html. # This is due to the fact that some english pages were removed. # printf "%s\n", join ("\n", keys %version); # printf "%s - %s\n", $version{'german/devel/index'}, $version{'english/devel/index'};