I have already talked about the sfFormExtraPlugin in a previous post and people were quite amazed by some widgets provided by the plugin.

Today, I will talk about sfFormLanguage, a form also provided by the sfFormExtraPlugin plugin.

Let the user change his language

sfFormLanguage allows the user to change his current language:

sfFormExtraPlugin form

To create a sfFormLanguage form, you need to pass the symfony user object (sfUser) and an array of supported languages:

class mainActions extends sfActions
{
  public function executeChangeLanguage($request)
  {
    $this->form = new sfFormLanguage($this->getUser(), array('languages' => array('en', 'fr')));
  }
}
 

The related template is quite straightforward:

<form action="<?php echo url_for('@change_language') ?>" method="post">
  <label for="language">Choose a language:</label>
  <?php echo $form['language'] ?>
  <?php echo $form->renderHiddenFields() ?>
  <input type="submit" value="ok">
</form>
 

When the user submits the form (post), we need to process it:

class mainActions extends sfActions
{
  public function executeChangeLanguage($request)
  {
    $this->form = new sfFormLanguage($this->getUser(), array('languages' => array('en', 'fr')));
 
    if ($request->isMethod('post'))
    {
      $this->form->process($request);
 
      return $this->redirect('@homepage');
    }
  }
}
 

The sfFormLanguage::process() method takes the current request as a parameter, binds the form with the data provided in the request, validates the form, and if the form is valid, automatically changes the user culture.

The above code does not manage form errors because it can't really happen, except if the user fakes the select values. In such a case, we don't really care if an error is displayed or not. But if you want to, the process() method returns true if the culture has been changed and false otherwise (if there was an error during validation for example):

class mainActions extends sfActions
{
  public function executeChangeLanguage($request)
  {
    $this->form = new sfFormLanguage($this->getUser(), array('languages' => array('en', 'fr')));
    if ($this->form->process($request))
    {
      // culture has been changed
      return $this->redirect('@homepage');
    }
 
    // the form is not valid (can't happen... but you never know)
    return $this->redirect('@homepage');
  }
}
 

sfFormLanguage is simple to use and very useful for internationalized website.

How to guess the language of the user?

When a user comes to your website for the first time, it is sometimes desirable to display the homepage in her "preferred" language. The symfony request object provides a getPreferredCulture() method that does the work for you. So, it is just a matter of changing the current user culture by the preferred one:

$user->setCulture($request->getPreferredCulture(array('en', 'fr')));
 

The getPreferredCulture() method takes an array of ordered cultures you support on your website.

It guesses the best culture possible, based on the HTTP_ACCEPT_LANGUAGE HTTP header. It returns the fist match between the HTTP header and your array of languages. If there is no match, the method returns the first supported culture (en in this example).