If your website is only available in English, you may be losing out on a lot of user traffic and revenue. A recent study has shown that only around 25% of internet users speak English, which means that localizing our websites is a big priority at Nord Security. We currently support more than 20 locales and have country-specific content, which helps us reach out to customers all over the world. Read on to find out how we do it.
First, let's define translations: a translation is a message that is localized for one or multiple languages. It has these attributes:
Initially, all of our translations were stored separately in each web project's files along with the code in our version control system. But that quickly became inconvenient, as we needed to constantly add new translations and update old ones. We needed a way to store translations in a centralized place that would allow us to update them across all our websites in real-time.
This is the diagram of the solution we came up with:
We'll briefly cover each part:
Refreshing translations in real-time is done by issuing a command via the Admin Panel. When the content manager adds new translations to a domain and wants to see them appear on our websites, he clicks the refresh button for that domain. This sends a command through our RabbitMQ broker to all the listening website consumers that they need to go and refresh the translations for that domain. After downloading the new translations, they are cached in Redis for fast lookup.
At the moment of writing this, we have 5+ localized websites in 26 locales and over 500,000 translated messages. The system scales well and has stood the test of time as new websites are added.
JSX content? No problem.
Our web content team writes JSX, which allows us to leverage the power of React components. But browsers can't render JSX, so we needed a way to which later gets translated and converted to static HTML. To solve this, we've made a system for writing JSX in the content editor and then converting it into static HTML.
The system consists of these parts:
When a content manager updates a blog post or publishes a page in the editor, the content is published as a message to RabbitMQ:
{
"locales": ["en", "fr", "es"],
"content": ""
}
It is then sent to the Static content generator microservice, which converts the JSX content to normal HTML and adds translations from the Translations microservice. After this is done, the (now HTML) post content is sent back to the web app through RabbitMQ again in separate messages:
{
"locale": "en",
"content": "Hello!"
}
"locale": "fr",
"content": "Bonjour!"
}
"locale": "es",
"content": "Hola!"
}
Content is saved separately for each separate language that the page supports in the database. When a user visits our site, we show him the translated static HTML.
That's a simplified view of how we serve localized content. There are also caching mechanisms in place to reduce database load. I won't go too much into detail about them in this article, but if you'd like to know more about how we cache HTML content, you can read about it here.
Here is some advice that you can hopefully use when localizing your web application:
https://your-website.com/{locale - code}/your-page
. The locale code should be lowercase and separated by a hyphen (E.g. en, pt-br, zh-tw). This way it's easy to add new languages as well as manage relative links on the website.Want to read more like this?
Get the latest news and tips from NordVPN.