vendor/symfony/twig-bridge/Extension/TranslationExtension.php line 125

  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  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\Bridge\Twig\Extension;
  11. use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor;
  12. use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;
  13. use Symfony\Bridge\Twig\TokenParser\TransDefaultDomainTokenParser;
  14. use Symfony\Bridge\Twig\TokenParser\TransTokenParser;
  15. use Symfony\Component\Translation\TranslatableMessage;
  16. use Symfony\Contracts\Translation\TranslatableInterface;
  17. use Symfony\Contracts\Translation\TranslatorInterface;
  18. use Symfony\Contracts\Translation\TranslatorTrait;
  19. use Twig\Extension\AbstractExtension;
  20. use Twig\TwigFilter;
  21. use Twig\TwigFunction;
  22. // Help opcache.preload discover always-needed symbols
  23. class_exists(TranslatorInterface::class);
  24. class_exists(TranslatorTrait::class);
  25. /**
  26.  * Provides integration of the Translation component with Twig.
  27.  *
  28.  * @author Fabien Potencier <fabien@symfony.com>
  29.  */
  30. final class TranslationExtension extends AbstractExtension
  31. {
  32.     private ?TranslatorInterface $translator;
  33.     private ?TranslationNodeVisitor $translationNodeVisitor;
  34.     public function __construct(TranslatorInterface $translator nullTranslationNodeVisitor $translationNodeVisitor null)
  35.     {
  36.         $this->translator $translator;
  37.         $this->translationNodeVisitor $translationNodeVisitor;
  38.     }
  39.     public function getTranslator(): TranslatorInterface
  40.     {
  41.         if (null === $this->translator) {
  42.             if (!interface_exists(TranslatorInterface::class)) {
  43.                 throw new \LogicException(sprintf('You cannot use the "%s" if the Translation Contracts are not available. Try running "composer require symfony/translation".'__CLASS__));
  44.             }
  45.             $this->translator = new class() implements TranslatorInterface {
  46.                 use TranslatorTrait;
  47.             };
  48.         }
  49.         return $this->translator;
  50.     }
  51.     public function getFunctions(): array
  52.     {
  53.         return [
  54.             new TwigFunction('t'$this->createTranslatable(...)),
  55.         ];
  56.     }
  57.     public function getFilters(): array
  58.     {
  59.         return [
  60.             new TwigFilter('trans'$this->trans(...)),
  61.         ];
  62.     }
  63.     public function getTokenParsers(): array
  64.     {
  65.         return [
  66.             // {% trans %}Symfony is great!{% endtrans %}
  67.             new TransTokenParser(),
  68.             // {% trans_default_domain "foobar" %}
  69.             new TransDefaultDomainTokenParser(),
  70.         ];
  71.     }
  72.     public function getNodeVisitors(): array
  73.     {
  74.         return [$this->getTranslationNodeVisitor(), new TranslationDefaultDomainNodeVisitor()];
  75.     }
  76.     public function getTranslationNodeVisitor(): TranslationNodeVisitor
  77.     {
  78.         return $this->translationNodeVisitor ?: $this->translationNodeVisitor = new TranslationNodeVisitor();
  79.     }
  80.     /**
  81.      * @param array|string $arguments Can be the locale as a string when $message is a TranslatableInterface
  82.      */
  83.     public function trans(string|\Stringable|TranslatableInterface|null $message, array|string $arguments = [], string $domain nullstring $locale nullint $count null): string
  84.     {
  85.         if ($message instanceof TranslatableInterface) {
  86.             if ([] !== $arguments && !\is_string($arguments)) {
  87.                 throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be a locale passed as a string when the message is a "%s", "%s" given.'__METHOD__TranslatableInterface::class, get_debug_type($arguments)));
  88.             }
  89.             if ($message instanceof TranslatableMessage && '' === $message->getMessage()) {
  90.                 return '';
  91.             }
  92.             return $message->trans($this->getTranslator(), $locale ?? (\is_string($arguments) ? $arguments null));
  93.         }
  94.         if (!\is_array($arguments)) {
  95.             throw new \TypeError(sprintf('Unless the message is a "%s", argument 2 passed to "%s()" must be an array of parameters, "%s" given.'TranslatableInterface::class, __METHOD__get_debug_type($arguments)));
  96.         }
  97.         if ('' === $message = (string) $message) {
  98.             return '';
  99.         }
  100.         if (null !== $count) {
  101.             $arguments['%count%'] = $count;
  102.         }
  103.         return $this->getTranslator()->trans($message$arguments$domain$locale);
  104.     }
  105.     public function createTranslatable(string $message, array $parameters = [], string $domain null): TranslatableMessage
  106.     {
  107.         if (!class_exists(TranslatableMessage::class)) {
  108.             throw new \LogicException(sprintf('You cannot use the "%s" as the Translation Component is not installed. Try running "composer require symfony/translation".'__CLASS__));
  109.         }
  110.         return new TranslatableMessage($message$parameters$domain);
  111.     }
  112. }