Recently, I had to develop a small web portal for a client. Since the portal consisted mostly of static pages which the client wanted to update himself, and I had limited time for development, WordPress platform was an obvious choice. We agreed to derive the design from the standard “Responsive” theme (WordPress Codex has a great article on how to do that).
The portal had to be multi-lingual, most pages would be in English, but some would have translations in Latvian. I found WordPress qTranslate plugin the best solution for my needs. It changes the way WordPress dashboard forms work, now a blog post has two fields “Title (Latvian)” and “Title (English)” as well as “Post content (Latvian)” and “Post content (English)”. If you don’t fill the fields for a particular language, the page would be treated as not translated and may be hidden in the navigation as well. You have to pick the default language of the site – what content to show if the user has not picked any language.
qTranslate provides several ways how you can do localization:
- using a subdomain, e.g. lv.yourdomain.com and en.yourdomain.com
- by adding a GET parameter to each page, eg. yourdomain.com/article_title/?lang=lv
- using a directory prefix, e.g. yourdomain.com/lv/articletitle, yourdomain.com/en/articletitle
I picked the latter, as it seemed most rational of the three. Now every page had two addresses and everything seemed to be running just fine. However, I found it a bit annoying that a returning visitor always sees the default language, regardless which language he had chosen in the previous visit. It would seem logical that qTranslate could just set a cookie “last language” or something like that. I found out, it does not. Moreover, qTranslate authors are not going to implement it, they say “it’s a wanted behavior”.
Not wanting to mess with plugin’s PHP code, I decided to fix this at the web server level (as you may know, Apache Mod_Rewrite can both read and set cookies).
So, I needed two parts of the algorithm:
— when the user requests a page where the URL contains language code, save that language in a cookie. In “.htaccess language” it is
#Only for requests which start with "/lv/" or "/en/".
RewriteCond %{REQUEST_URI} ^/(lv|en)/.*$ [NC]
#no need to set a cookie if you already have one with the same value
RewriteCond %{HTTP_COOKIE} !lang=%1 [NC]
#rewrite to the same address, but set a cookie to the value captured in first RewriteCond
RewriteRule . - [cookie=lang:%1:.%{HTTP_HOST}:144000:/]
— when the user requests the “root” of the portal and there is a “lang” cookie set, do a redirect to the particular language root page
#only for the root page /
RewriteCond %{REQUEST_URI} ^/$ [NC]
#only if you have a "lang" cookie
RewriteCond %{HTTP_COOKIE} lang=(en|lv) [NC] \
#redirect (not rewrite!) to either /en/ or /lv/
RewriteRule ^(.*)$ /%1/ [R=302,L]
So, after all modifications my .htaccess
file looks like this:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/$ [NC]
RewriteCond %{HTTP_COOKIE} lang=(lv|en) [NC]
RewriteRule ^(.*)$ /%1/ [R=302,L]
RewriteCond %{REQUEST_URI} ^/(lv|en)/.*$ [NC]
RewriteCond %{HTTP_COOKIE} !lang=%1 [NC]
RewriteRule . - [cookie=lang:%1:.%{HTTP_HOST}:144000:/]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress