Code snippets for symfony 1.x

Navigation

Refine Tags

Snippets tagged "culture"

Get a date from a culture dependent source

In an i18n application, if your template uses the input_date_tag() helper, the format of the date sent to the submit action will depend on the user culture. But then, how can you handle this date to, say, store it in a database in a culture independent format?

The answer lies in the sfI18N class:

$date= sfContext::getInstance()->getRequest()->getParameter('birth_date');
$user_culture = sfContext::getInstance()->getUser()->getCulture();
list($d, $m, $y) = sfI18N::getDateForCulture(
  $date,
  $user_culture
);

Now you have the day, month and year of the date in the $d, $m and $y variables, and you can do whatever you want with them.

If you use a Propel date setter, you can even call it directly with:

$person->setBirthDate("$y-$m-$d");

The same applies for the sfI18N::getTimestampForCulture() method.

by Francois Zaninotto on 2006-06-23, tagged culture  date  i18n 

default culture content fallback for i18n tables

By default, I18n content in database does not support fallback in default culture. This snippet allow you to enable I18n content fallback in order to always have a default value for your texts.

This snippet is sponsored by Dorigo consultants.

Fallback I18n content

To enable the fallback, edit your table object class in lib/model/TableClassName.php and add the following code. Then search and replace TableClassName by your table object class name.

  /**
   * Fetch the i18n object for this object culture.
   * 
   * @return     mixed A i18n object
   * @throws     PropelException Any exceptions caught during processing will be
   *     rethrown wrapped into a PropelException.
   */
  public function getCurrentTableClassNameI18n()
  {
    if (!isset($this->current_i18n[$this->culture]))
    {
      $obj = TableClassNameI18nPeer::retrieveByPK($this->getId(), $this->culture);
      if ($obj) // Test if there is a translation for current culture
      {
        $this->setTableClassNameI18nForCulture($obj, $this->culture);
      }
      else // Create a translation for this culture
      {
        $new_i18n = new TableClassNameI18n();
 
        $default_culture = sfConfig::get('sf_i18n_default_culture');
 
        // We try to fetch the default culture translation to initialise the new culture.
        if (!isset($this->current_i18n[$default_culture]))
        {
          $obj = TableClassNameI18nPeer::retrieveByPK($this->getId(), $default_culture);
          if ($obj) // Test if there is a translation for current culture
          {
            $this->setTableClassNameI18nForCulture($obj, $default_culture);
          }
        }
        else
        {
          $obj = $this->current_i18n[$default_culture];
        }
 
        if ($obj)
        {
          $obj->copyInto($new_i18n);
        }
 
        $new_i18n->setId($this->getId());
        $new_i18n->setCulture($this->culture);
 
        $this->setTableClassNameI18nForCulture($new_i18n, $this->culture);
      }
    }
 
    return $this->current_i18n[$this->culture];
  }
 

Saving fallback values at creation

You now need to add default translation when you create a new object. We do that with this doSave function.

To use this function, edit your table object class in lib/model/TableClassName.php and add the following code. Then search and replace TableClassName by your table object class name.

  /**
   * Stores the object in the database while setting default culture if necessary.
   *
   * If the object is new, it inserts it; otherwise an update is performed.
   * All related objects are also updated in this method.
   *
   * @param      Connection $con The database connection
   * @return     int The number of rows affected by this insert/update and any referring fk objects' save() operations.
   * @throws     PropelException Any exceptions caught during processing will be
   *     rethrown wrapped into a PropelException.
   * @see        save()
   */
  protected function doSave($con)
  {
 
    $default_culture = sfConfig::get('sf_i18n_default_culture');
 
    // We try to fetch the default culture translation to initialise the new culture.
    if (!isset($this->current_i18n[$default_culture]))
    {
      $obj = TableClassNameI18nPeer::retrieveByPK($this->getId(), $default_culture, $con);
      if ($obj) // Test if there is a translation for current culture
      {
        $this->setTableClassNameI18nForCulture($obj, $default_culture);
      }
    }
    else
    {
      $obj = $this->current_i18n[$default_culture];
    }
 
    if(!$obj && isset($this->current_i18n[$this->culture]))
    {
      $new_i18n = new TableClassNameI18n();
      $this->current_i18n[$this->culture]->copyInto($new_i18n);
 
      $new_i18n->setId($this->getId());
      $new_i18n->setCulture($default_culture);
 
      $this->setTableClassNameI18nForCulture($new_i18n, $default_culture);
    }
 
    return parent::doSave($con);
  }
 

