Skip to content
Browse files

initial commit version 0.2.3

  • Loading branch information...
0 parents commit a75f706a1aa98909459a0f1f34d2b903878f1dc2 @gusnips committed Aug 18, 2011
221 README
@@ -0,0 +1,221 @@
+#### Module to handle translations
+
+This extension collects all untranslated messages in the page and then you can add a button to translate, translate automatically using google translate, check for missing translations, edit translations and more.
+
+Basic usage:
+
+
+~~~
+[php]
+echo Yii::t('app','Some text').' - '.Yii::t('app','some other text');
+Yii::app()->translate->editLink('Translate');
+
+~~~
+
+
+##Setup
+
+In your config :
+~~~
+[php]
+<?php
+return array(
+ 'preload'=>array('translate'),//either here or somewhere in the beginning
+ //set up and import the module
+ 'modules'=>array(
+ 'translate'
+ ),
+ 'import'=>array(
+ 'application.modules.translate.TranslateModule'
+ ),
+ 'components'=>array(
+ //define the class and its missingTranslation event
+ 'messages'=>array(
+ 'class'=>'CDbMessageSource',
+ 'onMissingTranslation' => array('TranslateModule', 'missingTranslation'),
+ ),
+ 'translate'=>array(//if you name your component something else change TranslateModule
+ 'class'=>'translate.components.MPTranslate',
+ //any avaliable options here
+ 'acceptedLanguages'=>array(
+ 'en'=>'English',
+ 'pt'=>'Portugues',
+ 'es'=>'Espa�ol'
+ ),
+ ),
+ )
+);
+~~~
+
+Do not forget to create the tables like [described here](http://www.yiiframework.com/doc/api/1.1/CDbMessageSource "")
+####the id of message source must be auto-incremental
+
+the name of the tables can be modified
+
+~~~
+[php]
+CREATE TABLE SourceMessage
+(
+ id INTEGER PRIMARY KEY AUTO_INCREMENT,
+ category VARCHAR(32),
+ message TEXT
+);
+CREATE TABLE Message
+(
+ id INTEGER,
+ language VARCHAR(16),
+ translation TEXT,
+ PRIMARY KEY (id, language),
+ CONSTRAINT FK_Message_SourceMessage FOREIGN KEY (id)
+ REFERENCES SourceMessage (id) ON DELETE CASCADE ON UPDATE RESTRICT
+);
+
+~~~
+
+
+
+##How to use
+
+Extract the file to protected/modules
+
+somewhere in your application define the language like the following:
+~~~
+[php]
+//shortcut
+$translate=Yii::app()->translate;
+//in your layout add
+echo $translate->dropdown();
+//adn this
+if($translate->hasMessages()){
+ //generates a to the page where you translate the missing translations found in this page
+ echo $translate->translateLink('Translate');
+ //or a dialog
+ echo $translate->translateDialogLink('Translate','Translate page title');
+}
+//link to the page where you edit the translations
+echo $translate->editLink('Edit translations page');
+//link to the page where you check for all unstranslated messages of the system
+echo $translate->missingLink('Missing translations page');
+
+
+~~~
+
+
+
+##Options avaliable
+
+#### string $defaultLanguage
+defaults language to use if none is set.
+
+if null, it will receive Yii target language
+#### array $dialogOptions
+options of the dialog
+#### string $googleApiKey
+your google translate api key.
+
+set this if you wish to use googles translate service to translate the messages
+
+#### array $acceptedLanguages
+an array containing the languages accepted by your application.
+
+if not set, it will receive an array containing the target language and the source language
+
+#### boolean $autoTranslate
+wheter to auto translate the missing messages found on the page. Defaults to false.
+Needs google api key to set
+
+#### boolean $autoSetLanguage
+wheter to automatically set the language on the initialization of the component. Defaults to true.
+
+##Methods avaliable
+for the translate components
+use it like this:
+~~~
+[php]
+Yii::app()->translate->someMethod($someArg);
+~~~
+#### string getLanguage()
+Returns the language in use.
+The language is determined by many variables: session, post, get, header in this order.
+It will filter the language by using accepted languages.
+If is set "en_US" and it is not avaliable, then it will check if "en" is avaliable.
+#### string setLanguage($language=null)
+If $language is null then it will use getLanguage to determine it.
+It doesn't check if the language is in the accepted languages.
+Returns the language setted.
+#### boolean hasMessage()
+Return wheter there are messages to be translated in this page
+#### string dropdown()
+Returns a dropdown containing all accepted languages with an onchange event that will change the application's language.
+#### string googleTranslate($message,$targetLanguage=null,$sourceLanguage=null)
+Translate some message from $sourceLanguage to $targetLanguage using google translate api.
+Option GoogleApiKey must be defined to use this service.
+#### array getGoogleAcceptedLanguages($targetLanguage=null)
+returns an array containing all languages accepted by google translate.
+Option googleApiKey must be defined to use this service.
+#### string translateLink($label,$type='link')
+Generates a link or button to the page where you translate the missing translations found in this page
+#### string translateDialogLink($label,$title=null,$type='link')
+Generates a link or button that generates a dialog to the page where you translate the missing translations found in this page.
+#### string editLink($label,$type='link')
+Creates a link to the page where you edit the translations.
+#### string missingLink($label,$type='link')
+Creates a link to the page where you check all missing translations
+
+_type for any link can be 'button' or 'link'_
+
+if you are running php 5.3 you can use any method like this
+MPTranslate::someMethod($someArg);
+
+For the TranslateModule
+
+#### MPTranslate translator()
+returns the translate component
+#### string t($message,$params=array())
+used internally for the module to translate its content
+#### string $translateComponentId
+the id of the translate component. Defaults to 'translate'
+
+
+##Version
+
+0.2.3: 18/08/2011
+
+- LANGUAGE_KEY is now a constant named ID
+- Google errors are now logged instead of beeing treated as an exception
+
+0.2.2: 23/05/2011
+
+- Fixed pagination in dialog and textarea size
+
+0.2.1: 20/05/2011
+
+- Fixed some minor bugs
+
+0.2: 18/05/2011
+
+- complete rewrite of the code to allow easier customization
+- added google translate support (thanks to Toshi)
+- added defaultLanguage (thanks to duna)
+- fixed a couple of minor bugs
+- added a lof of new funcionalities
+
+0.1: 10/05/2011
+
+-first release
+
+
+##Resources
+
+[Get a google API key](https://code.google.com/apis/console/?api=translate "Get a google api key")
+
+[CDbMessageSource](http://www.yiiframework.com/doc/api/1.1/CDbMessageSource "CDbMessageSource")
+
+[Forum support](http://www.yiiframework.com/forum/index.php?/topic/19302-translate-module/ "Forum support")
+
+
+
+##Notes
+
+#### This module will slow down your application, use it for development only
+#### It's not fully tested. I'm expecting your feedback to improve it
52 TranslateModule.php
@@ -0,0 +1,52 @@
+<?php
+
+class TranslateModule extends CWebModule
+{
+ /**
+ * the name of the translate component
+ * change this in case you dont use the default name
+ * */
+ static $translateComponentId='translate';
+ /**
+ * TranslateModule::init()
+ *
+ * @return
+ */
+ public function init(){
+ $this->defaultController='Translate';
+ $this->setImport(array(
+ 'translate.models.*',
+ 'translate.controllers.*',
+ 'translate.components.*',
+ ));
+ return parent::init();
+ }
+ /**
+ * get the translate component
+ *
+ * @return MPTranslate
+ */
+ static function translator(){
+ $component=Yii::app()->getComponent(self::$translateComponentId);
+ if($component===null)
+ throw new CException('Translate component must be defined');
+ return $component;
+ }
+ static function __callStatic($method,$args){
+ return call_user_func_array(array(self::getTranslateComponent(),$method),$args);
+ }
+ static function missingTranslation($event){
+ return self::translator()->missingTranslation($event);
+ }
+ /**
+ * translate some message using the module configuration
+ *
+ * @param string $message
+ * @param array $params
+ * @return string translated message
+ */
+ static function t($message,$params=array()){
+ $translator=self::translator();
+ return Yii::t($translator::ID,$message,$params,'en','en');
+ }
+}
347 components/MPTranslate.php
@@ -0,0 +1,347 @@
+<?php
+class MPTranslate extends CApplicationComponent{
+ /**
+ * @staticvar array $messages contains the untranslated messages found
+ * */
+ static $messages=array();
+ /**
+ * @var string $defaultLanguage defaults language to use if none is set
+ * */
+ public $defaultLanguage=null;
+ /**
+ * @var $dialogOptions options of the dialog
+ * */
+ public $dialogOptions=array(
+ 'autoOpen'=>false,
+ 'modal'=>true,
+ 'width'=>'auto',
+ 'height'=>'auto',
+ );
+ /**
+ * @var string $googleTranslateApiKey your google translate api key
+ * set this if you wish to use googles translate service to translate the messages
+ * if empty it will not use the service
+ * */
+ public $googleApiKey=null;
+ /**
+ * @const string ID an unique key to be used in many situations
+ * */
+ const ID='mp-translate';
+ /**
+ * @var array $acceptedLanguages contains the languages accepted by your application
+ * */
+ public $acceptedLanguages=array();
+ /**
+ * @var boolean wheter to auto translate the missing messages found on the page
+ * needs google api key to set
+ * */
+ public $autoTranslate=false;
+ /**
+ * @var boolean wheter to automatically set the language on the initialization of the component
+ * */
+ public $autoSetLanguage=true;
+ /**
+ * @var array $_cache will contain variables
+ * */
+ private $_cache=array();
+ /**
+ * handles the initialization parameters of the components
+ */
+ function init(){
+ if(empty($this->defaultLanguage))
+ $this->defaultLanguage=Yii::app()->getLanguage();
+ if($this->autoSetLanguage)
+ $this->setLanguage($this->getLanguage());
+ if(!count($this->acceptedLanguages)){
+ if(($sourceLanguage=Yii::app()->sourceLanguage)!==null)
+ $this->acceptedLanguages[$sourceLanguage]=$sourceLanguage;
+ if(($targetLanguage=Yii::app()->getLanguage())!=null)
+ $this->acceptedLanguages[$targetLanguage]=$targetLanguage;
+ }
+ return parent::init();
+ }
+ /**
+ * method that handles the on missing translation event
+ *
+ * @param CMissingTranslationEvent $event
+ * @return string the message to translate or the translated message if autoTranslate is set to true
+ */
+ function missingTranslation($event){
+ Yii::import('translate.models.MessageSource');
+ $attributes=array('category'=>$event->category,'message'=>$event->message);
+ if(($model=MessageSource::model()->find('message=:message AND category=:category',$attributes))===null){
+ $model=new MessageSource();
+ $model->attributes=$attributes;
+ if(!$model->save())
+ return Yii::log(TranslateModule::t('Message '.$event->message.' could not be added to messageSource table'));;
+ }
+ if($model->id){
+ if($this->autoTranslate && substr($event->language,0,2)!==substr(Yii::app()->sourceLanguage,0,2)){//&& key_exists($event->language,$this->getGoogleAcceptedLanguages($event->language))
+ Yii::import('translate.models.Message');
+ $translation=$this->googleTranslate($event->message,$event->language,Yii::app()->sourceLanguage);
+ if($translation===false)
+ return false;
+ $messageModel=new Message;
+ $messageModel->attributes=array('id'=>$model->id,'language'=>$event->language,'translation'=>$translation);
+ if($messageModel->save())
+ $event->message=$translation;
+ else
+ return Yii::log(TranslateModule::t('Message '.$event->message.' could not be translated with auto-translate'));
+ }elseif(substr($event->language,0,2)!==substr(Yii::app()->sourceLanguage,0,2) || Yii::app()->getMessages()->forceTranslation){
+ self::$messages[$model->id]=array('language'=>$event->language,'message'=>$event->message,'category'=>$event->category);
+ }
+ }
+ return $event;
+ }
+ /**
+ * generates a link or button to the page where you translate the missing translations found in this page
+ *
+ * @param string $label label of the link
+ * @param string $type accepted types are : link and button
+ * @return string
+ */
+ function translateLink($label='Translate',$type='link'){
+ $form=CHtml::form(Yii::app()->getController()->createUrl('/translate/translate/index'));
+ if(count(self::$messages))
+ foreach(self::$messages as $index=>$message)
+ foreach($message as $name=>$value)
+ $form.=CHtml::hiddenField(self::ID."-missing[$index][$name]",$value);
+ if($type==='button')
+ $form.=CHtml::submitButton($label);
+ else
+ $form.=CHtml::linkButton($label);
+ $form.=CHtml::endForm();
+ return $form;
+ }
+ function hasMessages(){
+ return count(self::$messages)>0;
+ }
+ /**
+ * generates a link or button that generates a dialog to the page where you translate the missing translations found in this page
+ *
+ * @param string $label label of the link
+ * @param mixed $title title of the popup
+ * @param string $type accepted types are : link and button
+ * @return string
+ */
+ function translateDialogLink($label='Translate',$title=null,$type='link'){
+ return $this->ajaxDialog($label,'translate/translate/index',$title,$type,array('data'=>array(self::ID.'-missing'=>self::$messages)));
+ }
+ /**
+ * creates a link to the page where you edit the translations
+ *
+ * @param string $label
+ * @param string $type accepted types are button and link
+ * @return
+ */
+ function editLink($label='Edit translations',$type='link'){
+ $url=Yii::app()->getController()->createUrl('/translate/edit/admin');
+ if($type==='button')
+ return CHtml::button($label,$url);
+ else
+ return CHtml::link($label,$url);
+ }
+ /**
+ * creates a link to the page where you check all missing translations
+ *
+ * @param string $label
+ * @param string $type accepted types are button and link
+ * @return string
+ */
+ function missingLink($label='Missing translations',$type='link'){
+ $url=Yii::app()->getController()->createUrl('/translate/edit/missing');
+ if($type==='button')
+ return CHtml::button($label,$url);
+ else
+ return CHtml::link($label,$url);
+ }
+ private function ajaxDialog($label,$url,$title=null,$type='link',$ajaxOptions=array()){
+
+ $id=self::ID.'-dialog';
+
+ $ajaxOptions=array_merge(array(
+ 'update'=>'#'.$id,
+ 'type'=>'post',
+ 'complete'=>"function(){ $('#{$id}').dialog('option', 'position', 'center').dialog('open');}",
+ ),$ajaxOptions);
+
+ $url=Yii::app()->getController()->createUrl($url);
+
+ if($type==='button')
+ $content=CHtml::ajaxButton($label,$url,$ajaxOptions);
+ else
+ $content=CHtml::ajaxLink($label,$url,$ajaxOptions);
+
+ $content.=Yii::app()->getController()->widget('zii.widgets.jui.CJuiDialog',array(
+ 'options'=>array_merge($this->dialogOptions,array('title'=>$title)),
+ 'id'=>$id
+ ),true);
+ return $content;
+ }
+ /**
+ * returns the language in use
+ * the language is determined by many variables: session, post, get, header in this order
+ * it will filter the language by using accepted languages
+ *
+ * @return string
+ */
+ function getLanguage(){
+ $key=self::ID;
+ if(($language=@$this->_cache['language'])!==null)
+ return $language;
+ elseif(Yii::app()->getSession()->contains($key))
+ $language=Yii::app()->getSession()->get($key);
+ elseif(isset($_POST[$key]) && !empty($_POST[$key]))
+ $language=$_POST[$key];
+ elseif(isset($_GET[$key]) && !empty($_GET[$key]))
+ $language=$_GET[$key];
+ else
+ $language=Yii::app()->getRequest()->getPreferredLanguage();
+
+ if(!key_exists($language,$this->acceptedLanguages)){
+ if($language===Yii::app()->sourceLanguage)
+ $language=$this->defaultLanguage;
+ elseif(strpos($language,"_")!==false){
+ $language=substr($language,0,2);
+ if(!key_exists($language,$this->acceptedLanguages))
+ $language=$this->defaultLanguage;
+ }
+ }
+ return $language;
+ }
+ /**
+ *
+ * set the language that the application will use
+ * if $language is null then if you use getLanguage to determine the target language
+ *
+ * it doesn't check if the language is in the accepted languages
+ *
+ * @param string | null $language language to set
+ * @return string the language setted
+ */
+ function setLanguage($language=null){
+ if($language===null)
+ $language=$this->getLanguage();
+
+ $this->_cache['language']=$language;
+
+ Yii::app()->getSession()->add(self::ID,$language);
+ Yii::app()->setLanguage($language);
+ return $language;
+ }
+ /**
+ * generates a dropdown containing all accepted languages
+ *
+ * @return string
+ */
+ function dropdown(){
+ Yii::app()->getClientScript()->registerScript(self::ID.'-dropdown','
+ $("#'.self::ID.'").change(function(){
+ $.post(
+ "'.Yii::app()->getController()->createUrl("/translate/translate/set").'",
+ {"'.self::ID.'":$(this).val()},
+ function(){window.top.location.reload();}
+ )});
+ ');
+ return CHtml::dropDownList(self::ID,$this->getLanguage(),
+ $this->acceptedLanguages,
+ array('id'=>self::ID)
+ );
+ }
+ /**
+ * translate some message from $sourceLanguage to $targetLanguage using google translate api
+ * googleApiKey must be defined to use this service
+ * @param string $message to be translated
+ * @param string $targetLanguage language to translate the message to, if null it will use the current language in use
+ * @param mixed $sourceLanguage language that the message is written in, if null it will use the application source language
+ * @return string translated message
+ */
+ function googleTranslate($message,$targetLanguage=null,$sourceLanguage=null) {
+ if($targetLanguage===null)
+ $targetLanguage=Yii::app()->getLanguage();
+ if($sourceLanguage===null)
+ $sourceLanguage=Yii::app()->sourceLanguage;
+ if(empty($sourceLanguage))
+ throw new CException(TranslateModule::t('Source language must be defined'));
+ if($targetLanguage===$sourceLanguage)
+ throw new CException(TranslateModule::t('targetLanguage must be different than sourceLanguage'));
+ $query=$this->queryGoogle(array('q'=>$message,'source'=>$sourceLanguage,'target'=>$targetLanguage));
+ if(is_array($message)){
+ foreach($query->translations as $translation)
+ $translated[]=$translation->translatedText;
+ return $translated;
+ }else
+ return $query->translations[0]->translatedText;
+ }
+ /**
+ * returns an array containing all languages accepted by google translate
+ *
+ * @param string $targetLanguage
+ * @return array
+ */
+ function getGoogleAcceptedLanguages($targetLanguage=null){
+ $cacheKey=self::ID.'-cache-google-languages-'.$targetLanguage;
+ if(!isset($this->_cache[$cacheKey])){
+ if(($cache=Yii::app()->getCache())===null || ($languages=$cache->get($cacheKey))===false){
+ $queryLanguages=$this->queryGoogle($targetLanguage!==null ? array('target'=>$targetLanguage) : array(),'languages');
+ foreach($queryLanguages->languages as $language){
+ $languages[$language->language]=isset($language->name) ? $language->name : $language->language;
+ }
+ if($cache!==null)
+ $cache->set($cacheKey,$languages);
+ $this->_cache[$cacheKey]=$languages;
+ }
+ }else
+ $languages=$this->_cache[$cacheKey];
+ return $languages;
+ }
+ /**
+ * query google translate api
+ *
+ * @param array $args
+ * @param string $method the method to use, use null to translate
+ * accepted values are null(translate), "languages" and "detect"
+ * @return stdClass the google response object
+ */
+ protected function queryGoogle($args=array(),$method=null){
+ if(empty($this->googleApiKey))
+ throw new CException(TranslateModule::t('You must set googleApiKey'));
+ if($method!==null)
+ $method="/{$method}";
+ $url=preg_replace('/%5B\d+%5D/','',"https://www.googleapis.com/language/translate/v2{$method}?".http_build_query(array_merge($args,array('key'=>$this->googleApiKey))));
+
+ if(in_array('curl',get_loaded_extensions())){//curl has much better performance
+ $curl=curl_init($url);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//to speed up the query
+ $trans = curl_exec($curl);
+ curl_close($curl);
+ }else
+ $trans=file_get_contents($url);
+
+ if(!$trans)
+ return false;
+ $trans=json_decode($trans);
+
+ if(isset($trans->error)){
+ Yii::log('Google translate error:'.$trans->error->code.'. '.$trans->error->message,CLogger::LEVEL_ERROR,'translate');
+ return false;
+ }elseif(!isset($trans->data)){
+ Yii::log('Google transalte error:'.print_r($trans,true),CLogger::LEVEL_ERROR,'translate');
+ return false;
+ }else
+ return $trans->data;
+ }
+ /**
+ * helper so you can use MPTransalate::someMethod($args)
+ *
+ * php 5.3 only
+ *
+ * @param mixed $method
+ * @param mixed $args
+ * @return mixed
+ */
+ static function __callStatic($method,$args){
+ return call_user_func_array(array(TranslateModule::translator(),$method),$args);
+ }
+}
36 components/TranslateBaseController.php
@@ -0,0 +1,36 @@
+<?php
+
+class TranslateBaseController extends Controller{
+ /**
+ * override needed to check if its ajax, the redirect will be by javascript
+ */
+ public function redirect($url,$terminate=true,$statusCode=302){
+ if(!Yii::app()->getRequest()->getIsAjaxRequest()){
+ return parent::redirect($url,$terminate,$statusCode);
+ }else{
+ if(is_array($url)){
+ $route=isset($url[0]) ? $url[0] : '';
+ $url=$this->createUrl($route,array_splice($url,1));
+ }
+ echo CHtml::script("window.top.location='$url'");
+ if($terminate)
+ Yii::app()->end($statusCode);
+ }
+ }
+ /**
+ * override needed to, in case of ajax requests, use renderPartial and disable the jquery
+ */
+ public function render($view,$data=array(),$return=false){
+ if(!Yii::app()->getRequest()->getIsAjaxRequest()){
+ return parent::render($view,$data,$return);
+ }else{
+ Yii::app()->getClientScript()->scriptMap=array(
+ 'jquery.js'=>false,
+ 'jquery.min.js'=>false,
+ 'jquery.ui.js'=>false,
+ 'jquery.ui.min.js'=>false
+ );
+ return parent::renderPartial($view,$data,false,true);
+ }
+ }
+}
127 controllers/EditController.php
@@ -0,0 +1,127 @@
+<?php
+
+class EditController extends TranslateBaseController
+{
+ public $defaultAction='admin';
+ /**
+ * Updates a particular model.
+ * If update is successful, the browser will be redirected to the 'view' page.
+ * @param integer $id the ID of the model to be updated
+ */
+ public function actionCreate($id,$language)
+ {
+ $model=new Message('create');
+ $model->id=$id;
+ $model->language=$language;
+
+ if(isset($_POST['Message'])){
+ $model->attributes=$_POST['Message'];
+ if($model->save())
+ $this->redirect(array('missing'));
+ }
+
+ $this->render('form',array('model'=>$model));
+ }
+ /**
+ * Updates a particular model.
+ * If update is successful, the browser will be redirected to the 'view' page.
+ * @param integer $id the ID of the model to be updated
+ */
+ public function actionUpdate($id,$language)
+ {
+ $model=$this->translateLoadModel($id,$language);
+
+ if(isset($_POST['Message'])){
+ $model->attributes=$_POST['Message'];
+ if($model->save())
+ $this->redirect(array('admin'));
+ }
+
+ $this->render('form',array('model'=>$model));
+ }
+ /**
+ * Deletes a record
+ * @param integer $id the ID of the model to be deleted
+ * @param string $language the language of the model to de deleted
+ */
+ public function actionDelete($id,$language)
+ {
+ if(Yii::app()->getRequest()->getIsPostRequest()){
+ $model=$this->translateLoadModel($id,$language);
+ if($model->delete()){
+ if(Yii::app()->getRequest()->getIsAjaxRequest()){
+ echo TranslateModule::t('Message deleted successfully');
+ Yii::app()->end();
+ }else
+ $this->redirect(Yii::app()->getRequest()->getUrlReferrer());
+ }
+ }else
+ throw new CHttpException(400);
+
+ }
+
+ /**
+ * Manages all models.
+ */
+ public function actionAdmin()
+ {
+ $model=new Message('search');
+ $model->unsetAttributes(); // clear any default values
+ if(isset($_GET['Message']))
+ $model->attributes=$_GET['Message'];
+
+ $this->render('admin',array(
+ 'model'=>$model,
+ ));
+ }
+ /**
+ *
+ */
+ public function actionMissing()
+ {
+ $model=new MessageSource('search');
+ $model->unsetAttributes(); // clear any default values
+
+ if(isset($_GET['MessageSource']))
+ $model->attributes=$_GET['MessageSource'];
+
+ $model->language=TranslateModule::translator()->getLanguage();
+
+ $this->render('missing',array(
+ 'model'=>$model,
+ ));
+ }
+ /**
+ * Deletes a record
+ * @param integer $id the ID of the model to be deleted
+ * @param string $language the language of the model to de deleted
+ */
+ public function actionMissingdelete($id)
+ {
+ if(Yii::app()->getRequest()->getIsPostRequest()){
+ $model=MessageSource::model()->findByPk($id);
+ if($model->delete()){
+ if(Yii::app()->getRequest()->getIsAjaxRequest()){
+ echo TranslateModule::t('Message deleted successfully');
+ Yii::app()->end();
+ }else
+ $this->redirect(Yii::app()->getRequest()->getUrlReferrer());
+ }
+ }else
+ throw new CHttpException(400);
+
+ }
+
+ /**
+ * Returns the data model based on the primary key given in the GET variable.
+ * If the data model is not found, an HTTP exception will be raised.
+ * @param integer the ID of the model to be loaded
+ */
+ public function translateLoadModel($id,$language)
+ {
+ $model=Message::model()->findByPk(array('id'=>$id,'language'=>$language));
+ if($model===null)
+ throw new CHttpException(404,'The requested page does not exist.');
+ return $model;
+ }
+}
60 controllers/TranslateController.php
@@ -0,0 +1,60 @@
+<?php
+class TranslateController extends TranslateBaseController{
+ public function actionIndex(){
+ if(isset($_POST['Message'])){
+ foreach($_POST['Message'] as $id=>$message){
+ if(empty($message['translation']))
+ continue;
+ $model=new Message();
+ $message['id']=$id;
+ $model->setAttributes($message);
+ $model->save();
+ }
+ $this->redirect(Yii::app()->getUser()->getReturnUrl());
+ }
+ if(($referer=Yii::app()->getRequest()->getUrlReferrer()) && $referer!==$this->createUrl('index'))
+ Yii::app()->getUser()->setReturnUrl($referer);
+ $translator=TranslateModule::translator();
+ $key=$translator::ID."-missing";
+ if(isset($_POST[$key]))
+ $postMissing=$_POST[$key];
+ elseif(Yii::app()->getUser()->hasState($key))
+ $postMissing=Yii::app()->getUser()->getState($key);
+
+ if(count($postMissing)){
+ Yii::app()->getUser()->setState($key,$postMissing);
+ $cont=0;
+ foreach($postMissing as $id=>$message){
+ $models[$cont]=new Message;
+ $models[$cont]->setAttributes(array('id'=>$id,'language'=>$message['language']));
+ $cont++;
+ }
+ }else{
+ $this->renderText(TranslateModule::t('All messages translated'));
+ Yii::app()->end();
+ }
+
+ $data=array('messages'=>$postMissing,'models'=>$models);
+
+ $this->render('index',$data);
+ }
+ function actionSet(){
+ $translator=TranslateModule::translator();
+ if(Yii::app()->getRequest()->getIsPostRequest()){
+ TranslateModule::translator()->setLanguage($_POST[$translator::ID]);
+ $this->redirect(Yii::app()->getRequest()->getUrlReferrer());
+ }else
+ throw new CHttpException(400);
+ }
+ function actionGoogletranslate(){
+ if(Yii::app()->getRequest()->getIsPostRequest()){
+ $translation=TranslateModule::translator()->googleTranslate($_POST['message'],$_POST['language'],$_POST['sourceLanguage']);
+ if(is_array($translation))
+ echo CJSON::encode($translation);
+ else
+ echo $translation;
+ }else
+ throw new CHttpException(400);
+ }
+
+}
50 models/Message.php
@@ -0,0 +1,50 @@
+<?php
+class Message extends CActiveRecord{
+
+ public $message,$category;
+
+ static function model($className=__CLASS__){return parent::model($className);}
+ function tableName(){return Yii::app()->getMessages()->translatedMessageTable;}
+
+ function rules(){
+ return array(
+ array('id,language,translation','required'),
+ array('id', 'numerical', 'integerOnly'=>true),
+ array('language', 'length', 'max'=>16),
+ array('translation', 'safe'),
+ array('id, language, translation, category, message', 'safe', 'on'=>'search'),
+ );
+ }
+
+ function relations(){
+ return array(
+ 'source'=>array(self::BELONGS_TO,'MessageSource','id'),
+ );
+ }
+ function attributeLabels(){
+ return array(
+ 'id'=> TranslateModule::t('ID'),
+ 'language'=> TranslateModule::t('Language'),
+ 'translation'=> TranslateModule::t('Translation'),
+ 'category'=> MessageSource::model()->getAttributeLabel('category'),
+ 'message'=> MessageSource::model()->getAttributeLabel('message'),
+ );
+ }
+
+ function search(){
+ $criteria=new CDbCriteria;
+ $criteria->select='t.*,source.message as message,source.category as category';
+ $criteria->with=array('source');
+
+ $criteria->compare('t.id',$this->id);
+ $criteria->compare('t.language',$this->language,true);
+ $criteria->compare('t.translation',$this->translation,true);
+ $criteria->compare('source.category',$this->category,true);
+ $criteria->compare('source.message',$this->message,true);
+
+ return new CActiveDataProvider(get_class($this), array(
+ 'criteria'=>$criteria,
+ ));
+ }
+
+}
49 models/MessageSource.php
@@ -0,0 +1,49 @@
+<?php
+class MessageSource extends CActiveRecord{
+
+ public $language;
+
+ static function model($className=__CLASS__){return parent::model($className);}
+ function tableName(){return Yii::app()->getMessages()->sourceMessageTable;}
+
+ function rules(){
+ return array(
+ array('category,message','required'),
+ array('category', 'length', 'max'=>32),
+ array('message', 'safe'),
+ array('id, category, message,language', 'safe', 'on'=>'search'),
+ );
+ }
+
+ function relations(){
+ return array(
+ 'mt'=>array(self::HAS_MANY,'Message','id','joinType'=>'inner join'),
+ );
+ }
+ function attributeLabels(){
+ return array(
+ 'id'=> TranslateModule::t('ID'),
+ 'category'=> TranslateModule::t('Category'),
+ 'message'=> TranslateModule::t('Message'),
+ );
+ }
+
+ function search(){
+ $criteria=new CDbCriteria;
+
+ $criteria->with=array('mt');
+
+ $criteria->addCondition('not exists (select `id` from `'.Message::model()->tableName().'` `m` where `m`.`language`=:lang and `m`.id=`t`.`id`)');
+
+ $criteria->compare('t.id',$this->id);
+ $criteria->compare('t.category',$this->category);
+ $criteria->compare('t.message',$this->message);
+
+ $criteria->params[':lang']=$this->language;
+
+ return new CActiveDataProvider(get_class($this), array(
+ 'criteria'=>$criteria,
+ ));
+ }
+
+}
34 views/edit/admin.php
@@ -0,0 +1,34 @@
+<h1><?php echo TranslateModule::t('Manage Messages')?></h1>
+
+<?php
+$source=MessageSource::model()->findAll();
+$this->widget('zii.widgets.grid.CGridView', array(
+ 'id'=>'message-grid',
+ 'dataProvider'=>$model->search(),
+ 'filter'=>$model,
+ 'columns'=>array(
+ array(
+ 'name'=>'id',
+ 'filter'=>CHtml::listData($source,'id','id'),
+ ),
+ array(
+ 'name'=>'message',
+ 'filter'=>CHtml::listData($source,'message','message'),
+ ),
+ array(
+ 'name'=>'category',
+ 'filter'=>CHtml::listData($source,'category','category'),
+ ),
+ array(
+ 'name'=>'language',
+ 'filter'=>CHtml::listData($model->findAll(new CDbCriteria(array('group'=>'language'))),'language','language')
+ ),
+ 'translation',
+ array(
+ 'class'=>'CButtonColumn',
+ 'template'=>'{update}{delete}',
+ 'updateButtonUrl'=>'Yii::app()->getController()->createUrl("update",array("id"=>$data->id,"language"=>$data->language))',
+ 'deleteButtonUrl'=>'Yii::app()->getController()->createUrl("delete",array("id"=>$data->id,"language"=>$data->language))',
+ )
+ ),
+)); ?>
37 views/edit/form.php
@@ -0,0 +1,37 @@
+<?php $action=$model->getIsNewRecord() ? 'Create' : 'Update';?>
+<h1><?php echo TranslateModule::t(($action) . ' Message')." # ".$model->id." - ".TranslateModule::translator()->acceptedLanguages[$model->language]; ?></h1>
+
+<div class="form">
+
+<?php $form=$this->beginWidget('CActiveForm', array(
+ 'id'=>'message-form',
+ 'enableAjaxValidation'=>false,
+)); ?>
+
+ <p class="note">Fields with <span class="required">*</span> are required.</p>
+
+ <?php echo $form->hiddenField($model,'id',array('size'=>10,'maxlength'=>10)); ?>
+ <?php echo $form->hiddenField($model,'language',array('size'=>16,'maxlength'=>16)); ?>
+
+ <div class="row">
+ <?php echo $form->label($model->source,'category'); ?>
+ <?php echo $form->textField($model->source,'category',array('disabled'=>'disabled')); ?>
+ </div>
+ <div class="row">
+ <?php echo $form->label($model->source,'message'); ?>
+ <?php echo $form->textField($model->source,'message',array('disabled'=>'disabled')); ?>
+ </div>
+
+ <div class="row">
+ <?php echo $form->labelEx($model,'translation'); ?>
+ <?php echo $form->textArea($model,'translation',array('rows'=>2, 'cols'=>80)); ?>
+ <?php echo $form->error($model,'translation'); ?>
+ </div>
+
+ <div class="row buttons">
+ <?php echo CHtml::submitButton(TranslateModule::t($action)); ?>
+ </div>
+
+<?php $this->endWidget(); ?>
+
+</div><!-- form -->
31 views/edit/missing.php
@@ -0,0 +1,31 @@
+<h1><?php echo TranslateModule::t('Missing Translations')." - ".TranslateModule::translator()->acceptedLanguages[Yii::app()->getLanguage()]?></h1>
+<?php
+$source=MessageSource::model()->findAll();
+$this->widget('zii.widgets.grid.CGridView', array(
+ 'id'=>'message-grid',
+ 'dataProvider'=>$model->search(),
+ 'filter'=>$model,
+ 'columns'=>array(
+ 'id',
+ array(
+ 'name'=>'message',
+ 'filter'=>CHtml::listData($source,'message','message'),
+ ),
+ array(
+ 'name'=>'category',
+ 'filter'=>CHtml::listData($source,'category','category'),
+ ),
+ array(
+ 'class'=>'CButtonColumn',
+ 'template'=>'{create}{delete}',
+ 'deleteButtonUrl'=>'Yii::app()->getController()->createUrl("missingdelete",array("id"=>$data->id))',
+ 'buttons'=>array(
+ 'create'=>array(
+ 'label'=>TranslateModule::t('Create'),
+ 'url'=>'Yii::app()->getController()->createUrl("create",array("id"=>$data->id,"language"=>Yii::app()->getLanguage()))'
+ )
+ ),
+ 'header'=>TranslateModule::translator()->dropdown(),
+ )
+ ),
+)); ?>
52 views/translate/_form.php
@@ -0,0 +1,52 @@
+<?php
+
+$translator=TranslateModule::translator();
+$languageKey=$translator::ID;
+$id=$data->id;
+$message=$messages[$id];
+
+if($google)
+ $tagId="{$languageKey}-{$id}";
+
+echo CHtml::openTag('tr');
+
+echo CHtml::tag('td',array(),
+ CHtml::tag('span',array('margin:0 5px'),$message['category'])
+);
+echo CHtml::tag('td',array(),
+ CHtml::tag('span',array(
+ 'margin:0 5px',
+ 'class'=>$languageKey."-google-message"
+ ),$message['message']
+ )
+);
+echo CHtml::tag('td',array(),
+ CHtml::activeTextArea($data,"[$id]translation",array('id'=>$google ? $tagId : null,'class'=>"{$languageKey}-google-translation",'cols'=>35,'rows'=>2)).
+ CHtml::activeHiddenField($data,"[$id]language")
+);
+if($google){
+ echo CHtml::tag('td',array(),
+ CHtml::ajaxLink(TranslateModule::t('Translate'),
+ $this->createUrl('translate/googletranslate'),
+ array(
+ 'type'=>'post',
+ 'data'=>array(
+ 'message'=>$message['message'],
+ 'language'=>Yii::app()->getLanguage(),
+ 'sourceLanguage'=>Yii::app()->sourceLanguage
+ ),
+ 'success'=>"js:function(response){
+ \$('#{$tagId}').val(response);
+ \$('#{$tagId}-button').hide();
+ }",
+ 'error'=>'js:function(xhr){alert(xhr.responseText);}',
+ ),
+ array(
+ 'margin:0 5px',
+ 'class'=>"{$languageKey}-google-button",
+ 'id'=>$tagId.'-button',
+ )
+ )
+ );
+}
+echo CHtml::closeTag('tr');
74 views/translate/index.php
@@ -0,0 +1,74 @@
+<?php
+ $language=TranslateModule::translator();
+ $languageKey=$language::ID;
+
+ $google=!empty(TranslateModule::translator()->googleApiKey) ? true : false;
+?>
+<h2><?php echo TranslateModule::t('Translate to {lang}',array('{lang}'=>$language->acceptedLanguages[$language->getLanguage()]));?></h2>
+<?php
+ if($google){
+ echo CHtml::link(TranslateModule::t('Translate all with google translate'),"#",array('id'=>$languageKey."-google-translateall"));
+ echo CHtml::script(
+ "\$('#{$languageKey}-google-translateall').click(function(){
+ var messages=[];\$('.{$languageKey}-google-message').each(function(count){
+ messages[count]=$(this).html();
+ });".
+ CHtml::ajax(array(
+ 'url'=>$this->createUrl('translate/googletranslate'),
+ 'type'=>'post',
+ 'dataType'=>"json",
+ 'data'=>array(
+ 'language'=>Yii::app()->getLanguage(),
+ 'sourceLanguage'=>Yii::app()->sourceLanguage,
+ 'message'=>'js:messages'
+ ),
+ 'success'=>"js:function(response){
+ \$('.{$languageKey}-google-translation').each(function(count){
+ $(this).val(response[count]);
+ });
+ \$('.{$languageKey}-google-button,#{$languageKey}-google-translateall').hide();
+ }",
+ 'error'=>'js:function(xhr){alert(xhr.statusText);}',
+ ))."
+ return false;
+ });
+ ");
+ if(Yii::app()->getRequest()->isAjaxRequest){
+ echo CHtml::script("
+ $('#".$languageKey.'-pager'." a').click(function(){
+ \$dialog=$('#".$languageKey.'-dialog'."').load($(this).attr('href'));
+ return false;
+ });
+ ");
+ }
+ }
+?>
+<div class="form">
+ <?php echo CHtml::beginForm(); ?>
+ <table>
+ <thead>
+ <th><?php echo MessageSource::model()->getAttributeLabel('category'); ?></th>
+ <th><?php echo MessageSource::model()->getAttributeLabel('message'); ?></th>
+ <th><?php echo Message::model()->getAttributeLabel('translation');?></th>
+ <?php echo $google ? CHtml::tag('th') : null;?>
+ </thead>
+ <tbody>
+ <?php
+ $this->widget('zii.widgets.CListView', array(
+ 'dataProvider'=>new CArrayDataProvider($models),
+ 'pager'=>array(
+ 'id'=>$languageKey.'-pager',
+ 'class'=>'CLinkPager',
+ ),
+ 'viewData'=>array(
+ 'messages'=>$messages,
+ 'google'=>$google,
+ ),
+ 'itemView'=>'_form',
+ ));
+ ?>
+ </tbody>
+ </table>
+ <?php echo CHtml::submitButton(TranslateModule::t('Translate'));?>
+ <?php echo CHtml::endForm()?>
+</div>

0 comments on commit a75f706

Please sign in to comment.
Something went wrong with that request. Please try again.