Multilingual Web Pages Via PHP, Arrays And MySQL

Asked recently on Yahoo! Answers:

What is the best method to create a multi-lingual website?
Do we use xml, php, or what??? and how, help appreciated.

There are many different ways to go about having a Web page appear in multiple languages, and I may address others in upcoming articles. The approach I am going to focus on in this post assumes you already have your translations in hand, and simply want to give users a choice of languages in which your page can appear.

In the future, I may address ways of determining the default language to present to a user, based on his browser’s user-agent string; translating text on-the-fly via AJAX and one of the free translation Web sites (even ones that don’t have an API), and using alternative data sources, depending on interest in this article.

For now, two demos using PHP: The first will employ an array, the second will use a database as its back end. As always, I will have a link to a working demo and code you can download at the end of the discussion.

Example 1: Arrays

A very common way for many Web applications — such as phpBB, phpMyAdmin and others — to provide multi-language support is through arrays. Simply put, you place all your translations into a multi-dimensional associative array, or a bunch of single-dimension arrays, and echo out the appropriate cell of the array based on the user’s language input.

Here are examples of what I am talking about:

//multidimensional associative arrays;
//first dimension, language; second dimension, section
$translation['en']['hello'] = "Hello, World!";
$translation['fr']['hello'] = "Bonjour, Monde!";

//single-dimension arrays
//variable name: section; first dimension, language
$hello[0] = "Hello, World!";
$hello[1] = "Bonjour, Monde!";

Example 1, Step 1: Add Translations To Arrays

We’ll use the many single-dimension arrays approach, largely because I am lazy and didn’t want to go through the extra effort of writing an associative multidimensional array. I’m also going to provide three languages for my page: English, French and Spanish.

So, I declare several arrays, each for a section of the Web page I want to have translated. And I always put the translations in the same order for each array. That is, English is always the first item in the array; French, always the second; Spanish, always the third.

That way, I can select the same index for all the arrays I wind up declaring, and that index will always be the same language, regardless of the variable.

$hello = array('Hello World!', 'Bonjour Monde!', '¡Hola Mundo!');
$caption = array('Teena And Nikki Collins played the twin daughters of Doug The Head in the motion picture "Snatch."', 'Teena et Nikki Collins ont joué les filles jumelles de Doug La Tête dans le film cinématographique "Snatch."', 'Teena y Nikki Collins jugaron a hijas gemelas de Doug La Cabeza en la película "Snatch."');
$goodbye = array('Goodbye!', 'Au revoir!', '¡Adios!');

(Notice that I have taken care to convert all special characters, such as è and ¡, to HTML entities. Also, I got these translations from babelfish.yahoo.com; if they make no sense, it’s Yahoo!’s fault. Finally, I have purposely omitted the $gettysburg array present in the demo and download code because it is very, very long.)

Example 1, Step 2: Selecting The Correct Language

We now have an important decision: What will be the default language for the page? I’m choosing English, but it could just as easily be French or Spanish; you can choose any language you want as a default.

We need a simple switch statement at the top of our page. It’s going to set a variable for us based on the value of the lang variable in the querystring. If there is no lang variable, or the value of lang is not one of the specifically enumerated language variables in the switch statement, we’ll use the default language (English). This covers both the first-time visit to the page, and people tampering with the querystring values.

switch($_GET['lang']) {
	case 'fr':
		$lng = 1;
		break;
	case 'sp':
		$lng = 2;
		break;
	default:
		$lng = 0;
}

Example 1, Step 3: A Form To Change Languages

We need a simple PHP form to handle which language to use. It’s a form that gets back to itself; a SELECT named lang, with our translations as options; and a submit button. I’ve also added a JavaScript onchange event to automatically submit the form; more on that momentarily.

<form action="<?php echo $_SERVER['PHP_SELF']; ?<" method="get"<
	<label for="lang"<select Language:</label<
	<select id="lang" name="lang" onchange="submitForm()"<
		<option value="en"<?php if($_GET['lang'] != 'fr' && $_GET['lang'] != 'sp'){ echo " selected="selected"";} ?>>English</option>
		<option value="fr"<?php if($_GET['lang'] == 'fr'){ echo " selected="selected"";} ?>>French</option<
		<option value="sp"<?php if($_GET['lang'] == 'sp'){ echo " selected="selected"";} ?>>Spanish</option>
	</select>
	<input name="submit" type="submit" value="Translate!" />
</form>

(Notice that each option checks the querystring to see if it’s selected. Since we are getting this page every time the form is submitted, it’s good form to show in the list the currently selected language; if we didn’t do this, the list would continually show the first item (English) after every submission, even if English isn’t the current selected language.)

Example 1, Step 4: The JavaScript submitForm() Function

Our JavaScript function to submit the form will basically get the currently selected value from the drop-down list, append it to the path of the current page as the lang querystring’s value, and reload the page.

function submitForm() {
	var thelang = document.getElementById('lang').options[document.getElementById('lang').selectedIndex].value;
	window.location.href = window.location.pathname + '?lang=' + thelang;
}

Example 1, Step 5: Output The Proper Text

Showing the proper language is as simple as echoing the array for the text you want to display, at the index we chose with our switch statement:

<div lang="mainContainer">
	<h1><?php echo $hello[$lng]; ?></h1>
	<div lang="imgBox">
		<a href="http://www.imdb.com/gallery/granitz/1458/Events/1458/NikkiColli_Ausse_491530_400.jpg"><img src="NikkiColli_Ausse_491530_400.jpg" alt="Teena and Nikki Collins" title="Teena and Nikki Collins" /></a>
		<br />
		<?php echo $caption[$lng]; ?>
	</div>
	<p><?php echo $gettysburg[$lng]; ?></p>
	<p><em><?php echo $goodbye[$lng]; ?></em></p>
