Guiding users to translated pages

Intended audience: HTML developers (using editors or scripting), Web project managers, and anyone who is interested in content negotiation and language switching.


If my site contains alternative language versions of the same page, what can I do to help the user see the page in their preferred language?

This article is relevant for pages for which there are complete translations of the content. If your alternative pages have different content, or are regional variants rather than translations, you may need to do things differently.

Quick answer

Use server-based, language-related content negotiation to point the user to the page that matches their browser preferences, but also add links to each page so that the user can change languages easily if they prefer.

Consider how to indicate to the user where the in-page language links are, and if the page is available in a long list of languages, consider whether or not to use something like a select control (and if so, how to make it obvious what its function is).

If the user switches to a different language, offer them the opportunity to remember that choice and serve up subsequent pages in that language, overriding their browser settings.


Content negotiation

It's usually helpful to automatically guide a reader to a page in a language they prefer, if such a page is available . This is called content negotiation, and is done by the server when they request a page. There are different types of content negotiation. Here we are concerned with language-related content negotiation, which we will refer to as language negotiation.

This makes it easier for the user to quickly get to content in the language they prefer. There may be times when this delivers a page in a language the reader doesn't actually want, but there are ways to help with that, as we will see below.

For the page you are reading now, the server looks at the Accept-Language header, sent via HTTP when your browser requests a page.

The Accept-language header takes information from either the browser settings or system settings. When you install a browser, default preferences are always set, but in most desktop browsers you can also change or add to the language preferences. You can also specify a prioritised list of languages, so that if a version of the page is not available in your preferred language the server can look for alternative language versions of the page, in the order you prefer.

Be wary about using IP addresses or other location services to guess the language of the user. This approach can be useful for accessing region-specific services or finding local information, etc., but it can cause problems for language negotiation since the location of the user doesn't necessarily tally with the language in which they prefer to read a web page.

Whichever language negotiation method is used, you should ensure that there is a default option, which comes into play when content is not available in the language or languages you requested. In the case of the page you are reading, the fallback is to the English version, because that is the original version, is most up-to-date, and has undergone wide review. English is also chosen because the W3C views it as the most widely accessible lingua franca.

Of course, a user may prefer to fall back to another language that they know well, rather than to English. This is a matter of personal preference. If they prefer to look for another language before being redirected to the English default version, they may be able to do so by setting their browser or system's language preferences to a prioritised list, as mentioned above. If language negotiation fails for their preferred language, the server will try the others in their list, in order.

You may also find the article When to use language negotiation useful. It discusses in more detail when it is appropriate, or not, to use language negotiation.

Using content negotiation also makes it a lot easier to manage translations and to pass links to others.

Without content negotiation, the source text of a page would be full of links hard-wired to a particular language version, such as qa-site-conneg.en.html or qa-site-conneg.html.en. With content negotiation, that link becomes simply qa-site-conneg.

That reduces work for translators, is less prone to error, and makes it easier to manage changes as new language versions are added or old versions removed. It also alleviates potential problems if a user wants to send a link to someone else, since the person receiving the link would automatically see the page in their preferred language.

You may still use something like qa-site-conneg.en, but only when you specifically want to point to the English language version.

Links on the page

As we mentioned above, there may be times when the language requested by the user's browser is not the language they actually prefer when reading that particular page. This may be because they prefer reading technical information in English, or they prefer reading the original rather than a translation, or perhaps they are using a colleague's computer or working from a cyber-café in a foreign country and therefore don't control the browser language preferences.

For these reasons it is always best to add links to alternate language versions, and to do so on every page .

On the page you are currently reading, you'll find them at the top right corner of the page. We put them there to make it easy to spot them as soon as you arrive at the page. Such information should not be hidden, since the user may be looking at a page full of text that means nothing to them. The easier it is to discover those links, the better.

It's true that if a link brings you into the middle of the page you won't see the language selectors, but at least they should be easy to find, if needed.

If you look at the links at the top of this page, you'll notice that they are in the language of the page they point to. This again is to help users find what they need. If you were English and faced with a Persian page, and if the link to the English page was written in the Arabic script, you might not find it easily!

