From dcbb321f047e12b79a89669485b4d5e6bfcfbe2e Mon Sep 17 00:00:00 2001 From: Nicolas Date: Wed, 20 Nov 2019 18:03:50 +0100 Subject: [PATCH] Properly reload ALL the language files already loaded before the language switch We found an issue with the plugin that we actively use on the website of one of our clients: The translations of modules were missing in some cases. And the problem didn't happen with the Language Domains plugin turned off. After some debugging we realized that after a language switch, the Joomla core language files and the language file of the current component are reloaded by the plugin, but not all the language files already loaded. So we've modified the code of the plugin to : 1. get the path of all the language files already loaded and the language code before the switch 2. change these paths by replacing the language code to the new language's code 3. parse these new paths and add them to JLanguage after the switch We do that using Closure in order to be able to access the private attributes of JLanguage --- .../languagedomains/languagedomains.php | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/source/plugins/system/languagedomains/languagedomains.php b/source/plugins/system/languagedomains/languagedomains.php index 82f4994..10388e6 100644 --- a/source/plugins/system/languagedomains/languagedomains.php +++ b/source/plugins/system/languagedomains/languagedomains.php @@ -125,6 +125,10 @@ public function __construct(&$subject, $config) */ public function onAfterInitialise() { + // Store the previous language tag in the plugin + $this->oldLanguageTag = JFactory::getLanguage() + ->getTag(); + // Remove the cookie if it exists $this->cleanLanguageCookie(); @@ -224,6 +228,58 @@ public function onAfterInitialise() $this->helper->resetDefaultLanguage(); } + /** + * Function to get the paths of all the language files loaded before the language switch + */ + function getPaths() { + $loadOverride = function($filename = null) { + // Get the path of all the translation files already loaded + return $this->paths; + }; + + // We use Closure here as we need to access private attributes of JLanguage + $lang = JFactory::getLanguage(); + $loadOverrideCB = $loadOverride->bindTo($lang, 'JLanguage'); + $this->paths = $loadOverrideCB(); + } + + /** + * Function to relaod all the language files in the new language after the language switch + */ + function reloadPaths($oldtag, $tag) { + $loadOverride = function($paths, $oldcode, $code) { + foreach($paths as $extension => $extensionPaths) { + foreach($extensionPaths as $fileName => $oldResult) { + + // Replace the language code in the translation file path + $fileName = str_replace($oldcode, $code, $fileName); + + // Parse the language file + $strings = $this->parse($fileName); + $result = false; + + // Add the translations to JLanguage + if ($strings !== array()) { + $this->strings = array_replace($this->strings, $strings, $this->override); + $result = true; + } + // Record the result of loading the extension's file + if (!isset($this->paths[$extension])) + { + $this->paths[$extension] = array(); + } + + $this->paths[$extension][$fileName] = $result; + } + } + }; + + // We use Closure here as we need to access private attributes of JLanguage + $lang = JFactory::getLanguage(); + $loadOverrideCB = $loadOverride->bindTo($lang, 'JLanguage'); + $loadOverrideCB($this->paths, $oldtag, $tag); + } + /** * Event onAfterRoute */ @@ -254,6 +310,9 @@ public function onAfterRoute() { return; } + + // Get the paths of all the language files loaded before the language switch + $this->getPaths(); // If this language is not included in this plugins configuration, set it as current if (!$this->isLanguageBound($languageTag)) @@ -268,9 +327,8 @@ public function onAfterRoute() $this->debug('Current language tag: ' . $languageTag); - $language = JFactory::getLanguage(); - $option = $this->app->input->getCmd('option'); - $language->load($option, JPATH_SITE, $languageTag, true); + // Relaod all the language files in the new language after the language switch + $this->reloadPaths($this->oldLanguageTag, $languageTag); if (empty($languageTag)) {