Yii 1.1: multilingual-crud

Multilingual CRUD generator (Gii template). Automate creation of multilingual CRUDs for any structure models without data-losing
6 followers

Did you have some discomfort, creating multilingual sites and Models? I didn't find any elegant interface for solving this problem. So, what i need? I'd like to create automatically CRUD for any model with multilingual support. Create model of any structure and create automatically CRUD for managing this model with any list of languages. I don't need any additional tables for translations, but out-of-the-box generator for any model structure. Certainly, there will be some constraints to make it workable:

  • you need to make an additional field - varchar(10) 'language' to keep language in
  • change primary_key(id) to composite primary_key(id, language)
  • connect special multilingual behavior for more efficiency usage

And that's all. After this you can:

  • automatically generate CRUD for any multilingual CRUD
  • easily manipulate your model's data in your routines

Installation routines

Unpack module files to your application.module path. Configurate config/main.php:

'modules' => array(
  ...
  'gii' => array(
  ...
  'generatorPaths' => array(
    'application.modules.MultilingualCrud.extensions.gii-templates'
  ),
  ...
),
...
'MultilingualCrud' => array(
  'defaultLayout' => 'application.custom.layout', /// you can set default layout for your controller here, or //layouts/column2 will be used
  'fieldsPk' => array('id', 'language'), /// you can set composite key fields names (not tested yet). It is better to keep default. Chabge before generating
),
...
configure your current language in config
...
'language' => 'en_us',
...
  • configure your exist model:
  1. add composite key ('id', 'language')
  2. add custom multilingual behavior to your model
....
public function behaviors()
{
  return array(
    ...
    'ml' => array( /// ml is neccessary name
      'class' => 'application.modules.MultilingualCrud.components.MultilingualActiveRecordBehavior'
    )
  );
}
....
  • manage your languages using predefined module controller

go 'MultilingualCrud/' and admin your languages list. You can easily disable/enable exist languages to provide access for translations in your models.

  • go to the GII and create CRUD, using MultilingualCrud generator

That's all.

Now you can access your CRUD like always:

  • <controller>/admin

  • <controller>/create

  • <controller>/index

  • view, delete, update, etc.

Additional documentation and links:

Total 4 comments

#11947 report it
Junior - df9 at 2013/02/14 04:45pm
Little improvement

Hi there!

I've tried to get related models with the "with" chained method and got an error that the "language" field was ambiguous.

Changing the line 'condition' of the Ml Behavior file solved the problem. Just added $owner->getTableAlias() and a dot before the {$languageField}

...    public function locale($language = null) {
        $owner->getDbCriteria()->mergeWith(
            array(
                'condition' => $owner->getTableAlias() .  ".{$languageField}='{$language}'"
            )
        );
        return $owner;
    }

Hope this helps

Regards

#11869 report it
Junior - df9 at 2013/02/09 07:41am
Using elrtef WYSIWYG extension together with multilingual-crud

@deeptowncitizen: I don't really know what happened, I regenerated models and now it is working like a charm, thank you very much for sharing this ext!

My two cents of contribution:

For those who wants to use the elrtef wysiwyg editor, some tips:

First, comment out the following code in form view:

//else if(stripos($columnType,'text')!==false){
        //return CHtml::textArea(generateName($language, $columnName), $value, array('rows'=>6, 'cols'=>50));

This will disable field generation for TEXTAREA items

After that, make a simple change in ext.elrtef.elRTE.php:

Include a public property called "value", this will be used in the form view to pass attribute value to the widget

public $value = null;

In the same file, change the code that generates the TEXTAREA field (in the very bottom of the code):

echo '<textarea id="'.$id.'" name="'.$name.'" rows="10" cols="40">';
          echo $this->model['attributes'][$this->attribute];
      if(isset($this->value)) echo $this->value;
      echo '</textarea>';

Back to our form view file, insert a beginclip that captures the elrtef content for our field, inside the "foreach($langs as $language)" code. I've inserted after the line "$page = 0;".

$this->beginClip($language->language.'ELRTE');
 
    $this->widget('ext.elrtef.elRTE', array(
           'model' => $model,
           'attribute' => generateName($language->language, 'body'),
           'name' => generateName($language->language, 'body'),
        'value'=>$model->body,
           'options' => array(
               'doctype'=>'js:\'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\'',
               'cssClass' => 'el-rte',
               'cssfiles' => array('css/elrte-inner.css'),
               'absoluteURLs'=>true,
               'allowSource' => true,
               'lang'   => Yii::app()->getLanguage(),
               'height' => 600,
               'fmAllow'=>true, //if you want to use Media-manager
               'fmOpen'=>'js:function(callback) {$("<div id=\"elfinder\" />").elfinder(%elfopts%);}',//here used placeholder for settings
               'toolbar' => 'df9',
           ),
           'elfoptions' => array( //elfinder options
           'url'=>'auto',  //if set auto - script tries to connect with native connector
           'passkey'=>'df9password', //here passkey from first connector`s line
           'dialog'=>array('width'=>'600','modal'=>true,'title'=>'Select file'),
           'lang'   => Yii::app()->getLanguage(),
           'closeOnEditorCallback'=>true,
           'editorCallback'=>'js:callback',
           'baseUrl'=>'http://local.df9cms.com/legal/'
           ),
           )
    );
    $this->endClip();

Obviously, adjust the widget rendering according to your needs, please, don't simply "copy and paste" the above code without paying attention to properties or else it may break your code

Well, finally, in the same form view file, we need to skip the "auto-generation" of the field we want to be wysiwyg. Just change

$content .= "<div class=\"row\">" .
        CHtml::activeLabelEx($model,'body') .
        $this->clips[$language->language.'ELRTE'] .
        //generateField('body', 'text', 0, $language->language, ($model->language === $language->language) ? $model->body : '' ) .
        "</div>";

This will place the visual editor with the content captured by the clip in the exact place you want

Hope this can be useful for someone

Regards!

:)

#11857 report it
deeptowncitizen at 2013/02/07 06:42pm
Reproducing steps

Hello. Excuse me for this inconvtnience. Please, could you share with me a model and sql for this model to reproduce the issue you are experiencing (mail me on reshetnikd at gmail.com)? And thank you for pointing on documentation lacks, i'll fix it in a few days.

#11856 report it
Junior - df9 at 2013/02/07 06:26pm
I only get duplicate entry for....xxx

Thanks for sharing, but this doesn't work for me, i always get error when trying to create a new record.

CDbException

CDbCommand falhou ao executar o comando SQL: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2-' for key 'PRIMARY'. The SQL statement executed was: INSERT INTO df_prodcategory (status, order, name, id) VALUES (:yp0, :yp1, :yp2, :yp3). Bound with :yp0=1, :yp1=1, :yp2='Blade Sharpeners', :yp3=2

Also documentation lacks telling that you need to create the language table

Some hacks were needed to get it running, but inserting records doesn't work properly

regards

edit: I've put a rule aray('id, language', 'safe') in the model and now it is working...is it necessary?

tks

Leave a comment

Please to leave your comment.

Create extension