Internacionalización proyecto en CakePHP 3

Una tarea muy frecuente en proyectos grandes es la internacionalización del contenido del sitio web. En CakePHP 3 es muy sencillo hacerlo, en unos pocos pasos conseguiremos gestionar contenido de nuestras tablas en varios idiomas. Utilizaremos la tabla articles y el campo title para mantener una traducción al francés y español.

Paso 1

Ejecutaremos la siguiente sentencia SQL para crear la tabla.

CREATE TABLE IF NOT EXISTS `articles` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `body` text NOT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;


Paso 2

Ahora crearemos la tabla i18N que será la responsable de almacenar las traducciones. El fichero con la sentencias sql para crear esta tabla se encuentra en config/schema/i18n.sql.

CREATE TABLE i18n (
    id int NOT NULL auto_increment,
    locale varchar(6) NOT NULL,
    model varchar(255) NOT NULL,
    foreign_key int(10) NOT NULL,
    field varchar(255) NOT NULL,
    content text,
    PRIMARY KEY     (id),
    UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field),
    INDEX I18N_FIELD(model, foreign_key, field)
);
    

Paso 3

Ejecutaremos el comando bake para crear el controlador y las vistas de Artículos. Abre una ventana de terminal y sitúate en la carpeta raíz de tu proyecto. Ejecuta el siguiente comando:

sudo bin/cake bake all articles

Este comando creará el modelo, controlador y vistas de articles.

Paso 4

Abre el archivo /src/Model/Table/ArticlesTable.php y añádele el behaviour Trasnlate al objeto tabla. Añade la siguiente instrucción en la función initialize: $this->addBehavior('Translate', ['fields' => ['title', 'body']]);

class ArticlesTable extends Table
{
    public function initialize(array $config)
    {
       $this->addBehavior('Translate', ['fields' => ['title']]);
    }
}

Paso 5

Para hacer múltiples traducciones necesitamos modificar la clase Entity: /src/Model/Entity/Article.php

use Cake\ORM\Behavior\Translate\TranslateTrait;
use Cake\ORM\Entity;
class Article extends Entity
{
    use TranslateTrait;
}

Necesitamos incluir las siguientes lineas al inicio del fichero del controlador Articles.

use Cake\ORM\Behavior\Translate\TranslateTrait;
use Cake\I18n\I18n;

Crearemos una función para añadir las traducciones a la tabla i18n.

public function newTranslation(){
        $article = $this->Articles->newEntity();
        if ($this->request->is('post')) {
            $article = $this->Articles->patchEntity($article, $this->request->data);
            if(isset($this->request->data['french']) && !empty($this->request->data['french'])){
                $article->translation('fr')->title = $this->request->data['french'];
            }
            if(isset($this->request->data['spanish']) && !empty($this->request->data['spanish'])){
                $article->translation('es')->title = $this->request->data['spanish'];
            }
            // Added this line
            $article->user_id = $this->Auth->user('id');

            if ($this->Articles->save($article)) {
                $this->Flash->success(__('Your article has been saved.'));
                return $this->redirect(['action' => 'index']);
            }
            $this->Flash->error(__('Unable to add your article.'));
        }
        $this->set('article', $article);
        // Just added the categories list to be able to choose
        // one category for an article
        $categories = $this->Articles->Categories->find('treeList');
        $this->set(compact('categories'));
    }

Las funciones $article->translation('fr')->title y $article->translation('es')->title son las encargadas de grabar las correspondientes traducciones en la tabla i18n. Quedarían de la siguiente manera:

Paso 6

Ahora crearemos el archivo de la vista para esta función en /src/Template/Articles/new_translation.ctp.


Add New Article

Podrás ver el listado de artículos en la siguiente dirección: http://localhost/articles Para mostrar un listado de artículos en castellano hay que añadir la siguiente instrucción: "I18n::locale('es')".

public function index()
    {
        I18n::locale('es'); // Translate is Spanish
        $articles = $this->;paginate($this->;Articles);
        $this->set(compact('articles'));
        $this->set('_serialize', ['articles']);
    }

Y obtendremos la siguiente salida:

Si necesitas más información puedes consultar el manual de CakePHP3 en su sección de Translate y Internacionalitation y localization.

Volver al índice del blog