Permalink
Browse files

Refactoring `Message` and related filters.

Adding tests.
Moving placeholders and default filter back into class.
Updating `Message::_translated()` signature.
`translate()` looses filterability in favour of `_translated()`.
  • Loading branch information...
1 parent 4243e27 commit 4b3eb0eb9614daa30ab4341f83d0056d3973786b @davidpersson davidpersson committed with gwoo Feb 9, 2010
Showing with 162 additions and 68 deletions.
  1. +1 −30 app/config/bootstrap/g11n.php
  2. +51 −30 libraries/lithium/g11n/Message.php
  3. +110 −8 libraries/lithium/tests/cases/g11n/MessageTest.php
@@ -11,36 +11,7 @@
use \lithium\net\http\Media;
/**
- * Implements logic for handling cases where `Message::translate()` returns without a result.
- * The message specified for the `'default'` option will be used as a fall back. By
- * default the value for the options is the message passed to the method.
- */
-Message::applyFilter('translate', function($self, $params, $chain) {
- $params['options'] += array('default' => $params['id']);
- return $chain->next($self, $params, $chain) ?: $params['options']['default'];
-});
-
-/**
- * Placeholders in translated messages. Adds support for `String::insert()`-style placeholders
- * to translated messages. Placeholders may be used within the message and replacements provided
- * directly within the `options` argument.
- *
- * Usage:
- * {{{
- * Message::translate('Your {:color} paintings are looking just great.', array(
- * 'color' => 'silver',
- * 'locale' => 'fr'
- * ));
- * }}}
- *
- * @see lithium\util\String::insert()
- */
-Message::applyFilter('translate', function($self, $params, $chain) {
- return String::insert($chain->next($self, $params, $chain), $params['options']);
-});
-
-/**
- * Embeds message translation content filters into the `View` class (or other content handler,
+ * Embeds message translation short-hands into the `View` class (or other content handler,
* if specified) when content is rendered. This enables short-hand translation functions, i.e.
* `<?=$t("Translated content"); ?>`.
*/
@@ -9,6 +9,7 @@
namespace lithium\g11n;
use \lithium\core\Environment;
+use \lithium\util\String;
use \lithium\g11n\Locale;
use \lithium\g11n\Catalog;
@@ -56,21 +57,42 @@ class Message extends \lithium\core\StaticObject {
* Message::translate('house', array('count' => 23));
* }}}
*
+ * `String::insert()`-style placeholders may be used within the message
+ * and replacements provided directly within the `options` argument.
+ *
+ * Example:
+ * {{{
+ * Message::translate('Your {:color} paintings are looking just great.', array(
+ * 'color' => 'silver',
+ * 'locale' => 'fr'
+ * ));
+ * }}}
+ *
* @param string $id The id to use when looking up the translation.
* @param array $options Valid options are:
* - `'count'`: Used to determine the correct plural form.
* - `'locale'`: The target locale, defaults to current locale.
* - `'scope'`: The scope of the message.
- * @return string|void The translation or `null` if none could be found.
- * @filter
+ * - `'default'`: Is used as a fall back if `_translated()` returns without a result.
+ * @return string|void The translation or the value of the `'default'` option if none could be found.
+ * @see lithium\util\String::insert()
*/
public static function translate($id, $options = array()) {
- $params = compact('id', 'options');
- return static::_filter(__METHOD__, $params, function($self, $params, $chain) {
- return $self::invokeMethod('_translated', array($params['id'], $params['options']));
- });
- }
+ $defaults = array(
+ 'count' => 1,
+ // 'locale' => Environment::get('g11n.locale'),
+ 'locale' => 'root',
+ 'scope' => null,
+ 'default' => null
+ );
+ extract($options + $defaults);
+
+ $result = static::_translated($id, $count, $locale, compact('scope'));
+ if ($result || $default) {
+ return String::insert($result ?: $default, $options);
+ }
+ }
/**
* Returns an array containing named closures which are short-hand aliases for `translate()`.
@@ -113,39 +135,38 @@ public static function shortHands() {
* value of the `'count'` option to a closure.
*
* @param string $id The lookup key.
- * @param array $options Valid options are:
- * - `'count'`: Used to determine the correct plural form.
- * - `'locale'`: The target locale, defaults to current locale.
+ * @param integer $count Used to determine the correct plural form.
+ * @param string $locale The target locale.
+ * @param array $options Passed through to `Catalog::read()`. Valid options are:
* - `'scope'`: The scope of the message.
* @return string|void The translation or `null` if none could be found or the plural
* form could not be determined.
* @see lithium\g11n\Catalog
+ * @filter
* @todo Message pages need caching.
*/
- protected static function _translated($id, $options = array()) {
- $defaults = array(
- 'count' => 1,
- // 'locale' => Environment::get('g11n.locale'),
- 'locale' => 'root',
- 'scope' => null
- );
- extract($options + $defaults);
+ protected static function _translated($id, $count, $locale, $options = array()) {
+ $params = compact('id', 'count', 'locale', 'options');
- $page = Catalog::read('message', $locale, compact('scope'));
+ return static::_filter(__METHOD__, $params, function($self, $params, $chain) {
+ extract($params);
- if (!isset($page[$id])) {
- return null;
- }
- $translated = (array) $page[$id];
+ $page = Catalog::read('message', $locale, $options);
- if (!isset($page['plural']) || !is_callable($page['plural'])) {
- return null;
- }
- $key = $page['plural']($count);
+ if (!isset($page[$id])) {
+ return null;
+ }
+ $translated = (array) $page[$id];
- if (isset($translated[$key])) {
- return $translated[$key];
- }
+ if (!isset($page['plural']) || !is_callable($page['plural'])) {
+ return null;
+ }
+ $key = $page['plural']($count);
+
+ if (isset($translated[$key])) {
+ return $translated[$key];
+ }
+ });
}
}
@@ -23,26 +23,31 @@ public function setUp() {
Catalog::config(array(
'runtime' => array('adapter' => new Memory())
));
+ $data = function($n) { return $n == 1 ? 0 : 1; };
+ Catalog::write('message.plural', 'root', $data, array('name' => 'runtime'));
}
public function tearDown() {
Catalog::reset();
Catalog::config($this->_backups['catalogConfig']);
}
- public function testTranslate() {
- $data = function($n) { return $n == 1 ? 0 : 1; };
- Catalog::write('message.plural', 'root', $data, array('name' => 'runtime'));
-
+ public function testTranslateBasic() {
$data = array(
- 'lithium' => 'Kuchen',
- 'house' => array('Haus', 'Häuser')
+ 'catalog' => 'Katalog',
);
Catalog::write('message', 'de', $data, array('name' => 'runtime'));
- $expected = 'Kuchen';
- $result = Message::translate('lithium', array('locale' => 'de'));
+ $expected = 'Katalog';
+ $result = Message::translate('catalog', array('locale' => 'de'));
$this->assertEqual($expected, $result);
+ }
+
+ public function testTranslatePlural() {
+ $data = array(
+ 'house' => array('Haus', 'Häuser')
+ );
+ Catalog::write('message', 'de', $data, array('name' => 'runtime'));
$expected = 'Haus';
$result = Message::translate('house', array('locale' => 'de'));
@@ -52,6 +57,103 @@ public function testTranslate() {
$result = Message::translate('house', array('locale' => 'de', 'count' => 5));
$this->assertEqual($expected, $result);
}
+
+ public function testTranslateFail() {
+ $result = Message::translate('catalog', array('locale' => 'de'));
+ $this->assertNull($result);
+
+ Catalog::reset();
+ Catalog::config(array(
+ 'runtime' => array('adapter' => new Memory())
+ ));
+
+ $data = array(
+ 'catalog' => 'Katalog',
+ );
+ Catalog::write('message', 'de', $data, array('name' => 'runtime'));
+
+ $result = Message::translate('catalog', array('locale' => 'de'));
+ $this->assertNull($result);
+
+ $data = 'not a valid pluralization function';
+ Catalog::write('message.plural', 'root', $data, array('name' => 'runtime'));
+
+ $result = Message::translate('catalog', array('locale' => 'de'));
+ $this->assertNull($result);
+ }
+
+ public function testTranslateScope() {
+ $data = array(
+ 'catalog' => 'Katalog',
+ );
+ Catalog::write('message', 'de', $data, array('name' => 'runtime', 'scope' => 'test'));
+
+ $data = function($n) { return $n == 1 ? 0 : 1; };
+ Catalog::write('message.plural', 'root', $data, array(
+ 'name' => 'runtime', 'scope' => 'test'
+ ));
+
+ $result = Message::translate('catalog', array('locale' => 'de'));
+ $this->assertNull($result);
+
+ $expected = 'Katalog';
+ $result = Message::translate('catalog', array('locale' => 'de', 'scope' => 'test'));
+ $this->assertEqual($expected, $result);
+ }
+
+ public function testTranslateDefault() {
+ $result = Message::translate('Here I am', array('locale' => 'de'));
+ $this->assertNull($result);
+
+ $result = Message::translate('Here I am', array(
+ 'locale' => 'de', 'default' => 'Here I am'
+ ));
+ $expected = 'Here I am';
+ $this->assertEqual($expected, $result);
+ }
+
+ public function testTranslatePlaceholders() {
+ $data = array(
+ 'green' => 'grün',
+ 'The fish is {:color}.' => 'Der Fisch ist {:color}.',
+ '{:count} bike' => array('{:count} Fahrrad', '{:count} Fahrräder'),
+ );
+ Catalog::write('message', 'de', $data, array('name' => 'runtime'));
+
+ $expected = 'Der Fisch ist grün.';
+ $result = Message::translate('The fish is {:color}.', array(
+ 'locale' => 'de',
+ 'color' => Message::translate('green', array('locale' => 'de'))
+ ));
+ $this->assertEqual($expected, $result);
+
+ $expected = '1 Fahrrad';
+ $result = Message::translate('{:count} bike', array('locale' => 'de', 'count' => 1));
+ $this->assertEqual($expected, $result);
+
+ $expected = '7 Fahrräder';
+ $result = Message::translate('{:count} bike', array('locale' => 'de', 'count' => 7));
+ $this->assertEqual($expected, $result);
+ }
+
+ public function testTranslateLocales() {
+ $data = array(
+ 'catalog' => 'Katalog',
+ );
+ Catalog::write('message', 'de', $data, array('name' => 'runtime'));
+ $data = array(
+ 'catalog' => 'catalogue',
+ );
+ Catalog::write('message', 'fr', $data, array('name' => 'runtime'));
+
+ $expected = 'Katalog';
+ $result = Message::translate('catalog', array('locale' => 'de'));
+ $this->assertEqual($expected, $result);
+
+ $expected = 'catalogue';
+ $result = Message::translate('catalog', array('locale' => 'fr'));
+ $this->assertEqual($expected, $result);
+ }
}
?>

0 comments on commit 4b3eb0e

Please sign in to comment.