diff options
Diffstat (limited to 'www/wiki/extensions/Translate/ffs/XliffFFS.php')
-rw-r--r-- | www/wiki/extensions/Translate/ffs/XliffFFS.php | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/www/wiki/extensions/Translate/ffs/XliffFFS.php b/www/wiki/extensions/Translate/ffs/XliffFFS.php new file mode 100644 index 00000000..cef5d5bb --- /dev/null +++ b/www/wiki/extensions/Translate/ffs/XliffFFS.php @@ -0,0 +1,192 @@ +<?php +/** + * Partial support for the Xliff translation format. + * + * @file + * @author Niklas Laxström + * @license GPL-2.0-or-later + */ + +/** + * Partial support for the Xliff translation format. + * @since 2013-04 + * @ingroup FFS + */ +class XliffFFS extends SimpleFFS { + public static function isValid( $data ) { + $doc = new DomDocument( '1.0' ); + $doc->loadXML( $data ); + + $errors = libxml_get_errors(); + if ( $errors ) { + return false; + } + + if ( strpos( $data, 'version="1.2">' ) !== false ) { + $schema = __DIR__ . '/../data/xliff-core-1.2-transitional.xsd'; + if ( !$doc->schemaValidate( $schema ) ) { + return false; + } + } + + return true; + } + + public function getFileExtensions() { + return [ '.xlf', '.xliff', '.xml' ]; + } + + /** + * @param string $data + * @param string $element + * @return array Parsed data. + */ + public function readFromVariable( $data, $element = 'target' ) { + $messages = []; + $mangler = $this->group->getMangler(); + + $reader = new SimpleXMLElement( $data ); + $reader->registerXPathNamespace( + 'xliff', + 'urn:oasis:names:tc:xliff:document:1.2' + ); + + $items = array_merge( + $reader->xpath( '//trans-unit' ), + $reader->xpath( '//xliff:trans-unit' ) + ); + + foreach ( $items as $item ) { + /** @var SimpleXMLElement $source */ + $source = $item->$element; + + if ( !$source ) { + continue; + } + + $key = (string)$item['id']; + + /* In case there are tags inside the element, preserve + * them. */ + $dom = new DOMDocument( '1.0' ); + $dom->loadXML( $source->asXML() ); + $value = self::getInnerXml( $dom->documentElement ); + + /* This might not be 100% according to the spec, but + * for now if there is explicit approved=no, mark it + * as fuzzy, but don't do that if the attribute is not + * set */ + if ( (string)$source['state'] === 'needs-l10n' ) { + $value = TRANSLATE_FUZZY . $value; + } + + // Strip CDATA if present + $value = preg_replace( '/<!\[CDATA\[(.*?)\]\]>/s', '\1', $value ); + + $messages[$key] = $value; + } + + return [ + 'MESSAGES' => $mangler->mangle( $messages ), + ]; + } + + /** + * @param string $code Language code. + * @return array|bool + * @throws MWException + */ + public function read( $code ) { + if ( !$this->exists( $code ) ) { + return false; + } + + $filename = $this->group->getSourceFilePath( $code ); + $input = file_get_contents( $filename ); + if ( $input === false ) { + throw new MWException( "Unable to read file $filename." ); + } + + $element = $code === $this->group->getSourceLanguage() ? 'source' : 'target'; + + return $this->readFromVariable( $input, $element ); + } + + /** + * Gets the html inside en element without the element itself. + * + * @param DomElement $node + * @return string + */ + public static function getInnerXml( DomElement $node ) { + $text = ''; + foreach ( $node->childNodes as $child ) { + $text .= $child->ownerDocument->saveXML( $child ); + } + + return $text; + } + + protected function writeReal( MessageCollection $collection ) { + $mangler = $this->group->getMangler(); + + $template = new DomDocument( '1.0' ); + $template->preserveWhiteSpace = false; + $template->formatOutput = true; + + // Try to use the definition file as template + $sourceLanguage = $this->group->getSourceLanguage(); + $sourceFile = $this->group->getSourceFilePath( $sourceLanguage ); + if ( file_exists( $sourceFile ) ) { + $template->load( $sourceFile ); + } else { + // Else use standard template + $template->load( __DIR__ . '/../data/xliff-template.xml' ); + } + + $list = $template->getElementsByTagName( 'body' )->item( 0 ); + $list->nodeValue = null; + + /** @var TMessage $m */ + foreach ( $collection as $key => $m ) { + $key = $mangler->unmangle( $key ); + + $value = $m->translation(); + $value = str_replace( TRANSLATE_FUZZY, '', $value ); + + // @todo Support placeholder tags etc. + $source = $template->createDocumentFragment(); + $source->appendXML( htmlspecialchars( $m->definition() ) ); + + $target = $template->createDocumentFragment(); + $target->appendXML( htmlspecialchars( $value ) ); + + $sourceElement = $template->createElement( 'source' ); + $sourceElement->appendChild( $source ); + + $targetElement = $template->createElement( 'target' ); + $targetElement->appendChild( $target ); + if ( $m->getProperty( 'status' ) === 'fuzzy' ) { + $targetElement->setAttribute( 'state', 'needs-l10n' ); + } + if ( $m->getProperty( 'status' ) === 'proofread' ) { + $targetElement->setAttribute( 'state', 'signed-off' ); + } + + $transUnit = $template->createElement( 'trans-unit' ); + $transUnit->setAttribute( 'id', $key ); + $transUnit->appendChild( $sourceElement ); + $transUnit->appendChild( $targetElement ); + + $list->appendChild( $transUnit ); + } + + $template->encoding = 'UTF-8'; + + return $template->saveXML(); + } + + public function supportsFuzzy() { + return 'yes'; + } +} |