-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e720b6b
commit 9dd4360
Showing
9 changed files
with
230 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atoolo\Translator\Adapter; | ||
|
||
use Atoolo\Translator\Dto\TranslationParameter; | ||
|
||
abstract class AbstractAdapter | ||
{ | ||
/** | ||
* @param array<string> $text | ||
* @return array<string> | ||
*/ | ||
abstract public function translate(array $text, TranslationParameter $parameter): array; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atoolo\Translator\Adapter; | ||
|
||
use Atoolo\Translator\Dto\Format; | ||
use Atoolo\Translator\Dto\TranslationParameter; | ||
use DeepL\DeepLException; | ||
|
||
class DeeplAdapter extends AbstractAdapter | ||
{ | ||
private \DeepL\Translator $translator; | ||
|
||
/** | ||
* @throws DeepLException | ||
*/ | ||
public function __construct(string $authKey) | ||
{ | ||
$this->translator = new \DeepL\Translator($authKey); | ||
} | ||
|
||
/** | ||
* @param array<string> $text | ||
* @return array<string> | ||
* @throws DeepLException | ||
*/ | ||
public function translate(array $text, TranslationParameter $parameter): array | ||
{ | ||
$options = []; | ||
if ($parameter->format === Format::HTML) { | ||
$options['tagHandling'] = 'html'; | ||
} | ||
return $this->translator->translateText($text, $parameter->sourceLang, $parameter->targetLang, $options); | ||
Check failure on line 34 in src/Adapter/DeeplAdapter.php GitHub Actions / verify / Composer Verify (PHP 8.2)
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atoolo\Translator\Dto; | ||
|
||
enum Format | ||
{ | ||
case TEXT; | ||
case HTML; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atoolo\Translator\Dto; | ||
|
||
class TranslationParameter | ||
{ | ||
public function __construct( | ||
public string $sourceLang, | ||
public string $targetLang, | ||
public Format $format, | ||
) | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atoolo\Translator\Service; | ||
|
||
use Atoolo\Translator\Dto\TranslationParameter; | ||
|
||
class TextHasher | ||
{ | ||
public function hash(string $text, TranslationParameter $parameter): string | ||
{ | ||
return $parameter->sourceLang . '->' . $parameter->targetLang . ':' . hash('sha256', $text); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atoolo\Translator\Service; | ||
|
||
use Atoolo\Translator\Adapter\AbstractAdapter; | ||
use Atoolo\Translator\Dto\TranslationParameter; | ||
use Psr\Cache\InvalidArgumentException; | ||
use Symfony\Contracts\Cache\CacheInterface; | ||
|
||
class Translator | ||
{ | ||
public function __construct( | ||
private readonly AbstractAdapter $adapter, | ||
private readonly CacheInterface $translationCache, | ||
private readonly TextHasher $textHasher, | ||
) | ||
{ | ||
} | ||
|
||
/** | ||
* @param array<string> $text | ||
* @return array<string> | ||
* @throws InvalidArgumentException | ||
*/ | ||
public function translate(array $text, TranslationParameter $parameter): array | ||
{ | ||
$hashMapping = []; | ||
foreach ($text as $value) { | ||
$hash = $this->textHasher->hash($value, $parameter); | ||
$hashMapping[$hash] = $this->translationCache->get($hash, function () { | ||
return null; | ||
}); | ||
} | ||
|
||
$toTranslate = []; | ||
foreach ($hashMapping as $hash => $translation) { | ||
if ($translation === null) { | ||
$toTranslate[$hash] = $text[$hash]; | ||
} | ||
} | ||
|
||
if (empty($toTranslate)) { | ||
return array_values($hashMapping); | ||
Check failure on line 45 in src/Service/Translator.php GitHub Actions / verify / Composer Verify (PHP 8.2)
|
||
} | ||
|
||
$adapterTranslated = $this->adapter->translate($toTranslate, $parameter); | ||
|
||
$position = 0; | ||
foreach ($hashMapping as $hash => $translation) { | ||
if ($translation === null) { | ||
$hashMapping[$hash] = $adapterTranslated[$position]; | ||
$this->translationCache->get($hash, fn() => $hashMapping[$hash]); | ||
$position++; | ||
} | ||
} | ||
|
||
return array_values($hashMapping); | ||
Check failure on line 59 in src/Service/Translator.php GitHub Actions / verify / Composer Verify (PHP 8.2)
|
||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atoolo\Translator\Test\Service; | ||
|
||
use Atoolo\Translator\Adapter\AbstractAdapter; | ||
use Atoolo\Translator\Dto\Format; | ||
use Atoolo\Translator\Dto\TranslationParameter; | ||
use Atoolo\Translator\Service\TextHasher; | ||
use Atoolo\Translator\Service\Translator; | ||
use PHPUnit\Framework\Attributes\CoversClass; | ||
use PHPUnit\Framework\MockObject\Exception; | ||
use PHPUnit\Framework\TestCase; | ||
use Psr\Cache\InvalidArgumentException; | ||
use Symfony\Contracts\Cache\CacheInterface; | ||
|
||
#[CoversClass(Translator::class)] | ||
class TranslatorTest extends TestCase | ||
{ | ||
|
||
/** | ||
* @throws Exception | ||
* @throws InvalidArgumentException | ||
*/ | ||
public function testTranslate(): void | ||
{ | ||
$adapter = $this->createMock(AbstractAdapter::class); | ||
$cache = $this->createMock(CacheInterface::class); | ||
$textHasher = $this->createMock(TextHasher::class); | ||
$textHasher->method('hash')->willReturnCallback(fn (string $text, TranslationParameter $parameter) => $text); | ||
|
||
$parameter = new TranslationParameter('en', 'de', Format::TEXT); | ||
|
||
$cacheValues = [ | ||
$textHasher->hash('computer', $parameter) => 'Computer', | ||
$textHasher->hash('water', $parameter) => 'Wasser', | ||
$textHasher->hash('book', $parameter) => 'Buch', | ||
]; | ||
|
||
$cache->method('get')->willReturnCallback(function (string $key) use ($cacheValues) { | ||
return $cacheValues[$key]; | ||
}); | ||
|
||
$adapter->method('translate')->willReturn([ | ||
'Apfel', | ||
'Fahrrad', | ||
'Himmel', | ||
'Telefon', | ||
]); | ||
|
||
$translator = new Translator($adapter, $cache, $textHasher); | ||
|
||
|
||
$translation = $translator->translate([ | ||
'apple', | ||
'computer', | ||
'bicycle', | ||
'sky', | ||
'water', | ||
'book', | ||
'telephone', | ||
], $parameter); | ||
|
||
$expected = ['Apfel', 'Computer', 'Fahrrad', 'Himmel', 'Wasser', 'Buch', 'Telefon']; | ||
|
||
$this->assertEquals($expected, $translation, 'Unexpected translation'); | ||
} | ||
} |