Simple string localization in Kotlin Multiplatform

Yev Kanivets
xorum.io
Published in
3 min readAug 14, 2021

Kotlin Multiplatform Mobile gives us a lot of freedom on what to share and how to share between native mobile applications. Usually, it’s just the shared business logic, and no user-facing things live in the common KMM module. But sometimes we need more …

This article will describe a simple (no 3rd party needed) way to access and use localized strings from the KMM module. This approach is based on the native string localization provided by Android and iOS applications, so no changes to strings management are needed from your side.

Native localization

iOS and Android have similar approaches to the localization of strings with some major differences in details. Let’s do a quick recap to get context before diving into the KMM stuff.

On both operating systems, we have all localizable strings extracted to files (one per language) in the form of key-value lists. Once the application is run on the user's device, the operating system detects the closest language file and uses it to render your app's UI.

Rather straightforward. The main difference can be seen when it comes to using those strings in the code though.

strings.xml

On Android, you have a generated R class, which contains all string keys, accessible during the compilation, so you have an auto-completion and compile-time check for the existence of all strings you are trying to use.

Localizable.strings

On iOS, you pass the string key to NSLocalizedString, which is resolved and localized during the runtime, so you don’t have the auto-completion and compile-time check. String key is used as the default value.

KMM localization

To me, strings are one of the most user-facing parts of mobile applications, so I’m not sure that we should share it or have just one strings file in a KMM module. My take on it is that we should leave the power of strings to native platforms and developers.

Even though, we still may need to access those native strings from the KMM code sometimes. For example, if you need to show network errors to users without passing them all the way up to your views.

Here you can have many implementations inspired by the iOS or Android native approaches, or mixed ones. Here is the one which is close to the iOS native strings management using the expect/actual mechanism.

As you can see, it allows getting localized string, formatted string, or plural string by its String id. Now let’s check the platform-specific actual implementations.

Using the context and “reflection” we can get the localized string on Android. We simply return the id in case if a requested key doesn’t exist to match the native iOS implementation. But we can also throw an exception if needed.

On iOS, we access the main bundle (custom bundles may be listed as well), get the localized string from it, and return the id by default. The only complication here is about variadic parameters which aren’t supported by Objective-C interoperability, so we need ten-case when instead :)

Now, to use the localized string in KMM code, we can write something like this Strings.get("internet_error") with internet_error string localization provided by iOS and Android separately.

Conclusion

Kotlin Multiplatform is a very flexible tool that gives you the freedom to choose what and how you share between different platforms. Most of your needs even don’t require a 3rd party library to be used ;)

Here is the pull request, which adds the strings localization to our KMM mobile template if you need more details or a working example.

Featured in Kotlin Weekly #264.

--

--

Yev Kanivets
xorum.io

Technical Lead Mobile @ 360Learning | KMP enthusiast | Husband & dad | Marathon finisher