Dynamic Localization on Android | by Naing Aung Luu | Apr, 2022 | Medium

In-app localization is inevitable in trendy android app growth in case your app is concentrating on international customers. There are a number of methods one might implement in-app localization in an android app.

On this weblog, I’m gonna present you the way our Android crew usually implements dynamic localization at Codigo

Earlier than we dive into the implementation, why the title “Dynamic Localization”?

It’s just because we load the translations for your complete app at runtime.
The information supply for the translations may be from wherever! (Distant, native JSON file, or from any form of native asset)

What makes dynamic localization higher than Android’s localized assets?

Android’s localized assets rely in your consumer’s machine language settings. And it’s a hustle to manually management simply the app-specific locale and mirror the adjustments in real-time. (i.e you’d should restart your total exercise simply to refresh the locale).

Plus, your translated assets are completely native as a result of it’s packaged with the APK. It means you’ll should construct and launch a brand new model of the app each time you wish to replace the translations.

With Dynamic Localization, you may replace your translations remotely from a CMS or an Admin Dashboard or something, and your app will fetch and replace at runtime with out having to vary your code or generate any new builds.

Sounds promising? Let’s implement it!

Let’s set our objectives earlier than we begin. Our app ought to be capable of :

  1. Load default localization information as soon as the app begins
  2. Present easy accessibility to translations all over the place within the app
  3. Replicate consumer’s most popular language in real-time
    (i.e app ought to mirror adjustments to chose language with out restarting the app)
  4. Assist textual content templating in translated texts
  5. Use a default language in case one thing went mistaken
  1. Hold our default localization with a localization.json file as uncooked asset.
  2. Create an summary LocalizedViewModel offering localization-related data and functionalities, in order that any ViewModel can prolong from it fairly simply and take benefit off it.
  3. Expose an observable Localization information and persist consumer’s chosen language as a SharedPreference.
  4. Create a textual content formatting perform, in order that we will assist textual content templating in our Localized Strings.
  5. Fallback to our cached translations in case distant fetching failed.

Now that we’ve set our objectives, let’s dive into the implementation. I’ve setup a challenge to reveal how we will do dynamic localization. You’ll be able to clone or obtain the pattern challenge from the next repository.

The pattern challenge makes use of the next stack:

  • MVVM + Repositories + Native & Distant Information Sources
  • Jetpack Compose + Single Exercise (for UI)
  • Kotlin Flows (for reactivity)
  • Moshi-Kotlin (for JSON serialization)
  • Dagger Hilt (for dependency injection)

App UI

Demo app is setup with a minimal ui with only one display screen to current translated texts and three buttons to change between languages: English, Chinese language and Burmese.

Dwelling display screen of the Demo app with completely different language settings

To provide our app with localization information, I’ve setup a localization.json file as a uncooked android useful resource.

For those who checked the construction, it’s simply three json objects, one for every translation. And every a kind of accommodates the identical set of keys. We’ll be utilizing these translations in our demo app.

Now, let’s create aLocalizationclass to carry the above translations.

Localization.getDefaultLocalization() perform is used for preview functions in Jetpack Compose.

Now that we’ve the Localization class, we’ll create a LocalizationBundle class to carry the translations for all of the languages.

Lastly, we’ll create an enum class to carry our supported languages.

And that’s it for the info fashions, we will now transfer on to the enjoyable half, Repository and DataSources

Our information layer is about up this fashion…

Localization Repository

LocalizationRepository will eat information from each native (uncooked json file) and distant (a dummy community api) sources

Our LocalizationRepository exposes the next…

  • localizationFlow to eat the localization in real-time
  • currentAppLanguage , because the identify describes
  • updateLanguage perform to change between languages

And our implementation of LocalizationRepository is as follows…

Wah, there’s loads occurring right here! Let me break it down a bit for you.

  • First, we’ve our Flows and cached states setup. You’ll see personal and public flows right here. The personal one’s a MutableStateFlow and the general public one’s only a StateFlow . This manner, we prohibit exterior lessons from modifying our state.
  • updateLanguage perform emits the respective language localization object and saves in SharedPreference
  • We’ve got helper capabilities named getLocalization and LocalizationBundle.getLocalization() . The previous returns both the cached Translations or the one from localization.json, if the cache is empty. The latter extracts the rightLocalization object from a LocalizationBundle for the chosen language.
  • getLocalizationFromRemote() reveals the instance of fetching Localization from a distant Localization.

Native Information Supply

You’ll be able to see the implementation of LocalizationLocal lessons under.

It principally deserializes the localization.json file from Uncooked Asset right into a LocalizationBundle.

Now that our LocalizationRepository is prepared, we will begin integrating it in our ViewModels. We’re going to create an summary class named LocalizedViewModel as follows…

We’ve efficiently setup our ViewModels and Repositories. Now we will begin consuming the info in our UI! To make use of the localization information, we simply want the ViewModel class to increase LocalizedViewModel .

You’ll be able to see our Demo App’s Dwelling display screen implementation as under…

Since we’re utilizing Jetpack Compose, we simply use collectAsState() extension perform to eat the Localization Circulation.

For those who use Android’s DataBinding characteristic, we will bind it simply too!

Cherry On Prime with String templating

We are able to prolong our implementation additional by supporting string templates in our Translations. We are able to make use of the next methodology to exchange variables in our Translated strings.

In our implementation, we’re utilizing %@ as our template deal with. So our perform replaces each %@ with handed arguments. We are able to use any form of distinctive character or string for TEMPLATE_HANDLE

That’s it! Cheers!

We’ve efficiently applied “Dynamic Localization” characteristic and our UI will mirror the chosen language in real-time. You’ll be able to learn or check out my full implementation of this demo app on this Github repository. You’ll be able to freely remark any errors or misunderstandings relating to the article, too!

More Posts