Skip to content

Commit c888183

Browse files
committed
[TASK] Respect rte allow tags in translate request
With this change the RTE configuration is determined from the field to be translated. To give deepl a list of allowed HTML tags. To allow a correct separation in the translated text with HTML tag.
1 parent ffbcc23 commit c888183

File tree

13 files changed

+379
-74
lines changed

13 files changed

+379
-74
lines changed

Classes/Client.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Psr\Http\Message\ResponseInterface;
88
use TYPO3\CMS\Core\Http\RequestFactory;
99
use TYPO3\CMS\Core\Utility\GeneralUtility;
10+
use WebVision\WvDeepltranslate\Domain\Dto\TranslateOptions;
1011
use WebVision\WvDeepltranslate\Exception\ClientNotValidUrlException;
1112

1213
final class Client
@@ -31,15 +32,15 @@ public function __construct()
3132
$this->requestFactory = GeneralUtility::makeInstance(RequestFactory::class);
3233
}
3334

34-
public function translate(string $content, string $sourceLang, string $targetLang, string $glossary = ''): ResponseInterface
35-
{
35+
public function translate(
36+
string $content,
37+
TranslateOptions $options,
38+
string $glossary = ''
39+
): ResponseInterface {
3640
$baseUrl = $this->buildBaseUrl('translate');
3741

3842
$postFields = [
3943
'text' => $content,
40-
'source_lang' => $sourceLang,
41-
'target_lang' => $targetLang,
42-
'tag_handling' => 'xml',
4344
];
4445

4546
if (!empty($glossary)) {
@@ -48,6 +49,8 @@ public function translate(string $content, string $sourceLang, string $targetLan
4849

4950
$postFields['formality'] = $this->configuration->getFormality();
5051

52+
$postFields = array_merge($postFields, $options->toArray());
53+
5154
return $this->requestFactory->request($baseUrl, 'POST', $this->mergeRequiredRequestOptions([
5255
'form_params' => $postFields,
5356
]));
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WebVision\WvDeepltranslate\Domain\Dto;
6+
7+
/**
8+
* @internal
9+
*/
10+
final class TranslateOptions
11+
{
12+
protected string $splitSentences = 'nonewlines';
13+
14+
protected bool $outlineDetection = false;
15+
16+
protected array $splittingTags = [];
17+
18+
protected array $nonSplittingTags = [];
19+
20+
protected array $ignoreTags = [];
21+
22+
protected string $tagHandling = 'xml';
23+
24+
protected string $targetLanguage;
25+
26+
protected string $sourceLanguage;
27+
28+
public function getSplitSentences(): string
29+
{
30+
return $this->splitSentences;
31+
}
32+
33+
public function setSplitSentences(string $splitSentences): void
34+
{
35+
$this->splitSentences = $splitSentences;
36+
}
37+
38+
public function isOutlineDetection(): bool
39+
{
40+
return $this->outlineDetection;
41+
}
42+
43+
public function setOutlineDetection(bool $outlineDetection): void
44+
{
45+
$this->outlineDetection = $outlineDetection;
46+
}
47+
48+
public function getSplittingTags(): array
49+
{
50+
return $this->splittingTags;
51+
}
52+
53+
public function setSplittingTags(array $splittingTags): void
54+
{
55+
$this->splittingTags = $splittingTags;
56+
}
57+
58+
public function getNonSplittingTags(): array
59+
{
60+
return $this->nonSplittingTags;
61+
}
62+
63+
public function setNonSplittingTags(array $nonSplittingTags): void
64+
{
65+
$this->nonSplittingTags = $nonSplittingTags;
66+
}
67+
68+
public function getIgnoreTags(): array
69+
{
70+
return $this->ignoreTags;
71+
}
72+
73+
public function setIgnoreTags(array $ignoreTags): void
74+
{
75+
$this->ignoreTags = $ignoreTags;
76+
}
77+
78+
public function getTagHandling(): string
79+
{
80+
return $this->tagHandling;
81+
}
82+
83+
public function setTagHandling(string $tagHandling): void
84+
{
85+
$this->tagHandling = $tagHandling;
86+
}
87+
88+
public function getTargetLanguage(): string
89+
{
90+
return $this->targetLanguage;
91+
}
92+
93+
public function setTargetLanguage(string $targetLanguage): void
94+
{
95+
$this->targetLanguage = $targetLanguage;
96+
}
97+
98+
public function getSourceLanguage(): string
99+
{
100+
return $this->sourceLanguage;
101+
}
102+
103+
public function setSourceLanguage(string $sourceLanguage): void
104+
{
105+
$this->sourceLanguage = $sourceLanguage;
106+
}
107+
108+
public function toArray(): array
109+
{
110+
$param = [];
111+
$param['tag_handling'] = $this->tagHandling;
112+
113+
if (!empty($this->splittingTags)) {
114+
$param['outlineDetection'] = $this->outlineDetection;
115+
$param['split_sentences'] = $this->splitSentences;
116+
$param['splitting_tags'] = implode(',', $this->splittingTags);
117+
}
118+
119+
$param['source_lang'] = $this->sourceLanguage;
120+
$param['target_lang'] = $this->targetLanguage;
121+
122+
return $param;
123+
}
124+
}

Classes/Hooks/TranslateHook.php

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
use TYPO3\CMS\Core\Messaging\FlashMessage;
99
use TYPO3\CMS\Core\Messaging\FlashMessageService;
1010
use TYPO3\CMS\Core\Utility\GeneralUtility;
11-
use TYPO3\CMS\Extbase\Object\ObjectManager;
11+
use WebVision\WvDeepltranslate\Domain\Dto\TranslateOptions;
1212
use WebVision\WvDeepltranslate\Domain\Repository\PageRepository;
13-
use WebVision\WvDeepltranslate\Domain\Repository\SettingsRepository;
1413
use WebVision\WvDeepltranslate\Exception\LanguageIsoCodeNotFoundException;
1514
use WebVision\WvDeepltranslate\Exception\LanguageRecordNotFoundException;
15+
use WebVision\WvDeepltranslate\Resolver\RichtextAllowTagsResolver;
1616
use WebVision\WvDeepltranslate\Service\DeeplService;
1717
use WebVision\WvDeepltranslate\Service\GoogleTranslateService;
1818
use WebVision\WvDeepltranslate\Service\LanguageService;
@@ -24,31 +24,31 @@ class TranslateHook
2424

2525
protected GoogleTranslateService $googleService;
2626

27-
protected SettingsRepository $deeplSettingsRepository;
28-
2927
protected PageRepository $pageRepository;
3028

3129
private LanguageService $languageService;
3230

3331
public function __construct(
34-
?SettingsRepository $settingsRepository = null,
3532
?PageRepository $pageRepository = null,
3633
?DeeplService $deeplService = null,
37-
?GoogleTranslateService $googleService = null
34+
?GoogleTranslateService $googleService = null,
35+
?LanguageService $languageService = null
3836
) {
39-
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
40-
$this->deeplSettingsRepository = $settingsRepository ?? $objectManager->get(SettingsRepository::class);
41-
$this->deeplService = $deeplService ?? $objectManager->get(DeeplService::class);
42-
$this->googleService = $googleService ?? $objectManager->get(GoogleTranslateService::class);
37+
$this->deeplService = $deeplService ?? GeneralUtility::makeInstance(DeeplService::class);
4338
$this->pageRepository = $pageRepository ?? GeneralUtility::makeInstance(PageRepository::class);
44-
$this->languageService = GeneralUtility::makeInstance(LanguageService::class);
39+
$this->languageService = $languageService ?? GeneralUtility::makeInstance(LanguageService::class);
40+
$this->googleService = $googleService ?? GeneralUtility::makeInstance(GoogleTranslateService::class);
4541
}
4642

4743
/**
4844
* @param array{uid: int} $languageRecord
4945
*/
50-
public function processTranslateTo_copyAction(string &$content, array $languageRecord, DataHandler $dataHandler): string
51-
{
46+
public function processTranslateTo_copyAction(
47+
string &$content,
48+
array $languageRecord,
49+
DataHandler $dataHandler,
50+
string $columnName
51+
): string {
5252
$tableName = '';
5353
$currentRecordId = '';
5454

@@ -62,12 +62,7 @@ public function processTranslateTo_copyAction(string &$content, array $languageR
6262
break;
6363
}
6464

65-
if (!isset($cmdmap['localization']['custom']['srcLanguageId'])) {
66-
$cmdmap['localization']['custom']['srcLanguageId'] = '';
67-
}
68-
6965
$customMode = $cmdmap['localization']['custom']['mode'] ?? null;
70-
[$sourceLanguage,] = explode('-', (string)$cmdmap['localization']['custom']['srcLanguageId']);
7166

7267
//translation mode set to deepl or google translate
7368
if ($customMode === null) {
@@ -79,21 +74,28 @@ public function processTranslateTo_copyAction(string &$content, array $languageR
7974
$translatedContent = '';
8075
$targetLanguageRecord = [];
8176

77+
$translateOptions = GeneralUtility::makeInstance(TranslateOptions::class);
78+
$richtextAllowTagsResolver = GeneralUtility::makeInstance(RichtextAllowTagsResolver::class);
79+
$translateOptions->setSplittingTags(
80+
$richtextAllowTagsResolver->resolve($tableName, $currentRecordId, $columnName)
81+
);
82+
8283
try {
8384
$sourceLanguageRecord = $this->languageService->getSourceLanguage(
8485
$siteInformation['site']
8586
);
87+
$translateOptions->setSourceLanguage($sourceLanguageRecord['language_isocode']);
8688

8789
$targetLanguageRecord = $this->languageService->getTargetLanguage(
8890
$siteInformation['site'],
8991
(int)$languageRecord['uid']
9092
);
93+
$translateOptions->setTargetLanguage($targetLanguageRecord['language_isocode']);
9194

9295
$translatedContent = $this->translateContent(
9396
$content,
94-
$targetLanguageRecord,
97+
$translateOptions,
9598
$customMode,
96-
$sourceLanguageRecord
9799
);
98100
} catch (LanguageIsoCodeNotFoundException|LanguageRecordNotFoundException $e) {
99101
$flashMessage = GeneralUtility::makeInstance(
@@ -123,22 +125,17 @@ public function processTranslateTo_copyAction(string &$content, array $languageR
123125

124126
/**
125127
* These logics were outsourced to test them and later to resolve them in a service
126-
*
127-
* @param array{uid: int, language_isocode: string} $targetLanguageRecord
128-
* @param array{uid: int, language_isocode: string} $sourceLanguageRecord
129128
*/
130129
public function translateContent(
131130
string $content,
132-
array $targetLanguageRecord,
133-
string $customMode,
134-
array $sourceLanguageRecord
131+
TranslateOptions $translateOptions,
132+
string $customMode
135133
): string {
136134
// mode deepl
137135
if ($customMode == 'deepl') {
138136
$response = $this->deeplService->translateRequest(
139137
$content,
140-
$targetLanguageRecord['language_isocode'],
141-
$sourceLanguageRecord['language_isocode']
138+
$translateOptions
142139
);
143140

144141
if (!empty($response) && isset($response['translations'])) {
@@ -152,8 +149,8 @@ public function translateContent(
152149
} //mode google
153150
elseif ($customMode == 'google') {
154151
$response = $this->googleService->translate(
155-
$sourceLanguageRecord['language_isocode'],
156-
$targetLanguageRecord['language_isocode'],
152+
$translateOptions->getSourceLanguage(),
153+
$translateOptions->getTargetLanguage(),
157154
$content
158155
);
159156

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WebVision\WvDeepltranslate\Resolver;
6+
7+
use TYPO3\CMS\Backend\Utility\BackendUtility;
8+
use TYPO3\CMS\Core\Configuration\Richtext;
9+
use TYPO3\CMS\Core\Utility\GeneralUtility;
10+
11+
final class RichtextAllowTagsResolver
12+
{
13+
private Richtext $richtext;
14+
15+
public function __construct(
16+
?Richtext $richtext = null
17+
) {
18+
$this->richtext = $richtext ?? GeneralUtility::makeInstance(Richtext::class);
19+
}
20+
21+
public function resolve(string $tableName, int $recordId, string $fieldName): array
22+
{
23+
if (!isset($GLOBALS['TCA'][$tableName]['columns'])) {
24+
throw new \RuntimeException('TCA Columns ist not defined', 1689950520561);
25+
}
26+
27+
$field = $GLOBALS['TCA'][$tableName]['columns'][$fieldName];
28+
29+
if (!isset($field['config']['type'])) {
30+
return [];
31+
}
32+
33+
if ($field['config']['type'] !== 'text') {
34+
return [];
35+
}
36+
37+
if (isset($field['config']['enableRichtext'])) {
38+
if ($field['config']['enableRichtext'] === false) {
39+
return [];
40+
}
41+
} elseif (isset($GLOBALS['TCA'][$tableName]['types']['columnsOverrides'][$fieldName]['config']['enableRichtext'])) {
42+
if ($GLOBALS['TCA'][$tableName]['types']['columnsOverrides'][$fieldName]['config']['enableRichtext'] === false) {
43+
return [];
44+
}
45+
}
46+
47+
$record = BackendUtility::getRecord($tableName, $recordId);
48+
49+
$allowTags = [];
50+
$rteConfig = $this->richtext->getConfiguration($tableName, $fieldName, $record['pid'], $record['CType'], $field['config']);
51+
if (isset($rteConfig['processing']['allowTags'])) {
52+
$allowTags = array_unique(array_merge($allowTags, $rteConfig['processing']['allowTags']), SORT_REGULAR);
53+
}
54+
55+
return $allowTags;
56+
}
57+
}

0 commit comments

Comments
 (0)