aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xmarkup/pod-samples/pod/live-manual/tools/bin/po-stats.pl99
1 files changed, 99 insertions, 0 deletions
diff --git a/markup/pod-samples/pod/live-manual/tools/bin/po-stats.pl b/markup/pod-samples/pod/live-manual/tools/bin/po-stats.pl
new file mode 100755
index 0000000..bfd763e
--- /dev/null
+++ b/markup/pod-samples/pod/live-manual/tools/bin/po-stats.pl
@@ -0,0 +1,99 @@
+#!/usr/bin/env perl
+#
+# po-stats - what is translated, per language and per file
+#
+# The question before any translation work is where the effort should go, and
+# a .po file does not answer it by looking at it. gettext counts three states
+# and they are not the same thing:
+#
+# translated a msgstr with content and no fuzzy flag. This is what
+# reaches the document.
+# fuzzy a msgstr with content that po4a will not use, because the
+# source changed under it. The work exists and is not being
+# seen; a reviewer clearing the flag is cheaper than a
+# translator starting over.
+# untranslated an empty msgstr. sisu falls back to the source text, so
+# the document is readable and in the wrong language.
+#
+# Fuzzy is the interesting column. A language showing many fuzzy entries has
+# had work done that a source edit has taken out of use, and clearing them is
+# the cheapest translation available.
+#
+# usage: po-stats.pl (all languages, summary)
+# po-stats.pl --files de (per file, one language)
+#
+use strict;
+use warnings;
+use utf8;
+binmode(STDOUT, ":encoding(UTF-8)");
+
+my $per_file = 0;
+my @args;
+for (@ARGV) { $_ eq "--files" ? ($per_file = 1) : push @args, $_ }
+my $root = "../po4a/po";
+unless (-d $root) { die "po-stats: no catalogues at $root\n" }
+
+my @langs = @args ? @args : map { s{.*/}{}r } grep { -d } glob("$root/*");
+@langs = sort @langs;
+
+printf "%-8s %8s %8s %8s %8s %s\n",
+ "lang", "total", "done", "fuzzy", "empty", "translated";
+printf "%s\n", "-" x 62;
+
+my %tot;
+for my $lang (@langs) {
+ my (%n, %byfile);
+ for my $f (sort glob("$root/$lang/*.po")) {
+ my $c = count($f);
+ $n{$_} += $c->{$_} for qw(total done fuzzy empty);
+ $byfile{$f} = $c;
+ }
+ next unless $n{total};
+ printf "%-8s %8d %8d %8d %8d %5.1f%%\n",
+ $lang, $n{total}, $n{done}, $n{fuzzy}, $n{empty},
+ 100 * $n{done} / $n{total};
+ $tot{$_} += $n{$_} for qw(total done fuzzy empty);
+ next unless $per_file;
+ for my $f (sort { $byfile{$a}{done} <=> $byfile{$b}{done} } keys %byfile) {
+ my $c = $byfile{$f};
+ next unless $c->{total};
+ printf " %-44s %5.1f%% %d fuzzy\n",
+ ($f =~ m{([^/]+)$})[0], 100 * $c->{done} / $c->{total}, $c->{fuzzy};
+ }
+}
+printf "%s\n", "-" x 62;
+printf "%-8s %8d %8d %8d %8d %5.1f%%\n",
+ "all", $tot{total}, $tot{done}, $tot{fuzzy}, $tot{empty},
+ $tot{total} ? 100 * $tot{done} / $tot{total} : 0
+ if $tot{total};
+
+sub count {
+ my $file = shift;
+ open my $fh, "<:encoding(UTF-8)", $file or return { total => 0 };
+ my (%c, @id, @str, $mode, $fuzzy);
+ my $flush = sub {
+ return unless $mode;
+ my $id = join "", @id;
+ my $str = join "", @str;
+ if ($id ne "") { # not the catalogue's own header
+ $c{total}++;
+ if ($str eq "") { $c{empty}++ }
+ elsif ($fuzzy) { $c{fuzzy}++ }
+ else { $c{done}++ }
+ }
+ @id = (); @str = (); $mode = ""; $fuzzy = 0;
+ };
+ while (my $l = <$fh>) {
+ chomp $l;
+ if ($l =~ /^#,.*\bfuzzy\b/) { $fuzzy = 1 }
+ elsif ($l =~ /^#/) { }
+ elsif ($l =~ /^msgid\s+"(.*)"$/) { @id = ($1); @str = (); $mode = "id" }
+ elsif ($l =~ /^msgstr\s+"(.*)"$/) { @str = ($1); $mode = "str" }
+ elsif ($l =~ /^"(.*)"$/ && $mode) { $mode eq "id" ? push @id, $1 : push @str, $1 }
+ elsif ($l =~ /^\s*$/) { $flush->() }
+ }
+ $flush->();
+ close $fh;
+ $c{$_} //= 0 for qw(total done fuzzy empty);
+ return \%c;
+}