Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doctrine extensions translatable not working in symfony 6.4 with orm 3.1 #2867

Closed
fecou opened this issue Sep 9, 2024 · 8 comments
Closed

Comments

@fecou
Copy link

fecou commented Sep 9, 2024

Environment

Symfony 6.4
Doctrine ORM 3.1

Package

"gedmo/doctrine-extensions": "^3.16",

$ composer show --latest gedmo/doctrine-extensions
name     : gedmo/doctrine-extensions
descrip. : Doctrine behavioral extensions
keywords : Blameable, behaviors, doctrine, extensions, gedmo, loggable, nestedset, odm, orm, sluggable, sortable, timestampable, translatable, tree, uploadable
versions : * v3.16.1
latest   : v3.16.1
type     : library
license  : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage : http://gediminasm.org/
source   : [git] https://github.com/doctrine-extensions/DoctrineExtensions.git e85560ed96f977b8c29428a99222cb2ef2f0e80d
dist     : [zip] https://api.github.com/repos/doctrine-extensions/DoctrineExtensions/zipball/e85560ed96f977b8c29428a99222cb2ef2f0e80d e85560ed96f977b8c29428a99222cb2ef2f0e80d
path     : /media/donnees/web/kreatys/prev-and-co/vendor/gedmo/doctrine-extensions
names    : gedmo/doctrine-extensions

support
email : [email protected]
issues : https://github.com/doctrine-extensions/DoctrineExtensions/issues
source : https://github.com/doctrine-extensions/DoctrineExtensions/tree/v3.16.1
wiki : https://github.com/Atlantic18/DoctrineExtensions/tree/main/doc

autoload
psr-4
Gedmo\ => src/

requires
behat/transliterator ^1.2
doctrine/collections ^1.2 || ^2.0
doctrine/common ^2.13 || ^3.0
doctrine/deprecations ^1.0
doctrine/event-manager ^1.2 || ^2.0
doctrine/persistence ^2.2 || ^3.0
php ^7.4 || ^8.0
psr/cache ^1 || ^2 || ^3
psr/clock ^1
symfony/cache ^5.4 || ^6.0 || ^7.0

requires (dev)
doctrine/annotations ^1.13 || ^2.0
doctrine/cache ^1.11 || ^2.0
doctrine/dbal ^3.2
doctrine/doctrine-bundle ^2.3
doctrine/mongodb-odm ^2.3
doctrine/orm ^2.14.0 || ^3.0
friendsofphp/php-cs-fixer ^3.14.0
nesbot/carbon ^2.71 || ^3.0
phpstan/phpstan ^1.11
phpstan/phpstan-doctrine ^1.4
phpstan/phpstan-phpunit ^1.4
phpunit/phpunit ^9.6
rector/rector ^1.1
symfony/console ^5.4 || ^6.0 || ^7.0
symfony/doctrine-bridge ^5.4 || ^6.0 || ^7.0
symfony/phpunit-bridge ^6.0 || ^7.0
symfony/uid ^5.4 || ^6.0 || ^7.0
symfony/yaml ^5.4 || ^6.0 || ^7.0

suggests
doctrine/mongodb-odm to use the extensions with the MongoDB ODM
doctrine/orm to use the extensions with the ORM

conflicts
doctrine/annotations <1.13 || >=3.0
doctrine/dbal <3.2 || >=4.0
doctrine/mongodb-odm <2.3 || >=3.0
doctrine/orm <2.14.0 || 2.16.0 || 2.16.1 || >=4.0

Doctrine packages

"doctrine/annotations": "^2.0",
"doctrine/dbal": "^3",
"doctrine/doctrine-bundle": "^2.12",
"doctrine/doctrine-migrations-bundle": "^3.3",
"doctrine/orm": "^3.1",

$ composer show --latest 'doctrine/*'
Direct dependencies required in composer.json:
doctrine/annotations                2.0.2  2.0.2  Docblock Annotations Parser
doctrine/dbal                       3.8.4  4.1.1  Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.
doctrine/doctrine-bundle            2.12.0 2.13.0 Symfony DoctrineBundle
doctrine/doctrine-fixtures-bundle   3.6.1  3.6.1  Symfony DoctrineFixturesBundle
doctrine/doctrine-migrations-bundle 3.3.0  3.3.1  Symfony DoctrineMigrationsBundle
doctrine/orm                        3.1.2  3.2.2  Object-Relational-Mapper for PHP

