Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Gedmo Translation Form Bundle Laravel Package

andyhobbs/gedmo-translation-form-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle

    composer require andyhobbs/gedmo-translation-form-bundle
    

    Ensure StofDoctrineExtensionsBundle is also installed (required for Gedmo Translatable).

  2. Enable the Bundle Add to config/bundles.php:

    return [
        // ...
        AndyHobbs\GedmoTranslationFormBundle\AndyHobbsGedmoTranslationFormBundle::class => ['all' => true],
    ];
    
  3. Configure Translatable Entities Use the Gedmo\Mapping\Annotation\Translation annotation on your entity fields:

    use Gedmo\Mapping\Annotation as Gedmo;
    
    /**
     * @Gedmo\TranslationEntity(class="App\Entity\Translation")
     */
    class Product
    {
        /**
         * @Gedmo\Translatable
         */
        private $name;
    }
    
  4. First Use Case: Basic Form Integration In your form type, replace standard fields with GedmoTranslationsType:

    use AndyHobbs\GedmoTranslationFormBundle\Form\Type\GedmoTranslationsType;
    
    $builder->add('name', GedmoTranslationsType::class, [
        'fields' => ['name'], // Fields to translate
        'locales' => ['en', 'fr'], // Supported locales
    ]);
    

Implementation Patterns

Workflow: Handling Translations in Forms

  1. Entity Setup

    • Annotate fields with @Gedmo\Translatable.
    • Define a Translation entity (e.g., App\Entity\Translation) with @Gedmo\TranslationEntity.
  2. Form Type Integration

    • Replace single-field forms with GedmoTranslationsType for translatable fields.
    • Example for a multi-field entity:
      $builder->add('translatableFields', GedmoTranslationsType::class, [
          'fields' => ['title', 'description'],
          'locales' => ['en', 'es', 'de'],
          'options' => [
              'title' => ['label' => 'Product Title'],
              'description' => ['attr' => ['rows' => 5]],
          ],
      ]);
      
  3. Dynamic Locale Handling

    • Use getUser()->getLocale() or a service to fetch supported locales dynamically:
      $locales = $this->localeService->getSupportedLocales();
      $builder->add('name', GedmoTranslationsType::class, ['locales' => $locales]);
      
  4. Validation and Defaults

    • Set default values per locale:
      $builder->add('name', GedmoTranslationsType::class, [
          'defaults' => [
              'en' => 'Default English Name',
              'fr' => 'Nom par défaut',
          ],
      ]);
      
  5. Submitting and Persisting

    • The bundle auto-maps translations to the Translation entity. No extra logic needed for save().

Integration Tips

  • Symfony UX Turbo/Stimulus Use with Turbo to update translations via AJAX:

    // Stimulus controller to submit partial translations
    connect() {
        this.element.addEventListener('turbo:submit-end', (event) => {
            if (event.detail.success) {
                Turbo.visit(event.target.action);
            }
        });
    }
    
  • API Platform Extend GedmoTranslationsType to support API input:

    use ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException;
    
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('translations', CollectionType::class, [
            'entry_type' => TranslationType::class,
            'allow_add' => true,
            'allow_delete' => true,
            'prototype' => true,
            'by_reference' => false,
        ]);
    }
    
  • Doctrine Lifecycle Events Hook into prePersist/preUpdate to validate translations:

    public function prePersist(LifecycleEventArgs $args)
    {
        $entity = $args->getObject();
        if ($entity instanceof TranslatableEntity) {
            $this->validateTranslations($entity);
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Locale Mismatch

    • Issue: Submitting translations for unsupported locales throws InvalidArgumentException.
    • Fix: Always validate locales against Gedmo\Translatable\TranslatableListener:
      $supportedLocales = $this->container->getParameter('gedmo_translatable.locales');
      if (!in_array($locale, $supportedLocales)) {
          throw new \InvalidArgumentException("Locale '$locale' not supported.");
      }
      
  2. Missing Translation Entity

    • Issue: Forgetting to define a Translation entity causes ClassNotFoundException.
    • Fix: Ensure the entity exists and is annotated with @Gedmo\TranslationEntity.
  3. Form Data Binding

    • Issue: Nested translations may fail to bind if the input structure doesn’t match.
    • Fix: Use data_class to enforce proper hydration:
      $builder->add('name', GedmoTranslationsType::class, [
          'data_class' => Product::class,
      ]);
      
  4. Cascading Deletes

    • Issue: Deleting a translatable entity may not cascade to translations.
    • Fix: Add orphanRemoval: true to the OneToMany mapping in your Translation entity.

Debugging

  1. Check Form Data Dump submitted data to verify structure:

    $data = $request->request->all();
    dump($data['product']['translatableFields']);
    
  2. Enable Gedmo Logging Add to config/packages/doctrine.yaml:

    gedmo_listener:
        translatable: true
        log_enabled: true
    
  3. Query Logging Enable Doctrine debug mode to inspect generated queries:

    # config/packages/dev/doctrine.yaml
    doctrine:
        dbal:
            logging: true
            profiling: true
    

Extension Points

  1. Custom Translation Types Extend GedmoTranslationsType for domain-specific logic:

    class CustomTranslationsType extends GedmoTranslationsType
    {
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'custom_option' => true,
            ]);
        }
    }
    
  2. Override Default Templates Copy templates/form/fields.html.twig to templates/AndyHobbsGedmoTranslationForm/ to customize rendering.

  3. Add Validation Constraints Dynamically add constraints per locale:

    $builder->add('name', GedmoTranslationsType::class, [
        'validation' => [
            'en' => [new Length(['max' => 50])],
            'fr' => [new NotBlank()],
        ],
    ]);
    
  4. Event Subscribers Listen for form.pre_set_data to modify translations before binding:

    public function onPreSetData(FormEvent $event)
    {
        $data = $event->getData();
        if ($data instanceof Product) {
            $event->setData($this->hydrateTranslations($data));
        }
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui