Skip to content

Commit d45fb9d

Browse files
committed
implemented domains
1 parent bec758a commit d45fb9d

5 files changed

Lines changed: 139 additions & 100 deletions

File tree

README.md

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@ $t->loadTranslations('locales/gl.php');
4343
echo $t->gettext('apple'); //echoes "Mazá"
4444

4545
//Use the global functions:
46-
__currentTranslator($t);
46+
Gettext\Translator::initGettextFunctions($t);
4747

48-
//Use it:
4948
echo __('apple'); //echoes "Mazá"
5049

5150
__e('apple'); //echoes "Mazá"
@@ -193,8 +192,8 @@ echo $t->gettext('apple');
193192
To ease the use of translations in your php templates, you can use the provided functions:
194193

195194
```php
196-
//First set the translator instance as current translator:
197-
__currentTranslator($t);
195+
//First load the gettext functions and passing the instance
196+
Translator::initGettextFunctions($t);
198197

199198
echo __('apple'); //Returns Mazá
200199

@@ -265,7 +264,3 @@ Note, if the second argument is not defined, the default is `self::MERGE_ADD | s
265264
* [leom](https://github.com/leom) (Jed fixes)
266265
* [eusonlito](https://github.com/eusonlito) (Blade extractor)
267266
* [vvh-empora](https://github.com/vvh-empora) (fixes)
268-
269-
## TO-DO
270-
271-
* Working with domains

src/Translator.php

Lines changed: 42 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@ class Translator
77
{
88
public static $current;
99

10-
private $dictionary = array();
1110
private $domain;
11+
private $dictionary = array();
1212
private $context_glue = "\004";
13-
private $pluralCount = 2;
14-
private $pluralCode = 'return ($n != 1);';
15-
private $pluralFunction;
13+
private $plurals = array();
1614

1715

1816
/**
@@ -38,61 +36,51 @@ public static function initGettextFunctions(Translator $translator)
3836
public function loadTranslations($translations)
3937
{
4038
if (is_object($translations) && $translations instanceof Translations) {
41-
$this->loadArray(PhpArray::toArray($translations));
39+
$translations = PhpArray::toArray($translations);
4240
} elseif (is_string($translations) && is_file($translations)) {
43-
$this->loadArray(include $translations);
44-
} elseif (is_array($translations)) {
45-
$this->loadArray($translations);
46-
} else {
41+
$translations = include $translations;
42+
} elseif (!is_array($translations)) {
4743
throw new \InvalidArgumentException('Invalid Translator: only arrays, files or instance of Translations are allowed');
4844
}
4945

46+
foreach ($translations as $translation) {
47+
$this->addTranslations($translation);
48+
}
49+
5050
return $this;
5151
}
5252

53-
/**
54-
* Loads translations from an array
55-
*
56-
* @param array $translations
57-
*/
58-
protected function loadArray(array $translations)
59-
{
60-
foreach ($translations as &$translation) {
61-
$domain = isset($translation['']['domain']) ? $translation['']['domain'] : 'messages';
62-
63-
//Set the first domain loaded as default domain
64-
if (!$this->domain) {
65-
$this->domain = $domain;
66-
}
67-
68-
// If a plural form is set we extract those values
69-
if (isset($translation['']['plural-forms'])) {
70-
list($count, $code) = explode(';', $translation['']['plural-forms']);
71-
$this->pluralCount = (int) str_replace('nplurals=', '', $count);
72-
73-
// extract just the expression turn 'n' into a php variable '$n'.
74-
// Slap on a return keyword and semicolon at the end.
75-
$this->pluralCode = str_replace('plural=', 'return ', str_replace('n', '$n', $code)).';';
76-
}
77-
78-
unset($translation['']);
79-
$this->addTranslations($translation, $domain);
80-
}
81-
}
8253

8354
/**
8455
* Set new translations to the dictionary
8556
*
8657
* @param array $translations
87-
* @param null|string $domain
8858
*/
89-
public function addTranslations(array $translations, $domain = null)
59+
public function addTranslations(array $translations)
9060
{
91-
if ($domain === null) {
92-
$domain = $this->domain;
61+
$info = isset($translations['']) ? $translations[''] : null;
62+
unset($translations['']);
63+
64+
$domain = isset($info['domain']) ? $info['domain'] : 'messages';
65+
66+
//Set the first domain loaded as default domain
67+
if (!$this->domain) {
68+
$this->domain = $domain;
9369
}
9470

9571
if (!isset($this->dictionary[$domain])) {
72+
// If a plural form is set we extract those values
73+
$pluralForms = empty($info['plural-forms']) ? 'nplurals=2; plural=(n != 1)' : $info['plural-forms'];
74+
75+
list($count, $code) = explode(';', $pluralForms, 2);
76+
77+
// extract just the expression turn 'n' into a php variable '$n'.
78+
// Slap on a return keyword and semicolon at the end.
79+
$this->plurals[$domain] = [
80+
'count' => (int) str_replace('nplurals=', '', $count),
81+
'code' => str_replace('plural=', 'return ', str_replace('n', '$n', $code)).';',
82+
];
83+
9684
$this->dictionary[$domain] = $translations;
9785
} else {
9886
$this->dictionary[$domain] = array_replace_recursive($this->dictionary[$domain], $translations);
@@ -236,7 +224,7 @@ public function dpgettext($domain, $context, $original)
236224
*/
237225
public function dnpgettext($domain, $context, $original, $plural, $value)
238226
{
239-
$key = $this->isPlural($value);
227+
$key = $this->isPlural($domain, $value);
240228
$translation = $this->getTranslation($domain, $context, $original);
241229

242230
if (isset($translation[$key]) && $translation[$key] !== '') {
@@ -250,22 +238,27 @@ public function dnpgettext($domain, $context, $original, $plural, $value)
250238
* Executes the plural decision code given the number to decide which
251239
* plural version to take.
252240
*
241+
* @param string $domain
253242
* @param string $n
254243
* @return int
255244
*/
256-
public function isPlural($n)
245+
public function isPlural($domain, $n)
257246
{
258-
if (!$this->pluralFunction) {
259-
$this->pluralFunction = create_function('$n', self::fixTerseIfs($this->pluralCode));
247+
if (!isset($this->plurals[$domain])) {
248+
throw new \InvalidArgumentException("The gettext domain '$domain' is not loaded");
249+
}
250+
251+
if (!isset($this->plurals[$domain]['function'])) {
252+
$this->plurals[$domain]['function'] = create_function('$n', self::fixTerseIfs($this->plurals[$domain]['code']));
260253
}
261254

262-
if ($this->pluralCount <= 2) {
263-
return (call_user_func($this->pluralFunction, $n)) ? 2 : 1;
255+
if ($this->plurals[$domain]['count'] <= 2) {
256+
return (call_user_func($this->plurals[$domain]['function'], $n)) ? 2 : 1;
264257
}
265258

266259
// We need to +1 because while (GNU) gettext codes assume 0 based,
267260
// this gettext actually stores 1 based.
268-
return (call_user_func($this->pluralFunction, $n)) + 1;
261+
return (call_user_func($this->plurals[$domain]['function'], $n)) + 1;
269262
}
270263

271264
/**

src/translator_functions.php

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,16 @@ function p__($context, $original)
6363

6464
return vsprintf($text, is_array($args[0]) ? $args[0] : $args);
6565
}
66-
/*
6766

68-
Not implemented yet...
69-
70-
function __d($domain, $original)
67+
/**
68+
* Returns the translation of a string in a specific domain
69+
*
70+
* @param string $domain
71+
* @param string $original
72+
*
73+
* @return string
74+
*/
75+
function d__($domain, $original)
7176
{
7277
$text = Translator::dgettext($domain, $original);
7378

@@ -80,7 +85,16 @@ function __d($domain, $original)
8085
return vsprintf($text, is_array($args[0]) ? $args[0] : $args);
8186
}
8287

83-
function __dp($domain, $context, $original)
88+
/**
89+
* Returns the translation of a string in a specific domain and context
90+
*
91+
* @param string $domain
92+
* @param string $context
93+
* @param string $original
94+
*
95+
* @return string
96+
*/
97+
function dp__($domain, $context, $original)
8498
{
8599
$text = Translator::dpgettext($domain, $context, $original);
86100

@@ -93,7 +107,18 @@ function __dp($domain, $context, $original)
93107
return vsprintf($text, is_array($args[0]) ? $args[0] : $args);
94108
}
95109

96-
function __dnp($domain, $context, $original, $plural, $value)
110+
/**
111+
* Returns the singular/plural translation of a string in a specific domain and context
112+
*
113+
* @param string $domain
114+
* @param string $context
115+
* @param string $original
116+
* @param string $plural
117+
* @param string $value
118+
*
119+
* @return string
120+
*/
121+
function dnp__($domain, $context, $original, $plural, $value)
97122
{
98123
$text = Translator::dnpgettext($domain, $context, $original, $plural, $value);
99124

@@ -105,7 +130,6 @@ function __dnp($domain, $context, $original, $plural, $value)
105130

106131
return vsprintf($text, is_array($args[0]) ? $args[0] : $args);
107132
}
108-
*/
109133

110134
/**
111135
* Prints function result
@@ -136,3 +160,33 @@ function p__e()
136160
{
137161
echo call_user_func_array('p__', func_get_args());
138162
}
163+
164+
/**
165+
* Prints function result
166+
*
167+
* @see d__
168+
*/
169+
function d__e()
170+
{
171+
echo call_user_func_array('d__', func_get_args());
172+
}
173+
174+
/**
175+
* Prints function result
176+
*
177+
* @see dp__
178+
*/
179+
function dp__e()
180+
{
181+
echo call_user_func_array('dp__', func_get_args());
182+
}
183+
184+
/**
185+
* Prints function result
186+
*
187+
* @see dnp__
188+
*/
189+
function dnp__e()
190+
{
191+
echo call_user_func_array('dnp__', func_get_args());
192+
}

tests/PluralsTest.php

Lines changed: 0 additions & 36 deletions
This file was deleted.

tests/TranslatorTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@ public function testOne()
88
//Extract translations
99
$t = new Gettext\Translator();
1010
$t->loadTranslations(Gettext\Translations::fromPoFile(__DIR__.'/files/po.po'));
11+
$t->loadTranslations(Gettext\Translations::fromPoFile(__DIR__.'/files/plurals.po'));
1112

1213
$this->assertEquals('Cijeo broj', $t->gettext('Integer'));
1314
$this->assertEquals('Ovo polje ne može biti prazno.', $t->gettext('This field cannot be blank.'));
1415
$this->assertEquals('Value %sr is not a valid choice.', $t->gettext('Value %sr is not a valid choice.'));
16+
17+
//domains
18+
$this->assertEquals('single', $t->gettext('single'));
19+
$this->assertEquals('test', $t->dgettext('messages', 'single'));
1520
}
1621

1722
public function testFunctions()
@@ -27,4 +32,32 @@ public function testFunctions()
2732
$this->assertEquals('Value %sr is not a valid choice.', __('Value %sr is not a valid choice.'));
2833
$this->assertEquals('Value hellor is not a valid choice.', __('Value %sr is not a valid choice.', 'hello'));
2934
}
35+
36+
public function testPlural()
37+
{
38+
$t = new \Gettext\Translator();
39+
$t->loadTranslations(Gettext\Extractors\Po::fromFile(__DIR__.'/files/plurals.po'));
40+
41+
/**
42+
* Test that nplural=3 plural translation check comes up with the correct translation key.
43+
*/
44+
$this->assertEquals('1 plik', $t->ngettext("one file", "multiple files", 1), "plural calculation result bad");
45+
$this->assertEquals('2,3,4 pliki', $t->ngettext("one file", "multiple files", 2), "plural calculation result bad");
46+
$this->assertEquals('2,3,4 pliki', $t->ngettext("one file", "multiple files", 3), "plural calculation result bad");
47+
$this->assertEquals('2,3,4 pliki', $t->ngettext("one file", "multiple files", 4), "plural calculation result bad");
48+
$this->assertEquals('5-21 plików', $t->ngettext("one file", "multiple files", 5), "plural calculation result bad");
49+
$this->assertEquals('5-21 plików', $t->ngettext("one file", "multiple files", 6), "plural calculation result bad");
50+
51+
/**
52+
* Test that when less then the nplural translations are available it still works.
53+
*/
54+
$this->assertEquals('1', $t->ngettext("one", "more", 1), "non-plural fallback failed");
55+
$this->assertEquals('*', $t->ngettext("one", "more", 2), "non-plural fallback failed");
56+
$this->assertEquals('*', $t->ngettext("one", "more", 3), "non-plural fallback failed");
57+
58+
/**
59+
* Test that non-plural translations the fallback still works.
60+
*/
61+
$this->assertEquals('more', $t->ngettext("single", "more", 3), "non-plural fallback failed");
62+
}
3063
}

0 commit comments

Comments
 (0)