Internationalising (i18n) a website

3 min
Internationalising (i18n) a website

Personal blog

My personal website where I write new articles about engineering, systems, economics and psychology.

ReactGatsbyGraphQLHTMLSaas

I have written about Gatsby a few times on this blog. It is one of the easiest ways to create static pages such as blogs or corporate websites. However, internationalization is one feature that Gatsby doesn’t take full advantage of. The people at Gatsby wrote a post showing how to convert your normal website into a multilingual website, but there are several things they left out that I’m here to shed some light on.

In this post I will show factors to consider when internationalising a website and how I have internationalised the website you are visiting right now.

URLs’ structure

One of the biggest problems we face when creating a multilingual website is web structure. Some people think this isn’t important, but a wrong web structure can seriously damage SEO and makes it difficult for user navigates between languages.

As in my case, I’m not developing a blog from scratch, but starting from my website repository that I have working from months, I already have a predefined structure for the Spanish contents, more specifically the following structure:

╔═══════════════════════╗
║     Static pages      ║
╠═══════════════════════╣
║ /                     ║
║ /contacto/            ║
║ /politica-privacidad/ ║
║ /blog                 ║
║ /proyectos            ║
║ /libros               ║
╚═══════════════════════╝

╔═══════════════════════════════╗
║           Articles            ║
╠═══════════════════════════════╣
║ /desarrollo/ionic-calculadora ║
║ /lean/producto-minimo-viable  ║
║ /ingenieria/kpi               ║
╚═══════════════════════════════╝

╔══════════════╗
║  Categories  ║
╠══════════════╣
║ /desarrollo/ ║
║ /ingenieria/ ║
║ /lean/       ║
╚══════════════╝

╔═════════════════════════╗
║        Projects         ║
╠═════════════════════════╣
║ /proyectos/wateralo/    ║
║ /proyectos/profitchart/ ║
║ /proyectos/justtasks/   ║
╚═════════════════════════╝

This structure cannot be broken because the SEO disadvantages would be very important. My blog (this blog) has around 100 indexed pages and I wouldn’t like to redirect all of them. This would be heavy!

ISO 639

In i18n, the use of language and localisation codes are very important. For this case, I will only use language code, so I will not distinguish languages according to localisation (e.g. British English or American English).

These codes follow the ISO 639, a standardised nomenclature of languages from all over the world. There are many forms of this standard, but the most commonly used is the one that use two characters to define the language (e.g. “es” for Spanish or “en” for English).

Two options to choose from

The first option (1) is the simplest of all: insert before each URL the ISO language code. For example, the page /contact would become /en/contact in English and /es/contact in Spanish. Very simple! However, it has a drawback. Part of the URL is in English (/es/contact) and the content will be in Spanish. This may not have good SEO results.

The second option (2) is more complex. We also use the ISO language code, but the slug is different depending on the language. For example, the page /contact would become /en/contact in English and /es/contacto in Spanish. In this case, we solved the first option SEO problems. However, navigation between pages in different languages will become more complicated, because changing the ISO language code won’t be enough.

Let’s compare the two options!

╔════════════════════════════════╦═══════════════════════════════════╦══════════════════════════════════╗
║            Original            ║           i18n Option 1           ║          i18n Option 2           ║
╠════════════════════════════════╬═══════════════════════════════════╬══════════════════════════════════╣
║ /                              ║ /en/                              ║ /en/                             ║
║ /contacto/                     ║ /en/contacto/                     ║ /en/contact/                     ║
║ /blog                          ║ /en/blog/                         ║ /en/blog/                        ║
║                                ║                                   ║                                  ║
║ /desarrollo/ionic-calculadora/ ║ /en/desarrollo/ionic-calculadora/ ║ /en/development/ionic-calc/      ║
║ /lean/producto-minimo-viable/  ║ /en/lean/producto-minimo-viable/  ║ /en/lean/minimum-viable-product/ ║
║ /ingenieria/kpi/               ║ /en/ingenieria/kpi/               ║ /en/engineering/kpi/             ║
║                                ║                                   ║                                  ║
║ /desarrollo/                   ║ /en/desarrollo/                   ║ /en/development/                 ║
║ /ingenieria/                   ║ /en/ingenieria/                   ║ /en/engineering/                 ║
║ /lean/                         ║ /en/lean/                         ║ /en/lean/                        ║
║                                ║                                   ║                                  ║
║ /proyectos/wateralo/           ║ /en/proyectos/wateralo/           ║ /en/projects/wateralo/           ║
║ /proyectos/profitchart/        ║ /en/proyectos/profitchart/        ║ /en/projects/profitchart/        ║
║ /proyectos/justtasks/          ║ /en/proyectos/justtasks/          ║ /en/projects/justtasks/          ║
╚════════════════════════════════╩═══════════════════════════════════╩══════════════════════════════════╝

Choosing the best option for me

Unfortunately, none of the above options fully meet my needs. I have some pages indexed without an ISO language code and changing them would be a headache.

The solution I can think of is that Spanish pages should not have ISO prefix, respecting the current URL structure, and only adding the ISO prefix to the new languages such as English or French.

But with slugs in English (option 1) or with slugs in the language of the page (option 2)? After long consideration, I have decided to choose the second option, even if it is more difficult to implement.

HTML header changes

The HTML header contains important information about the web page. Among all of this information, we are interested only in the lang attribute and the alternative links.

The lang attribute

The lang attribute added to the HTML root tag indicates the language of the web page. We can find this data easily from the URL prefix.

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <meta name="description" content="">
</head>
<body>
</body>
</html>

Alternative links

Alternative links indicate to search engines if the webpage that the user is watching is available in another language. Also, they are used to avoid search engines penalise similar posts because we indicate with these links that these similar posts are the same but in different languages. Alternate links have the following tag structure:

<link rel="alternate" hreflang="en" href="www.juanoa.com/en">