Merge pull request 'Version 1.1.0' (#2) from develop into main
Reviewed-on: #2
This commit is contained in:
commit
48d7bfb6d3
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/vendor
|
95
README.md
95
README.md
@ -2,14 +2,99 @@
|
|||||||
|
|
||||||
Библиотека для Laravel, что бы общаться с сервисом перевода от <a href="https://yandex.cloud/ru/docs/translate/" target="_blank">yandex</a>. В будущем (скорей всего в далёком будущем) планирую расширить поддержку разных сервисов перевода. Что бы можно было общаться через один интерфейс с разными сервисами.
|
Библиотека для Laravel, что бы общаться с сервисом перевода от <a href="https://yandex.cloud/ru/docs/translate/" target="_blank">yandex</a>. В будущем (скорей всего в далёком будущем) планирую расширить поддержку разных сервисов перевода. Что бы можно было общаться через один интерфейс с разными сервисами.
|
||||||
|
|
||||||
Параметры в **.env**:
|
# Параметры в **.env**:
|
||||||
|
|
||||||
# TRANSLATE_SERVICE
|
### TRANSLATE_SERVICE
|
||||||
По умолчанию через какой сервис обращаться за переводом. На данный момент доступен только один сервис - **yandex**.
|
По умолчанию через какой сервис обращаться за переводом. На данный момент доступен только один сервис - **yandex**.
|
||||||
|
|
||||||
# TRANSLATE_YANDEX_FOLDER_ID
|
### TRANSLATE_YANDEX_FOLDER_ID
|
||||||
ID folder. Код можно увидеть в адресе console.yandex.cloud/folders/**{тут будет код}**.
|
ID folder. Код можно увидеть в адресе console.yandex.cloud/folders/**{тут будет код}**.
|
||||||
|
|
||||||
# TRANSLATE_YANDEX_AUTHORIZED_KEY_PATH
|
### TRANSLATE_YANDEX_AUTHORIZED_KEY_PATH
|
||||||
Абсолютный путь в рамках приложения Laravel к файлу **authorized_key.json**.
|
Абсолютный путь в рамках приложения Laravel к файлу **authorized_key.json**.
|
||||||
Например: положили файл в корень Laravel. Тогда будет путь такой: **/authorized_key.json**.
|
Например: положили файл в корень Laravel. Тогда будет путь такой: **/authorized_key.json**.
|
||||||
|
|
||||||
|
### TRANSLATE_YANDEX_LIMIT_MAX_REQUEST
|
||||||
|
Максимальное количество запросов в период, который указан в TRANSLATE_YANDEX_LIMIT_RATE_SECONDS. По умолчанию 20 запросов в секунду. **На данный момент работает только перевод через систему очередей.**
|
||||||
|
|
||||||
|
### TRANSLATE_YANDEX_LIMIT_RATE_SECONDS
|
||||||
|
Период в котором считается максимальное количество запросов. По умолчанию стоит секунда. **На данный момент работает только перевод через систему очередей.**
|
||||||
|
|
||||||
|
### TRANSLATE_YANDEX_LIMIT_MAX_SYMBOLS
|
||||||
|
Максимальное количество символов за один запрос. Если превышает, то делится на две части и делает по очереди два запроса. По умолчанию стоит 9000 символов. **На данный момент работает только перевод через систему очередей.**
|
||||||
|
|
||||||
|
# Методы
|
||||||
|
### Перевести обычный текст
|
||||||
|
> \KorElf\TranslateLaravel\Facades\Translate::translateText(
|
||||||
|
> <br> string | array \$text,
|
||||||
|
> <br> string \$targetLanguageCode,
|
||||||
|
> <br> ?string \$sourceLanguageCode = null
|
||||||
|
> <br>): string | array
|
||||||
|
|
||||||
|
**\$text** - текст который нужно перевести.
|
||||||
|
<br>**\$targetLanguageCode** - язык на который надо перевести.
|
||||||
|
<br>**\$sourceLanguageCode** - язык с которого надо перевести. Если **null**, то сервис сам пытается определить язык.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
### Перевести текст в формате HTML
|
||||||
|
> \KorElf\TranslateLaravel\Facades\Translate::translateHtml(
|
||||||
|
> <br> string | array \$text,
|
||||||
|
> <br> string \$targetLanguageCode,
|
||||||
|
> <br> ?string \$sourceLanguageCode = null
|
||||||
|
> <br>): string | array
|
||||||
|
|
||||||
|
**\$text** - текст который нужно перевести.
|
||||||
|
<br>**\$targetLanguageCode** - язык на который надо перевести.
|
||||||
|
<br>**\$sourceLanguageCode** - язык с которого надо перевести. Если **null**, то сервис сам пытается определить язык.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
### Получить список языков, который сервис поддерживает
|
||||||
|
> \KorElf\TranslateLaravel\Facades\Translate::listLanguages(): \KorElf\TranslateLaravel\DTO\Languages
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
### Перевести с помощью очередей (Queues)
|
||||||
|
> \KorElf\TranslateLaravel\Facades\Translate::runJob(
|
||||||
|
> <br> \KorElf\TranslateLaravel\DTO\RunTranslateDto \$params,
|
||||||
|
> <br> \KorElf\TranslateLaravel\Contracts\TranslationCompletedListener \$completedListener
|
||||||
|
<br>): \Illuminate\Foundation\Bus\PendingDispatch
|
||||||
|
|
||||||
|
**\$params** - параметры перевода.
|
||||||
|
<br>**\$completedListener** - после завершения перевода отправляет результат в этот объект. Объект должен соблюдать контракт **\KorElf\TranslateLaravel\Contracts\TranslationCompletedListener**.
|
||||||
|
|
||||||
|
**Пример:**
|
||||||
|
> Создаём файл TranslationListener например в папке app/Services
|
||||||
|
>
|
||||||
|
> <?php declare(strict_types=1);
|
||||||
|
>
|
||||||
|
> namespace App\Services;
|
||||||
|
>
|
||||||
|
> use Illuminate\Support\Facades\Log;
|
||||||
|
> use KorElf\TranslateLaravel\Contracts\TranslationCompletedListener;
|
||||||
|
>
|
||||||
|
> final class TranslationListener implements TranslationCompletedListener
|
||||||
|
> {
|
||||||
|
> public function onTranslationCompleted(array $translatedText): void
|
||||||
|
> {
|
||||||
|
> foreach ($translatedText as $translatedTextKey => $translatedTextValue) {
|
||||||
|
> Log::info($translatedTextKey . ': ' . $translatedTextValue);
|
||||||
|
> }
|
||||||
|
> }
|
||||||
|
> }
|
||||||
|
>
|
||||||
|
> Потом например в каком-то контроллере (а лучше конечно в сервисе) пишем такой метод
|
||||||
|
>
|
||||||
|
> public function sendingForTranslation(\App\Services\TranslationListener $translationListener): View
|
||||||
|
> {
|
||||||
|
> // Вначале создаём объект с параметрами
|
||||||
|
> $params = (new \KorElf\TranslateLaravel\DTO\RunTranslateDto)
|
||||||
|
> ->addParamText('title', 'Заголовок', 'en', 'ru')
|
||||||
|
> ->addParamHtml('content', '<p>Привет, Мир!</p>', 'en', 'ru');
|
||||||
|
>
|
||||||
|
> // Отправляем на очередь
|
||||||
|
> \KorElf\TranslateLaravel\Facades\Translate::runJob($params, $translationListener);
|
||||||
|
>
|
||||||
|
> return view('success');
|
||||||
|
> }
|
||||||
|
@ -21,18 +21,20 @@
|
|||||||
"php": "^8.2",
|
"php": "^8.2",
|
||||||
"illuminate/support": "^10.0|^11.0",
|
"illuminate/support": "^10.0|^11.0",
|
||||||
"guzzlehttp/guzzle": "^7.0.1",
|
"guzzlehttp/guzzle": "^7.0.1",
|
||||||
"web-token/jwt-framework": "^3.0"
|
"web-token/jwt-framework": "^3.0",
|
||||||
|
"ext-libxml": "^2.11.7",
|
||||||
|
"ext-dom": "^2.11.7"
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"laravel": {
|
"laravel": {
|
||||||
"providers": [
|
"providers": [
|
||||||
"korElf\\TranslateLaravel\\TranslateLaravelProvider"
|
"KorElf\\TranslateLaravel\\TranslateLaravelProvider"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"korElf\\TranslateLaravel\\": "src/"
|
"KorElf\\TranslateLaravel\\": "src/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,15 @@ return [
|
|||||||
|
|
||||||
'services' => [
|
'services' => [
|
||||||
'yandex' => [
|
'yandex' => [
|
||||||
'driver' => '\korElf\TranslateLaravel\Translate\YandexDriver',
|
'driver' => '\KorElf\TranslateLaravel\Translate\YandexDriver',
|
||||||
'config' => [
|
'config' => [
|
||||||
'folder_id' => env('TRANSLATE_YANDEX_FOLDER_ID'),
|
'folder_id' => env('TRANSLATE_YANDEX_FOLDER_ID'),
|
||||||
'authorized_key_path' => base_path(env('TRANSLATE_YANDEX_AUTHORIZED_KEY_PATH')),
|
'authorized_key_path' => base_path(env('TRANSLATE_YANDEX_AUTHORIZED_KEY_PATH')),
|
||||||
|
'limit' => [
|
||||||
|
'max_request' => (int) env('TRANSLATE_YANDEX_LIMIT_MAX_REQUEST', 20),
|
||||||
|
'rate_seconds' => (int) env('TRANSLATE_YANDEX_LIMIT_RATE_SECONDS', 1),
|
||||||
|
'max_symbols' => (int) env('TRANSLATE_YANDEX_LIMIT_MAX_SYMBOLS', 9000),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
10
src/Contracts/ProcessTranslateContract.php
Normal file
10
src/Contracts/ProcessTranslateContract.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\Contracts;
|
||||||
|
|
||||||
|
use KorElf\TranslateLaravel\DTO\ProcessTranslateLimit;
|
||||||
|
|
||||||
|
interface ProcessTranslateContract
|
||||||
|
{
|
||||||
|
public function getLimited(): ProcessTranslateLimit;
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace korElf\TranslateLaravel\Contracts;
|
namespace KorElf\TranslateLaravel\Contracts;
|
||||||
|
|
||||||
use korElf\TranslateLaravel\DTO\Languages;
|
use KorElf\TranslateLaravel\DTO\Languages;
|
||||||
use Illuminate\Contracts\Foundation\Application;
|
use Illuminate\Contracts\Foundation\Application;
|
||||||
|
|
||||||
interface Translate
|
interface Translate
|
||||||
|
8
src/Contracts/TranslationCompletedListener.php
Normal file
8
src/Contracts/TranslationCompletedListener.php
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\Contracts;
|
||||||
|
|
||||||
|
interface TranslationCompletedListener
|
||||||
|
{
|
||||||
|
public function onTranslationCompleted(array $translatedText): void;
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace korElf\TranslateLaravel\DTO;
|
namespace KorElf\TranslateLaravel\DTO;
|
||||||
|
|
||||||
final class Languages
|
final class Languages
|
||||||
{
|
{
|
||||||
|
41
src/DTO/Parameter.php
Normal file
41
src/DTO/Parameter.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\DTO;
|
||||||
|
|
||||||
|
use KorElf\TranslateLaravel\Enums\TextType;
|
||||||
|
|
||||||
|
final readonly class Parameter
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private string $text,
|
||||||
|
private TextType $textType,
|
||||||
|
private string $targetLanguageCode,
|
||||||
|
private ?string $sourceLanguageCode = null,
|
||||||
|
private ?string $driver = null
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function getText(): string
|
||||||
|
{
|
||||||
|
return $this->text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTextType(): TextType
|
||||||
|
{
|
||||||
|
return $this->textType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTargetLanguageCode(): string
|
||||||
|
{
|
||||||
|
return $this->targetLanguageCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSourceLanguageCode(): ?string
|
||||||
|
{
|
||||||
|
return $this->sourceLanguageCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDriver(): ?string
|
||||||
|
{
|
||||||
|
return $this->driver;
|
||||||
|
}
|
||||||
|
}
|
59
src/DTO/ProcessTranslateDto.php
Normal file
59
src/DTO/ProcessTranslateDto.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\DTO;
|
||||||
|
|
||||||
|
use KorElf\TranslateLaravel\Enums\TextType;
|
||||||
|
|
||||||
|
final readonly class ProcessTranslateDto
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private string $groupName,
|
||||||
|
private string $key,
|
||||||
|
private int $part,
|
||||||
|
private string $text,
|
||||||
|
private TextType $textType,
|
||||||
|
private string $targetLanguageCode,
|
||||||
|
private ?string $sourceLanguageCode = null,
|
||||||
|
private ?string $driver = null
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function getGroupName(): string
|
||||||
|
{
|
||||||
|
return $this->groupName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getKey(): string
|
||||||
|
{
|
||||||
|
return $this->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPart(): int
|
||||||
|
{
|
||||||
|
return $this->part;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getText(): string
|
||||||
|
{
|
||||||
|
return $this->text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTextType(): TextType
|
||||||
|
{
|
||||||
|
return $this->textType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTargetLanguageCode(): string
|
||||||
|
{
|
||||||
|
return $this->targetLanguageCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSourceLanguageCode(): ?string
|
||||||
|
{
|
||||||
|
return $this->sourceLanguageCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDriver(): ?string
|
||||||
|
{
|
||||||
|
return $this->driver;
|
||||||
|
}
|
||||||
|
}
|
27
src/DTO/ProcessTranslateLimit.php
Normal file
27
src/DTO/ProcessTranslateLimit.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\DTO;
|
||||||
|
|
||||||
|
final readonly class ProcessTranslateLimit
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private int $maxRequest,
|
||||||
|
private int $rateSeconds,
|
||||||
|
private string $driver,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function getMaxRequest(): int
|
||||||
|
{
|
||||||
|
return $this->maxRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRateSeconds(): int
|
||||||
|
{
|
||||||
|
return $this->rateSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDriver(): string
|
||||||
|
{
|
||||||
|
return $this->driver;
|
||||||
|
}
|
||||||
|
}
|
65
src/DTO/RunTranslateDto.php
Normal file
65
src/DTO/RunTranslateDto.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\DTO;
|
||||||
|
|
||||||
|
use KorElf\TranslateLaravel\Enums\TextType;
|
||||||
|
use KorElf\TranslateLaravel\Exceptions\RunTranslateDtoException;
|
||||||
|
|
||||||
|
final class RunTranslateDto
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array [key => \KorElf\TranslateLaravel\DTO\Parameter]
|
||||||
|
*/
|
||||||
|
private array $params = [];
|
||||||
|
|
||||||
|
public function addParam(
|
||||||
|
string $key,
|
||||||
|
string $text,
|
||||||
|
TextType $textType,
|
||||||
|
string $targetLanguageCode,
|
||||||
|
?string $sourceLanguageCode = null,
|
||||||
|
?string $driver = null
|
||||||
|
): self
|
||||||
|
{
|
||||||
|
if (isset($this->params[$key])) {
|
||||||
|
throw new RunTranslateDtoException('Duplicate key: ' . $key);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->params[$key] = new Parameter(
|
||||||
|
$text,
|
||||||
|
$textType,
|
||||||
|
$targetLanguageCode,
|
||||||
|
$sourceLanguageCode,
|
||||||
|
$driver,
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addParamHtml(
|
||||||
|
string $key,
|
||||||
|
string $text,
|
||||||
|
string $targetLanguageCode,
|
||||||
|
?string $sourceLanguageCode = null,
|
||||||
|
?string $driver = null
|
||||||
|
): self
|
||||||
|
{
|
||||||
|
return $this->addParam($key, $text, TextType::Html, $targetLanguageCode, $sourceLanguageCode, $driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addParamText(
|
||||||
|
string $key,
|
||||||
|
string $text,
|
||||||
|
string $targetLanguageCode,
|
||||||
|
?string $sourceLanguageCode = null,
|
||||||
|
?string $driver = null
|
||||||
|
): self
|
||||||
|
{
|
||||||
|
return $this->addParam($key, $text, TextType::Text, $targetLanguageCode, $sourceLanguageCode, $driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParams(): array
|
||||||
|
{
|
||||||
|
return $this->params;
|
||||||
|
}
|
||||||
|
}
|
20
src/DTO/Translated.php
Normal file
20
src/DTO/Translated.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\DTO;
|
||||||
|
|
||||||
|
final class Translated
|
||||||
|
{
|
||||||
|
private array $data = [];
|
||||||
|
|
||||||
|
public function add(string $key, int $parts): self
|
||||||
|
{
|
||||||
|
$this->data[$key] = $parts;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toArray(): array
|
||||||
|
{
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
}
|
17
src/Enums/TextType.php
Normal file
17
src/Enums/TextType.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\Enums;
|
||||||
|
|
||||||
|
enum TextType: string
|
||||||
|
{
|
||||||
|
case Text = 'text';
|
||||||
|
case Html = 'html';
|
||||||
|
|
||||||
|
public function functionName(): string
|
||||||
|
{
|
||||||
|
return match ($this) {
|
||||||
|
self::Text => 'translateText',
|
||||||
|
self::Html => 'translateHtml',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
10
src/Exceptions/AfterTranslateException.php
Normal file
10
src/Exceptions/AfterTranslateException.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\Exceptions;
|
||||||
|
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
|
final class AfterTranslateException extends RuntimeException
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
10
src/Exceptions/RunTranslateDtoException.php
Normal file
10
src/Exceptions/RunTranslateDtoException.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\Exceptions;
|
||||||
|
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
|
final class RunTranslateDtoException extends RuntimeException
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace korElf\TranslateLaravel\Exceptions;
|
namespace KorElf\TranslateLaravel\Exceptions;
|
||||||
|
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
class TranslateException extends RuntimeException
|
final class TranslateException extends RuntimeException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
@ -1,18 +1,22 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace korElf\TranslateLaravel\Facades;
|
namespace KorElf\TranslateLaravel\Facades;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Facade;
|
use Illuminate\Support\Facades\Facade;
|
||||||
|
use KorElf\TranslateLaravel\Contracts\TranslationCompletedListener;
|
||||||
|
use KorElf\TranslateLaravel\DTO\RunTranslateDto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @method static \korElf\TranslateLaravel\Contracts\Translate service(?string $name = null)
|
* @method static \KorElf\TranslateLaravel\Contracts\Translate service(?string $name = null)
|
||||||
* @method static \korElf\TranslateLaravel\Contracts\Translate resolve(string $name)
|
* @method static \KorElf\TranslateLaravel\Contracts\Translate resolve(string $name)
|
||||||
* @method static string|array translateText(string|array $text, string $targetLanguageCode, ?string $sourceLanguageCode = null)
|
* @method static string|array translateText(string|array $text, string $targetLanguageCode, ?string $sourceLanguageCode = null)
|
||||||
* @method static string|array translateHtml(string|array $text, string $targetLanguageCode, ?string $sourceLanguageCode = null)
|
* @method static string|array translateHtml(string|array $text, string $targetLanguageCode, ?string $sourceLanguageCode = null)
|
||||||
* @method static \korElf\TranslateLaravel\DTO\Languages listLanguages()
|
* @method static \Illuminate\Foundation\Bus\PendingDispatch runJob(RunTranslateDto $params, TranslationCompletedListener $completedListener)
|
||||||
|
* @method static \KorElf\TranslateLaravel\DTO\Languages listLanguages()
|
||||||
* @method static string getDefaultDriver()
|
* @method static string getDefaultDriver()
|
||||||
* @method static void setDefaultDriver(string $name)
|
* @method static void setDefaultDriver(string $name)
|
||||||
* @method static void purge(?string $name)
|
* @method static void purge(?string $name)
|
||||||
|
* @method static array getLimit(?string $driver)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
final class Translate extends Facade
|
final class Translate extends Facade
|
||||||
|
53
src/Jobs/AfterTranslate.php
Normal file
53
src/Jobs/AfterTranslate.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\Jobs;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use KorElf\TranslateLaravel\Contracts\TranslationCompletedListener;
|
||||||
|
use KorElf\TranslateLaravel\DTO\Translated;
|
||||||
|
use KorElf\TranslateLaravel\Exceptions\AfterTranslateException;
|
||||||
|
|
||||||
|
final class AfterTranslate implements ShouldQueue, ShouldBeEncrypted
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
private readonly string $groupName,
|
||||||
|
private readonly TranslationCompletedListener $listener,
|
||||||
|
private readonly Translated $translated,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
$translated = [];
|
||||||
|
$data = Cache::get($this->groupName, []);
|
||||||
|
|
||||||
|
$errors = [];
|
||||||
|
foreach ($this->translated->toArray() as $key => $parts) {
|
||||||
|
if (!isset($data[$key]) || count($data[$key]) !== $parts) {
|
||||||
|
$errors[] = $key;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$translated[$key] = implode(' ', $data[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($data)) {
|
||||||
|
throw new AfterTranslateException('Part or all of the text has not been translated. Keys: ' . implode(', ', $errors));
|
||||||
|
}
|
||||||
|
Cache::forget($this->groupName);
|
||||||
|
|
||||||
|
$this->listener->onTranslationCompleted($translated);
|
||||||
|
}
|
||||||
|
}
|
86
src/Jobs/ProcessTranslate.php
Normal file
86
src/Jobs/ProcessTranslate.php
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\Jobs;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\Middleware\RateLimited;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use KorElf\TranslateLaravel\Contracts\ProcessTranslateContract;
|
||||||
|
use KorElf\TranslateLaravel\DTO\ProcessTranslateDto;
|
||||||
|
use KorElf\TranslateLaravel\DTO\ProcessTranslateLimit;
|
||||||
|
use KorElf\TranslateLaravel\Facades\Translate;
|
||||||
|
|
||||||
|
final class ProcessTranslate implements ShouldQueue, ShouldBeEncrypted, ProcessTranslateContract
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
private readonly ProcessTranslateDto $param
|
||||||
|
) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the middleware the job should pass through.
|
||||||
|
*
|
||||||
|
* @return array<int, object>
|
||||||
|
*/
|
||||||
|
public function middleware(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
new RateLimited('kor-elf-translate'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLimited(): ProcessTranslateLimit
|
||||||
|
{
|
||||||
|
$driver = $this->param->getDriver();
|
||||||
|
if ($driver === null) {
|
||||||
|
$driver = Translate::getDefaultDriver();
|
||||||
|
}
|
||||||
|
$limit = Translate::getLimit($driver);
|
||||||
|
|
||||||
|
return new ProcessTranslateLimit(
|
||||||
|
maxRequest: $limit['max_request'] ?? 1000000000,
|
||||||
|
rateSeconds: $limit['rate_seconds'] ?? 1,
|
||||||
|
driver: $driver,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
$param = $this->param;
|
||||||
|
$groupName = $param->getGroupName();
|
||||||
|
|
||||||
|
$translated = Cache::get($groupName, []);
|
||||||
|
if (!isset($translated[$param->getKey()])) {
|
||||||
|
$translated[$param->getKey()] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$translate = Translate::service($param->getDriver());
|
||||||
|
$function = $param->getTextType()->functionName();
|
||||||
|
$key = $param->getKey();
|
||||||
|
$part = $param->getPart();
|
||||||
|
|
||||||
|
$translated[$key][$part] = $param->getText();
|
||||||
|
if (\trim($param->getText()) !== '') {
|
||||||
|
|
||||||
|
$translated[$key][$part] = $translate->{$function}(
|
||||||
|
$param->getText(),
|
||||||
|
$param->getTargetLanguageCode(),
|
||||||
|
$param->getSourceLanguageCode()
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache::put($groupName, $translated, 86400);
|
||||||
|
}
|
||||||
|
}
|
62
src/Jobs/RunTranslate.php
Normal file
62
src/Jobs/RunTranslate.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\Jobs;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Bus;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use KorElf\TranslateLaravel\Contracts\TranslationCompletedListener;
|
||||||
|
use KorElf\TranslateLaravel\DTO\ProcessTranslateDto;
|
||||||
|
use korElf\TranslateLaravel\DTO\RunTranslateDto;
|
||||||
|
use KorElf\TranslateLaravel\DTO\Translated;
|
||||||
|
use KorElf\TranslateLaravel\Translate\SplitTextIntoPartsCommand;
|
||||||
|
|
||||||
|
final class RunTranslate implements ShouldQueue, ShouldBeEncrypted
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
private readonly RunTranslateDto $runTranslateDto,
|
||||||
|
private readonly TranslationCompletedListener $translationCompletedListener,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle(SplitTextIntoPartsCommand $splitTextIntoPartsCommand): void
|
||||||
|
{
|
||||||
|
$chains = [];
|
||||||
|
$groupName = 'KorElf\TranslateLaravel\Jobs-' . Str::uuid()->toString();
|
||||||
|
$translated = new Translated();
|
||||||
|
foreach ($this->runTranslateDto->getParams() as $key => $param) {
|
||||||
|
/* @var \KorElf\TranslateLaravel\DTO\Parameter $param */
|
||||||
|
|
||||||
|
$texts = $splitTextIntoPartsCommand->execute($param->getText(), $param->getTextType(), $param->getDriver());
|
||||||
|
foreach ($texts as $part => $partText) {
|
||||||
|
$processTranslateDto = new ProcessTranslateDto(
|
||||||
|
$groupName,
|
||||||
|
$key,
|
||||||
|
$part,
|
||||||
|
$partText,
|
||||||
|
$param->getTextType(),
|
||||||
|
$param->getTargetLanguageCode(),
|
||||||
|
$param->getSourceLanguageCode(),
|
||||||
|
$param->getDriver(),
|
||||||
|
);
|
||||||
|
$chains[] = new ProcessTranslate($processTranslateDto);
|
||||||
|
}
|
||||||
|
$translated->add($key, count($texts));
|
||||||
|
}
|
||||||
|
$chains[] = new AfterTranslate($groupName, $this->translationCompletedListener, $translated);
|
||||||
|
|
||||||
|
Bus::chain($chains)->dispatch();
|
||||||
|
}
|
||||||
|
}
|
115
src/Translate/SplitTextIntoPartsCommand.php
Normal file
115
src/Translate/SplitTextIntoPartsCommand.php
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KorElf\TranslateLaravel\Translate;
|
||||||
|
|
||||||
|
use KorElf\TranslateLaravel\Enums\TextType;
|
||||||
|
use KorElf\TranslateLaravel\Facades\Translate;
|
||||||
|
use DOMDocument;
|
||||||
|
|
||||||
|
final readonly class SplitTextIntoPartsCommand
|
||||||
|
{
|
||||||
|
public function execute(string $text, TextType $textType, ?string $driver): array
|
||||||
|
{
|
||||||
|
$maxLength = Translate::getLimit($driver);
|
||||||
|
$maxLength = $maxLength['max_symbols'] ?? null;
|
||||||
|
if ($maxLength === null || $maxLength > mb_strlen($text)) {
|
||||||
|
return [$text];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($textType === TextType::Html) {
|
||||||
|
return $this->splitHtmlText($text, $maxLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->splitTextBySentences($text, $maxLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function splitTextBySentences(string $text, int $maxLength): array
|
||||||
|
{
|
||||||
|
// Common expression for searching for sentences.
|
||||||
|
$sentenceEndings = '/(?<=[.?!])\s+(?=[A-ZА-Я])/u';
|
||||||
|
|
||||||
|
//Dividing the text into sentences
|
||||||
|
$sentences = preg_split($sentenceEndings, $text, -1, PREG_SPLIT_NO_EMPTY);
|
||||||
|
|
||||||
|
$parts = [];
|
||||||
|
$currentPart = '';
|
||||||
|
|
||||||
|
foreach ($sentences as $sentence) {
|
||||||
|
// If adding a sentence does not exceed the limit, add it to the current part.
|
||||||
|
if (mb_strlen($currentPart . ' ' . $sentence) <= $maxLength) {
|
||||||
|
$currentPart .= (empty($currentPart) ? '' : ' ') . $sentence;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, save the current part and start a new one.
|
||||||
|
if (!empty($currentPart)) {
|
||||||
|
$parts[] = $currentPart;
|
||||||
|
$currentPart = '';
|
||||||
|
}
|
||||||
|
$currentPart = $sentence;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($currentPart)) {
|
||||||
|
$parts[] = $currentPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function splitHtmlText(string $html, int $maxLength): array
|
||||||
|
{
|
||||||
|
libxml_use_internal_errors(true);
|
||||||
|
|
||||||
|
$dom = new DOMDocument();
|
||||||
|
$dom->loadHTML(mb_convert_encoding('<body>' . $html . '</body>', 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
|
||||||
|
|
||||||
|
$parts = [];
|
||||||
|
$currentPart = new DOMDocument();
|
||||||
|
$currentLength = 0;
|
||||||
|
|
||||||
|
// Iterate through all child nodes of the root element
|
||||||
|
foreach ($dom->documentElement->childNodes as $node) {
|
||||||
|
if ($node->nodeType === XML_TEXT_NODE || $node->nodeType === XML_CDATA_SECTION_NODE) {
|
||||||
|
// Dividing text nodes into sentences
|
||||||
|
$sentences = preg_split('/(?<=[.?!])\s+(?=[A-ZА-Я])/', $node->textContent, -1, PREG_SPLIT_NO_EMPTY);
|
||||||
|
|
||||||
|
foreach ($sentences as $sentence) {
|
||||||
|
$sentenceHtml = htmlspecialchars($sentence);
|
||||||
|
if ($currentLength + mb_strlen($sentenceHtml) > $maxLength) {
|
||||||
|
$parts[] = $currentPart->saveHTML();
|
||||||
|
|
||||||
|
// Start new part
|
||||||
|
$currentPart = new DOMDocument();
|
||||||
|
$currentLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$textNode = $currentPart->createTextNode($sentence . ' ');
|
||||||
|
$currentPart->appendChild($textNode);
|
||||||
|
$currentLength += mb_strlen($sentenceHtml);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$nodeHtml = $dom->saveHTML($node);
|
||||||
|
|
||||||
|
if ($currentLength + mb_strlen($nodeHtml) > $maxLength) {
|
||||||
|
$parts[] = $currentPart->saveHTML();
|
||||||
|
|
||||||
|
// Start new part
|
||||||
|
$currentPart = new DOMDocument();
|
||||||
|
$currentLength = mb_strlen($nodeHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentPart->appendChild($currentPart->importNode($node, true));
|
||||||
|
$currentLength += mb_strlen($nodeHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($currentPart->hasChildNodes()) {
|
||||||
|
$parts[] = $currentPart->saveHTML();
|
||||||
|
}
|
||||||
|
|
||||||
|
libxml_clear_errors();
|
||||||
|
|
||||||
|
return $parts;
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,15 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace korElf\TranslateLaravel\Translate;
|
namespace KorElf\TranslateLaravel\Translate;
|
||||||
|
|
||||||
use Illuminate\Contracts\Foundation\Application;
|
use Illuminate\Contracts\Foundation\Application;
|
||||||
use korElf\TranslateLaravel\Contracts\Translate;
|
use Illuminate\Foundation\Bus\PendingDispatch;
|
||||||
|
use KorElf\TranslateLaravel\Contracts\CallbackAfterTranslated;
|
||||||
|
use KorElf\TranslateLaravel\Contracts\Translate;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
use KorElf\TranslateLaravel\Contracts\TranslationCompletedListener;
|
||||||
|
use KorElf\TranslateLaravel\DTO\RunTranslateDto;
|
||||||
|
use KorElf\TranslateLaravel\Jobs\RunTranslate;
|
||||||
|
|
||||||
final class TranslateManager
|
final class TranslateManager
|
||||||
{
|
{
|
||||||
@ -44,7 +49,7 @@ final class TranslateManager
|
|||||||
$config = $this->getConfig($name);
|
$config = $this->getConfig($name);
|
||||||
|
|
||||||
if (\is_null($config)) {
|
if (\is_null($config)) {
|
||||||
throw new InvalidArgumentException("Translate service [{$name}] is not defined.");
|
throw new InvalidArgumentException('Translate service [' . $name . '] is not defined.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $config['driver']::init($this->app, $config['config']);
|
return $config['driver']::init($this->app, $config['config']);
|
||||||
@ -60,6 +65,25 @@ final class TranslateManager
|
|||||||
unset($this->translates[$name]);
|
unset($this->translates[$name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run through queues.
|
||||||
|
*/
|
||||||
|
public function runJob(RunTranslateDto $params, TranslationCompletedListener $completedListener): PendingDispatch
|
||||||
|
{
|
||||||
|
return RunTranslate::dispatch($params, $completedListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLimit(?string $driver = null): array
|
||||||
|
{
|
||||||
|
if ($driver === null) {
|
||||||
|
$driver = $this->getDefaultDriver();
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = $this->getConfig($driver);
|
||||||
|
|
||||||
|
return $config['config']['limit'] ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamically call the default driver instance.
|
* Dynamically call the default driver instance.
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace korElf\TranslateLaravel\Translate\Yandex;
|
namespace KorElf\TranslateLaravel\Translate\Yandex;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
@ -10,15 +10,15 @@ use Jose\Component\KeyManagement\JWKFactory;
|
|||||||
use Jose\Component\Signature\Algorithm\PS256;
|
use Jose\Component\Signature\Algorithm\PS256;
|
||||||
use Jose\Component\Signature\JWSBuilder;
|
use Jose\Component\Signature\JWSBuilder;
|
||||||
use Jose\Component\Signature\Serializer\CompactSerializer;
|
use Jose\Component\Signature\Serializer\CompactSerializer;
|
||||||
use korElf\TranslateLaravel\Exceptions\TranslateException;
|
use KorElf\TranslateLaravel\Exceptions\TranslateException;
|
||||||
|
|
||||||
final class Connection
|
final class Connection
|
||||||
{
|
{
|
||||||
private readonly string $path;
|
private string $path;
|
||||||
private readonly string $folderId;
|
private string $folderId;
|
||||||
private readonly string $privateKey;
|
private string $privateKey;
|
||||||
private readonly string $keyId;
|
private string $keyId;
|
||||||
private readonly string $serviceAccountId;
|
private string $serviceAccountId;
|
||||||
|
|
||||||
public function __construct(string $path, string $folderId, string $privateKey, string $keyId, string $serviceAccountId)
|
public function __construct(string $path, string $folderId, string $privateKey, string $keyId, string $serviceAccountId)
|
||||||
{
|
{
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace korElf\TranslateLaravel\Translate;
|
namespace KorElf\TranslateLaravel\Translate;
|
||||||
|
|
||||||
use korElf\TranslateLaravel\Contracts\Translate;
|
use KorElf\TranslateLaravel\Contracts\Translate;
|
||||||
use korElf\TranslateLaravel\DTO\Languages;
|
use KorElf\TranslateLaravel\DTO\Languages;
|
||||||
use korElf\TranslateLaravel\Exceptions\TranslateException;
|
use KorElf\TranslateLaravel\Exceptions\TranslateException;
|
||||||
use korElf\TranslateLaravel\Translate\Yandex\Connection;
|
use KorElf\TranslateLaravel\Translate\Yandex\Connection;
|
||||||
use Illuminate\Contracts\Foundation\Application;
|
use Illuminate\Contracts\Foundation\Application;
|
||||||
|
|
||||||
final class YandexDriver implements Translate
|
final class YandexDriver implements Translate
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace korElf\TranslateLaravel;
|
namespace KorElf\TranslateLaravel;
|
||||||
|
|
||||||
|
use Illuminate\Cache\RateLimiting\Limit;
|
||||||
|
use Illuminate\Support\Facades\RateLimiter;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Illuminate\Contracts\Foundation\Application;
|
use Illuminate\Contracts\Foundation\Application;
|
||||||
use korElf\TranslateLaravel\Translate\TranslateManager;
|
use KorElf\TranslateLaravel\Contracts\ProcessTranslateContract;
|
||||||
|
use KorElf\TranslateLaravel\Translate\TranslateManager;
|
||||||
|
|
||||||
final class TranslateLaravelProvider extends ServiceProvider
|
final class TranslateLaravelProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
@ -13,6 +16,15 @@ final class TranslateLaravelProvider extends ServiceProvider
|
|||||||
$this->publishes([
|
$this->publishes([
|
||||||
__DIR__ . '/../config/translate.php' => config_path('translate.php'),
|
__DIR__ . '/../config/translate.php' => config_path('translate.php'),
|
||||||
], 'config');
|
], 'config');
|
||||||
|
|
||||||
|
RateLimiter::for('kor-elf-translate', function (ProcessTranslateContract $job) {
|
||||||
|
$limited = $job->getLimited();
|
||||||
|
|
||||||
|
return Limit::perSecond(
|
||||||
|
$limited->getMaxRequest(),
|
||||||
|
$limited->getRateSeconds()
|
||||||
|
)->by($limited->getDriver());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,7 +38,6 @@ final class TranslateLaravelProvider extends ServiceProvider
|
|||||||
__DIR__ . '/../config/translate.php',
|
__DIR__ . '/../config/translate.php',
|
||||||
'translate'
|
'translate'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->app->singleton('translate', function (Application $app) {
|
$this->app->singleton('translate', function (Application $app) {
|
||||||
return new TranslateManager($app);
|
return new TranslateManager($app);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user