Passed
Pull Request — master (#31)
by Alexander
03:04 queued 51s
created

Translator::withCategory()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Translator;
6
7
use Psr\EventDispatcher\EventDispatcherInterface;
8
use Yiisoft\I18n\Locale;
9
use Yiisoft\Translator\Event\MissingTranslationCategoryEvent;
10
use Yiisoft\Translator\Event\MissingTranslationEvent;
11
12
/**
13
 * Translator translates a message into the specified language.
14
 */
15
class Translator implements TranslatorInterface
16
{
17
    private string $defaultCategory;
18
    private string $locale;
19
    private ?EventDispatcherInterface $eventDispatcher;
20
    private ?string $fallbackLocale;
21
    /**
22
     * @var Category[]
23
     */
24
    private array $categories = [];
25
26
    /**
27
     * @param Category $defaultCategory Default category to use if category is not specified explicitly.
28
     * @param string $locale Default locale to use if locale is not specified explicitly.
29
     * @param string|null $fallbackLocale Locale to use if message for the locale specified was not found. Null for none.
30
     * @param EventDispatcherInterface|null $eventDispatcher Event dispatcher for translation events. Null for none.
31
     */
32 39
    public function __construct(
33
        Category $defaultCategory,
34
        string $locale,
35
        ?string $fallbackLocale = null,
36
        ?EventDispatcherInterface $eventDispatcher = null
37
    ) {
38 39
        $this->defaultCategory = $defaultCategory->getName();
39 39
        $this->eventDispatcher = $eventDispatcher;
40 39
        $this->locale = $locale;
41 39
        $this->fallbackLocale = $fallbackLocale;
42
43 39
        $this->addCategorySource($defaultCategory);
44 39
    }
45
46 39
    public function addCategorySource(Category $category): void
47
    {
48 39
        if (isset($this->categories[$category->getName()])) {
49 1
            throw new \RuntimeException('Category "' . $category->getName() . '" already exists.');
50
        }
51 39
        $this->categories[$category->getName()] = $category;
52 39
    }
53
54
    /**
55
     * @param Category[] $categories
56
     */
57 1
    public function addCategorySources(array $categories): void
58
    {
59 1
        foreach ($categories as $category) {
60 1
            $this->addCategorySource($category);
61
        }
62 1
    }
63
64 3
    public function setLocale(string $locale): void
65
    {
66 3
        $this->locale = $locale;
67 3
    }
68
69 3
    public function getLocale(): string
70
    {
71 3
        return $this->locale;
72
    }
73
74 36
    public function translate(
75
        string $id,
76
        array $parameters = [],
77
        string $category = null,
78
        string $locale = null
79
    ): string {
80 36
        $locale = $locale ?? $this->locale;
81
82 36
        $category = $category ?? $this->defaultCategory;
83
84 36
        if (empty($this->categories[$category])) {
85 1
            if ($this->eventDispatcher !== null) {
86 1
                $this->eventDispatcher->dispatch(new MissingTranslationCategoryEvent($category));
87
            }
88 1
            return $id;
89
        }
90
91 35
        $sourceCategory = $this->categories[$category];
92 35
        $message = $sourceCategory->getMessage($id, $locale, $parameters);
93
94 35
        if ($message === null) {
95 18
            if ($this->eventDispatcher !== null) {
96 12
                $this->eventDispatcher->dispatch(new MissingTranslationEvent($sourceCategory->getName(), $locale, $id));
97
            }
98
99 18
            $localeObject = new Locale($locale);
100 18
            $fallback = $localeObject->fallbackLocale();
101
102 18
            if ($fallback->asString() !== $localeObject->asString()) {
103 11
                return $this->translate($id, $parameters, $category, $fallback->asString());
104
            }
105
106 12
            if (!empty($this->fallbackLocale)) {
107 3
                $fallbackLocaleObject = (new Locale($this->fallbackLocale))->fallbackLocale();
108 3
                if ($fallbackLocaleObject->asString() !== $localeObject->asString()) {
109 3
                    return $this->translate($id, $parameters, $category, $fallbackLocaleObject->asString());
110
                }
111
            }
112
113 9
            $message = $id;
114
        }
115
116 35
        return $sourceCategory->format($message, $parameters, $locale);
117
    }
118
119 2
    public function withCategory(string $category): self
120
    {
121 2
        if (!isset($this->categories[$category])) {
122 1
            throw new \RuntimeException('Category with name "' . $category . '" does not exist.');
123
        }
124
125 1
        $new = clone $this;
126 1
        $new->defaultCategory = $category;
127 1
        return $new;
128
    }
129
130 1
    public function withLocale(string $locale): self
131
    {
132 1
        $new = clone $this;
133 1
        $new->setLocale($locale);
134 1
        return $new;
135
    }
136
}
137