Because of filter functionality we have created a form that is posted asynchronously to retrieve all items that match the given criteria. This is done using regular MVC controllers, but this raises a problem.
Upon entering the controller, the current culture and the PreferredCulture of ContentLanguage is reset to the master language. Multiple languages are available, so we've tried to force it to a different language. However, when one ContentArea is rendered (with Html.PropertyFor) the PreferredCulture of ContentLanguage was reset to the master language once more. The first block of the page has been rendered in the second language and the rest of the page in the master language.
I'd like to add that this only happens when the language is changed for this first time, or when the page is reloaded without cache (ctrl + f5).
Is there anyone who could explain why this is happening?
Bram van der Zee
When you make AJAX requests to regular controllers, you don't utilize Episerver routing and the URL does not include the language segment. Episerver looks at this segment when attempting to set the value of PreferredCulture for content requests.
When you make requests to a custom controller, without setting the PreferredCulture, Episerver will use the master language when loading content for your code. However, you can easily detect and set the language code for custom controllers.
I usually do something like this:
I once wrote a piece about above solution, including sample code, here.
While reading your question a second time, I remembered another solution.
It sounds like you are requesting HTML using AJAX. If true, you could implement the filtering in your existing Episerver page controller (the page with your form), with the following code at the end of your action method.
Your front end code would then request the page itself as an AJAX request. Then Episerver will figure out the language for you.
Let me understand this right, Bram.
The custom controller renders an Episerver page that contains several blocks? And you implemented my attribute solution on the custom controller class?
If you did that, then the PreferredCulture should be set and remain for that entire request. Neither pages nor blocks generally change that value. It is normally set before loading any routable content (not including blocks).
Are you sure that no other changes the PreferredCulture property? Do you load those blocks yourself (using IContentLoader), or do you render using the PropertyFor (or similar) method?
We load the page with IContentLoader. This is done in a controller where the attribute is active. There are multiple blocks on this page that are loaded in the view using the PropertyFor method. I'm testing the block controllers right now, but I doubt they change the PreferredCulture. I'll update the post with my findings.
Update: the blocks do revert to the master language. Adding the attribute to the block controllers does not help. The language settings seem off though. It recognizes the 2nd language as the master language, and the master language as language to show.
In your controller, the PreferredCulture is set correctly? And you call IContentLoader.Get<T> with no language parameter (it will pick up the current language, itself)?
I would maybe try loading the blocks from the page, using the content loader with a forced language parameter, to verify that the content can in fact be loaded in the selected language.
PreferredCulture is set correctly. The content retrieved with IContentLoader.Get<T> is retrieved in the correct language as well. The blocks are shown in the correct language when I do a soft refresh, but shows incorrect data on a hard refresh. From what I've seen, we might've an incorrect implementation of the IUpdateCurrentLanguage interface, where we store the current language in a cookie. However, this cookie is overwritten with the master language through multiple other parts of code that also call this implementation. I haven't been able to find where Episerver uses this implementation though.
Okay, then you probably don't want to call the IUpdateCurrentLanguage logic for these AJAX requests.
You can try changing my code sample, so it directly sets the content language and the UI culture (for things like date formatting and translations).
// Remove this:
// Add these:
Generally the IUpdateCurrentLanguage interface seems to be called from deep inside Episerver's routing. But not when using custom controllers, custom routing or WebAPI.
That didn't seem to make any difference. In our implementation of the IUpdateCurrentLanguage interface, somehow the master language is passed as a parameter. I've tried to force this to the 2nd language, which resulted in all pages being translated correctly. What we don't know is why the master language is passed as the parameter and how we can isolate the correct language in this method.
Update: seems like incorrect language is supplied by Episerver. Called from EPiServer.Cms.AspNet.dll!EPiServer.Web.Routing.Segments.Internal.RequestSegmentContext.Language.set(string value)
I've been going through the IUpdateCurrentLanguage implementation today and found out that images and bundles (css/js) also pass through this interface and try to update the language. As they do not have a 2nd language or even a language at all, they are defaulted to the master language or even null. By filtering on the accept-types of the incoming request, we were able to isolate the language update when actual pages were loaded, instead of images and bundles. It works as it should now. Thank you very much for your help!
You mean that your ModelState error messages are in wrong language, Jeroen?
In your controller action, can you verify that both Thread.CurrentThread.CurrentCulture and Thread.CurrentThread.CurrentUICulture are set to the requested language?
@Stefan, That is set correctly already using that custom attribute approach you suggested, but it seems that the ModelState is already filled earlier in the request pipeline with the culture. Because when in the controller I clear ModelState and revalidate it again it respects the right language.
That sounds right, Jeroen. OnActionExecuting seems to run just after the model binding and validation.
This is not a scenario I considered when implementing the solution. But you can probably amend it to fit in earlier in the pipeline.
this is nice overview of mvc pipeline. we had the same problem back in days..
I implemented an IHttpModule and this logic seems to do the trick. The Ajax requests are still working and there is no need for a custom filter attribute on controller level. Also the ModelState is now using the correct language. The code I've used below:
public class LocalizationHttpModule : IHttpModule
private readonly Injected<EPiServer.Configuration.Settings> _settings;
private readonly Injected<IUpdateCurrentLanguage> _updateCurrentLanguage;
public void Dispose()
public void Init(HttpApplication context)
context.BeginRequest += new EventHandler(context_BeginRequest);
private void context_BeginRequest(object sender, EventArgs e)
HttpRequest request = ((HttpApplication)sender)?.Request;
// If the PageUseBrowserLanguagePreferences setting is true, this is already handled everywhere.
if (request == null)
HttpRequestBase httpRequest = new HttpRequestWrapper(request);
string acceptedLanguages = httpRequest.UserLanguages;
if (acceptedLanguages == null || acceptedLanguages.Length == 0)
var languagePreferenceList = new LanguagePreferenceList();
var culture = ContentLanguage.Instance.DetermineCulture(languagePreferenceList);