Fetching a list with default translations

To complete this snippet, here is a fallback version of doSelectWithI18n.

To enable the fallback, edit your table object peer class in lib/model/TableClassNamePeer.php and add the following code. Then search and replace TableClassName by your table object class name.

  /**
   * Selects a collection of TableClassName objects pre-filled with their i18n objects.
   *
   * @param      Criteria $criteria
   * @param      string $culture The selected culture.
   * @param      Connection $con An optional database connection
   * @return     array Array of TableClassName objects.
   * @throws     PropelException Any exceptions caught during processing will be
   *     rethrown wrapped into a PropelException.
   */
  public static function doSelectWithI18n(Criteria $c, $culture = null, $con = null)
  {
    if ($culture === null)
    {
      $culture = sfContext::getInstance()->getUser()->getCulture();
    }
 
    $default_culture = sfConfig::get('sf_i18n_default_culture');
 
    // Set the correct dbName if it has not been overridden
    if ($c->getDbName() == Propel::getDefaultDB())
    {
      $c->setDbName(self::DATABASE_NAME);
    }
 
    TableClassNamePeer::addSelectColumns($c);
    $startcol = (TableClassNamePeer::NUM_COLUMNS - TableClassNamePeer::NUM_LAZY_LOAD_COLUMNS) + 1;
 
    TableClassNameI18nPeer::addSelectColumns($c);
 
    $c->addJoin(TableClassNamePeer::ID, TableClassNameI18nPeer::ID);
    $criterion = $c->getNewCriterion(TableClassNameI18nPeer::CULTURE, $culture);
    $criterion->addOr($c->getNewCriterion(TableClassNameI18nPeer::CULTURE, $default_culture));
    $c->add($criterion);
 
    $rs = BasePeer::doSelect($c, $con);
    $results = array();
    $uncultured_results = array();
 
    while($rs->next()) {
 
      $omClass = TableClassNamePeer::getOMClass();
 
      $cls = Propel::import($omClass);
      $obj1 = new $cls();
      $obj1->hydrate($rs);
      $obj1->setCulture($culture);
 
      if(isset($results[$obj1->getId()]))
      {
        $obj1 = $results[$obj1->getId()];
      }
 
      $omClass = TableClassNameI18nPeer::getOMClass($rs, $startcol);
 
      $cls = Propel::import($omClass);
      $obj2 = new $cls();
      $obj2->hydrate($rs, $startcol);
 
      $obj1->setTableClassNameI18nForCulture($obj2, $obj2->getCulture());
      $obj2->setTableClassName($obj1);
 
      if(!isset($uncultured_results[$obj1->getId()]))
      {
        $uncultured_results[$obj1->getId()] = $obj1;
      }
 
      if($obj2->getCulture() == $culture)
      {
        $uncultured_results[$obj1->getId()] = false;
      }
 
      if(!isset($results[$obj1->getId()]))
      {
        $results[$obj1->getId()] = $obj1;
      }
      elseif($obj2->getCulture() == $culture)
      {
        // Move result to the end of results array to fit eventual sort
        // criteria (ugly fix).
        unset($results[$obj1->getId()]);
        $results[$obj1->getId()] = $obj1;
      }
 
    }
 
    foreach($uncultured_results as $obj1)
    {
      if($obj1)
      {
        $obj1->setCulture($default_culture);
        $default_culture_object = $obj1->getCurrentTableClassNameI18n();
        if($default_culture_object)
        {
          $obj2 = new TableClassNameI18n();
          $default_culture_object->copyInto($obj2);
          $obj2->setCulture($culture);
          $obj2->setTableClassName($obj1);
          $obj1->setTableClassNameI18nForCulture($obj2, $obj2->getCulture());
        }
        $obj1->setCulture($culture);
      }
    }
 
    return array_values($results);
  }
 

Counting results filtered on translations

