At one of my former workplaces, Cendio AB, I ran a Plone site that can be accessed either in english by visiting http://www.cendio.com/, or in swedish, by visiting http://www.cendio.se/.

This approach has both pros and cons. Among the pros is that it's really easy to give away a URL that's always in the correct language when communicating with people - we have a lot of swedish customers, and we want them to get a swedish page all the time. Among the cons are that it's hard to support sessions that persist even if the language is changed. Since we have a site that is only editable by people at Cendio, this is currently not a problem for us.

Another reason that we have this configuration is that we've always had this configuration, so we and our customers are used to it.

In this HOWTO, I'll explain how this kind of setup can be accomplished with Plone 2.1.x and LinguaPlone.

You'll need basic understanding of VirtualHost configuration as well as Apache2 and Plone configuration to understand this HOWTO.

Theory of Operation

When I first started investigating if this kind of setup was possible with Plone, I found almost no documentation that stated that it was indeed doable. The LinguaPlone slides from the plone conference of 2005 hinted that it could be possible, but I found no HOWTOs or other explanations. I tried asking on the plone-users list, but I didn't get any answers that helped.

I sat down and did some creative thinking, and the setup described in this HOWTO is the result.

How does LinguaPlone Select Language?

LinguaPlone has several different methods for determining which language should be shown for a specific request:

  • Using the Accept-Language header in the HTTP request.
  • Using the URL (adding ?set_language=<language> to the URL of each request.
  • Using a cookie (I18N_DOMAIN)

In our setup, we actually use all three of them.

Forcing Plone to Use One Language per Domain

In my setup, I'm using the plone language selection features by replacing some of the headers set by the browser. Specifically, I replace the Accept-Language header and the cookie, by using features in the mod_rewrite module of the Apache2 instance that serves as a frontend.

In the VirtualHost for the swedish version of the site, I have the following statements:

RequestHeader set Accept-Language: sv
RequestHeader set Cookie: I18N_LANGUAGE="sv"

In the VirtualHost for the english version of the site, I have the following statements:

RequestHeader set Accept-Language: en
RequestHeader set Cookie: I18N_LANGUAGE="en"

Switching between languages

If a visitor wants to change language, perhaps because he found the english site but speaks swedish and therefore wants to switch to the swedish site, he can switch language using the standard LinguaPlone flags.

This is accomplished by using some mod_rewrite RewriteRule's in Apache2:

RewriteCond %{QUERY_STRING} set_language=en
RewriteCond %{SERVER_PORT} 443
RewriteRule ^/(.*)$ https://www.example.com/$1? [R,L]

RewriteCond %{QUERY_STRING} set_language=en
RewriteCond %{SERVER_PORT} 80
RewriteRule ^/(.*)$ http://www.example.com/$1? [R,L]

RewriteCond %{QUERY_STRING} set_language=sv
RewriteCond %{SERVER_PORT} 443
RewriteRule ^/(.*)$ https://www.example.se/$1? [R,L]

RewriteCond %{QUERY_STRING} set_language=sv
RewriteCond %{SERVER_PORT} 80
RewriteRule ^/(.*)$ http://www.example.se/$1? [R,L]

This catches requests that wants to switch language, and redirects them to the correct domain for the language. There are two rules per language, to allow for both http and https requests.

Editing Content

To allow editing of content, there's a third VirtualHost, webedit.example.com. It has no rewriting of the RequestHeaders nor any rewriting of requests containing set_language in the URL. Without this host, it's not possible to do multilingual editing (well, you can go directly to the plone instance, but since I want SSL protection of content editing operatings, a VirtualHost is of need), since the rewrite rules that make sure the respective hosts are served in two different languages interferes with how editing of multilingual objects work in LinguaPlone.

That's all, folks!