Skip to content

Commit

Permalink
Add translator bridge
Browse files Browse the repository at this point in the history
This adds a forward compatibility gateway to translate legacy calls via
Contao domains in Symfony default translator.
  • Loading branch information
discordier committed Jul 17, 2023
1 parent a7a462a commit bd27b61
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 15 deletions.
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"symfony/event-dispatcher": "^5.4",
"symfony/event-dispatcher-contracts": "^1.1 || ^2.0",
"symfony/http-kernel": "^5.4",
"symfony/translation": "^5.4"
"symfony/translation": "^5.4",
"symfony/translation-contracts": "^2.3"
},
"require-dev": {
"contao-community-alliance/dependency-container": "^2.1",
Expand Down Expand Up @@ -66,6 +67,7 @@
},
"extra": {
"branch-alias": {
"dev-release/2.4.x": "2.4.0-dev",
"dev-master": "2.3.x-dev",
"dev-support/2.0.x": "2.0.x-dev",
"dev-support/2.1.x": "2.1.x-dev",
Expand Down
2 changes: 1 addition & 1 deletion src/AbstractTranslator.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ abstract class AbstractTranslator implements TranslatorInterface
public function translate($string, $domain = null, array $parameters = [], $locale = null)
{
$newString = $this->getValue($string, $domain, $locale);
assert(is_string($newString));
assert(is_string($newString), 'Expected ' . var_export($newString, true) . ' to be a string.');

if ($newString == $string) {
return $string;
Expand Down
24 changes: 11 additions & 13 deletions src/Contao/ContaoTranslatorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,45 +20,43 @@

namespace ContaoCommunityAlliance\Translator\Contao;

use ContaoCommunityAlliance\Translator\SymfonyTranslatorBridge;
use ContaoCommunityAlliance\Translator\TranslatorChain;
use ContaoCommunityAlliance\Translator\TranslatorInitializer;
use ContaoCommunityAlliance\Translator\TranslatorInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\Translation\TranslatorInterface as SymfonyTranslator;

/**
* This class create the contao translator service.
*/
class ContaoTranslatorFactory
{
/**
* The event dispatcher.
*
* @var EventDispatcherInterface
*/
protected $dispatcher;

/**
* Create a new instance.
*
* @param EventDispatcherInterface $dispatcher The event dispatcher to use.
*/
public function __construct(EventDispatcherInterface $dispatcher)
{
$this->dispatcher = $dispatcher;
public function __construct(
protected EventDispatcherInterface $dispatcher,
private SymfonyTranslator $translator
) {
}

/**
* Create the translator service.
*
* @return \ContaoCommunityAlliance\Translator\TranslatorInterface
* @return TranslatorInterface
*/
public function createService()
{
$translator = new TranslatorChain();

$translator->add(new LangArrayTranslator($this->dispatcher));

$initializer = new TranslatorInitializer($this->dispatcher);
$initializer->initialize($translator);
$translator->add(new SymfonyTranslatorBridge($this->translator));

return $initializer->initialize($translator);
return $translator;
}
}
1 change: 1 addition & 0 deletions src/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ services:
ContaoCommunityAlliance\Translator\Contao\ContaoTranslatorFactory:
arguments:
- '@event_dispatcher'
- '@translator'

cca.translator.contao_translator:
class: ContaoCommunityAlliance\Translator\TranslatorInterface
Expand Down
125 changes: 125 additions & 0 deletions src/SymfonyTranslatorBridge.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<?php

/**
* This file is part of contao-community-alliance/translator.
*
* (c) 2013-2023 Contao Community Alliance.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* This project is provided in good faith and hope to be usable by anyone.
*
* @package contao-community-alliance/translator
* @author Christian Schiffler <[email protected]>
* @copyright 2014-2023 Contao Community Alliance.
* @license https://github.com/contao-community-alliance/translator/blob/master/LICENSE LGPL-3.0
* @filesource
*/

declare(strict_types=1);

namespace ContaoCommunityAlliance\Translator;

use Symfony\Contracts\Translation\TranslatorInterface as SymfonyTranslator;

final class SymfonyTranslatorBridge implements TranslatorInterface
{
private SymfonyTranslator $translator;

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

public function translate($string, $domain = null, array $parameters = [], $locale = null): string
{
if (($string !== $transValue = $this->try($string, $parameters, $domain, $locale))) {
return $transValue;
}
if (null === $locale) {
return $string;
}

return $this->try($string, $parameters, $domain, null);
}

public function translatePluralized(
$string,
$number,
$domain = null,
array $parameters = [],
$locale = null
): string {
if (($string !== $transValue = $this->tryPluralized($string, $number, $parameters, $domain, $locale))) {
return $transValue;
}
if (null === $locale) {
return $string;
}

return $this->tryPluralized($string, $number, $parameters, $domain, null);
}

/**
* This tries to fetch the translation string, if there is no match, return the original string.
*
* If there is a match, it will check the parameters and try to interpolate, as long as the parameters are a list.
* If the parameters are an associative array, they will get passed to the symfony translator instead.
*
* @param array<string, string>|list<float|int|string> $parameters
*/
private function try(string $string, array $parameters, ?string $domain, ?string $locale): string
{
if (!empty($domain)) {
// FIXME: Do we really need to always add contao_ prefix?
$domain = 'contao_' . $domain;
}

// Check if we have an associative array.
$transParams = array_is_list($parameters) ? [] : $parameters;

if (($string === $transValue = $this->translator->trans($string, $transParams, $domain, $locale))) {
return $string;
}
if ([] === $transParams && [] !== $parameters) {
/** @var list<float|int|string> $parameters */
return vsprintf($transValue, $parameters);
}
return $transValue;
}

/**
* This tries to fetch the translation string, if there is no match, return the original string.
*
* If there is a match, it will check the parameters and try to interpolate, as long as the parameters are a list.
* If the parameters are an associative array, they will get passed to the symfony translator instead.
*
* @param array<string, string>|list<float|int|string> $parameters
*/
private function tryPluralized(
string $string,
int $count,
array $parameters,
?string $domain,
?string $locale
): string {
if (!empty($domain)) {
// FIXME: Do we really need to always add contao_ prefix?
$domain = 'contao_' . $domain;
}

// Check if we have an associative array.
$transParams = array_is_list($parameters) ? [] : $parameters;
$transParams['%count%'] = $count;

if (($string === $transValue = $this->translator->trans($string, $transParams, $domain, $locale))) {
return $string;
}
if (['%count%' => $count] === $transParams && [] !== $parameters) {
/** @var list<float|int|string> $parameters */
return vsprintf($transValue, $parameters);
}
return $transValue;
}
}

0 comments on commit bd27b61

Please sign in to comment.