Skip to content

Commit c6a26ae

Browse files
authored
Merge pull request #1601 from DimensionDev/feature/language_settings
add in app language settings
2 parents 1bc4e5b + b53370b commit c6a26ae

File tree

14 files changed

+318
-192
lines changed

14 files changed

+318
-192
lines changed

app/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ android {
108108
lint {
109109
disable.add("MissingTranslation")
110110
}
111+
androidResources {
112+
generateLocaleConfig = true
113+
}
111114
}
112115

113116
dependencies {

app/src/main/java/dev/dimension/flare/ui/screen/settings/SettingsScreen.kt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package dev.dimension.flare.ui.screen.settings
22

3+
import android.content.Intent
4+
import android.provider.Settings
35
import androidx.compose.foundation.clickable
46
import androidx.compose.foundation.layout.Arrangement
57
import androidx.compose.foundation.layout.Column
@@ -19,8 +21,10 @@ import androidx.compose.runtime.remember
1921
import androidx.compose.ui.Alignment
2022
import androidx.compose.ui.Modifier
2123
import androidx.compose.ui.input.nestedscroll.nestedScroll
24+
import androidx.compose.ui.platform.LocalContext
2225
import androidx.compose.ui.res.stringResource
2326
import androidx.compose.ui.unit.dp
27+
import androidx.core.net.toUri
2428
import compose.icons.FontAwesomeIcons
2529
import compose.icons.fontawesomeicons.Solid
2630
import compose.icons.fontawesomeicons.solid.CircleInfo
@@ -30,6 +34,7 @@ import compose.icons.fontawesomeicons.solid.Database
3034
import compose.icons.fontawesomeicons.solid.Filter
3135
import compose.icons.fontawesomeicons.solid.Gear
3236
import compose.icons.fontawesomeicons.solid.Globe
37+
import compose.icons.fontawesomeicons.solid.Language
3338
import compose.icons.fontawesomeicons.solid.Palette
3439
import compose.icons.fontawesomeicons.solid.Robot
3540
import compose.icons.fontawesomeicons.solid.TableList
@@ -92,6 +97,7 @@ internal fun SettingsScreen(
9297
toAiConfig: () -> Unit,
9398
onBack: () -> Unit,
9499
) {
100+
val context = LocalContext.current
95101
val topAppBarScrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
96102
val state by producePresenter { settingsPresenter() }
97103
FlareScaffold(
@@ -231,6 +237,37 @@ internal fun SettingsScreen(
231237
toAppearance.invoke()
232238
},
233239
)
240+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
241+
ListItem(
242+
headlineContent = {
243+
Text(text = stringResource(id = R.string.settings_language_title))
244+
},
245+
leadingContent = {
246+
ThemedIcon(
247+
imageVector = FontAwesomeIcons.Solid.Language,
248+
contentDescription = stringResource(id = R.string.settings_language_title),
249+
color = ThemeIconData.Color.SapphireBlue,
250+
)
251+
},
252+
supportingContent = {
253+
Text(text = stringResource(id = R.string.settings_language_description))
254+
},
255+
modifier =
256+
Modifier
257+
.listCardItem()
258+
.clickable {
259+
try {
260+
val intent =
261+
Intent(Settings.ACTION_APP_LOCALE_SETTINGS).apply {
262+
data = "package:${BuildConfig.APPLICATION_ID}".toUri()
263+
}
264+
context.startActivity(intent)
265+
} catch (e: Exception) {
266+
e.printStackTrace()
267+
}
268+
},
269+
)
270+
}
234271
state.user.onSuccess {
235272
ListItem(
236273
headlineContent = {

app/src/main/java/dev/dimension/flare/ui/screen/splash/SplashScreen.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dev.dimension.flare.ui.screen.splash
22

3+
import android.os.Build
34
import androidx.compose.foundation.Image
45
import androidx.compose.foundation.layout.Box
56
import androidx.compose.foundation.layout.fillMaxSize
@@ -21,10 +22,12 @@ internal fun SplashScreen() {
2122
.padding(it),
2223
contentAlignment = Alignment.Center,
2324
) {
24-
Image(
25-
painterResource(id = R.drawable.ic_launcher_foreground),
26-
contentDescription = null,
27-
)
25+
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
26+
Image(
27+
painterResource(id = R.drawable.ic_launcher_foreground),
28+
contentDescription = null,
29+
)
30+
}
2831
}
2932
}
3033
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
unqualifiedResLocale=en-US

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@
6767
<string name="settings_ai_config_translation_description">Replace Google Translate with AI translation, might take longer time</string>
6868
<string name="settings_ai_config_enable_tldr">Enable AI Summarization</string>
6969
<string name="settings_ai_config_tldr_description">Enable AI summarization for long posts, only available in post that longer than 500 characters</string>
70+
<string name="settings_language_title">Language</string>
71+
<string name="settings_language_description">Change the language of the app</string>
7072

7173
<string name="status_loadmore_error_retry">Retry</string>
7274
<string name="login_expired">Login session expired</string>

compose-ui/src/commonMain/kotlin/dev/dimension/flare/data/model/AppSettings.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import okio.BufferedSource
1616
public data class AppSettings(
1717
val version: String,
1818
val aiConfig: AiConfig = AiConfig(),
19+
val language: String = "",
1920
) {
2021
@Serializable
2122
public data class AiConfig(

compose-ui/src/jvmMain/kotlin/dev/dimension/flare/ui/component/DateTimeText.jvm.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@ import dev.dimension.flare.ui.render.UiDateTime
66
import org.ocpsoft.prettytime.PrettyTime
77
import java.time.format.DateTimeFormatter
88
import java.util.Date
9+
import java.util.Locale
910

1011
private val prettyTime = PrettyTime(Date(0))
1112

13+
public fun updateTimeFormatterLocale(locale: Locale) {
14+
prettyTime.setLocale(locale)
15+
}
16+
1217
@Composable
1318
internal actual fun rememberFormattedDateTime(
1419
data: UiDateTime,

desktopApp/build.gradle.kts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,56 @@ extra["nativeDestDir"] = "resources/macos-arm64"
143143
apply(from = File(projectDir, "install-native-libs.gradle.kts"))
144144
apply(from = File(projectDir, "build-swift.gradle.kts"))
145145

146+
147+
148+
abstract class GenerateSupportedLocales : DefaultTask() {
149+
150+
@get:OutputDirectory
151+
abstract val outputDir: DirectoryProperty
152+
153+
@TaskAction
154+
fun run() {
155+
val resRoot = project.file("src/main/composeResources")
156+
157+
val locales = resRoot.listFiles()
158+
?.filter { it.isDirectory && it.name.startsWith("values-") }
159+
?.map { it.name.removePrefix("values-") } // e.g. "ja", "zh", "zh-rCN"
160+
?.distinct()
161+
?.sorted()
162+
?.map { it.replace("-r", "-") }
163+
?: emptyList()
164+
165+
val pkg = "dev.dimension.flare"
166+
val outDir = outputDir.get().asFile
167+
val outFile = File(outDir, "SupportedLocales.kt")
168+
169+
outDir.mkdirs()
170+
outFile.writeText(
171+
"""
172+
package $pkg
173+
174+
object SupportedLocales {
175+
val tags: List<String> = listOf(
176+
"en-US",
177+
${locales.joinToString(",\n ") { "\"$it\"" }}
178+
)
179+
}
180+
""".trimIndent()
181+
)
182+
}
183+
}
184+
185+
val generateSupportedLocales = tasks.register<GenerateSupportedLocales>("generateSupportedLocales") {
186+
outputDir.set(layout.buildDirectory.dir("generated/supportedLocales"))
187+
}
188+
kotlin {
189+
sourceSets {
190+
val main by getting {
191+
kotlin.srcDir(generateSupportedLocales.map { it.outputDir })
192+
}
193+
}
194+
}
195+
196+
tasks.named("compileKotlin") {
197+
dependsOn(generateSupportedLocales)
198+
}

desktopApp/src/main/composeResources/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@
205205
<string name="settings_appearance_theme_pure_color_description">Increase contrast between background and text</string>
206206
<string name="settings_appearance_full_width_post">Full width post</string>
207207
<string name="settings_appearance_full_width_post_description">Show the post in full width</string>
208+
<string name="settings_language_title">Language</string>
209+
<string name="settings_language_description">Change the language of the app</string>
208210

209211
<string name="settings_about_source_code">Source code</string>
210212
<string name="settings_about_telegram">Telegram</string>

desktopApp/src/main/kotlin/dev/dimension/flare/ui/route/Route.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,6 @@ internal sealed interface Route {
185185

186186
data object LocalCache : ScreenRoute
187187

188-
data object StorageUsage : ScreenRoute
189-
190188
data class Following(
191189
val accountType: AccountType,
192190
val userKey: MicroBlogKey,

0 commit comments

Comments
 (0)