I have a table with all entries including all translations in multiple languages: How can I create pagination sort links on translated fields? (Cake 3.1.6)
Summary: This is not working, I can't sort by the translations this way:
$this->Paginator->sort('_translations.es.title', 'Spanish')
Long version:
- I'm using a i18n table with translate behavior.
- I'm listing all translations (multiple languages) combined in a single table.
- And now I want to use pagination sort links on the translations (sort by language).
| Title ENGLISH | Title SPANISH | Title GERMAN | = pagination sort links
| ---------------- | ---------------- | --------------- |
| Christmas | Navidad | Weihnachten |
| Spring | Primavera | Frühling |
| ...
So here is my simplified test setup:
Table Articles has only one field title
to be translated.
i18n table is default setup as described in the book.
Baked Table class /src/Model/Table/ArticlesTable.php
, added Translate Behaviour:
public function initialize(array $config) {
// ... default config (removed in this post to simplify code)
$this->addBehavior('Translate', ['fields' => ['title']]); // added this line
}
Baked Entity class /src/Model/Entity/Article.php
, added TranslateTrait:
namespace App\Model\Entity;
use Cake\ORM\Behavior\Translate\TranslateTrait; // added this line
use Cake\ORM\Entity;
class Article extends Entity {
protected $_accessible = [
'*' => true,
'id' => false,
];
use TranslateTrait; // added this line
}
Baked Controller /src/Controller/ArticlesController.php
, modified as below:
namespace App\Controller;
use App\Controller\AppController;
class ArticlesController extends AppController {
public $paginate = [
'sortWhitelist' => [ // Allow pagination sort on this fields:
'title',
'_translations.es.title',
'_translations.de.title'
]
];
public function index() {
$query = $this->Articles->find('translations'); // Retrieve All Translations
$this->set('articles', $this->paginate($query));
}
}
Baked View /src/Template/Articles/index.ctp
, modified/simplified:
<table>
<tr>
<th><?= $this->Paginator->sort('title', 'English') ?></th>
<th><?= $this->Paginator->sort('_translations.es.title', 'Spanish') ?></th>
<th><?= $this->Paginator->sort('_translations.de.title', 'German') ?></th>
</tr>
<?php foreach ($articles as $article): ?>
<tr>
<td><?= h($article->title) ?></td>
<td><?= h($article->_translations['es']->title) ?></td>
<td><?= h($article->_translations['de']->title) ?></td>
</tr>
<?php endforeach; ?>
</table>
The translations in the table are shown correctly, but it's not possible to sort by the translated fields. When I click on the pagination links for the translations I get the following error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column '_translations.es' in 'order clause'
SQL Query:
SELECT Articles.id AS `Articles__id`,
Articles.title AS `Articles__title`,
Articles.created AS `Articles__created`,
Articles.modified AS `Articles__modified`
FROM articles Articles
ORDER BY _translations.es asc LIMIT 20 OFFSET 0
In this similar question the format Posts_title_translation.content
is used - I have no idea where this is coming from, but I also tried it this way (of course I also added the variants of the field names in the paginator whitelist):
$this->Paginator->sort('Articles_title_translation', 'Spanish')
$this->Paginator->sort('Articles_title_translation.es', 'Spanish')
$this->Paginator->sort('Articles_title_translation.content', 'Spanish')
$this->Paginator->sort('Articles_title_translation.es.content', 'Spanish')
None of them is working... (obviously)
How can I sort the table items by the i18n translations of the title field?