Skip to content

Refactor EntityTranslator to use a dedicated TranslationCacheService #3

@CreativeNative

Description

@CreativeNative

Refactor EntityTranslator to use a dedicated TranslationCacheService

Problem

Currently, the EntityTranslator contains both translation logic and caching logic ($translationCache and $inProgress).
This makes the class harder to test, maintain, and understand. Parts of the caching logic are difficult to cover with unit tests.

Goal

Extract the caching logic into a dedicated service (TranslationCacheService) to improve separation of concerns, testability, and maintainability.

Tasks

1. Create TranslationCacheService

Responsibilities:

  • Store translated entities by TUUD + locale.
  • Track entities currently being translated (inProgress) to avoid infinite recursion.
  • Provide the following methods:
has(string $tuuid, string $locale): bool
get(string $tuuid, string $locale): ?TranslatableInterface
set(string $tuuid, string $locale, TranslatableInterface $entity): void
markInProgress(string $tuuid, string $locale): void
unmarkInProgress(string $tuuid, string $locale): void
isInProgress(string $tuuid, string $locale): bool

Optional: Implement a PSR-6 or PSR-16 cache interface for persistent caching (e.g., Redis, APCu) in the future.

Benefits:
Isolates caching logic from translation logic and makes it fully unit-testable without hitting the database.


2. Update EntityTranslator

  • Inject the new service:
public function __construct(
    string $defaultLocale,
    array $locales,
    EventDispatcherInterface $eventDispatcher,
    AttributeHelper $attributeHelper,
    EntityManagerInterface $entityManager,
    TranslationCacheService $cacheService
) { ... }
  • Replace all $translationCache and $inProgress usage with calls to the cache service:
if ($cacheService->has($tuuid, $locale)) {
    return $cacheService->get($tuuid, $locale);
}

if ($cacheService->isInProgress($tuuid, $locale)) {
    return $entity;
}

$cacheService->markInProgress($tuuid, $locale);
...
$cacheService->set($translated->getTuuid(), $locale, $translated);
$cacheService->unmarkInProgress($tuuid, $locale);
  • Keep all other logic intact:
    • Translation handlers
    • Event dispatching (PRE_TRANSLATE / POST_TRANSLATE)
    • Attribute handling (SharedAmongstTranslations, EmptyOnTranslate)
    • Locale validation

3. Benefits

  • Testability: Unit-test EntityTranslator without touching the database.
  • Separation of concerns: Translation vs caching responsibilities are clearly separated.
  • Simpler code coverage: No need to cover $inProgress or $translationCache internals in main translation tests.
  • Future-proof: Can support persistent PSR caching without changing the translator logic.

4. Optional Enhancements

  • Implement persistent caching with PSR-6 / PSR-16 (Redis, APCu, filesystem).
  • Add metrics/logging to measure cache hits vs misses.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions