Michael Dayah of Ptable.com asked about how to extend the technique from Serving XHTML with Apache MultiViews and Serving Pre-Compressed Files with Apache MultiViews to serve files for a language requested using a query parameter. This post outlines the slick technique we worked out.

Initially we investigated using mod_rewrite and mod_headers in various ways. Unfortunately, it appears that mod_negotiation (which implements MultiViews) performs negotiation in the type_checker hook of the preparation phase of request processing (see mod_negotiation.c:3212) which is before the fixup hook used by mod_headers (see mod_headers.c:1007) and mod_rewrite (see mod_rewrite.c:5315). This prevents header or environment changes made by those modules from affecting MultiViews negotiation, unless other trickery (e.g. sub-requests) is used.

The solution we came up with is to use SetEnvIfExpr from mod_setenvif to set the prefer-language environment variable. For example, to use the language from a query parameter named lang if it contains a value which might be a valid Basic Language Range for Accept-Language:

Options +MultiViews
SetEnvIfExpr "%{QUERY_STRING} =~ /(?:^|&)lang=([A-Za-z]{1,8}(?:-[A-Za-z0-9]{1,8})*)(?:&|$)/" prefer-language=$1

This combination should be sufficient for requests such as GET /index.html?lang=fr to return index.html.fr regardless of the value in the Accept-Language request header, if present.

Note: The mapping from language tags to file extensions is configured by AddLanguage. On Debian, the default mapping is defined in /etc/apache2/mods-available/mime.conf (linked from /etc/apache2/mods-enabled/mime.conf when mod_mime is enabled) and can be changed using RemoveLanguage/AddLanguage as desired.

Best of luck!