Skip to content

ps_linklist constructor loads the translation catalogue of every active language – Module Manager runs out of memory on multi-language shops #210

Description

@webeshop

Prerequisites

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

  1. Install PrestaShop and add many languages (reproduced with 22 active languages).
  2. Make sure ps_linklist is installed (it is by default).
  3. Set memory_limit to 512M (or lower, it fails sooner).
  4. Go to Modules > Module Manager in the back office.
  5. Error 500. var/logs/prod-*.log shows OutOfMemoryError during 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

  1. added theissue type on Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions