Thank you very much for your guide.  I've solved I18N in a little
different way, but you way is inspirational.


On 11 čvn, 11:49, "Christopher Schnell" <[email protected]> wrote:
> Forgot to mention one thing. The objects __toString methods need to be able 
> to do some sort of language fallback like
>
>   public function __toString()
>   {
>     // get the title in the current language
>     $title=$this->getTitle();
>
>     // maybe some other preferences here
>     //...
>
>     // Last possibility: get the title in the first available language
>     if(empty($title))
>     {
>       $cultures=sfConfig::get('sf_application_cultures');
>
>       for($i=0;$i<count($cultures['code']);$i++){
>         if($this->getTitle($cultures['code'][$i])!=null)
>         {
>           $title=$this->getTitle($cultures['code'][$i]);
>           break;
>         }
>       }
>     }
>
>     return $title;
>   }
>
> -----Ursprüngliche Nachricht-----
> Von: [email protected] [mailto:[email protected]] 
> Im Auftrag von Christopher Schnell
> Gesendet: Freitag, 11. Juni 2010 11:29
> An: [email protected]
> Betreff: AW: [symfony-users] Re: Managing i18n content for frontend in the 
> backend
>
> Ok, here we go:
>
> Maybe I should explain the project a little: It is a system for managing 
> online E-Learning courses. It has several customers that can be assigned to 
> courses. The customers can manage their courses in coursecategories. Courses 
> and coursecategories have titles and descriptions which are translated. 
> Originally, we had German and English, so I did it the "Jobeet way". Then a 
> customer said, they wanted to also store the data also in Simplified Chinese. 
> Thats when I started to rebuild the translation system. Now, I have a system, 
> where i can simply add a language in my configuration file and be done with 
> it. Here is how it works:
>
> 1. in the apps settings.yml, I add the available cultures, like
> ...
> application_cultures:
>       code:                 [en, de, zh]
>       name:                 [English, Deutsch, Simp.Chinese]
>
> 2. In the schema.yml I have to set the "required" option for the translated 
> values to false, so that I won't get an error on saving the form.
>
> 3. Then, I had to write an custom validator, that validates that a title (or 
> any other mandatory field) is set in at least one language.
>
> In configure() of the main Form (not the I18n):
> ...
> $cultures=sfConfig::get('sf_application_cultures');
>
> $this->embedI18n($cultures['code']);
> for($i=0;$i<count($cultures['code']);$i++)
> {
>   $this->widgetSchema->setLabel($cultures['code'][$i], 
> $cultures['name'][$i]);}
>
> $this->validatorSchema->setPostValidator(
>   new sfValidatorCallback(array('callback' => array($this, 
> 'validateOneTitle')))
> );
> ...
>
> And then write a method validateOneTitle()
> public function validateOneTitle($validator, $values)
> {
>   $cultures=sfConfig::get('sf_application_cultures');
>   for($i=0;$i<count($cultures['code']);$i++)
>   {
>     if(!empty($values[$cultures['code'][$i]]['title']))
>     {
>       return $values;
>     }
>   }
>
>   throw new sfValidatorError($validator, 'You need to enter the title in the 
> language, you are editing.');
>
> }
>
> That is all in the form class.
>
> Now we have to add a small filter form that can be used to trigger the ajax 
> call. It looks like this:
>
> class LanguageFilterForm extends BaseForm
> {
>   public function configure()
>   {
>     $cultures=sfConfig::get('sf_application_cultures');
>
>     for($i=0;$i<count($cultures['code']);$i++){
>       $mycultures[$cultures['code'][$i]]=$cultures['name'][$i];
>     }
>
>     $this->widgetSchema['languages']=new 
> sfWidgetFormSelect(array('choices'=>$mycultures));
>   }
>
> }
>
> The more tricky parts are the template and the action class. Lets start with 
> the template:
> In the editSuccess.php the div for the form that is reloaded by the ajax-call 
> is located. I do all my ajax-stuff with jquery. In my example, I use the form 
> for a above explained "Coursecategory".
>
> <div id="canvas">
>   <img id="loader" src="/images/loader.gif" style="vertical-align: middle; 
> display: none" />
>   <?php include_partial('form', 
> array('form'=>$form,'editingLanguageCode'=>$editingLanguageCode,'editingLan­guageName'=>$editingLanguageName,'coursecategory'=>$coursecategory))?>
> </div>
>
> <?php slot('col2_content') ?>    
>   <?php include_partial('global/ajaxLanguageForm', 
> array('module'=>$sf_context->getModuleName(),'action'=>'edit','object'=>$co­ursecategory,'languageForm'=>$languageForm))?>
> <?php end_slot() ?>
>
> We pass all the required data to the form partial (the form object, the 
> coursecategory object (which of course isn't nessessary, but "grown" code), 
> and the languagecode and name).
>
> The partial in the slot is a dropdownbox, that I include in all forms for 
> translated Objects, therefor it resides in the  layout folder and gets the 
> module and action passed, as well as the LanguageFilterForm. The code of the 
> partial is like:
>
> <?php echo javascript_tag() ?>
> $(document).ready(function()
> {
>   $("#languages").change(function()
>   {
>         $('#loader').show();
>
>     var myLang=$(this).children('option:selected').val();
>     $("#canvas").load(
>       $(this).parents('form').attr('action'),
>       { lang: myLang },
>       function() { $('#loader').hide(); }
>     );
>   });});
>
> <?php end_javascript_tag() ?>
>
> <form action="<?php echo url_for($module.'/'.$action.(!$object->isNew() ? 
> '?id='.$object->getId() : '')) ?>" method="post">
>         <?php echo $languageForm['languages']->renderError() ?>
>         <?php echo $languageForm['languages'] ?>
>         <?php echo $languageForm['_csrf_token']?>
> </form>
>
> Now the form partial is still missing. I leave this code out, since it is a 
> little long. The important thing is that the form is not rendered by <?php 
> echo $form?> but as single form fields. I split the form into two partials, 
> one is the form with non translated values and the other is the form with 
> translations. So in the main form, I include:
>
> <?php include_partial('i18nForm', 
> array('form'=>$form,'editingLanguageCode'=>$editingLanguageCode));?>
>
> The I18nForm partial now needs to change the language code in the form fields 
> to store the translated values like:
>
> <tr>
>       <th>
>         <label for="coursecategory_<?php echo 
> $editingLanguageCode?>_title"><?php echo __('Title') ?> *</label>
>       </th>
>       <td>
>         <div class="error_message"><?php echo 
> $form[$editingLanguageCode]['title']->renderError() ?></div>
>         <?php echo $form[$editingLanguageCode]['title']->render(array('class' 
> => 'input')) ?>
>       </td>
>     </tr>
>
> Thats all in the templates, only the action is missing. Since i have to 
> process two forms (languageform and Objectform), I placed  the form creation 
> code in a separate method. Most of the code is pretty standard.
>
>   public function executeNew(sfWebRequest $request)
>   {
>     $this->getForms($request->getParameter('lang'));
>   }
>
>   public function executeCreate(sfWebRequest $request)
>   {
>     $this->forward404Unless($request->isMethod(sfRequest::POST));
>
>     $this->getForms($request->getParameter('lang'));
>
>     $this->processForm($request, $this->form);
>
>     $this->setTemplate('new');
>   }
>
>   /**
>    * Edit a Coursecategory
>    *
>    * @param sfWebRequest $request A request object
>    */
>   public function executeEdit(sfWebRequest $request)
>   {
>     
> $this->coursecategory=CoursecategoryPeer::retrieveByPk($request->getParamet­er('id'));
>
>     $this->getForms($request->getParameter('lang'),$this->coursecategory);
>
>     if($request->isXmlHttpRequest())
>     {
>       return $this->renderPartial('coursecategory/form', array('form' => 
> $this->form,'coursecategory'=>$this->coursecategory,'editingLanguageCode'=>­$this->editingLanguageCode,'editingLanguageName'=>$this->editingLanguageNam­e));
>     }    
>   }
>
>   public function executeUpdate(sfWebRequest $request)
>   {
>     $this->forward404Unless($request->isMethod(sfRequest::POST) || 
> $request->isMethod(sfRequest::PUT));
>     $this->forward404Unless($Coursecategory = 
> CoursecategoryPeer::retrieveByPk($request->getParameter('id')), 
> sprintf('Object Coursecategory does not exist (%s).', 
> $request->getParameter('id')));
>
>     $this->getForms($request->getParameter('lang'),$Coursecategory);
>
>     $this->processForm($request, $this->form);
>
>     $this->setTemplate('edit');
>   }
>
>   protected function processForm(sfWebRequest $request, sfForm $form)
>   {
>     $form->bind($request->getParameter($form->getName()), 
> $request->getFiles($form->getName()));
>     if ($form->isValid())
>     {
>       $this->getUser()->setFlash('notice', 'Coursecategory saved 
> successfully.');
>       $Coursecategory = $form->save();
>
>       $this->redirect('@coursecategory');
>     }
>   }
>
>   protected function getForms($lang=null,$coursecategory=null)
>   {
>     $editingLanguage=$this->getUser()->getEditingLanguage($lang);
>     $this->editingLanguageCode=$editingLanguage['code'];
>     $this->editingLanguageName=$editingLanguage['name'];
>
>     $this->form = new CoursecategoryForm($coursecategory);
>
>     $this->languageForm=new LanguageFilterForm();
>     $this->languageForm->setDefault('languages',$this->editingLanguageCode);
>   }
>
> Last thing, I forgot was that the default language should be the one, the 
> user selected for himself, so that is the call to 
> this->getUser()->getEditingLanguage($lang);
>
> In myUser.class.php
>
>   public function getEditingLanguage($lang=null)
>   {
>     $cultures=sfConfig::get('sf_application_cultures');
>
>     $editingLanguage['code']=$this->getCulture();
>
>     if(!is_null($lang))
>     {
>       $editingLanguage['code']=$lang;
>     }
>
>     for($i=0;$i<count($cultures['code']);$i++){
>       if($cultures['code'][$i]==$editingLanguage['code'])
>       {
>         $editingLanguage['name']=$cultures['name'][$i];
>       }
>     }
>
>     return $editingLanguage;
>   }
>
> That's all, I hope I didn't forget anything. If anything is unclear, feel 
> free to ask. Here is also some screenshot of the 
> form:http://www.mda.ch/lms/Bildschirmfoto.pnghttp://www.mda.ch/lms/Bildschirmfoto-1.png
>
> Regards,
> Christopher.
>
> -----Ursprüngliche Nachricht-----
> Von: [email protected] [mailto:[email protected]] 
> Im Auftrag von Tom Ptacnik
> Gesendet: Donnerstag, 10. Juni 2010 10:10
> An: symfony users
> Betreff: [symfony-users] Re: Managing i18n content for frontend in the backend
>
> I prefer codewise, but if you can show me also how it look in action,
> I don't ...
>
> číst dál »

-- 
If you want to report a vulnerability issue on symfony, please send it to 
security at symfony-project.com

You received this message because you are subscribed to the Google
Groups "symfony users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/symfony-users?hl=en

Reply via email to