Installation Add the package via Composer:
composer require avris/stringer-symfony
Ensure Avris\Stringer\Symfony\StringerBundle is enabled in config/bundles.php:
return [
// ...
Avris\Stringer\Symfony\StringerBundle::class => ['all' => true],
];
Configuration Publish the default config (optional):
php bin/console config:dump-reference AvrisStringerBundle
Override defaults in config/packages/avris_stringer.yaml:
avris_stringer:
api_key: '%env(STRINGER_API_KEY)%'
default_locale: 'en_US'
enabled: true
First Use Case
Inject the StringerClient service and use it in a controller:
use Avris\Stringer\Symfony\Client\StringerClient;
class TranslationController extends AbstractController
{
public function __construct(private StringerClient $stringer)
{
}
public function translate(string $text, string $locale): string
{
return $this->stringer->translate($text, $locale);
}
}
Translation Integration
Use the StringerClient in services or controllers:
$translated = $this->stringer->translate(
'Hello {name}!', // Source text
'en_US', // Source locale
['name' => 'John'] // Variables
);
Twig Integration Extend Twig with a custom extension:
// src/Twig/StringerExtension.php
class StringerExtension extends \Twig\Extension\AbstractExtension
{
public function __construct(private StringerClient $stringer) {}
public function getFunctions(): array
{
return [
new \Twig\TwigFunction('translate', [$this, 'translate']),
];
}
public function translate(string $text, string $locale, array $vars = []): string
{
return $this->stringer->translate($text, $locale, $vars);
}
}
Register the extension in services.yaml:
services:
App\Twig\StringerExtension:
tags: ['twig.extension']
Event Listeners
Hook into StringerEvents (e.g., TranslationFailedEvent) for logging/retries:
use Avris\Stringer\Symfony\Event\TranslationFailedEvent;
class StringerListener
{
public function onTranslationFailed(TranslationFailedEvent $event)
{
// Log or retry logic
}
}
Register in services.yaml:
services:
App\EventListener\StringerListener:
tags:
- { name: 'kernel.event_listener', event: 'stringer.translation_failed', method: 'onTranslationFailed' }
Caching Layer Cache translations using Symfony’s cache system:
use Symfony\Contracts\Cache\CacheInterface;
class CachedStringerClient
{
public function __construct(
private StringerClient $client,
private CacheInterface $cache
) {}
public function translate(string $text, string $locale, array $vars = []): string
{
$cacheKey = md5($text . $locale . json_encode($vars));
return $this->cache->get($cacheKey, function () use ($text, $locale, $vars) {
return $this->client->translate($text, $locale, $vars);
});
}
}
API Key Management
api_key in config violates security best practices.%env() in avris_stringer.yaml:
api_key: '%env(STRINGER_API_KEY)%'
.env file permissions (chmod 600 .env).Locale Fallbacks
config/packages/avris_stringer.yaml:
locales:
en_US:
fallback: en_GB
en_GB:
fallback: en_US
Rate Limiting
use Symfony\Component\HttpClient\RetryableHttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;
$client = new RetryableHttpClient(
HttpClientInterface::create(),
[
'max_retries' => 3,
'delay' => 1000, // ms
'multiplier' => 2,
'max_delay' => 5000,
]
);
Variable Placeholders
{name} vs. {{name}}) may cause parsing errors.StringerClient::escapeVariables() for dynamic content:
$safeText = $this->stringer->escapeVariables($userInput);
Enable Verbose Logging
Add to config/packages/monolog.yaml:
handlers:
stringer:
type: stream
path: "%kernel.logs_dir%/stringer.log"
level: debug
channels: ["stringer"]
Then enable the channel in StringerBundle config:
logging:
channel: "stringer"
HTTP Client Debugging
Use Symfony’s HttpClient debug mode:
$client = HttpClient::create([
'debug' => true,
]);
Custom Translator
Extend StringerClient to add pre/post-processing:
class CustomStringerClient extends StringerClient
{
public function translate(string $text, string $locale, array $vars = []): string
{
$text = $this->preProcess($text); // Add custom logic
$result = parent::translate($text, $locale, $vars);
return $this->postProcess($result);
}
}
Event Dispatching
Extend StringerEvents for custom workflows:
use Avris\Stringer\Symfony\Event\TranslationEvent;
$event = new TranslationEvent($text, $locale, $vars);
$this->eventDispatcher->dispatch($event, StringerEvents::TRANSLATE);
if ($event->isPropagationStopped()) {
return $event->getResult();
}
Batch Processing
Use StringerClient::translateBatch() for bulk translations:
$results = $this->stringer->translateBatch([
['text' => 'Hello', 'locale' => 'en_US'],
['text' => 'Hola', 'locale' => 'es_ES'],
]);
How can I help you explore Laravel packages today?