Speak Their Language: Enhancing User Experience with Multilingual Support In Mobile App

Everwell Engineering
Pulse by Everwell
Published in
5 min readJun 23, 2023

In an era of expanding global markets it is becoming more crucial than ever to address the diverse vernacular of prospective users. A fundamental aspect of achieving this objective is integrating multilingual support into mobile applications. By incorporating translations and embracing multilingual support, mobile applications can effectively overcome language barriers, enhance usability, and facilitate a high degree of personalisation.

At Everwell, seamless user experience is one of our top priorities. Working towards the uphill task of incorporating languages within our website, we also embarked on the solving the same problem for mobile applications.

To bring the translations into effect in mobile applications, the first challenge we had to consider was to package these files without increasing the bundle size by a lot. We decided to go for simple xml configurations which mimicked the strings.xml in the values folder, a pre-existing support provided by Android.

To extend the support for each language, we created a values folder for each. In the res directory of our Android project, we created separate directories with the naming convention values-{language_code}. For example, values-ru for Russian translations, values-frfor French translations, and so on. These directories would hold the translated string resources for each language.

Folder structure with the language support

These folders would each have their own strings.xml with the translated string resources for the respective language. Here is a sample string that would have distinct translations in the language-specific folders.

<string name="action_sign_in">Войти</string>

We also configured a fallback as manually maintaining the consistency for each of the resource files was a hard job. Conceptually, if a specific translation was missing for a given language, Android would automatically fallback to the default values/strings.xml file. Therefore, instead of maintaining the consistency across, we only planned to do so primarily for the values/strings.xml file.

The subsequent step involved configuring the locale to ensure that it recognised and honoured the diverse set of translation strings that were configured. To bring this into effect we introduced a language selector UI which brought about this change dynamically

Whenever a language would be selected, we would have to update the locale. Here is some sample code which helps do something similar

private fun setLocale(context: Context, language: String): Context {
// Create a Locale object with the desired language code
val locale = Locale(language)
Locale.setDefault(locale)

// Get the resources and configuration objects
val resources = context.resources
val configuration = resources.configuration

// Set the locale in the configuration
configuration.locale = locale

// Update the configuration with the new locale
resources.updateConfiguration(configuration, resources.displayMetrics)
return context
}

While the solution seems straightforward, due to the fact that the app activity is already loaded, the changes did not seem to apply automatically. We explicitly added an application restart for the locale changes to be brought into effect.

Intent intent = getIntent();
finish();
startActivity(intent);

Some salient points which we had to also incorporate is to persist the locale selection as well as have a default locale always configured to cover all the bases.

Now that the mobile application was ready to serve different strings, we needed a great way to automatically maintain all the translations in your code, and also have a hassle-free way check the quality of translations. You can read our post on effectively choosing such a translation management service .

Using Localise.biz and Python, we made a script which helped automatically import all the translated strings into the structure created above. Here is a sample to help you through

import io
import os
import requests
import shutil
import zipfile
from xml.dom import minidom


# Usage: Run from the command line using "python load_localise_files.py" in the app/src/main/res directory

print("Requesting translation files for Android")

headers = {"Authorization": "Loco <auth_code>"}
r = requests.get("https://localise.biz/api/export/archive/xml.zip?fallback=en", headers=headers, stream=True)

z = zipfile.ZipFile(io.BytesIO(r.content))
z.extractall("temp-translations/")

for subdir, dirs, files in os.walk("temp-translations"):
for file in files:
if not file.endswith("xml"):
continue

master_file = minidom.parse(os.path.join(subdir, file))
master_strings = master_file.getElementsByTagName("resources")[0]
master_items = master_strings.getElementsByTagName('string')

_, subdir = os.path.split(subdir)
subdir = subdir[:9]
print("Cleaning translations: " + subdir)

for elem in master_items:
if not elem.firstChild or elem.firstChild.nodeValue == "" or elem.firstChild.nodeValue == "#N/A":
if elem.nextSibling and elem.nextSibling.nodeType == minidom.Node.TEXT_NODE and elem.nextSibling.data.isspace():
master_strings.removeChild(elem.nextSibling)
master_strings.removeChild(elem)

if not os.path.exists(subdir):
os.makedirs(subdir)

print("Writing translations: " + subdir)

file_handle = open(os.path.join(subdir, "strings.xml"),"w", encoding="utf-8")
master_file.writexml(file_handle)
file_handle.close()

shutil.rmtree("temp-translations")
print("Successfully updated Android translations for all languages")
encoding='utf-8') as fp:
print("Writing translations: " + key_map[key])
json.dump(final_strings, fp, ensure_ascii=False,
indent=4, separators=(',', ': '))
else:
print("Unsupported key " + key + " in load_localise_files.py")

With translation support in mobile apps, our services can be accessible to users from diverse linguistic backgrounds, leading to increased user satisfaction and better retention. With the above solution in place, one of the ways to keep you mobile application regional translation friendly would be to have most of the commonly spoken languages already present.

In addition to this, bad translations are often more harmful than no translations so it is required to continually improve our existing translations, refining them by taking user feedback, and getting native speakers to add more nuance to the translations. With increasing globalisation of the internet, product owners need to be more proactive in localising the applications to unlock the full potential and establish a strong presence in global markets.

Credits: Kandula Mohan Krishna

--

--