Skip to content

Commit

Permalink
Added parameter extractor
Browse files Browse the repository at this point in the history
  • Loading branch information
andrey-helldar committed Jun 27, 2024
1 parent 8e32c5d commit 6c6247c
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 43 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"require": {
"php": "^8.2",
"deeplcom/deepl-php": "^1.7",
"dragon-code/support": "^6.13",
"guzzlehttp/guzzle": "^7.8",
"illuminate/config": "^10.0 || ^11.0",
"illuminate/support": "^10.0 || ^11.0",
Expand Down
51 changes: 51 additions & 0 deletions src/Concerns/Extractable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace LaravelLang\Translator\Concerns;

use LaravelLang\Translator\Services\Parameters;

trait Extractable
{
/** @var array<Parameters> */
protected array $parameters = [];

protected function extractParameters(iterable|string $text): array|string
{
if (is_string($text)) {
$service = Parameters::make();

$result = $service->extract($text);

$this->setParameter($text, $service);

return $result;
}

return collect($text)->map(
fn (string $value) => $this->extractParameters($value)
)->all();
}

protected function injectParameters(iterable|string $hash, iterable|string $translated): array|string
{
if (is_string($hash)) {
return $this->getParameter($hash)?->inject($translated) ?? $translated;
}

return collect($translated)->map(
fn (string $text, mixed $key) => $this->getParameter($hash[$key])?->inject($text) ?? $text
)->all();
}

protected function getParameter(string $key): ?Parameters
{
return $this->parameters[md5($key)] ?? null;
}

protected function setParameter(string $key, Parameters $parameters): void
{
$this->parameters[md5($key)] = $parameters;
}
}
2 changes: 0 additions & 2 deletions src/Integrations/Google.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ class Google extends Integration

public function __construct(
protected GoogleTranslate $translator,
protected bool|string $preserveParameters = true
) {}

protected function request(iterable|string $text, Locale|string $to, Locale|string|null $from): Collection
Expand All @@ -155,7 +154,6 @@ protected function request(iterable|string $text, Locale|string $to, Locale|stri
protected function translator(Locale|string $to, Locale|string|null $from): GoogleTranslate
{
return $this->translator
->preserveParameters($this->preserveParameters)
->setSource($this->locale($from))
->setTarget($this->locale($to));
}
Expand Down
7 changes: 5 additions & 2 deletions src/Integrations/Integration.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@

use Illuminate\Support\Collection;
use LaravelLang\LocaleList\Locale;
use LaravelLang\Translator\Concerns\Extractable;
use LaravelLang\Translator\Contracts\Translator;

abstract class Integration implements Translator
{
use Extractable;

protected array $map = [];

public static string $integration;
Expand All @@ -35,8 +38,8 @@ public function translate(
}

return is_iterable($text)
? $this->request($text, $to, $from)->all()
: $this->request($text, $to, $from)->first();
? $this->injectParameters($text, $this->request($this->extractParameters($text), $to, $from)->all())
: $this->injectParameters($text, $this->request($this->extractParameters($text), $to, $from)->first());
}

protected function locale(Locale|string|null $locale): ?string
Expand Down
39 changes: 1 addition & 38 deletions src/Requests/GoogleTranslate.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,4 @@

use Stichoza\GoogleTranslate\GoogleTranslate as BaseTranslate;

class GoogleTranslate extends BaseTranslate
{
/**
* Extract replaceable keywords from string using the supplied pattern.
*/
protected function extractParameters(string $string): string
{
if (! $this->pattern) {
return $string;
}

return preg_replace_callback(
$this->pattern,
function ($matches) {
static $index = -1;

++$index;

return '{' . $index . '}';
},
$string
);
}

/**
* Inject the replacements back into the translated string.
*
* @param array<string> $replacements
*/
protected function injectParameters(string $string, array $replacements): string
{
return preg_replace_callback(
'/\{(\d+)}/',
fn ($matches) => $replacements[$matches[1]],
$string
);
}
}
class GoogleTranslate extends BaseTranslate {}
73 changes: 73 additions & 0 deletions src/Services/Parameters.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

declare(strict_types=1);

namespace LaravelLang\Translator\Services;

use DragonCode\Support\Concerns\Makeable;
use DragonCode\Support\Facades\Helpers\Str;
use LaravelLang\Config\Facades\Config;

class Parameters
{
use Makeable;

protected array $values = [];

public function extract(float|int|string $text): float|int|string
{
if (! $pattern = $this->pattern()) {
return $text;
}

if (is_numeric($text)) {
return $text;
}

return preg_replace_callback($pattern, function (array $matches) {
$index = count($this->values);

$this->values[$index] = $matches[0];

return '{' . $index . '}';
}, $text);
}

public function inject(float|int|string $text): float|int|string
{
if (! $this->values || ! $this->pattern()) {
return $text;
}

if (is_numeric($text)) {
return $text;
}

return Str::replaceFormat($text, $this->values, '{%d}');
}

public function extracted(): array
{
return $this->values;
}

protected function pattern(): bool|string
{
$value = $this->preserveParameters();

if (is_string($value)) {
return $value;
}

if ($value === true) {
return '/:(\w+)/';
}

return false;
}

protected function preserveParameters(): bool|string
{
return Config::shared()->translators->options->preserveParameters;
}
}
36 changes: 36 additions & 0 deletions tests/Datasets/Strings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

dataset('translatable-with-parameters', fn () => [
[
'Foo :attr1 bar :attr2: q :attr3 w :attr4 e :attr5.',
'Foo {0} bar {1}: q {2} w {3} e {4}.',
[':attr1', ':attr2', ':attr3', ':attr4', ':attr5'],
],
[
'Foo :attr1',
'Foo {0}',
[':attr1'],
],
[
'Foo bar',
'Foo bar',
[],
],
[
'Foo 123',
'Foo 123',
[],
],
[
1234,
1234,
[],
],
[
1234.56,
1234.56,
[],
],
]);
2 changes: 1 addition & 1 deletion tests/Helpers/Mocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function mockGoogleTranslator(array|string|null $text = null): void
{
$mock = mock(Google::$integration);

$mock->shouldReceive('preserveParameters', 'setSource', 'setTarget')->andReturnSelf();
$mock->shouldReceive('setSource', 'setTarget')->andReturnSelf();

is_array($text)
? $mock->shouldReceive('translate')->andReturn(...$text)
Expand Down
17 changes: 17 additions & 0 deletions tests/Unit/Services/ParametersTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

use LaravelLang\Translator\Services\Parameters;

test('extract', function (mixed $source, mixed $target, array $extracts) {
$service = Parameters::make();

$extracted = $service->extract($source);

expect($extracted)->toBe($target);

expect($service->inject($extracted))->toBe($source);

expect($service->extracted())->toBe($extracts);
})->with('translatable-with-parameters');

0 comments on commit 6c6247c

Please sign in to comment.