src/Twig/TransExtension.php line 25

Open in your IDE?
  1. <?php
  2. namespace App\Twig;
  3. use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor;
  4. use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;
  5. use Symfony\Bridge\Twig\TokenParser\TransDefaultDomainTokenParser;
  6. use Symfony\Bridge\Twig\TokenParser\TransTokenParser;
  7. use Symfony\Component\Security\Core\Security;
  8. use Symfony\Component\Translation\TranslatableMessage;
  9. use Symfony\Contracts\Translation\TranslatableInterface;
  10. use Symfony\Contracts\Translation\TranslatorInterface;
  11. use Symfony\Contracts\Translation\TranslatorTrait;
  12. use Twig\Environment;
  13. use Twig\Extension\AbstractExtension;
  14. use Twig\TwigFilter;
  15. use Twig\TwigFunction;
  16. class TransExtension extends AbstractExtension
  17. {
  18. private $translator;
  19. private $translationNodeVisitor;
  20. private $security;
  21. public function __construct(TranslatorInterface $translator = null, TranslationNodeVisitor $translationNodeVisitor = null, Security $security, Environment $twig)
  22. {
  23. $this->translator = $translator;
  24. $this->translationNodeVisitor = $translationNodeVisitor;
  25. $this->security = $security;
  26. $this->twig = $twig;
  27. }
  28. /**
  29. * {@inheritdoc}
  30. */
  31. public function getFunctions(): array
  32. {
  33. return [
  34. new TwigFunction('t', [$this, 'createTranslatable']),
  35. ];
  36. }
  37. /**
  38. * {@inheritdoc}
  39. */
  40. public function getFilters(): array
  41. {
  42. return [
  43. new TwigFilter('admintrans', [$this, 'trans']),
  44. ];
  45. }
  46. /**
  47. * {@inheritdoc}
  48. */
  49. public function getTokenParsers(): array
  50. {
  51. return [
  52. // {% trans %}Symfony is great!{% endtrans %}
  53. new TransTokenParser(),
  54. // {% trans_default_domain "foobar" %}
  55. new TransDefaultDomainTokenParser(),
  56. ];
  57. }
  58. /**
  59. * {@inheritdoc}
  60. */
  61. public function getNodeVisitors(): array
  62. {
  63. return [$this->getTranslationNodeVisitor(), new TranslationDefaultDomainNodeVisitor()];
  64. }
  65. public function getTranslationNodeVisitor(): TranslationNodeVisitor
  66. {
  67. return $this->translationNodeVisitor ?: $this->translationNodeVisitor = new TranslationNodeVisitor();
  68. }
  69. /**
  70. * @param string|\Stringable|TranslatableInterface|null $message
  71. * @param array|string $arguments Can be the locale as a string when $message is a TranslatableInterface
  72. */
  73. public function trans($message, $arguments = [], string $domain = null, string $locale = null, int $count = null): string
  74. {
  75. if ($message instanceof TranslatableInterface) {
  76. if ([] !== $arguments && !\is_string($arguments)) {
  77. 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)));
  78. }
  79. return $message->trans($this->getTranslator(), $locale ?? (\is_string($arguments) ? $arguments : null));
  80. }
  81. if (!\is_array($arguments)) {
  82. 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)));
  83. }
  84. if ('' === $message = (string)$message) {
  85. return '';
  86. }
  87. if (null !== $count) {
  88. $arguments['%count%'] = $count;
  89. }
  90. $user = $this->security->getUser();
  91. $isAdmin = !is_null($user) && in_array('ROLE_ADMIN', $user->getRoles());
  92. return $this->getTranslator()->trans($message, $arguments, $domain, $locale) . ($isAdmin ? $this->twig->render('components/text-edit-markup.html.twig', [
  93. 'message' => $message
  94. ]) : '');
  95. }
  96. public function getTranslator(): TranslatorInterface
  97. {
  98. if (null === $this->translator) {
  99. if (!interface_exists(TranslatorInterface::class)) {
  100. throw new \LogicException(sprintf('You cannot use the "%s" if the Translation Contracts are not available. Try running "composer require symfony/translation".', __CLASS__));
  101. }
  102. $this->translator = new class() implements TranslatorInterface {
  103. use TranslatorTrait;
  104. };
  105. }
  106. return $this->translator;
  107. }
  108. public function createTranslatable(string $message, array $parameters = [], string $domain = null): TranslatableMessage
  109. {
  110. if (!class_exists(TranslatableMessage::class)) {
  111. throw new \LogicException(sprintf('You cannot use the "%s" as the Translation Component is not installed. Try running "composer require symfony/translation".', __CLASS__));
  112. }
  113. return new TranslatableMessage($message, $parameters, $domain);
  114. }
  115. }