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

Entity Translate Bundle Laravel Package

austral/entity-translate-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the bundle via Composer:

    composer require austral/entity-translate-bundle
    

    Enable it in config/bundles.php:

    Austral\EntityTranslateBundle\EntityTranslateBundle::class => ['all' => true],
    
  2. Configure Translatable Entities Extend Austral\EntityBundle\Entity\AbstractEntity and implement Austral\EntityBundle\Interfaces\EntityInterface:

    use Austral\EntityBundle\Entity\AbstractEntity;
    use Austral\EntityBundle\Interfaces\EntityInterface;
    use Austral\EntityTranslateBundle\Interfaces\TranslatableInterface;
    
    class Product extends AbstractEntity implements EntityInterface, TranslatableInterface
    {
        // Your fields
    }
    
  3. Define Translatable Fields Use the Translate annotation or attribute (PHP 8+):

    use Austral\EntityTranslateBundle\Annotation\Translate;
    
    #[Translate]
    private ?string $name = null;
    
  4. First Use Case: Basic Translation Create a translated entity via the repository:

    $product = $productRepository->createTranslatedEntity(Product::class, 'en');
    $product->setName('Laptop');
    $productRepository->save($product);
    

Implementation Patterns

Workflow: Managing Translations

  1. Create/Update Translations Use the repository methods to handle translations:

    // Create a new translation for an existing entity
    $translatedEntity = $repository->createTranslation($entity, 'fr');
    $translatedEntity->setName('Ordinateur portable');
    $repository->save($translatedEntity);
    
    // Update an existing translation
    $frTranslation = $repository->findTranslation($entity, 'fr');
    $frTranslation->setDescription('Détails en français...');
    $repository->save($frTranslation);
    
  2. Fetching Translations Retrieve translations dynamically:

    // Get all translations for an entity
    $translations = $repository->getTranslations($entity);
    
    // Get a specific translation (e.g., fallback to 'en' if 'fr' doesn't exist)
    $translation = $repository->getTranslation($entity, 'fr', 'en');
    
  3. Form Integration Use Symfony Forms with translation-aware fields:

    $builder->add('name', TextType::class, [
        'attr' => ['data-translatable' => true],
        'translation_locale' => $request->getLocale(), // e.g., 'fr'
    ]);
    
  4. Doctrine Events Listen for translation-related events (e.g., prePersist, preUpdate):

    $entityManager->getEventManager()->addEventListener(
        TranslatableEvents::PRE_TRANSLATE,
        [$this, 'onPreTranslate']
    );
    

Integration Tips

  • Symfony Translation System Integrate with Symfony's Translator for dynamic locale switching:

    $this->translator->trans($entity->getTranslatedField('name'), [], null, 'fr');
    
  • API Responses Serialize translations in APIs using serializers:

    # config/serializer/Entity.Product.yaml
    Austral\EntityTranslateBundle\Serializer\TranslatableNormalizer:
        format: json
    
  • Validation Validate translations per locale:

    $validator->validate($entity, null, ['locale' => 'fr']);
    

Gotchas and Tips

Pitfalls

  1. Locale Fallback Logic

    • If a translation doesn’t exist for a requested locale, the bundle falls back to the default locale (configured in framework.default_locale). Ensure your fallback logic aligns with business requirements.
    • Fix: Override the fallback behavior in your repository:
      $translation = $repository->getTranslation($entity, 'es', null); // No fallback
      
  2. Circular References in Serialization

    • Translated entities may cause infinite loops during serialization if not handled.
    • Fix: Exclude circular references in your serializer configuration:
      attributes:
          ignore:
              - translations
      
  3. Doctrine Listener Conflicts

    • The HttpRequestService in DoctrineListener might interfere with existing listeners.
    • Fix: Disable it if unused:
      # config/packages/austral_entity_translate.yaml
      austral_entity_translate:
          doctrine_listener:
              http_request_service: false
      
  4. Annotation vs. Attribute

    • Older PHP versions (<8.0) require annotations (@Translate), while PHP 8+ supports attributes (#[Translate]).
    • Tip: Use attributes for new projects to avoid annotation parsing overhead.

Debugging

  • Missing Translations Check if the TranslatableInterface is implemented and fields are annotated/attributed correctly. Enable Doctrine debugging:

    doctrine:schema:update --dump-sql
    
  • Performance Issues Avoid loading all translations at once. Use DQL or QueryBuilder to fetch only needed locales:

    $qb->leftJoin('entity.translations', 't', 'WITH', 't.locale IN (:locales)')
       ->setParameter('locales', ['en', 'fr']);
    

Extension Points

  1. Custom Translation Storage Extend Austral\EntityTranslateBundle\Repository\TranslatableRepository to use a custom storage backend (e.g., Redis for caching).

  2. Translation Events Dispatch custom events for translation lifecycle:

    $dispatcher->dispatch(new TranslatableEvent($entity, 'fr', TranslatableEvents::POST_TRANSLATE));
    
  3. Dynamic Locale Detection Override locale detection in Austral\EntityTranslateBundle\Service\LocaleDetector:

    public function detectLocale(): string
    {
        return $this->requestStack->getCurrentRequest()->getPreferredLanguage();
    }
    
  4. Bulk Translation Updates Use batch processing for large-scale translations:

    $entityManager->getConnection()->beginTransaction();
    try {
        foreach ($entities as $entity) {
            $translation = $repository->createTranslation($entity, 'de');
            // Update fields...
            $repository->save($translation);
        }
        $entityManager->getConnection()->commit();
    } catch (\Exception $e) {
        $entityManager->getConnection()->rollBack();
    }
    

Configuration Quirks

  • Default Locale Ensure framework.default_locale in config/packages/framework.yaml matches your primary locale to avoid unexpected fallbacks.

  • Translation Field Naming The bundle assumes translated fields follow the pattern {field}__{locale} (e.g., name__en). Customize this in your entity mapping if needed:

    # config/doctrine/mapping/Product.yaml
    Austral\EntityTranslateBundle\Mapping\TranslatableDriver:
        translation_field_suffix: '_translated'
    
  • Symfony 6.4+ Compatibility The bundle requires Symfony 6.4 for full compatibility. Test thoroughly if using older versions.

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.
phpshko/laravel-livewire-depdrop
larasell-dev/larasell
calliostro/spotify-bundle
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer