Perl script to make your translations uniform



I have written a Perl script to help me make translations uniform.
You call it with an argument list that includes all the .po files for your
language, both ones you have worked on and ones you are still planning to do.
In the first pass, it collects all your translations and remarks about any
that are inconsistent.  For instance, if you translated "Cancel" as "xxx" in
one place but as "yyy" in another, it lets you know.  In the second pass,
it fills in previously-empty translations in all your .po files if you have
prepared a translation for that message anywhere.  It keeps a backup copy
of the original .po files in case you want to revert.  

I hope this comes in handy to someone.  

Raphael

--- script follows
#!/usr/local/bin/perl -w

=head1 SYNOPSYS

	consistent.pl *.po

1. Looks at all the files and assembles standard msgstr's (translations) for
msgid's (original strings).

2. Warns about any inconsistent translations.

3. Generates new .po files that incorporate known translations for as-yet
untranslated msgstr's.

=head1 AUTHOR
	
	Raphael Finkel <raphael cs uky edu>
	3/2003
	Copyright c 2003, Gnu Public License
=cut

use strict;

my %translations = ();
my %sources = ();
my $outLength = 50; # chars of shortend msgids or msgstrs to show

sub shorten {
	my ($string) = @_;
	if (length($string) <= $outLength) {
		return($string);
	} else {
		return(substr($string, 0, $outLength) . " ... ");
	}
} # shorten

sub assimilateFiles {
	my $fileName;
	foreach $fileName (@ARGV) { # one file
		# print "Working on file $fileName\n"; # debug
		open INFILE, $fileName or die "Can't open ${fileName}: $!";
		my ($line, $theMsgId, $theMsgStr);
		while (defined($line = <INFILE>)) { # one msgid/msgstr pair
			chomp $line;
			next unless $line =~ /^msgid "(.*)"$/;
			$theMsgId = $1;
			while (defined($line = <INFILE>)) { # continuation msgid lines
				chomp $line;
				last unless $line =~ /^"(.*)"$/;
				$theMsgId .= $1;
			} # continuation msgid lines
			last unless defined($line);
			$line =~ /^msgstr "(.*)"$/;
			if (!defined($1)) {
				print "expected msgstr in $fileName: line $.\n";
				next;
			}
			next if $theMsgId eq ""; # just the header; always different
			$theMsgStr = $1;
			while (defined($line = <INFILE>)) { # continuation msgstr lines
				chomp $line;
				last unless $line =~ /^"(.*)"$/;
				$theMsgStr .= $1;
			} # continuation msgstr lines
			next if $theMsgStr eq ""; # this file makes no assertions
			if (defined($translations{$theMsgId})) { # seen before
				if ($translations{$theMsgId} ne $theMsgStr) { # conflict
					print "$fileName: line $.\n";
					print "\tmsgid = \"" . shorten($theMsgId) . "\"\n";
					print "\tmsgstr = \"" . shorten($theMsgStr) . "\"\n";
					print "\t$sources{$theMsgId} = \"" .
						shorten($translations{$theMsgId}) .  "\"\n";
				} # conflict
			} else {
				$translations{$theMsgId} = $theMsgStr;
				$sources{$theMsgId} = $fileName;
				# print "[$theMsgId] -> [$theMsgStr]\n"; # debug
			}
		} # one msgid/msgstr pair
		close INFILE;
	} # one file
} # assimilateFiles

sub modifyFiles {
	my $fileName;
	foreach $fileName (@ARGV) { # one file
		# print "Working on file $fileName\n"; # debug
		open INFILE, $fileName or die "Can't open $fileName: $!";
		open OUTFILE, ">$fileName.tmp" or die "Can't open $fileName.tmp: $!";
		my ($line, $theMsgId, $theMsgStr, $changes);
		$changes = 0;
		while (defined($line = <INFILE>)) { # one msgid/msgstr pair
			chomp $line;
			print OUTFILE "$line\n";
			next unless $line =~ /^msgid "(.*)"$/;
			$theMsgId = $1;
			while (defined($line = <INFILE>)) { # continuation msgid lines
				chomp $line;
				last unless $line =~ /^"(.*)"$/;
				print OUTFILE "$line\n";
				$theMsgId .= $1;
			} # continuation msgid lines
			last unless defined($line);
			$line =~ /^msgstr "(.*)"$/;
			if (!defined($1)) {
				print "expected msgstr in $fileName: line $.\n";
				print OUTFILE "$line\n";
				next;
			}
			if ($theMsgId eq "") { # just the header; always different
				print OUTFILE "msgstr \"\"\n";
				next;
			}
			$theMsgStr = $line . "\n";
			while (defined($line = <INFILE>)) { # continuation msgstr lines
				chomp $line;
				last unless $line =~ /^"(.*)"$/;
				$theMsgStr .= $line . "\n";
			} # continuation msgstr lines
			if ($theMsgStr eq "msgstr \"\"\n" and
					defined($translations{$theMsgId})) { # worth replacing
				print "${fileName}: [$theMsgId] -> " .
					"[$translations{$theMsgId}]\n"; # debug
				print OUTFILE "msgstr \"" . $translations{$theMsgId} . "\"\n";
				$changes += 1;
			} else { # don't replace
				print OUTFILE $theMsgStr;
				# print $theMsgStr; # debug
			}
			print OUTFILE "$line\n" if defined($line); # typically empty
		} # one msgid/msgstr pair
		close INFILE;
		close OUTFILE;
		if ($changes) {
			# print "renaming $fileName.tmp to ${fileName}\n"; # debug
			print "${fileName}: $changes " .
				($changes == 1 ? "change" : "changes") . "\n";
			rename "$fileName", "$fileName.bak" or
				die "Rename $fileName ${fileName}.bak: $!";
			rename "$fileName.tmp", $fileName or
				die "Rename $fileName.tmp ${fileName}: $!";
		} else {
			unlink "$fileName.tmp";
		}
	} # one file
} # modifyFiles

assimilateFiles();
modifyFiles();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]