Compare commits
16 Commits
4dc6060fb3
...
develop
Author | SHA1 | Date | |
---|---|---|---|
d4174cf7d2
|
|||
de496eaea1
|
|||
94db6aa51d
|
|||
c33fcd1d7c
|
|||
3d4bef0e56
|
|||
19b0e68b8b
|
|||
ba74aa9977
|
|||
224240708d
|
|||
4049f9df53
|
|||
c112b225dc
|
|||
e3194cef48
|
|||
41a7343338
|
|||
90aa909b7f
|
|||
8b35a5691f
|
|||
844264fb62
|
|||
d8d17064d0
|
@@ -11,6 +11,7 @@ final readonly class StoreUpdate extends Dto
|
||||
private string $title,
|
||||
private string $description,
|
||||
private Storages $storages,
|
||||
private bool $isTranslateAutomatically = false,
|
||||
) { }
|
||||
|
||||
public function getTitle(): string
|
||||
@@ -27,4 +28,9 @@ final readonly class StoreUpdate extends Dto
|
||||
{
|
||||
return $this->storages;
|
||||
}
|
||||
|
||||
public function isTranslateAutomatically(): bool
|
||||
{
|
||||
return $this->isTranslateAutomatically;
|
||||
}
|
||||
}
|
||||
|
@@ -8,10 +8,16 @@ final readonly class Update extends Dto
|
||||
{
|
||||
public function __construct(
|
||||
private Translations $translations,
|
||||
private bool $isTranslateAutomatically = false,
|
||||
) { }
|
||||
|
||||
public function getTranslations(): Translations
|
||||
{
|
||||
return $this->translations;
|
||||
}
|
||||
|
||||
public function isTranslateAutomatically(): bool
|
||||
{
|
||||
return $this->isTranslateAutomatically;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,25 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Dto\Service\ProjectTranslationServiceTextHash;
|
||||
|
||||
final class Codes
|
||||
{
|
||||
private array $codes = [];
|
||||
|
||||
public function add(string $code, string $value): self
|
||||
{
|
||||
$this->codes[$code] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCodes(): array
|
||||
{
|
||||
return $this->codes;
|
||||
}
|
||||
|
||||
public function getCodeNames(): array
|
||||
{
|
||||
return \array_keys($this->codes);
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Dto\Service\ProjectTranslationServiceTextHash;
|
||||
|
||||
final class HashStatusWaiting
|
||||
{
|
||||
private array $hash = [];
|
||||
|
||||
public function add(string $code, bool $isWaiting): void
|
||||
{
|
||||
$this->hash[$code] = $isWaiting;
|
||||
}
|
||||
|
||||
public function isStatusWaiting(string $code): bool
|
||||
{
|
||||
return $this->hash[$code] ?? false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Dto\Service\ProjectTranslationServiceTextHash;
|
||||
|
||||
final class Hashes
|
||||
{
|
||||
private array $hashes = [];
|
||||
private array $ids = [];
|
||||
|
||||
public function add(int $hashId, string $code, string $hash): void
|
||||
{
|
||||
$this->hashes[$hashId] = [
|
||||
'code' => $code,
|
||||
'hash' => $hash,
|
||||
];
|
||||
$this->ids[] = $hashId;
|
||||
}
|
||||
|
||||
public function getHash(int $hashId): ?array
|
||||
{
|
||||
return $this->hashes[$hashId] ?? null;
|
||||
}
|
||||
|
||||
public function getIds(): array
|
||||
{
|
||||
return $this->ids;
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Dto\Service\ProjectTranslationServiceTextHash;
|
||||
|
||||
final class TranslateCodes
|
||||
{
|
||||
private array $codes = [];
|
||||
private array $hashes = [];
|
||||
|
||||
public function add(int $languageId, string $code, string $hash, int $hashId): self
|
||||
{
|
||||
if (!isset($this->codes[$languageId])) {
|
||||
$this->codes[$languageId] = [];
|
||||
}
|
||||
$this->codes[$languageId][] = $code;
|
||||
|
||||
if (!isset($this->hashes[$languageId])) {
|
||||
$this->hashes[$languageId] = [];
|
||||
}
|
||||
$this->hashes[$languageId][$code] = [
|
||||
'hash' => $hash,
|
||||
'hashId' => $hashId,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCodes(): array
|
||||
{
|
||||
return $this->codes;
|
||||
}
|
||||
|
||||
public function getHashesByLanguage(int $languageId): array
|
||||
{
|
||||
return $this->hashes[$languageId] ?? [];
|
||||
}
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Illuminate\Cache\TaggedCache;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
enum CacheTag: string
|
||||
{
|
||||
case Project = 'project';
|
||||
case ProjectTranslation = 'project_translation';
|
||||
case DocumantationVersion = 'documantation_version';
|
||||
|
||||
public function getCache(): TaggedCache
|
||||
{
|
||||
return Cache::tags($this->value);
|
||||
}
|
||||
}
|
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Enums\CacheTag;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
final readonly class DocumentationVersion
|
||||
@@ -17,7 +17,7 @@ final readonly class DocumentationVersion
|
||||
}
|
||||
|
||||
$seconds = 3600;
|
||||
$version = CacheTag::DocumantationVersion->getCache()->remember(self::class . $project->id . '-' . $versionSlug, $seconds, function () use ($project, $versionSlug) {
|
||||
$version = Cache::remember(self::class . $project->id . '-' . $versionSlug, $seconds, function () use ($project, $versionSlug) {
|
||||
return $project->documentationVersions()->where('slug', $versionSlug)->first() ?? false;
|
||||
});
|
||||
if ($version === false) {
|
||||
|
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Enums\CacheTag;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Closure;
|
||||
|
||||
@@ -17,7 +17,7 @@ final class ProjectAndLanguage extends ProjectLanguage
|
||||
}
|
||||
|
||||
$seconds = 3600;
|
||||
$project = CacheTag::Project->getCache()->remember(self::class . $projectCode, $seconds, function () use ($projectCode) {
|
||||
$project = Cache::remember(self::class . $projectCode, $seconds, function () use ($projectCode) {
|
||||
return $this->projectRepository->getProjectByCode($projectCode) ?? false;
|
||||
});
|
||||
if ($project === false) {
|
||||
|
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Enums\CacheTag;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
@@ -21,7 +21,7 @@ final class ProjectDomainAndLanguage extends ProjectLanguage
|
||||
}
|
||||
|
||||
$seconds = 3600;
|
||||
$project = CacheTag::Project->getCache()->remember(self::class . $httpHost, $seconds, function () use ($httpHost) {
|
||||
$project = Cache::remember(self::class . $httpHost, $seconds, function () use ($httpHost) {
|
||||
return $this->projectRepository->getProjectByHttpHost($httpHost) ?? false;
|
||||
});
|
||||
if ($project === false) {
|
||||
|
@@ -2,13 +2,13 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Enums\CacheTag;
|
||||
use App\Models\Project;
|
||||
use App\Repositories\ProjectLanguageRepository;
|
||||
use App\Repositories\ProjectRepository;
|
||||
use App\Repositories\ProjectTranslationRepository;
|
||||
use App\Services\WebsiteTranslations;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
abstract class ProjectLanguage
|
||||
{
|
||||
@@ -21,7 +21,7 @@ abstract class ProjectLanguage
|
||||
protected function getWebsiteTranslations(Project $project, ?string $languageCode): ?WebsiteTranslations
|
||||
{
|
||||
$seconds = 3600 * 3;
|
||||
$language = CacheTag::Project->getCache()->remember(self::class . $project->id . '-' . $languageCode, $seconds, function () use ($project, $languageCode) {
|
||||
$language = Cache::remember(self::class . $project->id . '-' . $languageCode, $seconds, function () use ($project, $languageCode) {
|
||||
return $this->projectLanguageRepository->getProjectLanguageByCodeOrDefault($project, $languageCode) ?? false;
|
||||
});
|
||||
if ($language === false) {
|
||||
@@ -34,7 +34,7 @@ abstract class ProjectLanguage
|
||||
}
|
||||
|
||||
$seconds = 3600 * 24;
|
||||
$translations = CacheTag::ProjectTranslation->getCache()->remember(self::class . '-translations-' . $project->id . '-' . $language->id, $seconds, function () use ($project, $language) {
|
||||
$translations = Cache::remember(self::class . '-translations-' . $project->id . '-' . $language->id, $seconds, function () use ($project, $language) {
|
||||
return $this->projectTranslationRepository->getProjectTranslations($project->id, $language->id)->all()->pluck('text', 'code')->toArray();
|
||||
});
|
||||
|
||||
|
@@ -26,6 +26,7 @@ final class StoreUpdateRequest extends FormRequest implements FormRequestDto
|
||||
'title' => ['required', 'string', 'max:255',],
|
||||
'description' => ['nullable', 'string',],
|
||||
'storage.content_images.*.file' => ['numeric', 'min:1'],
|
||||
'translate-automatically' => ['nullable', 'boolean'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -35,6 +36,7 @@ final class StoreUpdateRequest extends FormRequest implements FormRequestDto
|
||||
title: $this->input('title'),
|
||||
description: $this->input('description'),
|
||||
storages: $this->storages(),
|
||||
isTranslateAutomatically: (bool) $this->input('translate-automatically', false),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,7 @@ final class UpdateRequest extends FormRequest implements FormRequestDto
|
||||
{
|
||||
return [
|
||||
'language.*.id' => ['required', 'numeric', 'min:1'],
|
||||
'language.*.code' => ['nullable', 'string', 'min:2', 'max:50'],
|
||||
'language.*.code' => ['nullable', 'string', 'min:2', 'max:50', 'required_with:language.*.source_language_id'],
|
||||
'language.*.source_language_id' => ['nullable', 'numeric', 'min:1', 'different:language.*.id'],
|
||||
];
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@ final class UpdateRequest extends FormRequest implements FormRequestDto
|
||||
'translations' => ['nullable', 'array'],
|
||||
'translations.*.code' => ['required', 'string', new In(Translations::getTranslationCodes())],
|
||||
'translations.*.text' => ['nullable', 'string', 'max:1000'],
|
||||
'translate-automatically' => ['nullable', 'boolean'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -33,6 +34,9 @@ final class UpdateRequest extends FormRequest implements FormRequestDto
|
||||
);
|
||||
}
|
||||
|
||||
return new Update($translations);
|
||||
return new Update(
|
||||
translations: $translations,
|
||||
isTranslateAutomatically: (bool) $this->input('translate-automatically', false),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
58
app/application/app/Jobs/Translate/ProcessProjectContent.php
Normal file
58
app/application/app/Jobs/Translate/ProcessProjectContent.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Jobs\Translate;
|
||||
|
||||
use App\Services\Translate\Project\ProjectContentService;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Foundation\Queue\Queueable;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
|
||||
final class ProcessProjectContent implements ShouldQueue, ShouldBeEncrypted
|
||||
{
|
||||
use Dispatchable, Queueable;
|
||||
|
||||
/**
|
||||
* Get the middleware the job should pass through.
|
||||
*
|
||||
* @return array<int, object>
|
||||
*/
|
||||
public function middleware(): array
|
||||
{
|
||||
return [
|
||||
(new WithoutOverlapping($this->uniqueId()))->expireAfter(180),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly int $projectId,
|
||||
private readonly array $contentIds = [],
|
||||
private readonly array $exceptLanguages = [],
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Get the unique ID for the job.
|
||||
*/
|
||||
public function uniqueId(): string
|
||||
{
|
||||
return 'project-' . $this->projectId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function handle(ProjectContentService $projectContentService): void
|
||||
{
|
||||
$result = $projectContentService->translate($this->projectId, $this->contentIds, $this->exceptLanguages);
|
||||
if ($result->isError() && $result->getCode() !== 404) {
|
||||
cache()->lock($this->uniqueId())->forceRelease();
|
||||
throw new Exception($result->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Jobs\Translate;
|
||||
|
||||
use App\Services\Translate\Project\TranslationTextService;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Foundation\Queue\Queueable;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
|
||||
final class ProcessTranslationText implements ShouldQueue, ShouldBeEncrypted
|
||||
{
|
||||
use Dispatchable, Queueable;
|
||||
|
||||
/**
|
||||
* Get the middleware the job should pass through.
|
||||
*
|
||||
* @return array<int, object>
|
||||
*/
|
||||
public function middleware(): array
|
||||
{
|
||||
return [
|
||||
(new WithoutOverlapping($this->uniqueId()))->expireAfter(180),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly int $projectId,
|
||||
private readonly int $languageId,
|
||||
private readonly array $translateTextCode = [],
|
||||
private readonly array $exceptLanguages = [],
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Get the unique ID for the job.
|
||||
*/
|
||||
public function uniqueId(): string
|
||||
{
|
||||
return 'ProcessTranslationText-' . $this->projectId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function handle(TranslationTextService $translationTextService): void
|
||||
{
|
||||
$result = $translationTextService->translate($this->projectId, $this->languageId, $this->translateTextCode, $this->exceptLanguages);
|
||||
if ($result->isError() && $result->getCode() !== 404) {
|
||||
cache()->lock($this->uniqueId())->forceRelease();
|
||||
throw new Exception($result->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@@ -37,6 +37,7 @@ final class Documentation extends Model
|
||||
'slug',
|
||||
'is_public',
|
||||
'category_id',
|
||||
'sort',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@@ -17,5 +17,6 @@ final class ProjectContent extends Model implements StorageContract
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'description',
|
||||
'language_id',
|
||||
];
|
||||
}
|
||||
|
@@ -0,0 +1,47 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\ProjectTranslationServiceHashes\Status;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
final class ProjectTranslationServiceTextHash extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'project_translation_service_text_hashes';
|
||||
|
||||
/**
|
||||
* The model's default values for attributes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $attributes = [
|
||||
'status' => Status::Waiting,
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'language_id',
|
||||
'code',
|
||||
'status',
|
||||
'hash',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the attributes that should be cast.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'status' => Status::class,
|
||||
];
|
||||
}
|
||||
}
|
@@ -22,4 +22,13 @@ final readonly class ProjectTranslationRepository
|
||||
$query = ProjectTranslation::query()->withTrashed()->where('project_id', $projectId)->where('language_id', $languageId);
|
||||
return $this->createSearchInstanceCommand->execute($query);
|
||||
}
|
||||
|
||||
public function getProjectTranslationByCodes(int $projectId, int $languageId, array $codes): Search
|
||||
{
|
||||
$query = ProjectTranslation::query()
|
||||
->where('project_id', $projectId)
|
||||
->where('language_id', $languageId)
|
||||
->whereIn('code', $codes);
|
||||
return $this->createSearchInstanceCommand->execute($query);
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,6 @@ final readonly class ProjectTranslationServiceHashRepository
|
||||
$query = ProjectTranslationServiceHash::query()
|
||||
->where('morph_type', $morph)
|
||||
->where('morph_id', $morphId)
|
||||
->whereIn('language_id', $languages)
|
||||
->when($languages, function (Builder $query) use ($languages) {
|
||||
$query->whereIn('language_id', $languages);
|
||||
})
|
||||
|
@@ -0,0 +1,33 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Contracts\Search;
|
||||
use App\Models\ProjectTranslationServiceTextHash;
|
||||
use App\Services\Search\CreateSearchInstanceCommand;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
final readonly class ProjectTranslationServiceTextHashRepository
|
||||
{
|
||||
|
||||
public function __construct(
|
||||
private CreateSearchInstanceCommand $createSearchInstanceCommand,
|
||||
) { }
|
||||
|
||||
public function getHashes(array $codes, ?array $languages = null): Search
|
||||
{
|
||||
$query = ProjectTranslationServiceTextHash::query()
|
||||
->whereIn('code', $codes)
|
||||
->when($languages, function (Builder $query) use ($languages) {
|
||||
$query->whereIn('language_id', $languages);
|
||||
});
|
||||
|
||||
return $this->createSearchInstanceCommand->execute($query);
|
||||
}
|
||||
|
||||
public function getHashesByIds(array $ids): Search
|
||||
{
|
||||
$query = ProjectTranslationServiceTextHash::query()->whereIn('id', $ids);
|
||||
return $this->createSearchInstanceCommand->execute($query);
|
||||
}
|
||||
}
|
@@ -5,6 +5,7 @@ namespace App\Services\Admin\Project;
|
||||
use App\Contracts\ServiceResultError;
|
||||
use App\Dto\Service\Admin\Project\About\StoreUpdate;
|
||||
use App\Enums\Morph;
|
||||
use App\Jobs\Translate\ProcessProjectContent;
|
||||
use App\Models\ProjectContent;
|
||||
use App\Models\User;
|
||||
use App\Repositories\ProjectContentRepository;
|
||||
@@ -69,6 +70,7 @@ final class AboutService extends Service
|
||||
'project' => $project,
|
||||
'language' => $language,
|
||||
'content' => $content,
|
||||
'serviceTranslationEnable' => config('translation_service.enable', false),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -105,6 +107,9 @@ final class AboutService extends Service
|
||||
$this->storageService->saveAndDelete($aboutProject, $storages);
|
||||
return $aboutProject;
|
||||
});
|
||||
if (\config('translation_service.enable', false)) {
|
||||
$this->translateContent($aboutProject, $data);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
return $this->errService(__('Server Error'));
|
||||
@@ -133,6 +138,9 @@ final class AboutService extends Service
|
||||
|
||||
return $aboutProject;
|
||||
});
|
||||
if (\config('translation_service.enable', false)) {
|
||||
$this->translateContent($aboutProject, $data);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
return $this->errService(__('Server Error'));
|
||||
@@ -148,4 +156,15 @@ final class AboutService extends Service
|
||||
'description' => $data->getDescription(),
|
||||
];
|
||||
}
|
||||
|
||||
private function translateContent(ProjectContent $projectContent, StoreUpdate $data): void
|
||||
{
|
||||
if (! $data->isTranslateAutomatically()) {
|
||||
return;
|
||||
}
|
||||
$translateExceptLanguages = [$projectContent->language_id];
|
||||
$translateContentIds = [$projectContent->id];
|
||||
|
||||
ProcessProjectContent::dispatch($projectContent->project_id, $translateContentIds, $translateExceptLanguages);
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ namespace App\Services\Admin\Project;
|
||||
use App\Dto\QuerySettingsDto;
|
||||
use App\Dto\Builder\DocumentationVersion as DocumentationVersionBuilderDto;
|
||||
use App\Dto\Service\Admin\Project\DocumentationVersion\StoreUpdate;
|
||||
use App\Enums\CacheTag;
|
||||
use App\Enums\DocumentationVersionStatus;
|
||||
use App\Models\DocumentationVersion;
|
||||
use App\Models\User;
|
||||
@@ -141,7 +140,7 @@ final class DocumentationVersionService extends Service
|
||||
$dataVersion = $this->getDataVersion($data);
|
||||
return $this->documentationVersionCommandHandler->handleStore($project, $dataVersion);
|
||||
});
|
||||
$this->clearCacheCommandHandler->byTag(CacheTag::DocumantationVersion);
|
||||
$this->clearCacheCommandHandler->all();
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
return $this->errService(__('Server Error'));
|
||||
@@ -178,7 +177,7 @@ final class DocumentationVersionService extends Service
|
||||
$dataVersion = $this->getDataVersion($data);
|
||||
return $this->documentationVersionCommandHandler->handleUpdate($version, $dataVersion);
|
||||
});
|
||||
$this->clearCacheCommandHandler->byTag(CacheTag::DocumantationVersion);
|
||||
$this->clearCacheCommandHandler->all();
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
return $this->errService(__('Server Error'));
|
||||
@@ -207,7 +206,7 @@ final class DocumentationVersionService extends Service
|
||||
DB::transaction(function () use ($version) {
|
||||
$this->documentationVersionCommandHandler->handleDestroy($version);
|
||||
});
|
||||
$this->clearCacheCommandHandler->byTag(CacheTag::DocumantationVersion);
|
||||
$this->clearCacheCommandHandler->all();
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
return $this->errService(__('Server Error'));
|
||||
|
@@ -3,8 +3,9 @@
|
||||
namespace App\Services\Admin\Project;
|
||||
|
||||
use App\Dto\Service\Admin\Project\Translation\Translations;
|
||||
use App\Dto\Service\Admin\Project\Translation\Translation;
|
||||
use App\Dto\Service\Admin\Project\Translation\Update;
|
||||
use App\Enums\CacheTag;
|
||||
use App\Jobs\Translate\ProcessTranslationText;
|
||||
use App\Models\ProjectTranslation;
|
||||
use App\Models\User;
|
||||
use App\Repositories\ProjectRepository;
|
||||
@@ -60,6 +61,7 @@ final class TranslationService extends Service
|
||||
'language' => $language,
|
||||
'projectTranslations' => $this->projectTranslationRepository->getProjectTranslations($projectId, $languageId)->all()->pluck('text', 'code')->toArray(),
|
||||
'translations' => Translations::getTranslationCodes(),
|
||||
'serviceTranslationEnable' => config('translation_service.enable', false),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -80,7 +82,10 @@ final class TranslationService extends Service
|
||||
DB::transaction(function () use ($data, $project, $language) {
|
||||
$this->translationModelSyncCommand->execute($project, $language, $data->getTranslations());
|
||||
});
|
||||
$this->clearCacheCommandHandler->byTag(CacheTag::ProjectTranslation);
|
||||
$this->clearCacheCommandHandler->all();
|
||||
if (\config('translation_service.enable', false)) {
|
||||
$this->translateContent($projectId, $languageId, $data);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
return $this->errService(__('Server Error'));
|
||||
@@ -88,4 +93,19 @@ final class TranslationService extends Service
|
||||
|
||||
return $this->ok(__('Translations successfully updated'));
|
||||
}
|
||||
|
||||
private function translateContent(int $projectId, int $languageId, Update $data): void
|
||||
{
|
||||
if (! $data->isTranslateAutomatically()) {
|
||||
return;
|
||||
}
|
||||
$translateExceptLanguages = [$languageId];
|
||||
$translateTextCode = [];
|
||||
foreach ($data->getTranslations()->getTranslations() as $translation) {
|
||||
/** @var Translation $translation */
|
||||
$translateTextCode[] = $translation->getCode();
|
||||
}
|
||||
|
||||
ProcessTranslationText::dispatch($projectId, $languageId, $translateTextCode, $translateExceptLanguages);
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ namespace App\Services\Admin;
|
||||
use App\Dto\Builder\Project as ProjectBuilderDto;
|
||||
use App\Dto\QuerySettingsDto;
|
||||
use App\Dto\Service\Admin\Project\StoreUpdate;
|
||||
use App\Enums\CacheTag;
|
||||
use App\Enums\Morph;
|
||||
use App\Models\Project;
|
||||
use App\Models\ProjectLanguage;
|
||||
@@ -134,7 +133,7 @@ final class ProjectService extends Service
|
||||
|
||||
return $project;
|
||||
});
|
||||
$this->clearCacheCommandHandler->byTag(CacheTag::Project);
|
||||
$this->clearCacheCommandHandler->all();
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
return $this->errService(__('Server Error'));
|
||||
@@ -177,7 +176,7 @@ final class ProjectService extends Service
|
||||
|
||||
return $project;
|
||||
});
|
||||
$this->clearCacheCommandHandler->byTag(CacheTag::Project);
|
||||
$this->clearCacheCommandHandler->all();
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
return $this->errService(__('Server Error'));
|
||||
@@ -202,7 +201,7 @@ final class ProjectService extends Service
|
||||
DB::transaction(function () use ($project) {
|
||||
$this->projectCommandHandler->handleDestroy($project);
|
||||
});
|
||||
$this->clearCacheCommandHandler->byTag(CacheTag::Project);
|
||||
$this->clearCacheCommandHandler->all();
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
return $this->errService(__('Server Error'));
|
||||
|
@@ -2,12 +2,12 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Enums\CacheTag;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
final readonly class ClearCacheCommandHandler
|
||||
{
|
||||
public function byTag(CacheTag $tag)
|
||||
public function all(): void
|
||||
{
|
||||
$tag->getCache()->flush();
|
||||
Cache::flush();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,23 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\ProjectTranslation;
|
||||
|
||||
use App\Models\ProjectLanguage;
|
||||
|
||||
final readonly class TranslationText
|
||||
{
|
||||
public function __construct(
|
||||
private ProjectLanguage $language,
|
||||
private array $translations,
|
||||
) { }
|
||||
|
||||
public static function init(ProjectLanguage $language, array $translations): self
|
||||
{
|
||||
return new self($language, $translations);
|
||||
}
|
||||
|
||||
public function translate(string $code): string
|
||||
{
|
||||
return $this->translations[$code] ?? __($code, [], $this->language->system_lang?->getLocale());
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\ProjectTranslation;
|
||||
|
||||
use App\Models\Project;
|
||||
use App\Models\ProjectLanguage;
|
||||
use App\Repositories\ProjectTranslationRepository;
|
||||
|
||||
final readonly class TranslationTextCommand
|
||||
{
|
||||
public function __construct(
|
||||
private ProjectTranslationRepository $translationRepository,
|
||||
) { }
|
||||
|
||||
public function execute(Project $project, ProjectLanguage $language, array $codes): TranslationText
|
||||
{
|
||||
$translations = $this->translationRepository
|
||||
->getProjectTranslationByCodes($project->id, $language->id, $codes)
|
||||
->all()->pluck('text', 'code');
|
||||
|
||||
return TranslationText::init($language, $translations->toArray());
|
||||
}
|
||||
}
|
@@ -30,7 +30,7 @@ final readonly class CompletionChecker
|
||||
$isWaiting = true;
|
||||
$hashSuccessIds[] = $hash->id;
|
||||
}
|
||||
$hashStatusWaiting->add($hash['field'], $isWaiting);
|
||||
$hashStatusWaiting->add($hash->field, $isWaiting);
|
||||
}
|
||||
|
||||
$this->commandHandler->handleSetStatusById($hashSuccessIds, Status::Success);
|
||||
|
@@ -0,0 +1,40 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\ProjectTranslationServiceTextHash;
|
||||
|
||||
use App\Dto\Service\ProjectTranslationServiceTextHash\Hashes;
|
||||
use App\Dto\Service\ProjectTranslationServiceTextHash\HashStatusWaiting;
|
||||
use App\Enums\ProjectTranslationServiceHashes\Status;
|
||||
use App\Repositories\ProjectTranslationServiceTextHashRepository;
|
||||
|
||||
final readonly class CompletionChecker
|
||||
{
|
||||
public function __construct(
|
||||
private ProjectTranslationServiceTextHashRepository $hashRepository,
|
||||
private ProjectTranslationServiceTextHashCommandHandler $commandHandler,
|
||||
) { }
|
||||
|
||||
public function execute(Hashes $hashesDto): HashStatusWaiting
|
||||
{
|
||||
$hashes = $this->hashRepository->getHashesByIds($hashesDto->getIds())->all();
|
||||
$hashStatusWaiting = new HashStatusWaiting();
|
||||
$hashSuccessIds = [];
|
||||
foreach ($hashes as $hash) {
|
||||
$dataHash = $hashesDto->getHash($hash->id);
|
||||
if ($dataHash === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$isWaiting = false;
|
||||
if ($hash->status === Status::Waiting && $hash->hash === $dataHash['hash'] && $hash->code === $dataHash['code']) {
|
||||
$isWaiting = true;
|
||||
$hashSuccessIds[] = $hash->id;
|
||||
}
|
||||
$hashStatusWaiting->add($hash->code, $isWaiting);
|
||||
}
|
||||
|
||||
$this->commandHandler->handleSetStatusById($hashSuccessIds, Status::Success);
|
||||
|
||||
return $hashStatusWaiting;
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\ProjectTranslationServiceTextHash;
|
||||
|
||||
use App\Dto\Service\ProjectTranslationServiceTextHash\Codes;
|
||||
use App\Dto\Service\ProjectTranslationServiceTextHash\TranslateCodes;
|
||||
use App\Enums\ProjectTranslationServiceHashes\Status;
|
||||
use App\Models\ProjectTranslationServiceTextHash;
|
||||
use App\Repositories\ProjectTranslationServiceTextHashRepository;
|
||||
|
||||
final readonly class HashTrackerCommand
|
||||
{
|
||||
public function __construct(
|
||||
private ProjectTranslationServiceTextHashRepository $hashRepository,
|
||||
private ProjectTranslationServiceTextHashCommandHandler $commandHandler,
|
||||
) { }
|
||||
|
||||
public function execute(array $languages, Codes $codes): TranslateCodes
|
||||
{
|
||||
$hashes = $this->hashRepository->getHashes($codes->getCodeNames(), $languages)->all();
|
||||
|
||||
$translateCodes = new TranslateCodes();
|
||||
foreach ($codes->getCodes() as $code => $value) {
|
||||
$textHash = $this->generateHashFromText((string) $value);
|
||||
foreach ($languages as $language) {
|
||||
$modelHash = $hashes->where('language_id', $language)->firstWhere('code', $code);
|
||||
if ($modelHash === null) {
|
||||
$modelHash = $this->commandHandler->handleStore([
|
||||
'language_id' => $language,
|
||||
'code' => $code,
|
||||
'hash' => $textHash,
|
||||
'status' => Status::Waiting,
|
||||
]);
|
||||
$translateCodes->add($language, $code, $textHash, $modelHash->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($modelHash->hash === $textHash && $this->isSuccess($modelHash)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$translateCodes->add($language, $code, $textHash, $modelHash->id);
|
||||
$this->commandHandler->handleUpdate($modelHash, [
|
||||
'hash' => $textHash,
|
||||
'status' => Status::Waiting,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return $translateCodes;
|
||||
}
|
||||
|
||||
private function generateHashFromText(string $text): string
|
||||
{
|
||||
return \hash('sha256', $text);
|
||||
}
|
||||
|
||||
private function isSuccess(ProjectTranslationServiceTextHash $modelHash): bool
|
||||
{
|
||||
if ($modelHash->status === Status::Success) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ($modelHash->updated_at >= now()->subMinutes(10));
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\ProjectTranslationServiceTextHash;
|
||||
|
||||
use App\Enums\ProjectTranslationServiceHashes\Status;
|
||||
use App\Models\ProjectTranslationServiceTextHash;
|
||||
|
||||
final readonly class ProjectTranslationServiceTextHashCommandHandler
|
||||
{
|
||||
public function handleStore(array $data): ProjectTranslationServiceTextHash
|
||||
{
|
||||
return ProjectTranslationServiceTextHash::create($data);
|
||||
}
|
||||
|
||||
public function handleUpdate(ProjectTranslationServiceTextHash $hash, array $data): ProjectTranslationServiceTextHash
|
||||
{
|
||||
$hash->update($data);
|
||||
$hash->touch();
|
||||
return $hash;
|
||||
}
|
||||
|
||||
public function handleSetStatusById(array $ids, Status $status): void
|
||||
{
|
||||
ProjectTranslationServiceTextHash::query()->whereIn('id', $ids)->update(['status' => $status->value]);
|
||||
}
|
||||
}
|
@@ -3,7 +3,6 @@
|
||||
namespace App\Services\Site;
|
||||
|
||||
use App\Dto\Service\Site\Documentation;
|
||||
use App\Enums\CacheTag;
|
||||
use App\Enums\DocumentationVersionStatus;
|
||||
use App\Models\DocumentationCategory;
|
||||
use App\Models\Documentation as ModelDocumentation;
|
||||
@@ -22,6 +21,7 @@ use App\Dto\Builder\Documentation as DocumentationBuilderDto;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
final class DocumentationService extends Service
|
||||
{
|
||||
@@ -37,8 +37,7 @@ final class DocumentationService extends Service
|
||||
if ($user?->cannot('viewAny', DocumentationVersion::class)) {
|
||||
$isPublic = 1;
|
||||
}
|
||||
$version = CacheTag::DocumantationVersion->getCache()
|
||||
->remember(self::class . $project->id . '_' . $isPublic ?? 0, $seconds, function () use ($project, $isPublic) {
|
||||
$version = Cache::remember(self::class . $project->id . '_' . $isPublic ?? 0, $seconds, function () use ($project, $isPublic) {
|
||||
$versions = $project->documentationVersions()
|
||||
->when($isPublic, function (Builder $query) {
|
||||
$query->where('is_public', 1);
|
||||
|
@@ -13,7 +13,7 @@ use App\Services\ProjectTranslationServiceHash\CompletionChecker;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use KorElf\TranslateLaravel\Contracts\TranslationCompletedListener;
|
||||
|
||||
final class DocumentationCategoryContentService implements TranslationCompletedListener
|
||||
final readonly class DocumentationCategoryContentService implements TranslationCompletedListener
|
||||
{
|
||||
public function __construct(
|
||||
private DocumentationCategoryRepository $categoryRepository,
|
||||
|
@@ -0,0 +1,89 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Translate\Completed\Project;
|
||||
|
||||
use App\Dto\Service\ProjectTranslationServiceHash\Hashes;
|
||||
use App\Exceptions\Services\Translate\CompletedException;
|
||||
use App\Jobs\Translate\ProcessProjectContent;
|
||||
use App\Models\Project;
|
||||
use App\Models\ProjectContent;
|
||||
use App\Repositories\ProjectRepository;
|
||||
use App\Services\ProjectTranslationService\NoTranslateAttributeHandler;
|
||||
use App\Services\ProjectTranslationServiceHash\CompletionChecker;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use KorElf\TranslateLaravel\Contracts\TranslationCompletedListener;
|
||||
|
||||
final readonly class ProjectContentService implements TranslationCompletedListener
|
||||
{
|
||||
public function __construct(
|
||||
private ProjectRepository $projectRepository,
|
||||
private NoTranslateAttributeHandler $noTranslateAttributeHandler,
|
||||
private CompletionChecker $completionChecker,
|
||||
) { }
|
||||
|
||||
/**
|
||||
* @throws CompletedException
|
||||
*/
|
||||
public function onTranslationCompleted(array $translatedText, array $data = []): void
|
||||
{
|
||||
if (
|
||||
!isset($data['projectId'])
|
||||
|| !isset($data['languageId'])
|
||||
|| !isset($data['hashes'])
|
||||
) {
|
||||
throw new CompletedException('Required data is missing: projectId, languageId, or hashes.');
|
||||
}
|
||||
|
||||
$project = $this->projectRepository->getProjectById((int) $data['projectId']);
|
||||
if ($project === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$projectContent = DB::transaction(function () use ($data, $project, $translatedText) {
|
||||
$values = [];
|
||||
$hashes = $this->completionChecker->execute(
|
||||
$this->getHashes($data['hashes']),
|
||||
);
|
||||
|
||||
foreach ($translatedText as $translatedTextKey => $translatedTextValue) {
|
||||
if ($hashes->isStatusWaiting($translatedTextKey) !== true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$translatedTextValue = $this->noTranslateAttributeHandler->handleRemoveAttribute($translatedTextValue);
|
||||
$values[$translatedTextKey] = $translatedTextValue;
|
||||
}
|
||||
if (\count($values) === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$projectContent = $project->contents()->where('language_id', $data['languageId'])->first();
|
||||
if ($projectContent !== null) {
|
||||
$projectContent->update($values);
|
||||
return $projectContent;
|
||||
}
|
||||
|
||||
$values['language_id'] = $data['languageId'];
|
||||
return $project->contents()->create($values);
|
||||
});
|
||||
if (\config('translation_service.enable', false) && $projectContent !== null) {
|
||||
$this->translateContent($project, $projectContent, $data);
|
||||
}
|
||||
}
|
||||
|
||||
private function translateContent(Project $project, ProjectContent $projectContent, array $data): void
|
||||
{
|
||||
$translateExceptLanguages = $data['exceptLanguages'] ?? [];
|
||||
$translateExceptLanguages[] = $data['languageId'];
|
||||
ProcessProjectContent::dispatch($project->id, [$projectContent->id], $translateExceptLanguages);
|
||||
}
|
||||
|
||||
private function getHashes(array $hashes): Hashes
|
||||
{
|
||||
$hashesDto = new Hashes();
|
||||
foreach ($hashes as $field => $hash) {
|
||||
$hashesDto->add((int) $hash['hashId'], $field, $hash['hash']);
|
||||
}
|
||||
return $hashesDto;
|
||||
}
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Translate\Completed\Project;
|
||||
|
||||
use App\Dto\Service\ProjectTranslationServiceTextHash\Hashes;
|
||||
use App\Exceptions\Services\Translate\CompletedException;
|
||||
use App\Jobs\Translate\ProcessTranslationText;
|
||||
use App\Models\Project;
|
||||
use App\Models\ProjectTranslation;
|
||||
use App\Repositories\ProjectRepository;
|
||||
use App\Repositories\ProjectTranslationRepository;
|
||||
use App\Services\ProjectTranslationServiceTextHash\CompletionChecker;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use KorElf\TranslateLaravel\Contracts\TranslationCompletedListener;
|
||||
|
||||
final readonly class TranslationTextService implements TranslationCompletedListener
|
||||
{
|
||||
public function __construct(
|
||||
private ProjectRepository $projectRepository,
|
||||
private CompletionChecker $completionChecker,
|
||||
private ProjectTranslationRepository $projectTranslationRepository,
|
||||
) { }
|
||||
|
||||
/**
|
||||
* @throws CompletedException
|
||||
*/
|
||||
public function onTranslationCompleted(array $translatedText, array $data = []): void
|
||||
{
|
||||
if (
|
||||
!isset($data['projectId'])
|
||||
|| !isset($data['languageId'])
|
||||
|| !isset($data['hashes'])
|
||||
) {
|
||||
throw new CompletedException('Required data is missing: projectId, languageId, or hashes.');
|
||||
}
|
||||
|
||||
$project = $this->projectRepository->getProjectById((int) $data['projectId']);
|
||||
if ($project === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$translations = $this->projectTranslationRepository->getProjectTranslationByCodes($project->id, $data['languageId'], \array_keys($translatedText))->all();
|
||||
|
||||
$translateTextCode = DB::transaction(function () use ($data, $translatedText, $translations) {
|
||||
$translateTextCode = [];
|
||||
$hashes = $this->completionChecker->execute(
|
||||
$this->getHashes($data['hashes']),
|
||||
);
|
||||
|
||||
foreach ($translatedText as $translatedTextKey => $translatedTextValue) {
|
||||
if ($hashes->isStatusWaiting($translatedTextKey) !== true) {
|
||||
continue;
|
||||
}
|
||||
$translateTextCode[] = $translatedTextKey;
|
||||
$translation = $translations->firstWhere('code', $translatedTextKey);
|
||||
if ($translation !== null) {
|
||||
$translation->update([
|
||||
'text' => $translatedTextValue,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
ProjectTranslation::create([
|
||||
'project_id' => (int) $data['projectId'],
|
||||
'language_id' => (int) $data['languageId'],
|
||||
'code' => $translatedTextKey,
|
||||
'text' => $translatedTextValue,
|
||||
]);
|
||||
}
|
||||
|
||||
return $translateTextCode;
|
||||
});
|
||||
|
||||
if (\config('translation_service.enable', false) && !empty($translateTextCode)) {
|
||||
$this->translateContent($project, $translateTextCode, $data);
|
||||
}
|
||||
}
|
||||
|
||||
private function translateContent(Project $project, array $translateTextCode, array $data): void
|
||||
{
|
||||
$translateExceptLanguages = $data['exceptLanguages'] ?? [];
|
||||
$translateExceptLanguages[] = $data['languageId'];
|
||||
ProcessTranslationText::dispatch($project->id, $data['languageId'], $translateTextCode, $translateExceptLanguages);
|
||||
}
|
||||
|
||||
private function getHashes(array $hashes): Hashes
|
||||
{
|
||||
$hashesDto = new Hashes();
|
||||
foreach ($hashes as $code => $hash) {
|
||||
$hashesDto->add((int) $hash['hashId'], $code, $hash['hash']);
|
||||
}
|
||||
return $hashesDto;
|
||||
}
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Translate\Project;
|
||||
|
||||
use App\Dto\Service\ProjectTranslationServiceHash\Fields;
|
||||
use App\Dto\Service\ProjectTranslationServiceHash\TranslateFields;
|
||||
use App\Enums\Morph;
|
||||
use App\Repositories\ProjectRepository;
|
||||
use App\Repositories\ProjectTranslationServiceRepository;
|
||||
use App\ServiceResults\ServiceResultError;
|
||||
use App\ServiceResults\ServiceResultSuccess;
|
||||
use App\Services\ProjectTranslationService\NoTranslateAttributeHandler;
|
||||
use App\Services\ProjectTranslationServiceHash\HashTrackerCommand;
|
||||
use App\Services\Service;
|
||||
use App\Services\Translate\Completed\Project\ProjectContentService as ProjectContentServiceCompleted;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use KorElf\TranslateLaravel\DTO\AfterTranslateDto;
|
||||
use KorElf\TranslateLaravel\Facades\Translate;
|
||||
|
||||
final class ProjectContentService extends Service
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ProjectRepository $projectRepository,
|
||||
private readonly ProjectTranslationServiceRepository $projectTranslationServiceRepository,
|
||||
private readonly HashTrackerCommand $hashTrackerCommand,
|
||||
private readonly NoTranslateAttributeHandler $noTranslateAttributeHandler,
|
||||
) {}
|
||||
|
||||
public function translate(int $projectId, array $contentIds, array $exceptLanguages): ServiceResultSuccess | ServiceResultError
|
||||
{
|
||||
try {
|
||||
$project = $this->projectRepository->getProjectById($projectId);
|
||||
if ($project === null) {
|
||||
return $this->errNotFound(__('Project not found'));
|
||||
}
|
||||
|
||||
$contents = $project->contents()
|
||||
->whereIn('id', $contentIds)
|
||||
->cursor();
|
||||
|
||||
$sourceLanguagesCode = [];
|
||||
foreach ($contents as $content) {
|
||||
if (!isset($sourceLanguagesCode[$content->language_id])) {
|
||||
$sourceLanguagesCode[$content->language_id] = $this->projectTranslationServiceRepository->getLanguageCodeByLanguageId($content->language_id) ?? 'null';
|
||||
}
|
||||
$translateIntoLanguage = $this->projectTranslationServiceRepository
|
||||
->getLanguagesBySourceLanguage($content->language_id, $exceptLanguages)
|
||||
->all()->pluck('code', 'language_id')->toArray();
|
||||
|
||||
if (empty($translateIntoLanguage)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fields = (new Fields())
|
||||
->add('title', $content->title ?? '')
|
||||
->add('description', $content->description ?? '');
|
||||
$translations = DB::transaction(function () use ($content, $translateIntoLanguage, $fields) {
|
||||
return $this->hashTrackerCommand->execute(Morph::ProjectContent, $content->id, \array_keys($translateIntoLanguage), $fields);
|
||||
});
|
||||
/** @var TranslateFields $translations */
|
||||
unset($fields);
|
||||
|
||||
foreach ($translations->getFields() as $languageId => $fields) {
|
||||
$params = new \KorElf\TranslateLaravel\DTO\RunTranslateDto();
|
||||
$sourceLanguageCode = null;
|
||||
if (isset($sourceLanguagesCode[$content->language_id]) && $sourceLanguagesCode[$content->language_id] !== 'null') {
|
||||
$sourceLanguageCode = $sourceLanguagesCode[$content->language_id];
|
||||
}
|
||||
foreach ($fields as $field) {
|
||||
$text = $this->noTranslateAttributeHandler->handleAddAttribute((string) $content->{$field} ?? '');
|
||||
$params->addParamHtml($field, $text, $translateIntoLanguage[$languageId], $sourceLanguageCode);
|
||||
}
|
||||
|
||||
$afterTranslateDto = new AfterTranslateDto(ProjectContentServiceCompleted::class, [
|
||||
'projectId' => $projectId,
|
||||
'languageId' => $languageId,
|
||||
'hashes' => $translations->getHashesByLanguage($languageId),
|
||||
'exceptLanguages' => $exceptLanguages,
|
||||
]);
|
||||
Translate::runJob($params, $afterTranslateDto);
|
||||
unset($params, $afterTranslateDto);
|
||||
}
|
||||
|
||||
unset($translations, $translateIntoLanguage);
|
||||
}
|
||||
unset($contents, $documentation);
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
\report($e);
|
||||
return $this->errService($e->getMessage());
|
||||
}
|
||||
|
||||
return $this->ok();
|
||||
}
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Translate\Project;
|
||||
|
||||
use App\Dto\Service\ProjectTranslationServiceTextHash\Codes;
|
||||
use App\Dto\Service\ProjectTranslationServiceTextHash\TranslateCodes;
|
||||
use App\Repositories\ProjectRepository;
|
||||
use App\Repositories\ProjectTranslationServiceRepository;
|
||||
use App\ServiceResults\ServiceResultError;
|
||||
use App\ServiceResults\ServiceResultSuccess;
|
||||
use App\Services\ProjectTranslation\TranslationText;
|
||||
use App\Services\ProjectTranslation\TranslationTextCommand;
|
||||
use App\Services\ProjectTranslationServiceTextHash\HashTrackerCommand;
|
||||
use App\Services\Translate\Completed\Project\TranslationTextService as TranslationTextServiceCompleted;
|
||||
use App\Services\Service;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use KorElf\TranslateLaravel\DTO\AfterTranslateDto;
|
||||
use KorElf\TranslateLaravel\Facades\Translate;
|
||||
|
||||
final class TranslationTextService extends Service
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ProjectRepository $projectRepository,
|
||||
private readonly TranslationTextCommand $translationTextCommand,
|
||||
private readonly ProjectTranslationServiceRepository $projectTranslationServiceRepository,
|
||||
private readonly HashTrackerCommand $hashTrackerCommand,
|
||||
) { }
|
||||
|
||||
public function translate(int $projectId, int $languageId, array $translateTextCode, array $exceptLanguages): ServiceResultSuccess | ServiceResultError
|
||||
{
|
||||
try {
|
||||
$project = $this->projectRepository->getProjectById($projectId);
|
||||
if ($project === null) {
|
||||
return $this->errNotFound(__('Project not found'));
|
||||
}
|
||||
$language = $project->languages()->firstWhere('id', $languageId);
|
||||
if ($language === null) {
|
||||
return $this->errNotFound(__('Language not found'));
|
||||
}
|
||||
|
||||
$translateIntoLanguage = $this->projectTranslationServiceRepository
|
||||
->getLanguagesBySourceLanguage($languageId, $exceptLanguages)
|
||||
->all()->pluck('code', 'language_id')->toArray();
|
||||
|
||||
if (empty($translateIntoLanguage)) {
|
||||
return $this->ok();
|
||||
}
|
||||
|
||||
$translationText = $this->translationTextCommand->execute($project, $language, $translateTextCode);
|
||||
$codes = $this->getCodes($translationText, $translateTextCode);
|
||||
$translations = DB::transaction(function () use ($translateIntoLanguage, $codes) {
|
||||
return $this->hashTrackerCommand->execute(\array_keys($translateIntoLanguage), $codes);
|
||||
});
|
||||
/** @var TranslateCodes $translations */
|
||||
unset($codes);
|
||||
|
||||
$sourceLanguageCode = $this->projectTranslationServiceRepository->getLanguageCodeByLanguageId($language->id);
|
||||
foreach ($translations->getCodes() as $currentLanguageId => $codes) {
|
||||
$params = new \KorElf\TranslateLaravel\DTO\RunTranslateDto();
|
||||
foreach ($codes as $code) {
|
||||
$text = $translationText->translate($code);
|
||||
$params->addParamHtml($code, $text, $translateIntoLanguage[$currentLanguageId], $sourceLanguageCode);
|
||||
}
|
||||
|
||||
$afterTranslateDto = new AfterTranslateDto(TranslationTextServiceCompleted::class, [
|
||||
'projectId' => $projectId,
|
||||
'languageId' => $currentLanguageId,
|
||||
'hashes' => $translations->getHashesByLanguage($currentLanguageId),
|
||||
'exceptLanguages' => $exceptLanguages,
|
||||
]);
|
||||
Translate::runJob($params, $afterTranslateDto);
|
||||
unset($params, $afterTranslateDto);
|
||||
}
|
||||
|
||||
unset($translations, $translateIntoLanguage, $project, $language, $translationText, $sourceLanguageCode);
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
\report($e);
|
||||
return $this->errService($e->getMessage());
|
||||
}
|
||||
|
||||
return $this->ok();
|
||||
}
|
||||
|
||||
private function getCodes(TranslationText $translationText, array $translateTextCode): Codes
|
||||
{
|
||||
$codes = new Codes();
|
||||
foreach ($translateTextCode as $code) {
|
||||
$codes->add($code, $translationText->translate($code));
|
||||
}
|
||||
|
||||
return $codes;
|
||||
}
|
||||
}
|
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace app\View\Components\Site;
|
||||
|
||||
use App\Enums\CacheTag;
|
||||
use App\Models\Project;
|
||||
use App\Services\WebsiteTranslations;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\View\Component;
|
||||
use Illuminate\View\View;
|
||||
@@ -24,7 +24,7 @@ final class ChooseLanguage extends Component
|
||||
}
|
||||
|
||||
$seconds = 3600 * 12;
|
||||
$languages = CacheTag::Project->getCache()->remember(self::class . $this->project->id, $seconds, function () {
|
||||
$languages = Cache::remember(self::class . $this->project->id, $seconds, function () {
|
||||
return $this->project->languages;
|
||||
});
|
||||
|
||||
|
@@ -2,13 +2,12 @@
|
||||
|
||||
namespace App\View\Components\Site;
|
||||
|
||||
use App\Enums\CacheTag;
|
||||
use App\Models\DocumentationVersion;
|
||||
use App\Models\Project;
|
||||
use App\Models\User;
|
||||
use App\Services\WebsiteTranslations;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\View\Component;
|
||||
use Illuminate\View\View;
|
||||
|
||||
@@ -29,8 +28,7 @@ final class ChooseVersion extends Component
|
||||
}
|
||||
|
||||
$seconds = 3600 * 12;
|
||||
$versions = CacheTag::DocumantationVersion->getCache()
|
||||
->remember(self::class . $this->project->id . '-' . $isPublic ?? 0, $seconds, function () use ($isPublic) {
|
||||
$versions = Cache::remember(self::class . $this->project->id . '-' . $isPublic ?? 0, $seconds, function () use ($isPublic) {
|
||||
return $this->project->documentationVersions()
|
||||
->when($isPublic, function (Builder $query) {
|
||||
$query->where('is_public', 1);
|
||||
|
@@ -4,6 +4,7 @@ use Illuminate\Foundation\Application;
|
||||
use Illuminate\Foundation\Configuration\Exceptions;
|
||||
use Illuminate\Foundation\Configuration\Middleware;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
return Application::configure(basePath: dirname(__DIR__))
|
||||
->withRouting(
|
||||
@@ -19,8 +20,15 @@ return Application::configure(basePath: dirname(__DIR__))
|
||||
},
|
||||
)
|
||||
->withMiddleware(function (Middleware $middleware) {
|
||||
//
|
||||
|
||||
})
|
||||
->withExceptions(function (Exceptions $exceptions) {
|
||||
//
|
||||
$exceptions->respond(function (Response $response) {
|
||||
if ($response->getStatusCode() === 419) {
|
||||
return back()
|
||||
->withInput()
|
||||
->withErrors(['csrf' => __('http-statuses.csrfError')]);
|
||||
}
|
||||
return $response;
|
||||
});
|
||||
})->create();
|
||||
|
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('project_translation_service_text_hashes', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('code');
|
||||
$table->unsignedBigInteger('language_id')->index();
|
||||
$table->foreign('language_id')->references('id')->on('project_languages');
|
||||
$table->unsignedInteger('status')->index()->default(0);
|
||||
$table->char('hash', 64);
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['language_id', 'code'], 'unique_language_code');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('project_translation_service_text_hashes');
|
||||
}
|
||||
};
|
@@ -81,4 +81,5 @@ return [
|
||||
'598' => 'Network Read Timeout Error',
|
||||
'599' => 'Network Connect Timeout Error',
|
||||
'unknownError' => 'Unknown Error',
|
||||
'csrfError' => 'It looks like your session has expired. Please try again.',
|
||||
];
|
||||
|
@@ -310,6 +310,7 @@ return [
|
||||
'content_images' => 'content images',
|
||||
'source_language_id' => 'source language identifier',
|
||||
'translate_from_language' => 'translate from language',
|
||||
'translate-automatically' => 'translate automatically',
|
||||
'translate-automatically.*' => 'translate automatically',
|
||||
],
|
||||
];
|
||||
|
@@ -81,4 +81,5 @@ return [
|
||||
'598' => 'Истекло время ожидания',
|
||||
'599' => 'Истекло время подключения',
|
||||
'unknownError' => 'Неизвестная ошибка',
|
||||
'csrfError' => 'Похоже, что срок действия Вашей сессии истек. Пожалуйста, попробуйте еще раз.',
|
||||
];
|
||||
|
@@ -310,6 +310,7 @@ return [
|
||||
'content_images' => 'изображения контента',
|
||||
'source_language_id' => 'идентификатор исходного языка',
|
||||
'translate_from_language' => 'перевести с языка',
|
||||
'translate-automatically' => 'переводить автоматически',
|
||||
'translate-automatically.*' => 'переводить автоматически',
|
||||
],
|
||||
];
|
||||
|
@@ -1,4 +1,9 @@
|
||||
@csrf
|
||||
@if($serviceTranslationEnable)
|
||||
<x-volt.forms.checkbox :title="__('Automatic translation')" name="translate-automatically"
|
||||
:user-value="1" class="language-content" checkbox-value="1"
|
||||
not-checked-value="0"/>
|
||||
@endif
|
||||
<x-volt.forms.input :title="__('validation.attributes.title')" name="title" type="text" :value="$content->title" required autofocus />
|
||||
<x-volt.forms.textarea-wysiwyg
|
||||
:title="__('validation.attributes.description')"
|
||||
|
@@ -8,6 +8,11 @@
|
||||
<h3 id="category" class="mb-4">{{ __('admin-sections.Translations') }}</h3>
|
||||
<div class="table-responsive">
|
||||
<form method="post" action="{{ route('admin.projects.translations.update', ['project' => $project->id, 'language' => $language->id]) }}">
|
||||
@if($serviceTranslationEnable)
|
||||
<x-volt.forms.checkbox :title="__('Automatic translation')" name="translate-automatically"
|
||||
:user-value="1" class="language-content" checkbox-value="1"
|
||||
not-checked-value="0"/><br>
|
||||
@endif
|
||||
<table class="table table-centered table-nowrap mb-0 rounded">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
|
@@ -39,9 +39,9 @@
|
||||
<nav id="menu">
|
||||
<div class="menu__title">{{ $websiteTranslations->translate('site.Menu') }}</div>
|
||||
<ul>
|
||||
<li><a href="{{ \App\Enums\Site\ProjectSection::Home->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['home', 'language.home', 'project.home', 'project.language.home'])])>{{ $websiteTranslations->translate('site.About project') }}</a></li>
|
||||
<li><a href="{{ \App\Enums\Site\ProjectSection::Documentation->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['documentation', 'documentation.home'])])>{{ $websiteTranslations->translate('site.Documentation') }}</a></li>
|
||||
<li><a href="{{ \App\Enums\Site\ProjectSection::Feedback->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['feedback', 'language.feedback', 'project.feedback', 'project.language.feedback'])])>{{ $websiteTranslations->translate('site.Feedback') }}</a></li>
|
||||
<li><a href="{{ \App\Enums\Site\ProjectSection::Home->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['home', 'language.home', 'project.home', 'project.language.home', 'home-language'])])>{{ $websiteTranslations->translate('site.About project') }}</a></li>
|
||||
<li><a href="{{ \App\Enums\Site\ProjectSection::Documentation->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['documentation.*'])])>{{ $websiteTranslations->translate('site.Documentation') }}</a></li>
|
||||
<li><a href="{{ \App\Enums\Site\ProjectSection::Feedback->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['feedback', 'language.feedback', 'project.feedback', 'project.language.feedback', 'feedback-language'])])>{{ $websiteTranslations->translate('site.Feedback') }}</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="section-container">
|
||||
|
@@ -19,7 +19,7 @@ COPY --from=unit_builder /var/lib/unit/ /var/lib/unit/
|
||||
|
||||
COPY docker/unit-config.json /docker-entrypoint.d/config.json
|
||||
|
||||
RUN apk --no-cache add pcre2 libbz2 libpng libwebp libjpeg-turbo icu-libs freetype oniguruma libzip \
|
||||
RUN apk --no-cache add pcre2 libbz2 libpng libwebp libjpeg-turbo icu-libs freetype oniguruma libzip jq \
|
||||
&& apk add --no-cache --virtual .phpize-deps icu-dev libpng-dev bzip2-dev libwebp-dev libjpeg-turbo-dev freetype-dev oniguruma-dev libzip-dev pcre2-dev ${PHPIZE_DEPS} \
|
||||
&& docker-php-ext-configure intl --enable-intl && \
|
||||
docker-php-ext-configure bcmath --enable-bcmath && \
|
||||
|
@@ -42,6 +42,20 @@ if [ "$role" = "app" ]; then
|
||||
if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -print -quit 2>/dev/null | /bin/grep -q .; then
|
||||
echo "$0: /docker-entrypoint.d/ is not empty, applying initial configuration..."
|
||||
|
||||
if [[ -n "${UNIT_SOURCE:-}" ]]; then
|
||||
config="/docker-entrypoint.d/config.json"
|
||||
tmp="$(mktemp)"
|
||||
jq --arg src "${UNIT_SOURCE}" '
|
||||
.listeners["*:9000"].forwarded.source =
|
||||
( $src
|
||||
| split(",")
|
||||
| map( gsub("^\\s+|\\s+$"; "") ) # trim пробелы
|
||||
| map( select(. != "") ) # убрать пустые
|
||||
)
|
||||
' "$config" > "$tmp"
|
||||
mv "$tmp" "$config"
|
||||
fi
|
||||
|
||||
echo "$0: Looking for certificate bundles in /docker-entrypoint.d/..."
|
||||
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.pem"); do
|
||||
echo "$0: Uploading certificates bundle: $f"
|
||||
@@ -60,12 +74,6 @@ if [ "$role" = "app" ]; then
|
||||
curl_put $f "config"
|
||||
done
|
||||
|
||||
if [ ! -z ${UNIT_SOURCE+x} ]
|
||||
then
|
||||
echo $UNIT_SOURCE > /docker-entrypoint.d/unit_source.json
|
||||
curl_put "/docker-entrypoint.d/unit_source.json" "config/listeners/*:9000/forwarded/source"
|
||||
fi
|
||||
|
||||
echo "$0: Looking for shell scripts in /docker-entrypoint.d/..."
|
||||
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.sh"); do
|
||||
echo "$0: Launching $f";
|
||||
|
@@ -42,6 +42,20 @@ if [ "$role" = "app" ]; then
|
||||
if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -print -quit 2>/dev/null | /bin/grep -q .; then
|
||||
echo "$0: /docker-entrypoint.d/ is not empty, applying initial configuration..."
|
||||
|
||||
if [[ -n "${UNIT_SOURCE:-}" ]]; then
|
||||
config="/docker-entrypoint.d/config.json"
|
||||
tmp="$(mktemp)"
|
||||
jq --arg src "${UNIT_SOURCE}" '
|
||||
.listeners["*:9000"].forwarded.source =
|
||||
( $src
|
||||
| split(",")
|
||||
| map( gsub("^\\s+|\\s+$"; "") ) # trim пробелы
|
||||
| map( select(. != "") ) # убрать пустые
|
||||
)
|
||||
' "$config" > "$tmp"
|
||||
mv "$tmp" "$config"
|
||||
fi
|
||||
|
||||
echo "$0: Looking for certificate bundles in /docker-entrypoint.d/..."
|
||||
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.pem"); do
|
||||
echo "$0: Uploading certificates bundle: $f"
|
||||
@@ -60,12 +74,6 @@ if [ "$role" = "app" ]; then
|
||||
curl_put $f "config"
|
||||
done
|
||||
|
||||
if [ ! -z ${UNIT_SOURCE+x} ]
|
||||
then
|
||||
echo $UNIT_SOURCE > /docker-entrypoint.d/unit_source.json
|
||||
curl_put "/docker-entrypoint.d/unit_source.json" "config/listeners/*:9000/forwarded/source"
|
||||
fi
|
||||
|
||||
echo "$0: Looking for shell scripts in /docker-entrypoint.d/..."
|
||||
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.sh"); do
|
||||
echo "$0: Launching $f";
|
||||
|
@@ -1,4 +1,4 @@
|
||||
version: '3.7'
|
||||
#version: '3.7'
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
@@ -16,7 +16,7 @@ services:
|
||||
- ./app/application:/var/www/html
|
||||
environment:
|
||||
CONTAINER_ROLE: app
|
||||
UNIT_SOURCE: '"172.16.0.0/12"'
|
||||
UNIT_SOURCE: "172.16.0.0/12"
|
||||
|
||||
queue:
|
||||
build:
|
||||
|
@@ -1,8 +1,8 @@
|
||||
version: '3.7'
|
||||
#version: '3.7'
|
||||
services:
|
||||
app:
|
||||
# image: korelf/my-projects-website:0.3.1 # docker hub
|
||||
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.3.1 # MDHub
|
||||
# image: korelf/my-projects-website:0.5.0 # docker hub
|
||||
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.5.0 # MDHub
|
||||
# restart: always
|
||||
depends_on:
|
||||
- db
|
||||
@@ -13,15 +13,15 @@ services:
|
||||
env_file: app/.env
|
||||
environment:
|
||||
CONTAINER_ROLE: app
|
||||
UNIT_SOURCE: '"172.16.0.0/12"'
|
||||
UNIT_SOURCE: "172.16.0.0/12"
|
||||
volumes:
|
||||
- ./app/storage/app:/var/www/html/storage/app
|
||||
- ./app/storage/logs:/var/www/html/storage/logs
|
||||
# - ./app/translate/authorized_key.json:/var/www/html/storage/translation_service/authorized_key.json
|
||||
|
||||
queue:
|
||||
# image: korelf/my-projects-website:0.3.1 # docker hub
|
||||
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.3.1 # MDHub
|
||||
# image: korelf/my-projects-website:0.5.0 # docker hub
|
||||
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.5.0 # MDHub
|
||||
# restart: always
|
||||
depends_on:
|
||||
- db
|
||||
@@ -35,8 +35,8 @@ services:
|
||||
# - ./app/translate/authorized_key.json:/var/www/html/storage/translation_service/authorized_key.json
|
||||
|
||||
scheduler:
|
||||
# image: korelf/my-projects-website:0.3.1 # docker hub
|
||||
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.3.1 # MDHub
|
||||
# image: korelf/my-projects-website:0.5.0 # docker hub
|
||||
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.5.0 # MDHub
|
||||
# restart: always
|
||||
depends_on:
|
||||
- db
|
||||
|
@@ -1,4 +1,4 @@
|
||||
version: '3.7'
|
||||
#version: '3.7'
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
@@ -13,6 +13,8 @@ services:
|
||||
- ${DOCKER_APP_PORT}:9000
|
||||
volumes:
|
||||
- ./app/application:/var/www/html
|
||||
environment:
|
||||
CONTAINER_ROLE: app
|
||||
|
||||
queue:
|
||||
build:
|
||||
|
Reference in New Issue
Block a user