Skip to content

Commit

Permalink
Fixed typing of incoming values
Browse files Browse the repository at this point in the history
  • Loading branch information
andrey-helldar committed Jun 28, 2024
1 parent 0e061ff commit a0fec5b
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 71 deletions.
4 changes: 2 additions & 2 deletions src/Contracts/Translator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ interface Translator
public function can(Locale|string $to): bool;

public function translate(
iterable|string $text,
iterable|string|int|float|bool|null $text,
Locale|string|null $to,
Locale|string|null $from = null
): array|string;
): array|string|int|float|bool|null;
}
12 changes: 6 additions & 6 deletions src/Facades/Translate.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@

use Illuminate\Support\Facades\Facade;
use LaravelLang\LocaleList\Locale;
use LaravelLang\Translator\Services\Translate as TranslateService;
use LaravelLang\Translator\Services\Translate as Service;

/**
* @method static array|string text(iterable|string $text, Locale|string $to, Locale|string|null $from = null)
* @method static array|string viaDeepl(iterable|string $text, Locale|string $to, Locale|string|null $from = null)
* @method static array|string viaGoogle(iterable|string $text, Locale|string $to, Locale|string|null $from = null)
* @method static array|string viaYandex(iterable|string $text, Locale|string $to, Locale|string|null $from = null)
* @method static array|string|int|float|bool|null text(iterable|string|int|float|bool|null $text, Locale|string $to, Locale|string|null $from = null)
* @method static array|string|int|float|bool|null viaDeepl(iterable|string|int|float|bool|null $text, Locale|string $to, Locale|string|null $from = null)
* @method static array|string|int|float|bool|null viaGoogle(iterable|string|int|float|bool|null $text, Locale|string $to, Locale|string|null $from = null)
* @method static array|string|int|float|bool|null viaYandex(iterable|string|int|float|bool|null $text, Locale|string $to, Locale|string|null $from = null)
*/
class Translate extends Facade
{
protected static function getFacadeAccessor(): string
{
return TranslateService::class;
return Service::class;
}
}
12 changes: 8 additions & 4 deletions src/Integrations/Integration.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ abstract class Integration implements Translator
{
use Extractable;

protected array $map = [];

public static string $integration;

protected array $map = [];

abstract protected function request(
array|string $text,
Locale|string $to,
Expand All @@ -29,10 +29,14 @@ public function can(Locale|string $to): bool
}

public function translate(
iterable|string $text,
iterable|string|int|float|bool|null $text,
Locale|string|null $to,
Locale|string|null $from = null
): array|string {
): array|string|int|float|bool|null {
if (! is_iterable($text) && ! is_string($text)) {
return $text;
}

if ($this->invalidLocale($to)) {
return is_string($text) ? $text : collect($text)->all();
}
Expand Down
45 changes: 24 additions & 21 deletions src/Services/Translate.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,25 @@

namespace LaravelLang\Translator\Services;

use Illuminate\Support\Str;
use LaravelLang\Config\Data\Shared\Translators\TranslatorData;
use LaravelLang\Config\Facades\Config;
use LaravelLang\LocaleList\Locale;
use LaravelLang\Translator\Contracts\Translator;
use LaravelLang\Translator\Integrations\Deepl;
use LaravelLang\Translator\Integrations\Google;
use LaravelLang\Translator\Integrations\Yandex;
use RuntimeException;

/**
* @method array|string|int|float|bool|null viaDeepl(iterable|string $text, Locale|string $to, Locale|string|null $from = null)
* @method array|string|int|float|bool|null viaGoogle(iterable|string $text, Locale|string $to, Locale|string|null $from = null)
* @method array|string|int|float|bool|null viaYandex(iterable|string $text, Locale|string $to, Locale|string|null $from = null)
*/
class Translate
{
public function text(iterable|string $text, Locale|string $to, Locale|string|null $from = null): array|string
{
public function text(
iterable|string|int|float|bool|null $text,
Locale|string $to,
Locale|string|null $from = null
): array|string|int|float|bool|null {
foreach ($this->translators() as $service) {
if ($translated = $this->translate($service->translator, $text, $to, $from)) {
return $translated;
Expand All @@ -25,36 +32,32 @@ public function text(iterable|string $text, Locale|string $to, Locale|string|nul
return $text;
}

public function viaDeepl(iterable|string $text, Locale|string $to, Locale|string|null $from = null): array|string
public function __call(string $name, array $arguments): array|string|int|float|bool|null
{
return $this->via(Deepl::class, $text, $to, $from);
}
if (Str::startsWith($name, 'via')) {
$provider = Str::of($name)->substr(3)->lower()->toString();

public function viaGoogle(iterable|string $text, Locale|string $to, Locale|string|null $from = null): array|string
{
return $this->via(Google::class, $text, $to, $from);
}
return $this->via($this->translators()[$provider]->translator, ...$arguments);
}

public function viaYandex(iterable|string $text, Locale|string $to, Locale|string|null $from = null): array|string
{
return $this->via(Yandex::class, $text, $to, $from);
throw new RuntimeException("Undefined method called `$name`.");
}

protected function via(
string $translator,
iterable|string $text,
iterable|string|int|float|bool|null $text,
Locale|string $to,
Locale|string|null $from
): array|string {
Locale|string|null $from = null
): array|string|int|float|bool|null {
return $this->translate($translator, $text, $to, $from) ?: $text;
}

protected function translate(
string $translator,
iterable|string $text,
iterable|string|int|float|bool|null $text,
Locale|string $to,
Locale|string|null $from
): array|string|null {
Locale|string|null $from = null
): array|string|int|float|bool|null {
$translator = $this->initialize($translator);

if ($translator->can($to)) {
Expand Down
9 changes: 9 additions & 0 deletions tests/Datasets/Strings.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,12 @@
[],
],
]);

dataset('translatable-mixed-values', fn () => [
['Foo', 'Foo'],
['', ''],
[' ', ' '],
[123, 123],
[123.45, 123.45],
[null, null],
]);
14 changes: 7 additions & 7 deletions tests/Helpers/Mocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,29 @@
use LaravelLang\Translator\Integrations\Yandex;
use Tests\Constants\Value;

function mockTranslators(array|string|null $text = null): void
function mockTranslators(array|string|int|float|null $text = null): void
{
mockDeeplTranslator($text);
mockGoogleTranslator($text);
mockYandexTranslator($text);
}

function mockDeeplTranslator(array|string|null $text = null): void
function mockDeeplTranslator(array|string|int|float|null $text = null): void
{
$mock = mock(Deepl::$integration);

$text ??= Value::Text1French;

$result = fn (?string $text) => new TextResult($text, 'fr');
$result = fn (string|int|float|null $text) => new TextResult((string) $text, 'fr');

$values = is_array($text) ? array_map(fn (string $value) => $result($value), $text) : $result($text);
$values = is_array($text) ? array_map(fn (string|int|float|null $value) => $result($value), $text) : $result($text);

$mock->shouldReceive('translateText')->andReturn($values);

mockTranslator(Deepl::class, $mock);
}

function mockGoogleTranslator(array|string|null $text = null): void
function mockGoogleTranslator(array|string|int|float|null $text = null): void
{
$mock = mock(Google::$integration);

Expand All @@ -45,13 +45,13 @@ function mockGoogleTranslator(array|string|null $text = null): void
mockTranslator(Google::class, $mock);
}

function mockYandexTranslator(array|string|null $text = null): void
function mockYandexTranslator(array|string|int|float|null $text = null): void
{
$mock = mock(Yandex::$integration);

$values = Arr::wrap($text ?? [Value::Text1French]);

$mock->shouldReceive('translate')->andReturn(array_map(fn (string $text) => [
$mock->shouldReceive('translate')->andReturn(array_map(fn (array|string $text) => [
'text' => $text,
'detectedLanguageCode' => Locale::French->value,
], $values));
Expand Down
59 changes: 28 additions & 31 deletions tests/Unit/Translate/FacadeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,31 @@

use LaravelLang\LocaleList\Locale;
use LaravelLang\Translator\Facades\Translate;
use Tests\Constants\Value;

test('translate', function () {
expect(Translate::text(Value::Text1English, Locale::French))->toBe(
Value::Text1French
);
});

test('cannot be translated', function () {
expect(Translate::text(Value::Text1English, 'qwerty'))->toBe(
Value::Text1English
);
});

test('via deepl', function () {
expect(Translate::viaDeepl(Value::Text1English, Locale::French))->toBe(
Value::Text1French
);
});

test('via google', function () {
expect(Translate::viaGoogle(Value::Text1English, Locale::French))->toBe(
Value::Text1French
);
});

test('via yandex', function () {
expect(Translate::viaYandex(Value::Text1English, Locale::French))->toBe(
Value::Text1French
);
});

test('translate', function (mixed $source, mixed $target) {
mockTranslators($target);

expect(Translate::text($source, Locale::French))->toBe($target);
})->with('translatable-mixed-values');

test('cannot be translated', function (mixed $source, mixed $target) {
expect(Translate::text($source, 'qwerty'))->toBe($target);
})->with('translatable-mixed-values');

test('via deepl', function (mixed $source, mixed $target) {
mockTranslators($target);

expect(Translate::viaDeepl($source, Locale::French))->toBe($target);
})->with('translatable-mixed-values');

test('via google', function (mixed $source, mixed $target) {
mockTranslators($target);

expect(Translate::viaGoogle($source, Locale::French))->toBe($target);
})->with('translatable-mixed-values');

test('via yandex', function (mixed $source, mixed $target) {
mockTranslators($target);

expect(Translate::viaYandex($source, Locale::French))->toBe($target);
})->with('translatable-mixed-values');

0 comments on commit a0fec5b

Please sign in to comment.