yii-language-behavior A behavior for handling multiple languages in Yii.

  1. Requirements
  2. Usage
  3. History
  4. Credits
  5. Resources

This extension is designed for back end creation and update of multiple languages and the display of a single, selected language on the front end. I will extend this as I continue to work on it for my own applications. It differs from similar extensions in that all translatable data is contained within a single language specific table for each class that has translatable data.

Requirements

Yii 1.1 or above

Usage

I choose to put the behavior within /protected/behaviors/.

Configure your primary model class by loading the behavior. For example, I have two models: Category (primary) and CategoryLang (translation class) - see example SQL in the download package. Thus I put the following within my Category class:

public function behaviors() {
		return array(
			'LanguageBehavior' => array(
				'class' => 'application.behaviors.LanguageBehavior',
				'translationClass' => 'CategoryLang',
				'translationForeignKey' => 'category_id',
				'languageColumn' => 'language_id',
				'languageRelation' => 'categoryLang', // choose a name for the relation
				'translationColumns' => array('category_name','category_description'), 
				'languages' => Yii::app()->params['languages'],
			),
		);
	}

*Note - Although I have declared a relation in the above configuration: 'languageRelation' => 'categoryLang', the relation in fact does not exist in my model. This property is used when generating a dynamic relation within the behavior.

You also need to declare your translation attributes as public properties within the primary model class, plus a property for handling translation errors:

public $categoryName;
public $categoryDescription;
public $translationError;

This extension was designed using a separate language table (SQL included in the download). Languages should be set in the application configuration using a suitable configuration behavior. I use the following code within beginRequest():

if(!isset(Yii::app()->params['languages'])) {
		$languages = Language::model()->findAll();
		$language_array = array();
		foreach($languages as $val) {
			$language_array[] = array('id' => $val->id,
									  'code' => $val->code,
									  'name' => $val->name,
									  'image' => $val->image);
		}
		Yii::app()->params['languages'] = $language_array;
	}

Translations are loaded automatically in the back end with your model as an array which can be looped through like this:

<?php foreach (Yii::app()->params['languages'] as $val) : ?>
	<b><?php echo $val['name']; ?>:</b><br />
	<b><?php echo CHtml::encode($data->getAttributeLabel('category_name')); ?>:</b>
	<?php echo CHtml::encode($data->category_name[$val['id']]); ?>
	<br />
<?php endforeach; ?>

You should use a foreign key constraint CASCADE to delete records in your language tables (see example SQL in download).

The extension handles validation of translatable attributes, however Yii's addError() does not allow anything other than a string. This means that to display errors in the "Yii way" requires some creative hacking of your create/update form, plus the use of our $translation_error property. Below is a simple example:

<?php foreach (Yii::app()->params['languages'] as $val) : ?>
<fieldset>
    <legend><?php echo $val['name']; ?></legend>
    <div class="row">
	<?php (isset($model->translationError['category_name'][$val['id']]) ? $class='error': $class=''); ?>
    <?php echo $form->labelEx($model,'category_name_', array('class' => $class)); ?>
    <?php echo $form->textField($model,'category_name[' . $val['id'] . ']',array('size'=>60,'maxlength'=>255, 'class' => $class)); ?>
    <?php echo (isset($model->translationError['category_name'][$val['id']]) ? '<div class="errorMessage">' . $model->translationError['category_name'][$val['id']] . '</div>':''); ?>
    </div>
</fieldset>
<?php endforeach; ?>

The behavior outputs the error messages at the top of your form from our translation class validation rules using the standard $form->errorSummary($model)

For your front end simply set Yii::app()->session['language_id'] to the ID of the selected/detected language or whatever you want your default language to be.

*Please Note - Yii::app()->session['language_id'] must always be set for the front end and unset for the back end.

You can access model attributes in the front end like this:

$category = Category::model()->findByPk($id);    
// 'categoryLang' is our relation name declared in the model behavior configuration
echo $category->categoryLang->category_name;

History

27-12-2012 - Version 1.0.0 First release, just the basics.

27-12-2012 - Version 1.0.1 Updates for better error handling and refactoring for when new languages are added.

28-12-2012 - Version 1.0.2 Removed redundant $translation_table property.

28-12-2012 - Version 1.0.3 Support for front end single (selected) language.

29-12-2012 - Version 1.0.4 Dynamic relation for front end single (selected) language.

04-04-2013 - Version 1.0.5 Update for PHP 5.4

05-06-2013 - Version 1.0.6 Minor update

Credits

Thanks to guillemc and fredpeaks for their work on Yii languages.

Resources

3 1
14 followers
1 103 downloads
Yii Version: 1.1
License: BSD-2-Clause
Category: Database
Developed by: Backslider
Created on: Dec 27, 2012
Last updated: 10 years ago

Downloads

show all

Related Extensions