PluginProbe
Metricool – Social media and site statistics / 2.1.1
Metricool – Social media and site statistics v2.1.1
2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.27 trunk
metricool / vendor / _scoped / symfony / translation / Loader / XliffFileLoader.php

XliffFileLoader.php in Metricool – Social media and site statistics 2.1.1, at vendor/_scoped/symfony/translation/Loader/XliffFileLoader.php

189 lines 8.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <[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 namespace Metricool\Vendor\Symfony\Component\Translation\Loader;
12
13 use Metricool\Vendor\Symfony\Component\Config\Resource\FileResource;
14 use Metricool\Vendor\Symfony\Component\Config\Util\Exception\InvalidXmlException;
15 use Metricool\Vendor\Symfony\Component\Config\Util\Exception\XmlParsingException;
16 use Metricool\Vendor\Symfony\Component\Config\Util\XmlUtils;
17 use Metricool\Vendor\Symfony\Component\Translation\Exception\InvalidResourceException;
18 use Metricool\Vendor\Symfony\Component\Translation\Exception\NotFoundResourceException;
19 use Metricool\Vendor\Symfony\Component\Translation\Exception\RuntimeException;
20 use Metricool\Vendor\Symfony\Component\Translation\MessageCatalogue;
21 use Metricool\Vendor\Symfony\Component\Translation\Util\XliffUtils;
22 /**
23 * XliffFileLoader loads translations from XLIFF files.
24 *
25 * @author Fabien Potencier <[email protected]>
26 */
27 class XliffFileLoader implements LoaderInterface
28 {
29 /**
30 * {@inheritdoc}
31 */
32 public function load($resource, string $locale, string $domain = 'messages')
33 {
34 if (!class_exists(XmlUtils::class)) {
35 throw new RuntimeException('Loading translations from the Xliff format requires the Symfony Config component.');
36 }
37 if (!$this->isXmlString($resource)) {
38 if (!stream_is_local($resource)) {
39 throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
40 }
41 if (!file_exists($resource)) {
42 throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
43 }
44 if (!is_file($resource)) {
45 throw new InvalidResourceException(sprintf('This is neither a file nor an XLIFF string "%s".', $resource));
46 }
47 }
48 try {
49 if ($this->isXmlString($resource)) {
50 $dom = XmlUtils::parse($resource);
51 } else {
52 $dom = XmlUtils::loadFile($resource);
53 }
54 } catch (\InvalidArgumentException|XmlParsingException|InvalidXmlException $e) {
55 throw new InvalidResourceException(sprintf('Unable to load "%s": ', $resource) . $e->getMessage(), $e->getCode(), $e);
56 }
57 if ($errors = XliffUtils::validateSchema($dom)) {
58 throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: ', $resource) . XliffUtils::getErrorsAsString($errors));
59 }
60 $catalogue = new MessageCatalogue($locale);
61 $this->extract($dom, $catalogue, $domain);
62 if (is_file($resource) && class_exists(FileResource::class)) {
63 $catalogue->addResource(new FileResource($resource));
64 }
65 return $catalogue;
66 }
67 private function extract(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
68 {
69 $xliffVersion = XliffUtils::getVersionNumber($dom);
70 if ('1.2' === $xliffVersion) {
71 $this->extractXliff1($dom, $catalogue, $domain);
72 }
73 if ('2.0' === $xliffVersion) {
74 $this->extractXliff2($dom, $catalogue, $domain);
75 }
76 }
77 /**
78 * Extract messages and metadata from DOMDocument into a MessageCatalogue.
79 */
80 private function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
81 {
82 $xml = simplexml_import_dom($dom);
83 $encoding = $dom->encoding ? strtoupper($dom->encoding) : null;
84 $namespace = 'urn:oasis:names:tc:xliff:document:1.2';
85 $xml->registerXPathNamespace('xliff', $namespace);
86 foreach ($xml->xpath('//xliff:file') as $file) {
87 $fileAttributes = $file->attributes();
88 $file->registerXPathNamespace('xliff', $namespace);
89 foreach ($file->xpath('.//xliff:trans-unit') as $translation) {
90 $attributes = $translation->attributes();
91 if (!(isset($attributes['resname']) || isset($translation->source))) {
92 continue;
93 }
94 $source = (string) (isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source);
95 if (isset($translation->target) && 'needs-translation' === (string) $translation->target->attributes()['state'] && \in_array((string) $translation->target, [$source, (string) $translation->source], \true)) {
96 continue;
97 }
98 // If the xlf file has another encoding specified, try to convert it because
99 // simple_xml will always return utf-8 encoded values
100 $target = $this->utf8ToCharset((string) ($translation->target ?? $translation->source), $encoding);
101 $catalogue->set($source, $target, $domain);
102 $metadata = ['source' => (string) $translation->source, 'file' => ['original' => (string) $fileAttributes['original']]];
103 if ($notes = $this->parseNotesMetadata($translation->note, $encoding)) {
104 $metadata['notes'] = $notes;
105 }
106 if (isset($translation->target) && $translation->target->attributes()) {
107 $metadata['target-attributes'] = [];
108 foreach ($translation->target->attributes() as $key => $value) {
109 $metadata['target-attributes'][$key] = (string) $value;
110 }
111 }
112 if (isset($attributes['id'])) {
113 $metadata['id'] = (string) $attributes['id'];
114 }
115 $catalogue->setMetadata($source, $metadata, $domain);
116 }
117 }
118 }
119 private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
120 {
121 $xml = simplexml_import_dom($dom);
122 $encoding = $dom->encoding ? strtoupper($dom->encoding) : null;
123 $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:2.0');
124 foreach ($xml->xpath('//xliff:unit') as $unit) {
125 foreach ($unit->segment as $segment) {
126 $attributes = $unit->attributes();
127 $source = $attributes['name'] ?? $segment->source;
128 // If the xlf file has another encoding specified, try to convert it because
129 // simple_xml will always return utf-8 encoded values
130 $target = $this->utf8ToCharset((string) ($segment->target ?? $segment->source), $encoding);
131 $catalogue->set((string) $source, $target, $domain);
132 $metadata = [];
133 if (isset($segment->target) && $segment->target->attributes()) {
134 $metadata['target-attributes'] = [];
135 foreach ($segment->target->attributes() as $key => $value) {
136 $metadata['target-attributes'][$key] = (string) $value;
137 }
138 }
139 if (isset($unit->notes)) {
140 $metadata['notes'] = [];
141 foreach ($unit->notes->note as $noteNode) {
142 $note = [];
143 foreach ($noteNode->attributes() as $key => $value) {
144 $note[$key] = (string) $value;
145 }
146 $note['content'] = (string) $noteNode;
147 $metadata['notes'][] = $note;
148 }
149 }
150 $catalogue->setMetadata((string) $source, $metadata, $domain);
151 }
152 }
153 }
154 /**
155 * Convert a UTF8 string to the specified encoding.
156 */
157 private function utf8ToCharset(string $content, ?string $encoding = null): string
158 {
159 if ('UTF-8' !== $encoding && !empty($encoding)) {
160 return mb_convert_encoding($content, $encoding, 'UTF-8');
161 }
162 return $content;
163 }
164 private function parseNotesMetadata(?\SimpleXMLElement $noteElement = null, ?string $encoding = null): array
165 {
166 $notes = [];
167 if (null === $noteElement) {
168 return $notes;
169 }
170 /** @var \SimpleXMLElement $xmlNote */
171 foreach ($noteElement as $xmlNote) {
172 $noteAttributes = $xmlNote->attributes();
173 $note = ['content' => $this->utf8ToCharset((string) $xmlNote, $encoding)];
174 if (isset($noteAttributes['priority'])) {
175 $note['priority'] = (int) $noteAttributes['priority'];
176 }
177 if (isset($noteAttributes['from'])) {
178 $note['from'] = (string) $noteAttributes['from'];
179 }
180 $notes[] = $note;
181 }
182 return $notes;
183 }
184 private function isXmlString(string $resource): bool
185 {
186 return 0 === strpos($resource, '<?xml');
187 }
188 }
189