symfony: Cannot add resources to the translator from an event subscriber

Symfony version(s) affected:

2.7.5 and more recent (2.6.13 definitely not affected; 2.8.41 definitely affected)

Description

Since Symfony 2.7.5, or at least since 2.8.x, it seems impossible to add resources to the default translator from an event subscriber (or from anywhere short of a compiler pass, for that matter.) The new resources are never loaded. It was working fine in Symfony 2.6.13.

Performance improvements to the loading of translations introduced between 2.6 and 2.8 seem to be the cause.

How to reproduce

See the demonstrator, that features minimalistic projects for Symfony 2.6, 2.8, and 4.1.

https://github.com/oscherler/sf-translation-loading-demonstrator

Possible Culprit

After bisecting on tags between v2.6.13 and v2.8.41, it seems that the change occurred between v2.7.4 and v2.7.5. Specifically, this change in src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php:

 /**
  * {@inheritdoc}
  */
 public function warmUp($cacheDir)
 {
     // skip warmUp when translator doesn't use cache
     if (null === $this->options['cache_dir']) {
         return;
     }
 
-    foreach ($this->resourceLocales as $locale) {
+    $locales = array_merge($this->getFallbackLocales(), array($this->getLocale()), $this->resourceLocales);
+    foreach (array_unique($locales) as $locale) {
+        // reset catalogue in case it's already loaded during the dump of the other locales.
+        if (isset($this->catalogues[$locale])) {
+            unset($this->catalogues[$locale]);
+        }
+
         $this->loadCatalogue($locale);
     }
 }

Reverting it in the demonstrator solves the problem, although I am not sure whether it’s all that is needed to fix it for certain.

Possible Solution

An option would be to have a public method on the translator that allows to trigger a proper loading of the newly added resources and that could be called from the event subscriber. But I haven’t yet been able to write such a method reliably, as I don’t fully understand how the resources are loaded in the current implementation.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 16 (12 by maintainers)

Commits related to this issue

Most upvoted comments

For this use case, why not having a RuntimeResourceLoaderTranslator that decorates the original Translator object. This way the inner translator would use the Symfony cache while the decorator would perform the logic to load catalog at runtime and cache keys in memory.