Translation: added pluralization support

This commit is contained in:
Igor Scheller 2018-10-18 23:34:18 +02:00 committed by msquare
parent 90e1a94962
commit b443b53919
9 changed files with 130 additions and 26 deletions

View File

@ -23,10 +23,15 @@ function user_angeltypes_unconfirmed_hint()
. '</a>';
}
return sprintf(ngettext('There is %d unconfirmed angeltype.', 'There are %d unconfirmed angeltypes.',
count($unconfirmed_user_angeltypes)),
count($unconfirmed_user_angeltypes)) . ' ' . __('Angel types which need approvals:') . ' ' . join(', ',
$unconfirmed_links);
$count = count($unconfirmed_user_angeltypes);
return _e(
'There is %d unconfirmed angeltype.',
'There are %d unconfirmed angeltypes.',
$count,
[$count]
)
. ' ' . __('Angel types which need approvals:')
. ' ' . join(', ', $unconfirmed_links);
}
/**

View File

@ -175,10 +175,8 @@ class ShiftCalendarShiftRenderer
$angeltype,
$shift_entries
);
$inner_text = sprintf(
ngettext('%d helper needed', '%d helpers needed', $shift_signup_state->getFreeEntries()),
$shift_signup_state->getFreeEntries()
);
$freeEntriesCount = $shift_signup_state->getFreeEntries();
$inner_text = _e('%d helper needed', '%d helpers needed', $freeEntriesCount, [$freeEntriesCount]);
switch ($shift_signup_state->getState()) {
case ShiftSignupState::ADMIN:

View File

@ -727,10 +727,7 @@ function User_view_state_admin($freeloader, $user_source)
if ($user_source['got_voucher'] > 0) {
$state[] = '<span class="text-success">'
. glyph('cutlery')
. sprintf(
ngettext('Got %s voucher', 'Got %s vouchers', $user_source['got_voucher']),
$user_source['got_voucher']
)
. _e('Got %s voucher', 'Got %s vouchers', $user_source['got_voucher'], [$user_source['got_voucher']])
. '</span>';
} else {
$state[] = '<span class="text-danger">' . __('Got no vouchers') . '</span>';

View File

@ -39,11 +39,39 @@ class Translator
{
$translated = $this->translateGettext($key);
if (!empty($replace)) {
$translated = call_user_func_array('sprintf', array_merge([$translated], $replace));
return $this->replaceText($translated, $replace);
}
return $translated;
/**
* Get the translation for a given key
*
* @param string $key
* @param string $pluralKey
* @param int $number
* @param array $replace
* @return string
*/
public function translatePlural(string $key, string $pluralKey, int $number, array $replace = []): string
{
$translated = $this->translateGettextPlural($key, $pluralKey, $number);
return $this->replaceText($translated, $replace);
}
/**
* Replace placeholders
*
* @param string $key
* @param array $replace
* @return mixed|string
*/
protected function replaceText(string $key, array $replace = [])
{
if (empty($replace)) {
return $key;
}
return call_user_func_array('sprintf', array_merge([$key], $replace));
}
/**
@ -55,7 +83,21 @@ class Translator
*/
protected function translateGettext(string $key): string
{
return _($key);
return gettext($key);
}
/**
* Translate the key via gettext
*
* @param string $key
* @param string $keyPlural
* @param int $number
* @return string
* @codeCoverageIgnore
*/
protected function translateGettextPlural(string $key, string $keyPlural, int $number): string
{
return ngettext($key, $keyPlural, $number);
}
/**

View File

@ -44,6 +44,7 @@ class Translation extends TwigExtension
{
return [
new TwigFunction('__', [$this->translator, 'translate']),
new TwigFunction('_e', [$this->translator, 'translatePlural']),
];
}

View File

@ -153,6 +153,23 @@ function __($key, $replace = [])
return $translator->translate($key, $replace);
}
/**
* Translate the given message
*
* @param string $key
* @param string $keyPlural
* @param int $number
* @param array $replace
* @return string
*/
function _e($key, $keyPlural, $number, $replace = [])
{
/** @var Translator $translator */
$translator = app('translator');
return $translator->translatePlural($key, $keyPlural, $number, $replace);
}
/**
* @param string $path
* @param array $parameters

View File

@ -10,12 +10,12 @@ use stdClass;
class TranslatorTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Helpers\Translator::__construct()
* @covers \Engelsystem\Helpers\Translator::setLocale()
* @covers \Engelsystem\Helpers\Translator::setLocales()
* @covers \Engelsystem\Helpers\Translator::getLocale()
* @covers \Engelsystem\Helpers\Translator::getLocales()
* @covers \Engelsystem\Helpers\Translator::hasLocale()
* @covers \Engelsystem\Helpers\Translator::__construct
* @covers \Engelsystem\Helpers\Translator::setLocale
* @covers \Engelsystem\Helpers\Translator::setLocales
* @covers \Engelsystem\Helpers\Translator::getLocale
* @covers \Engelsystem\Helpers\Translator::getLocales
* @covers \Engelsystem\Helpers\Translator::hasLocale
*/
public function testInit()
{
@ -47,7 +47,8 @@ class TranslatorTest extends ServiceProviderTest
}
/**
* @covers \Engelsystem\Helpers\Translator::translate()
* @covers \Engelsystem\Helpers\Translator::translate
* @covers \Engelsystem\Helpers\Translator::replaceText
*/
public function testTranslate()
{
@ -56,14 +57,36 @@ class TranslatorTest extends ServiceProviderTest
->setConstructorArgs(['de_DE.UTF-8', ['de_DE.UTF-8' => 'Deutsch']])
->setMethods(['translateGettext'])
->getMock();
$translator->expects($this->once())
$translator->expects($this->exactly(2))
->method('translateGettext')
->with('My favourite number is %u!')
->willReturn('Meine Lieblingszahl ist die %u!');
->withConsecutive(['Hello!'], ['My favourite number is %u!'])
->willReturnOnConsecutiveCalls('Hallo!', 'Meine Lieblingszahl ist die %u!');
$return = $translator->translate('Hello!');
$this->assertEquals('Hallo!', $return);
$return = $translator->translate('My favourite number is %u!', [3]);
$this->assertEquals('Meine Lieblingszahl ist die 3!', $return);
}
/**
* @covers \Engelsystem\Helpers\Translator::translatePlural
*/
public function testTranslatePlural()
{
/** @var Translator|MockObject $translator */
$translator = $this->getMockBuilder(Translator::class)
->setConstructorArgs(['de_DE.UTF-8', ['de_DE.UTF-8' => 'Deutsch']])
->setMethods(['translateGettextPlural'])
->getMock();
$translator->expects($this->once())
->method('translateGettextPlural')
->with('%s apple', '%s apples', 2)
->willReturn('2 Äpfel');
$return = $translator->translatePlural('%s apple', '%s apples', 2, [2]);
$this->assertEquals('2 Äpfel', $return);
}
}

View File

@ -218,6 +218,26 @@ class HelpersTest extends TestCase
$this->assertEquals('Lorem foo Ipsum', __('Lorem %s Ipsum', ['foo']));
}
/**
* @covers \_e
*/
public function testTranslatePlural()
{
/** @var Translator|MockObject $translator */
$translator = $this->getMockBuilder(Translator::class)
->disableOriginalConstructor()
->getMock();
$this->getAppMock('translator', $translator);
$translator->expects($this->once())
->method('translatePlural')
->with('One: %u', 'Multiple: %u', 4, [4])
->willReturn('Multiple: 4');
$this->assertEquals('Multiple: 4', _e('One: %u', 'Multiple: %u', 4, [4]));
}
/**
* @covers \url
*/

View File

@ -40,6 +40,7 @@ class TranslationTest extends ExtensionTest
$functions = $extension->getFunctions();
$this->assertExtensionExists('__', [$translator, 'translate'], $functions);
$this->assertExtensionExists('_e', [$translator, 'translatePlural'], $functions);
}
/**