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!
min read
Start by creating a new project in Android Studio.
File ▸ New ▸ New Project ▸ App...
💡 Make sure to select Empty Compose Activity as a template.
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:
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!
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!
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.
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.
Now we see the German localized version!
💡 Don’t forget to delete this code, since it is for testing purposes only!
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:
Now you can see German version directly in the IDE!
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:
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.
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.
For some other cases, you can use %d for Integer and %.2f for Float placeholders.
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:
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.
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 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.
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:
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:
Sign up for a 7-day free trial and check it yourself!