FallbackTranslator::transChoice()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 11
c 1
b 0
f 0
nc 6
nop 5
dl 0
loc 21
ccs 0
cts 12
cp 0
crap 20
rs 9.9
1
<?php
2
3
/*
4
 * This file is part of the PHP Translation package.
5
 *
6
 * (c) PHP Translation team <[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
12
namespace Translation\Bundle\Translator;
13
14
use Symfony\Component\Translation\MessageCatalogueInterface;
15
use Symfony\Component\Translation\TranslatorBagInterface;
16
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Translation\TranslatorInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use Symfony\Contracts\Translation\LocaleAwareInterface;
18
use Symfony\Contracts\Translation\TranslatorInterface as NewTranslatorInterface;
19
use Translation\Translator\Translator;
20
21
/**
22
 * This is a bridge between Symfony's translator service and Translation\Translator\Translator.
23
 *
24
 * @author Tobias Nyholm <[email protected]>
25
 */
26
final class FallbackTranslator implements TranslatorInterface
27
{
28
    /**
29
     * @var LegacyTranslatorInterface|NewTranslatorInterface
30
     */
31
    private $symfonyTranslator;
32
33
    /**
34
     * @var Translator
35
     */
36
    private $externalTranslator;
37
38
    /**
39
     * @var string
40
     */
41
    private $defaultLocale;
42
43
    /**
44
     * $symfonyTranslator param can't be type hinted as we have to deal with both LegacyTranslatorInterface & NewTranslatorInterface.
45
     * Once we won't support sf ^3.4 anymore, we will be able to type hint $symfonyTranslator with NewTranslatorInterface.
46
     *
47
     * @param LegacyTranslatorInterface|NewTranslatorInterface $symfonyTranslator
48
     */
49 2
    public function __construct(string $defaultLocale, $symfonyTranslator, Translator $externalTranslator)
50
    {
51 2
        if (!$symfonyTranslator instanceof LegacyTranslatorInterface && !$symfonyTranslator instanceof LocaleAwareInterface) {
52 1
            throw new \InvalidArgumentException('The given translator must implements LocaleAwareInterface.');
53
        }
54
55 1
        if (!$symfonyTranslator instanceof TranslatorBagInterface) {
56
            throw new \InvalidArgumentException('The given translator must implements TranslatorBagInterface.');
57
        }
58
59 1
        $this->symfonyTranslator = $symfonyTranslator;
60 1
        $this->externalTranslator = $externalTranslator;
61 1
        $this->defaultLocale = $defaultLocale;
62 1
    }
63
64
    /**
65
     * {@inheritdoc}
66
     */
67
    public function trans($id, array $parameters = [], $domain = null, $locale = null): string
68
    {
69
        $id = (string) $id;
70
        if (empty($domain)) {
71
            $domain = 'messages';
72
        }
73
74
        $catalogue = $this->getCatalogue($locale);
75
        if ($catalogue->defines($id, $domain)) {
76
            return $this->symfonyTranslator->trans($id, $parameters, $domain, $locale);
77
        }
78
79
        $locale = $catalogue->getLocale();
80
        if (empty($locale) || $locale === $this->defaultLocale) {
81
            // we cant do anything...
82
            return $id;
83
        }
84
85
        $orgString = $this->symfonyTranslator->trans($id, $parameters, $domain, $this->defaultLocale);
86
87
        return $this->translateWithSubstitutedParameters($orgString, $locale, $parameters);
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null): string
94
    {
95
        $id = (string) $id;
96
        if (empty($domain)) {
97
            $domain = 'messages';
98
        }
99
100
        $catalogue = $this->getCatalogue($locale);
101
        if ($catalogue->defines($id, $domain)) {
102
            return $this->symfonyTranslator->transChoice($id, $number, $parameters, $domain, $locale);
0 ignored issues
show
Bug introduced by
The method transChoice() does not exist on Symfony\Contracts\Translation\TranslatorInterface. Did you maybe mean trans()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

102
            return $this->symfonyTranslator->/** @scrutinizer ignore-call */ transChoice($id, $number, $parameters, $domain, $locale);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
103
        }
104
105
        $locale = $catalogue->getLocale();
106
        if ($locale === $this->defaultLocale) {
107
            // we cant do anything...
108
            return $id;
109
        }
110
111
        $orgString = $this->symfonyTranslator->transChoice($id, $number, $parameters, $domain, $this->defaultLocale);
112
113
        return $this->translateWithSubstitutedParameters($orgString, $locale, $parameters);
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119
    public function setLocale($locale): void
120
    {
121
        $this->symfonyTranslator->setLocale($locale);
0 ignored issues
show
Bug introduced by
The method setLocale() does not exist on Symfony\Contracts\Translation\TranslatorInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Symfony\Component\Transl...oLocalizationTranslator. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

121
        $this->symfonyTranslator->/** @scrutinizer ignore-call */ 
122
                                  setLocale($locale);
Loading history...
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     */
127
    public function getLocale(): string
128
    {
129
        return $this->symfonyTranslator->getLocale();
0 ignored issues
show
Bug introduced by
The method getLocale() does not exist on Symfony\Contracts\Translation\TranslatorInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Symfony\Component\Transl...oLocalizationTranslator. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

129
        return $this->symfonyTranslator->/** @scrutinizer ignore-call */ getLocale();
Loading history...
130
    }
131
132
    /**
133
     * {@inheritdoc}
134
     */
135
    public function getCatalogue($locale = null): MessageCatalogueInterface
136
    {
137
        return $this->symfonyTranslator->getCatalogue($locale);
0 ignored issues
show
Bug introduced by
The method getCatalogue() does not exist on Symfony\Contracts\Translation\TranslatorInterface. It seems like you code against a sub-type of Symfony\Contracts\Translation\TranslatorInterface such as Symfony\Component\Translation\Translator or Symfony\Component\Transl...DataCollectorTranslator or Symfony\Component\Translation\LoggingTranslator. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

137
        return $this->symfonyTranslator->/** @scrutinizer ignore-call */ getCatalogue($locale);
Loading history...
138
    }
139
140
    /**
141
     * Passes through all unknown calls onto the translator object.
142
     */
143
    public function __call(string $method, array $args)
144
    {
145
        return \call_user_func_array([$this->symfonyTranslator, $method], $args);
146
    }
147
148
    /**
149
     * @param string $orgString This is the string in the default locale. It has the values of $parameters in the string already.
150
     * @param string $locale    you wan to translate to
151
     */
152 1
    private function translateWithSubstitutedParameters(string $orgString, string $locale, array $parameters): string
153
    {
154
        // Replace parameters
155 1
        $replacements = [];
156 1
        foreach ($parameters as $placeholder => $nonTranslatableValue) {
157 1
            $replacements[(string) $nonTranslatableValue] = \sha1($placeholder);
158
        }
159
160 1
        $replacedString = \str_replace(\array_keys($replacements), \array_values($replacements), $orgString);
161 1
        $translatedString = $this->externalTranslator->translate($replacedString, $this->defaultLocale, $locale);
162
163 1
        if (null === $translatedString) {
164
            // Could not be translated
165
            return $orgString;
166
        }
167
168 1
        return \str_replace(\array_values($replacements), \array_keys($replacements), $translatedString);
169
    }
170
}
171