If you want to use a pager with a filter on translations, you will need this count method. Once this method present, the magic is done by :

    $criteria->setDistinct();
    $pager->setCriteria($criteria);
    $pager->setPeerMethod('doSelectWithI18n');
    $pager->setPeerCountMethod('doCountWithI18n');
 

Note : The setDistinct is very important for this snippet to work. It should not falsify your results, and without it, the doCountWithI18n method could return bad results.

To enable the fallback, edit your table object peer class in lib/model/TableClassNamePeer.php and add the following code. Then search and replace TableClassName by your table object class name.

  /**
   * Returns the number of rows matching criteria with I18N criteria.
   *
   * @param      Criteria $criteria
   * @param      boolean $distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria).
   * @param      Connection $con An optional database connection
   * @param      string $culture The selected culture.
   * @return     int Number of matching rows.
   */
  public static function doCountWithI18n(Criteria $criteria, $distinct = false, $con = null, $culture = null)
  {
    // we're going to modify criteria, so copy it first
    $criteria = clone $criteria;
 
    $default_culture = sfConfig::get('sf_i18n_default_culture');
 
    if ($culture === null)
    {
      // We use current user culture.
      $culture = sfContext::getInstance()->getUser()->getCulture();
    }
 
    // clear out anything that might confuse the ORDER BY clause
    $criteria->clearSelectColumns()->clearOrderByColumns();
    $criteria->addSelectColumn(TableClassNamePeer::COUNT_DISTINCT);
 
    // just in case we're grouping: add those columns to the select statement
    foreach($criteria->getGroupByColumns() as $column)
    {
      $criteria->addSelectColumn($column);
    }
 
    $criteria->addJoin(TableClassNamePeer::ID, TableClassNameI18nPeer::ID);
    $criterion = $criteria->getNewCriterion(TableClassNameI18nPeer::CULTURE, $culture);
    $criterion->addOr($criteria->getNewCriterion(TableClassNameI18nPeer::CULTURE, $default_culture));
    $criteria->add($criterion);
 
    $rs = TableClassNamePeer::doSelectRS($criteria, $con);
    if ($rs->next()) {
      return $rs->getInt(1);
    } else {
      // no rows returned; we infer that means 0 matches.
      return 0;
    }
  }
 
by Pierre-Yves Landuré on 2007-10-10, tagged culture  data  database  i18n  object  propel 
(4 comments)

Browser culture detection

This filter use the accepted-languages browser setting to setup the user culture. The autodetection is run once by session.

This filter is sponsored by Dorigo consultants.

It check app.yml for accepted_languages setting in order to fit the available application locales.

It allow the use of sf_culture request parameter overide (this overide is avaible by default in symfony afaik). So you can use language changing links in your application.

It may be enhanced by a check of the really available locales but i don't know how it can be done.

To use this filter, create a file named SwitchLanguageFilter.class.php in lib/ or app/frontend/lib and fill it with this code and follow its documentation :

<?php
/**
 * Setup user culture from request
 * 
 * from http://www.symfony-project.com/snippets/snippet/80
 * Thanks to François Zaninotto
 * Thanks to Garfield-fr on #symfony-fr
 * 
 * Add the following lines in your app.yml to configure your application available languages.
 *   all:
 *     accepted:
 *       languages: [en, fr]
 * 
 * Then add this to your filters.yml
 * 
 *   # Filter that setup user culture
 *   mySwitchLanguageFilter:
 *     class: SwitchLanguageFilter
 * 
 * @package    SwitchLanguageFilter
 * @subpackage filter
 * @author     Pierre-Yves Landuré <py.landure@dorigo.fr>
 */
 
class SwitchLanguageFilter extends sfFilter
{
 
  /**
   * Check that the language is a valid application culture.
   * @param string $language The tested language code
   * @param string $default_language The default language code
   * 
   * @return string $language if no accepted languages is set,
   *                else $language if it is in accepted languages
   *                else $default_language
   */
  private function getAvailableCulture($language, $default_language = null)
  {
    $all_languages = sfConfig::get('app_accepted_languages', array());
 
    if(count($all_languages))
    {
      if(in_array($language, $all_languages)) // Test if language is available
      {
        return $language;
      }
      else // Else test if first part of language is available
      {
        $language_parts = explode('_', $language);
        if(count($language_parts))
        {
          if(in_array($language_parts[0], $all_languages))
          {
            return $language_parts[0];
          }
        }
      }
      return $default_language;
    }
 
    return $language;
  }
 
