Dec 15, 2022

Translating The Forge

5 min read - Published: a year ago

I often get told that life is about the journey, rather than the destination. Well, I can say that the process of getting The Forge ready for translation has been quite the journey, indeed!

Just like The Forge makes it easy to host your games with players across the world, we want to make it as easy as possible to navigate and understand the site itself, without having to resort to browser based machine translation tools such as Google translate.

The whole process, from making the site able to store, access, and display content for different languages, to doing so in a way that lets us easily add to and continue to develop the site, is called "internationalization".

That word is a mouthful, so I'll use the shortened form (i18n) to refer to it. The word starts with an "i", ends with "n", and has eighteen letters, so: i18n. You might've come across short-hand like this before and wondered what it meant. Now you know!

Translation (sometimes also called t8n) is a part of i18n, one that we'll touch on again later in this article. For now, let's look at i18n's other components, the lessons that were learnt, and how the challenges they presented were addressed.

String extraction, where it all begins

The first big challenge of the i18n effort is actually getting a handle on which strings we have in the project. If you're unfamiliar with the computer programming term "string", don't be intimidated! It's a very simple concept: A string is a word, a sentence, or any other sequence of text characters. For i18n, we're particularly interested in the strings that'll be displayed to the user, because that's what you read and interpret every time you access The Forge.

Each of these strings needs to be captured and put into a dictionary, essentially a JSON file with each translation value associated with a specific key. That way, whenever we want to show a string, we pass its key through a translation function that can look up the right key in the right language's dictionary and display it.

It's very time consuming to fill and maintain dictionaries with thousands of keys manually. The easiest way to do this is to use a purpose-built tool like i18next-parser, which reads your code and recognizes strings wrapped with the translation function. New strings are added to translation dictionaries, while unused strings are removed. This simplifies translation management immensely, down the line.

When you're building a website from the ground up, it's relatively easy to wrap each new key with a translation function. But when you've got a project that's been going for a couple of years and already has momentum, you've got to take special care and dedicate effort to wrapping each string that you want translated before it can be picked up for string extraction. It's possible to use regular expressions to find strings in code, but the code also needs to be interpreted to determine whether the string is user facing and whether it should be translated.

This is especially true when strings are constructed programmatically, since different languages are likely to have different word orders. You can't always translate two parts of a larger string individually and then stick them together, so changes need to be made in the code so that the whole string can be captured and effectively translated.

While the process of wrapping existing strings for translation is very manual, another concern is whether the translation tools you choose are supported across your entire project. We decided to use i18next as i18n framework, because of its plugin support and flexibility. The Forge makes use of JavaScript, Handlebars, and Vue, and the actual translation function used differs between each of them. Using a comprehensive i18n framework that supports each of the different parts of The Forge means that we have less repetition across the code base and fewer dependencies.

The long and winding road

Because of the sheer number of strings in the project and the manual component of checking whether those strings are translatable as-is or whether they need to be rewritten, it took a long time before the entire project was considered wrapped for translation. As new features were added, because i18n touched nearly every part of the code, branches needed to be kept in sync. Finally, we were ready to merge i18n into the codebase, and even though we were just translating into English at that point, our source language, we were able to catch mistakes and fix them.

These oddities could be anything from finding an untranslated string, to a static string that contains HTML elements that were being escaped. Those who are familiar with web development will know that it is important to escape unsafe HTML to prevent vulnerabilities in your website. Making sure that the translation functions are able to escape unsafe HTML, and not escape safe HTML that you want displayed, means going through your strings with a fine-toothed comb. Good examples of this are strings that contains links, pointing you to another part of the website, or a forum post. Because we often use HTML tags for styling (e.g. <b></b> and <strong></strong>), special care should be taken to ensure that escaping is handled appropriately.

Continuous localization and translation, the final steps

With string extraction out of the way, testing done and a way to maintain translation dictionaries in place, The Forge can be considered translated. The Forge currently supports English, French, Japanese, Spanish, and German under the hood.

There's just one problem, one that a lot of module developers have run into themselves: We only have complete translations for our source language, English! As it happens, the community has already noticed an opportunity, and rolled a natural 20 while implementing a solution.

Foundry Hub recently released its new project: Foundry Hub Weblate. This is a platform that brings Foundry VTT module developers closer to their users by allowing bilingual community members to contribute directly to the translation efforts of Foundry modules, giving the developers more freedom to focus on improvements and new features.

We got into contact with the awesome folks over at Foundry Hub, and they've helped us to set up a project on their platform to make The Forge's strings available to community translators!

At the time of writing, i18n is currently in Beta status on The Forge, meaning that the site is fully capable of supporting translation and we are in the process of populating translations for our supported languages. Soon, we will allow users to select their desired language similarly to how they are able to select their desired theme.

Interested in helping us translate?

We appreciate that! If you'd like to get involved and contribute to the ongoing translation process of The Forge, we'd like to invite you to follow the links below and explore our project on Foundry Hub Weblate.

Translation status

The Forge's Weblate project information and full instructions for translators can be found here. You can also read the original Foundry Hub Weblate announcement here, and the project provides useful information for both translators and developers on its home page.

Thank you for reading the article and accompanying us on our i18n adventure. We hope that you will soon be able to enjoy using The Forge in your own language!

Be sure to keep an eye on The Forge's Workshop for more information on new and exciting upcoming features.