Better Navigation for Multilingual Sites

Thursday Aug 12th 2004 by Benoît Marchal

It's a big world out there! Remember to code appropriately to reach global users.

Adapting or creating a site for a global audience is a significant challenge. You need to localize the content, be ready to answer requests in foreign languages and, if you sell online, comply with local regulations in terms of privacy, taxation and more.

From a design standpoint, you need to integrate the localized content in the navigation. You want foreign visitors to find the localized content that was so hard to create!

HTTP Helps

HTTP can help with the navigation thanks to "content negotiation." The principle is the following: when the client requests a resource from the server, it adds information about the user preference, including the languages that he or she speaks. The server analyses the header and returns the most appropriate localized version.

The header looks like:

Accept-Language: fr-be, fr; q=0.8 en; q=0.5

I.e. it lists acceptable locales (according to RFC 1766). The optional q "quality" parameter establishes an hierarchy. The higher q are to be prefered so, in the above example, the user would want the Belgian French version, failing the generic French version, failing that the English version.


The Apache web server implements content negotiation through the mod_negotiate module. By default the module is built with Apache.

mod_negotiate supports two working modes: type-map files and multi views. Type-map are more flexible and I prefer to use it. To enbable type-map, uncomment the following line in httpd.conf and restart the server:

AddHandler type-map var

Alternatively you can add the statement to an .htaccess file, e.g. for virtual servers.

Next you must prepare a type-map for localized resources. The type-map associates files and languages. Listing 1 is an example:

Listing 1: about.var

URI: about

URI: special.cgi 

Content-Language: fr, fr-be, fr-ca, fr-ch, fr-lu, fr-mc 

Content-type: text/html 

Description: Français 

URI: about-german.html 

Content-Language: de, de-ch, de-at, de-lu, de-li 

Content-type: text/html 

Description: Deutsch

URI: about.html 

Content-Language: en, en-au, en-bz, en-ca, en-ie, en-jm, en-nz, en-ph, en-za, en-tt, en-gb, en-us, en-zw 

Content-type: text/html 

Description: English 

The type-map is broken down in sections. The first section gives the URI for the multi-lingual ressource. In the above example, if the client accesses http://domain/about, the server will return localized content.

The following associates language tags to a specific resource. If the client requests one of the French locales, then the server will call the special.cgi script, if the user requests a German locale, the server returns about-german.html and if the user request an English page, the server returns about.html.

You can add more sections to support more languages. The URIs can point to CGI scripts, redirections, servlets, anything.

The Language Tag Problem

Unfortunately content negotiation is another great protocol that is hampered by poor browser implementations.

Technically, the user can request either a generic language, e.g. en for English, or a variation of the language, e.g. en-us for American English or en-gb for British English. In practice, users who read a variation understand the generic language as well.

Therefore browsers are encouraged to request both the specific variation and the more generic language. By default, the major browsers request only specific language, e.g. American English to the exclusion of generic English.

Since few users bother to change the default configuration, it pays to list all the variations in the type-map.

Error Handling

If the browser requests a local that is not available, mod_negotiate generates a (rather unfriendly) error 406. You can trap the error page through the usual ErrorDocument directive or by adding the following URI section immediately under URI:about

URI: none.html 

Content-type: text/html 

Description: Default

Multi Views

I like type-maps because they are very flexible. Depending on the locale, a resource can point to HTML pages, CGI scripts, servlets or even redirection (send them to a country-specific site).

If you localize many pages, you may not want to write all the type maps. mod_negotiate also support multi views which let it extract the language from the file name. See the Apache manual for information on multi views.


Content negotiation greatly simplifies the navigation of localized web site. Don't bother asking the user for his or her language preferences, get them from the browser.

About the Author

Benoît Marchal is a Belgian writer and consultant. He is the author of XML by Example and other XML books. He is currently developing new training material on UML modelling and XML.

Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved