LP#1775466 XLIFF->PO->XLIFF merge tool
authorBill Erickson <berickxx@gmail.com>
Tue, 14 Aug 2018 16:51:25 +0000 (12:51 -0400)
committerBill Erickson <berickxx@gmail.com>
Tue, 14 Aug 2018 16:51:25 +0000 (12:51 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/locale/fix-po2xliff.pl [deleted file]
Open-ILS/src/eg2/src/locale/merge-po2xliff-messages.pl [new file with mode: 0755]

diff --git a/Open-ILS/src/eg2/src/locale/fix-po2xliff.pl b/Open-ILS/src/eg2/src/locale/fix-po2xliff.pl
deleted file mode 100755 (executable)
index 2c3eee2..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/perl
-use XML::LibXML;
-# ------------------------------------------------------------
-# The xliff2po and po2xliff crosswalk results in message IDs
-# getting stored in an unexpected location as far as Angular is
-# concerned.
-#
-# E.g.
-#
-#  <trans-unit xml:space="preserve" id="52" approved="no">
-#    <source>Sort Priority</source>
-#    <target state="needs-translation">Sort Priority</target>
-#    <context-group name="po-reference" purpose="location">
-#      <context context-type="sourcefile">1f93d86f7ad773b5f4232b60fff10567179f28f4</context>
-#    </context-group>
-#  </trans-unit>
-#
-#  Angular expaect the trans-unit id attribute to match the "sourcefile"
-#  hash from the context group.  This script makes that happen.
-#  Result is:
-#
-#  <trans-unit xml:space="preserve" id="1f93d86f7ad773b5f4232b60fff10567179f28f4" approved="no">
-#    <source>Sort Priority</source>
-#    <target state="needs-translation">Sort Priority</target>
-#    <context-group name="po-reference" purpose="location">
-#      <context context-type="sourcefile">1f93d86f7ad773b5f4232b60fff10567179f28f4</context>
-#    </context-group>
-#  </trans-unit>
-#
-#  NOTES:
-#  npm run build-translations
-#  xliff2po -i src/locale/messages.fr-CA.xlf -o src/locale/messages.fr-CA.po
-#  # add translations to .po file ...
-#  po2xliff -i src/locale/messages.fr-CA.po -o src/locale/messages.fr-CA.from-PO.xlf
-#  perl src/locale/fix-po2xliff.pl src/locale/messages.fr-CA.from-PO.xlf src/locale/messages.fr-CA.xlf
-#  ng build --configuration=production-fr-CA ...
-# ------------------------------------------------------------
-
-sub usage {
-    print <<DOCS;
-        Synopsis:
-
-            $0 messages.fr-CA.from-PO.xlf messages.fr-CA.xlf
-
-            1. First param is input file.
-            2. Second param is output file.  Defaults to STDOUT.
-DOCS
-    exit(0);
-}
-
-# Returns the first element by tag name that's a child of $node.
-sub gbn {
-    my ($node, $name) = @_;
-    return $node->getElementsByTagName($name)->[0];
-}
-
-my $infile = shift;
-my $outfile = shift;
-
-usage() unless $infile;
-
-my $doc = XML::LibXML->new->parse_file($infile);
-
-my $body = gbn(gbn($doc->documentElement, 'file'), 'body');
-
-for my $trans ($body->getElementsByTagName('trans-unit')) {
-
-    my $source = gbn($trans, 'source');
-    my $target = gbn($trans, 'target');
-    my $context_group = gbn($trans, 'context-group');
-    next unless $context_group;
-
-    my $context = gbn($context_group, 'context');
-    my $msg_id = $context->textContent;
-    $trans->setAttribute('id', $msg_id);
-}
-
-if ($outfile) {
-    open OUTFILE, '>', $outfile;
-    print OUTFILE $doc->toString(1);
-} else {
-    print $doc->toString(1) . "\n";
-}
-
-
-
-
-
diff --git a/Open-ILS/src/eg2/src/locale/merge-po2xliff-messages.pl b/Open-ILS/src/eg2/src/locale/merge-po2xliff-messages.pl
new file mode 100755 (executable)
index 0000000..f650909
--- /dev/null
@@ -0,0 +1,97 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use XML::LibXML;
+# ---------------------------------------------------------------------
+# The xliff2po -> po2xliff round trip results in files Angular is
+# not able to use for localization.  The message ID / context data
+# is out of sorts.
+# This script extracts translations from the round-tripped xliff file
+# and merges them back into the original Angular-approved xliff file.
+# ---------------------------------------------------------------------
+
+sub usage {
+    print <<DOCS;
+        Synopsis
+            $0 messages.fr-CA.from-PO.xlf messages.fr-CA.xlf
+
+        messages.fr-CA.from-PO.xlf is the result of a round trip of:
+
+        xliff2po -i messages.fr-CA.xlf -o messages.fr-CA.po
+        # translations applied to .po file...
+        po2xliff -i messages.fr-CA.po -o messages.fr-CA.from-PO.xlf
+DOCS
+    exit(0);
+}
+
+my $xlf_source = shift;
+my $xlf_target = shift;
+my %translations;
+
+usage() unless $xlf_source && $xlf_target;
+
+# Returns the first element by tag name that's a child of $node.
+sub gbn {
+    my ($node, $name) = @_;
+    return $node->getElementsByTagName($name)->[0];
+}
+
+# Create a map of message-id to translated strings.
+# In the round-tripped file, the message ID is stored as file context data.
+sub extract_source_translations {
+
+    my $doc = XML::LibXML->new->parse_file($xlf_source);
+
+    my $body = gbn(gbn($doc->documentElement, 'file'), 'body');
+
+    for my $trans ($body->getElementsByTagName('trans-unit')) {
+
+        my $source = gbn($trans, 'source');
+        my $target = gbn($trans, 'target');
+
+        # No translation, nothing to merge;
+        next if $source->textContent eq $target->textContent;
+
+        my $context_group = gbn($trans, 'context-group');
+        next unless $context_group;
+
+        my $context = gbn($context_group, 'context');
+        my $msg_id = $context->textContent;
+        $translations{$msg_id} = $target->textContent;
+    }
+}
+
+# Merged strings extracted above into the xliff by matching on message id.
+sub merge_target_translations {
+
+    my $doc = XML::LibXML->new->parse_file($xlf_target);
+
+    my $body = gbn(gbn($doc->documentElement, 'file'), 'body');
+
+    for my $trans ($body->getElementsByTagName('trans-unit')) {
+        my $msg_id = $trans->getAttribute('id');
+
+        my $translation = $translations{$msg_id};
+        
+        next unless $translation;
+
+        my $source = gbn($trans, 'source');
+        my $target = gbn($trans, 'target');
+
+        # print "Merging translation [$msg_id] ". 
+        #   $source->textContent . " : $translation\n";
+
+        $target->removeChildNodes();
+        $target->appendTextNode($translation);
+    }
+
+    open TARGET, '>', $xlf_target
+        or die "Cannot open for writing: $xlf_target : $!\n";
+
+    print TARGET $doc->toString(1);
+    close TARGET;
+}
+
+extract_source_translations();
+merge_target_translations();
+