  /**
   * The filter call.
   */
  public function execute ($filterChain)
  {
    $context = $this->getContext();
    $user = $context->getUser();
 
    $default_culture = sfConfig::get('sf_i18n_default_culture');
    $selected_culture = $user->getCulture();
 
    if(!$user->getAttribute('sf_culture_autodetected', false))
    {
      $browser_languages = $context->getRequest()->getLanguages();
 
      foreach($browser_languages as $language)
      {
        $allowed_culture = $this->getAvailableCulture($language);
        if($allowed_culture)
        {
          $selected_culture = $allowed_culture;
          break;
        }
      }
 
      $user->setAttribute('sf_culture_autodetected', true);
    }
 
    $selected_culture = $context->getRequest()->getParameter('sf_culture', $selected_culture);
    $selected_culture = $this->getAvailableCulture($selected_culture, $default_culture);
    if($selected_culture != $user->getCulture())
    {
      // The user wants to see the page in another language
      $user->setCulture($selected_culture);
    }
 
    $filterChain->execute();
  }
}
 
by Pierre-Yves Landuré on 2007-10-09, tagged culture  filter  i18n  request 

Switch culture from any page of your site and improve SEO

CONTEXT

Symfony internationalization is normally managed using session variables. To switch culture you can visit a page that first changes you session variable and then send you back to the page you were visiting, but this potentially breaks your SEO.

Adding culture in every URL is a better solution, but if you want to go back to the page you were visiting, you have to deal with redirection by yourself.

This widget solves the redirection issue by creating localized urls.

CODE

Save your file here: apps/appname/lib/helper/I18nUrlHelper.php

/*
 * Generate a localized version for the URL you are visiting.
 */
 
function localized_current_url($sf_culture = null)
{
  if (! $sf_culture)
  {
    throw new sfException(sprintf('Invalid parameter $sf_culture "%s".', $sf_culture));
  }
 
  $routing    = sfContext::getInstance()->getRouting();
  $request    = sfContext::getInstance()->getRequest();
  $controller = sfContext::getInstance()->getController();
 
  // depending on your routing configuration, you can set $route_name = $routing->getCurrentRouteName()
  $route_name = '';
 
  $parameters = $controller->convertUrlStringToParameters($routing->getCurrentInternalUri());
  $parameters[1]['sf_culture'] = $sf_culture;
 
  return $routing->generate($route_name, array_merge($request->getGetParameters(), $parameters[1]));
}
 

EXAMPLE

Obviously, you must add the :sf_culture token in every rule of your application routing.yml:

product_page:
  url:   /:sf_culture/product/:id
  requirements: { sf_culture: (?:en|es|fr|it|de) }
  param: { module: product, action: show }
 
homepage:
  url:   /:sf_culture
  requirements: { sf_culture: (?:en|es|fr|it|de) }
  param: { module: page, action: home }

