Repository navigation
Description
Prerequisites
- I understand and accept the project's code of conduct.
- I have already searched in existing issues and found no previous report of this bug.
Describe the bug and add attachments
Ps_Linklist::__construct() builds the tab name for every active language:
$tabNames = [];
foreach (Language::getLanguages(true) as $lang) {
$tabNames[$lang['locale']] = $this->trans('Link List', [], 'Modules.Linklist.Admin', $lang['locale']);
}Each trans() call with a different locale makes the translator load the whole catalogue of that locale (all core and module domains). The constructor runs whenever the module is instantiated, so on every request that instantiates it the shop loads N full catalogues instead of one. The Module Manager instantiates every module, so this happens each time it opens.
On a shop with 22 languages (memory_limit 512M), Modules → Module Manager fails with OutOfMemoryError: Allowed memory size of 536870912 bytes exhausted. Where it fails varies (MessageCatalogue.php, XliffFileLoader.php, Translate.php, …), but it always fails while loading translations. Every additional module adds strings to all N catalogues, so the failure becomes more frequent over time.
Measured by instantiating all 143 active modules in one request (front context):
- before
ps_linklist: 1 catalogue loaded (cs-CZ), about 11 MB used; - after
new Ps_Linklist(): 22 catalogues loaded, +38 MB; - no other module loads additional locales.
In the back office the catalogues also include the Admin* domains, which are much larger, so memory goes past 512 MB.
The loop has been there since commit cdd9964 (2020-06-16, "Fix tab localization", first released in ps_linklist 4.0.0). It is still in the current master / dev (7.0.1). Reproduced with ps_linklist 6.0.7.
Proposed fix
The tab already declares wording + wording_domain, and the core re-translates tab names from them (TabTranslator). Two options:
A) plain string, as blockwishlist does:
$this->tabs = [
[
'route_name' => 'admin_link_block_list',
'class_name' => 'AdminLinkWidget',
'visible' => true,
'name' => 'Link List',
'parent_class_name' => 'AdminParentThemes',
'wording' => 'Link List',
'wording_domain' => 'Modules.Linklist.Admin',
],
];B) keep localized names, but compute them only when the core asks for the tabs (the constructor keeps 'name' => 'Link List'):
public function getTabs()
{
$tabs = parent::getTabs();
$tabNames = [];
foreach (Language::getLanguages(true) as $lang) {
$tabNames[$lang['locale']] = $this->trans('Link List', [], 'Modules.Linklist.Admin', $lang['locale']);
}
$tabs[0]['name'] = $tabNames;
return $tabs;
}getTabs() is called by ModuleTabRegister::registerTabs() (on install) and by ModuleController::moduleNeedsReload() (after a module action), so it never runs on regular requests or when the Module Manager list is displayed.
Workaround applied on the affected shop (option A): Module Manager loads again, a single catalogue is loaded, and the module's memory overhead dropped from +38 MB to +0.05 MB. The footer link blocks render unchanged.
Steps to reproduce
- Install PrestaShop and add many languages (reproduced with 22 active languages).
- Make sure ps_linklist is installed (it is by default).
- Set
memory_limitto 512M (or lower, it fails sooner). - Go to Modules > Module Manager in the back office.
- Error 500.
var/logs/prod-*.logshowsOutOfMemoryErrorduring translation catalogue loading.
To confirm the cause: remove the foreach loop in the ps_linklist constructor (use a plain string as the tab name) and reload the page. Only one catalogue is loaded and the page works.
Expected behavior
Instantiating a module should not load translation catalogues for languages other than the current one. Tab names are only needed when the tab is registered (ModuleTabRegister::registerTabs() → getTabs(), on install).
Actual Result
Every instantiation of ps_linklist loads the full translation catalogue of every active language (22 instead of 1, +38 MB). The Module Manager instantiates all modules and runs out of memory (error 500).
PrestaShop version where the bug happens
8.2.8,9.1.5,9.2.0
Module version where the bug happens
4.0.0 - 7.0.1
PHP version(s) where the bug happened
8.1
Your company or customer's name goes here (if applicable).
IT Web Partner s.r.o.
Activity