Browse Source

Implemented singular form fallback for __n() and __dn()

This helps developers get feedback on their code without having to translate stirngs to
any given locale beforehand
Jose Lorenzo Rodriguez 11 years ago
parent
commit
012d48289e

+ 9 - 2
src/I18n/Formatter/IcuFormatter.php

@@ -37,7 +37,14 @@ class IcuFormatter implements FormatterInterface {
  * @return string The formatted message
  */
 	public function format($locale, $message, array $vars) {
-		if (is_string($message)) {
+		$isString = is_string($message);
+		if ($isString && isset($vars['_singular'])) {
+			$message = [$vars['_singular'], $message];
+			unset($vars['_singular']);
+			$isString = false;
+		}
+
+		if ($isString) {
 			return $this->_formatMessage($locale, $message, $vars);
 		}
 
@@ -53,7 +60,7 @@ class IcuFormatter implements FormatterInterface {
 
 		if (!is_string($message)) {
 			$count = isset($vars['_count']) ? $vars['_count'] : 0;
-			unset($vars['_count']);
+			unset($vars['_count'], $vars['_singular']);
 			$form = PluralRules::calculate($locale, $count);
 			$message = $message[$form];
 		}

+ 8 - 0
src/I18n/Formatter/SprintfFormatter.php

@@ -36,6 +36,13 @@ class SprintfFormatter implements FormatterInterface {
  * @return string The formatted message
  */
 	public function format($locale, $message, array $vars) {
+		$isString = is_string($message);
+		if ($isString && isset($vars['_singular'])) {
+			$message = [$vars['_singular'], $message];
+			unset($vars['_singular']);
+			$isString = false;
+		}
+
 		if (is_string($message)) {
 			return vsprintf($message, $vars);
 		}
@@ -52,6 +59,7 @@ class SprintfFormatter implements FormatterInterface {
 
 		if (!is_string($message)) {
 			$count = isset($vars['_count']) ? $vars['_count'] : 0;
+			unset($vars['_singular']);
 			$form = PluralRules::calculate($locale, $count);
 			$message = $message[$form];
 		}

+ 7 - 7
src/Utility/Time.php

@@ -357,25 +357,25 @@ class Time extends Carbon implements JsonSerializable {
 
 		$relativeDate = '';
 		if ($fNum >= 1 && $years > 0) {
-			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d year', '%d years', $years, $years);
+			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '{0} year', '{0} years', $years, $years);
 		}
 		if ($fNum >= 2 && $months > 0) {
-			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d month', '%d months', $months, $months);
+			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '{0} month', '{0} months', $months, $months);
 		}
 		if ($fNum >= 3 && $weeks > 0) {
-			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d week', '%d weeks', $weeks, $weeks);
+			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '{0} week', '{0} weeks', $weeks, $weeks);
 		}
 		if ($fNum >= 4 && $days > 0) {
-			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d day', '%d days', $days, $days);
+			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '{0} day', '{0} days', $days, $days);
 		}
 		if ($fNum >= 5 && $hours > 0) {
-			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d hour', '%d hours', $hours, $hours);
+			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '{0} hour', '{0} hours', $hours, $hours);
 		}
 		if ($fNum >= 6 && $minutes > 0) {
-			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d minute', '%d minutes', $minutes, $minutes);
+			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '{0} minute', '{0} minutes', $minutes, $minutes);
 		}
 		if ($fNum >= 7 && $seconds > 0) {
-			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d second', '%d seconds', $seconds, $seconds);
+			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '{0} second', '{0} seconds', $seconds, $seconds);
 		}
 
 		// When time has passed

+ 2 - 2
src/basics.php

@@ -631,7 +631,7 @@ if (!function_exists('__n')) {
 		$arguments = func_num_args() === 4 ? (array)$args : array_slice(func_get_args(), 3);
 		return I18n::translator()->translate(
 			$plural,
-			['_count' => $count] + $arguments
+			['_count' => $count, '_singular' => $singular] + $arguments
 		);
 	}
 
@@ -681,7 +681,7 @@ if (!function_exists('__dn')) {
 		$arguments = func_num_args() === 5 ? (array)$args : array_slice(func_get_args(), 4);
 		return I18n::translator($domain)->translate(
 			$plural,
-			['_count' => $count] + $arguments
+			['_count' => $count, '_singular' => $singular] + $arguments
 		);
 	}
 

+ 15 - 0
tests/TestCase/I18n/Formatter/IcuFormatterTest.php

@@ -147,4 +147,19 @@ class IcuFormatterTest extends TestCase {
 		);
 	}
 
+/**
+ * Tests that it is possible to provide a singular fallback when passing a string message.
+ * This is useful for getting quick feedback on the code during development instead of
+ * having to provide all plural forms even for the default language
+ *
+ * @return void
+ */
+	public function testSingularFallback() {
+		$formatter = new IcuFormatter();
+		$singular = 'one thing';
+		$plural = 'many things';
+		$this->assertEquals($singular, $formatter->format('en_US', $plural, ['_count' => 1, '_singular' => $singular]));
+		$this->assertEquals($plural, $formatter->format('en_US', $plural, ['_count' => 2, '_singular' => $singular]));
+	}
+
 }

+ 15 - 0
tests/TestCase/I18n/Formatter/SprintfFormatterTest.php

@@ -95,4 +95,19 @@ class SprintfFormatterTest extends TestCase {
 		);
 	}
 
+/**
+ * Tests that it is possible to provide a singular fallback when passing a string message.
+ * This is useful for getting quick feedback on the code during development instead of
+ * having to provide all plural forms even for the default language
+ *
+ * @return void
+ */
+	public function testSingularFallback() {
+		$formatter = new SprintfFormatter();
+		$singular = 'one thing';
+		$plural = 'many things';
+		$this->assertEquals($singular, $formatter->format('en_US', $plural, ['_count' => 1, '_singular' => $singular]));
+		$this->assertEquals($plural, $formatter->format('en_US', $plural, ['_count' => 2, '_singular' => $singular]));
+	}
+
 }