Support configuring interface language per user (#1406)

## Description
Adds a setting to configure the app's language/locale. It is configured
per user. This settings has no impact on audio or subtitles language
choices.

Only languages Wholphin has translations for can be used. If you would
like to contribute new translations, check out
https://translate.codeberg.org/projects/wholphin/!

Dev notes: This doesn't exactly follow Android's recommendations because
the [guidelines are for
per-app](https://developer.android.com/guide/topics/resources/app-languages)
and not users within the app.

### Related issues
Closes #513
Closes #669

### Testing
- Emulator API 34
- Nvidia shield API 30
- Fire TV OS 7 API 28

## Screenshots
<img width="1280" height="720" alt="language Large"
src="https://github.com/user-attachments/assets/bf1c0962-8a36-4012-aed9-eab564fc1114"
/>

## AI or LLM usage
None
This commit is contained in:
Damontecres 2026-05-24 09:55:08 -04:00 • committed by GitHub
parent 625cdcb4a3
commit 903c45dfb8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 1501 additions and 418 deletions

View file

@ -46,9 +46,8 @@ import java.util.UUID
ItemTrackModification::class,
SeerrServer::class,
SeerrUser::class,
],
version = 32,
version = 33,
exportSchema = true,
autoMigrations = [
AutoMigration(3, 4),
@ -64,6 +63,7 @@ import java.util.UUID
AutoMigration(20, 30),
AutoMigration(30, 31),
AutoMigration(31, 32),
AutoMigration(32, 33),
],
)
@TypeConverters(Converters::class)

View file

@ -7,6 +7,7 @@ import com.github.damontecres.wholphin.data.model.BaseItem
import com.github.damontecres.wholphin.ui.AspectRatio
import com.github.damontecres.wholphin.ui.components.ViewOptions
import com.github.damontecres.wholphin.ui.nav.Destination
import com.github.damontecres.wholphin.ui.util.ResStringProvider
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
import org.jellyfin.sdk.model.UUID
import org.jellyfin.sdk.model.api.ExtraType
@ -41,8 +42,7 @@ sealed interface ExtrasItem {
) : ExtrasItem {
override val destination: Destination =
Destination.ItemGrid(
title = null,
titleRes = type.stringRes,
title = ResStringProvider(type.stringRes),
request =
GetItemsRequest(
ids = items.map { it.id },

View file

@ -64,6 +64,7 @@ data class JellyfinUser(
@ColumnInfo(defaultValue = "false")
val requireLogin: Boolean = false,
val lastUsed: ZonedDateTime? = null,
val uiLanguage: String? = null,
) {
val hasPin: Boolean get() = pin.isNotNullOrBlank()