Making WordPress’s qTranslate plugin work on different domain names

Recently I was handed a WordPress site for a client that used qTranslate for various versions of their website in different languages. The caveat was that each language needed its own domain name, not a subdomain, path or query string of the main one. For sure I could have redirected the welsh domain to the english version with the /cy/ path in it, but I had a better idea. Use nginx. This is utterly genius.

First, configure your main site. This will be the english, the default language configured within qTranslate. qTranslate is configured using the “pre-path” language selection.

server {
	listen 80;
	server_name	www.englishdomain.com;
 
	root /var/www/website;
 
	location ~ ^/cy/.*$ {
		rewrite ^/cy/(.*)$ http://www.welshdomain.com/$1 redirect;
	}
 
	location / {
		proxy_set_header	X-Forwarded-For		$proxy_add_x_forwarded_for;
		proxy_set_header	Host			www.englishdomain.com;
		proxy_set_header	Accept-Encoding		"";
		proxy_read_timeout	120;
		proxy_pass		http://127.0.0.1:8000;
		proxy_redirect		default;
 
                sub_filter_once off;
                sub_filter 'www.englishdomain.com/cy' 'www.welshdomain.com';
	}
}

Almost the same again for your welsh domain, with a few subtle alterations:

server {
	listen 80;
	server_name	www.welshdomain.com;
 
	root /var/www/website;
 
	location / {
		rewrite ^/(.*)$ /cy/$1 last;
                break;
	}
 
	location ~* ^/cy/ {
                proxy_set_header        X-Forwarded-For         $proxy_add_x_forwarded_for;
                proxy_set_header        Host                    www.englishdomain.com;
		proxy_set_header	Accept-Encoding		"";
                proxy_read_timeout      120;
                proxy_pass              http://127.0.0.1:8000;
		proxy_redirect		default;
 
                sub_filter_once off;
                sub_filter 'www.englishdomain.com/cy' 'www.welshdomain.com';
	}
}

Finally, your backend Apache configuration:

<VirtualHost *:8000>
	ServerName www.englishdomain.com
	DocumentRoot /var/www/website
 
	<Location />
		RemoveOutputFilter DEFLATE
	</Location>
</VirtualHost>

What’s going on here:

  • Visits to www.englishdomain.com get passed straight through.
  • The output from the Apache backend is manipulated using sub_filter to rewrite the HTML inline from www.englishdomain.com/cy to www.welshdomain.com
  • Any visits to www.englishdomain.com/cy/ are rewritten with a 302 to www.welshdomain.com, though this isn’t strictly necessary due to the above HTML rewrite, and the below functions of the welsh domain’s configuration
  • Visits to www.welshdomain.com are rewritten transparently to www.englishdomain.com/cy/ then passed via a proxy back to Apache
  • Again, the HTML is rewritten inline by nginx’s sub_filter to keep the domain consistent and to stop the user being sent back and forth all the time

Using these sets of rules, I was able to achieve something that qTranslate isn’t strictly able to do – provide translation using completely different domain names. In this configuration, WordPress is none the wiser, all it sees is visits to www.englishdomain.com, suffixed with the path of the selected language which is “injected” into the URI before being sent to proxy_pass. This likely won’t work for more than one translation, as you can only specify sub_filter once per configuration. There is an nginx module called HttpSubsModule which allows you to specify multiple sub_filter rules (using its own syntax and commands, obviously), so then in theory you should be able to replicate the welsh domain’s configuration for each other language you want to use, and duplicate the subs_filter rules to rewrite the HTML inline to send users to the correct domain names for each language.