default_symfony:
  url:   /symfony/:sf_culture/:action/*
  requirements: { sf_culture: (?:en|es|fr|it|de) }
  param: { module: default }
 
default_index:
  url:   /:sf_culture/:module
  param: { action: index }
  requirements: { sf_culture: (?:en|es|fr|it|de) }
 
default:
  url:   /:sf_culture/:module/:action/*
  requirements: { sf_culture: (?:en|es|fr|it|de) }
 

This code let you create a list of link to the localized versions. The list of languages/cultures is taken from your config file.

<div>
  <?php foreach(sfConfig::get('app_languages_available') as $language) { ?>
    <a href="<?php echo localized_current_url($language); ?>"><?php echo $language; ?></a>  
  <?php } ?>
</div>
 
by Davide Fedrigo on 2009-09-28, tagged culture  helper  i18n  navigation  routing 
(3 comments)

Default culture content for i18n table

The table i18n doesn't support default culture. This snippet add the support of the default culture.

This snippet is a port of the snippet "default culture content fallback for i18n tables" for Symfony 1.2

Fallback I18n content

To enable the fallback, edit your table object class in lib/model/TableClassName.php and add the following code. Then search and replace TableClassName by your table object class name.

  /**
   * Fetch the i18n object for this object culture.
   *
   * @param   string          $culture    The culture to set
   * @return  mixed                       A i18n object
   * @throws  PropelException             Any exceptions caught during processing will be rethrown wrapped into a PropelException.
   * @link    http://snippets.symfony-project.org/snippet/237 -- modified for Symfony 1.2
   */
  public function getCurrentTableClassNameI18n($culture = null)
  {
    if (is_null($culture)) {
      $culture = is_null($this->culture) ? sfPropel::getDefaultCulture() : $this->culture;
    }
 
    if (!isset($this->current_i18n[$culture]))
    {
      $obj = TableClassNameI18nPeer::retrieveByPK($this->getId(), $culture);
      if ($obj !== null) { // Test if there is a translation for current culture
        $this->setTableClassNameI18nForCulture($obj, $culture);
      } else { // Create a translation for this culture
        $new_i18n = new TableClassNameI18n();
 
        $default_culture = sfConfig::get('sf_default_culture');
 
        // We try to fetch the default culture translation to initialise the new culture.
        if (!isset($this->current_i18n[$default_culture])) {
          $obj = TableClassNameI18nPeer::retrieveByPK($this->getId(), $default_culture);
          if ($obj !== null) { // Test if there is a translation for current culture
            $this->setTableClassNameI18nForCulture($obj, $default_culture);
          }
        } else {
          $obj = $this->current_i18n[$default_culture];
        }
 
        if ($obj !== null) {
          $obj->copyInto($new_i18n);
        }
 
        $new_i18n->setId($this->getId());
        $new_i18n->setCulture($culture);
 
        $this->setTableClassNameI18nForCulture($new_i18n, $culture);
      }
    }
 
    return $this->current_i18n[$culture];
  }
 

Saving fallback values at creation

You now need to add default translation when you create a new object. We do that with this doSave function.

To use this function, edit your table object class in lib/model/TableClassName.php and add the following code. Then search and replace TableClassName by your table object class name.

  /**
   * Stores the object in the database while setting default culture if necessary.
   *
   * If the object is new, it inserts it; otherwise an update is performed.
   * All related objects are also updated in this method.
   *
   * @param      Connection      $con The database connection
   * @return     int             The number of rows affected by this insert/update and any referring fk objects' save() operations.
   * @throws     PropelException Any exceptions caught during processing will be rethrown wrapped into a PropelException.
   * @see        save()
   * @link       http://snippets.symfony-project.org/snippet/237 -- modified for Symfony 1.2
   */
  protected function doSave(PropelPDO $con)
  {
    $default_culture = sfConfig::get('sf_default_culture');
    $current_culture = is_null($this->culture) ? sfPropel::getDefaultCulture() : $this->culture;
    $obj = null;
 
    // We try to fetch the default culture translation to initialise the new culture.
    if (!isset($this->current_i18n[$default_culture])) {
      $obj = TableClassNameI18nPeer::retrieveByPK($this->getId(), $default_culture, $con);
      if ($obj !== null) { // Test if there is a translation for current culture
        $this->setTableClassNameI18nForCulture($obj, $default_culture);
      }
    } else {
      $obj = $this->current_i18n[$default_culture];
    }
 
    if($obj === null && isset($this->current_i18n[$current_culture])) {
      $new_i18n = new TableClassNameI18n();
      $this->current_i18n[$current_culture]->copyInto($new_i18n);
 
      $new_i18n->setId($this->getId());
      $new_i18n->setCulture($default_culture);
 
      $this->setTableClassNameI18nForCulture($new_i18n, $default_culture);
    }
 
    return parent::doSave($con);
  }
 

Fetching a list with default translations

To complete this snippet, here is a fallback version of doSelectWithI18n.

