Fallback for the URL on MultiUrlPicker if language is not published
I'm trying to setup my multi-lingual site so if my page doesn't have a published version for the language I'm in, it shows the English content.
Since the language version has not been created yet, it doesn't have a URL so my plan was to link the user to the English URL rather than the translated one. If I select a page using a MultiUrlPicker and the language I'm in is published, it will work fine and return the correct link. However if the language for that page is not published, it will return "#"
Is there a way to set the fallback logic on a MultiUrlPicker field so if the users language isn't published for the selected page, it returns the default language's URL rather than defaulting to "#"?
I can't see an easy way to do it, but curious if any one else has came across this issue.
It looks like this is also true for a IPublishedContent Url() property.
It looks like I can specify the culture for the requested URL, but I can't set a fallback like I can for a Value().
Do I just need to handle this myself and check if the language is published before getting the URL and if not get the English URL, or is there a way to have Umbraco do this step?
Posing my solution here (since I just searched for the same problem again and forgot I had solved it)
I ended up overriding the DefaultUrlProvider and made a new GetUrl method that would do the fallback to the default language on the URL.
Here is the code in v8:
/// <summary>
/// This overrides the Default URL provider so that if a page isn't published, the GetURL() will fallback and return the english URL instead of the default value of "#"
/// This should work for all instances of Url() including PublishContent and MutltiNodeLinks
/// </summary>
public class UrlProviderWithFallbackLanguage : DefaultUrlProvider
{
private readonly ILocalizationService _localizationService;
public UrlProviderWithFallbackLanguage(IRequestHandlerSection requestSettings, ILogger logger, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, ServiceContext serviceContext)
:base(requestSettings, logger, globalSettings, siteDomainHelper)
{
_localizationService = serviceContext.LocalizationService;
}
public override UrlInfo GetUrl(UmbracoContext umbracoContext, IPublishedContent content, UrlMode mode, string culture, Uri current)
{
var urlInfo = base.GetUrl(umbracoContext, content, mode, culture, current);
//If we return null, fallback to the default langauge
if(urlInfo == null)
{
var defaultLanguageCode = _localizationService.GetDefaultLanguageIsoCode();
urlInfo = base.GetUrl(umbracoContext, content, mode, defaultLanguageCode, current);
}
return urlInfo;
}
And then register class this in the compositions so the site will use it.
/// <summary>
/// This overrides the default fall back logic of the GetValue() calls to fallback to langauge by default. (Umbraco v9)
/// </summary>
public class UrlProviderWithFallbackLanguage : DefaultUrlProvider
{
private readonly ILocalizationService _localizationService;
public UrlProviderWithFallbackLanguage(ILocalizationService localizationService, IOptions<RequestHandlerSettings> requestSettings, ILogger<DefaultUrlProvider> logger, ISiteDomainMapper siteDomainMapper, IUmbracoContextAccessor umbracoContextAccessor, UriUtility uriUtility)
: base(requestSettings, logger, siteDomainMapper, umbracoContextAccessor, uriUtility)
{
_localizationService = localizationService;
}
public override UrlInfo GetUrl(IPublishedContent content, UrlMode mode, string culture, Uri current)
{
var urlInfo = base.GetUrl(content, mode, culture, current);
//If we return null, fallback to the default langauge
if (urlInfo == null)
{
var defaultLanguageCode = _localizationService.GetDefaultLanguageIsoCode();
urlInfo = base.GetUrl(content, mode, defaultLanguageCode, current);
}
return urlInfo;
}
}
Another update I made for my translated site, I also updated the fallback logic for my GetValue() method, so the modal builder would fallback each field to the default language if not set. This is a slightly different problem, but I figured I could add my code here just in case anyone finds it helpful.
/// <summary>
/// This overrides the default fall back logic of the GetValue() calls to fallback to langauge by default. (Umbraco v8)
/// </summary>
public class CustomPublishedValueFallback : PublishedValueFallback
{
public CustomPublishedValueFallback(ServiceContext serviceContext, IVariationContextAccessor variationContextAccessor)
: base(serviceContext, variationContextAccessor)
{
}
public override bool TryGetValue<T>(IPublishedContent content, string alias, string culture, string segment, Fallback fallback, T defaultValue, out T value, out IPublishedProperty noValueProperty)
{
//When no fallback, use ToLanguage by default
if (!fallback.Any(f => f == Fallback.DefaultValue || f == Fallback.Language || f == Fallback.Ancestors))
{
fallback = Fallback.ToLanguage;
}
return base.TryGetValue(content, alias, culture, segment, fallback, defaultValue, out value, out noValueProperty);
}
}
And then register class this in the compositions so the site will use it.
I am having exactly the same issue in V8, so I am happy to see your solution here.
Are you sure what you posted for v8 is correct? YOur text mentions you override default DefaultUrlProvider and create a new GetUrl() method, however, your v8 code looks like something else.
You're right, I had copied the wrong code in to my answer for my v8 solution. That code was overriding the GetValue() method so my Modals builder would use the language fallback logic.
I updated my post above with the right code, which will override the DefaultUrlProvider to add some fallback logic.
Fallback for the URL on MultiUrlPicker if language is not published
I'm trying to setup my multi-lingual site so if my page doesn't have a published version for the language I'm in, it shows the English content.
Since the language version has not been created yet, it doesn't have a URL so my plan was to link the user to the English URL rather than the translated one. If I select a page using a MultiUrlPicker and the language I'm in is published, it will work fine and return the correct link. However if the language for that page is not published, it will return "#"
Is there a way to set the fallback logic on a MultiUrlPicker field so if the users language isn't published for the selected page, it returns the default language's URL rather than defaulting to "#"?
I can't see an easy way to do it, but curious if any one else has came across this issue.
What languages do you have deo with besides English?
I've got 6 other languages, and English set as my site's default language.
It looks like this is also true for a IPublishedContent Url() property.
It looks like I can specify the culture for the requested URL, but I can't set a fallback like I can for a Value().
Do I just need to handle this myself and check if the language is published before getting the URL and if not get the English URL, or is there a way to have Umbraco do this step?
Posing my solution here (since I just searched for the same problem again and forgot I had solved it)
I ended up overriding the DefaultUrlProvider and made a new GetUrl method that would do the fallback to the default language on the URL.
Here is the code in v8:
And then register class this in the compositions so the site will use it.
Or, if you're using v9, here is the class:
Another update I made for my translated site, I also updated the fallback logic for my GetValue() method, so the modal builder would fallback each field to the default language if not set. This is a slightly different problem, but I figured I could add my code here just in case anyone finds it helpful.
And then register class this in the compositions so the site will use it.
Hi Kevin,
I am having exactly the same issue in V8, so I am happy to see your solution here.
Are you sure what you posted for v8 is correct? YOur text mentions you override default DefaultUrlProvider and create a new GetUrl() method, however, your v8 code looks like something else.
So this code of yours
doesn't seem to do anything with your v8 code.
Any input appreciated! Thank you!
Hi Mikael,
You're right, I had copied the wrong code in to my answer for my v8 solution. That code was overriding the GetValue() method so my Modals builder would use the language fallback logic.
I updated my post above with the right code, which will override the DefaultUrlProvider to add some fallback logic.
Hopefully that makes more sense now.
Hi,
We recently encountered the same problem.
Finally, we implemented a CustomUrlProvider with a little bit more logic respecting a fallback language.
We also decided to respect if the main content is provided for published language variant.
You can find an explanation and solution in the article: Problem with linking in Umbraco across pages in different cultures.
is working on a reply...