Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
XliffFFS.php
Go to the documentation of this file.
1<?php
11use Wikimedia\Zest\Zest;
12
18class XliffFFS extends SimpleFFS {
19 public static function isValid( $data ) {
20 $doc = new DomDocument( '1.0' );
21 $doc->loadXML( $data );
22
23 $errors = libxml_get_errors();
24 if ( $errors ) {
25 return false;
26 }
27
28 if ( strpos( $data, 'version="1.2">' ) !== false ) {
29 $schema = __DIR__ . '/../data/xliff-core-1.2-transitional.xsd';
30 if ( !$doc->schemaValidate( $schema ) ) {
31 return false;
32 }
33 }
34
35 return true;
36 }
37
38 public function getFileExtensions() {
39 return [ '.xlf', '.xliff', '.xml' ];
40 }
41
47 public function readFromVariable( $data, $element = 'target' ) {
48 $messages = [];
49 $mangler = $this->group->getMangler();
50
51 $reader = new SimpleXMLElement( $data );
52 $reader->registerXPathNamespace(
53 'xliff',
54 'urn:oasis:names:tc:xliff:document:1.2'
55 );
56
57 $items = array_merge(
58 $reader->xpath( '//trans-unit' ),
59 $reader->xpath( '//xliff:trans-unit' )
60 );
61
62 foreach ( $items as $item ) {
64 $source = $item->$element;
65
66 if ( !$source ) {
67 continue;
68 }
69
70 $key = (string)$item['id'];
71
72 /* In case there are tags inside the element, preserve
73 * them. */
74 $dom = new DOMDocument( '1.0' );
75 $dom->loadXML( $source->asXML() );
76 $value = self::getInnerXml( $dom->documentElement );
77
78 /* This might not be 100% according to the spec, but
79 * for now if there is explicit approved=no, mark it
80 * as fuzzy, but don't do that if the attribute is not
81 * set */
82 if ( (string)$source['state'] === 'needs-l10n' ) {
83 $value = TRANSLATE_FUZZY . $value;
84 }
85
86 // Strip CDATA if present
87 $value = preg_replace( '/<!\[CDATA\[(.*?)\]\]>/s', '\1', $value );
88
89 $messages[$key] = $value;
90 }
91
92 return [
93 'MESSAGES' => $mangler->mangleArray( $messages ),
94 ];
95 }
96
102 public function read( $code ) {
103 if ( !$this->exists( $code ) ) {
104 return false;
105 }
106
107 $filename = $this->group->getSourceFilePath( $code );
108 $input = file_get_contents( $filename );
109 if ( $input === false ) {
110 throw new MWException( "Unable to read file $filename." );
111 }
112
113 $element = $code === $this->group->getSourceLanguage() ? 'source' : 'target';
114
115 return $this->readFromVariable( $input, $element );
116 }
117
124 public static function getInnerXml( DOMElement $node ) {
125 $text = '';
126 foreach ( $node->childNodes as $child ) {
127 $text .= $child->ownerDocument->saveXML( $child );
128 }
129
130 return $text;
131 }
132
133 protected function writeReal( MessageCollection $collection ) {
134 $mangler = $this->group->getMangler();
135
136 $template = new DomDocument( '1.0' );
137 $template->preserveWhiteSpace = false;
138 $template->formatOutput = true;
139
140 // Try to use the definition file as template
141 $sourceLanguage = $this->group->getSourceLanguage();
142 $sourceFile = $this->group->getSourceFilePath( $sourceLanguage );
143 if ( file_exists( $sourceFile ) ) {
144 $template->load( $sourceFile );
145 } else {
146 // Else use standard template
147 $template->load( __DIR__ . '/../data/xliff-template.xml' );
148 }
149
150 $list = Zest::getElementsByTagName( $template, 'body' )[0];
151 $list->nodeValue = null;
152
154 foreach ( $collection as $key => $m ) {
155 $key = $mangler->unmangle( $key );
156
157 $value = $m->translation();
158 $value = str_replace( TRANSLATE_FUZZY, '', $value );
159
160 // @todo Support placeholder tags etc.
161 $source = $template->createDocumentFragment();
162 $source->appendXML( htmlspecialchars( $m->definition() ) );
163
164 $target = $template->createDocumentFragment();
165 $target->appendXML( htmlspecialchars( $value ) );
166
167 $sourceElement = $template->createElement( 'source' );
168 $sourceElement->appendChild( $source );
169
170 $targetElement = $template->createElement( 'target' );
171 $targetElement->appendChild( $target );
172 if ( $m->getProperty( 'status' ) === 'fuzzy' ) {
173 $targetElement->setAttribute( 'state', 'needs-l10n' );
174 }
175 if ( $m->getProperty( 'status' ) === 'proofread' ) {
176 $targetElement->setAttribute( 'state', 'signed-off' );
177 }
178
179 $transUnit = $template->createElement( 'trans-unit' );
180 $transUnit->setAttribute( 'id', $key );
181 $transUnit->appendChild( $sourceElement );
182 $transUnit->appendChild( $targetElement );
183
184 $list->appendChild( $transUnit );
185 }
186
187 $template->encoding = 'UTF-8';
188
189 return $template->saveXML();
190 }
191
192 public function supportsFuzzy() {
193 return 'yes';
194 }
195}
This file contains the class for core message collections implementation.
exists( $code=false)
Returns true if the file for this message group in a given language exists.
Definition SimpleFFS.php:77
Partial support for the Xliff translation format.
Definition XliffFFS.php:18
supportsFuzzy()
Query the capabilities of this FFS.
Definition XliffFFS.php:192
read( $code)
Definition XliffFFS.php:102
writeReal(MessageCollection $collection)
Definition XliffFFS.php:133
readFromVariable( $data, $element='target')
Definition XliffFFS.php:47
getFileExtensions()
Return the commonly used file extensions for these formats.
Definition XliffFFS.php:38
static getInnerXml(DOMElement $node)
Gets the html inside en element without the element itself.
Definition XliffFFS.php:124