TranslateBehaviorTest.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\Model\Behavior;
  16. use Cake\Collection\Collection;
  17. use Cake\Event\Event;
  18. use Cake\I18n\I18n;
  19. use Cake\Model\Behavior\TranslateBehavior;
  20. use Cake\Model\Behavior\Translate\TranslateTrait;
  21. use Cake\ORM\Entity;
  22. use Cake\ORM\TableRegistry;
  23. use Cake\TestSuite\TestCase;
  24. /**
  25. * Stub entity class
  26. */
  27. class Article extends Entity {
  28. use TranslateTrait;
  29. }
  30. /**
  31. * Translate behavior test case
  32. */
  33. class TranslateBehaviorTest extends TestCase {
  34. /**
  35. * fixtures
  36. *
  37. * @var array
  38. */
  39. public $fixtures = [
  40. 'core.translates',
  41. 'core.articles',
  42. 'core.comments',
  43. 'core.authors'
  44. ];
  45. public function tearDown() {
  46. parent::tearDown();
  47. I18n::locale(I18n::defaultLocale());
  48. TableRegistry::clear();
  49. }
  50. /**
  51. * Returns an array with all the translations found for a set of records
  52. *
  53. * @param array|\Traversable $data
  54. * @return Collection
  55. */
  56. protected function _extractTranslations($data) {
  57. return (new Collection($data))->map(function ($row) {
  58. $translations = $row->get('_translations');
  59. if (!$translations) {
  60. return [];
  61. }
  62. return array_map(function ($t) {
  63. return $t->toArray();
  64. }, $translations);
  65. });
  66. }
  67. /**
  68. * Tests that fields from a translated model are overriden
  69. *
  70. * @return void
  71. */
  72. public function testFindSingleLocale() {
  73. $table = TableRegistry::get('Articles');
  74. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  75. $table->locale('eng');
  76. $results = $table->find()->combine('title', 'body', 'id')->toArray();
  77. $expected = [
  78. 1 => ['Title #1' => 'Content #1'],
  79. 2 => ['Title #2' => 'Content #2'],
  80. 3 => ['Title #3' => 'Content #3'],
  81. ];
  82. $this->assertSame($expected, $results);
  83. }
  84. /**
  85. * Tests that fields from a translated model use the I18n class locale
  86. * and that it propogates to associated models
  87. *
  88. * @return void
  89. */
  90. public function testFindSingleLocaleAssociatedEnv() {
  91. I18n::locale('eng');
  92. $table = TableRegistry::get('Articles');
  93. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  94. $table->hasMany('Comments');
  95. $table->Comments->addBehavior('Translate', ['fields' => ['comment']]);
  96. $results = $table->find()
  97. ->select(['id', 'title', 'body'])
  98. ->contain(['Comments' => ['fields' => ['article_id', 'comment']]])
  99. ->hydrate(false)
  100. ->toArray();
  101. $expected = [
  102. [
  103. 'id' => 1,
  104. 'title' => 'Title #1',
  105. 'body' => 'Content #1',
  106. 'comments' => [
  107. ['article_id' => 1, 'comment' => 'Comment #1', '_locale' => 'eng'],
  108. ['article_id' => 1, 'comment' => 'Comment #2', '_locale' => 'eng'],
  109. ['article_id' => 1, 'comment' => 'Comment #3', '_locale' => 'eng'],
  110. ['article_id' => 1, 'comment' => 'Comment #4', '_locale' => 'eng']
  111. ],
  112. '_locale' => 'eng'
  113. ],
  114. [
  115. 'id' => 2,
  116. 'title' => 'Title #2',
  117. 'body' => 'Content #2',
  118. 'comments' => [
  119. ['article_id' => 2, 'comment' => 'First Comment for Second Article', '_locale' => 'eng'],
  120. ['article_id' => 2, 'comment' => 'Second Comment for Second Article', '_locale' => 'eng']
  121. ],
  122. '_locale' => 'eng'
  123. ],
  124. [
  125. 'id' => 3,
  126. 'title' => 'Title #3',
  127. 'body' => 'Content #3',
  128. 'comments' => [],
  129. '_locale' => 'eng'
  130. ]
  131. ];
  132. $this->assertSame($expected, $results);
  133. I18n::locale('spa');
  134. $results = $table->find()
  135. ->select(['id', 'title', 'body'])
  136. ->contain(['Comments' => ['fields' => ['article_id', 'comment']]])
  137. ->hydrate(false)
  138. ->toArray();
  139. $expected = [
  140. [
  141. 'id' => 1,
  142. 'title' => 'First Article',
  143. 'body' => 'First Article Body',
  144. 'comments' => [
  145. ['article_id' => 1, 'comment' => 'First Comment for First Article', '_locale' => 'spa'],
  146. ['article_id' => 1, 'comment' => 'Second Comment for First Article', '_locale' => 'spa'],
  147. ['article_id' => 1, 'comment' => 'Third Comment for First Article', '_locale' => 'spa'],
  148. ['article_id' => 1, 'comment' => 'Comentario #4', '_locale' => 'spa']
  149. ],
  150. '_locale' => 'spa'
  151. ],
  152. [
  153. 'id' => 2,
  154. 'title' => 'Second Article',
  155. 'body' => 'Second Article Body',
  156. 'comments' => [
  157. ['article_id' => 2, 'comment' => 'First Comment for Second Article', '_locale' => 'spa'],
  158. ['article_id' => 2, 'comment' => 'Second Comment for Second Article', '_locale' => 'spa']
  159. ],
  160. '_locale' => 'spa'
  161. ],
  162. [
  163. 'id' => 3,
  164. 'title' => 'Third Article',
  165. 'body' => 'Third Article Body',
  166. 'comments' => [],
  167. '_locale' => 'spa'
  168. ]
  169. ];
  170. $this->assertSame($expected, $results);
  171. }
  172. /**
  173. * Tests that fields from a translated model are not overriden if translation
  174. * is null
  175. *
  176. * @return void
  177. */
  178. public function testFindSingleLocaleWithNullTranslation() {
  179. $table = TableRegistry::get('Comments');
  180. $table->addBehavior('Translate', ['fields' => ['comment']]);
  181. $table->locale('spa');
  182. $results = $table->find()
  183. ->where(['Comments.id' => 6])
  184. ->combine('id', 'comment')->toArray();
  185. $expected = [6 => 'Second Comment for Second Article'];
  186. $this->assertSame($expected, $results);
  187. }
  188. /**
  189. * Tests that overriding fields with the translate behavior works when
  190. * using conditions and that all other columns are preserved
  191. *
  192. * @return void
  193. */
  194. public function testFindSingleLocaleWithConditions() {
  195. $table = TableRegistry::get('Articles');
  196. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  197. $table->locale('eng');
  198. $results = $table->find()
  199. ->where(['Articles.id' => 2])
  200. ->all();
  201. $this->assertCount(1, $results);
  202. $row = $results->first();
  203. $expected = [
  204. 'id' => 2,
  205. 'title' => 'Title #2',
  206. 'body' => 'Content #2',
  207. 'author_id' => 3,
  208. 'published' => 'Y',
  209. '_locale' => 'eng'
  210. ];
  211. $this->assertEquals($expected, $row->toArray());
  212. }
  213. /**
  214. * Tests that translating fields work when other formatters are used
  215. *
  216. * @return void
  217. */
  218. public function testFindList() {
  219. $table = TableRegistry::get('Articles');
  220. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  221. $table->locale('eng');
  222. $results = $table->find('list')->toArray();
  223. $expected = [1 => 'Title #1', 2 => 'Title #2', 3 => 'Title #3'];
  224. $this->assertSame($expected, $results);
  225. }
  226. /**
  227. * Tests that the query count return the correct results
  228. *
  229. * @return void
  230. */
  231. public function testFindCount() {
  232. $table = TableRegistry::get('Articles');
  233. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  234. $table->locale('eng');
  235. $this->assertEquals(3, $table->find()->count());
  236. }
  237. /**
  238. * Tests that it is possible to get all translated fields at once
  239. *
  240. * @return void
  241. */
  242. public function testFindTranslations() {
  243. $table = TableRegistry::get('Articles');
  244. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  245. $results = $table->find('translations');
  246. $expected = [
  247. [
  248. 'eng' => ['title' => 'Title #1', 'body' => 'Content #1', 'locale' => 'eng'],
  249. 'deu' => ['title' => 'Titel #1', 'body' => 'Inhalt #1', 'locale' => 'deu'],
  250. 'cze' => ['title' => 'Titulek #1', 'body' => 'Obsah #1', 'locale' => 'cze']
  251. ],
  252. [
  253. 'eng' => ['title' => 'Title #2', 'body' => 'Content #2', 'locale' => 'eng'],
  254. 'deu' => ['title' => 'Titel #2', 'body' => 'Inhalt #2', 'locale' => 'deu'],
  255. 'cze' => ['title' => 'Titulek #2', 'body' => 'Obsah #2', 'locale' => 'cze']
  256. ],
  257. [
  258. 'eng' => ['title' => 'Title #3', 'body' => 'Content #3', 'locale' => 'eng'],
  259. 'deu' => ['title' => 'Titel #3', 'body' => 'Inhalt #3', 'locale' => 'deu'],
  260. 'cze' => ['title' => 'Titulek #3', 'body' => 'Obsah #3', 'locale' => 'cze']
  261. ]
  262. ];
  263. $translations = $this->_extractTranslations($results);
  264. $this->assertEquals($expected, $translations->toArray());
  265. $expected = [
  266. 1 => ['First Article' => 'First Article Body'],
  267. 2 => ['Second Article' => 'Second Article Body'],
  268. 3 => ['Third Article' => 'Third Article Body']
  269. ];
  270. $grouped = $results->combine('title', 'body', 'id');
  271. $this->assertEquals($expected, $grouped->toArray());
  272. }
  273. /**
  274. * Tests that it is possible to request just a few translations
  275. *
  276. * @return void
  277. */
  278. public function testFindFilteredTranslations() {
  279. $table = TableRegistry::get('Articles');
  280. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  281. $results = $table->find('translations', ['locales' => ['deu', 'cze']]);
  282. $expected = [
  283. [
  284. 'deu' => ['title' => 'Titel #1', 'body' => 'Inhalt #1', 'locale' => 'deu'],
  285. 'cze' => ['title' => 'Titulek #1', 'body' => 'Obsah #1', 'locale' => 'cze']
  286. ],
  287. [
  288. 'deu' => ['title' => 'Titel #2', 'body' => 'Inhalt #2', 'locale' => 'deu'],
  289. 'cze' => ['title' => 'Titulek #2', 'body' => 'Obsah #2', 'locale' => 'cze']
  290. ],
  291. [
  292. 'deu' => ['title' => 'Titel #3', 'body' => 'Inhalt #3', 'locale' => 'deu'],
  293. 'cze' => ['title' => 'Titulek #3', 'body' => 'Obsah #3', 'locale' => 'cze']
  294. ]
  295. ];
  296. $translations = $this->_extractTranslations($results);
  297. $this->assertEquals($expected, $translations->toArray());
  298. $expected = [
  299. 1 => ['First Article' => 'First Article Body'],
  300. 2 => ['Second Article' => 'Second Article Body'],
  301. 3 => ['Third Article' => 'Third Article Body']
  302. ];
  303. $grouped = $results->combine('title', 'body', 'id');
  304. $this->assertEquals($expected, $grouped->toArray());
  305. }
  306. /**
  307. * Tests that it is possible to combine find('list') and find('translations')
  308. *
  309. * @return void
  310. */
  311. public function testFindTranslationsList() {
  312. $table = TableRegistry::get('Articles');
  313. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  314. $results = $table
  315. ->find('list', [
  316. 'idField' => 'title',
  317. 'valueField' => '_translations.deu.title',
  318. 'groupField' => 'id'
  319. ])
  320. ->find('translations', ['locales' => ['deu']]);
  321. $expected = [
  322. 1 => ['First Article' => 'Titel #1'],
  323. 2 => ['Second Article' => 'Titel #2'],
  324. 3 => ['Third Article' => 'Titel #3']
  325. ];
  326. $this->assertEquals($expected, $results->toArray());
  327. }
  328. /**
  329. * Tests that you can both override fields and find all translations
  330. *
  331. * @return void
  332. */
  333. public function testFindTranslationsWithFieldOverriding() {
  334. $table = TableRegistry::get('Articles');
  335. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  336. $table->locale('cze');
  337. $results = $table->find('translations', ['locales' => ['deu', 'cze']]);
  338. $expected = [
  339. [
  340. 'deu' => ['title' => 'Titel #1', 'body' => 'Inhalt #1', 'locale' => 'deu'],
  341. 'cze' => ['title' => 'Titulek #1', 'body' => 'Obsah #1', 'locale' => 'cze']
  342. ],
  343. [
  344. 'deu' => ['title' => 'Titel #2', 'body' => 'Inhalt #2', 'locale' => 'deu'],
  345. 'cze' => ['title' => 'Titulek #2', 'body' => 'Obsah #2', 'locale' => 'cze']
  346. ],
  347. [
  348. 'deu' => ['title' => 'Titel #3', 'body' => 'Inhalt #3', 'locale' => 'deu'],
  349. 'cze' => ['title' => 'Titulek #3', 'body' => 'Obsah #3', 'locale' => 'cze']
  350. ]
  351. ];
  352. $translations = $this->_extractTranslations($results);
  353. $this->assertEquals($expected, $translations->toArray());
  354. $expected = [
  355. 1 => ['Titulek #1' => 'Obsah #1'],
  356. 2 => ['Titulek #2' => 'Obsah #2'],
  357. 3 => ['Titulek #3' => 'Obsah #3']
  358. ];
  359. $grouped = $results->combine('title', 'body', 'id');
  360. $this->assertEquals($expected, $grouped->toArray());
  361. }
  362. /**
  363. * Tests that fields can be overriden in a hasMany association
  364. *
  365. * @return void
  366. */
  367. public function testFindSingleLocaleHasMany() {
  368. $table = TableRegistry::get('Articles');
  369. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  370. $table->hasMany('Comments');
  371. $comments = $table->hasMany('Comments')->target();
  372. $comments->addBehavior('Translate', ['fields' => ['comment']]);
  373. $table->locale('eng');
  374. $comments->locale('eng');
  375. $results = $table->find()->contain(['Comments' => function ($q) {
  376. return $q->select(['id', 'comment', 'article_id']);
  377. }]);
  378. $list = new Collection($results->first()->comments);
  379. $expected = [
  380. 1 => 'Comment #1',
  381. 2 => 'Comment #2',
  382. 3 => 'Comment #3',
  383. 4 => 'Comment #4'
  384. ];
  385. $this->assertEquals($expected, $list->combine('id', 'comment')->toArray());
  386. }
  387. /**
  388. * Test that it is possible to bring translations from hasMany relations
  389. *
  390. * @return void
  391. */
  392. public function testTranslationsHasMany() {
  393. $table = TableRegistry::get('Articles');
  394. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  395. $table->hasMany('Comments');
  396. $comments = $table->hasMany('Comments')->target();
  397. $comments->addBehavior('Translate', ['fields' => ['comment']]);
  398. $results = $table->find('translations')->contain([
  399. 'Comments' => function ($q) {
  400. return $q->find('translations')->select(['id', 'comment', 'article_id']);
  401. }
  402. ]);
  403. $comments = $results->first()->comments;
  404. $expected = [
  405. [
  406. 'eng' => ['comment' => 'Comment #1', 'locale' => 'eng']
  407. ],
  408. [
  409. 'eng' => ['comment' => 'Comment #2', 'locale' => 'eng']
  410. ],
  411. [
  412. 'eng' => ['comment' => 'Comment #3', 'locale' => 'eng']
  413. ],
  414. [
  415. 'eng' => ['comment' => 'Comment #4', 'locale' => 'eng'],
  416. 'spa' => ['comment' => 'Comentario #4', 'locale' => 'spa']
  417. ]
  418. ];
  419. $translations = $this->_extractTranslations($comments);
  420. $this->assertEquals($expected, $translations->toArray());
  421. }
  422. /**
  423. * Tests that it is possible to both override fields with a translation and
  424. * also find separately other translations
  425. *
  426. * @return void
  427. */
  428. public function testTranslationsHasManyWithOverride() {
  429. $table = TableRegistry::get('Articles');
  430. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  431. $table->hasMany('Comments');
  432. $comments = $table->hasMany('Comments')->target();
  433. $comments->addBehavior('Translate', ['fields' => ['comment']]);
  434. $table->locale('cze');
  435. $comments->locale('eng');
  436. $results = $table->find('translations')->contain([
  437. 'Comments' => function ($q) {
  438. return $q->find('translations')->select(['id', 'comment', 'article_id']);
  439. }
  440. ]);
  441. $comments = $results->first()->comments;
  442. $expected = [
  443. 1 => 'Comment #1',
  444. 2 => 'Comment #2',
  445. 3 => 'Comment #3',
  446. 4 => 'Comment #4'
  447. ];
  448. $list = new Collection($comments);
  449. $this->assertEquals($expected, $list->combine('id', 'comment')->toArray());
  450. $expected = [
  451. [
  452. 'eng' => ['comment' => 'Comment #1', 'locale' => 'eng']
  453. ],
  454. [
  455. 'eng' => ['comment' => 'Comment #2', 'locale' => 'eng']
  456. ],
  457. [
  458. 'eng' => ['comment' => 'Comment #3', 'locale' => 'eng']
  459. ],
  460. [
  461. 'eng' => ['comment' => 'Comment #4', 'locale' => 'eng'],
  462. 'spa' => ['comment' => 'Comentario #4', 'locale' => 'spa']
  463. ]
  464. ];
  465. $translations = $this->_extractTranslations($comments);
  466. $this->assertEquals($expected, $translations->toArray());
  467. $this->assertEquals('Titulek #1', $results->first()->title);
  468. $this->assertEquals('Obsah #1', $results->first()->body);
  469. }
  470. /**
  471. * Tests that it is possible to translate belongsTo associations
  472. *
  473. * @return void
  474. */
  475. public function testFindSingleLocaleBelongsto() {
  476. $table = TableRegistry::get('Articles');
  477. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  478. $authors = $table->belongsTo('Authors')->target();
  479. $authors->addBehavior('Translate', ['fields' => ['name']]);
  480. $table->locale('eng');
  481. $authors->locale('eng');
  482. $results = $table->find()
  483. ->select(['title', 'body'])
  484. ->order(['title' => 'asc'])
  485. ->contain(['Authors' => function ($q) {
  486. return $q->select(['id', 'name']);
  487. }]);
  488. $expected = [
  489. [
  490. 'title' => 'Title #1',
  491. 'body' => 'Content #1',
  492. 'author' => ['id' => 1, 'name' => 'May-rianoh', '_locale' => 'eng'],
  493. '_locale' => 'eng'
  494. ],
  495. [
  496. 'title' => 'Title #2',
  497. 'body' => 'Content #2',
  498. 'author' => ['id' => 3, 'name' => 'larry', '_locale' => 'eng'],
  499. '_locale' => 'eng'
  500. ],
  501. [
  502. 'title' => 'Title #3',
  503. 'body' => 'Content #3',
  504. 'author' => ['id' => 1, 'name' => 'May-rianoh', '_locale' => 'eng'],
  505. '_locale' => 'eng'
  506. ]
  507. ];
  508. $results = array_map(function ($r) {
  509. return $r->toArray();
  510. }, $results->toArray());
  511. $this->assertEquals($expected, $results);
  512. }
  513. /**
  514. * Tests that updating an existing record translations work
  515. *
  516. * @return void
  517. */
  518. public function testUpdateSingleLocale() {
  519. $table = TableRegistry::get('Articles');
  520. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  521. $table->locale('eng');
  522. $article = $table->find()->first();
  523. $this->assertEquals(1, $article->get('id'));
  524. $article->set('title', 'New translated article');
  525. $table->save($article);
  526. $this->assertNull($article->get('_i18n'));
  527. $article = $table->find()->first();
  528. $this->assertEquals(1, $article->get('id'));
  529. $this->assertEquals('New translated article', $article->get('title'));
  530. $this->assertEquals('Content #1', $article->get('body'));
  531. $table->locale(false);
  532. $article = $table->find()->first();
  533. $this->assertEquals(1, $article->get('id'));
  534. $this->assertEquals('First Article', $article->get('title'));
  535. $table->locale('eng');
  536. $article->set('title', 'Wow, such translated article');
  537. $article->set('body', 'A translated body');
  538. $table->save($article);
  539. $this->assertNull($article->get('_i18n'));
  540. $article = $table->find()->first();
  541. $this->assertEquals(1, $article->get('id'));
  542. $this->assertEquals('Wow, such translated article', $article->get('title'));
  543. $this->assertEquals('A translated body', $article->get('body'));
  544. }
  545. /**
  546. * Tests adding new translation to a record
  547. *
  548. * @return void
  549. */
  550. public function testInsertNewTranslations() {
  551. $table = TableRegistry::get('Articles');
  552. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  553. $table->locale('fra');
  554. $article = $table->find()->first();
  555. $this->assertEquals(1, $article->get('id'));
  556. $article->set('title', 'Le titre');
  557. $table->save($article);
  558. $this->assertEquals('fra', $article->get('_locale'));
  559. $article = $table->find()->first();
  560. $this->assertEquals(1, $article->get('id'));
  561. $this->assertEquals('Le titre', $article->get('title'));
  562. $this->assertEquals('First Article Body', $article->get('body'));
  563. $article->set('title', 'Un autre titre');
  564. $article->set('body', 'Le contenu');
  565. $table->save($article);
  566. $this->assertNull($article->get('_i18n'));
  567. $article = $table->find()->first();
  568. $this->assertEquals('Un autre titre', $article->get('title'));
  569. $this->assertEquals('Le contenu', $article->get('body'));
  570. }
  571. /**
  572. * Tests that it is possible to use the _locale property to specify the language
  573. * to use for saving an entity
  574. *
  575. * @return void
  576. */
  577. public function testUpdateTranslationWithLocaleInEntity() {
  578. $table = TableRegistry::get('Articles');
  579. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  580. $article = $table->find()->first();
  581. $this->assertEquals(1, $article->get('id'));
  582. $article->set('_locale', 'fra');
  583. $article->set('title', 'Le titre');
  584. $table->save($article);
  585. $this->assertNull($article->get('_i18n'));
  586. $article = $table->find()->first();
  587. $this->assertEquals(1, $article->get('id'));
  588. $this->assertEquals('First Article', $article->get('title'));
  589. $this->assertEquals('First Article Body', $article->get('body'));
  590. $table->locale('fra');
  591. $article = $table->find()->first();
  592. $this->assertEquals(1, $article->get('id'));
  593. $this->assertEquals('Le titre', $article->get('title'));
  594. $this->assertEquals('First Article Body', $article->get('body'));
  595. }
  596. /**
  597. * Tests that translations are added to the whitelist of associations to be
  598. * saved
  599. *
  600. * @return void
  601. */
  602. public function testSaveTranslationWithAssociationWhitelist() {
  603. $table = TableRegistry::get('Articles');
  604. $table->hasMany('Comments');
  605. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  606. $table->locale('fra');
  607. $article = $table->find()->first();
  608. $this->assertEquals(1, $article->get('id'));
  609. $article->set('title', 'Le titre');
  610. $table->save($article, ['associated' => ['Comments']]);
  611. $this->assertNull($article->get('_i18n'));
  612. $article = $table->find()->first();
  613. $this->assertEquals('Le titre', $article->get('title'));
  614. }
  615. /**
  616. * Tests that after deleting a translated entity, all translations are also removed
  617. *
  618. * @return void
  619. */
  620. public function testDelete() {
  621. $table = TableRegistry::get('Articles');
  622. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  623. $article = $table->find()->first();
  624. $this->assertTrue($table->delete($article));
  625. $translations = TableRegistry::get('I18n')->find()
  626. ->where(['model' => 'Articles', 'foreign_key' => $article->id])
  627. ->count();
  628. $this->assertEquals(0, $translations);
  629. }
  630. /**
  631. * Tests saving multiple translations at once when the translations already
  632. * exist in the database
  633. *
  634. * @return void
  635. */
  636. public function testSaveMultipleTranslations() {
  637. $table = TableRegistry::get('Articles');
  638. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  639. $article = $results = $table->find('translations')->first();
  640. $translations = $article->get('_translations');
  641. $translations['deu']->set('title', 'Another title');
  642. $translations['eng']->set('body', 'Another body');
  643. $article->set('_translations', $translations);
  644. $table->save($article);
  645. $this->assertNull($article->get('_i18n'));
  646. $article = $results = $table->find('translations')->first();
  647. $translations = $article->get('_translations');
  648. $this->assertEquals('Another title', $translations['deu']->get('title'));
  649. $this->assertEquals('Another body', $translations['eng']->get('body'));
  650. }
  651. /**
  652. * Tests saving multiple existing translations and adding new ones
  653. *
  654. * @return void
  655. */
  656. public function testSaveMultipleNewTranslations() {
  657. $table = TableRegistry::get('Articles');
  658. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  659. $article = $results = $table->find('translations')->first();
  660. $translations = $article->get('_translations');
  661. $translations['deu']->set('title', 'Another title');
  662. $translations['eng']->set('body', 'Another body');
  663. $translations['spa'] = new Entity(['title' => 'Titulo']);
  664. $translations['fre'] = new Entity(['title' => 'Titre']);
  665. $article->set('_translations', $translations);
  666. $table->save($article);
  667. $this->assertNull($article->get('_i18n'));
  668. $article = $results = $table->find('translations')->first();
  669. $translations = $article->get('_translations');
  670. $this->assertEquals('Another title', $translations['deu']->get('title'));
  671. $this->assertEquals('Another body', $translations['eng']->get('body'));
  672. $this->assertEquals('Titulo', $translations['spa']->get('title'));
  673. $this->assertEquals('Titre', $translations['fre']->get('title'));
  674. }
  675. /**
  676. * Tests that iterating a resultset twice when using the translations finder
  677. * will not cause any errors nor information loss
  678. *
  679. * @return void
  680. */
  681. public function testUseCountInFindTranslations() {
  682. $table = TableRegistry::get('Articles');
  683. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  684. $articles = $results = $table->find('translations');
  685. $all = $articles->all();
  686. $this->assertCount(3, $all);
  687. $article = $all->first();
  688. $this->assertNotEmpty($article->get('_translations'));
  689. }
  690. /**
  691. * Tests that multiple translations saved when having a default locale
  692. * are correclty saved
  693. *
  694. * @return void
  695. */
  696. public function testSavingWithNonDefaultLocale() {
  697. $table = TableRegistry::get('Articles');
  698. $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
  699. $table->entityClass(__NAMESPACE__ . '\Article');
  700. I18n::locale('fra');
  701. $translations = [
  702. 'fra' => ['title' => 'Un article'],
  703. 'spa' => ['title' => 'Un artículo']
  704. ];
  705. $article = $table->get(1);
  706. foreach ($translations as $lang => $data) {
  707. $article->translation($lang)->set($data, ['guard' => false]);
  708. }
  709. $table->save($article);
  710. $article = $table->find('translations')->where(['Articles.id' => 1])->first();
  711. $this->assertEquals('Un article', $article->translation('fra')->title);
  712. $this->assertEquals('Un artículo', $article->translation('spa')->title);
  713. }
  714. }