Skip to content

Commit

Permalink
feat(i18n): add languages to in-app language picker (#571)
Browse files Browse the repository at this point in the history
* feat(i18n): add languages to in-app language picker

* fix(i18n): locale system settings not working for Android 13

* feat(i18n): show selected language at settings page

* fix(ci): ignore ExtraTranslation for linter

* feat(i18n): add fallback in in-app language picker for A13+

* chore: clean up
  • Loading branch information
JunkFood02 authored Jan 31, 2024
1 parent 069e090 commit 66b1d51
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 111 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ android {
}
}
lint {
disable += "MissingTranslation"
disable.addAll("MissingTranslation", "ExtraTranslation")
}
buildTypes {
release {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import me.ash.reader.infrastructure.preference.SettingsProvider
import me.ash.reader.ui.ext.languages
import me.ash.reader.ui.page.common.HomeEntry
import java.lang.reflect.Field
import java.util.Locale
import javax.inject.Inject


Expand All @@ -39,14 +40,16 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.addFlags(FLAG_LAYOUT_IN_SCREEN or FLAG_LAYOUT_NO_LIMITS)
}
Log.i("RLog", "onCreate: ${ProfileInstallerInitializer().create(this)}")

// Set the language
LanguagesPreference.fromValue(languages).let {
LanguagesPreference.setLocale(it)
if (Build.VERSION.SDK_INT < 33) {
LanguagesPreference.fromValue(languages).let {
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
Expand Up @@ -2,6 +2,8 @@ package me.ash.reader.infrastructure.preference

import android.content.Context
import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.core.os.LocaleListCompat
import androidx.datastore.preferences.core.Preferences
import kotlinx.coroutines.CoroutineScope
Expand All @@ -14,132 +16,200 @@ import me.ash.reader.ui.ext.put
import java.util.*

sealed class LanguagesPreference(val value: Int) : Preference() {
object UseDeviceLanguages : LanguagesPreference(0)
object English : LanguagesPreference(1)
object ChineseSimplified : LanguagesPreference(2)
object German : LanguagesPreference(3)
object French : LanguagesPreference(4)
object Czech : LanguagesPreference(5)
object Italian : LanguagesPreference(6)
object Hindi : LanguagesPreference(7)
object Spanish : LanguagesPreference(8)
object Polish : LanguagesPreference(9)
object Russian : LanguagesPreference(10)
object Basque : LanguagesPreference(11)
object Indonesian : LanguagesPreference(12)

object ChineseTraditional : LanguagesPreference(13)
data object UseDeviceLanguages : LanguagesPreference(0)
data object English : LanguagesPreference(1)
data object ChineseSimplified : LanguagesPreference(2)
data object German : LanguagesPreference(3)
data object French : LanguagesPreference(4)
data object Czech : LanguagesPreference(5)
data object Italian : LanguagesPreference(6)
data object Hindi : LanguagesPreference(7)
data object Spanish : LanguagesPreference(8)
data object Polish : LanguagesPreference(9)
data object Russian : LanguagesPreference(10)
data object Basque : LanguagesPreference(11)
data object Indonesian : LanguagesPreference(12)
data object ChineseTraditional : LanguagesPreference(13)
data object Arabic : LanguagesPreference(14)
data object Bulgarian : LanguagesPreference(15)
data object Catalan : LanguagesPreference(16)
data object Danish : LanguagesPreference(17)
data object Dutch : LanguagesPreference(18)
data object Esperanto : LanguagesPreference(19)
data object Filipino : LanguagesPreference(20)
data object Hebrew : LanguagesPreference(21)
data object Hungarian : LanguagesPreference(22)
data object Japanese : LanguagesPreference(23)
data object Kannada : LanguagesPreference(24)
data object NorwegianBokmal : LanguagesPreference(25)
data object Persian : LanguagesPreference(26)
data object Portuguese : LanguagesPreference(27)
data object PortugueseBrazil : LanguagesPreference(28)
data object Romanian : LanguagesPreference(29)
data object Serbian : LanguagesPreference(30)
data object Slovenian : LanguagesPreference(31)
data object Swedish : LanguagesPreference(32)
data object Turkish : LanguagesPreference(33)
data object Ukrainian : LanguagesPreference(34)
data object Vietnamese : LanguagesPreference(35)


override fun put(context: Context, scope: CoroutineScope) {
scope.launch {
context.dataStore.put(
DataStoreKeys.Languages,
value
DataStoreKeys.Languages, value
)
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)
@Composable
fun toDesc(): String {
return when (this) {
ChineseTraditional -> stringResource(id = R.string.chinese_traditional)
ChineseSimplified -> stringResource(id = R.string.chinese_simplified)
else -> {
this.toLocale().toDisplayName()
}
}
}

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")
}

private fun toLocaleList(): LocaleListCompat = toLocale()?.let { LocaleListCompat.create(it) }
?: LocaleListCompat.getEmptyLocaleList()
fun toLocale(): Locale? = when (this) {
UseDeviceLanguages -> null
English -> Locale("en")
ChineseSimplified -> Locale.forLanguageTag("zh-Hans")
German -> Locale("de")
French -> Locale("fr")
Czech -> Locale("cs")
Italian -> Locale("it")
Hindi -> Locale("hi")
Spanish -> Locale("es")
Polish -> Locale("pl")
Russian -> Locale("ru")
Basque -> Locale("eu")
Indonesian -> Locale("in")
ChineseTraditional -> Locale.forLanguageTag("zh-Hant")
Arabic -> Locale("ar")
Bulgarian -> Locale("bg")
Catalan -> Locale("ca")
Danish -> Locale("da")
Dutch -> Locale("nl")
Esperanto -> Locale("eo")
Filipino -> Locale("fil")
Hebrew -> Locale("he")
Hungarian -> Locale("hu")
Japanese -> Locale("ja")
Kannada -> Locale("kn")
NorwegianBokmal -> Locale("nb")
Persian -> Locale("fa")
Portuguese -> Locale("pt")
PortugueseBrazil -> Locale("pt", "BR")
Romanian -> Locale("ro")
Serbian -> Locale("sr")
Slovenian -> Locale("sl")
Swedish -> Locale("sv")
Turkish -> Locale("tr")
Ukrainian -> Locale("uk")
Vietnamese -> Locale("vi")
}

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,
Arabic,
Basque,
Bulgarian,
Catalan,
ChineseSimplified,
ChineseTraditional,
Czech,
Danish,
Dutch,
English,
Esperanto,
Filipino,
French,
German,
Hebrew,
Hindi,
Hungarian,
Indonesian,
Italian,
Japanese,
Kannada,
NorwegianBokmal,
Persian,
Polish,
Portuguese,
PortugueseBrazil,
Romanian,
Serbian,
Slovenian,
Spanish,
Swedish,
Turkish,
Ukrainian,
Vietnamese
)

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
}

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
}
fromValue(preferences[DataStoreKeys.Languages.key] ?: 0)

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
14 -> Arabic
15 -> Bulgarian
16 -> Catalan
17 -> Danish
18 -> Dutch
19 -> Esperanto
20 -> Filipino
21 -> Hebrew
22 -> Hungarian
23 -> Japanese
24 -> Kannada
25 -> NorwegianBokmal
26 -> Persian
27 -> Portuguese
28 -> PortugueseBrazil
29 -> Romanian
30 -> Serbian
31 -> Slovenian
32 -> Swedish
33 -> Turkish
34 -> Ukrainian
35 -> Vietnamese
else -> default
}

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

}
}

