Of all the things that are taught in web development classes, Server Side Includes never seems to come up. Server Side Includes (SSI for short) is a simple scripting language that can be used in web pages as an alternative to more complex languages such as Perl and PHP. Whilst SSI may lack many of the advanced features of other scripting languages, it is a powerful tool in its own right. In this tutorial, I will introduce you to some SSI basics, then move on to demonstrating how to produce a multilingual server side includes page using only HTML.
This article was last updated on the 4th March, 2018 (8th Adar, 5780) to use non-legacy flow control elements.
Configuring Your Web Server
Depending on your environment, a little configuration might be required to start using SSI. If you’re new to web servers, check out my post on my development environment to get a few links to some of the more common server stacks that you can use.
Apache (including MAMP)
Put the following code in a .htaccess
file in the directory that you’re working in, and SSI should work.
Options +Includes
AddType text/html .shtml
AddHandler server-parsed .shtml
AddOutputFilter INCLUDES .shtml
Microsoft IIS
Depending on what version of IIS you have, you’ll need to open Internet Information Services Manager and find the ServerSideIncludeModule
module/Web Service Extension. Then you can enable SSI on individual websites in each site’s Properties options. Make sure that index.shtml
is included in your default content pages.
Nginx
In your Nginx conf.d
file, add ssi on;
to the location
block for the relevant site. Alternatively, add ssi on;
within a location /
block to enable it for every site. Ensure that index.shtml
is included in your default pages list. For example:
location / {
root /var/www/html/;
index index.html index.php index.shtml;
ssi on;
}
The SSI Basics
SSI uses a series of HTML comments to introduce scripted functionality to otherwise static pages. Like PHP, it must be interpreted every time the page is opened. Here’s an example of an SSI statement:
<!DOCTYPE html>
<html lang="en-GB" dir="ltr">
<head>
<meta charset="utf-8" />
<title>Hello Server Side Includes!</title>
</head>
<body>
<h1>Today's date and time:</h1>
<p><!--#echo var="DATE_LOCAL" --></p>
</body>
</html>
SSI is traditionally included in an shtml file instead of a html file. Save this code in a file with the shtml
suffix, such as index.shtml
, then point your browser to its location on your web server. If everything is set up right, you should see something like the picture below in your web browser.
If nothing shows up, don’t panic! View the page source in your browser. If you can see the statement we added as a HTML comment in the page source, then you haven’t enabled SSI, or it isn’t configured properly. Go back up to the configuration step, or check the documentation for your web server.
As you can see, including <!--#echo var="DATE_LOCAL" -->
in the page has resulted in the local date and time being printed to the webpage when you open it in your browser. Every SSI statement looks similar to this. For example, <!--#echo var="LAST_MODIFIED" -->
will display the date and time that the current file was last modified. You can see what this looks like on the page we created in the picture below.
The top date and time is the local date and time that we originally added. The latter is the last modified date, showing when the page was updated to include that statement.
Creating A Multilingual Page
Let’s say that we want to create a small personal website that will be available in both English and Hebrew. I’ve chosen these two languages in particular as they are both written in opposite directions. We’re going to start by creating the English version of the page, which will serve as our base template.
<!DOCTYPE html>
<html lang="en-GB" dir="ltr">
<head>
<meta charset="utf-8" />
<title>Rachel's Webpage</title>
</head>
<body>
<h1>Rachel</h1>
<p>Hello World!</p>
</body>
</html>
As you can see, it isn’t all that different to the page we created earlier. There’s a few different ways we can go about creating a multilingual website. We can separate out two sets of HTML files into an en/
directory and a he/
directory. We can also separate out the languages into separate domains entirely, such as https://www.rauchland.com/
and https://www.rauchland.co.il/
. We aren’t going to do either of those; we’re going to use query strings.
Query Strings and Conditional Statements
If you don’t know what a query string is, they are a list of variables that are appended to the end of a URL in your address bar, after the ?
. A common example of this is YouTube links, where v=dQw4w9WgXcQ
is the query string of the URL https://www.youtube.com/watch?v=dQw4w9WgXcQ
.
We’re going to use the query string ?lang=en
for our English version, and the query string ?lang=he
for our Hebrew version. The default – the URL without a query string – will be English.
To do this, we’re going to have to add an IF statement that evaluates what the current query string is against a regular expression. Because the default page is English, we’re going to check if the query string states the language should be Hebrew. If it doesn’t, it will just default to English. The syntax for this is incredibly simple, as you can see below.
<!DOCTYPE html>
<html lang="en-GB" dir="ltr">
<head>
<meta charset="utf-8" />
<title>Rachel's Webpage</title>
</head>
<body>
<!--#if expr"%{QUERY_STRING} =~ /lang=he/" -->
<h1>רחל</h1>
<p>!שלום עולם</p>
<!--#else -->
<h1>Rachel</h1>
<p>Hello World!</p>
<!--#endif -->
</body>
</html>
Now we have two separate languages in a single page. If you open the page without SSI support enabled, you will see both languages. With SSI enabled, however, you will only see the language specific to your current query string. If you visit index.shtml
or index.shtml?lang=en
, or any other query string that isn’t defined in the code, the page will be in English. If you visit index.shtml?lang=he
, it will be in Hebrew.
More Than One Conditional On One Page
The page will work, but it won’t work well. As you can see, in the html
tag, we defined the page language as “English – Great Britain” and the direction as “left to right”. To render Hebrew properly and produce more semantic HTML, we need to change these values to “Hebrew – Israel” and “right to left” when the page is in Hebrew. How do we do that, you ask? Exactly the same way as we changed the content language before.
<!DOCTYPE html>
<!--#if expr="%{QUERY_STRING} =~ /lang=he/" --><html lang="he-IL" dir="rtl">
<!--#else --><html lang="en-GB" dir="ltr"><!--#endif -->
<head>
<meta charset="utf-8" />
<title>Rachel's Webpage</title>
</head>
<body>
<!--#if expr"%{QUERY_STRING} =~ /lang=he/" -->
<h1>רחל</h1>
<p>!שלום עולם</p>
<!--#else -->
<h1>Rachel</h1>
<p>Hello World!</p>
<!--#endif -->
</body>
</html>
And there you have it! Now the page will display the content in the right direction for the right language. If you want to let your users change the language of the page, you can just add an anchor with the appropriate query string to the page.
<!DOCTYPE html>
<!--#if expr="%{QUERY_STRING} =~ /lang=he/" --><html lang="he-IL" dir="rtl">
<!--#else --><html lang="en-GB" dir="ltr"><!--#endif -->
<head>
<meta charset="utf-8" />
<title>Rachel's Webpage</title>
</head>
<body>
<!--#if expr"%{QUERY_STRING} =~ /lang=he/" -->
<h1>רחל</h1>
<p>!שלום עולם</p>
<a href="index.shtml?lang=en" dir="ltr">English</a>
<!--#else -->
<h1>Rachel</h1>
<p>Hello World!</p>
<a href="index.shtml?lang=he" dir="rtl">עברית</a>
<!--#endif -->
</body>
</html>
That’s all there is to it. You now have a fully-functional, multilingual web page using only server side includes.
Concluding Multilingual Server Side Includes Pages
Looks can be deceiving. Server Side Include’s incredibly simple syntax, that appears as nothing more than fancy comments to the unsuspecting eye, can be used to change the content of a page, to include multiple separate documents in a single page, for basic variable manipulation and echoing, and a whole bunch more.
Hopefully, this short tutorial will encourage you to explore SSI in greater detail, and use it in your projects when a comparatively complex language like Perl, PHP or Python would be overkill.
You can learn more about server side includes, including more examples, syntax and commands, at the Apache documentation website.
As always, drop a comment below or join my Discord server if you have any comments or questions.