diff --git a/composer.json b/composer.json
index 083d29f..656f5ab 100644
--- a/composer.json
+++ b/composer.json
@@ -23,6 +23,7 @@
"deeplcom/deepl-php": "^1.7",
"guzzlehttp/guzzle": "^7.8",
"illuminate/support": "^10.0 || ^11.0",
+ "laravel-lang/config": "^1.0@dev",
"laravel-lang/locale-list": "^1.4",
"stichoza/google-translate-php": "^5.1"
},
diff --git a/phpunit.xml b/phpunit.xml
index d5e0876..1f62eb0 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -19,5 +19,14 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/Contracts/Translator.php b/src/Contracts/Translator.php
index 8383007..9ac056f 100644
--- a/src/Contracts/Translator.php
+++ b/src/Contracts/Translator.php
@@ -10,5 +10,9 @@ interface Translator
{
public function can(Locale|string $to): bool;
- public function translate(array|string $text, Locale|string $to, Locale|string|null $from = null): array|string;
+ public function translate(
+ iterable|string $text,
+ Locale|string|null $to,
+ Locale|string|null $from = null
+ ): array|string;
}
diff --git a/src/Integrations/Deepl.php b/src/Integrations/Deepl.php
index b165292..bd750c8 100644
--- a/src/Integrations/Deepl.php
+++ b/src/Integrations/Deepl.php
@@ -10,6 +10,8 @@
class Deepl extends Integration
{
+ public static string $integration = DeeplTranslator::class;
+
protected array $map = [
Locale::French->value => 'fr',
];
@@ -20,6 +22,6 @@ public function __construct(
protected function request(iterable|string $text, Locale|string $to, Locale|string|null $from): Collection
{
- return collect($this->translator->translateText($text, $this->lang($from), $this->lang($to)));
+ return collect($this->translator->translateText($text, $this->locale($from), $this->locale($to)));
}
}
diff --git a/src/Integrations/Google.php b/src/Integrations/Google.php
index 0a74d65..312b516 100644
--- a/src/Integrations/Google.php
+++ b/src/Integrations/Google.php
@@ -10,13 +10,15 @@
class Google extends Integration
{
+ public static string $integration = GoogleTranslate::class;
+
protected array $map = [
Locale::French->value => 'fr',
];
public function __construct(
protected GoogleTranslate $translator,
- protected string|true $regex = true
+ protected string|bool $regex = true
) {}
protected function request(iterable|string $text, Locale|string $to, Locale|string|null $from): Collection
@@ -30,7 +32,7 @@ protected function translator(Locale|string $to, Locale|string|null $from): Goog
{
return $this->translator
->preserveParameters($this->regex)
- ->setSource($this->lang($from))
- ->setTarget($this->lang($to));
+ ->setSource($this->locale($from))
+ ->setTarget($this->locale($to));
}
}
diff --git a/src/Integrations/Integration.php b/src/Integrations/Integration.php
index 367dae8..132c100 100644
--- a/src/Integrations/Integration.php
+++ b/src/Integrations/Integration.php
@@ -10,6 +10,8 @@
abstract class Integration implements Translator
{
+ public static string $integration;
+
protected array $map = [];
abstract protected function request(
@@ -20,35 +22,44 @@ abstract protected function request(
public function can(Locale|string $to): bool
{
- return $this->lang($to) !== null;
+ return $this->locale($to) !== null;
}
public function translate(
- array|string $text,
- Locale|string $to,
+ iterable|string $text,
+ Locale|string|null $to,
Locale|string|null $from = null
): array|string {
- return is_array($text)
+ if ($this->invalidLocale($to)) {
+ return is_string($text) ? $text : collect($text)->all();
+ }
+
+ return is_iterable($text)
? $this->request($text, $to, $from)->all()
: $this->request($text, $to, $from)->first();
}
- protected function lang(Locale|string|null $lang): ?string
+ protected function locale(Locale|string|null $locale): ?string
{
- $lang = $lang?->value ?? $lang;
+ $locale = $locale?->value ?? $locale;
- if (empty($lang)) {
+ if (empty($locale)) {
return null;
}
- if ($value = $this->map[$lang] ?? false) {
+ if ($value = $this->map[$locale] ?? false) {
return $value;
}
- if (in_array($lang, $this->map, true)) {
- return $lang;
+ if (in_array($locale, $this->map, true)) {
+ return $locale;
}
return null;
}
+
+ protected function invalidLocale(Locale|string|null $locale): bool
+ {
+ return ! $this->locale($locale);
+ }
}
diff --git a/src/Integrations/Yandex.php b/src/Integrations/Yandex.php
index 5378a96..5e942e3 100644
--- a/src/Integrations/Yandex.php
+++ b/src/Integrations/Yandex.php
@@ -10,6 +10,8 @@
class Yandex extends Integration
{
+ public static string $integration = YandexCloud::class;
+
protected array $map = [
Locale::French->value => 'fr',
];
@@ -20,6 +22,6 @@ public function __construct(
protected function request(iterable|string $text, Locale|string $to, Locale|string|null $from): Collection
{
- return collect($this->translator->translate($text, $this->lang($to), $this->lang($from)));
+ return collect($this->translator->translate($text, $this->locale($to), $this->locale($from)));
}
}
diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php
index 66f3a7d..849540c 100644
--- a/src/ServiceProvider.php
+++ b/src/ServiceProvider.php
@@ -4,39 +4,32 @@
namespace LaravelLang\Translator;
-use DeepL\Translator;
-use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
-use LaravelLang\Translator\Integrations\Deepl;
-use LaravelLang\Translator\Integrations\Google;
-use LaravelLang\Translator\Integrations\Yandex;
-use LaravelLang\Translator\Requests\YandexCloud;
-use Stichoza\GoogleTranslate\GoogleTranslate;
+use LaravelLang\Config\Data\Shared\TranslatorData;
+use LaravelLang\Config\Facades\Config;
+use LaravelLang\Translator\Contracts\Translator;
class ServiceProvider extends BaseServiceProvider
{
public function boot(): void
{
- $this->app->singleton(Deepl::class, function (Application $app) {
- return new Deepl(
- translator: new Translator($app['config']->get('services.deepl.key')),
- );
- });
+ foreach ($this->translators() as $config) {
+ $this->bootTranslator($config->translator, $config->credentials);
+ }
+ }
- $this->app->singleton(Google::class, function (Application $app) {
- return new Google(
- translator: new GoogleTranslate(),
- regex : $app['config']->get('services.google_translate.regex_parameters') ?: true,
- );
- });
+ protected function bootTranslator(Translator|string $translator, array $credentials): void
+ {
+ $this->app->singleton($translator, fn () => new $translator(
+ new $translator::$integration(...$credentials)
+ ));
+ }
- $this->app->singleton(Yandex::class, function (Application $app) {
- return new Yandex(
- new YandexCloud(
- key : $app['config']->get('services.yandex_translate.key'),
- folderId: $app['config']->get('services.yandex_translate.folder_id'),
- )
- );
- });
+ /**
+ * @return array
+ */
+ protected function translators(): array
+ {
+ return Config::shared()->translators->enabled;
}
}
diff --git a/src/Services/Translate.php b/src/Services/Translate.php
index bb06988..2ac18cd 100644
--- a/src/Services/Translate.php
+++ b/src/Services/Translate.php
@@ -4,6 +4,8 @@
namespace LaravelLang\Translator\Services;
+use LaravelLang\Config\Data\Shared\TranslatorData;
+use LaravelLang\Config\Facades\Config;
use LaravelLang\LocaleList\Locale;
use LaravelLang\Translator\Contracts\Translator;
use LaravelLang\Translator\Integrations\Deepl;
@@ -14,8 +16,8 @@ class Translate
{
public function text(iterable|string $text, Locale|string $to, Locale|string|null $from = null): array|string
{
- foreach ($this->translators() as $class) {
- if ($translated = $this->translate($class, $text, $to, $from)) {
+ foreach ($this->translators() as $service) {
+ if ($translated = $this->translate($service->translator, $text, $to, $from)) {
return $translated;
}
}
@@ -65,9 +67,12 @@ protected function translate(
return null;
}
+ /**
+ * @return array
+ */
protected function translators(): array
{
- return config('localization.translators');
+ return Config::shared()->translators->enabled;
}
protected function initialize(string $class): Translator
diff --git a/tests/Datasets/Translators.php b/tests/Datasets/Translators.php
index 2cee832..a9771db 100644
--- a/tests/Datasets/Translators.php
+++ b/tests/Datasets/Translators.php
@@ -7,7 +7,7 @@
use LaravelLang\Translator\Integrations\Yandex;
dataset('translators', fn () => [
- Deepl::class => [Deepl::class],
- Google::class => [Google::class],
- Yandex::class => [Yandex::class],
+ class_basename(Deepl::class) => [Deepl::class],
+ class_basename(Google::class) => [Google::class],
+ class_basename(Yandex::class) => [Yandex::class],
]);
diff --git a/tests/Helpers/Mocks.php b/tests/Helpers/Mocks.php
index 26fe2de..6bae72c 100644
--- a/tests/Helpers/Mocks.php
+++ b/tests/Helpers/Mocks.php
@@ -2,45 +2,57 @@
declare(strict_types=1);
-use DeepL\Translator as DeeplTranslator;
+use DeepL\Translator as DeeplTranslate;
+use Illuminate\Support\Arr;
use LaravelLang\Translator\Integrations\Deepl;
use LaravelLang\Translator\Integrations\Google;
use LaravelLang\Translator\Integrations\Yandex;
-use LaravelLang\Translator\Requests\YandexCloud;
+use LaravelLang\Translator\Requests\YandexCloud as YandexTranslate;
use Stichoza\GoogleTranslate\GoogleTranslate;
use Tests\Constants\Value;
-function mockTranslator(string $translator, string $integration, array $methods = []): void
+function mockTranslators(array|string $text = null): void
{
- $service = mock($integration);
+ mockDeeplTranslator($text);
+ mockGoogleTranslator($text);
+ mockYandexTranslator($text);
+}
- foreach ($methods as $key => $value) {
- is_string($key)
- ? $service->shouldReceive($key)->andReturn($value)
- : $service->shouldReceive($value)->andReturnSelf();
- }
+function mockDeeplTranslator(array|string|null $text = null): void
+{
+ $mock = mock(DeeplTranslate::class);
- app()->forgetInstance($translator);
- app()->singleton($translator, fn () => new $translator($service));
+ $mock->shouldReceive('translateText')->andReturn($text ?? Value::Text1French);
+
+ mockTranslator(Deepl::class, $mock);
}
-function mockTranslators(
- array|string|null $deepl = null,
- array|string|null $google = null,
- array|string|null $yandex = null,
-): void {
- mockTranslator(Deepl::class, DeeplTranslator::class, [
- 'translateText' => $deepl ?? Value::Text1French,
- ]);
-
- mockTranslator(Google::class, GoogleTranslate::class, [
- 'translate' => $google ?? Value::Text1French,
- 'preserveParameters',
- 'setSource',
- 'setTarget',
- ]);
-
- mockTranslator(Yandex::class, YandexCloud::class, [
- 'translate' => $yandex ?? [Value::Text1French],
- ]);
+function mockGoogleTranslator(array|string|null $text = null): void
+{
+ $mock = mock(GoogleTranslate::class);
+
+ $mock->shouldReceive('preserveParameters', 'setSource', 'setTarget')->andReturnSelf();
+
+ is_array($text)
+ ? $mock->shouldReceive('translate')->andReturn(...$text)
+ : $mock->shouldReceive('translate')->andReturn($text ?? Value::Text1French);
+
+ mockTranslator(Google::class, $mock);
+}
+
+function mockYandexTranslator(array|string|null $text = null): void
+{
+ $mock = mock(YandexTranslate::class);
+
+ $mock->shouldReceive('translate')->andReturn(
+ Arr::wrap($text ?? [Value::Text1French])
+ );
+
+ mockTranslator(Yandex::class, $mock);
+}
+
+function mockTranslator(string $translator, mixed $mock): void
+{
+ app()->forgetInstance($translator);
+ app()->singleton($translator, fn () => new $translator($mock));
}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 18fc3aa..1253746 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -3,23 +3,36 @@
namespace Tests;
use Illuminate\Config\Repository;
-use LaravelLang\Translator\ServiceProvider;
+use LaravelLang\Config\Enums\Name;
+use LaravelLang\Config\ServiceProvider as ConfigServiceProvider;
+use LaravelLang\Translator\Integrations\Deepl;
+use LaravelLang\Translator\Integrations\Google;
+use LaravelLang\Translator\Integrations\Yandex;
+use LaravelLang\Translator\ServiceProvider as TranslatorServiceProvider;
use Orchestra\Testbench\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
protected function getPackageProviders($app): array
{
- return [ServiceProvider::class];
+ return [
+ TranslatorServiceProvider::class,
+ ConfigServiceProvider::class,
+ ];
}
protected function defineEnvironment($app): void
{
tap($app['config'], function (Repository $config) {
- $config->set('services.deepl.key', 'foo');
+ $config->set(Name::Shared() . '.translators.google.translator', Google::class);
+ $config->set(Name::Shared() . '.translators.google.credentials.key', 'foo');
- $config->set('services.yandex_translate.key', 'foo');
- $config->set('services.yandex_translate.folder_id', 'bar');
+ $config->set(Name::Shared() . '.translators.deepl.translator', Deepl::class);
+ $config->set(Name::Shared() . '.translators.deepl.credentials.key', 'foo');
+
+ $config->set(Name::Shared() . '.translators.yandex.translator', Yandex::class);
+ $config->set(Name::Shared() . '.translators.yandex.credentials.key', 'foo');
+ $config->set(Name::Shared() . '.translators.yandex.credentials.folter', '123');
});
}
}
diff --git a/tests/Unit/Can/IntegrationTest.php b/tests/Unit/Can/IntegrationTest.php
index 3e51b7f..0be0799 100644
--- a/tests/Unit/Can/IntegrationTest.php
+++ b/tests/Unit/Can/IntegrationTest.php
@@ -14,5 +14,5 @@
test('cannot be translatable', function (string $translator) {
$translator = translator($translator);
- expect($translator->can('qwerty'))->toBeTrue();
+ expect($translator->can('qwerty'))->toBeFalse();
})->with('translators');
diff --git a/tests/Unit/Translate/IntegrationCanTest.php b/tests/Unit/Translate/IntegrationCanTest.php
index 77eab7e..b9de488 100644
--- a/tests/Unit/Translate/IntegrationCanTest.php
+++ b/tests/Unit/Translate/IntegrationCanTest.php
@@ -14,6 +14,11 @@
})->with('translators');
test('as array without keys', function (string $translator) {
+ mockTranslators([
+ Value::Text1French,
+ Value::Text2French,
+ ]);
+
$translator = translator($translator);
expect($translator->translate([Value::Text1English, Value::Text2English], Locale::French))->toBe([
@@ -23,6 +28,11 @@
})->with('translators');
test('as array with keys', function (string $translator) {
+ mockTranslators([
+ 'foo' => Value::Text1French,
+ 'bar' => Value::Text2French,
+ ]);
+
$translator = translator($translator);
expect($translator->translate([
@@ -35,6 +45,11 @@
})->with('translators');
test('as collection', function (string $translator) {
+ mockTranslators([
+ 'foo' => Value::Text1French,
+ 'bar' => Value::Text2French,
+ ]);
+
$translator = translator($translator);
expect($translator->translate(collect([