@Composable
fun Locale?.toDisplayName(): String = this?.getDisplayName(this) ?: stringResource(
id = R.string.use_device_languages
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import androidx.core.os.LocaleListCompat
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import me.ash.reader.R
import me.ash.reader.infrastructure.preference.LocalNewVersionNumber
import me.ash.reader.infrastructure.preference.LocalSkipVersionNumber
import me.ash.reader.infrastructure.preference.toDisplayName
import me.ash.reader.ui.component.base.Banner
import me.ash.reader.ui.component.base.DisplayText
import me.ash.reader.ui.component.base.FeedbackIconButton
Expand All @@ -31,6 +33,7 @@ import me.ash.reader.ui.page.common.RouteName
import me.ash.reader.ui.page.settings.tips.UpdateDialog
import me.ash.reader.ui.page.settings.tips.UpdateViewModel
import me.ash.reader.ui.theme.palette.onLight
import java.util.Locale

@Composable
fun SettingsPage(
Expand Down Expand Up @@ -123,7 +126,7 @@ fun SettingsPage(
item {
SelectableSettingGroupItem(
title = stringResource(R.string.languages),
desc = stringResource(R.string.languages_desc),
desc = Locale.getDefault().toDisplayName(),
icon = Icons.Outlined.Language,
) {
navController.navigate(RouteName.LANGUAGES) {
Expand Down
Loading

0 comments on commit 66b1d51

Please sign in to comment.