Passed
Push — master ( bfa12e...cd3045 )
by Alexander
02:21
created

Translator::getSimpleMessageFormatter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Translator;
6
7
use Psr\EventDispatcher\EventDispatcherInterface;
8
use RuntimeException;
9
use Yiisoft\I18n\Locale;
10
use Yiisoft\Translator\Event\MissingTranslationCategoryEvent;
11
use Yiisoft\Translator\Event\MissingTranslationEvent;
12
13
/**
14
 * Translator translates a message into the specified language.
15
 */
16
final class Translator implements TranslatorInterface
17
{
18
    private string $defaultCategory = 'app';
19
    private string $locale;
20
    private ?string $fallbackLocale;
21
    private ?EventDispatcherInterface $eventDispatcher;
22
23
    /**
24
     * @var CategorySource[][] Array of category message sources indexed by category names.
25
     */
26
    private array $categorySources = [];
27
28
    private ?SimpleMessageFormatter $simpleMessageFormatter = null;
29
30
    /**
31
     * @param string $locale Default locale to use if locale is not specified explicitly.
32
     * @param string|null $fallbackLocale Locale to use if message for the locale specified was not found. Null for none.
33
     * @param EventDispatcherInterface|null $eventDispatcher Event dispatcher for translation events. Null for none.
34
     */
35 54
    public function __construct(
36
        string $locale,
37
        ?string $fallbackLocale = null,
38
        ?EventDispatcherInterface $eventDispatcher = null
39
    ) {
40 54
        $this->locale = $locale;
41 54
        $this->fallbackLocale = $fallbackLocale;
42 54
        $this->eventDispatcher = $eventDispatcher;
43
    }
44
45 52
    public function addCategorySource(CategorySource $category): void
46
    {
47 52
        if (isset($this->categorySources[$category->getName()])) {
48 14
            $this->categorySources[$category->getName()][] = $category;
49
        } else {
50 52
            $this->categorySources[$category->getName()] = [$category];
51
        }
52
    }
53
54 15
    public function addCategorySources(array $categories): void
55
    {
56 15
        foreach ($categories as $category) {
57 15
            $this->addCategorySource($category);
58
        }
59
    }
60
61 3
    public function setLocale(string $locale): void
62
    {
63 3
        $this->locale = $locale;
64
    }
65
66 3
    public function getLocale(): string
67
    {
68 3
        return $this->locale;
69
    }
70
71 52
    public function translate(
72
        string $id,
73
        array $parameters = [],
74
        string $category = null,
75
        string $locale = null
76
    ): string {
77 52
        $locale = $locale ?? $this->locale;
78
79 52
        $category = $category ?? $this->defaultCategory;
80
81 52
        if (empty($this->categorySources[$category])) {
82 3
            if ($this->eventDispatcher !== null) {
83 2
                $this->eventDispatcher->dispatch(new MissingTranslationCategoryEvent($category));
84
            }
85 3
            return $this->getSimpleMessageFormatter()->format($id, $parameters);
86
        }
87
88 49
        return $this->translateUsingCategorySources($id, $parameters, $category, $locale);
89
    }
90
91
    /**
92
     * @psalm-immutable
93
     */
94 2
    public function withCategory(string $category): self
95
    {
96 2
        if (!isset($this->categorySources[$category])) {
97 1
            throw new RuntimeException('Category with name "' . $category . '" does not exist.');
98
        }
99
100 1
        $new = clone $this;
101 1
        $new->defaultCategory = $category;
102 1
        return $new;
103
    }
104
105 1
    public function withLocale(string $locale): self
106
    {
107 1
        $new = clone $this;
108 1
        $new->setLocale($locale);
109 1
        return $new;
110
    }
111
112 49
    private function translateUsingCategorySources(
113
        string $id,
114
        array $parameters,
115
        string $category,
116
        string $locale
117
    ): string {
118 49
        $sourceCategory = end($this->categorySources[$category]);
119
        do {
120 49
            $message = $sourceCategory->getMessage($id, $locale, $parameters);
121
122 49
            if ($message !== null) {
123 36
                return $sourceCategory->format($message, $parameters, $locale);
124
            }
125
126 31
            if ($this->eventDispatcher !== null) {
127 12
                $this->eventDispatcher->dispatch(new MissingTranslationEvent($sourceCategory->getName(), $locale, $id));
128
            }
129 31
        } while (($sourceCategory = prev($this->categorySources[$category])) !== false);
130
131 26
        $localeObject = new Locale($locale);
132 26
        $fallback = $localeObject->fallbackLocale();
133
134 26
        if ($fallback->asString() !== $localeObject->asString()) {
135 14
            return $this->translateUsingCategorySources($id, $parameters, $category, $fallback->asString());
136
        }
137
138 19
        if (!empty($this->fallbackLocale)) {
139 10
            $fallbackLocaleObject = (new Locale($this->fallbackLocale))->fallbackLocale();
140 10
            if ($fallbackLocaleObject->asString() !== $localeObject->asString()) {
141 9
                return $this->translateUsingCategorySources($id, $parameters, $category, $fallbackLocaleObject->asString());
142
            }
143
        }
144
145 13
        $categorySource = end($this->categorySources[$category]);
146 13
        return $categorySource->format($id, $parameters, $locale);
147
    }
148
149 3
    private function getSimpleMessageFormatter(): SimpleMessageFormatter
150
    {
151 3
        if ($this->simpleMessageFormatter === null) {
152 3
            $this->simpleMessageFormatter = new SimpleMessageFormatter();
153
        }
154 3
        return $this->simpleMessageFormatter;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->simpleMessageFormatter could return the type null which is incompatible with the type-hinted return Yiisoft\Translator\SimpleMessageFormatter. Consider adding an additional type-check to rule them out.
Loading history...
155
    }
156
}
157