To enable the fallback, edit your table object peer class in lib/model/TableClassNamePeer.php and add the following code. Then search and replace TableClassName by your table object class name.

  /**
   * Selects a collection of TableClassName objects pre-filled with their i18n objects.
   *
   * @param     Criteria         $criteria   The criteria's object
   * @param     string           $culture    The selected culture.
   * @param     PropelPDO        $con        An optional database connection
   * @return    array                        Array of TableClassName objects.
   * @throws    PropelException              Any exceptions caught during processing will be rethrown wrapped into a PropelException.
   * @link      http://snippets.symfony-project.org/snippet/237 -- modified for Symfony 1.2
   */
  public static function doSelectWithI18n(Criteria $criteria, $culture = null, PropelPDO $con = null)
  {
    $criteria = clone $criteria;
 
    if ($culture === null) {
      $culture = sfContext::getInstance()->getUser()->getCulture();
    }
 
    $default_culture = sfConfig::get('sf_default_culture');
 
    // Set the correct dbName if it has not been overridden
    if ($criteria->getDbName() == Propel::getDefaultDB()) {
      $criteria->setDbName(self::DATABASE_NAME);
    }
 
    TableClassNamePeer::addSelectColumns($c);
    $startcol = (TableClassNamePeer::NUM_COLUMNS - TableClassNamePeer::NUM_LAZY_LOAD_COLUMNS) + 1;
 
    TableClassNameI18nPeer::addSelectColumns($c);
 
    $criteria->addJoin(TableClassNamePeer::ID, TableClassNameI18nPeer::ID);
    $criterion = $criteria->getNewCriterion(TableClassNameI18nPeer::CULTURE, $culture);
    $criterion->addOr($criteria->getNewCriterion(TableClassNameI18nPeer::CULTURE, $default_culture));
    $criteria->add($criterion);
 
    $stmt = BasePeer::doSelect($c, $con);
    $results = array();
    $uncultured_results = array();
 
    while($row = $stmt->fetch(PDO::FETCH_NUM)) {
 
      $obj1 = new TableClassName();
      $obj1->hydrate($row);
      $obj1->setCulture($culture);
 
      if(isset($results[$obj1->getId()])) {
        $obj1 = $results[$obj1->getId()];
      }
 
      $omClass = TableClassNameI18nPeer::getOMClass($row, $startcol);
 
      $cls = Propel::importClass($omClass);
      $obj2 = new $cls();
      $obj2->hydrate($row, $startcol);
 
      $obj1->setTableClassNameI18nForCulture($obj2, $obj2->getCulture());
      $obj2->setTableClassName($obj1);
 
      if(!isset($uncultured_results[$obj1->getId()])) {
        $uncultured_results[$obj1->getId()] = $obj1;
      }
 
      if($obj2->getCulture() == $culture) {
        $uncultured_results[$obj1->getId()] = false;
      }
 
      if(!isset($results[$obj1->getId()])) {
        $results[$obj1->getId()] = $obj1;
      } elseif($obj2->getCulture() == $culture) {
        // Move result to the end of results array to fit eventual sort
        // criteria (ugly fix).
        unset($results[$obj1->getId()]);
        $results[$obj1->getId()] = $obj1;
      }
    }
 
    foreach ($uncultured_results as $obj1) {
      if ($obj1) {
        $obj1->setCulture($default_culture);
        $default_culture_object = $obj1->getCurrentTableClassNameI18n();
        if ($default_culture_object) {
          $obj2 = new TableClassNameI18n();
          $default_culture_object->copyInto($obj2);
          $obj2->setCulture($culture);
          $obj2->setTableClassName($obj1);
          $obj1->setTableClassNameI18nForCulture($obj2, $obj2->getCulture());
        }
        $obj1->setCulture($culture);
      }
    }
 
    return array_values($results);
  }
 

Counting results filtered on translations

Before enable the fallback, you must create a constant in your table object peer class in lib/model/TableClassNamePeer.php and replace table by your table name

const COUNT_DISTINCT = 'COUNT(DISTINCT table.ID)';
 

