Single string with multiple translations

Posted on Aug 12, 2010 in Wordpress | 1 comment

Multilingual wordpress sites are not as straight-foward to create as you may think (unless you’re using multi-site). There are various plugins that make this easier, although they all lack something or other (my favourite is qTranslate so far). It gets tricky when you add custom text to sidebars, other plugins, or your themes. It’s not really the fault of the translation plugins either, because it’s literally impossible to reliably force plugin outputs to be translated in a user-friendly manner.

I came across a problem like this where a custom theme I made needed to accommodate the multilingual capabilities of qTranslate for some small snippets of text here and there which could be added in the theme options page (e.g. address, slogans etc.). The amount of work that would be required to make a multilingual options page was not justifiable for the project. So…. I came up with a pretty simple solution which I’m sure others can easily use in their plugins and themes:

Basically, if used, you can pass along text wrapped in curly bracket tags, much like html except the tags use curly brackets and the tag names are the language code(e.g. en_US, de_DE, fr_FR). The result is that you could add this to a text box:

{en_US}english text{/en_US}{fr_FR}french text{/fr_FR}

With the above string the function will choose the correct language based on the current wordpress locale, and if that doesn’t exist, revert to the first language in the string. This is also compatible with non-translated strings. Whilst not ideal for a whole post, this would definitely come in handy for smaller snippets of text, such as widget titles, theme texts, etc. where fully fledged translation functionality is not needed.

Without further ado, here is the function:

 * Separates a string by {lang_code}{/lang_code} 
 * style wrappers and returns the desired locale. If the locale 
 * parameter is empty, function will use default locale (e.g. en_US).
 * If no local is matched, the first language is used. If no brackets 
 * are enclosed, the $string param is returned as is.
 * @param $string
 * @param $locale
 * @return string
function ml_string($string, $locale = ''){
	$locale = ($locale == '') ? get_locale():$locale;
	//Do a regex and extract all text within braces
	$matches = array();
	preg_match_all('/{([a-zA-Z_]{5})}([^{]+){/[a-zA-Z_]{5}}/', $string, $matches);
	if( count($matches[0]) > 0 ){
		//Check if the language we want exists, if not we take the first language there
		foreach($matches[1] as $key => $lang){
			if ($lang == $locale) {
				return $matches[2][$key];
		return $matches[2][0];
	return $string;