Recently we had an issue with an Episerver site where a user was on the German version of one of our client’s sites, and they were occasionally seeing English content. We were able to determine that the English content was only visible when it was content returned to the browser through use of an AJAX call, and not on a fresh page load. Diving deeper into the issue, we found that all AJAX calls would only return English content.
When an Episerver site uses multiple languages, Episerver determines what language the user is visiting based on the URL structure. URLs in Episerver follow a standard structure:
http://www.domainhere.com/en-ca/restofurl
The language always follows the top-level domain (e.g., .net,.com, .org, .dev) in an Episerver URL.
Episerver parses the URL to get this language code, and based on the page or block a user is visiting, serves up the translation that matches to that language code as long as there is a translation. If there is no translation available, the user will receive a 404 error unless a content editor has set up a fallback language. With the above example URL, Episerver will try to serve content to the user in the en-ca translation.
In most sites, including ours, API calls aren’t made to the server including a language code. Either the API call is the absolute URL of the site along with the route such as http://www.domainhere.com/findmycontent, or the call uses a relative route such as /findmycontent. It’s not up to the frontend code communicating to APIs to tell it what language the user is viewing, and it’s unrealistic to include language parameters on all of the API calls.
Instead, the solution is to set the current language back to what the user is viewing on only AJAX calls, even though it’s not included in the URL. This needs to happen before the server calls the method the browser is trying to communicate with. With ASP.NET MVC this can be done by using the filter ActionFilterAttribute and overriding the OnActionExecuting() method of said filter.
With ASP.NET MVC there are a couple ways of registering filters. In the case of setting the language for Episerver to pick up, it is recommended to decorate the individual MVC actions across your site with the filter you create for this purpose. Adding this filter globally or even at the controller level is unwise as not all MVC actions need to have their languages set. Decorating an action with this new filter should be done on a case-by-case basis of whether or not the action is returning language specific content. The filter we came up with is below:
<p> CODE: https://gist.github.com/thec2group-blog/3308391f604d763bdaf8afaf1c29207a.js</p>
A good example of an action that should be decorated with this new filter is making a call to Episerver Find underneath the hood, such as to retrieve products from a catalog. It’s important that Episerver Find returns products based on the language the user has set in their browser for your site. If the user gets English products back when they’re visiting your German site, you could ultimately lose the sale.
While the custom filter will solve setting the language back to what the user is viewing, it somehow needs to know what language that is. Whatever way you choose to do this is up to you, but our end result was setting a cookie called “Language” for the user.
When the user first visits site this cookie was set to “en” as that is the master language for all of our sites. If the user changes their language using a language selector on the site, the frontend code sets the “Language” cookie to their selected language. Now the server can pick up on this cookie’s value when it needs it. Our JavaScript for setting this cookie is as follows:
<p> CODE: https://gist.github.com/thec2group-blog/a0006b2ef6d377bf00d3423411640391.js</p>
Implementing these ASP.NET MVC filters on a case-by-case basis can prove to be invaluable if your Episerver instance utilizes multiple languages alongside AJAX calls. Doing so will ultimately relieve any obstacles to providing a seamless user experience for nonnative site visitors.