From the start, I was interested in making the content posted here available in two languages: Greek and English. This is no small feat, and I thought long and hard on how to make it possible and get it working just the way I like it. So here is a rundown of how internationalization works here:
The prerequisites are not many:
Make the content available in both languages.
Make the interface available in both languages.
I have slacked and made the tags English-only. Maybe I'll fix that later on, but it'll do for now.
Now, you have two choices about making a site handle international visitors. You either:
let them decide what language they prefer, by providing the choices somewhere in your interface or,
try to use their request data (like the IP address, or the language preference sent by their browser) to decide their preferred language.
The first approach is the most foolproof, as a user explicitly chooses his language. He can't be wrong, can he? But, there is a snag: what is the first page he sees? If it is in his own language, there's no problem. But if it is in another language, he'll get confused and probably leave. Advanced users may scan the interface for visual clues to change the language (if they know they have this option). With first impressions being so important, you shouldn't scare your visitors away.
This is solved by the second approach, mostly. However, the problem there lies in that a) the location of the user not always matches their language, b) most users never set their language preference in their browser anyway (I have no source for this, it's just a gut feeling) and c) the user has no visible choice in your site. If you guess wrong, he can't change it, so he leaves.
Well, this leaves us with the only sensible approach: Combine these two. So this is what I've done, of course aided by Django.
We first try to find implicit facts that point to a language. In Django, this is done using the LocaleMiddleware:
LocaleMiddleware tries to determine the user’s language preference by following this algorithm:
First, it looks for a django_language key in the the current user’s session.
Failing that, it looks for a cookie called django_language.
Failing that, it looks at the Accept-Language HTTP header. This header is sent by your browser and tells the server which language(s) you prefer, in order by priority. Django tries each language in the header until it finds one with available translations.
Failing that, it uses the global LANGUAGE_CODE setting.
This is a pretty good approach, as it handles both new and returning visitors.
We also provide a simple interface, the two little flags on the right edge of the header, to give the option of setting the language explicitly. This should cover us but...
Unfortunately, we have to deal with search engines, too. Crawlers don't have sessions, nor accept cookies, nor emit
Accept-Language HTTP headers. So they'll reach only your default language. If we continue this reasoning, you'll have issues with incoming links too: When I link to a page that is in Greek, I'll expect my link to point in the same version. So we have to somehow put the language information on the URL too. Since we have everything translated, it makes sense to put the language in the lowest level possible:
So now, if someone links to a page, he also links to a language. So far so good. What about our first page, without any paths appended ? What would come up if someone bookmarked
http://www.example.com ? Of course we will use the discovery mechanism described above and redirect him to the language we guess. This will work with crawlers too, as they handle redirects. The crawler will also find the language setting flags and will happily index all our languages, since now they have distinct URLs.
There's also the possibility that a visitor will follow a link that is in another language than his own. We could try to redirect him to his preferred language, but this will put us back in the first, half-baked approach. Plus, he'll never be able to view content in another language, unless he clears his session and cookies, and change his preferred language in his browser. Instead, we'll just give him a discreet message in his preferred language notifying him that the content he is viewing is also available in another language, and give him the link to it.
I haven't implemented any of this at the time of writing. I'll try to, and present the code and results in the part 2 of this article.