Skip to content

Commit

Permalink
Merge pull request #16 from sitegeist/FEATURE/translation-cache
Browse files Browse the repository at this point in the history
FEATURE: Translation Cache
  • Loading branch information
gradinarufelix authored Aug 21, 2023
2 parents acae1c5 + 70e5c49 commit 1978333
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 6 deletions.
55 changes: 51 additions & 4 deletions Classes/Infrastructure/DeepL/DeepLTranslationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ class DeepLTranslationService implements TranslationServiceInterface
*/
protected $apiKeyCache;

/**
* @var StringFrontend
*/
protected $translationCache;

/**
* @param array<string,string> $texts
* @param string $targetLanguage
Expand All @@ -64,6 +69,24 @@ class DeepLTranslationService implements TranslationServiceInterface
*/
public function translate(array $texts, string $targetLanguage, ?string $sourceLanguage = null): array
{
$isCacheEnabled = $this->settings['enableCache'] ?? false;

$cachedEntries = [];

if ($isCacheEnabled) {
foreach ($texts as $i => $text) {
$entryIdentifier = $this->getEntryIdentifier($text, $targetLanguage, $sourceLanguage);
if ($this->translationCache->has($entryIdentifier)) {
$cachedEntries[$i] = $this->translationCache->get($entryIdentifier);
unset($texts[$i]);
}
}

if (empty($texts)) {
return $cachedEntries;
}
}

// store keys and values seperately for later reunion
$keys = array_keys($texts);
$values = array_values($texts);
Expand Down Expand Up @@ -119,15 +142,28 @@ public function translate(array $texts, string $targetLanguage, ?string $sourceL
if ($apiResponse->getStatusCode() == 200) {
$returnedData = json_decode($apiResponse->getBody()->getContents(), true);
if (is_null($returnedData)) {
return $texts;
return array_replace($texts, $cachedEntries);
}
$translations = array_map(
function ($part) {
return preg_replace('/(<ignore>|<\/ignore>)/i', '', $part['text']);
},
$returnedData['translations']
);
return array_combine($keys, $translations);

$translationWithOriginalIndex = array_combine($keys, $translations);

if ($isCacheEnabled) {
foreach ($translationWithOriginalIndex as $i => $translatedString) {
$originalString = $texts[$i];
$this->translationCache->set($this->getEntryIdentifier($originalString, $targetLanguage, $sourceLanguage), $translatedString);
}
}

$mergedTranslatedStrings = array_replace($translationWithOriginalIndex, $cachedEntries);
ksort($mergedTranslatedStrings);

return $mergedTranslatedStrings;
} else {
if ($apiResponse->getStatusCode() === 403) {
$this->logger->critical('Your DeepL API credentials are either wrong, or you don\'t have access to the requested API.');
Expand All @@ -143,11 +179,11 @@ function ($part) {
} else {
$this->logger->warning('Unexpected status from Deepl API', ['status' => $apiResponse->getStatusCode()]);
}
return $texts;

return array_replace($texts, $cachedEntries);
}
}


public function getStatus(): ApiStatus
{
$hasSettingsKey = $this->settings['authenticationKey'] ? true : false;
Expand Down Expand Up @@ -187,4 +223,15 @@ protected function getDeeplAuthenticationKey(): DeepLAuthenticationKey
$settingsKey = $this->settings['authenticationKey'] ?? null;
return new DeepLAuthenticationKey($customKey ?? $settingsKey);
}

/**
* @param string $text
* @param string $targetLanguage
* @param string|null $sourceLanguage
* @return string
*/
protected function getEntryIdentifier(string $text, string $targetLanguage, string $sourceLanguage = null): string
{
return sha1($text . $targetLanguage . $sourceLanguage);
}
}
7 changes: 7 additions & 0 deletions Configuration/Caches.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@ Sitegeist_LostInTranslation_ApiKeyCache:
persistent: true
backendOptions:
defaultLifetime: 0

Sitegeist_LostInTranslation_TranslationCache:
frontend: Neos\Cache\Frontend\StringFrontend
backend: Neos\Cache\Backend\FileBackend
backendOptions:
# one week
defaultLifetime: 302400
7 changes: 7 additions & 0 deletions Configuration/Objects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ Sitegeist\LostInTranslation\Infrastructure\DeepL\DeepLTranslationService:
arguments:
1:
value: Sitegeist_LostInTranslation_ApiKeyCache
translationCache:
object:
factoryObjectName: Neos\Flow\Cache\CacheManager
factoryMethodName: getCache
arguments:
1:
value: Sitegeist_LostInTranslation_TranslationCache

Sitegeist\LostInTranslation\Controller\LostInTranslationModuleController:
properties:
Expand Down
8 changes: 8 additions & 0 deletions Configuration/Settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ Sitegeist:
#
numberOfAttempts: 1

#
# Here you can optionally disable the translation cache,
# see README for more information.
# BEWARE: disabling this cache while using the Eel Helper
# can significantly slow down your page or even
# lead to timeouts. Use with care!
#
enableCache: true

nodeTranslation:
#
Expand Down
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,10 @@ Sitegeist:
## Eel Helper
The package also provides two Eel helper to translate texts in Fusion.
The package also provides two Eel Helper to translate texts in Fusion.
**:warning: Every one of these Eel helpers make an individual request to DeepL.** Thus having many of them on one page can significantly slow down the performance for if the page is uncached.
:bulb: It is recommended to enable the [translation cache](#translation-cache).
:bulb: Only use while the [translation cache](#translation-cache) is enabled!
To translate a single text you can use:
Expand All @@ -203,6 +203,19 @@ ${Sitegeist.LostInTranslation.translate(['Hello world!', 'My name is...'], 'de',
# Output: ['Hallo Welt!', 'Mein Name ist...']
```

### Translation Cache

The plugin includes a translation cache for the DeepL API that stores the individual text parts
and their translated result for up to one week.
By default, the cache is enabled. To disable the cache, you need to set the following setting:

```yaml
Sitegeist:
LostInTranslation:
DeepLApi:
enableCache: false
```
## Performance
For every translated node a single request is made to the DeepL API. This can lead to significant delay when Documents with lots of nodes are translated. It is likely that future versions will improve this.
Expand Down

0 comments on commit 1978333

Please sign in to comment.