avoo/serializer-translation
Installation:
composer require avoo/serializer-translation-bundle
Register the bundle in config/app.php (Laravel) or AppKernel.php (Symfony):
// Laravel (Service Provider)
$this->mergeConfigFrom(__DIR__.'/avoo-serializer-translation.php', 'avoo.serializer_translation');
Configure Metadata Cache (in config/avoo-serializer-translation.php):
'metadata' => [
'cache' => 'file',
'file_cache' => [
'dir' => storage_path('framework/cache/avoo'),
],
],
First Use Case: Translate a property in an entity using annotations:
use Avoo\SerializerTranslation\Configuration\Annotation as AvooSerializer;
class User {
/**
* @AvooSerializer\Translate()
*/
public $name;
}
Add translation key to resources/lang/en/messages.php:
return [
'user.name' => 'Hello, %name%',
];
Serialize with Translation:
$serializer = $this->container->get('jms_serializer');
$data = $serializer->serialize($user, 'json');
Property-Level Translation: Use annotations/YAML/XML to mark properties for translation:
# config/serializer/User.yaml
App\Entity\User:
properties:
bio:
expose: true
translate: true
parameters:
"%user%" : "expr(object.getFullName())"
Dynamic Locale Handling: Override locale per-serialization:
$serializer->serialize($user, 'json', [
'translation_locale' => 'fr',
]);
Nested Object Translation: Apply translation to nested entities via metadata:
<class name="App\Entity\Post">
<property name="author" type="App\Entity\User">
<a:translate />
</property>
</class>
Integration with Laravel: Bind the serializer to Laravel’s container:
$this->app->bind('jms_serializer', function ($app) {
$serializer = SerializerBuilder::create()
->addMetadataDir(__DIR__.'/config/serializer')
->build();
return $serializer;
});
Translation Domains:
Use custom domains for translations (e.g., validation, admin):
/**
* @AvooSerializer\Translate(domain="admin")
*/
public $role;
'metadata' => ['cache' => 'file', 'file_cache' => ['dir' => storage_path('cache/avoo')]],
expr() for dynamic values:
translate:
parameters:
"%date%" : "expr(service('date.formatter').format(object.getCreatedAt()))"
config/app.php:
'fallback_locales' => ['en', 'fr'],
Metadata Cache Invalidation: Clear cache after adding new annotations/metadata:
php artisan cache:clear
php artisan config:clear
Or manually delete storage/framework/cache/avoo/.
Locale Mismatches: Ensure translation keys match the domain/locale specified in metadata. Example:
# Wrong: Key not found in 'admin' domain
@AvooSerializer\Translate(domain="admin")
public $name; // Missing 'admin.name' in translations
Circular References:
Avoid translating properties in circularly referenced entities (e.g., User->posts->author->user). Use @MaxDepth in JMS Serializer:
<class name="App\Entity\User" max-depth="2">
<property name="posts" type="App\Entity\Post">
<a:translate max-depth="1" />
</property>
</class>
Annotation vs. XML/YAML: Annotations are parsed at runtime and may slow down serialization. Prefer XML/YAML for production.
Parameter Syntax:
Incorrect expr() syntax breaks serialization:
# Wrong: Missing quotes around service call
parameters:
"%user%" : expr(service('user.repository').find(object.getId()))
Enable Metadata Debugging:
$serializer->getMetadataFactory()->setCache(new \Metadata\Cache\ArrayCache());
Inspect metadata with:
$metadata = $serializer->getMetadataFactory()->getMetadataForClass(get_class($user));
dd($metadata->propertyMetadata);
Translation Key Lookup: Use Laravel’s translation helper to verify keys:
__('user.name', ['%name%' => 'John']);
Serialization Errors: Wrap serialization in a try-catch to log errors:
try {
$serializer->serialize($user, 'json');
} catch (\Exception $e) {
\Log::error('Serialization failed: ' . $e->getMessage());
}
Custom Parameter Handlers:
Extend Avoo\SerializerTranslation\Parameter\ParameterHandlerInterface to support custom expr() functions:
class CustomParameterHandler implements ParameterHandlerInterface {
public function handle($value, $parameter, $object) {
return strtoupper($value);
}
}
Register in config:
'parameter_handlers' => [
'custom' => CustomParameterHandler::class,
],
Dynamic Domains: Override domain per-serialization via context:
$serializer->serialize($user, 'json', [
'translation_domain' => 'admin',
]);
Fallback Translations:
Implement a custom Translator service to handle missing keys:
$translator = new CustomTranslator($loader, $fallback);
$serializer->setTranslator($translator);
How can I help you explore Laravel packages today?