Completed
Push — master ( f4415a...651f7b )
by Anton
12s
created

Translator::translatePlural()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0175

Importance

Changes 0
Metric Value
cc 3
nc 4
nop 4
dl 0
loc 16
ccs 7
cts 8
cp 0.875
crap 3.0175
rs 9.7333
c 0
b 0
f 0
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 self
51
     */
52 604
    public function setDomain($domain)
53
    {
54 604
        $this->domain = $domain;
55 604
        return $this;
56
    }
57
58
    /**
59
     * Set locale
60
     *
61
     * @param  string $locale
62
     *
63
     * @return self
64
     */
65 604
    public function setLocale($locale)
66
    {
67 604
        $this->locale = $locale;
68 604
        return $this;
69
    }
70
71
    /**
72
     * Set path to l10n
73
     *
74
     * @param  string $path
75
     *
76
     * @return self
77
     */
78 604
    public function setPath($path)
79
    {
80 604
        $this->path = $path;
81 604
        return $this;
82
    }
83
84
    /**
85
     * Initialization
86
     *
87
     * @return void
88
     * @throws ConfigurationException
89
     * @throw  \Bluz\Config\ConfigException
90
     */
91 604
    public function init() : void
92
    {
93
        // Setup locale
94 604
        putenv('LC_ALL=' . $this->locale);
95 604
        putenv('LANG=' . $this->locale);
96 604
        putenv('LANGUAGE=' . $this->locale);
97
98
        // Windows workaround
99 604
        \defined('LC_MESSAGES') ?: \define('LC_MESSAGES', 6);
100
101 604
        setlocale(LC_MESSAGES, $this->locale);
102
103
        // For gettext only
104 604
        if (\function_exists('gettext')) {
105
            // Setup domain path
106 604
            $this->addTextDomain($this->domain, $this->path);
107
108
            // Setup default domain
109 604
            textdomain($this->domain);
110
        }
111 604
    }
112
113
    /**
114
     * Add text domain for gettext
115
     *
116
     * @param  string $domain of text for gettext setup
117
     * @param  string $path   on filesystem
118
     *
119
     * @return void
120
     * @throws ConfigurationException
121
     */
122 604
    public function addTextDomain($domain, $path) : void
123
    {
124
        // check path
125 604
        if (!is_dir($path)) {
126 1
            throw new ConfigurationException("Translator configuration path `$path` not found");
127
        }
128
129 604
        bindtextdomain($domain, $path);
130
131
        // @todo: hardcoded codeset
132 604
        bind_textdomain_codeset($domain, 'UTF-8');
133 604
    }
134
135
    /**
136
     * Translate message
137
     *
138
     * Simple example of usage
139
     * equal to gettext('Message')
140
     *
141
     *     Translator::translate('Message');
142
     *
143
     * Simple replace of one or more argument(s)
144
     * equal to sprintf(gettext('Message to %s'), 'Username')
145
     *
146
     *     Translator::translate('Message to %s', 'Username');
147
     *
148
     * @param  string   $message
149
     * @param  string[] ...$text
150
     *
151
     * @return string
152
     */
153 458
    public static function translate(string $message, ...$text) : string
154
    {
155 458
        if (empty($message)) {
156 1
            return $message;
157
        }
158
159 458
        if (\function_exists('gettext')) {
160 458
            $message = gettext($message);
161
        }
162
163 458
        if (\func_num_args() > 1) {
164 179
            $message = vsprintf($message, $text);
165
        }
166
167 458
        return $message;
168
    }
169
170
    /**
171
     * Translate plural form
172
     *
173
     * Example of usage plural form + sprintf
174
     * equal to sprintf(ngettext('%d comment', '%d comments', 4), 4)
175
     *     Translator::translatePlural('%d comment', '%d comments', 4)
176
     *
177
     * Example of usage plural form + sprintf
178
     * equal to sprintf(ngettext('%d comment', '%d comments', 4), 4, 'Topic')
179
     *     Translator::translatePlural('%d comment to %s', '%d comments to %s', 4, 'Topic')
180
     *
181
     * @param  string   $singular
182
     * @param  string   $plural
183
     * @param  integer  $number
184
     * @param  string[] ...$text
185
     *
186
     * @return string
187
     * @link   http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html
188
     */
189 2
    public static function translatePlural(string $singular, string $plural, $number, ...$text) : string
190
    {
191 2
        if (\function_exists('ngettext')) {
192 2
            $message = ngettext($singular, $plural, $number);
193
        } else {
194
            $message = $singular;
195
        }
196
197 2
        if (\func_num_args() > 3) {
198
            // first element is number
199 1
            array_unshift($text, $number);
200 1
            $message = vsprintf($message, $text);
201
        }
202
203 2
        return $message;
204
    }
205
}
206