Ver índice de contenidos del libro

19.2. Incluyendo la cultura en la URL

El sitio web de Jobeet está disponible en inglés y francés. Como una misma URL sólo puede representar un único recurso, debemos incluir la cultura como parte de la URL. Para ello, abre el archivo routing.yml y añade la variable especial :sf_culture en todas las rutas salvo en api_jobs y homepage. En las rutas sencillas, añade /:sf_culture al principio de la URL. En las colecciones de rutas, añade /:sf_culture al principio del valor de la opción prefix_path.

# apps/frontend/config/routing.yml
affiliate:
  class: sfPropelRouteCollection
  options:
    model:          JobeetAffiliate
    actions:        [new, create]
    object_actions: { wait: get }
    prefix_path:    /:sf_culture/affiliate

category:
  url:     /:sf_culture/category/:slug.:sf_format
  class:   sfPropelRoute
  param:   { module: category, action: show, sf_format: html }
  options: { model: JobeetCategory, type: object }
  requirements:
    sf_format: (?:html|atom)

job_search:
  url:   /:sf_culture/search
  param: { module: job, action: search }

job:
  class: sfPropelRouteCollection
  options:
    model:          JobeetJob
    column:         token
    object_actions: { publish: put, extend: put }
    prefix_path:    /:sf_culture/job
  requirements:
    token: \w+

job_show_user:
  url:     /:sf_culture/job/:company_slug/:location_slug/:id/:position_slug
  class:   sfPropelRoute
  options:
    model: JobeetJob
    type:  object
    method_for_criteria: doSelectActive
  param:   { module: job, action: show }
  requirements:
    id:        \d+
    sf_method: get

Cuando se incluye la variable sf_culture en una ruta, Symfony utiliza su valor para modificar automáticamente la cultura del usuario.

Como tenemos tantas portadas como idiomas soportados por la aplicación (/en/, /fr/, ...), la portada por defecto (/) debe redirigir al usuario a la portada adecuada en función de su cultura. Sin embargo, si es la primera vez que el usuario entra en Jobeet, el usuario todavía no tiene definida su cultura, por lo que debemos elegir la cultura que mejor se adapte al usuario.

En primer lugar, añade el método isFirstRequest() en la clase myUser. Se trata de un método sencillo que devuelve true sólo para la primera petición realizada en cada sesión de usuario:

// apps/frontend/lib/myUser.class.php
public function isFirstRequest($boolean = null)
{
  if (is_null($boolean))
  {
    return $this->getAttribute('first_request', true);
  }
  else
  {
    $this->setAttribute('first_request', $boolean);
  }
}

Añade también una ruta llamada localized_homepage:

# apps/frontend/config/routing.yml
localized_homepage:
  url:   /:sf_culture/
  param: { module: job, action: index }
  requirements:
    sf_culture: (?:fr|en)

A continuación, modifica la acción index del módulo job para incluir la lógica que se encarga de redirigir al usuario a la mejor portada cuando realiza la primera petición de su sesión de usuario:

// apps/frontend/modules/job/actions/actions.class.php
public function executeIndex(sfWebRequest $request)
{
  if (!$request->getParameter('sf_culture'))
  {
    if ($this->getUser()->isFirstRequest())
    {
      $culture = $request->getPreferredCulture(array('en', 'fr'));
      $this->getUser()->setCulture($culture);
      $this->getUser()->isFirstRequest(false);
    }
    else
    {
      $culture = $this->getUser()->getCulture();
    }
 
    $this->redirect('@localized_homepage');
  }
 
  $this->categories = JobeetCategoryPeer::getWithJobs();
}

Si no existe la variable sf_culture en la petición, eso significa que el usuario ha entrado en la URL /. Si estamos en ese caso y la sesión es nueva, se utiliza la cultura preferida por el usuario. En otro caso, se sigue utilizando la cultura actual del usuario.

El último paso consiste en redirigir al usuario a la ruta localized_homepage. Si te fijas en el código anterior, en la redirección no hemos incluido el valor de la variable sf_culture, ya que Symfony se encarga de añadirla automáticamente.

Si ahora intentas acceder a la URL /it/, Symfony devuelve un error de tipo 404 porque hemos restringido los posibles valores de la variable sf_culture a en o fr. Por tanto, añade este requerimiento en todas las rutas que incluyen la cultura:

requirements:
  sf_culture: (?:fr|en)