Passed
Push — master ( 2b1ac9...97cf13 )
by Mihail
02:13
created

I18n::info()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 10
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 14
ccs 10
cts 10
cp 1
crap 2
rs 9.9332
1
<?php declare(strict_types=1);
2
3
namespace Koded\I18n;
4
5
use Koded\Stdlib\Config;
6
use Throwable;
7
use function ini_set;
8
use function strtr;
9
use function vsprintf;
10
11
interface I18nFormatter
12
{
13
    /**
14
     * Message formatter for argument replacement in the message.
15
     *
16
     * @param string $string
17
     * @param array $arguments
18
     * @return string The message with applied arguments (if any)
19
     */
20
    public function format(string $string, array $arguments): string;
21
}
22
23
final class StrtrFormatter implements I18nFormatter
24
{
25 1
    public function format(string $string, array $arguments): string
26
    {
27 1
        return $arguments ? strtr($string, $arguments) : $string;
28
    }
29
}
30
31
final class DefaultFormatter implements I18nFormatter
32
{
33 8
    public function format(string $string, array $arguments): string
34
    {
35 8
        return $arguments ? vsprintf($string, $arguments) : $string;
36
    }
37
}
38
39
class I18n
40
{
41
    public const DEFAULT_LOCALE = 'en_US';
42
43
    /*
44
     * Default configuration parameters for all catalogs.
45
     * Values are taken by the explicitly set default locale,
46
     * or the first loaded catalog instance.
47
     */
48
    private static ?string $catalog = null;
49
    private static ?string $formatter = null;
50
    private static ?string $directory = null;
51
    private static ?string $locale = null;
52
53
    /** @var array<string, I18nCatalog> */
54
    private static array $catalogs = [];
55
56
    // @codeCoverageIgnoreStart
57
    private function __construct() {}
58
    // @codeCoverageIgnoreEnd
59
60 9
    public static function translate(
61
        string $string,
62
        array  $arguments = [],
63
        string $locale = null): string
64
    {
65
        try {
66 9
            return self::$catalogs[$locale]->translate('messages', $string, $arguments);
67 9
        } catch (Throwable) {
68 9
            self::registerCatalog($locale ??= self::locale());
69 9
            return self::$catalogs[$locale]->translate('messages', $string, $arguments);
70
        }
71
    }
72
73 6
    public static function locale(): string
74
    {
75 6
        return self::$locale ??= I18nCatalog::normalizeLocale(\Locale::getDefault());
76
    }
77
78
    /**
79
     * @return array{string, I18nCatalog}
80
     */
81 11
    public static function catalogs(): array
82
    {
83 11
        return self::$catalogs;
84
    }
85
86
    /**
87
     * @return array{locale:string, catalogs:<string, array{class: string, formatter:string, dir:string, locale:string}>}
88
     */
89 1
    public static function info(): array
90
    {
91 1
        $catalogs = [];
92 1
        foreach (self::$catalogs as $locale => $instance) {
93 1
            $catalogs[$locale] = [
94 1
                'class' => $instance::class,
95 1
                'formatter' => $instance->formatter()::class,
96 1
                'dir' => $instance->directory(),
97 1
                'locale' => $instance->locale(),
98
            ];
99
        }
100
        return [
101 1
            'locale' => self::$locale,
102 1
            'catalogs' => $catalogs,
103
        ];
104
    }
105
106 17
    public static function register(
107
        I18nCatalog $catalog,
108
        bool        $asDefault = false): void
109
    {
110 17
        $locale = $catalog->locale();
111 17
        if ($asDefault || empty(self::$catalogs)) {
112 17
            self::setDefaultLocale($locale);
113 17
            self::$directory = $catalog->directory();
114 17
            self::$formatter = $catalog->formatter()::class;
115 17
            self::$catalog = $catalog::class;
116
        }
117 17
        self::$catalogs[$locale] = $catalog;
118 17
    }
119
120 17
    public static function flush(): void
121
    {
122 17
        self::$catalogs = [];
123 17
        self::$directory = null;
124 17
        self::$formatter = null;
125 17
        self::$catalog = null;
126 17
        self::$locale = null;
127 17
        ini_set('intl.default_locale', '');
128 17
        \Locale::setDefault('');
129 17
    }
130
131 9
    private static function registerCatalog(string $locale): void
132
    {
133 9
        if (isset(self::$catalogs[$locale])) {
134 5
            return;
135
        }
136 5
        self::$catalogs[$locale] = I18nCatalog::new((new Config)
137 5
            ->set('translation.locale', $locale)
138 5
            ->set('translation.dir', self::$directory)
139 5
            ->set('translation.formatter', self::$formatter)
140 5
            ->set('translation.catalog', self::$catalog)
141
        );
142 5
    }
143
144 17
    private static function setDefaultLocale(string $locale): void
145
    {
146 17
        self::$locale = $locale;
147 17
        ini_set('intl.default_locale', $locale);
148 17
        \Locale::setDefault($locale);
149 17
    }
150
}
151