To enable the fallback, edit your table object peer class in lib/model/TableClassNamePeer.php and add the following code. Then search and replace TableClassName by your table object class name.

  /**
   * Returns the number of rows matching criteria with I18N criteria.
   *
   * @param       Criteria    $criteria   The criteria's object
   * @param       boolean     $distinct   Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria).
   * @param       Connection  $con        An optional database connection
   * @param       string      $culture    The selected culture.
   * @return      int                     Number of matching rows.
   * @link        http://snippets.symfony-project.org/snippet/237 -- modified for Symfony 1.2
   */
  public static function doCountWithI18n(Criteria $criteria = null, $distinct = false, PropelPDO $con = null, $culture = null)
  {
    // we're going to modify criteria, so copy it first
    if ($criteria === null){
      $criteria = new Criteria();
    } else {
      $criteria = clone $criteria;
    }
 
    $default_culture = sfConfig::get('sf_default_culture');
 
    if ($culture === null) {
      // We use current user culture.
      $culture = sfContext::getInstance()->getUser()->getCulture();
    }
 
    // clear out anything that might confuse the ORDER BY clause
    $criteria->clearSelectColumns()->clearOrderByColumns();
    $criteria->addSelectColumn(TableClassNamePeer::COUNT_DISTINCT);
 
    // just in case we're grouping: add those columns to the select statement
    foreach($criteria->getGroupByColumns() as $column)
    {
      $criteria->addSelectColumn($column);
    }
 
    $criteria->addJoin(TableClassNamePeer::ID, TableClassNameI18nPeer::ID);
    $criterion = $criteria->getNewCriterion(TableClassNameI18nPeer::CULTURE, $culture);
    $criterion->addOr($criteria->getNewCriterion(TableClassNameI18nPeer::CULTURE, $default_culture));
    $criteria->add($criterion);
 
    $rs = TableClassNamePeer::doSelectStmt($criteria, $con);
    if ($res = $rs->fetchColumn(0)) {
      return $res;
    } else {
      // no rows returned; we infer that means 0 matches.
      return 0;
    }
  }
 
by Simon Leblanc on 2009-09-20, tagged culture  data  database  i18n  object  propel  symfony12 

Set user culture from domain name

This filter tries to set the user culture by reading the domain part of the url. I use it for SEO, giving a different domain for each lang of my site.

Add this to your settings.yml :

    domain_culture:
       fr:   [.net, .fr, fr.mydomain.info]
       it:   [it.mydomain.info]
       en:   [.co.uk, .com, .mydomain.info]
 

Order is important : first match will assign the corresponding culture.

Create a lib/filters/domainCultureFilter.class.php file :

<?php
 
class domainCultureFilter extends sfFilter
{
    public function execute($filterChain)
    {
        $user = $this->getContext()->getUser();
        $request = $this->getContext()->getRequest();
        if (!$request->getParameter('sf_culture'))
        {
            if ($user->getAttribute('first_request', true))
            {
                $user->setAttribute('first_request', false);
                $domainCulture=sfConfig::get('sf_domain_culture');
                foreach ((array)$domainCulture as $culture=>$domains)
                {
                    foreach ((array)$domains as $domain)
                    {
                        $pattern = '/'.$domain.'/';
                        if (preg_match( $pattern ,  $_SERVER['HTTP_HOST']) )
                        {
                            $user->setCulture($culture);
                        }
                        break 2;
                    }
                }
            }
        }
        // Execute next filter
        $filterChain->execute();
    }
}
 

Add the filter to filters.yml :

# insert your own filters here
culture:
   class: domainCultureFilter
 

Comments are very welcome.

by Pierre Bastoul on 2009-04-10, tagged culture  domain  filter 
(3 comments)

Culture-aware templates

The following view class tries to load the template under directory name of the current culture, then fall back to the default template if such template cannot be found.

So if you access to "index" action of module "foo" and if current user culture is "zh_HK", the class will try to load: "module/foo/templates/zh_HK/indexSuccess.php"

If no such file exist, it will fall back to the default behaviour by loading "module/foo/templates/indexSuccess.php"

class sfCulturePHPView extends sfPHPView
{
  protected
    $cultureDirectory = '';
 
  public function initialize($context, $moduleName, $actionName, $viewName)
  {
    parent::initialize($context, $moduleName, $actionName, $viewName);
  }
 
  public function getDirectory()
  {
    if ($this->cultureDirectory)
      return $this->directory.'/'.$this->cultureDirectory;
    return $this->directory;
  }
 
  protected function preRenderCheck()
  {
    parent::preRenderCheck();
 
    // determine whether the culture-aware template is usable
    $currentCulture = $this->context->getUser()->getCulture();
 
    $template = $this->directory.'/'.$currentCulture.'/'.$this->template;
 
    if (is_readable($template))
      $this->cultureDirectory = $currentCulture;
    else
      $this->cultureDirectory = '';
  }
}
 
by Tamcy on 2008-05-27, tagged culture  view 
(1 comment)