584
600
## XML (non-bonobo-activation) merge code
586
sub xml_merge_translations
591
local $/; # slurp mode
592
open INPUT, "<$FILE" or die "can't open $FILE: $!";
597
open OUTPUT, ">$OUTFILE" or die;
599
# FIXME: support attribute translations
601
# Empty nodes never need translation, so unmark all of them.
602
# For example, <_foo/> is just replaced by <foo/>.
603
$source =~ s|<\s*_($w+)\s*/>|<$1/>|g;
605
# Support for <_foo>blah</_foo> style translations.
606
while ($source =~ s|^(.*?)([ \t]*)<\s*_($w+)\s*>(.*?)<\s*/_\3\s*>([ \t]*\n)?||s)
614
print OUTPUT "$spaces<$tag>$string</$tag>\n";
616
$string =~ s/\s+/ /g;
619
$string = entity_decode($string);
621
for my $lang (sort keys %po_files_by_lang)
623
my $translation = $translations{$lang, $string};
624
next if !$translation;
625
$translation = entity_encode($translation);
626
print OUTPUT "$spaces<$tag xml:lang=\"$lang\">$translation</$tag>\n";
603
# Process tag attributes
604
# Only parameter is a HASH containing attributes -> values mapping
605
sub getAttributeString
608
my $do_translate = shift || 0;
609
my $language = shift || "";
611
foreach my $e (reverse(sort(keys %{ $sub }))) {
613
my $string = $sub->{$e};
616
$string =~ s/^[\s]+//;
617
$string =~ s/[\s]+$//;
619
if ($string =~ /^'.*'$/)
623
$string =~ s/^['"]//g;
624
$string =~ s/['"]$//g;
626
if ($do_translate && $key =~ /^_/) {
632
my $decode_string = entity_decode($string);
633
my $translation = $translations{$language, $decode_string};
635
$translation = entity_encode($translation);
636
$string = $translation;
641
$result .= " $key=$quote$string$quote";
646
# Returns a translatable string from XML node, it works on contents of every node in XML::Parser tree
647
# doesn't support nesting of translatable tags (i.e. <_blah>this <_doh>doesn't</_doh> work</_blah> -- besides
648
# can you define the correct semantics for this?)
654
my @list = @{ $ref };
657
my $count = scalar(@list);
658
my $attrs = $list[0];
660
while ($index < $count) {
661
my $type = $list[$index];
662
my $content = $list[$index+1];
666
# lets strip the whitespace here, and *ONLY* here
667
$content =~ s/\s+/ /gs;
668
$result .= ($content);
670
#print "no cdata content when expected it\n"; # is this possible, is this ok?
671
# what to do if this happens?
672
# Did I mention that I hate XML::Parser tree style?
675
# We've got another element
677
$result .= getAttributeString($attrs, 0); # no nested translatable elements
679
my $subresult = getXMLstring($content);
681
$result .= ">".$subresult . "</$type>";
697
my $nodename = shift;
699
my $language = shift || "";
702
if ($content =~ /^[\s]*$/) {
703
$leading_space .= $content;
708
my @all = @{ $content };
709
my $attrs = shift @all;
710
my $outattr = getAttributeString($attrs, 1, $language);
713
if ($nodename =~ /^_/) {
718
print $fh "<$nodename$outattr";
720
$lookup = getXMLstring($content);
721
$lookup =~ s/^\s+//s;
722
$lookup =~ s/\s+$//s;
725
my $translation = $translations{$language, $lookup};
726
if ($MULTIPLE_OUTPUT && $translation) {
727
print $fh " xml:lang=\"", $language, "\"";
728
print $fh ">", $translation, "</$nodename>";
729
return; # this means there will be no same translation with xml:lang="$language"...
730
# if we want them both, just remove this "return"
732
print $fh ">$lookup</$nodename>";
739
for my $lang (sort keys %po_files_by_lang) {
740
if ($MULTIPLE_OUTPUT && $lang ne "$language") {
747
my $localattrs = getAttributeString($attrs, 1, $lang);
748
my $decode_string = ($lookup); #entity_decode($lookup);
749
my $translation = $translations{$lang, $decode_string};
751
$translation = ($translation);
753
$leading_space =~ s/.*\n//g;
754
print $fh $leading_space;
755
print $fh "<", $nodename, " xml:lang=\"", $lang, "\"", $localattrs;
756
print $fh ">", $translation , "</$nodename>";
762
my $count = scalar(@all);
769
while ($index < $count) {
770
my $type = $all[$index];
771
my $rest = $all[$index+1];
772
traverse($fh, $type, $rest, $language);
776
print $fh "</$nodename>";
782
sub intltool_tree_char
786
my $clist = $expat->{Curlist};
789
# Use original_string so that we retain escaped entities
792
if ($pos > 0 and $clist->[$pos - 1] eq '0') {
793
$clist->[$pos] .= $expat->original_string();
795
push @$clist, 0 => $expat->original_string();
799
sub intltool_tree_start
805
# Use original_string so that we retain escaped entities
806
# in attribute values. We must convert the string to an
807
# @origlist array to conform to the structure of the Tree
810
my @original_array = split /\x/, $expat->original_string();
811
my $source = $expat->original_string();
813
# Remove leading tag.
815
$source =~ s|^\s*<\s*(\S+)||s;
817
# Grab attribute key/value pairs and push onto @origlist array.
821
if ($source =~ /^\s*([\w:-]+)\s*[=]\s*["]/)
823
$source =~ s|^\s*([\w:-]+)\s*[=]\s*["]([^"]*)["]||s;
825
push @origlist, '"' . $2 . '"';
827
elsif ($source =~ /^\s*([\w:-]+)\s*[=]\s*[']/)
829
$source =~ s|^\s*([\w:-]+)\s*[=]\s*[']([^']*)[']||s;
831
push @origlist, "'" . $2 . "'";
839
my $ol = [ { @origlist } ];
841
push @{ $expat->{Lists} }, $expat->{Curlist};
842
push @{ $expat->{Curlist} }, $tag => $ol;
843
$expat->{Curlist} = $ol;
848
my $filename = shift || return;
850
die "ERROR Cannot find filename: $filename\n";
853
my $ret = eval 'require XML::Parser';
855
die "You must have XML::Parser installed to run $0\n\n";
857
my $xp = new XML::Parser(Style => 'Tree');
858
$xp->setHandlers(Char => \&intltool_tree_char);
859
$xp->setHandlers(Start => \&intltool_tree_start);
860
my $tree = $xp->parsefile($filename);
862
# <foo><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo>
864
# [foo, [{}, head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]], bar, [{},
865
# 0, "Howdy", ref, [{}]], 0, "do" ] ]
877
die "ERROR Cannot find filename: $infile\n";
880
print $fh qq{<?xml version="1.0" encoding="UTF-8"?>\n};
883
open DOCINPUT, "<${FILE}" or die;
884
$source = <DOCINPUT>;
887
if ($source =~ /(<!DOCTYPE.*\[.*\]\s*>)/s)
891
elsif ($source =~ /(<!DOCTYPE[^>]*>)/s)
901
my $language = shift || "";
903
my $name = shift @{ $ref };
904
my $cont = shift @{ $ref };
905
traverse($fh, $name, $cont, $language);
912
if ($MULTIPLE_OUTPUT) {
913
for my $lang (sort keys %po_files_by_lang) {
915
mkdir $lang or die "Cannot create subdirectory $lang: $!\n";
917
open OUTPUT, ">$lang/$OUTFILE" or die "Cannot open $lang/$OUTFILE: $!\n";
918
my $tree = readXml($FILE);
919
print_header($FILE, \*OUTPUT);
920
parseTree(\*OUTPUT, $tree, $lang);
922
print "CREATED $lang/$OUTFILE\n" unless $QUIET_ARG;
630
print OUTPUT $source;
925
open OUTPUT, ">$OUTFILE" or die "Cannot open $OUTFILE: $!\n";
926
my $tree = readXml($FILE);
927
print_header($FILE, \*OUTPUT);
928
parseTree(\*OUTPUT, $tree);
930
print "CREATED $OUTFILE\n" unless $QUIET_ARG;
635
933
sub keys_merge_translations