-
-
Save pulse00/1985208 to your computer and use it in GitHub Desktop.
| <?php | |
| class PageAdmin extends BaseAdmin | |
| { | |
| protected function configureFormFields(FormMapper $formMapper) | |
| { | |
| parent::configureFormFields($formMapper); | |
| $page = $formMapper->getAdmin()->getSubject(); | |
| foreach (Page::translationFields() as $field) { | |
| $options = array( | |
| 'data' => $page, | |
| 'locales' => array('en', 'de'), | |
| ); | |
| if ($field != 'name') { | |
| $options['type'] = 'textarea'; | |
| } | |
| $formMapper->remove($field)->add($field, 'sonata_type_translatable', $options); | |
| } | |
| } | |
| public function preUpdate($object) | |
| { | |
| $this->translate($object); | |
| parent::preUpdate($object); | |
| } | |
| public function prePersist($object) | |
| { | |
| $this->translate($object); | |
| parent::prePersist($object); | |
| } | |
| private function translate(Page $page) | |
| { | |
| // translationFields() simply returns an array | |
| // of names of the fields to be translated, e.g. array('name', 'description') | |
| foreach (Page::translationFields() as $field) { | |
| $getter = 'get' . ucfirst($field); | |
| foreach ($page->{$getter}() as $key => $value) { | |
| $parts = explode('_', $key); | |
| $name = $parts[0]; | |
| $locale = $parts[1]; | |
| $page->translate($locale)->{$name} = $value; | |
| } | |
| } | |
| foreach (Page::translationFields() as $field) { | |
| $getter = 'get' . ucfirst($field); | |
| if ( is_array($page->{$getter}()) ) { | |
| $setter = 'set' . ucFirst($field); | |
| $page->{$setter}(''); | |
| } | |
| } | |
| } | |
| } |
| # register the translatable type as a service | |
| parameters: | |
| dubture_core.page.form.type.translatable.class: Application\Sonata\PageBundle\Form\Type\TranslatableType | |
| services: | |
| dubture_core.page.form.type.translatable: | |
| class: %dubture_core.page.form.type.translatable.class% | |
| tags: | |
| - { name: form.type, alias: sonata_type_translatable } |
| <?php | |
| class TranslatableType extends AbstractType | |
| { | |
| public function buildForm(FormBuilder $builder, array $options) | |
| { | |
| // creates an input field for each locale with the name | |
| // fieldName_locale | |
| foreach ($options['locales'] as $locale) { | |
| $name = $builder->getName() . '_' . $locale; | |
| $builder->add($name, $options['type'], $opts); | |
| } | |
| } | |
| public function getDefaultOptions(array $options) | |
| { | |
| return array_merge($options, array('type' => null)); | |
| } | |
| public function getName() | |
| { | |
| return 'sonata_type_translatable'; | |
| } | |
| } |
I forgot to remove the $opts variable from the gist, it's simply an array for the 3rd FormBuilder::add argument, something like:
<?php
$opts = array('attr' => array('class' => 'aloha'));As for the get{Field}De problem, this is one major awkwardness of this solution, as you need to add these methods for each field and each locale.
<?php
public function getNameDe() { return $this->translate('de')->getName(); }
public function setNameDe($name) { $this->translate('de')->setName($name); return $this } All in all i think this is not a really proper way to do the database translations together with sonata - that's why i'll probably switch to the Symfony CMF and jackrabbit
For resolving this error i have changed like below and i have added a TranslationProxy :
<?php
class TranslatableType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
// creates an input field for each locale with the name
// fieldName_locale
foreach ($options['locales'] as $locale) {
//here modification BEGIN
$name = $locale.'Translation.'.$builder->getName() ;
//here modification END
$builder->add($name, $options['type'], array());
}
}
public function getDefaultOptions(array $options)
{
return array_merge($options, array('type' => null));
}
public function getName()
{
return 'sonata_type_translatable';
}
}This post can help too http://knplabs.fr/blog/I%28blah...blah...blah%29n
@cifren this sounds like a good solution...the problem is that the builder do not accept a name like itTranslation.title. It tells:
The name "itTranslation.title" contains illegal characters. Names should start with a letter, digit or underscore and only contain letters, digits, numbers, underscores ("_"), hyphens ("-") and colons (":").
Maybe this is related to the fact that I'm on symfony master? Maybe the form component changed in some way?
by now my solution is adding two magic methods to che entity:
public function __get($property)
{
if (preg_match('/(.*)_(.{2})/', $property, $matches)) {
$prop = $matches[1];
$lang = $matches[2];
$method = 'get'.ucfirst($prop);
return $this->translate($lang)->{$method}();
}
}
public function __set($property, $value)
{
if (preg_match('/(.*)_(.{2})/', $property, $matches)) {
$prop = $matches[1];
$lang = $matches[2];
$method = 'set'.ucfirst($prop);
$this->translate($lang)->{$method}($value);
}
}
and in the admin class simply call:
$form
->add('title', 'text')
->add('title_en', 'text')
At the end I try other else
Create an array of the translation and give it to Form and get back and create all the translation object just after like this :
In the Entity :
<?php
....
public function getArrayTranslations($default_locale = 'en', $all_locale_translation = null) {
$all_locale_translation = (!$this->all_locale_translation)? $default_locale : $this->all_locale_translation;
$default_locale = (!$this->default_locale)? $default_locale : $this->default_locale;
$arrayTranslations = array();
foreach($all_locale_translation as $locale)
{
foreach(self::translationFields() as $property)
{
$getter = 'get'.lcfirst($property);
$arrayTranslations[$locale][$property] = $this->translate(($locale==$default_locale)?null:$locale)->$getter();
}
}
return $arrayTranslations;
}
public function setArrayTranslations($array, $default_locale = 'en', $all_locale_translation = null) {
$all_locale_translation = (!$this->all_locale_translation)? $default_locale : $this->all_locale_translation;
$default_locale = (!$this->default_locale)? $default_locale : $this->default_locale;
foreach($array as $locale => $values)
{
foreach($values as $property => $value)
{
$setter = 'set'.lcfirst($property);
$this->translate(($locale==$default_locale)?null:$locale)->$setter($value);
}
}
return $this;
}
public static function translationFields() {
return array('title', 'blog', 'tags', 'intro');
}
....And in the Admin Form :
<?php
public function __construct($code, $class, $baseControllerName, ObjectManager $om, $default_locale, $all_locale)
{
parent::__construct($code, $class, $baseControllerName);
$this->om = $om;
$this->default_locale = $default_locale;
$this->all_locale = $all_locale;
}
protected function configureFormFields(FormMapper $formMapper)
{
....
->add('array_translations', 'collection',
array(
'type' => new BlogTranslationType()
)
)
....
}And BlogTranslationType
<?php
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('title')
->add('intro', 'textarea)
->add('blog', 'textarea')
->add('tags')
;
}And that's it !!!
After I added somefeature for the language option to get all the information from the config.yml
=> you have an example on this GIT https://github.com/cifren/BlogPerso/blob/master/src/Blogger/BlogBundle/Admin/BlogAdmin.php
hi!
Thanks for sharing...
this is not working for me. Firstly, in the TranslatableType there is no $opts var...and than the form gets an error because it looks for a get{Field}De to populate the default value...
Any idea?