</div>

You can see a working demo of this approach here:

http://demo.dougv.com/php_translate/

Example 2: Database Back End

If you have many, many Web pages that are changing often, the arrays approach may not be the right choice for you. So, if you have access to a MySQL database — and virtually all Web hosts offering PHP offer MySQL, too — then it may well prove a better choice.

We need to make a few changes in our approach to get the PHP version to work, but it is fundamentally similar to the approach in Example 1.

Example 2, Step 1: Create The Database Table And Populate It

Our table has four columns:

  • A unique identifier / primary key column;
  • a varchar column that indicates the content we want;
  • a char column indicating the language used; and
  • a text column containing the translation.
CREATE TABLE IF NOT EXISTS `php_translate` (
  `record_id` int(10) unsigned NOT NULL auto_increment,
  `trans_section` varchar(20) NOT NULL,
  `trans_lang` char(2) NOT NULL,
  `trans_text` longtext NOT NULL,
  PRIMARY KEY  (`record_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;

(I’ve included the sample table and records I have used for the demo in the download file.)

Example 2, Step 2: Connect To Database, Set Language

First, we connect to our database:

$link = mysql_connect('server_name', 'username', 'password') or die('cannot connect to db server');
mysql_select_db('database_name') or die('cannot select database');

Next, we change the method for determining if we have a good lang querystring variable. In this case, we’re going to use a regular expression to test if the variable contains one of our accepted language values; if it does not, we set the default language.

if(!preg_match('/^(fr)|(en)|(sp)$/', $_GET['lang'])) {
	$lng = 'en';
}
else {
	$lng = $_GET['lang'];
}

Example 2, Step 3: Get The Appropriate Translation From The Database

Based on the chosen language, we run a simple SELECT query to get all records that match the chosen language.

(Note that you might want to change the query’s WHERE clause to select only sections that will appear on the page, or maybe even add a column to indicate which text appears on which page of the site. This is a modification I may address in the future if there is interest.)

We’re going to read all the selected records into a single-dimensional keyed array — by assigning each key to be the section column, and each value to be the text column.

$trans = array();
$rs = mysql_query("SELECT trans_section, trans_text FROM php_translate WHERE trans_lang = '$lng'") or die('cannot select language from database');
while($row = mysql_fetch_array($rs)) {
	$trans[$row['trans_section']] = $row['trans_text'];
}

Example 2, Step 4: Create the HTML Language Selection Form And the JavaScript Form Submission Function

Because the form and the JavaScript submission function work the same in both examples, I won’t revisit them here.

Example 2, Step 5: Print Out The Appropriate Sections

Again, printing out the appropriate translations is very simple: We just echo out the appropriate key from the array we made in Step 3.

<div lang="mainContainer">
	<h1><?php echo $trans['hello']; ?></h1>
	<div lang="imgBox">
		<a href="http://www.imdb.com/gallery/granitz/1458/Events/1458/NikkiColli_Ausse_491530_400.jpg"><img src="NikkiColli_Ausse_491530_400.jpg" alt="Teena and Nikki Collins" title="Teena and Nikki Collins" /></a>
		<br />
		<?php echo $trans['caption']; ?>
	</div>
	<p><?php echo $trans['gettysburg']; ?></p>
	<p><em><?php echo $trans['goodbye']; ?></em></p>
</div>

You can see a working demo of this example here: http://demo.dougv.com/php_translate/db.php

This code on GitHub: https://github.com/dougvdotcom/php-translate

20 Comments

  1. Hiiiiiiiii there,

    Thanks for this useful post, however I used the first approach and it works fine for me. So keep it up……..

  2. Hi,
    Thanks for the tutorial, was very helpful.
    I just have one question.
    If I choose the second example how would I link pages so that when a link is pressed it prompts you to that page with the language you already selected?

  3. Hi Doug, I really enjoyed this tut. Do you know of a solution in PHP array that would enable Asian character translations such as Chinese or Korean ?

  4. @nomadsoul: If your pages are encoded in UTF-8, and you either 1. set your database collation to be UTF-8 or 2. save the file containing your translations as UTF-8, then there should be no problem using Chinese, Korean or other non-Latin character sets. A good text editor that can save UTF-8 encoded files in a must: for PC, either Notepad++ or Sublime Text; for Mac, either TextWrangler or BBEdit.

  5. Hello thanks for the such too helpful and nice tutorial, but i want some text to post the data within selected language to translate the input typed data into dropdown selected language

    I am talking about your First array post can you modified it with some html tags to covert into their selected language code
    when i entered or type the data into input it must be convert into same as selected language can you provide me something this type of example??

  6. Hello and thanks for your post it has been the most helpful i’ve found so far. If my website has different pages for example Home, Page2, Page3 and etc… and 4 languages, how would this work in regards to the second example.

    Would it make more sense to have a separate php file for each language?
    Do i store the translation for each page in the database and then pull it to the site when the language is selected?

  7. @Jessica:

    Would it make more sense to have a separate php file for each language?

    If you’re going to use a MySQL database, then it really depends on the depth of your site.

    You could use the trans_section column to record the page; or, if you need to use the section field, you could add another column in the database, called something like trans_page, and store the URL to the page there.

    You could then look up the translation by calling $_SERVER[‘SCRIPT_NAME’] to get the relative path to the page, and look that up in your database; either in trans_section or your new trans_page column.

    Do i store the translation for each page in the database and then pull it to the site when the language is selected?

    The short answer is yes.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!