summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Scheller <igor.scheller@igorshp.de>2018-10-18 23:34:18 +0200
committermsquare <msquare@notrademark.de>2018-10-30 22:50:22 +0100
commitb443b53919f50bd0176e7b67dfd1efc28276a770 (patch)
treedf4d089d9d431f5223a71e6b40f9d87361705929
parent90e1a949623ead173c0952f802d7b5c5487251b1 (diff)
Translation: added pluralization support
-rw-r--r--includes/controller/user_angeltypes_controller.php13
-rw-r--r--includes/view/ShiftCalendarShiftRenderer.php6
-rw-r--r--includes/view/User_view.php5
-rw-r--r--src/Helpers/Translator.php50
-rw-r--r--src/Renderer/Twig/Extensions/Translation.php1
-rw-r--r--src/helpers.php17
-rw-r--r--tests/Unit/Helpers/TranslatorTest.php43
-rw-r--r--tests/Unit/HelpersTest.php20
-rw-r--r--tests/Unit/Renderer/Twig/Extensions/TranslationTest.php1
9 files changed, 130 insertions, 26 deletions
diff --git a/includes/controller/user_angeltypes_controller.php b/includes/controller/user_angeltypes_controller.php
index aa614cf3..734bd1e9 100644
--- a/includes/controller/user_angeltypes_controller.php
+++ b/includes/controller/user_angeltypes_controller.php
@@ -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);
}
/**
diff --git a/includes/view/ShiftCalendarShiftRenderer.php b/includes/view/ShiftCalendarShiftRenderer.php
index 9e40b1c6..80cea241 100644
--- a/includes/view/ShiftCalendarShiftRenderer.php
+++ b/includes/view/ShiftCalendarShiftRenderer.php
@@ -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:
diff --git a/includes/view/User_view.php b/includes/view/User_view.php
index fb541619..f8160765 100644
--- a/includes/view/User_view.php
+++ b/includes/view/User_view.php
@@ -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>';
diff --git a/src/Helpers/Translator.php b/src/Helpers/Translator.php
index 1e953a21..94fbd795 100644
--- a/src/Helpers/Translator.php
+++ b/src/Helpers/Translator.php
@@ -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);
+ }
+
+ /**
+ * 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 $translated;
+ 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);
}
/**
diff --git a/src/Renderer/Twig/Extensions/Translation.php b/src/Renderer/Twig/Extensions/Translation.php
index 63f9800e..41619c19 100644
--- a/src/Renderer/Twig/Extensions/Translation.php
+++ b/src/Renderer/Twig/Extensions/Translation.php
@@ -44,6 +44,7 @@ class Translation extends TwigExtension
{
return [
new TwigFunction('__', [$this->translator, 'translate']),
+ new TwigFunction('_e', [$this->translator, 'translatePlural']),
];
}
diff --git a/src/helpers.php b/src/helpers.php
index 84f26dfa..64ca9ec8 100644
--- a/src/helpers.php
+++ b/src/helpers.php
@@ -154,6 +154,23 @@ function __($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
* @return UrlGeneratorInterface|string
diff --git a/tests/Unit/Helpers/TranslatorTest.php b/tests/Unit/Helpers/TranslatorTest.php
index 396d2b65..34050e42 100644
--- a/tests/Unit/Helpers/TranslatorTest.php
+++ b/tests/Unit/Helpers/TranslatorTest.php
@@ -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);
+ }
}
diff --git a/tests/Unit/HelpersTest.php b/tests/Unit/HelpersTest.php
index b9cedd30..b36abc64 100644
--- a/tests/Unit/HelpersTest.php
+++ b/tests/Unit/HelpersTest.php
@@ -219,6 +219,26 @@ class HelpersTest extends TestCase
}
/**
+ * @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
*/
public function testUrl()
diff --git a/tests/Unit/Renderer/Twig/Extensions/TranslationTest.php b/tests/Unit/Renderer/Twig/Extensions/TranslationTest.php
index f1548604..18705683 100644
--- a/tests/Unit/Renderer/Twig/Extensions/TranslationTest.php
+++ b/tests/Unit/Renderer/Twig/Extensions/TranslationTest.php
@@ -40,6 +40,7 @@ class TranslationTest extends ExtensionTest
$functions = $extension->getFunctions();
$this->assertExtensionExists('__', [$translator, 'translate'], $functions);
+ $this->assertExtensionExists('_e', [$translator, 'translatePlural'], $functions);
}
/**