Published on August 02, 2022/Last edited on August 02, 2022/10 min read
Every day, people log into the Braze platform to send highly personalized and relevant messages to their users. There are Braze customers on six of the seven continents, and the marketing, growth, and engagement team members at these companies speak every language that you could imagine. So, in order to better serve our users both now and in the future, Braze launched an initiative in 2020 focused on internationalizing our product—that is, designing and developing the Braze platform in a way that removes barriers to deploying it effectively around the globe.
At its core, internationalization—often rendered as “i18n” because there are 18 characters between the “i” and the closing “n”—isn’t an end result, it’s a way of working. After a product goes through i18n, it may not look any different on the outside, but it’s often utterly changed under the hood in order to allow it to be leveraged in a wider range of regions. Localization (nicknamed “l10n” for similar reasons), on the other hand, requires software providers to take an internationalized product and allow it to be translated, formatted, and configured in such a way that users in a specific locale can easily take advantage of it. That usually involves table stakes elements like text translations and date formatting in an area’s local language, but it may also require nuanced changes like currency translation, handling keyboard inputs, number formatting, or alphabetical sorting. In general, the idea is that i18n makes it possible for you to do l10n many times over without requiring major additional engineering work.
At Braze, successfully internationalizing our product was a company-wide initiative that required updates across many of our surfaces, from Braze.com to our instructional videos, one of the biggest parts of that undertaking was the work done in connection with our core SaaS product. So let’s take a look at how that came about and how we made it work.
The difficulties that come with internationalization are heavily influenced by the product you’ve created so far. And after nearly 10 years of building our platform, we found that some of the decisions we’d made had the potential to complicate our internationalization efforts. Think hard-coding strings as English in the code base, assuming US-style date formats, and other decisions that only made sense if you were operating under the assumption that Braze would only ever be used by English speakers within the United States.
Fixing those issues was daunting. For one thing, every line of code in our code base needed to be analyzed to determine if they had to be adjusted as part of our i18n efforts. For another, the internal team within our technical organization that was responsible for this initiative was still in the process of being staffed up. Personally, I was expecting the QA associated with the project to be a nightmare—after all, how do you check every single string to ensure that it still looks good and that all our features work after they’ve been internationalized?
That said, it wasn’t all doom and gloom. We realized pretty quickly that we weren’t the first SaaS company that had to address significant tech debt in order to successfully internationalize our product, and that meant there were a wealth of resources (e.g. Slack sharing their experience with localization) and frameworks (e.g i18next) available for reference. We also got lucky when it came to hiring: A few of the strategic hires we made had carried out this kind of complex work before and were able to bring that experience to bear on our project. Finally, we had just announced a joint venture with Japan Cloud to open a Braze office in Tokyo. That gave us access to individuals at Japan Cloud who had seen products undergo internationalization in the past and were able to share their perspective and experience to help ensure a smoother process for us. It also put us on a deadline and gave us our first target language: Japanese.
When you set out on an i18n journey, you expect there to be a lot of tweaks that you’ll have to make to your product—and, trust me, there will be. But some aspects of the effort will necessarily be bigger than others. At Braze, the biggest challenge in our i18n effort was the work needed to prepare text in our product for translations. Why? Well, if the text in your product isn’t easily translatable, none of your international users are going to be able to read the dashboard, and that means all of the work you put into date formatting, number formatting, font selection, or choosing international-friendly images and colors accomplishes nothing.
Given that, we knew we had to prioritize preparing text for translation. That effort—and the description below—were made possible thanks to some amazing documentation compiled by Gregory Beaver, Staff Software Engineer at Braze and our resident i18n expert. Three of the biggest elements of that effort were:
In order to make it easy for your product to display different languages, you need to remove any hard-coded or static strings and replace them with dynamic references. That allows your product to pull in different text strings to show to the user based on the language being displayed. To assist with that process, there are a number of i18n libraries for your programming language of choice that you can incorporate into your product in order to handle some of the heavy lifting.
For instance, imagine that we have a line of code that reads “Hello {place}” where “Hello” is hard-coded and “place” is a variable. We could address this by including the rails i18n library within our project.
Once you’ve included this library, you can take advantage of some of its helper methods. Start by referencing the library and passing a few fields as parameters; the first parameter is our key for this string: hello-world. That way, when we have translations ready to go, we’ll know which translation is meant to go where. Next, we have `Hello { place }`—that’s the default text that will be leveraged if we aren’t able to find the key above—and then finally the default value for the “place” variable.
Then the i18n helper methods can do the work to look up the language file for each user’s current language setting (English, in this case), and then return the translated value for the key:
If, on the other hand, the user in question had set our product’s language setting to Japanese, the application would reference the `ja` fileset of translations, which looks like:
In the example above, the fix works in part because both English and Japanese happen to use the same sentence structure for a phrase like “Hello world.” That’s not necessarily the same for every instance or for every language—for example, Arabic has three ways to pluralize words (including two distinct ways and a gender split of one of them), Japanese has several ways to represent a multitude of things, and Russian has a huge set of declensions, which results in many, many varieties of plurals.
How does this issue play out when it comes to i18n? Consider the Account Settings page in the Braze dashboard—there’s a sentence on that page that reads “Change your subscriptions in Company Settings” with a hyperlink associated with the words “Company Settings.” In English, that means that the link is at the end of the sentence
In Turkish, however, the word order is swapped, so that the link falls in the middle of the sentence:
Given these sorts of complications, the usual best practices of software development surrounding the DRY (Don’t Repeat Yourself) principles are to embrace an anti-pattern. Accordingly, it’s wise to put the longest possible sentences into your translations framework, as context will be different across different languages and cannot necessarily be predicted from the English locale. This approach gives your translators—whether manual or automated—the best chance of getting it right.
Another significant element of this process that we had to figure out how to handle was text expansion. It’s often the case that the length of a sentence in one language will be notably longer or shorter than a sentence in another, leading to complications with the look and feel of text within your product. For Braze, we knew that this factor was something we’d have to deal with, so we wanted to make sure that nothing looked wonky when we started pulling in translated text. One catch? We didn’t actually have the translated text yet.
Enter pseudolocalization. This is a tool that’s used to transform English sentences in order to show whether text is running through the translation service, while also expanding text by 30% (a representative text expansion for some languages vs. English). By using pseudolocalization, we were able to make sure that text wouldn’t overflow into other fields if there was significant text expansion because of translation:
And while the tool can be funny to look at, we found it quite helpful—in fact, it helped us flag several areas of our product where design changes were required to accommodate shifting text lengths. For example, without running pseudolocalization, we would have not caught the overlapping lines in our push notification settings until the text was already translated:
Our initial effort to audit and update all the legacy strings in the Braze platform ended up taking about six months. Completion of that work was aided by the decision to have all Product Engineering teams agree to a shared OKR over multiple quarters that committed them to reviewing the areas of code they owned and preparing text for translations, among other localization prep.
While those teams were carrying out that work, we were able to onboard our translation team in Japan and have them work through strings as they became available. This made it possible for us to incrementally introduce new translations—behind a feature flag, of course—and test things in small sections. By breaking down the QA of our i18n efforts over multiple weeks and sharing the responsibility with the local team in Japan, we were able to make the task more manageable and far less daunting.
In the end, we met our goal of releasing a fully translated version of the Braze dashboard for our Japanese user base by the end of 2021, ensuring that our growing number of customers in the region could use Braze with ease. And since the release, we’ve continued to make localization adjustments for Japanese, while also working to ensure that our teams maintain strong habits around i18n. That includes accounting for i18n when estimating workloads, ensuring that work is reviewed in the pseudolocalization framework as part of QA, and running automated testing on our front end to validate that i18n isn’t causing any user-facing issues. There’s always more to do, but we’re happy to have launched the Japanese dashboard successfully and to have built a strong foundation for future efforts in this area.
Interested in tackling these kinds of ambitious, rewarding challenges? Check out the open positions on the Braze Careers Page.
Sign up for regular updates from Braze.