logo

Android Localization with Jetpack Compose - A Comprehensive Guide

First announced at I/O 2019, Jetpack Compose is a new declarative UI framework for creating user interfaces for Android apps. It simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs. In this tutorial, we will show you how to easily localize your android app and how to get it right. It will also give you some testing tips on making android localization easier and more efficient, so you can get back to coding or marketing your app!

20 September, 2022

7 min read

Create an android application

Start by creating a new project in Android Studio.

File ▸ New ▸ New Project ▸ App...

💡 Make sure to select Empty Compose Activity as a template.

Adding a new language

In the Project Android panel on the left, select ModuleName res values.

Right-click the strings.xml file, and select Open Translations Editor.

The Translations Editor displays the key and value pairs from the strings.

To add a language, do the following:

  1. Click the globe icon in the Translations Editor.

  2. Select the language you want to add from the list.

Screenshot 2022-08-26 at 14.02.33.png

The new language appears in the Translations Editor and a values-* folder with a strings.xml file is added to the project.

💡 e.g. if you select the German folder values-de will be created with a new strings.xml file in it

That’s it, now we can add some translations!

Localization with Jetpack Compose

First, let’s add some translations.

Add this to the English strings.xml file:

<resources>
<string name="app_name">JetpackLocalizationDemo</string>
<string name="welcome_title">Welcome to Localization Demo</string>
<string name="welcome_subtitle">Here you will learn how to localize your android app with Jetpack Compose UI</string>
</resources>

And this to the German strings.xml file:

<resources>
<string name="app_name">JetpackLocalizationDemo</string>
<string name="welcome_title">Willkommen bei der Lokalisierungsdemo</string>
<string name="welcome_subtitle">Hier erfahren Sie, wie Sie Ihre Android-App mit Jetpack Compose UI lokalisieren</string>
</resources>

Update MainActivity.kt with the new Composable Greeting component.

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
JetpackLocalizationDemoTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Greeting()
}
}
}
}
}
@Composable
fun Greeting() {
Column(
modifier = Modifier
.fillMaxSize()
.padding(20.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Text(text = stringResource(R.string.welcome_title))
Text(text = stringResource(R.string.welcome_subtitle), textAlign = TextAlign.Center)
}
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
JetpackLocalizationDemoTheme {
Greeting()
}
}

Build and run the app. Viola!

Screenshot 2022-08-29 at 11.24.51.png

We localized our Android app developed with Jetpack Compose! So how does this work?

We used stringResource() method for getting the localized string by id and that’s it, pretty straightforward.

Testing Localization During Development

You can test specific languages by setting language in the device settings.

However, for fast check that is time-consuming, and a preferable option would be to switch our app to another language without touching the device’s settings.

We can do that programmatically in runtime by adding this code to the onCreate method in MainActivity.

val config = resources.configuration
val locale = Locale("de")
Locale.setDefault(locale)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
config.setLocale(locale)
else
config.locale = locale
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
createConfigurationContext(config)
resources.updateConfiguration(config, resources.displayMetrics)

Build and run again.

Screenshot 2022-08-29 at 12.35.57.png

Now we see the German localized version!

💡 Don’t forget to delete this code, since it is for testing purposes only!

Jetpack Compose Translated Preview

With Jetpack Compose there is an even better way to test localization, without running the app at all, in Preview!

To test different user locales, you need to add the locale parameter to the DefaultPreview:

@Preview(showBackground = true, locale = "de")
@Composable
fun DefaultPreview() {
JetpackLocalizationDemoTheme {
Greeting()
}
}

Check your Preview tab, and click on the Build Refresh button to refresh the canvas if no change is reflected:

Screenshot 2022-08-29 at 12.44.15.png

Now you can see German version directly in the IDE!

Multiple Previews

Sometimes it is useful to see all variants at once without running on a simulator or a real device.

Replace DefaultPreview function with this:

@Preview(showBackground = true)
@Composable
fun DefaultPreview1() {
JetpackLocalizationDemoTheme {
Greeting()
}
}
@Preview(showBackground = true, locale = "de")
@Composable
fun DefaultPreview2() {
JetpackLocalizationDemoTheme {
Greeting()
}
}

Refresh the Preview and check the result:

Screenshot 2022-08-29 at 12.50.15.png

English and German Preview, side by side! Pretty awesome, right?

This is particularly helpful when you have many languages and regions you need to support and want to get a feel for their look on the UI.

Interpolated Strings

Very often you’ll want to have some dynamic parts of the text, like the user name or some information fetched from the backend.

Let’s add some personalized greetings to our app. Add a new key with a string placeholder to our resource files.

<string name="welcome_name">Welcome %s</string>

Update our Greeting component to show welcome to our users.

@Composable
fun Greeting(name: String) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(20.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Text(text = stringResource(R.string.welcome_name, name))
Text(text = stringResource(R.string.welcome_subtitle), textAlign = TextAlign.Center)
}
}

