Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IVirtualPageControllers localize based on browser-headers since the introduction of EagerMatcherPolicy #16626

Closed
kasparboelkjeldsen opened this issue Jun 19, 2024 · 3 comments

Comments

@kasparboelkjeldsen
Copy link
Contributor

Which Umbraco version are you using? (Please write the exact version, example: 10.1.0)

13.3.2 or newer, including 13.4.0-rc2

Bug summary

If you are using an IVirtualPageController with a mapped endpoint, and in the view or controller utilize Umbracos dictionary or other features that rely on the CurrentUICulture of the current thread, it will chose the language/culture based of browser headers and not the domain setup in Umbraco.

When I manually disable the new EagerMatcherPolicy service and rely on the standard non-optimized behavior everything works as it should.

Specifics

I have set up a POC on this public repository

https://github.com/kasparboelkjeldsen/Umbraco.LocalizationBugIn13.3.2/tree/main

It includes database and everything for ease of reproduction.

I discovered this bug when a customer was experiencing weird behavior for some of their users - specifically those using Edge or Brav browser, but not those using Chrome.

After a long investigation I've tracked it down to being due to the "Accept-Language" header being sent by the browsers being different, and Chrome (for Danes at least) will start it's header with "da-DK" whereas the other browsers won't.

I don't know the exact machnics of MachingPolicies well enough to know how this happens, but the end result is, that the "System.Threading.Thread.CurrentThread.CurrentUICulture" will differ on the View, based of the browser-headers.

As Umbracos dictionary and I assume other things rely on the CurrentUICulture being set correctly based of the domain and language setup in the CMS this can have quite severe consequences.

In my POC you will see a frontpage that has a single dictionary key, with the default language being danish. There is no english domain setup, so we should never see the english dictionary key.

I have then set up the route /silly to go through a IVirtualPage controller that just loads the same content. This time the dictionary item will be in English if the browser hasn't sent a accept-language header that starts with "da-DK".

I've included a lazy JS test on the page as well so you don't have to fiddle with browers and settings to test it.

image

Steps to reproduce

You can pull down the POC or

  • Setup Umbraco with at least 2 languages, where English isn't the default
  • Create a dictionary key that differs between the languages
  • Create a frontpage and use that key
  • Compose in a UmbracoPipelineFilter and set a custom endpoint to a IVirtualPageController
public void Compose(IUmbracoBuilder builder)
{
    builder.Services.Configure<UmbracoPipelineOptions>(options =>
    {
        options.AddFilter(new UmbracoPipelineFilter(nameof(CustomVirtualPageController))
        {
            Endpoints = app => app.UseEndpoints(e =>
            {
                // danish
                e.MapControllerRoute("CustomVirtualPageController", "/silly", new { Controller = "CustomVirtualPage", Action = "Index" });

            })
        });
    });
}
  • Create the controller with this code
public class CustomVirtualPageController : UmbracoPageController, IVirtualPageController
{
    private readonly IUmbracoContextAccessor _umbracoContextAccessor;
    public CustomVirtualPageController(ILogger<UmbracoPageController> logger, ICompositeViewEngine compositeViewEngine, IUmbracoContextAccessor umbracoContextAccessor) : base(logger, compositeViewEngine)
    {
        _umbracoContextAccessor = umbracoContextAccessor;
    }

    public IPublishedContent? FindContent(ActionExecutingContext actionExecutingContext)
    {
        _umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext);

        return umbracoContext.Content.GetAtRoot().FirstOrDefault();
    }

    public IActionResult Index()
    {
        return View("VirtualPage", CurrentPage);
    }
}
  • access /silly with a browser or tool that doesn't have "da-DK" in the start of the accept-language header (or just no accept-language header at all)

Expected result / actual result

I expect my translations to be in the language I've set for the domain in Umbraco

Copy link

Hi there @kasparboelkjeldsen!

Firstly, a big thank you for raising this issue. Every piece of feedback we receive helps us to make Umbraco better.

We really appreciate your patience while we wait for our team to have a look at this but we wanted to let you know that we see this and share with you the plan for what comes next.

  • We'll assess whether this issue relates to something that has already been fixed in a later version of the release that it has been raised for.
  • If it's a bug, is it related to a release that we are actively supporting or is it related to a release that's in the end-of-life or security-only phase?
  • We'll replicate the issue to ensure that the problem is as described.
  • We'll decide whether the behavior is an issue or if the behavior is intended.

We wish we could work with everyone directly and assess your issue immediately but we're in the fortunate position of having lots of contributions to work with and only a few humans who are able to do it. We are making progress though and in the meantime, we will keep you in the loop and let you know when we have any questions.

Thanks, from your friendly Umbraco GitHub bot 🤖 🙂

@kasparboelkjeldsen
Copy link
Contributor Author

Further testing:
It's worth noting that if your languages don't include English as one of them, anyone visiting a page that is handled through the EagerMatcherPolicy that doesn't happen to have the correct accept-lanuage in their request header will get blank dictionary values.

@Zeegaan
Copy link
Member

Zeegaan commented Jun 20, 2024

Fixed in #16635

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants