Skip to content

Commit

Permalink
Translate attributes of one produt at once. Refactor translation process
Browse files Browse the repository at this point in the history
  • Loading branch information
drejmanMacopedia committed Jun 5, 2023
1 parent 085a68b commit ddb011e
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public function process(mixed $item): ProductInterface|ProductModelInterface
*/
private function translateAttributes(mixed $product, array $action): ProductInterface|ProductModelInterface
{
return $this->translateAttributesService->translateAttributes($product, $action);
return $this->translateAttributesService
->setStepExecution($this->stepExecution)
->translateAttributes($product, $action);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ final class MacopediaTranslatorExtension extends Extension
public function load(array $configs, ContainerBuilder $container): void
{
$loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('connector.yml');
$loader->load('services.yml');
$loader->load('connector.yml');
$loader->load('repositories.yml');
}
}
20 changes: 20 additions & 0 deletions src/Macopedia/OpenAiTranslator/Repository/AttributeRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Macopedia\OpenAiTranslator\Repository;

use Akeneo\Pim\Structure\Bundle\Doctrine\ORM\Repository\AttributeRepository as BaseAttributeRepository;

class AttributeRepository extends BaseAttributeRepository
{
public function getAttributesByCodes(array $codes): array
{
return $this->_em->createQueryBuilder()
->select('att')
->from($this->_entityName, 'att', 'att.code')
->where('att.code IN (:codes)')->setParameter('codes', $codes)
->getQuery()
->getResult();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ services:
macopedia.step.update_product_translations.mass_edit:
class: '%pim_connector.step.item_step.class%'
arguments:
- 'perform'
- 'translate'
- '@event_dispatcher'
- '@akeneo_batch.job_repository'
- '@pim_enrich.reader.database.product_and_product_model'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
services:
Macopedia\OpenAiTranslator\Repository\AttributeRepository:
factory: [ '@doctrine.orm.entity_manager', 'getRepository' ]
arguments: [ '%pim_catalog.entity.attribute.class%' ]
tags:
- { name: 'pim_repository' }
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ services:
Macopedia\OpenAiTranslator\Service\TranslateAttributesService:
arguments:
- '@Macopedia\OpenAiTranslator\Translator\OpenAiTranslator'
- '@pim_catalog.repository.attribute'
- '@Macopedia\OpenAiTranslator\Repository\AttributeRepository'
- '@pim_catalog.entity_with_family_variant.check_attribute_editable'
- '@pim_catalog.updater.property_setter'
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@
use Akeneo\Pim\Enrichment\Component\Product\EntityWithFamilyVariant\CheckAttributeEditable;
use Akeneo\Pim\Enrichment\Component\Product\Model\ProductInterface;
use Akeneo\Pim\Enrichment\Component\Product\Model\ProductModelInterface;
use Akeneo\Pim\Enrichment\Component\Product\Value\ScalarValue;
use Akeneo\Pim\Structure\Component\AttributeTypes;
use Akeneo\Pim\Structure\Component\Repository\AttributeRepositoryInterface;
use Akeneo\Tool\Component\Batch\Item\DataInvalidItem;
use Akeneo\Tool\Component\Batch\Job\BatchStatus;
use Akeneo\Tool\Component\Batch\Job\ExitStatus;
use Akeneo\Tool\Component\Batch\Model\StepExecution;
use Akeneo\Tool\Component\StorageUtils\Updater\PropertySetterInterface;
use Macopedia\OpenAiTranslator\Translator\Language;
use Macopedia\OpenAiTranslator\Translator\TranslatorInterface;
use Macopedia\OpenAiTranslator\Exception\InvalidOpenAiResponseException;
use Webmozart\Assert\Assert;

class TranslateAttributesService
{
private StepExecution $stepExecution;

public function __construct(
private TranslatorInterface $translator,
private AttributeRepositoryInterface $attributeRepository,
Expand All @@ -25,21 +31,38 @@ public function __construct(
) {
}

public function setStepExecution(StepExecution $stepExecution): self
{
$this->stepExecution = $stepExecution;

return $this;
}

/**
* @param ProductInterface|ProductModelInterface $product
* @param array<string, string|array<int, string>> $action
*/
public function translateAttributes(mixed $product, array $action): ProductInterface|ProductModelInterface
{
[$sourceScope, $targetScope, $sourceLocaleAkeneo, $targetLocaleAkeneo, $targetLocale, $attributesToTranslate] = $this->extractVariables($action);
$translations = [];

$attributes = $this->attributeRepository->getAttributesByCodes($attributesToTranslate);
$summary = [];
$scopes = [];

foreach ($attributesToTranslate as $attributeCode) {
$attribute = $this->attributeRepository->findOneByIdentifier($attributeCode);
foreach ($attributes as $attribute) {
if (!$this->checkAttributeEditable->isEditable($product, $attribute)) {
$this->stepExecution->addWarning('Attribute is not editable', [], new DataInvalidItem($attribute));
$this->stepExecution->incrementSummaryInfo('skip');
$this->stepExecution->incrementProcessedItems();
continue;
}

if (!($attribute->getType() === AttributeTypes::TEXT || $attribute->getType() === AttributeTypes::TEXTAREA)) {
$this->stepExecution->addWarning('Attribute is not text', [], new DataInvalidItem($attribute));
$this->stepExecution->incrementSummaryInfo('skip');
$this->stepExecution->incrementProcessedItems();
continue;
}

Expand All @@ -48,26 +71,38 @@ public function translateAttributes(mixed $product, array $action): ProductInter
$targetScope = null;
}

$attributeCode = $attribute->getCode();
$attributeValue = $product->getValue($attributeCode, $sourceLocaleAkeneo, $sourceScope);
if ($attributeValue === null) {
$this->stepExecution->addWarning('Attribute value is empty', [], new DataInvalidItem($attribute));
$this->stepExecution->incrementSummaryInfo('skip');
$this->stepExecution->incrementProcessedItems();
continue;
}

$translatedText = $this->translator->translate(
$attributeValue->getData(),
$targetLocale
);
$translations[$attributeCode] = $attributeValue->getData();
$scopes[$attributeCode] = $targetScope;
}

if ($translatedText === null) {
continue;
}
$translatedText = $this->translator->translate(
json_encode($translations),
$targetLocale
);

$this->propertySetter->setData($product, $attributeCode, $translatedText, [
if ($translatedText === null) {
throw new InvalidOpenAiResponseException($translations);
}

foreach (json_decode($translatedText) as $key => $translation) {
$summary[$key] = [[$translations[$key] => $translation]];
$this->propertySetter->setData($product, $key, $translation, [
'locale' => $targetLocaleAkeneo,
'scope' => $targetScope,
'scope' => $scopes[$key],
]);
}

$this->stepExecution->setExitStatus(new ExitStatus(ExitStatus::COMPLETED, json_encode($summary)));

return $product;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

class OpenAiTranslator implements TranslatorInterface
{
private const MESSAGE = 'Translate text betweeen <START> and <STOP> to %s. Keep HTMl unchanged. <START>%s<STOP>';
private const MESSAGE = 'Translate all values of given JSON betweeen <START> and <STOP> to %s. Keep HTML unchanged. Return valid JSON. <START>%s<STOP>';

public function __construct(
private OpenAiClient $openAiClient
Expand Down

0 comments on commit ddb011e

Please sign in to comment.