I'm trying to generate the hreflang links for our multilingual Magento 2 site, and as the category slug changes, I cannot simply replace the store code in the URL.

I've come up with this:

        $category = $this->_registry->registry('current_category');

        if (!$category->getId()) {
            throw new LocalizedException(__('Failed to initialize category'));

        $categoryId = $category->getId();

        foreach ($this->_storeManager->getStores() as $store) {
            $locale = $this->_scopeConfig->getValue('general/locale/code', \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $store->getStoreId());

                $output[$locale] = $category->getUrl();

It seems to work except that the $category->getUrl() always return the current store URL, even if I loaded the category from another store. Is it a bug or should I do something else?


You should use the category repository to load the category for a specific store.

Inject the category repository in your constructor (alternative use the object manager):

\Magento\Catalog\Model\CategoryRepository $categoryRepository,

In your foreach loop replace the the category loading with the following:

$category = $this->categoryRepository->get($categoryId, $store->getStoreId());
  • The category gets loaded, but the url returned when I call getUrl on it is still the url on the current loaded store. – werfu Mar 7 '19 at 14:14
  • Can you check for a category for which you get the wrong url what's in the url_rewrite table? Run the following SQL: select * from url_rewrite where entity_type = 'category' and entity_id = [YOUR CATEGORY ID]? – HelgeB Mar 7 '19 at 14:28
  • There's a rewrite for each store, albeit the requested path seemingly not ok. However this doesn't explain why the returned URL contains the current store code in the URL instead of the one I've passed to the get call. I must say though that the rewrite system seems very broken on the site, some products having lost their rewrite and only being accessible through built-in route. – werfu Mar 7 '19 at 14:58

The best solution I found so far comes from the following GitHub Magento 2 Seo module: https://github.com/staempfli/magento2-module-seo/

Especially from this class: https://github.com/staempfli/magento2-module-seo/blob/develop/Service/HrefLang/CategoryUrlRetriever.php

 * @param int $identifier the category ID
 * @param Store $store
 * @return string
public function getUrl($identifier, $store)
    /** @var Category $category */
    $category = $this->registry->registry('category');
    if(!$category) {
        $category = $this->categoryRepository->get($identifier, $store->getId());
    $path = $this->categoryUrlPathGenerator->getUrlPathWithSuffix($category);
    return $store->getBaseUrl() . $path;

Where $this->categoryUrlPathGenerator is the object of Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.