Skip to content

Commit 6c6247c

Browse files
Added parameter extractor
1 parent 8e32c5d commit 6c6247c

File tree

9 files changed

+185
-43
lines changed

9 files changed

+185
-43
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"require": {
2222
"php": "^8.2",
2323
"deeplcom/deepl-php": "^1.7",
24+
"dragon-code/support": "^6.13",
2425
"guzzlehttp/guzzle": "^7.8",
2526
"illuminate/config": "^10.0 || ^11.0",
2627
"illuminate/support": "^10.0 || ^11.0",

src/Concerns/Extractable.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace LaravelLang\Translator\Concerns;
6+
7+
use LaravelLang\Translator\Services\Parameters;
8+
9+
trait Extractable
10+
{
11+
/** @var array<Parameters> */
12+
protected array $parameters = [];
13+
14+
protected function extractParameters(iterable|string $text): array|string
15+
{
16+
if (is_string($text)) {
17+
$service = Parameters::make();
18+
19+
$result = $service->extract($text);
20+
21+
$this->setParameter($text, $service);
22+
23+
return $result;
24+
}
25+
26+
return collect($text)->map(
27+
fn (string $value) => $this->extractParameters($value)
28+
)->all();
29+
}
30+
31+
protected function injectParameters(iterable|string $hash, iterable|string $translated): array|string
32+
{
33+
if (is_string($hash)) {
34+
return $this->getParameter($hash)?->inject($translated) ?? $translated;
35+
}
36+
37+
return collect($translated)->map(
38+
fn (string $text, mixed $key) => $this->getParameter($hash[$key])?->inject($text) ?? $text
39+
)->all();
40+
}
41+
42+
protected function getParameter(string $key): ?Parameters
43+
{
44+
return $this->parameters[md5($key)] ?? null;
45+
}
46+
47+
protected function setParameter(string $key, Parameters $parameters): void
48+
{
49+
$this->parameters[md5($key)] = $parameters;
50+
}
51+
}

src/Integrations/Google.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ class Google extends Integration
142142

143143
public function __construct(
144144
protected GoogleTranslate $translator,
145-
protected bool|string $preserveParameters = true
146145
) {}
147146

148147
protected function request(iterable|string $text, Locale|string $to, Locale|string|null $from): Collection
@@ -155,7 +154,6 @@ protected function request(iterable|string $text, Locale|string $to, Locale|stri
155154
protected function translator(Locale|string $to, Locale|string|null $from): GoogleTranslate
156155
{
157156
return $this->translator
158-
->preserveParameters($this->preserveParameters)
159157
->setSource($this->locale($from))
160158
->setTarget($this->locale($to));
161159
}

src/Integrations/Integration.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66

77
use Illuminate\Support\Collection;
88
use LaravelLang\LocaleList\Locale;
9+
use LaravelLang\Translator\Concerns\Extractable;
910
use LaravelLang\Translator\Contracts\Translator;
1011

1112
abstract class Integration implements Translator
1213
{
14+
use Extractable;
15+
1316
protected array $map = [];
1417

1518
public static string $integration;
@@ -35,8 +38,8 @@ public function translate(
3538
}
3639

3740
return is_iterable($text)
38-
? $this->request($text, $to, $from)->all()
39-
: $this->request($text, $to, $from)->first();
41+
? $this->injectParameters($text, $this->request($this->extractParameters($text), $to, $from)->all())
42+
: $this->injectParameters($text, $this->request($this->extractParameters($text), $to, $from)->first());
4043
}
4144

4245
protected function locale(Locale|string|null $locale): ?string

src/Requests/GoogleTranslate.php

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,4 @@
66

77
use Stichoza\GoogleTranslate\GoogleTranslate as BaseTranslate;
88

9-
class GoogleTranslate extends BaseTranslate
10-
{
11-
/**
12-
* Extract replaceable keywords from string using the supplied pattern.
13-
*/
14-
protected function extractParameters(string $string): string
15-
{
16-
if (! $this->pattern) {
17-
return $string;
18-
}
19-
20-
return preg_replace_callback(
21-
$this->pattern,
22-
function ($matches) {
23-
static $index = -1;
24-
25-
++$index;
26-
27-
return '{' . $index . '}';
28-
},
29-
$string
30-
);
31-
}
32-
33-
/**
34-
* Inject the replacements back into the translated string.
35-
*
36-
* @param array<string> $replacements
37-
*/
38-
protected function injectParameters(string $string, array $replacements): string
39-
{
40-
return preg_replace_callback(
41-
'/\{(\d+)}/',
42-
fn ($matches) => $replacements[$matches[1]],
43-
$string
44-
);
45-
}
46-
}
9+
class GoogleTranslate extends BaseTranslate {}

src/Services/Parameters.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace LaravelLang\Translator\Services;
6+
7+
use DragonCode\Support\Concerns\Makeable;
8+
use DragonCode\Support\Facades\Helpers\Str;
9+
use LaravelLang\Config\Facades\Config;
10+
11+
class Parameters
12+
{
13+
use Makeable;
14+
15+
protected array $values = [];
16+
17+
public function extract(float|int|string $text): float|int|string
18+
{
19+
if (! $pattern = $this->pattern()) {
20+
return $text;
21+
}
22+
23+
if (is_numeric($text)) {
24+
return $text;
25+
}
26+
27+
return preg_replace_callback($pattern, function (array $matches) {
28+
$index = count($this->values);
29+
30+
$this->values[$index] = $matches[0];
31+
32+
return '{' . $index . '}';
33+
}, $text);
34+
}
35+
36+
public function inject(float|int|string $text): float|int|string
37+
{
38+
if (! $this->values || ! $this->pattern()) {
39+
return $text;
40+
}
41+
42+
if (is_numeric($text)) {
43+
return $text;
44+
}
45+
46+
return Str::replaceFormat($text, $this->values, '{%d}');
47+
}
48+
49+
public function extracted(): array
50+
{
51+
return $this->values;
52+
}
53+
54+
protected function pattern(): bool|string
55+
{
56+
$value = $this->preserveParameters();
57+
58+
if (is_string($value)) {
59+
return $value;
60+
}
61+
62+
if ($value === true) {
63+
return '/:(\w+)/';
64+
}
65+
66+
return false;
67+
}
68+
69+
protected function preserveParameters(): bool|string
70+
{
71+
return Config::shared()->translators->options->preserveParameters;
72+
}
73+
}

tests/Datasets/Strings.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
dataset('translatable-with-parameters', fn () => [
6+
[
7+
'Foo :attr1 bar :attr2: q :attr3 w :attr4 e :attr5.',
8+
'Foo {0} bar {1}: q {2} w {3} e {4}.',
9+
[':attr1', ':attr2', ':attr3', ':attr4', ':attr5'],
10+
],
11+
[
12+
'Foo :attr1',
13+
'Foo {0}',
14+
[':attr1'],
15+
],
16+
[
17+
'Foo bar',
18+
'Foo bar',
19+
[],
20+
],
21+
[
22+
'Foo 123',
23+
'Foo 123',
24+
[],
25+
],
26+
[
27+
1234,
28+
1234,
29+
[],
30+
],
31+
[
32+
1234.56,
33+
1234.56,
34+
[],
35+
],
36+
]);

tests/Helpers/Mocks.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function mockGoogleTranslator(array|string|null $text = null): void
2828
{
2929
$mock = mock(Google::$integration);
3030

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

3333
is_array($text)
3434
? $mock->shouldReceive('translate')->andReturn(...$text)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use LaravelLang\Translator\Services\Parameters;
6+
7+
test('extract', function (mixed $source, mixed $target, array $extracts) {
8+
$service = Parameters::make();
9+
10+
$extracted = $service->extract($source);
11+
12+
expect($extracted)->toBe($target);
13+
14+
expect($service->inject($extracted))->toBe($source);
15+
16+
expect($service->extracted())->toBe($extracts);
17+
})->with('translatable-with-parameters');

0 commit comments

Comments
 (0)