Problem with linking in Umbraco across pages in different cultures

Unfortunately, the current system design cause serious SEO optimization issues and decreases website visibility

Overview of multilingual linking challenges

First, Umbraco respects whether the page has been published for a specific language while creating a URL for a specific culture.

I was convinced that Umbraco provides a URL to the page in the default/fallback language if the page is not published for a specific culture.

Unfortunately, no such logic exists in the Umbraco, and no configuration can enable it.

I guess it was too obvious for me.

I'm still convinced that it should work as expected because, right now, it's not possible to link a page across different cultures.

Therefore, I decided to raise an issue for Umbraco: https://github.com/umbraco/Umbraco-CMS/issues/15498

Unfortunately, the issue was closed.

Of course, we can type correct URLs by hand in the URL Picker for the menu and other links, but it should not be solved this way.

It's highly recommended that internal links are generated automatically by selected content in the node tree.

Otherwise, we will be struggling with broken links or redirections.

Possible workaround

I can see two workarounds that could be introduced without coding.

The vary by culture option should be used only for pages that will be translated for each language. Unfortunately, editors must provide content and publish specific language variants to link across pages. 

Such a solution has to be introduced by design. 

If you notice such an issue after launch, then you will get into trouble because a universal document type could be already used for both scenarios, and it's not possible to just disable culture variations or change the document type of existing content.

As far as I remember, the changing document type feature was available in Umbraco 6-7 and removed in Umbraco 8. 

I really miss this functionality!

However, let's focus on the other workaround.

The required content of the page could be set as optional, and all language variants could be published without providing translated content.

Then, the content of the default or fallback language can be used during page rendering.

Editors will be able to link between pages, no matter if the content is provided or not. 

Be aware that the second solution is highly not recommended because it will cause duplicated content from an SEO perspective.

Unfortunately, I have seen such a solution on essential websites created by Umbraco partners.

Corner case in cross-cultural linking

Unfortunately, there is another case we need to take into account.

To publish a child page for a specific language, we need to begin with publishing a parent page for the same language if both pages vary by culture.

We need to take into account that the homepage is commonly used as a configuration node and varies by culture in most multilingual websites because culture-specific properties have to be provided, such as:

  • Menu
  • Footer
  • SEO properties

If the culture-specific content for the homepage will not be provided, then duplicated content will also occur.

So, if we have already encountered a duplicated content issue for the homepage, then it's not possible to unpublish duplicated language variants or just disable culture variation for the document type used by the homepage.

Implementing CustomUrlProvider

I invented the easiest & fastest solution without braking changes, which should work for any Umbraco website.

We can implement a custom URL provider, which is a straightforward solution that could be easily introduced in the current Umbraco website.

The custom URL provider should be able to generate a URL to the page in the default/fallback language if the page has not been published for the specific culture.

To solve the duplicated homepage, we can expand the custom URL provider logic a little bit.

We can check if the content is provided for the specific culture.

If not, the default/fallback language URL should be generated.

Even more, we can check any page to see if the culture-specific content is provided or not.

The custom URL provider with such functionality will allow us to unpublish all nodes (except the homepage) for unnecessary language variants.

If bots already recognize the duplicated content, then an appropriate redirection should be set for the homepage.

Below, you can find a basic implementation of CustomUrlProvider.

As you can see, it's not necessary to implement this provider from scratch because we can derive from the base DefaultUrlProvider, which is set as public.

public class MyCustomUrlProvider : DefaultUrlProvider
{
    private readonly ILocalizationService _localizationService;

    public MyCustomUrlProvider(
        IOptionsMonitor<RequestHandlerSettings> requestSettings,
        ILogger<MyCustomUrlProvider> logger,
        ISiteDomainMapper siteDomainMapper,
        IUmbracoContextAccessor umbracoContextAccessor,
        UriUtility uriUtility,
        ILocalizationService localizationService)
        : base(requestSettings, logger, siteDomainMapper, umbracoContextAccessor, uriUtility, localizationService)
    {
        _localizationService = localizationService;
    }

    public override UrlInfo GetUrl(IPublishedContent content, UrlMode mode, string culture, Uri current)
    {
        var urlInfo = base.GetUrl(content, mode, culture, current);

        if (urlInfo != null)
            return urlInfo;

        var defaultLanguageIsoCode = _localizationService.GetDefaultLanguageIsoCode();

        return base.GetUrl(content, mode, defaultLanguageIsoCode, current);
    }
}

Of course, we need to register the MyCustomUrlProvider in a composer as follows:

public class MyComposer : IComposer
{
    public void Compose(IUmbracoBuilder builder)
    {
        builder.UrlProviders().Insert<MyCustomUrlProvider>();
    }
}

It's worth mentioning that for any language added in the Settings section (except for default language) we could specify a fallback language as below:

Fall back language configuration in the Settings section of the Umbraco CMS

Therefore, we can extend the CustomUrlProvider with additional logic respecting the fallback language if specified in the Umbraco configuration.

Below, you can find a piece of code that allows you to establish the fallback language.

var fallbackLanguageId = _localizationService.GetLanguageByIsoCode(culture).FallbackLanguageId;

if (fallbackLanguageId != null)
{
    var fallbackLanguageIsoCode = _localizationService.GetLanguageIsoCodeById(fallbackLanguageId.Value);

    //TODO: Add additional code here
}

Final thoughts on multicultural linking

Reflecting on the challenges of linking across Umbraco pages in different cultures, it's clear that while Umbraco offers robust multilingual support, some nuances require custom solutions.

The focus on a custom URL provider as a workaround is particularly insightful.

This approach addresses the immediate issue of managing links in a multilingual environment and opens up possibilities for more tailored and user-friendly navigation experiences.

🌐 Explore More: I encourage you to visit our blog to discover innovative solutions and Umbraco's capabilities.

↑ Top ↑