Tuesday, February 11, 2014

Finding the language in SPAs

Coming from a background of being a .Net web developer I never needed to worry much about figuring out what language I should display pages in. The framework figured it out and all I really had to do was make sure that strings were localized. The mystical resource manager would handle it all.

Now writing a single page application things are a little different. I have had to understand language selection a little better. So it turns out there are four places to hold language information.

Accept-Language

Inside the HTTP header in a line "Accept-Language" and it has a weird string involving language codes and "q" values that are essentially meaningless and point to a poorly defined specification process. This is the language that your web pages should display in. When you configure your browser to be in a language this is what you are controlling. In the normal mode of operation a browser makes a request and the header defines the language they want the response in. But all is not well! JavaScript is not allowed access to the HTTP header for security purposes. So to get the language you really need to build a web service that echoes back the value of "Accept-Language".

Installation

The browser itself has a language version that it is installed with. This comes from "window.navigator.userLanguage" or "window.navigator.language". Now this is probably what you want although technically it is not correct. So the advantage here is that JavaScript can get this piece of information and that it is probably right. The disadvantage is that it is possibly wrong and you can not easily change it.

Query String

A popular place to put language information is in the query string. Savvy users can easily manipulate it. The server can access it and JavaScript can access it. You can even argue that query string values should override what is in Accept-Language. So this is one way to go and it offers a lot of convenience, but the problem is you need to make sure that it is there. It also is a little code smelly because you are duplicating "Accept-Language" and when the two disagree you have to make an arbitrary call as to which to honor. (Or in the case of single page applications you pick the query string because you can't see the header.

JavaScript State

I have also seen cases where you store language information in JavaScript itself. I count in this cookies or web storage or whatever. Systems like this seem rare, but it is possible. 

So what should I do?

Well, to be most correct you should build a web service that mirrors back what is in the Accept-Language header. Then you store this. This is actually slightly incorrect still because the user should reconfigure the language they are using id-stream. Another option is to attach the language to every XHR, but you don't really want to do this. You don't want to rewrite strings on your page based on every request. So you should probably live with being slightly incorrect or correct if you view the initial page load as the only one who should figure out language.

A slightly less correct way is to read the query string and then fall back on to the installation language if the query string isn't there.

No comments:

Post a Comment