We added a name parameter that we used for a placeholder. Build and run the app.

placeholder.png

For some other cases, you can use %d for Integer and %.2f for Float placeholders.

Plurals localization

If/else block with multiple keys can solve your headaches for one language but for a more bulletproof solution, we are going to use plurals tag in the resources file.

The full set supported by Android is zero, one, two, few, many, and other.

Now we can add some pluralization rules!

Let's take a string like this: %d home(s) found.

We would like to show:

  • One home found’ - when argument is 1

  • %d homes found’ - when argument is 2 or more

Let’s add a new plural string to the resource file.

<plurals name="homes_num">
<item quantity="one">One home found.</item>
<item quantity="other">%d homes found.</item>
</plurals>

As a developer, you should always supply one and other strings.

For each plural option, you can add a new item and define its translation.

Now, let's test our pluralization rules. We will use getQuantityString() method.

Replace your Greeting body and add a new Preview:

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun Greeting(count: Int) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(20.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Text(text = pluralStringResource(id = R.plurals.homes_num, count = count, count))
}
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
JetpackLocalizationDemoTheme {
Greeting(1)
}
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview1() {
JetpackLocalizationDemoTheme {
Greeting(12)
}
}

As you can see we can use pluralStringResource for getting the quantity string. Make sure to pass the count parameter twice if you have an Int placeholder in translation as we have in this example.

Build and check two Previews we made.

Screenshot 2022-09-02 at 14.54.58.png

That’s it! We’ve successfully added plural rules to our app. You can now play around, add more rules, change the count constant to 1,2 or higher and test our pluralization rules!

Translations Editor

Translations Editor is a tool in Android Studio for easier manipulation and overview of strings.

Right-click on the English strings.xml file and select Translations Editor at the bottom of the drop-down.

Screenshot 2022-09-02 at 15.13.52.png

Besides a nice overview of keys and translations, you get warnings for untranslated keys, and you can make sure everything is translated into all languages here.

Final thoughts about Jetpack Compose apps Localization

Jetpack Compose is an up-and-coming framework. It is, without a doubt, the future of Android UI building.

When it comes to Android localization, still, there are a lot of manual tasks which can be automated.

Some of the pain points of manual localization are:

  • Copy-pasting from spreadsheets is a painful, error-prone, and slow process

  • You have no centralized platform to work from

  • Collaboration is not so easy

  • You can't automate the localization process with spreadsheets

Translized is a localization platform that can help you with that and do all the heavy lifting.

Some of the benefits you can expect from using a localization platform are:

  • Saving engineering hours

  • Ensuring translations quality

  • Easy collaboration

  • Reaching new markets faster

Sign up for a 7-day free trial and check it yourself!

Content

Replace slow or expensive processes and ensure translation quality with Translized

Our 7-day free trial includes 60 000 keys and unlimited projects.
View Pricing Plans to upgrade, or continue with our free plan - 200 keys.

Try for free