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!
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:
Click the globe icon in the Translations Editor.
Select the language you want to add from the list.

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()}}}}}@Composablefun 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)@Composablefun DefaultPreview() {JetpackLocalizationDemoTheme {Greeting()}}
Build and run the app. Viola!

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.configurationval locale = Locale("de")Locale.setDefault(locale)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)config.setLocale(locale)elseconfig.locale = localeif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)createConfigurationContext(config)resources.updateConfiguration(config, resources.displayMetrics)
Build and run again.

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")@Composablefun DefaultPreview() {JetpackLocalizationDemoTheme {Greeting()}}
Check your Preview tab, and click on the Build Refresh button to refresh the canvas if no change is reflected:

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)@Composablefun DefaultPreview1() {JetpackLocalizationDemoTheme {Greeting()}}@Preview(showBackground = true, locale = "de")@Composablefun DefaultPreview2() {JetpackLocalizationDemoTheme {Greeting()}}
Refresh the Preview and check the result:

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.
@Composablefun 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.

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)@Composablefun 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)@Composablefun DefaultPreview() {JetpackLocalizationDemoTheme {Greeting(1)}}@Preview(showBackground = true)@Composablefun 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.

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.

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!