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

Serializer Translation Bundle Laravel Package

avoo/serializer-translation-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package Add to composer.json:

    {
        "require": {
            "avoo/serializer-translation-bundle": "^0.1"
        }
    }
    

    Run composer update.

  2. Register the Bundle Add to config/bundles.php (Symfony 4+):

    return [
        // ...
        Avoo\SerializerTranslationBundle\AvooSerializerTranslationBundle::class => ['all' => true],
    ];
    

    For Symfony 3.x, add to AppKernel.php:

    new Avoo\SerializerTranslationBundle\AvooSerializerTranslationBundle(),
    
  3. Configure JMS Serializer Ensure jms/serializer-bundle is installed and configured in config/packages/jms_serializer.yaml:

    jms_serializer:
        metadata:
            directories:
                FOSUserBundle: ../../vendor/friendsofsymfony/user-bundle/Resources/config/serializer
                App: %kernel.project_dir%/config/serializer
    
  4. First Use Case: Translate a Property Annotate a DTO or entity property with @Serializer\SerializedName and @Serializer\Translation:

    use JMS\Serializer\Annotation as Serializer;
    
    class ProductDto
    {
        /**
         * @Serializer\SerializedName("name")
         * @Serializer\Translation("name", "product.name")
         */
        public $name;
    }
    

    Ensure translations exist in translations/messages.en.yaml:

    product:
        name: "Product Name"
    
  5. Serialize with Translation

    $serializer = $container->get('jms_serializer');
    $productDto = new ProductDto();
    $productDto->name = 'product_name_key'; // Key, not value
    
    $serialized = $serializer->serialize($productDto, 'json');
    // Output: {"name":"Product Name"}
    

Implementation Patterns

Common Workflows

1. Translating Dynamic Data

Use a translation service to fetch translations dynamically:

use Symfony\Contracts\Translation\TranslatorInterface;

class ProductDto
{
    /**
     * @Serializer\SerializedName("description")
     * @Serializer\Translation("description", service="translator", method="trans")
     */
    public $descriptionKey;

    public function __construct(TranslatorInterface $translator)
    {
        $this->translator = $translator;
    }

    public function getDescriptionKey()
    {
        return $this->descriptionKey;
    }
}

Configure in config/packages/jms_serializer.yaml:

jms_serializer:
    handlers:
        Avoo\SerializerTranslation\TranslationHandler:
            service: translator
            method: trans

2. Contextual Translations

Pass translation context (e.g., gender, pluralization):

/**
 * @Serializer\Translation("greeting", "greeting.hello", context={"gender": "male"})
 */
public $gender;

Translations file:

greeting:
    hello:
        male: "Hello Sir"
        female: "Hello Madam"

3. Nested Object Translation

Translate properties in nested objects:

class AddressDto
{
    /**
     * @Serializer\Translation("street", "address.street")
     */
    public $streetKey;
}

class UserDto
{
    /**
     * @Serializer\SerializedName("address")
     */
    public $address;
}

Serializer will automatically translate streetKey in the nested AddressDto.

4. Conditional Translation

Use a custom handler for conditional logic:

use Avoo\SerializerTranslation\TranslationHandlerInterface;

class ConditionalTranslationHandler implements TranslationHandlerInterface
{
    public function translate($value, array $context = [])
    {
        if ($value === 'special') {
            return 'Special Value';
        }
        return $value;
    }
}

Register in services.yaml:

services:
    App\Serializer\ConditionalTranslationHandler:
        tags: [jms_serializer.subscribing_handler]

5. API Response Translation

Translate API responses globally by extending the serializer context:

$context = [
    'translation_locale' => 'en',
    'translation_domain' => 'api',
];
$serializer->serialize($data, 'json', $context);

Integration Tips

Symfony Translation Integration

Leverage Symfony’s Translator component for consistency:

# config/packages/translation.yaml
framework:
    translator:
        paths: ['%kernel.project_dir%/translations']
        defaults:
            locale: '%locale%'

Custom Translation Providers

Extend functionality by creating a custom translation provider:

use Avoo\SerializerTranslation\TranslationProviderInterface;

class DatabaseTranslationProvider implements TranslationProviderInterface
{
    public function translate($key, array $context = [])
    {
        // Fetch from DB
        return $this->db->fetchTranslation($key, $context);
    }
}

Register in services.yaml:

services:
    App\Serializer\DatabaseTranslationProvider:
        tags: [avoo.serializer_translation.provider]

Testing Translations

Mock translations in tests:

$translator = $this->createMock(TranslatorInterface::class);
$translator->method('trans')->willReturn('Mocked Translation');

$handler = new TranslationHandler($translator);
$this->assertEquals('Mocked Translation', $handler->translate('key'));

Gotchas and Tips

Pitfalls

1. Translation Key vs. Value Confusion

  • Issue: Passing the translated value instead of the translation key to the serializer.
  • Fix: Always pass keys (e.g., "product.name"), not values (e.g., "Product Name").
  • Debug: Check if $serialized output matches expected translations.

2. Missing Translation Files

  • Issue: SerializerTranslationException if translation files are missing or misconfigured.
  • Fix:
    • Ensure translations/messages.{locale}.yaml exists.
    • Verify framework.translation.paths in config/packages/translation.yaml.
  • Debug: Run php bin/console debug:translation to list available translations.

3. Handler Registration Order

  • Issue: Custom handlers may not override default behavior if not registered correctly.
  • Fix: Use tags: [jms_serializer.subscribing_handler] with priority:
    tags:
        - { name: jms_serializer.subscribing_handler, priority: 255 }
    

4. Locale Mismatch

  • Issue: Translations not found due to incorrect locale.
  • Fix: Explicitly set the locale in the serializer context:
    $serializer->serialize($data, 'json', ['locale' => 'fr']);
    

5. Circular References

  • Issue: Infinite loops when translating nested objects with circular references.
  • Fix: Use @Serializer\MaxDepth to limit serialization depth:
    /**
     * @Serializer\MaxDepth(3)
     */
    class UserDto { ... }
    

Debugging Tips

Enable Serializer Debugging

Configure JMS Serializer to log metadata:

jms_serializer:
    metadata:
        debug: true

Check logs for generated metadata (e.g., app/log/dev.log).

Inspect Handler Execution

Temporarily log handler calls:

class TranslationHandler
{
    public function translate($value, array $context = [])
    {
        error_log("Translating: {$value}, Context: " . json_encode($context));
        return $this->translator->trans($value, $context);
    }
}

Validate Translation Keys

Use a regex to validate translation keys (e.g., ^[a-z]+\.[a-z]+$):

if (!preg_match('/^[a-z]+\.[a-z]+$/', $key)) {
    throw new \InvalidArgumentException("Invalid translation key: {$key}");
}

Extension Points

1. Custom Translation Providers

Implement TranslationProviderInterface for non-Symfony translation sources:

class ApiTranslationProvider implements TranslationProviderInterface
{
    public function translate($key, array $context = [])
    {
        return $this->httpClient->request('GET', "/api/translate?key={$key}")->getContent();
    }
}

Register with:

tags: [avoo.serializer_translation.provider]

2. Dynamic Translation Context

Modify context

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.
nasirkhan/laravel-sharekit
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony