Completed
Push — master ( 929e4f...acab5f )
by Anton
07:41
created

Translator   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 180
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 97.56%

Importance

Changes 0
Metric Value
dl 0
loc 180
ccs 40
cts 41
cp 0.9756
rs 10
c 0
b 0
f 0
wmc 15
lcom 1
cbo 2

7 Methods

Rating   Name   Duplication   Size   Complexity  
A setDomain() 0 4 1
A setLocale() 0 4 1
A setPath() 0 4 1
A init() 0 21 3
A addTextDomain() 0 12 2
A translate() 0 16 4
A translatePlural() 0 16 3
1
<?php
2
/**
3
 * Bluz Framework Component
4
 *
5
 * @copyright Bluz PHP Team
6
 * @link      https://github.com/bluzphp/framework
7
 */
8
9
declare(strict_types=1);
10
11
namespace Bluz\Translator;
12
13
use Bluz\Common\Exception\ConfigurationException;
14
use Bluz\Common\Options;
15
16
/**
17
 * Translator based on gettext library
18
 *
19
 * @package  Bluz\Translator
20
 * @author   Anton Shevchuk
21
 * @link     https://github.com/bluzphp/framework/wiki/Translator
22
 */
23
class Translator
24
{
25
    use Options;
26
27
    /**
28
     * Locale
29
     *
30
     * @var string
31
     * @link http://www.loc.gov/standards/iso639-2/php/code_list.php
32
     */
33
    protected $locale = 'en_US';
34
35
    /**
36
     * @var string text domain
37
     */
38
    protected $domain = 'messages';
39
40
    /**
41
     * @var string path to text domain files
42
     */
43
    protected $path;
44
45
    /**
46
     * Set domain
47
     *
48
     * @param  string $domain
49
     *
50
     * @return void
51
     */
52 604
    public function setDomain($domain): void
53
    {
54 604
        $this->domain = $domain;
55 604
    }
56
57
    /**
58
     * Set locale
59
     *
60
     * @param  string $locale
61
     *
62
     * @return void
63
     */
64 604
    public function setLocale($locale): void
65
    {
66 604
        $this->locale = $locale;
67 604
    }
68
69
    /**
70
     * Set path to l10n
71
     *
72
     * @param  string $path
73
     *
74
     * @return void
75
     */
76 604
    public function setPath($path): void
77
    {
78 604
        $this->path = $path;
79 604
    }
80
81
    /**
82
     * Initialization
83
     *
84
     * @return void
85
     * @throws ConfigurationException
86
     * @throw  \Bluz\Config\ConfigException
87
     */
88 604
    public function init(): void
89
    {
90
        // Setup locale
91 604
        putenv('LC_ALL=' . $this->locale);
92 604
        putenv('LANG=' . $this->locale);
93 604
        putenv('LANGUAGE=' . $this->locale);
94
95
        // Windows workaround
96 604
        \defined('LC_MESSAGES') ?: \define('LC_MESSAGES', 6);
97
98 604
        setlocale(LC_MESSAGES, $this->locale);
99
100
        // For gettext only
101 604
        if (\function_exists('gettext')) {
102
            // Setup domain path
103 604
            $this->addTextDomain($this->domain, $this->path);
104
105
            // Setup default domain
106 604
            textdomain($this->domain);
107
        }
108 604
    }
109
110
    /**
111
     * Add text domain for gettext
112
     *
113
     * @param  string $domain of text for gettext setup
114
     * @param  string $path   on filesystem
115
     *
116
     * @return void
117
     * @throws ConfigurationException
118
     */
119 604
    public function addTextDomain($domain, $path): void
120
    {
121
        // check path
122 604
        if (!is_dir($path)) {
123 1
            throw new ConfigurationException("Translator configuration path `$path` not found");
124
        }
125
126 604
        bindtextdomain($domain, $path);
127
128
        // @todo: hardcoded codeset
129 604
        bind_textdomain_codeset($domain, 'UTF-8');
130 604
    }
131
132
    /**
133
     * Translate message
134
     *
135
     * Simple example of usage
136
     * equal to gettext('Message')
137
     *
138
     *     Translator::translate('Message');
139
     *
140
     * Simple replace of one or more argument(s)
141
     * equal to sprintf(gettext('Message to %s'), 'Username')
142
     *
143
     *     Translator::translate('Message to %s', 'Username');
144
     *
145
     * @param  string   $message
146
     * @param  string[] ...$text
147
     *
148
     * @return string
149
     */
150 458
    public static function translate(string $message, ...$text): string
151
    {
152 458
        if (empty($message)) {
153 1
            return $message;
154
        }
155
156 458
        if (\function_exists('gettext')) {
157 458
            $message = gettext($message);
158
        }
159
160 458
        if (\func_num_args() > 1) {
161 179
            $message = vsprintf($message, $text);
162
        }
163
164 458
        return $message;
165
    }
166
167
    /**
168
     * Translate plural form
169
     *
170
     * Example of usage plural form + sprintf
171
     * equal to sprintf(ngettext('%d comment', '%d comments', 4), 4)
172
     *     Translator::translatePlural('%d comment', '%d comments', 4)
173
     *
174
     * Example of usage plural form + sprintf
175
     * equal to sprintf(ngettext('%d comment', '%d comments', 4), 4, 'Topic')
176
     *     Translator::translatePlural('%d comment to %s', '%d comments to %s', 4, 'Topic')
177
     *
178
     * @param  string   $singular
179
     * @param  string   $plural
180
     * @param  integer  $number
181
     * @param  string[] ...$text
182
     *
183
     * @return string
184
     * @link   http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html
185
     */
186 2
    public static function translatePlural(string $singular, string $plural, $number, ...$text): string
187
    {
188 2
        if (\function_exists('ngettext')) {
189 2
            $message = ngettext($singular, $plural, $number);
190
        } else {
191
            $message = $singular;
192
        }
193
194 2
        if (\func_num_args() > 3) {
195
            // first element is number
196 1
            array_unshift($text, $number);
197 1
            $message = vsprintf($message, $text);
198
        }
199
200 2
        return $message;
201
    }
202
}
203