vendor/symfony/translation/Loader/XliffFileLoader.php line 84

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