Ver índice de contenidos del libro

19.4. Cambiando de idioma

Para que el usuario pueda modificar su cultura, debemos incluir en el layout un formulario para cambiar de idioma. El framework de formularios de Symfony no incluye por defecto un formulario de este tipo, pero como se trata de algo bastante común para los sitios web disponibles en varios idiomas, los propios creadores de Symfony mantienen un plugin llamado sfFormExtraPlugin que contiene validadores, widgets y formularios que son útiles pero que no se incluyen por defecto en Symfony porque son demasiado específicos o contienen dependencias externas.

Instala el plugin mediante la tarea plugin:install:

$ php symfony plugin:install sfFormExtraPlugin

No te olvides de borrar la cache de Symfony porque este plugin define clases nuevas:

$ php symfony cc

Nota El plugin sfFormExtraPlugin contiene widgets que incluyen dependencias externas con librerías de JavaScript. Entre otros, este plugin contiene un editor avanzado de fechas y un editor de textos WYSIWYG. Te recomendamos que leas la documentación del plugin para descubrir cosas muy interesantes.

El plugin sfFormExtraPlugin incluye sfFormLanguage, un tipo de formulario que permite seleccionar el idioma de la aplicación. A continuación se muestra cómo puedes añadir el formulario del idioma en el layout:

Nota El código que se muestra a continuación no es la forma más adecuada de incluir el formulario. Incluimos este código para mostrar la forma equivocada de incluir este formulario. Más adelante se muestra cómo incluir bien el formulario en la aplicación Symfony.

// apps/frontend/templates/layout.php
<div id="footer">
  <div class="content">
    <!-- footer content -->
 
    <?php $form = new sfFormLanguage(
      $sf_user,
      array('languages' => array('en', 'fr'))
      )
    ?>
    <form action="<?php echo url_for('@change_language') ?>">
      <?php echo $form ?><input type="submit" value="ok" />
    </form>
  </div>
</div>

¿Te has dado cuenta del error? Efectivamente, crear el objeto del formulario no es algo propio de la capa de la vista. Este objeto se debe crear en la acción. Como el código se ha incluido en el layout, el formulario se crea en cada acción, algo que no es nada práctico. En estos casos, debes utilizar un componente. Los componentes son como los elementos parciales pero con código asociado. Se podría considerar que un componente es como una acción muy simplificada.

Los componentes definidos por las plantillas se incluyen en el layout mediante el helper include_component():

// apps/frontend/templates/layout.php
<div id="footer">
  <div class="content">
    <!-- footer content -->
 
    <?php include_component('language', 'language') ?>
  </div>
</div>

Los argumentos del helper include_component() son el nombre del módulo y el nombre de la acción. Se puede utilizar un tercer argumento opcional para pasar parámetros al componente.

Crea un módulo llamado language para poder definir el componente y la acción que van a modificar el idioma del usuario:

$ php symfony generate:module frontend language

Los componentes se definen en el archivo actions/components.class.php. Crea ese archivo y añade lo siguiente:

// apps/frontend/modules/language/actions/components.class.php
class languageComponents extends sfComponents
{
  public function executeLanguage(sfWebRequest $request)
  {
    $this->form = new sfFormLanguage(
      $this->getUser(),
      array('languages' => array('en', 'fr'))
    );
  }
}

Como se puede observar en el código anterior, la clase de los componentes es muy similar a la clase de las acciones.

Además, el nombre de la plantilla de un componente sigue las mismas convenciones que en los elementos parciales: un guión bajo (_) seguido por el nombre del componente:

// apps/frontend/modules/language/templates/_language.php
<form action="<?php echo url_for('@change_language') ?>">
  <?php echo $form ?><input type="submit" value="ok" />
</form>

Como el plugin no incluye la acción que realmente cambia la cultura del usuario, modifica el archivo routing.yml para crear una nueva ruta llamada change_language:

# apps/frontend/config/routing.yml
change_language:
  url:   /change_language
  param: { module: language, action: changeLanguage }

Y después se crea la acción correspondiente:

// apps/frontend/modules/language/actions/actions.class.php
class languageActions extends sfActions
{
  public function executeChangeLanguage(sfWebRequest $request)
  {
    $form = new sfFormLanguage(
      $this->getUser(),
      array('languages' => array('en', 'fr'))
    );
 
    $form->process($request);
 
    return $this->redirect('@localized_homepage');
  }
}

El método process() del formulario sfFormLanguage se encarga de modificar la cultura del usuario en función de la información enviada por el usuario.

Pie de página internacionalizado

Figura 19.1 Pie de página internacionalizado