Transitive dependencies not required in composer.json:
doctrine/cache                      2.2.0  2.2.0  PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memca...
doctrine/collections                2.2.2  2.2.2  PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.
doctrine/common                     3.4.4  3.4.4  PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on...
doctrine/data-fixtures              1.7.0  1.7.0  Data Fixtures for all Doctrine Object Managers
doctrine/deprecations               1.1.3  1.1.3  A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or ...
doctrine/event-manager              2.0.0  2.0.1  The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.
doctrine/inflector                  2.0.10 2.0.10 PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and sin...
doctrine/instantiator               2.0.0  2.0.0  A small, lightweight utility to instantiate objects in PHP without invoking their constructors
doctrine/lexer                      3.0.1  3.0.1  PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.
doctrine/migrations                 3.7.4  3.8.1  PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for ver...
doctrine/persistence                3.3.2  3.3.3  The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object ma...
doctrine/sql-formatter              1.2.0  1.4.1  a PHP SQL highlighting library

PHP version

$ php -v
PHP 8.2.17 (cli) (built: Mar 22 2024 11:33:03) (NTS)

Subject

I installed doctrine extensions and doctrine annotations.
in config/doctrine.yaml :
mappings : translatable: type: attribute is_bundle: false prefix: Gedmo\Translatable\Entity dir: '%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Translatable/Entity' alias: GedmoTranslatable

I have a country entity :
`
...
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Translatable\Translatable;

#[ORM\Entity(repositoryClass: CountryRepository::class)]
class Country implements Translatable
{

#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;

#[Gedmo\Translatable]
#[ORM\Column(length: 255)]
private ?string $nom = null;

/**
 * @Gedmo\Locale
 * Used locale to override Translation listener`s locale
 * this is not a mapped field of entity metadata, just a simple property
 */
#[Gedmo\Locale]
private $locale;

