As my friends and I found mobile app UI localization immensely fascinating, we decided to localize an open source Android app “ShutUp!” from English into Traditional Chinese, Simplified Chinese, and Korean for our final project showcase. We obtained the source code from GitHub and mainly worked on the project in Android Studio.

The hardest part of this project is to internationalize this app properly so that it’s ready for localization. We encountered two challenges with internationalization: string externalization and concatenation.
Challenge #1: string externalization
To externalize all the user-facing strings, we carefully examined the UI and documented the strings in the app. Next, we created an XML file to store all the strings and replaced the hard-coded strings with parameterized strings, such as “@string/stringName” in XML files and R.string.stringName in Java files. This is where we hit the brick wall: though we were able to externalize the strings in XML files, we couldn’t do the same for strings in Java files. Therefore, the app seemed fully internationalized in the emulator, but none of the button was functional.
We tried to tackle this issue with various approaches. We tried to externalize the strings using all kinds of methods mentioned in Stack Overflow, but none of them worked out. We even tried to solve the issue with brute force: If an action in Java files is triggered by a condition contain a hard-coded string, we will include the corresponding localized string in the condition, as shown in the image below.

We implemented this approach and successfully localized the app into Traditional Chinese. However, the code will be too messy and difficult to read if we plan to localize the app into more than one language.
Hence, to centralize the localized strings in Java files, we imported java.util.Locale so that the program can perform locale-sensitive operations and created multiple dictionaries (one dictionary for each target language) with the localized strings as keys and the original strings as values. Every time the program is run, a dictionary will be selected based on the locale and the localized strings will be matched with the original strings. Then the program can be executed successfully even though the strings cannot be internationalized and localized in Java files.
This method also worked, but it is not scalable for two reasons. To begin with, we need to add multiple dictionaries to multiple Java files with hard-coded strings in this app. Secondly, whenever we want to add a new language, we have to update all the Java files by adding a new dictionary. In short, this approach is counter-intuitive, unscalable, and error-prone.
That is why we decided to go back and tried to fix the string externalization issue. Fortunately, we finally externalized the strings in Java files by wrapping the hard-coded strings with getString().
Challenge #2: string concatenation
Another challenge we encounter is concatenation issue. As shown in the following images, some of the strings were concatenated in the source code.

The syntax works fine in Chinese and Korean, so we didn’t really fix the concatenation issue due to time constraint. However, if the app were to be localize into more languages, this is definitely something that needs to be fixed. The localizers can avoid string concatenation by changing the wording of the sentence or modifying the code by using variables that can be moved around in the sentence.
Final thoughts
To sum up, after conquering the internationalization issue, we successfully localized ShutUp! Into three languages.



I believe this project can serve as a great example to evangelize the importance of taking localization into consideration in the engineering team. By storing strings in a centralized location and using variables properly to avoid string concatenation, the developers can help streamline the localization workflow tremendously and save the company a lot of time and money.