1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the PHP Translation package. |
5
|
|
|
* |
6
|
|
|
* (c) PHP Translation team <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Translation\SymfonyStorage\Loader\Port; |
13
|
|
|
|
14
|
|
|
use Symfony\Component\Translation\MessageCatalogue; |
15
|
|
|
use Symfony\Component\Translation\Exception\InvalidArgumentException; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* This code is moved from the Symfony 3.4 repo. It will be removed when |
19
|
|
|
* we drop support for Symfony 3.3 and below. |
20
|
|
|
* |
21
|
|
|
* @author Tobias Nyholm <[email protected]> |
22
|
|
|
*/ |
23
|
|
|
class SymfonyPort |
24
|
|
|
{ |
25
|
|
|
/** |
26
|
|
|
* @param \DOMDocument $dom |
27
|
|
|
* @param MessageCatalogue $catalogue |
28
|
|
|
* @param string $domain |
29
|
|
|
*/ |
30
|
2 |
|
public function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, $domain) |
31
|
|
|
{ |
32
|
2 |
|
$xml = simplexml_import_dom($dom); |
33
|
2 |
|
$encoding = strtoupper($dom->encoding); |
34
|
|
|
|
35
|
2 |
|
$xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:2.0'); |
36
|
|
|
|
37
|
2 |
|
foreach ($xml->xpath('//xliff:unit') as $unit) { |
38
|
2 |
|
$segment = $unit->segment; |
39
|
2 |
|
$source = $segment->source; |
40
|
|
|
|
41
|
|
|
// If the xlf file has another encoding specified, try to convert it because |
42
|
|
|
// simple_xml will always return utf-8 encoded values |
43
|
2 |
|
$target = $this->utf8ToCharset((string) (isset($segment->target) ? $segment->target : $source), $encoding); |
44
|
|
|
|
45
|
2 |
|
$catalogue->set((string) $source, $target, $domain); |
46
|
|
|
|
47
|
2 |
|
$metadata = []; |
48
|
2 |
View Code Duplication |
if (isset($segment->target) && $segment->target->attributes()) { |
|
|
|
|
49
|
|
|
$metadata['target-attributes'] = []; |
50
|
|
|
foreach ($segment->target->attributes() as $key => $value) { |
51
|
|
|
$metadata['target-attributes'][$key] = (string) $value; |
52
|
|
|
} |
53
|
|
|
} |
54
|
|
|
|
55
|
2 |
|
if (isset($unit->notes)) { |
56
|
1 |
|
$metadata['notes'] = []; |
57
|
1 |
|
foreach ($unit->notes->note as $noteNode) { |
58
|
1 |
|
$note = []; |
59
|
1 |
|
foreach ($noteNode->attributes() as $key => $value) { |
60
|
1 |
|
$note[$key] = (string) $value; |
61
|
1 |
|
} |
62
|
1 |
|
$note['content'] = (string) $noteNode; |
63
|
1 |
|
$metadata['notes'][] = $note; |
64
|
1 |
|
} |
65
|
1 |
|
} |
66
|
|
|
|
67
|
2 |
|
$catalogue->setMetadata((string) $source, $metadata, $domain); |
68
|
2 |
|
} |
69
|
2 |
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Convert a UTF8 string to the specified encoding. |
73
|
|
|
* |
74
|
|
|
* @param string $content String to decode |
75
|
|
|
* @param string $encoding Target encoding |
76
|
|
|
* |
77
|
|
|
* @return string |
78
|
|
|
*/ |
79
|
2 |
|
private function utf8ToCharset($content, $encoding = null) |
80
|
|
|
{ |
81
|
2 |
|
if ('UTF-8' !== $encoding && !empty($encoding)) { |
82
|
|
|
return mb_convert_encoding($content, $encoding, 'UTF-8'); |
83
|
|
|
} |
84
|
|
|
|
85
|
2 |
|
return $content; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Gets xliff file version based on the root "version" attribute. |
90
|
|
|
* Defaults to 1.2 for backwards compatibility. |
91
|
|
|
* |
92
|
|
|
* @param \DOMDocument $dom |
93
|
|
|
* |
94
|
|
|
* @throws InvalidArgumentException |
95
|
|
|
* |
96
|
|
|
* @return string |
97
|
|
|
* |
98
|
|
|
* @deprecated Will be removed when we drop support for SF2.7 |
99
|
|
|
*/ |
100
|
|
|
public function getVersionNumber(\DOMDocument $dom) |
101
|
|
|
{ |
102
|
|
|
/** @var \DOMNode $xliff */ |
103
|
|
|
foreach ($dom->getElementsByTagName('xliff') as $xliff) { |
104
|
|
|
$version = $xliff->attributes->getNamedItem('version'); |
105
|
|
|
if ($version) { |
106
|
|
|
return $version->nodeValue; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
$namespace = $xliff->attributes->getNamedItem('xmlns'); |
110
|
|
|
if ($namespace) { |
111
|
|
|
if (substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34) !== 0) { |
112
|
|
|
throw new InvalidArgumentException(sprintf('Not a valid XLIFF namespace "%s"', $namespace)); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
return substr($namespace, 34); |
116
|
|
|
} |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
// Falls back to v1.2 |
120
|
|
|
return '1.2'; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Extract messages and metadata from DOMDocument into a MessageCatalogue. |
125
|
|
|
* |
126
|
|
|
* @param \DOMDocument $dom Source to extract messages and metadata |
127
|
|
|
* @param MessageCatalogue $catalogue Catalogue where we'll collect messages and metadata |
128
|
|
|
* @param string $domain The domain |
129
|
|
|
* |
130
|
|
|
* @deprecated Will be removed when we drop support for SF2.7 |
131
|
|
|
*/ |
132
|
|
|
public function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, $domain) |
133
|
|
|
{ |
134
|
|
|
$xml = simplexml_import_dom($dom); |
135
|
|
|
$encoding = strtoupper($dom->encoding); |
136
|
|
|
|
137
|
|
|
$xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:1.2'); |
138
|
|
|
foreach ($xml->xpath('//xliff:trans-unit') as $translation) { |
139
|
|
|
$attributes = $translation->attributes(); |
140
|
|
|
|
141
|
|
|
if (!(isset($attributes['resname']) || isset($translation->source))) { |
142
|
|
|
continue; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
$source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source; |
146
|
|
|
// If the xlf file has another encoding specified, try to convert it because |
147
|
|
|
// simple_xml will always return utf-8 encoded values |
148
|
|
|
$target = $this->utf8ToCharset((string) (isset($translation->target) ? $translation->target : $source), $encoding); |
149
|
|
|
|
150
|
|
|
$catalogue->set((string) $source, $target, $domain); |
151
|
|
|
|
152
|
|
|
$metadata = []; |
153
|
|
|
if ($notes = $this->parseNotesMetadata($translation->note, $encoding)) { |
|
|
|
|
154
|
|
|
$metadata['notes'] = $notes; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
View Code Duplication |
if (isset($translation->target) && $translation->target->attributes()) { |
|
|
|
|
158
|
|
|
$metadata['target-attributes'] = []; |
159
|
|
|
foreach ($translation->target->attributes() as $key => $value) { |
160
|
|
|
$metadata['target-attributes'][$key] = (string) $value; |
161
|
|
|
} |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
if (isset($attributes['id'])) { |
165
|
|
|
$metadata['id'] = (string) $attributes['id']; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
$catalogue->setMetadata((string) $source, $metadata, $domain); |
169
|
|
|
} |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* @param \SimpleXMLElement|null $noteElement |
174
|
|
|
* @param string|null $encoding |
175
|
|
|
* |
176
|
|
|
* @return array |
177
|
|
|
* |
178
|
|
|
* @deprecated Will be removed when we drop support for SF2.7 |
179
|
|
|
*/ |
180
|
|
|
private function parseNotesMetadata(\SimpleXMLElement $noteElement = null, $encoding = null) |
181
|
|
|
{ |
182
|
|
|
$notes = []; |
183
|
|
|
|
184
|
|
|
if (null === $noteElement) { |
185
|
|
|
return $notes; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
/** @var \SimpleXMLElement $xmlNote */ |
189
|
|
|
foreach ($noteElement as $xmlNote) { |
190
|
|
|
$noteAttributes = $xmlNote->attributes(); |
191
|
|
|
$note = ['content' => $this->utf8ToCharset((string) $xmlNote, $encoding)]; |
192
|
|
|
if (isset($noteAttributes['priority'])) { |
193
|
|
|
$note['priority'] = (int) $noteAttributes['priority']; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
if (isset($noteAttributes['from'])) { |
197
|
|
|
$note['from'] = (string) $noteAttributes['from']; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
$notes[] = $note; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
return $notes; |
204
|
|
|
} |
205
|
|
|
} |
206
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.