...
public function setTranslatableLocale($locale)
{
$this->locale = $locale;
}
...
`

I have also a fixture
... $repository = $em->getRepository('Gedmo\\Translatable\\Entity\\Translation'); ... $repository->translate($country, 'nom', 'fr', 'Allemagne')
But if I do that, I get error : The translation listener could not be found

Also if I open a form switching locale in french. I write a name of the country in french. I save.
After I switch to english. I write a name of the country in english. I save.

I expect that when something to be written in the table ext_translations, but nothing is written. The attribute #[Gedmo\Translatable] is ignored. My fields with this attribute aren't translatable.

@ofourny
Copy link

ofourny commented Sep 19, 2024

So had the same problem : The translation listener could not be found. I found a fix, sorry if it's not the right explanation but it works for me for now.

I have
"php": ">=8.3", "doctrine/doctrine-bundle": "^2.13", "doctrine/orm": "^3.2.2"
it was working in 6.4, but at equals other packages not working in 7.0 and after.

So this is my original configuration,

    Gedmo\Translatable\TranslatableListener:
        calls:
            - [setTranslatableLocale, ['%locale%']]     # Set locale, typically the current request's locale
            - [setDefaultLocale, ['%locale%']]          # Set default locale, fallback to the default app locale
        tags:
            - { name: doctrine.event_subscriber, connection: default }

I tried different things as it is deprecated to declared events like that but from this doc it should still works. https://symfony.com/doc/7.0/doctrine/events.html

So I tried with the new way using AsDoctrineListener, and made a listener like this ;

<?php

namespace App\Listeners;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Events;
use Gedmo\Translatable\TranslatableListener;

#[AsDoctrineListener(event: Events::postLoad, priority: 0, connection: 'default')]
#[AsDoctrineListener(event: Events::postPersist, priority: 0, connection: 'default')]
#[AsDoctrineListener(event: Events::preFlush, priority: 0, connection: 'default')]
#[AsDoctrineListener(event: Events::onFlush, priority: 0, connection: 'default')]
#[AsDoctrineListener(event: Events::loadClassMetadata, priority: 0, connection: 'default')]

class WatbookTranslatableListener extends TranslatableListener
{

}

@mbabker
Copy link
Contributor

mbabker commented Sep 19, 2024

You don't need to subclass the listener, just update your config to match the updated documentation.

@ofourny
Copy link

ofourny commented Sep 19, 2024

Thanks I was looking for something like that, looked in the wrong place.

@fecou
Copy link
Author

fecou commented Sep 20, 2024

Thank you for your answers.
It works much better know. For example I can know make fixtures with translations.
But it still doesnt work in my edit form with a translatable field. When I look in the database, I have a new ext_translations, so it seems ok. But the language is "en_US" instead of "en".
When I assign the language, I assign "en_US" but in the route I only have "en".
Maybe it explains why if in my controller I put dd($request->getLocale()); it prints "en" instead of "en_US".
There is an inconsistency there that doesnt allow me to use the doctrine extension with translatable.
Any idea how to solve that ?

@fecou
Copy link
Author

fecou commented Sep 20, 2024

In services.yaml I have :

parameters:
locale: 'fr_FR' # gedmo translatable

and

gedmo.mapping.driver.attribute:
    class: Gedmo\Mapping\Driver\AttributeReader
# Gedmo Translatable Extension Listener (see https://github.com/doctrine-extensions/DoctrineExtensions/blob/main/doc/frameworks/symfony.md#registering-extension-listeners)
gedmo.listener.translatable:
    class: Gedmo\Translatable\TranslatableListener
    tags:
        - { name: doctrine.event_listener, event: 'postLoad' }
        - { name: doctrine.event_listener, event: 'postPersist' }
        - { name: doctrine.event_listener, event: 'preFlush' }
        - { name: doctrine.event_listener, event: 'onFlush' }
        - { name: doctrine.event_listener, event: 'loadClassMetadata' }
    calls:
        # Uncomment the below call if using attributes, and comment the call for the annotation reader
        - [ setAnnotationReader, [ '@gedmo.mapping.driver.attribute' ] ]
        # The `annotation_reader` service was deprecated in Symfony 6.4 and removed in Symfony 7.0
        # - [ setAnnotationReader, [ '@annotation_reader' ] ]
        # The Kernel's `locale` parameter is used to configure the default locale for the extension
        - [ setDefaultLocale, [ '%locale%' ] ]

In doctrine.yaml, I have :

doctrine:orm:mappings:
translatable:
type: attribute
alias: GedmoTranslatable
prefix: Gedmo\Translatable\Entity
dir: '%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Translatable/Entity'

And in translations.yaml, I have :

framework:
default_locale: fr_FR
enabled_locales: ['fr_FR', 'en_US']
translator:
default_path: '%kernel.project_dir%/translations'
fallbacks:
- fr_FR
providers:

@fecou
Copy link
Author

fecou commented Sep 20, 2024

What is really strange is that in my entry in ext_translations table I change "fr_FR" to "fr", matching in fact with the $request->getLocale(), twig stills serving the field in english. So it's as if symfony wouldnt translate and ignores ext_translations entries.

@fecou
Copy link
Author

fecou commented Oct 17, 2024

Reading the documentation again, at https://github.com/doctrine-extensions/DoctrineExtensions/blob/main/doc/frameworks/symfony.md#configuring-extensions-via-event-subscribers, I realize I didn't add the event listener.
So I have :
`<?php

namespace App\EventListener;

// see https://github.com/doctrine-extensions/DoctrineExtensions/blob/main/doc/frameworks/symfony.md#configuring-extensions-via-event-subscribers

use Gedmo\Translatable\TranslatableListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;

final class GedmoExtensionsEventSubscriber implements EventSubscriberInterface
{
public function __construct(
private TranslatableListener $translatableListener,
private ?AuthorizationCheckerInterface $authorizationChecker = null,
private ?TokenStorageInterface $tokenStorage = null,
) {}

public static function getSubscribedEvents(): array
{
    return [
        KernelEvents::REQUEST => [
            ['configureTranslatableListener'], // Must run after the locale is configured
        ],
    ];
}

/**
 * Configures the translatable listener using the request locale
 */
public function configureTranslatableListener(RequestEvent $event): void
{
    $this->translatableListener->setTranslatableLocale($event->getRequest()->getLocale());
}

}`
But adding this listener gives me this error :
Cannot autowire service "App\EventListener\GedmoExtensionsEventSubscriber": argument "$translatableListener" of method "__construct()" references class "Gedmo\Translatable\TranslatableListener" but no such service exists.
What is the problem there ? Thank you !

@fecou
Copy link
Author

fecou commented Oct 17, 2024

In services.yam, I added :
App\EventListener\GedmoExtensionsEventSubscriber: arguments: - '@gedmo.listener.translatable'

It works know !

@fecou fecou closed this as completed Oct 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants