Skip to content

Commit

Permalink
fix(i18n): configuration loss when switching locale (#541)
Browse files Browse the repository at this point in the history
* fix(i18n): configuration loss when switching locale

* feat(locale): enable auto-localeconfig
  • Loading branch information
JunkFood02 authored Jan 30, 2024
1 parent 178c771 commit 069e090
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 107 deletions.
7 changes: 7 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ android {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}

// https://developer.android.com/guide/topics/resources/app-languages#auto-localeconfig
androidResources {
generateLocaleConfig true
}

namespace 'me.ash.reader'
}

Expand Down Expand Up @@ -197,6 +203,7 @@ dependencies {
// android
implementation "androidx.core:core-ktx:1.12.0"
implementation "androidx.activity:activity-compose:1.8.2"
implementation 'androidx.appcompat:appcompat:1.6.1'
testImplementation "junit:junit:4.13.2"
androidTestImplementation "androidx.test.ext:junit:1.1.3"
androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0"
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>

<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
android:exported="false">
<meta-data
android:name="autoStoreLocales"
android:value="true" />
</service>
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import android.os.Bundle
import android.util.Log
import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.CompositionLocalProvider
import androidx.core.view.WindowCompat
import androidx.profileinstaller.ProfileInstallerInitializer
Expand All @@ -28,7 +28,7 @@ import javax.inject.Inject
* The Single-Activity Architecture.
*/
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
class MainActivity : AppCompatActivity() {

@Inject
lateinit var imageLoader: ImageLoader
Expand All @@ -46,8 +46,7 @@ class MainActivity : ComponentActivity() {

// Set the language
LanguagesPreference.fromValue(languages).let {
if (it == LanguagesPreference.UseDeviceLanguages) return@let
it.setLocale(this)
LanguagesPreference.setLocale(it)
}

// Workaround for https://github.com/Ashinch/ReadYou/issues/312: increase cursor window size
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package me.ash.reader.infrastructure.preference

import android.content.Context
import android.os.LocaleList
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat
import androidx.datastore.preferences.core.Preferences
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import me.ash.reader.R
import me.ash.reader.ui.ext.DataStoreKeys
Expand Down Expand Up @@ -31,124 +33,113 @@ sealed class LanguagesPreference(val value: Int) : Preference() {
override fun put(context: Context, scope: CoroutineScope) {
scope.launch {
context.dataStore.put(
DataStoreKeys.Languages,
value
DataStoreKeys.Languages,
value
)
setLocale(context)
scope.launch(Dispatchers.Main) { setLocale(this@LanguagesPreference) }
}
}

fun toDesc(context: Context): String =
when (this) {
UseDeviceLanguages -> context.getString(R.string.use_device_languages)
English -> context.getString(R.string.english)
ChineseSimplified -> context.getString(R.string.chinese_simplified)
German -> context.getString(R.string.german)
French -> context.getString(R.string.french)
Czech -> context.getString(R.string.czech)
Italian -> context.getString(R.string.italian)
Hindi -> context.getString(R.string.hindi)
Spanish -> context.getString(R.string.spanish)
Polish -> context.getString(R.string.polish)
Russian -> context.getString(R.string.russian)
Basque -> context.getString(R.string.basque)
Indonesian -> context.getString(R.string.indonesian)
ChineseTraditional -> context.getString(R.string.chinese_traditional)
}

fun getLocale(): Locale =
when (this) {
UseDeviceLanguages -> LocaleList.getDefault().get(0)
English -> Locale("en", "US")
ChineseSimplified -> Locale("zh", "CN")
German -> Locale("de", "DE")
French -> Locale("fr", "FR")
Czech -> Locale("cs", "CZ")
Italian -> Locale("it", "IT")
Hindi -> Locale("hi", "IN")
Spanish -> Locale("es", "ES")
Polish -> Locale("pl", "PL")
Russian -> Locale("ru", "RU")
Basque -> Locale("eu", "ES")
Indonesian -> Locale("in", "ID")
ChineseTraditional -> Locale("zh", "TW")
}
when (this) {
UseDeviceLanguages -> context.getString(R.string.use_device_languages)
English -> context.getString(R.string.english)
ChineseSimplified -> context.getString(R.string.chinese_simplified)
German -> context.getString(R.string.german)
French -> context.getString(R.string.french)
Czech -> context.getString(R.string.czech)
Italian -> context.getString(R.string.italian)
Hindi -> context.getString(R.string.hindi)
Spanish -> context.getString(R.string.spanish)
Polish -> context.getString(R.string.polish)
Russian -> context.getString(R.string.russian)
Basque -> context.getString(R.string.basque)
Indonesian -> context.getString(R.string.indonesian)
ChineseTraditional -> context.getString(R.string.chinese_traditional)
}

fun setLocale(context: Context) {
val locale = getLocale()
val resources = context.resources
val metrics = resources.displayMetrics
val configuration = resources.configuration
configuration.setLocale(locale)
configuration.setLocales(LocaleList(locale))
context.createConfigurationContext(configuration)
resources.updateConfiguration(configuration, metrics)
private fun toLocale(): Locale? =
when (this) {
UseDeviceLanguages -> null
English -> Locale("en", "US")
ChineseSimplified -> Locale("zh", "CN")
German -> Locale("de", "DE")
French -> Locale("fr", "FR")
Czech -> Locale("cs", "CZ")
Italian -> Locale("it", "IT")
Hindi -> Locale("hi", "IN")
Spanish -> Locale("es", "ES")
Polish -> Locale("pl", "PL")
Russian -> Locale("ru", "RU")
Basque -> Locale("eu", "ES")
Indonesian -> Locale("in", "ID")
ChineseTraditional -> Locale("zh", "TW")
}

val appResources = context.applicationContext.resources
val appMetrics = appResources.displayMetrics
val appConfiguration = appResources.configuration
appConfiguration.setLocale(locale)
appConfiguration.setLocales(LocaleList(locale))
context.applicationContext.createConfigurationContext(appConfiguration)
appResources.updateConfiguration(appConfiguration, appMetrics)
}
private fun toLocaleList(): LocaleListCompat = toLocale()?.let { LocaleListCompat.create(it) }
?: LocaleListCompat.getEmptyLocaleList()

companion object {

val default = UseDeviceLanguages
val values = listOf(
UseDeviceLanguages,
English,
ChineseSimplified,
German,
French,
Czech,
Italian,
Hindi,
Spanish,
Polish,
Russian,
Basque,
Indonesian,
ChineseTraditional,
UseDeviceLanguages,
English,
ChineseSimplified,
German,
French,
Czech,
Italian,
Hindi,
Spanish,
Polish,
Russian,
Basque,
Indonesian,
ChineseTraditional,
)

fun fromPreferences(preferences: Preferences): LanguagesPreference =
when (preferences[DataStoreKeys.Languages.key]) {
0 -> UseDeviceLanguages
1 -> English
2 -> ChineseSimplified
3 -> German
4 -> French
5 -> Czech
6 -> Italian
7 -> Hindi
8 -> Spanish
9 -> Polish
10 -> Russian
11 -> Basque
12 -> Indonesian
13 -> ChineseTraditional
else -> default
}
when (preferences[DataStoreKeys.Languages.key]) {
0 -> UseDeviceLanguages
1 -> English
2 -> ChineseSimplified
3 -> German
4 -> French
5 -> Czech
6 -> Italian
7 -> Hindi
8 -> Spanish
9 -> Polish
10 -> Russian
11 -> Basque
12 -> Indonesian
13 -> ChineseTraditional
else -> default
}

fun fromValue(value: Int): LanguagesPreference =
when (value) {
0 -> UseDeviceLanguages
1 -> English
2 -> ChineseSimplified
3 -> German
4 -> French
5 -> Czech
6 -> Italian
7 -> Hindi
8 -> Spanish
9 -> Polish
10 -> Russian
11 -> Basque
12 -> Indonesian
13 -> ChineseTraditional
else -> default
}
when (value) {
0 -> UseDeviceLanguages
1 -> English
2 -> ChineseSimplified
3 -> German
4 -> French
5 -> Czech
6 -> Italian
7 -> Hindi
8 -> Spanish
9 -> Polish
10 -> Russian
11 -> Basque
12 -> Indonesian
13 -> ChineseTraditional
else -> default
}

fun setLocale(preference: LanguagesPreference) {
AppCompatDelegate.setApplicationLocales(preference.toLocaleList())
}

}
}
1 change: 1 addition & 0 deletions app/src/main/res/resources.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
unqualifiedResLocale=en-US

0 comments on commit 069e090

Please sign in to comment.