Blog Infos
Author
Published
Topics
Published

How to use the new feature from Android 13 to display your app in a language different of the system one

Recently Google released the developer preview of Android 13 — also known as Tiramisu — that introduces a new feature which developers have been waiting for a certain time: the Per-app language preferences.

This new feature make it possible to run the application under locales that are not necessarily the same set at Android settings, providing a better experience for multilingual users. It allows applications to change the locale preferences at runtime using the newly introduced APIs.

This article will explain how to implement an app that uses the new Per-app language preferences.

App project

Once this feature was introduced in the Android 13 developer preview, make sure to set the right versions in the SDK configurations at your build.gradle.

We set the minSdkPreview and targetSdkPreview to Tiramisu and compileSdkPreview to android-Tiramisu. You can see the complete build.gradlebelow:

plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdkPreview "android-Tiramisu"
defaultConfig {
applicationId "com.paceli.sampleperapplanguage"
minSdkPreview "Tiramisu"
targetSdkPreview "Tiramisu"
versionCode 1
versionName "1.0"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
}
view raw build.gradle hosted with ❤ by GitHub

Configuration of build.gradle to use Android Tiramisu developer preview SDK

 

Localized strings

Having the project created and configured, it’s time to add some localized text so we are able to see if the application language is really changing as expected.

So let’s add a couple of locales to the application using the Android Studio’s Translations Editor as usual, and then adding a new string with our very famous sentence, Hello World, and its localized versions.

I am using Google Translate to create the localized strings, so please forgive me if anything is not translated as expected.

Android Studio’s Translations Editor

Job Offers

Job Offers


    Senior Android Engineer, Infrastructure

    Peloton
    New York, USA
    • Full Time
    apply now

    Mobile Developer Android (m/w/d) Firebase

    REWE digital
    Köln / Cologne
    • Full Time
    apply now

    Senior Android Engineer (m/f/d)

    Trade Republic
    Berlin, Germany
    • Full Time
    apply now
Load more listings

OUR VIDEO RECOMMENDATION

, ,

The Evolution of Android Graphics in Android 12/13

Android 12 and 13 both added significant new capabilities to Android platform graphics, including RenderEffect, RuntimeShader, and more. At the same time, RenderScript has been deprecated and we’ve introduced the RenderScript Intrinsics Replacement Toolkit. This…
Watch Video

The Evolution of Android Graphics in Android 12/13

Daniel Galpin
Android Developer Advocate and Fast Talking YouTuber
Google

The Evolution of Android Graphics in Android 12/13

Daniel Galpin
Android Developer Ad ...
Google

The Evolution of Android Graphics in Android 12/13

Daniel Galpin
Android Developer Advocat ...
Google

Jobs

Locale Picker

Now that the application already have the localized text to be displayed to the user, we just need to provide a way that they can choose which language should be used while running our app.

In order to do that, let’s create an Spinner with the supported locale tags and also an option to reset language preference and use system locale. Then set the Spinner’s onItemSelectedListener in order to call the code that actually changes the application language:

private fun initLocalePicker() {
val systemLocale = getString(R.string.system_locale)
val spinner: Spinner = findViewById(R.id.localePicker)
val locales = listOf(systemLocale, "en-US", "es-ES", "iw-IL", "ja-JP", "uk-UA")
spinner.adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, locales)
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val selectedLocale = spinner.adapter.getItem(position) as String
if (selectedLocale != systemLocale) {
updateAppLocales(Locale.forLanguageTag(selectedLocale))
} else {
updateAppLocales()
}
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
}
view raw MainActivity.kt hosted with ❤ by GitHub

Code to initialize the locale picker

 

Changing App’s Locale

In order to change current application’s locale we need to obtain an instance of LocaleManager using the getSystemService method from Context class. Then create a new LocaleList with the new locales that must be used by the application and pass it as argument to setApplicationLocales.

Note: LocaleList is a class available in Android SDK. It is not the same as a List of Locale instances.
private fun updateAppLocales(vararg locales: Locale) {
val localeManager = getSystemService(LocaleManager::class.java)
localeManager.applicationLocales = LocaleList(*locales)
}
view raw MainActivity.kt hosted with ❤ by GitHub

Code to update the application locales preference

 

To reset application locales and use the system’s one, pass an empty LocaleListthat can be obtained by calling LocaleList#getEmptyLocaleList().

Calling getApplicationLocales will return the list of locales that are currently set for the application. Let’s use it to update the activity’s title with the display name of the current locale:

private fun updateActivityTitle() {
val localeManager = getSystemService(LocaleManager::class.java)
val appLocales = localeManager.applicationLocales
title = if (appLocales.isEmpty) {
getString(R.string.system_locale)
} else {
appLocales.get(0).displayName
}
}
view raw MainActivity.kt hosted with ❤ by GitHub

Code to update activity’s title with the display name of current locale

 

Now the application is ready. You can find the complete activity’s code below:

package com.paceli.sampleperapplanguage
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Spinner
import android.app.LocaleManager
import android.os.Build
import android.os.LocaleList
import androidx.annotation.RequiresApi
import java.util.*
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initLocalePicker()
updateActivityTitle()
}
private fun updateActivityTitle() {
val localeManager = getSystemService(LocaleManager::class.java)
val appLocales = localeManager.applicationLocales
title = if (appLocales.isEmpty) {
getString(R.string.system_locale)
} else {
appLocales.get(0).displayName
}
}
private fun updateAppLocales(vararg locales: Locale) {
val localeManager = getSystemService(LocaleManager::class.java)
localeManager.applicationLocales = LocaleList(*locales)
}
private fun initLocalePicker() {
val systemLocale = getString(R.string.system_locale)
val spinner: Spinner = findViewById(R.id.localePicker)
val locales = listOf(systemLocale, "en-US", "es-ES", "iw-IL", "ja-JP", "uk-UA")
spinner.adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, locales)
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val selectedLocale = spinner.adapter.getItem(position) as String
if (selectedLocale != systemLocale) {
updateAppLocales(Locale.forLanguageTag(selectedLocale))
} else {
updateAppLocales()
}
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
}
}
view raw MainActivity.kt hosted with ❤ by GitHub
Conclusion

You can read more about this feature at its Android developers page.

Please be aware that it is still under developer preview phase and it may be modified or removed at the final version. I’ll be updating the GitHub repositorywith any changes that may be required when the final version is released.

If you find this article helpful, please don’t forget to clap. I would also appreciate your feedback in the comments section. Thanks!

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
Today, We will explore the New notification 🔔 runtime permission that was added in…
READ MORE
blog
Android 13 (API 33) introduces a new tool called photo picker 🖼. Today, we…
READ MORE
blog
In the recently published Android 13 Developer Preview blog post, Dave Burke noted two…
READ MORE
blog
Google recently announced the first Developer Preview of Android 13, while there are a…
READ MORE

Leave a Reply

Your email address will not be published.

Fill out this field
Fill out this field
Please enter a valid email address.

Menu