Skip to content
This repository was archived by the owner on Jul 11, 2025. It is now read-only.

Commit f5821ed

Browse files
neelanshsahaiashnoheNeelansh Sahai
authored
Add Sample App using views (#390)
* PerAppLanguages demo using Compose + Shows in-app language picker + Shows Settings App language picker video: https://photos.app.goo.gl/mgP8ZXUaiE5SpveN7 Patchset 1 can be ignored, this is boilerplate code from the New Project Wizard Patchset 2 and above contains code required to use the per-app language preferences with Compose Patchset 3: license files Patchset 4 -- 6: ack code review comments Change-Id: Ide4b342283ba2443b67d16870459c27ad50f2c89 * PerAppLanguages Compose Sample README Change-Id: I3b2e20431493299db3dc16da963e5a83cc34f490 * move per app language preferences compose app to compose_app directory to make way for an additional app Change-Id: I008e73eac8f71964f8f5f68e3893420f5ca3c42c * Add Per App Language Preferences sample in views Change-Id: Ie59890cf181a23ac6f60fabf7b7b8ea0fd71dcd6 * Add README.md Change-Id: Ib1ff08bf76b2d252289e25847b5b563535ee30e7 Co-authored-by: Ash Nohe <[email protected]> Co-authored-by: Neelansh Sahai <[email protected]>
1 parent c5c36c4 commit f5821ed

File tree

3 files changed

+155
-0
lines changed

3 files changed

+155
-0
lines changed

PerAppLanguages/views_app/README.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Per App Language Preference, Sample code using Views
2+
3+
This Compose sample demonstrates how to use the new [Per-App Language Preferences](https://developer.android.com/guide/topics/resources/app-languages) APIs introduced in API level 33. The new set of APIs allows an application language to be different from the system language
4+
5+
With this feature now Users will be able to change the language settings from the settings option by selecting:
6+
7+
***Settings → System → Languages & Input → App Languages → [Select the desired App][Select the desired Language]***
8+
9+
![Example 1](screenshots/SystemSettings.gif)
10+
11+
---
12+
13+
## Steps required to implement the APIs
14+
15+
### 1. Add the Libraries
16+
17+
Use the latest version of AppCompat Library
18+
19+
```bash
20+
dependencies {
21+
...
22+
implementation "androidx.appcompat:appcompat:$latestAppCompatVersion"
23+
implementation "androidx.appcompat:appcompat-resources:$latestAppCompatVersion"
24+
...
25+
}
26+
```
27+
28+
### 2. Create locale_config.xml file
29+
Create a new file in `values/xml/` directory and name it as `locale_config.xml`. This file should contain a list of all the locales that are supported by the app. The list element should be a string containing a locale tag.
30+
31+
> NOTE: The locale tags must follow the BCP47 syntax ( which is usually {language subtag}–{script subtag}–{country subtag} ). Anything other than that will be filtered out by the system and won't be visible in the system settings.
32+
33+
```xml
34+
<?xml version="1.0" encoding="utf-8"?>
35+
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
36+
...
37+
<locale android:name="en"/> <!-- English -->
38+
<locale android:name="en-GB"/> <!-- English (United Kingdom) -->
39+
<locale android:name="fr"/> <!-- French -->
40+
<locale android:name="ja"/> <!-- Japanese -->
41+
<locale android:name="zh-Hans-MO"/> <!-- Chinese (Macao) in Simplified Script -->
42+
<locale android:name="zh-Hant-TW"/> <!-- Chinese (Taiwan) in Traditional Script -->
43+
...
44+
</locale-config>
45+
```
46+
47+
### 3. Add the LocaleConfig in the `AndroidManifest.xml`
48+
Specify this `locale_config.xml` file in the app’s `AndroidManifest.xml`
49+
50+
```xml
51+
<manifest>
52+
...
53+
<application
54+
...
55+
android:localeConfig="@xml/locales_config"
56+
</application>
57+
</manifest>
58+
```
59+
60+
### 4. Use AndroidX APIs
61+
Use the APIs in your code to set and get the app locales.
62+
```kotlin
63+
val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags("xx-YY")
64+
65+
// Call this on the main thread as it may require Activity.restart()
66+
AppCompatDelegate.setApplicationLocales(appLocale)
67+
68+
69+
// Call this to get the selected locale and display it in your App
70+
val selectedLocale = AppCompatDelegate.getApplicationLocales()[0]
71+
```
72+
73+
### 5. Delegate storage to AndroidX
74+
Let AndroidX handle the locale storage so that the user preference persists.
75+
76+
```xml
77+
<application
78+
...
79+
<service
80+
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
81+
android:enabled="false"
82+
android:exported="false">
83+
<meta-data
84+
android:name="autoStoreLocales"
85+
android:value="true" />
86+
</service>
87+
</application>
88+
```
89+
90+
### Additional things to take care of while migrating to the API
91+
If earlier the user preference was stored in, let's say a SharedPreference, then it is recommended to handle that preference to AndroidX, on the first app launch after the update of Per-App Language Feature. This snippet for migration will ensure a smooth transition and the user is not required to set App Language after updating the app.
92+
93+
```kotlin
94+
// Specify the constants to be used in the below code snippets
95+
companion object {
96+
97+
// Constants for SharedPreference File
98+
const val PREFERENCE_NAME = "shared_preference"
99+
const val PREFERENCE_MODE = Context.MODE_PRIVATE
100+
101+
// Constants for SharedPreference Keys
102+
const val FIRST_TIME_MIGRATION = "first_time_migration"
103+
const val SELECTED_LANGUAGE = "selected_language"
104+
105+
// Constants for SharedPreference Values
106+
const val STATUS_DONE = "status_done"
107+
}
108+
```
109+
110+
```kotlin
111+
// Utility method to put a string in a SharedPreference
112+
private fun putString(key: String, value: String) {
113+
val editor = getSharedPreferences(PREFERENCE_NAME, PREFERENCE_MODE).edit()
114+
editor.putString(key, value)
115+
editor.apply()
116+
}
117+
118+
// Utility method to get a string from a SharedPreference
119+
private fun getString(key: String): String? {
120+
val preference = getSharedPreferences(PREFERENCE_NAME, PREFERENCE_MODE)
121+
return preference.getString(key, null)
122+
}
123+
```
124+
125+
```kotlin
126+
// Check if the migration has already been done or not
127+
if (getString(FIRST_TIME_MIGRATION) != STATUS_DONE) {
128+
129+
// Fetch the selected language from wherever it was stored. In this case it’s SharedPref
130+
// In this case let’s assume that it was stored in a key named SELECTED_LANGUAGE
131+
getString(SELECTED_LANGUAGE)?.let { it →
132+
133+
// Set this locale using the AndroidX library that will handle the storage itself
134+
val localeList = LocaleListCompat.forLanguageTags(it)
135+
AppCompatDelegate.setApplicationLocales(localeList)
136+
137+
// Set the migration flag to ensure that this is executed only once
138+
putString(FIRST_TIME_MIGRATION, STATUS_DONE)
139+
}
140+
}
141+
```
142+
143+
Once this is done. The app will work seamlessly, with the In-App Language Picker and the System Settings Language Picker as well.
144+
145+
![Sample App walk-through](screenshots/SampleAppWalkThrough.gif)
146+
147+
---
148+
149+
# Getting Started
150+
This sample uses the Gradle build system. To build this project, use the `gradlew build` command or use "Import Project" in Android Studio.
151+
152+
# Support
153+
If you've found an error in this sample, please file an issue: https://github.com/android/user-interface
154+
155+
Patches are encouraged, and may be submitted by forking this project and submitting a pull request through GitHub. Please see CONTRIBUTING.md for more details.
3.23 MB
Loading
3.72 MB
Loading

0 commit comments

Comments
 (0)