martes, 2 de abril de 2013

XLIFF merger

Me he encontrado con un proyecto de Symfony 1.4 que utilizaba más de un archivo de traducciones por cada aplicación. La situación se había vuelto insostenible al introducir Pootle en la ecuación, por lo cual desarrollé un pequeño script que combina dos o más archivos en el formato adecuado en uno solo (de hecho, la salida del mismo es por stdout, para mayor flexibilidad).

El código es rápido y el XML de salida se genera con una simple concatenación de cadenas, pero hace el trabajo. Espero que sea de ayuda. Está preparado para ser guardado en un archivo con permisos de ejecución.


#!/usr/bin/php
<?php

/**
 * (c) 2013, Fernando del Valle
 * Code licensed as GPL
 * Merges two or more XLIFF files, as the ones used by Pootle or Symfony.
 */

$files = @array_slice($argv,1);
if( count( $files ) < 2 ) {
    echo "Usage: xliff_merge.php file1 file2 [... filen]";
    exit(-1);
}

try {
        $dictionary = array();
        foreach( $files as $filename ) {
            if( !file_exists( $filename ) )
                throw new Exception("File '$filename' does not exist");
            $root = simplexml_load_file( $filename );
            $file = $root->file;
            if( !$file )
                throw new Exception("Bad format");
            $source = $file['source-language'];
            $target = $file['target-language'];
            $body = $file->body;
            $tunits = $body['trans-unit'];
            foreach( $body[0] as $tunit ) {
                $sstr = $tunit->source->__toString();
                $tstr = $tunit->target->__toString();
                $approved = @$tunit['approved'];
                if( !$sstr )
                    continue;
                $dictionary[ $sstr ] = array( 'target' => $tstr, 'approved' => $approved );
            }
        }
        $results = array();
        $results[] = "<?xml version='1.0' encoding='utf-8'?>";
        $results[] = "<xliff version=\"1.0\">";
        $results[] = "\t<file datatype=\"plaintext\" source-language=\"$source\" target-language=\"$target\" original=\"global\">";
        $results[] = "\t\t<body>";
        $c = 1;
        foreach( $dictionary as $source_string => $arr ) {
            $target_string = $arr['target'];
            $results[] = "\t\t\t<trans-unit id=\"$c\" ".($arr['approved'] ? 'approved="yes"' : '').">";
            $results[] = "\t\t\t\t<source>$source_string</source>";
            $results[] = "\t\t\t\t<target>$target_string</target>";
            $results[] = "\t\t\t</trans-unit>";
            $c++;
        }
        $results[] = "\t\t</body>";
        $results[] = "\t</file>";
        $results[] = "</xliff>";

        echo join( "\r\n", $results );
} catch (Exception $e) {
    echo "FATAL ERROR: {$e->getMessage()}";
    exit(-1);
}

No hay comentarios: