Passed
Push — master ( 97cf13...6b5bbb )
by Mihail
12:34
created

I18n::languages()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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