Est-ce que quelqu'un a réussi à traduire les entités Sonata Admin sur Symfony 3 (en fait j'utilise 3.3).Traduction d'entités Sonata Admin sur Symfony 3
J'ai essayé différentes solutions, mais aucune n'a vraiment fonctionné. Avec la traduction gedmo, le problème principal est que les traductions sont sauvegardées pour les différentes langues de la base de données, mais dans l'admin (formulaires de fin de liste aussi) le paquet Sonata ne dispense que la traduction locale par défaut. cliqué/choisi. J'ai également essayé avec KNP tarnslation bundle, et avec traduction A2lix, mais ces deux ont le même problème: lorsque vous définissez (dans la classe admin) un champ comme "triable" puis dans la liste des enregistrements lorsque vous essayez de Symfony lance une erreur, car les systèmes de traduction tentent de créer une association avec un autre champ qui n'existe pas! Quoi qu'il en soit, restant sur la Gedmo soultion, le principal problème est que (mettre à part la solution A2lix à cause du problème que j'ai déjà mentionné) je ne sais pas comment définir un champ traduisible dans la classe admin (BlogPostAdmin.php) parce que simplement en utilisant les fichiers de configuration et l'entité et la classe de traduction, ne semble pas fonctionner. Le problème, comme déjà dit, est que les traductions sont sauvegardées dans la base de données, mais ne sont pas affichées dans les listes/formulaires d'administration.
Voici mes fichiers de configuration et entités:
AppKernel.php
<?php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = [
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new AppBundle\AppBundle(),
/// These are the other bundles the SonataAdminBundle relies on
new Sonata\CoreBundle\SonataCoreBundle(),
new Sonata\BlockBundle\SonataBlockBundle(),
new Knp\Bundle\MenuBundle\KnpMenuBundle(),
new Sonata\TranslationBundle\SonataTranslationBundle(),
// And finally, the storage and SonataAdminBundle
new Sonata\DoctrineORMAdminBundle\SonataDoctrineORMAdminBundle(),
new Sonata\AdminBundle\SonataAdminBundle(),
// stof [used in Sonata translations]
new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(),
// assetic
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
];
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
if ('dev' === $this->getEnvironment()) {
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
$bundles[] = new Symfony\Bundle\WebServerBundle\WebServerBundle();
}
}
return $bundles;
}
public function getRootDir()
{
return __DIR__;
}
public function getCacheDir()
{
return dirname(__DIR__).'/var/cache/'.$this->getEnvironment();
}
public function getLogDir()
{
return dirname(__DIR__).'/var/logs';
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml');
}
}
config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: it
framework:
#esi: ~
translator: { fallbacks: ['%locale%'] }
secret: '%secret%'
router:
resource: '%kernel.project_dir%/app/config/routing.yml'
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
#serializer: { enable_annotations: true }
templating:
engines: ['twig']
default_locale: '%locale%'
trusted_hosts: ~
session:
# https://symfony.com/doc/current/reference/configuration/framework.html#handler-id
handler_id: session.handler.native_file
save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'
fragments: ~
http_method_override: true
assets: ~
php_errors:
log: true
# Twig Configuration
twig:
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
# Doctrine Configuration
doctrine:
dbal:
driver: pdo_mysql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
charset: UTF8
# if using pdo_sqlite as your database driver:
# 1. add the path in parameters.yml
# e.g. database_path: "%kernel.project_dir%/var/data/data.sqlite"
# 2. Uncomment database_path in parameters.yml.dist
# 3. Uncomment next line:
#path: '%database_path%'
orm:
auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
# mappings:
# # Doctrine extensions
# translatable:
# type: annotation
# alias: Gedmo
# prefix: Gedmo\Translatable\Entity
# dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity/MappedSuperclass"
# Swiftmailer Configuration
swiftmailer:
transport: '%mailer_transport%'
host: '%mailer_host%'
username: '%mailer_user%'
password: '%mailer_password%'
spool: { type: memory }
sonata_block:
default_contexts: [cms]
blocks:
# enable the SonataAdminBundle block
sonata.admin.block.admin_list:
contexts: [admin]
sonata_translation:
locales: [it, en]
default_locale: %locale%
# here enable the types you need
gedmo:
enabled: true
# knplabs:
# enabled: true
#phpcr:
# enabled: true
sonata_admin:
templates:
layout: admin/layout.html.twig
assetic:
debug: '%kernel.debug%'
use_controller: '%kernel.debug%'
filters:
cssrewrite: ~
#stof_doctrine_extensions:
# #default_locale: %locale%
# orm:
# default:
# sluggable: true
# timestampable: true
services.yml
# Learn more about services, parameters and containers at
# https://symfony.com/doc/current/service_container.html
parameters:
locale: 'it'
locales: ['it', 'en']
services:
# default configuration for services in *this* file
_defaults:
# automatically injects dependencies in your services
autowire: true
# automatically registers your services as commands, event subscribers, etc.
autoconfigure: true
# this means you cannot fetch services directly from the container via $container->get()
# if you need to do this, you can override this setting on individual services
public: false
# makes classes in src/AppBundle available to be used as services
# this creates a service per class whose id is the fully-qualified class name
AppBundle\:
resource: '../../src/AppBundle/*'
# you can exclude directories or files
# but if a service is unused, it's removed anyway
exclude: '../../src/AppBundle/{Entity,Repository,Tests}'
# controllers are imported separately to make sure they're public
# and have a tag that allows actions to type-hint services
AppBundle\Controller\:
resource: '../../src/AppBundle/Controller'
public: true
tags: ['controller.service_arguments']
# add more services, or override services that need manual wiring
# AppBundle\Service\ExampleService:
# arguments:
# $someArgument: 'some_value'
admin.category:
class: AppBundle\Admin\CategoryAdmin
arguments: [~, AppBundle\Entity\Category, ~]
tags:
- { name: sonata.admin, manager_type: orm, label: Category }
public: true
admin.blog_post:
class: AppBundle\Admin\BlogPostAdmin
arguments: [~, AppBundle\Entity\BlogPost, ~]
tags:
- { name: sonata.admin, manager_type: orm, label: Blog post }
public: true
# Doctrine Extension listeners to handle behaviors
gedmo.listener.translatable:
class: Gedmo\Translatable\TranslatableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
#- [ setAnnotationReader, [ @annotation_reader ] ]
- [ setDefaultLocale, [ it ] ]
- [ setTranslationFallback, [ false ] ]
- [ setPersistDefaultLocaleTranslation, [ false ] ]
BlogPost.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Sonata\TranslationBundle\Model\Gedmo\AbstractPersonalTranslatable;
use Gedmo\Mapping\Annotation as Gedmo;
use Sonata\TranslationBundle\Model\Gedmo\TranslatableInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Sonata\TranslationBundle\Model\Gedmo\AbstractPersonalTranslation;
use Sonata\TranslationBundle\Traits\Gedmo\PersonalTranslatableTrait;
/**
* BlogPost
*
* @ORM\Table(name="blog_post")
* @ORM\Entity(repositoryClass="AppBundle\Repository\BlogPostRepository")
* @Gedmo\TranslationEntity(class="AppBundle\Entity\Translations\BlogPostTr")
* @ORM\HasLifecycleCallbacks
*/
class BlogPost implements TranslatableInterface
{
use PersonalTranslatableTrait;
/**
* Post locale
* Used locale to override Translation listener's locale
*
* @Gedmo\Locale
*/
protected $locale;
/**
* @ORM\ManyToOne(targetEntity="Category", inversedBy="blogPosts")
*/
private $category;
public function setCategory(Category $category)
{
$this->category = $category;
}
public function getCategory()
{
return $this->category;
}
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="title", type="string", length=255)
* @Gedmo\Translatable
*/
private $title;
/**
* @var string
*
* @ORM\Column(name="body", type="text")
* @Gedmo\Translatable
*/
private $body;
/**
* @var bool
*
* @ORM\Column(name="draft", type="boolean")
*/
private $draft = false;
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* @param string $title
*
* @return BlogPost
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set body
*
* @param string $body
*
* @return BlogPost
*/
public function setBody($body)
{
$this->body = $body;
return $this;
}
/**
* Get body
*
* @return string
*/
public function getBody()
{
return $this->body;
}
/**
* Set draft
*
* @param boolean $draft
*
* @return BlogPost
*/
public function setDraft($draft)
{
$this->draft = $draft;
return $this;
}
/**
* Get draft
*
* @return bool
*/
public function getDraft()
{
return $this->draft;
}
// TRANSLATION
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Translations\BlogPostTr", mappedBy="object", cascade={"persist", "remove"})
*/
protected $translations;
public function __construct()
{
$this->translations = new ArrayCollection;
}
public function getTranslations()
{
return $this->translations;
}
public function addTranslation(AbstractPersonalTranslation $t)
{
$this->translations->add($t);
$t->setObject($this);
}
public function removeTranslation(AbstractPersonalTranslation $t)
{
$this->translations->removeElement($t);
}
public function setTranslations($translations)
{
$this->translations = $translations;
}
/**
* Sets translatable locale
*
* @param string $locale
*/
public function setTranslatableLocale($locale)
{
$this->locale = $locale;
}
}
BlogPostTr.php
<?php
namespace AppBundle\Entity\Translations;
use Doctrine\ORM\Mapping as ORM;
use Sonata\TranslationBundle\Model\Gedmo\AbstractPersonalTranslation;
/**
* @ORM\Entity
* @ORM\Table(name="blog_post_translation",
* uniqueConstraints={@ORM\UniqueConstraint(name="lookup_unique_idx", columns={
* "locale", "object_id", "field"
* })}
*)
*/
class BlogPostTr extends AbstractPersonalTranslation
{
/**
* Convinient constructor
*
* @param string $locale
* @param string $field
* @param string $content
*/
public function __construct($locale = null, $field = null, $content = null)
{
$this->setLocale($locale);
$this->setField($field);
$this->setContent($content);
}
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\BlogPost", inversedBy="translations")
* @ORM\JoinColumn(name="object_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $object;
}
BlogPostAdmin.php
<?php
namespace AppBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
class BlogPostAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->tab('Post')
->with('Content', array('class' => 'col-md-9'))
->add('title', 'text')
// ->add('title', 'translatable_field', array(
// 'allow_extra_fields' => true,
// 'field' => 'title',
// 'personal_translation' => 'AppBundle\Entity\Translations\BlogPostTr',
// 'property_path' => 'translations',
// ))
->add('body', 'textarea')
->end()
->end()
->tab('Publishing options')
->with('Meta data', array('class' => 'col-md-3'))
->add('category', 'sonata_type_model', array(
'class' => 'AppBundle\Entity\Category',
'property' => 'name',
))
->end()
->end();
}
// protected function configureDatagridFilters(DatagridMapper $datagridMapper)
// {
// $datagridMapper->add('title');
// }
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('title');
}
public function toString($object)
{
return $object instanceof BlogPost
? $object->getTitle()
: 'Blog Post'; // shown in the breadcrumb on the create view
}
}
S'il vous plaît aider!