Development

Changeset 8408

You must first sign up to be able to contribute.

Changeset 8408

Show
Ignore:
Timestamp:
04/11/08 09:39:47 (6 months ago)
Author:
nicolas
Message:

Fixed #3122:

Now the forms framework labels, error messages and help texts can be easily translated setting a php callable (or a sfCallable instance) for this purpose. In a symfony context (remember that the new forms framework can be used without symfony), the callable (__()) is automatically set through the default factories configuration process.

  • Added a constructor to the sfWidgetFormSchemaFormatter, which from now must must have an instance of sfWidgetFormSchema instance passed as a parameter,
  • Added a way to statically get and set a translation callable in sfWidgetFormSchemaFormatter,
  • Moved html label generation methods from sfWidgetFormSchema to sfWidgetFormSchemaFormatter (but this won't break BC),
  • Added translation callable declaration in default factories.yml symfony i18n configuration,
  • Created according unit and functional tests.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/1.1

    • Property svn:ignore changed from
      .project
      .projectOptions
      .cache
      to
      .project
      .projectOptions
      .cache
      .settings
  • branches/1.1/lib/autoload/sfCoreAutoload.class.php

    r8404 r8408  
    335335  'sfViewCacheManagerUpgrade' => 'task/project/upgrade1.1', 
    336336  'sfWebDebugUpgrade' => 'task/project/upgrade1.1', 
    337   'sfTaskInitTask' => 'task/task', 
    338337  'sfBaseTask' => 'task', 
    339338  'sfCommandApplicationTask' => 'task', 
    340339  'sfFilesystem' => 'task', 
    341340  'sfTask' => 'task', 
     341  'sfTaskInitTask' => 'task/task', 
    342342  'sfTestAllTask' => 'task/test', 
    343343  'sfTestFunctionalTask' => 'task/test', 
  • branches/1.1/lib/config/sfFactoryConfigHandler.class.php

    r8226 r8408  
    143143                     "%s". 
    144144                     "    \$this->factories['i18n'] = new \$class(\$this->configuration, \$cache, %s);\n". 
     145                     "    sfWidgetFormSchemaFormatter::setTranslationCallable(array(\$this->factories['i18n'], '__'));\n". 
    145146                     "  }\n" 
    146147                     , $class, $cache, var_export($parameters, true) 
  • branches/1.1/lib/form/sfForm.class.php

    r8158 r8408  
    259259      if (!isset($labels[$i])) 
    260260      { 
    261         $labels[$i] = sprintf('%s (%s)', $widgetSchema->generateLabelName($name), $i); 
     261        $labels[$i] = sprintf('%s (%s)', $widgetSchema->getFormFormatter()->generateLabelName($name), $i); 
    262262      } 
    263263 
  • branches/1.1/lib/form/sfFormField.class.php

    r7667 r8408  
    122122    } 
    123123 
    124     return $this->parent->getWidget()->generateLabel($this->name); 
     124    return $this->parent->getWidget()->getFormFormatter()->generateLabel($this->name); 
    125125  } 
    126126 
     
    137137    } 
    138138 
    139     return $this->parent->getWidget()->generateLabelName($this->name); 
     139    return $this->parent->getWidget()->getFormFormatter()->generateLabelName($this->name); 
    140140  } 
    141141 
  • branches/1.1/lib/validator/sfValidatorError.class.php

    r7902 r8408  
    105105   * 
    106106   * $i18n->__($error->getMessageFormat(), $error->getArguments()); 
     107   *  
     108   * If no message format has been set in the validator, the exception standard 
     109   * message is returned. 
    107110   * 
    108111   * @return string The message format 
     
    110113  public function getMessageFormat() 
    111114  { 
    112     return $this->validator->getMessage($this->code); 
     115    $messageFormat = $this->validator->getMessage($this->code); 
     116    if (!$messageFormat) 
     117    { 
     118      $messageFormat = $this->getMessage(); 
     119    } 
     120     
     121    return $messageFormat; 
    113122  } 
    114123} 
  • branches/1.1/lib/widget/sfWidgetForm.class.php

    r5937 r8408  
    160160   * @return string The field id or null. 
    161161   */ 
    162   protected function generateId($name, $value = null) 
     162  public function generateId($name, $value = null) 
    163163  { 
    164164    if (false === $this->getOption('id_format')) 
  • branches/1.1/lib/widget/sfWidgetFormSchema.class.php

    r8284 r8408  
    141141      } 
    142142       
    143       $this->formFormatters[$name] = new $class(); 
     143      $this->formFormatters[$name] = new $class($this); 
    144144    } 
    145145     
     
    343343 
    344344        // don't add a label tag and errors if we embed a form schema 
    345         $label = $widget instanceof sfWidgetFormSchema ? $this->generateLabelName($name) : $this->generateLabel($name); 
     345        $label = $widget instanceof sfWidgetFormSchema ? $this->getFormFormatter()->generateLabelName($name) : $this->getFormFormatter()->generateLabel($name); 
    346346        $error = $widget instanceof sfWidgetFormSchema ? array() : $error; 
    347347 
     
    389389        if (isset($errors[$name])) 
    390390        { 
    391           $globalErrors[$this->generateLabelName($name)] = $errors[$name]; 
     391          $globalErrors[$this->getFormFormatter()->generateLabelName($name)] = $errors[$name]; 
    392392        } 
    393393      } 
     
    395395 
    396396    return $globalErrors; 
    397   } 
    398  
    399   /** 
    400    * Generates a label for the given field name. 
    401    * 
    402    * @param  string The field name 
    403    * 
    404    * @return string The label tag 
    405    */ 
    406   public function generateLabel($name) 
    407   { 
    408     $labelName = $this->generateLabelName($name); 
    409  
    410     if (false === $labelName) 
    411     { 
    412       return ''; 
    413     } 
    414  
    415     return $this->renderContentTag('label', $labelName, array('for' => $this->generateId($this->generateName($name)))); 
    416   } 
    417  
    418   /** 
    419    * Generates the label name for the given field name. 
    420    * 
    421    * @param  string The field name 
    422    * 
    423    * @return string The label name 
    424    */ 
    425   public function generateLabelName($name) 
    426   { 
    427     $label = $this->getLabel($name); 
    428     if (!$label && false !== $label) 
    429     { 
    430       $label = str_replace('_', ' ', ucfirst($name)); 
    431     } 
    432  
    433     return $label; 
    434397  } 
    435398 
  • branches/1.1/lib/widget/sfWidgetFormSchemaDecorator.class.php

    r7053 r8408  
    194194 
    195195  /** 
    196    * @see sfWidgetFormSchema 
     196   * @see sfWidgetFormSchemaFormatter 
    197197   */ 
    198198  public function generateLabel($name) 
    199199  { 
    200     return $this->widget->generateLabel($name); 
    201   } 
    202  
    203   /** 
    204    * @see sfWidgetFormSchema 
     200    return $this->widget->getFormFormatter()->generateLabel($name); 
     201  } 
     202 
     203  /** 
     204   * @see sfWidgetFormSchemaFormatter 
    205205   */ 
    206206  public function generateLabelName($name) 
    207207  { 
    208     return $this->widget->generateLabelName($name); 
     208    return $this->widget->getFormFormatter()->generateLabelName($name); 
    209209  } 
    210210 
  • branches/1.1/lib/widget/sfWidgetFormSchemaFormatter.class.php

    r6220 r8408  
    1919abstract class sfWidgetFormSchemaFormatter 
    2020{ 
     21  protected static  
     22    $translationCallable       = null; 
     23   
    2124  protected 
    2225    $rowFormat                 = '', 
     
    2629    $errorRowFormatInARow      = "    <li>%error%</li>\n", 
    2730    $namedErrorRowFormatInARow = "    <li>%name%: %error%</li>\n", 
    28     $decoratorFormat           = ''; 
    29  
     31    $decoratorFormat           = '', 
     32    $widgetSchema              = null; 
     33 
     34  /** 
     35   * Constructor 
     36   * 
     37   * @param sfWidgetFormSchema $widgetSchema 
     38   */ 
     39  public function __construct(sfWidgetFormSchema $widgetSchema) 
     40  { 
     41    $this->widgetSchema = $widgetSchema; 
     42  } 
     43     
    3044  public function formatRow($label, $field, $errors = array(), $help = '', $hiddenFields = null) 
    3145  { 
     
    3852    )); 
    3953  } 
    40  
     54   
     55  /** 
     56   * Translates a string using an i18n callable, if it has been provided 
     57   * 
     58   * @param  mixed  $subject     The subject to translate 
     59   * @param  array  $parameters  Additional parameters to pass back to the callable 
     60   *  
     61   * @return string 
     62   */ 
     63  static public function translate($subject, $parameters = array()) 
     64  { 
     65    if (false === $subject) 
     66    { 
     67      return false;   
     68    } 
     69     
     70    if (is_null(self::$translationCallable)) 
     71    { 
     72      return strtr($subject, $parameters); 
     73    } 
     74     
     75    if (self::$translationCallable instanceof sfCallable) 
     76    { 
     77      return self::$translationCallable->call($subject, $parameters); 
     78    } 
     79 
     80    return call_user_func(self::$translationCallable, $subject, $parameters); 
     81  } 
     82   
     83  /** 
     84   * Returns the current i18n callable 
     85   * 
     86   * @return mixed 
     87   */ 
     88  static public function getTranslationCallable() 
     89  { 
     90    return self::$translationCallable; 
     91  } 
     92   
     93  /** 
     94   * Sets a callable which aims to translate form labels, errors and help messages  
     95   * 
     96   * @param  mixed  $callable 
     97   *  
     98   * @throws InvalidArgumentException if an invalid php callable or sfCallable has been provided 
     99   */ 
     100  static public function setTranslationCallable($callable) 
     101  { 
     102    if (!$callable instanceof sfCallable && !is_callable($callable)) 
     103    { 
     104      throw new InvalidArgumentException('Provided i18n callable should be either an instance of sfCallable or a valid PHP callable'); 
     105    } 
     106     
     107    self::$translationCallable = $callable; 
     108  } 
     109   
    41110  public function formatHelp($help) 
    42111  { 
     
    46115    } 
    47116 
    48     return strtr($this->getHelpFormat(), array('%help%' => $help)); 
     117    return strtr($this->getHelpFormat(), array('%help%' => self::translate($help))); 
    49118  } 
    50119 
     
    72141 
    73142    return strtr($this->getErrorListFormatInARow(), array('%errors%' => implode('', $this->unnestErrors($errors)))); 
     143  } 
     144   
     145  /** 
     146   * Generates a label for the given field name. 
     147   * 
     148   * @param  string The field name 
     149   * 
     150   * @return string The label tag 
     151   */ 
     152  public function generateLabel($name) 
     153  { 
     154    $labelName = $this->generateLabelName($name); 
     155 
     156    if (false === $labelName) 
     157    { 
     158      return ''; 
     159    } 
     160 
     161    $widgetId = $this->widgetSchema->generateId($this->widgetSchema->generateName($name)); 
     162    return $this->widgetSchema->renderContentTag('label', $labelName, array('for' => $widgetId)); 
     163  } 
     164 
     165  /** 
     166   * Generates the label name for the given field name. 
     167   * 
     168   * @param  string The field name 
     169   * 
     170   * @return string The label name 
     171   */ 
     172  public function generateLabelName($name) 
     173  { 
     174    $label = $this->widgetSchema->getLabel($name); 
     175     
     176    if (!$label && false !== $label) 
     177    { 
     178      $label = str_replace('_', ' ', ucfirst($name)); 
     179    } 
     180 
     181    return self::translate($label); 
    74182  } 
    75183 
     
    86194      else 
    87195      { 
    88         $err = is_object($error) ? $error->__toString() : $error; 
     196        if ($error instanceof sfValidatorError) 
     197        { 
     198          $err = self::translate($error->getMessageFormat(), $error->getArguments()); 
     199        } 
     200        else 
     201        { 
     202          $err = self::translate($error); 
     203        } 
    89204 
    90205        if (!is_integer($name)) 
     
    101216    return $newErrors; 
    102217  } 
    103  
     218   
    104219  public function setRowFormat($format) 
    105220  { 
  • branches/1.1/test/functional/fixtures/project/apps/i18n/modules/i18n/actions/actions.class.php

    r4344 r8408  
    3030    $this->forward('i18n', 'index'); 
    3131  } 
     32   
     33  public function executeI18nForm(sfWebRequest $request) 
     34  { 
     35    $this->form = new I18nForm(); 
     36    if ($request->isMethod('post')) 
     37    { 
     38      $this->form->bind($request->getParameter('i18n')); 
     39    } 
     40  } 
    3241} 
  • branches/1.1/test/functional/fixtures/project/apps/i18n/modules/i18n/i18n/messages.fr.xml

    r2757 r8408  
    77        <target>une phrase locale en français</target> 
    88      </trans-unit> 
     9      <trans-unit id="2"> 
     10        <source>First name</source> 
     11        <target>Prénom</target> 
     12      </trans-unit> 
     13      <trans-unit id="3"> 
     14        <source>Last name</source> 
     15        <target>Nom</target> 
     16      </trans-unit> 
     17      <trans-unit id="4"> 
     18        <source>Put your first name here</source> 
     19        <target>Mettez votre prénom ici</target> 
     20      </trans-unit> 
     21      <trans-unit id="4"> 
     22        <source>Required.</source> 
     23        <target>Champ requis.</target> 
     24      </trans-unit> 
     25      <trans-unit id="5"> 
     26        <source>Email address</source> 
     27        <target>Adresse email</target> 
     28      </trans-unit> 
     29      <trans-unit id="6"> 
     30        <source>%value% is an invalid email address</source> 
     31        <target>%value% est une adresse email invalide</target> 
     32      </trans-unit> 
    933    </body> 
    1034  </file> 
  • branches/1.1/test/unit/widget/sfWidgetFormSchemaFormatterListTest.php

    r5996 r8408  
    1313$t = new lime_test(2, new lime_output_color()); 
    1414 
    15 $f = new sfWidgetFormSchemaFormatterList(); 
     15$f = new sfWidgetFormSchemaFormatterList(new sfWidgetFormSchema()); 
    1616 
    1717// ->formatRow() 
  • branches/1.1/test/unit/widget/sfWidgetFormSchemaFormatterTableTest.php

    r5996 r8408  
    1313$t = new lime_test(2, new lime_output_color()); 
    1414 
    15 $f = new sfWidgetFormSchemaFormatterTable(); 
     15$f = new sfWidgetFormSchemaFormatterTable(new sfWidgetFormSchema()); 
    1616 
    1717// ->formatRow() 
  • branches/1.1/test/unit/widget/sfWidgetFormSchemaFormatterTest.php

    r5937 r8408  
    1111require_once(dirname(__FILE__).'/../../bootstrap/unit.php'); 
    1212 
    13 $t = new lime_test(10, new lime_output_color()); 
     13$t = new lime_test(22, new lime_output_color()); 
    1414 
    1515class MyFormatter extends sfWidgetFormSchemaFormatter 
     
    2424    return parent::unnestErrors($errors, $prefix); 
    2525  } 
     26   
     27  static public function dropTranslationCallable() 
     28  { 
     29    self::$translationCallable = null; 
     30  } 
    2631} 
    2732 
    28 $f = new MyFormatter(); 
     33$w1 = new sfWidgetFormInput(); 
     34$w2 = new sfWidgetFormInput(); 
     35$w = new sfWidgetFormSchema(array('w1' => $w1, 'w2' => $w2)); 
     36$f = new MyFormatter($w); 
    2937 
    3038// ->formatRow() 
     
    3240$output = <<<EOF 
    3341<li> 
    34   label 
    35   <input />help 
     42  <label>label</label> 
     43  <input /><p>help</p> 
    3644</li> 
    3745 
    3846EOF; 
    39 $t->is($f->formatRow('label', '<input />', array(), 'help', ''), $output, '->formatRow() formats a field in a row'); 
     47$t->is($f->formatRow('<label>label</label>', '<input />', array(), '<p>help</p>', ''), $output, '->formatRow() formats a field in a row'); 
    4048 
    4149// ->formatErrorRow() 
     
    7078  $t->is($f->$getter(), $value, sprintf('->%s() ->%s()', $getter, $setter)); 
    7179} 
     80 
     81$t->diag('::setTranslationCallable() ::getTranslationCallable()'); 
     82function my__($string) 
     83{ 
     84  return sprintf('[%s]', $string); 
     85} 
     86 
     87class myI18n 
     88{ 
     89  static public function __($string) 
     90  { 
     91    return my__($string); 
     92  } 
     93} 
     94MyFormatter::setTranslationCallable('my__'); 
     95 
     96$t->is(MyFormatter::getTranslationCallable(), 'my__', 'get18nCallable() retrieves i18n callable correctly'); 
     97 
     98MyFormatter::setTranslationCallable(new sfCallable('my__')); 
     99$t->isa_ok(MyFormatter::getTranslationCallable(), 'sfCallable', 'get18nCallable() retrieves i18n sfCallable correctly'); 
     100 
     101try 
     102{ 
     103  $f->setTranslationCallable('foo'); 
     104  $t->fail('setTranslationCallable() does not throw InvalidException when i18n callable is invalid'); 
     105} 
     106catch (InvalidArgumentException $e) 
     107{ 
     108  $t->pass('setTranslationCallable() throws InvalidException if i18n callable is not a valid callable'); 
     109} 
     110catch (Exception $e) 
     111{ 
     112  $t->fail('setTranslationCallable() throws unexpected exception'); 
     113} 
     114 
     115$t->diag('->translate()'); 
     116$t->is(MyFormatter::translate('label'), '[label]', 'translate() call i18n sfCallable as expected'); 
     117 
     118MyFormatter::setTranslationCallable(array('myI18n', '__')); 
     119$t->is(MyFormatter::translate('label'), '[label]', 'translate() call i18n callable as expected'); 
     120 
     121$t->diag('->generateLabel() ->generateLabelName() ->setLabel() ->setLabels()'); 
     122MyFormatter::dropTranslationCallable(); 
     123$w = new sfWidgetFormSchema(array( 
     124  'first_name' => new sfWidgetFormInput(), 
     125  'last_name'  => new sfWidgetFormInput(), 
     126)); 
     127$f = new MyFormatter($w); 
     128$t->is($f->generateLabelName('first_name'), 'First name', '->generateLabelName() generates a label value from a label name'); 
     129 
     130$w->setLabels(array('first_name' => 'The first name')); 
     131$t->is($f->generateLabelName('first_name'), 'The first name', '->setLabels() changes all current labels'); 
     132 
     133$w->setLabel('first_name', 'A first name'); 
     134$t->is($f->generateLabelName('first_name'), 'A first name', '->setLabel() sets a label value'); 
     135 
     136$w->setLabel('first_name', false); 
     137$t->is($f->generateLabel('first_name'), '', '->generateLabel() returns an empty string if the label is false'); 
     138 
     139$w->setLabel('first_name', 'Your First Name'); 
     140$t->is($f->generateLabel('first_name'), '<label for="first_name">Your First Name</label>', '->generateLabelName() returns a label tag'); 
     141 
     142$w->setLabel('last_name', 'Your Last Name'); 
     143$t->is($f->generateLabel('last_name'), '<label for="last_name">Your Last Name</label>', '->generateLabelName() returns a label tag'); 
     144MyFormatter::setTranslationCallable('my__'); 
     145$t->is($f->generateLabel('last_name'), '<label for="last_name">[Your Last Name]</label>', '->generateLabelName() returns a i18ned label tag'); 
  • branches/1.1/test/unit/widget/sfWidgetFormSchemaTest.php

    r8284 r8408  
    1111require_once(dirname(__FILE__).'/../../bootstrap/unit.php'); 
    1212 
    13 $t = new lime_test(61, new lime_output_color()); 
     13$t = new lime_test(57, new lime_output_color()); 
    1414 
    1515$w1 = new sfWidgetFormInput(array(), array('class' => 'foo1')); 
     
    7575$t->is(get_class($w->getFormFormatter()), 'sfWidgetFormSchemaFormatterTable', '->getFormFormatter() returns a sfWidgetSchemaFormatter object'); 
    7676 
    77 $w->addFormFormatter('custom', $customFormatter = new sfWidgetFormSchemaFormatterList()); 
     77$w->addFormFormatter('custom', $customFormatter = new sfWidgetFormSchemaFormatterList($w)); 
    7878$w->setFormFormatterName('custom'); 
    7979$t->is(get_class($w->getFormFormatter()), 'sfWidgetFormSchemaFormatterList', '->addFormFormatter() associates a name with a sfWidgetSchemaFormatter object'); 
     
    141141$t->diag('->setLabels() ->setLabel() ->getLabels() ->getLabel() ->generateLabelName()'); 
    142142$w = new sfWidgetFormSchema(); 
    143 $t->is($w->generateLabelName('first_name'), 'First name', '->generateLabelName() generates a label value from a label name'); 
     143$w->setLabel('first_name', 'A first name'); 
     144$t->is($w->getLabels(), array('first_name' => 'A first name'), '->getLabels() returns all current labels'); 
     145 
    144146$w->setLabels(array('first_name' => 'The first name')); 
    145 $t->is($w->generateLabelName('first_name'), 'The first name', '->setLabels() changes all current labels'); 
     147$t->is($w->getFormFormatter()->generateLabelName('first_name'), 'The first name', '->setLabels() changes all current labels'); 
     148 
    146149$w->setLabel('first_name', 'A first name'); 
    147 $t->is($w->generateLabelName('first_name'), 'A first name', '->setLabel() sets a label value'); 
    148 $t->is($w->getLabels(), array('first_name' => 'A first name'), '->getLabels() returns all current labels'); 
     150$t->is($w->getFormFormatter()->generateLabelName('first_name'), 'A first name', '->setLabel() sets a label value'); 
    149151 
    150152// ->setHelps() ->getHelps() ->setHelp() ->getHelp() 
     
    155157$w->setHelp('last_name', 'Please, provide your last name'); 
    156158$t->is($w->getHelp('last_name'), 'Please, provide your last name', '->setHelp() changes one help message'); 
    157  
    158 // ->generateLabel() 
    159 $t->diag('->generateLabel()'); 
    160 $w = new sfWidgetFormSchema(); 
    161 $w->setLabel('first_name', false); 
    162 $t->is($w->generateLabel('first_name'), '', '->generateLabelName() returns an empty string if the label is false'); 
    163 $w->setLabel('first_name', 'The First Name'); 
    164 $t->is($w->generateLabel('first_name'), '<label for="first_name">The First Name</label>', '->generateLabelName() returns a label tag'); 
    165 $t->is($w->generateLabel('last_name'), '<label for="last_name">Last name</label>', '->generateLabelName() returns a label tag'); 
    166159 
    167160// ->needsMultipartForm()