How the Alarmy Team Localizes App Copy into Over 50 Languages
A deep dive into the app translation process, the destiny of any global service.
🤖 Do you want to leave without depositing the changed alarm?
= Leave without saving changed alarm? … um, what?
Have you ever downloaded a popular foreign app only to panic because it's entirely in another language? Or had a good laugh at some hilariously awkward translations?
What language an app supports and how well it's translated are pretty crucial. I mean, you have to understand it to even decide whether to use it, right?!
Of course, features are the most important part of an app. But if users can't understand them, they can't even use those great features. Plus, a "well-explained" feature can make it sound much more appealing, ultimately boosting the charm of the service itself.
Alarmy supports users all around the globe. To ensure quality in this process, our User & Product Operation group (UPO group) handles translations whenever a new feature or text is added.
In this post, I'll give you a sneak peek into how we run this translation process.
Running a global service isn't that hard! (Well, it's not exactly easy either...)
🧐 Strings? Localization? What do they mean?
Before we dive in, let me explain some terms I'll be using a lot throughout this post.
☝️ First, the words, phrases, and sentences used within an app are called "strings". If you look it up in a dictionary, it means a sequence of characters in computer programming, which is exactly where it comes from.
On both Android and iOS platforms, almost all the text in an app is stored as character sequences inside string files. So, in this post, just think of "string" as "any word, phrase, or sentence that appears in the app."
✌️ Second, the Alarmy team uses "translation" and "localization" to mean quite different things. Translation simply refers to converting the source text (English/Korean) into another language. On the other hand, localization means adapting it to the culture and nuances of that specific country. In other words, during the localization process, a translation might be further refined, or if an English expression is already universally understood, we might just keep it in English without translating it. I'll be making sure to distinguish between these two terms appropriately in this post.
🤷 Why do we localize?
If you were launching and managing an app in multiple countries, what would your goal be when localizing strings? Actually, why even localize in the first place? Going even deeper, why do we even put text in an app?
I believe the purpose of a string is to convey meaning. Within the space of an app, strings are how the app creators speak to the users.
Let's think about the goal of string localization based on the analogy that {strings = speech}. Looking back at when I learned English, my main goals were to communicate my thoughts and intentions clearly, and to express myself as naturally as a native speaker.
Similarly, our UPO group has two main goals for string localization: 1️⃣ capturing the intended meaning of the product while 2️⃣ translating it naturally for locals.
The overall process to achieve this goal looks like this:
Writing the source text: Laying the groundwork in Korean and English.
Initial translation: Using automated translation to create other languages.
Applying to the source code.
Secondary localization: Improving it to be more natural and appropriate.
Now let's take a closer look at each step.
1. Writing the source text: Laying the groundwork in Korean and English
The birth of a string happens the moment a Product Manager (PM) and Product Designer (PD) plan a new feature or an improvement to an existing one. While planning the product spec for the screen, they decide, 'We should put this kind of text here.' Once this planning is done, they request collaboration from the UPO group to create or modify strings. They drop all the strings from their screen designs into a table in our document template.
When a UPO manager starts the requested task, the first thing they do is check the product spec to understand why the strings were added. We look at the problem definition set by the PM (the What, Why, and How) and the design goals for each screen created by the PD. After that, we double-check the original Korean text provided by the PD. We verify how a user would understand it and conversely, whether it accurately conveys what the product intends.
Beyond the main purpose, we also give feedback on sentence endings and tone. The vibe changes completely depending on whether you say 'You can do X,' 'Please do X,' or 'X is done,' right? The PD team already thinks deeply about this before handing it over, but we put ourselves in the user's shoes to verify it one more time and exchange feedback.
Once we lock in the Korean text, we localize it into English and hand it back to the PM & PD. After getting their final feedback, the PM makes the ultimate decision.
2. Initial translation: Using automated translation to create other languages
Alright, now we start translating into languages other than English and Korean. Before full localization, we do a basic translation pass first. Because of this, the goal is "to translate just enough so that speakers of that language can understand it." It can't be perfect from the get-go, after all. 🥲
Alarmy supports over 50 languages. If we were to copy and paste all those languages into a translation site one by one, it would take forever. So, we automatically translate them using a Python script connected to the Google Cloud Translation API. But we can't afford to have completely botched translations, so we run pre- and post-processing steps to prevent mistranslations. We do a ton of work during this step, but to avoid making this post too long, I'll just summarize.
First, before feeding it into the translator, we prepare English text that is "as spelled out as possible." When writing the source text in Korean/English, we often use implicit expressions, but running these straight through machine translation can yield some bizarre results. So, we explicitly add omitted subjects and objects to the source text and replace special idioms with standard vocabulary before plugging it into the translator.
Second, we back-translate the results into English/Korean to double-check for any mistranslations. Since machine translation has its limits, we can't be 100% sure it was translated perfectly, but this at least prevents it from translating into a completely different meaning.
For instance, we once translated the "Save" button into multiple languages, and in a few languages, it got translated as "Save money" (like a bank deposit). We pushed this to the app without realizing it and received a lot of user feedback. 😂 Ever since then, the shorter the word, the more meticulously we check for mistranslations.
Lastly, proper nouns are replaced separately after translation. Specifically, if we put the app name "Alarmy" directly into the translator, it often assumes it's a typo and translates it as "alarm" or changes it to other words like "Alarmi". So we let the translator output whatever word it gives, and after the translation is done, we swap it back to the app name "Alarmy". Feature names treated like proper nouns go through the exact same process.
3. Applying to the source code
Alarmy uses a solution called Lokalise to manage and update in-app strings. We adopted an online solution because it saves the engineering group from tedious manual work, and for the UPO group operating it, the huge perk is that we can make edits directly on the web without needing to file a separate request. (Paid for with company money, of course.)
There are several ways to apply translations to the app source code via Lokalise. We opted for Github integration, where we send our changes as Pull Requests (PRs) and merge them after a code review. There is also an option to embed an SDK in the app for real-time updates, but we figured the Github integration had a better resource-to-risk ratio relative to its impact.
Here's our detailed workflow:
An engineer adds the string's Key value and the base language (English) directly into the source code.
After that, the changes are synced to Lokalise, and we can check the updates on the Lokalise webpage.
I then add the non-English translations for those added or modified Key values.
Once the work is done, I send over a PR, and the engineer reviews the code and merges it into the app.
When a test build containing the changes is released, we check if the text looks good on the screen and make sure nothing is broken. If there are no issues, it gets included in the new version and shipped out!
4. Secondary localization: Improving it to be more natural and appropriate
While reading up to this point, didn't you think, 'Isn't machine translation going to be super awkward?'
You're right. Machine translation DEF-I-NITE-LY has its limits. No matter how hard we try to prevent mistranslations through the earlier steps, things can still be translated incorrectly, the intention might get lost, the length could get unnecessarily bloated, or the sentence might sound too rigid for Alarmy's tone and manner... There's just so much room for improvement. 😭
So, we do follow-up polish work to better capture the intent and make it feel more natural from a local's perspective.
There are roughly two ways to go about this: outsourcing to translation agencies or getting help from users. Since we are still exploring different options and comparing pros and cons, we can't definitively say "This is the one!", but I'll briefly touch on the methods we've tried or are currently trying.
We've been testing out various methods one by one, but the UPO group recently concluded that "getting help from users is more effective." Translation agencies obviously have huge advantages, but we realized that the power of users who deeply know the Alarmy app is massive. So we're currently brainstorming and experimenting with how we can best communicate with users regarding localization! I'll come back with a more detailed post on this later. 😉
Lessons learned and setting higher goals
It's already been over two years since the UPO group started managing Alarmy's strings. There are still areas we're lacking in and plenty more we want to try, but thinking about how much more we can improve gets me excited. To wrap up this post, let me share some of the epiphanies I've had while localizing strings.
👉 First, it's all about the users!
The ones who truly understand 'Alarmy from a user's perspective' are the users themselves. No matter how intimately I know the app's features inside out, I can never exactly know what's going through our users' minds and hearts. Especially with localization, which is directly tied to other countries' languages, cultures, and trends, it's even harder to know how foreign users view Alarmy. Because of this, getting help from users—or at the very least, actively gathering their feedback—is the very first step toward helping them understand Alarmy better. This is something I feel every single moment as I chat with various users to improve our string quality.
👉 Second, clarify what you're trying to say!
This is something I feel from the very first step of locking in the Korean/English text. Just like how it's hard to pick the right words when speaking if your own thoughts aren't organized, strings need to have a crystal clear intention and meaning. This is especially true when conveying meaning in the limited space of a mobile screen. You have to sync that intention with the PM handling the product spec and the designer, and then clearly convey it to the translation agencies or users involved in the localization process for a good localization.
👉 Third, just give it a shot.
Before opting for machine translation, we debated, 'Should we just leave it in English?' Changing it to a local language, even if it's clunky vs. leaving it in well-polished English that they might not understand. Both have pros and cons, but we've seen a lot of benefits from deciding to 'just translate it and ship it!' We started getting way more specific user feedback on certain strings. Sure, that's also proof that there are more strings looking awkward to users now, but it's given us the stepping stones to get faster feedback and iterate.
As fast as new features are added, and considering we support over 50 languages, the areas we need to improve in localization keep piling up. But as our processes become more sophisticated and we rack up insights, I'm feeling confident that we can do this faster and better.
Our challenge continues until the day every single user around the globe goes 👥 "Wait, Alarmy wasn't made in our country?!"
I'll keep sharing fun episodes and lessons from our localization journey. Catch you later!