blob: bb93435c30088ba3bf52d4994c76c7797180f9f2 [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\Translation;
13
14use Psr\Log\LoggerInterface;
15use Symfony\Component\Translation\Exception\InvalidArgumentException;
16use Symfony\Contracts\Translation\LocaleAwareInterface;
17use Symfony\Contracts\Translation\TranslatorInterface;
18
19/**
20 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
21 */
22class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface
23{
24 /**
25 * @var TranslatorInterface|TranslatorBagInterface
26 */
27 private $translator;
28
29 private $logger;
30
31 /**
32 * @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
33 */
34 public function __construct(TranslatorInterface $translator, LoggerInterface $logger)
35 {
36 if (!$translator instanceof TranslatorBagInterface || !$translator instanceof LocaleAwareInterface) {
37 throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', get_debug_type($translator)));
38 }
39
40 $this->translator = $translator;
41 $this->logger = $logger;
42 }
43
44 /**
45 * {@inheritdoc}
46 */
47 public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null)
48 {
49 $trans = $this->translator->trans($id = (string) $id, $parameters, $domain, $locale);
50 $this->log($id, $domain, $locale);
51
52 return $trans;
53 }
54
55 /**
56 * {@inheritdoc}
57 */
58 public function setLocale(string $locale)
59 {
60 $prev = $this->translator->getLocale();
61 $this->translator->setLocale($locale);
62 if ($prev === $locale) {
63 return;
64 }
65
66 $this->logger->debug(sprintf('The locale of the translator has changed from "%s" to "%s".', $prev, $locale));
67 }
68
69 /**
70 * {@inheritdoc}
71 */
72 public function getLocale()
73 {
74 return $this->translator->getLocale();
75 }
76
77 /**
78 * {@inheritdoc}
79 */
80 public function getCatalogue(string $locale = null)
81 {
82 return $this->translator->getCatalogue($locale);
83 }
84
85 /**
86 * {@inheritdoc}
87 */
88 public function getCatalogues(): array
89 {
90 return $this->translator->getCatalogues();
91 }
92
93 /**
94 * Gets the fallback locales.
95 *
96 * @return array The fallback locales
97 */
98 public function getFallbackLocales()
99 {
100 if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) {
101 return $this->translator->getFallbackLocales();
102 }
103
104 return [];
105 }
106
107 /**
108 * Passes through all unknown calls onto the translator object.
109 */
110 public function __call(string $method, array $args)
111 {
112 return $this->translator->{$method}(...$args);
113 }
114
115 /**
116 * Logs for missing translations.
117 */
118 private function log(string $id, ?string $domain, ?string $locale)
119 {
120 if (null === $domain) {
121 $domain = 'messages';
122 }
123
124 $catalogue = $this->translator->getCatalogue($locale);
125 if ($catalogue->defines($id, $domain)) {
126 return;
127 }
128
129 if ($catalogue->has($id, $domain)) {
130 $this->logger->debug('Translation use fallback catalogue.', ['id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()]);
131 } else {
132 $this->logger->warning('Translation not found.', ['id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()]);
133 }
134 }
135}