From 7472b01428c67ec873d096c992a02a4d42991b2a Mon Sep 17 00:00:00 2001 From: AD7six Date: Fri, 19 Sep 2014 10:33:32 +0000 Subject: [PATCH] implement translation behavior default locale The behavior now reads I18n::defaultLocale() to find the locale to return translations in unless explicitly overriden. Bundled with this change set is adding support to the translate behavior for unhydrated result sets Fixes #4509 --- src/Model/Behavior/TranslateBehavior.php | 27 +++-- .../Model/Behavior/TranslateBehaviorTest.php | 99 +++++++++++++++++++ 2 files changed, 116 insertions(+), 10 deletions(-) diff --git a/src/Model/Behavior/TranslateBehavior.php b/src/Model/Behavior/TranslateBehavior.php index 321adda032d..ba1c618a394 100644 --- a/src/Model/Behavior/TranslateBehavior.php +++ b/src/Model/Behavior/TranslateBehavior.php @@ -17,6 +17,7 @@ use ArrayObject; use Cake\Collection\Collection; use Cake\Event\Event; +use Cake\I18n\I18n; use Cake\ORM\Behavior; use Cake\ORM\Entity; use Cake\ORM\Query; @@ -63,7 +64,8 @@ class TranslateBehavior extends Behavior { 'implementedFinders' => ['translations' => 'findTranslations'], 'implementedMethods' => ['locale' => 'locale'], 'fields' => [], - 'translationTable' => 'i18n' + 'translationTable' => 'i18n', + 'defaultLocale' => 'en_US' ]; /** @@ -130,7 +132,7 @@ public function setupFieldAssociations($fields, $table) { public function beforeFind(Event $event, $query) { $locale = $this->locale(); - if (empty($locale)) { + if ($locale === $this->config('defaultLocale')) { return; } @@ -170,7 +172,7 @@ public function beforeSave(Event $event, Entity $entity, ArrayObject $options) { $this->_bundleTranslatedFields($entity); - if (!$locale) { + if ($locale === $this->config('defaultLocale')) { return; } @@ -230,7 +232,7 @@ public function afterSave(Event $event, Entity $entity) { */ public function locale($locale = null) { if ($locale === null) { - return $this->_locale; + return $this->_locale ?: I18n::defaultLocale(); } return $this->_locale = (string)$locale; } @@ -281,26 +283,31 @@ public function findTranslations(Query $query, array $options) { protected function _rowMapper($results, $locale) { return $results->map(function($row) use ($locale) { $options = ['setter' => false, 'guard' => false]; + $hydrated = !is_array($row); foreach ($this->_config['fields'] as $field) { + $name = $field . '_translation'; - $translation = $row->get($name); + $translation = isset($row[$name]) ? $row[$name] : null; if ($translation === null || $translation === false) { - $row->unsetProperty($name); + unset($row[$name]); continue; } - $content = $translation->get('content'); + $content = isset($translation['content']) ? $translation['content'] : null; if ($content !== null) { - $row->set($field, $content, $options); + $row[$field] = $content; } unset($row[$name]); } - $row->set('_locale', $locale, $options); - $row->clean(); + $row['_locale'] = $locale; + if ($hydrated) { + $row->clean(); + } + return $row; }); } diff --git a/tests/TestCase/Model/Behavior/TranslateBehaviorTest.php b/tests/TestCase/Model/Behavior/TranslateBehaviorTest.php index f8aae68d152..c9851906077 100644 --- a/tests/TestCase/Model/Behavior/TranslateBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/TranslateBehaviorTest.php @@ -16,6 +16,7 @@ use Cake\Collection\Collection; use Cake\Event\Event; +use Cake\I18n\I18n; use Cake\Model\Behavior\TranslateBehavior; use Cake\ORM\Entity; use Cake\ORM\TableRegistry; @@ -39,6 +40,7 @@ class TranslateBehaviorTest extends TestCase { ]; public function tearDown() { + I18n::defaultLocale('en_US'); parent::tearDown(); TableRegistry::clear(); } @@ -79,6 +81,103 @@ public function testFindSingleLocale() { $this->assertSame($expected, $results); } +/** + * Tests that fields from a translated model use the I18n class locale + * and that it propogates to associated models + * + * @return void + */ + public function testFindSingleLocaleAssociatedEnv() { + I18n::defaultLocale('eng'); + + $table = TableRegistry::get('Articles'); + $table->addBehavior('Translate', ['fields' => ['title', 'body']]); + + $table->hasMany('Comments'); + $table->Comments->addBehavior('Translate', ['fields' => ['comment']]); + + $results = $table->find() + ->select(['id', 'title', 'body']) + ->contain(['Comments' => ['fields' => ['article_id', 'comment']]]) + ->hydrate(false) + ->toArray(); + + $expected = [ + [ + 'id' => 1, + 'title' => 'Title #1', + 'body' => 'Content #1', + 'comments' => [ + ['article_id' => 1, 'comment' => 'Comment #1', '_locale' => 'eng'], + ['article_id' => 1, 'comment' => 'Comment #2', '_locale' => 'eng'], + ['article_id' => 1, 'comment' => 'Comment #3', '_locale' => 'eng'], + ['article_id' => 1, 'comment' => 'Comment #4', '_locale' => 'eng'] + ], + '_locale' => 'eng' + ], + [ + 'id' => 2, + 'title' => 'Title #2', + 'body' => 'Content #2', + 'comments' => [ + ['article_id' => 2, 'comment' => 'First Comment for Second Article', '_locale' => 'eng'], + ['article_id' => 2, 'comment' => 'Second Comment for Second Article', '_locale' => 'eng'] + ], + '_locale' => 'eng' + ], + [ + 'id' => 3, + 'title' => 'Title #3', + 'body' => 'Content #3', + 'comments' => [], + '_locale' => 'eng' + ] + ]; + $this->assertSame($expected, $results); + + I18n::defaultLocale('spa'); + + $results = $table->find() + ->select(['id', 'title', 'body']) + ->contain(['Comments' => ['fields' => ['article_id', 'comment']]]) + ->hydrate(false) + ->toArray(); + + $expected = [ + [ + 'id' => 1, + 'title' => 'First Article', + 'body' => 'First Article Body', + 'comments' => [ + ['article_id' => 1, 'comment' => 'First Comment for First Article', '_locale' => 'spa'], + ['article_id' => 1, 'comment' => 'Second Comment for First Article', '_locale' => 'spa'], + ['article_id' => 1, 'comment' => 'Third Comment for First Article', '_locale' => 'spa'], + ['article_id' => 1, 'comment' => 'Comentario #4', '_locale' => 'spa'] + ], + '_locale' => 'spa' + ], + [ + 'id' => 2, + 'title' => 'Second Article', + 'body' => 'Second Article Body', + 'comments' => [ + ['article_id' => 2, 'comment' => 'First Comment for Second Article', '_locale' => 'spa'], + ['article_id' => 2, 'comment' => 'Second Comment for Second Article', '_locale' => 'spa'] + ], + '_locale' => 'spa' + ], + [ + 'id' => 3, + 'title' => 'Third Article', + 'body' => 'Third Article Body', + 'comments' => [], + '_locale' => 'spa' + ] + ]; + $this->assertSame($expected, $results); + + } + /** * Tests that fields from a translated model are not overriden if translation * is null