Since we have the space for it, all the links are visible at once. If you have a long list of alternatives, you may prefer to use a pull-down or pop-out list. There can be significant drawbacks with that approach, however. The main one being how to indicate, in a language neutral but clearly recognisable way, what the selection control does. The article Using select to link to localized content goes into greater detail about things you should consider when using a pull-down list.

Another key recommendation is to resist the temptation to use country flags to identify languages. Some countries have more than one language, and some languages are spoken in more than one country. Although flags may be suitable to link to geographically tailored versions of a page, such as a UK vs. a Canadian vs. an Australian retail site, they are not appropriate for linking to pages that are simply translations.

You may also want to show the meaning of the language links using the language of the current page. For instance, on an English page you could include the English version of the language alongside each native version, eg. français (French). We don't do this for the page you are reading, partly due to lack of space, and partly because it doesn't seem necessary. We do, however, produce an English version in a tooltip, which you will see if you mouse over the links. This leads to a slight complication since it isn't possible to use a lang attribute on a single element to indicate that the title text is in one language and the element content in another. Therefore we use two nested elements as shown in this code snippet.

<span title="Swedish"><span translate="no" dir="auto" lang="sv">Svenska</span></span>

The outer span produces the tooltip. The translate attribute prevents automatic translation tools from changing the text Svenska, and the dir attribute isolates the text directionally, ensuring that lists including right-to-left language names retain the expected order.

It may also be worth mentioning that we automate the production of these links to alternative language versions, and store the data in one external file. This makes it much easier when adding or deleting language versions of a page, because it removes the need to manually change the links across all alternative versions.

Overriding the language negotiation

Suppose your native language is Spanish and so your browser is set to receive content in Spanish most of the time, but suppose also that you understand English and you prefer to read technical articles such as W3C pages in the English original.

If you are redirected to a Spanish page every time you follow a link and have to manually move to the English page, this can quickly become tiresome. The reader needs some way to indicate that they want to stay in their preferred language while reading pages on the site, and a mechanism that ensures that they do.

The page you are reading enables this by allowing you to set a cookie any time you click on the language links at the top right of the page. Every time you link to one of these pages, the server checks whether a cookie is set and active, and if so, serves the page in the language in which you last viewed it.

You can do the same thing with localStorage, if you prefer that to cookies.

Additional information

Which type of content negotiation to use on Apache?

The page you are currently reading is served by an Apache server. When doing content negotiation, there are two common ways of managing page redirects with Apache: MultiViews or type maps. We use type maps because we feel it gives us greater flexibility in redirecting requests, but your mileage may vary. The downside is that it requires some additional files on the server, and those files need to be edited when a translation is added or removed. See the next section for a quick overview of type maps. We also have an article that describes how to use MultiViews, if you prefer that approach.

Using type maps for language negotiation

What follows are some brief notes about using the type map approach for language negotiation on a Apache server. See the Apache documentation for full details of how to use this approach.

To use type maps you create a file in the same directory as the main file, with the same name, but with the extension .var. This file is invoked by the server when a file of that name is requested without a language extension (ie. .en, or .de). The file tells the server where to look for a specific language version.

You also need to configure your server to use type maps content negotiation by adding an AddHandler directive. For example, we use:

AddHandler type-map .var

Here is an example of a file called my-article.var:

URI: my-article

Content-language: de
Content-type: text/html

Content-language: en
Content-type: text/html
URI: my-article.en.php

Content-language: es
Content-type: text/html
URI: another-file-with-long-name-so-you-notice.php

Content-language: uk
Content-type: text/html

Content-type: text/html
URI: my-article.en.php

When a request comes in for the resource, the server looks at the Accept-Language header sent by the browser. If it is de (German), the server will look down the list and send back the file

Now note how, if the incoming Accept-Language header is set to es (Spanish), the server routes the request to a file with a completely different name. It could also be in a different directory.

Finally note that the last two lines define the default case: if no Accept-Language is matched to the items above, the server will return the nominated file (in this case the English version at my-article.en.php).