Gii-generated files should be localized, and more intelligent ;)

Hi, folks!

It seems this is the right place to brainstorming, so here we go!

I think Gii should have the option to localize the files it generates. This is specially useful for monolingual applications, on which an url like ‘http://myapp.com.br/cliente/create’ (‘cliente’ is the Portuguese word for ‘customer’) would sound strange.

I managed to “translate” the CRUD generation into Portuguese (the hard-coded way), so, by example, my actionCreate are now generated as actionInserir. Although not strictly necessary, I’ve translate the views filenames as well.

Another point: I modified the function generateActiveField() in gii/generators/crud/CrudeCode.php to look like this:




<?php

(...)

public function generateActiveField($modelClass, $column)

  {


    /* MY CODE BEGINS HERE */

    foreach (CActiveRecord::model($modelClass)->relations() as $relation)

      if ($relation[0] == CActiveRecord::BELONGS_TO && $column->name == $relation[2]) {

        $relSchema = CActiveRecord::model($relation[1])->tableSchema;

        $descrField = $relSchema->primaryKey;

        foreach ($relSchema->columns as $col)

          if (preg_match('/^(descr_|nome_)/i', $col->name)) {

            $descrField = $col->name;

            break;

          }


        return "\$form->dropDownList(\$model, '{$column->name}',

					CHtml::listData({$relation[1]}::model()->findAll(), '{$relSchema->primaryKey}', '$descrField'),

					array('prompt'=>''));";

      }


    if ($column->type === 'boolean')

      return "\$form->checkBox(\$model,'{$column->name}')";

    else if ($column->dbType == 'date') {

      $dayNamesMin = 'array("Dm", "Sg", "Tr", "Qr", "Qt", "Sx", "Sb")';

      $dayNamesShort = 'array("Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb")';

      $dayNames = 'array("Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira",

      "Sábado")';


      $monthNamesShort = 'array("Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez")';

      $monthNames = 'array("Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro",

      "Outubro", "Novembro", "Dezembro")';


      return "\$this->widget('zii.widgets.jui.CJuiDatePicker', array('model'=>\$model,

        'attribute'=>'{$column->name}', 'options'=>array('showAnim'=>'fold', 'dateFormat'=>'dd/mm/yy',

        'dayNamesMin' => $dayNamesMin, 'dayNamesShort' => $dayNamesShort, 'dayNames' => $dayNames,

        'monthNamesShort' => $monthNamesShort, 'monthNames' => $monthNames)), true)";

    }

    else if ($column->dbType == 'datetime')

      return "\$form->widget('CMaskedTextField',array('model'=>\$model, 'attribute'=>'{$column->name}', 'mask'=>'99/99/9999 99:99', 'placeholder'=>' ', ), true)";

    else

      /* MY CODE ENDS HERE */


      if (stripos($column->dbType, 'text') !== false)

        return "\$form->textArea(\$model,'{$column->name}',array('rows'=>6, 'cols'=>50))";

      else

      {

        if (preg_match('/^(password|pass|passwd|passcode)$/i', $column->name))

          $inputField = 'passwordField';

        else

          $inputField = 'textField';


        if ($column->type !== 'string' || $column->size === null)

          return "\$form->{$inputField}(\$model,'{$column->name}')";

        else

        {

          if (($size = $maxLength = $column->size) > 60)

            $size = 60;

          return "\$form->{$inputField}(\$model,'{$column->name}',array('size'=>$size,'maxlength'=>$maxLength))";

        }

      }

  }

(...)

?>



A brief summary of what I’ve added:

  • Fields whose dbType is ‘date’ have CJuiDatePickers generated for them (I added Portuguese translations for day and month names - this must be moved to the message system in the “real world”);

  • Fields whose dbType is ‘datetime’ hava CMaskedTextField generated for them, with an appropriate mask, of course.

And the most time-saving feature I’ve introduced:

  • Fields that have a CActiveRecord::BELONGS_TO relation attached to them automagically got dropdownlists, already linked to the models they belong. I know it’s a bit hard to determine which would be the textfield (in my case, are those starting with ‘descr_’), but I think that picking the second field on the related model would be a good guess.

What do you think?

100% Support for your idea.

Actually i did it in another framework already with the more features.

TINYINT => Radio button

MEDIUMINT => Checkbox

INT => Textfield

DOUBLE => Textfield

DATE => DatePicker / Dropdown Boxes

DATETIME => DatePicker / Dropdown Boxes

TIME => Dropdown Boxes

TEXT => Textarea

MEDIUMTEXT => Textarea (Show in <ul>)

LONGTEXT => Rich Text Editor (FCK / TinyMCE)

VARCHAR(254) => Textfield x 3 (E-mail Input)

VARCHAR(253) => File Input (Photo)

VARCHAR(252) => Textfield (AlphaNumeric)

VARCHAR(251) => Textfield (Phone)

VARCHAR(250) => Textfield (started with http)

VARCHAR(249) => Textfield (Video like Youtube/MetaCafe)

VARCHAR(n) => Textfield (with length validation)

In the relationship part you suggest,

It’s very complicated work since there are a lot of cases.

I tried a lot of CRUD with different framework (Symfony, CakePHP, Zend, etc),

but no one can do it perfectly.

So I built 3 code generator already for (Joomla, CakePHP, and my own framework)

Actually I had some ideas about CRUD in relationships,

I would like to share with Yii if someone like it.

Hope Yii professional will enjoy.

Warren Chan

Hong Kong

Localize the text, headers - yes.

Please don’t translate actions/method names - use SEF to get “nice” URL. When non-Portuguese guy look at your code… you know :slight_smile:

Agreed :slight_smile: