Skip to content

feat: add internationalization support, language selector, and Russia language - #14

Merged
Mahmud0808 merged 6 commits into
Mahmud0808:masterfrom
Ruslik31:master
Sep 4, 2026
Merged

feat: add internationalization support, language selector, and Russia language#14
Mahmud0808 merged 6 commits into
Mahmud0808:masterfrom
Ruslik31:master

Conversation

@Ruslik31

@Ruslik31 Ruslik31 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

No description provided.

Copilot AI lite review requested due to automatic review settings September 3, 2026 14:38
@Ruslik31

Ruslik31 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

😊

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The current locale switching logic won’t restore “System default” after a non-system language is selected because it uses Locale.getDefault() after having already overridden the process default locale.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR introduces app-level internationalization by adding a persisted language preference, a language selector in Settings, and Russian (ru) string resources across shared/UI and platform-specific modules.

Changes:

  • Add AppLanguage + persist language in UserPreferences/DataStore and surface it in AppUiState.
  • Add a Language row + chooser dialog in the Appearance settings section.
  • Add Russian translations and new language-related string resources (labels and setting title).
File summaries
File Description
ui/src/jvmCommonMain/kotlin/com/drdisagree/teledrive/presentation/TeleDriveApp.kt Applies the selected locale via LocalLocaleList and updates java.util.Locale based on the chosen language.
ui/src/jvmCommonMain/kotlin/com/drdisagree/teledrive/presentation/settings/SettingsSectionScreen.kt Adds a language selector dialog and a Settings row showing the current language.
ui/src/jvmCommonMain/kotlin/com/drdisagree/teledrive/presentation/AppViewModel.kt Extends AppUiState to include the selected language from preferences.
ui/src/commonMain/composeResources/values/strings.xml Adds new language setting strings and a language_labels array.
ui/src/commonMain/composeResources/values-ru/strings.xml Adds a full Russian localization set for shared UI strings.
shared/src/commonMain/kotlin/com/drdisagree/teledrive/domain/model/UserPreferences.kt Adds a persisted language field to user preferences.
shared/src/commonMain/kotlin/com/drdisagree/teledrive/domain/model/AppLanguage.kt Introduces the AppLanguage enum (SYSTEM/ENGLISH/RUSSIAN) plus code parsing helpers.
shared/src/commonMain/kotlin/com/drdisagree/teledrive/data/repository/SettingsRepositoryImpl.kt Reads/writes the new language preference to DataStore.
shared/src/commonMain/kotlin/com/drdisagree/teledrive/data/local/preferences/PreferenceKeys.kt Adds the LANGUAGE preference key.
desktop/src/main/composeResources/values-ru/strings.xml Adds Russian strings for desktop-specific UI resources.
android/src/main/res/values-ru/strings.xml Adds Russian strings for Android-native resources (e.g., notifications/errors).
Review details

Suppressed comments (1)

shared/src/commonMain/kotlin/com/drdisagree/teledrive/data/repository/SettingsRepositoryImpl.kt:172

  • If you switch the stored language value to use AppLanguage.code/fromCode, update the write side too; otherwise the repo will keep persisting enum names and code remains unused.
        this[PreferenceKeys.KEY_BACKUP_CREATED] = prefs.keyBackupCreated
        this[PreferenceKeys.THEME] = prefs.theme.name
        this[PreferenceKeys.LANGUAGE] = prefs.language.name
        this[PreferenceKeys.DYNAMIC_COLOR] = prefs.dynamicColor
        this[PreferenceKeys.VIEW_MODE] = prefs.viewMode.name
  • Files reviewed: 11/11 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are correctness/stability issues in the locale plumbing (system-locale restore behavior and an unsafe LocalLocaleList cast) plus a persistence robustness issue (storing enum name instead of stable code).

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (4)

Previously missed (2) — in code that hasn't changed since the last review.

ui/src/commonMain/composeResources/values-ru/strings.xml:197

  • Typo in Russian translation: "входе" should be "вход".
    ui/src/commonMain/composeResources/values-ru/strings.xml:553
  • Grammar in Russian translation: "Удален диски" should be "Удалены диски".

ui/src/jvmCommonMain/kotlin/com/drdisagree/teledrive/presentation/TeleDriveApp.kt:146

  • AppLanguage.SYSTEM uses java.util.Locale.getDefault() after the app may have already overridden the default locale, so switching back to “System” won’t restore the original system locale (it will keep the last overridden value). Capturing the initial default locale (or deriving it from the platform config) avoids this incorrect behavior.
    LaunchedEffect(state.language) {
        val javaLocale = when (state.language) {
            AppLanguage.SYSTEM -> java.util.Locale.getDefault()
            AppLanguage.ENGLISH -> java.util.Locale.forLanguageTag("en")
            AppLanguage.RUSSIAN -> java.util.Locale.forLanguageTag("ru")

shared/src/commonMain/kotlin/com/drdisagree/teledrive/data/repository/SettingsRepositoryImpl.kt:171

  • AppLanguage defines a stable code specifically for persistence, but the preference is being stored using prefs.language.name. Persisting the code makes the stored value resilient to future enum renames while remaining compatible with fromCode.
        this[PreferenceKeys.THEME] = prefs.theme.name
        this[PreferenceKeys.LANGUAGE] = prefs.language.name
        this[PreferenceKeys.DYNAMIC_COLOR] = prefs.dynamicColor
  • Files reviewed: 11/11 changed files
  • Comments generated: 1
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The current locale switching logic can fail to track system locale changes and relies on a brittle cast when providing LocalLocaleList.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

ui/src/commonMain/composeResources/values-ru/strings.xml:197

  • Typo/grammar: "использует входе" is ungrammatical in Russian; it should be "использует вход".

This issue also appears on line 553 of the same file.

ui/src/jvmCommonMain/kotlin/com/drdisagree/teledrive/presentation/TeleDriveApp.kt:156

  • LocalLocaleList is force-cast to ProvidableCompositionLocal, which will throw a ClassCastException if the underlying type ever changes. A safe cast with an explicit error message makes failures clearer and avoids hard crashes from the provider call site.
        CompositionLocalProvider(
            (LocalLocaleList as ProvidableCompositionLocal<LocaleList>) provides targetLocaleList,
            LocalCompactLayout provides state.compactLayout

ui/src/commonMain/composeResources/values-ru/strings.xml:553

  • Grammar: "Удален диски" should be plural in Russian ("Удалены диски").
    <string name="channels_removed_missing">Удален диски (%1$d), чьи каналы больше не существуют в Telegram</string>
  • Files reviewed: 11/11 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread ui/src/jvmCommonMain/kotlin/com/drdisagree/teledrive/presentation/TeleDriveApp.kt Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@Ruslik31

Ruslik31 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

ugh.. yyyeess..

@Mahmud0808

Copy link
Copy Markdown
Owner

Thanks, translation coverage is complete and the plural forms are correct. Two things before merge:

  1. Compose Multiplatform string resources don't go through String.format, they only substitute positional tokens like %1$d, so a literal %% renders as "%%" on screen. Please change %% to a single % in home_storage_percent, home_storage_percent_min, and preview_archive_packed_summary_saved in values-ru (the English base uses single % for this reason).
  2. Resource resolution reads Locale.current, which is backed by java.util.Locale.getDefault(), so the DisposableEffect runs too late: the recomposition triggered by the LocalLocaleList provide happens before the effect sets the new default, leaving the UI on the old language until something else recomposes. Setting the default during composition instead fixes the ordering:
val systemDefault = remember { java.util.Locale.getDefault() }
remember(state.language) {
    java.util.Locale.setDefault(
        when (state.language) {
            AppLanguage.SYSTEM -> systemDefault
            AppLanguage.ENGLISH -> java.util.Locale.forLanguageTag("en")
            AppLanguage.RUSSIAN -> java.util.Locale.forLanguageTag("ru")
        }
    )
}

The DisposableEffect can then be removed. Also Android notification strings resolve from the system locale, so they follow the device language rather than the in-app choice.

@Ruslik31

Ruslik31 commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

done :) + add strings for hardcode transtales + fix two translates mistakes

@Mahmud0808
Mahmud0808 merged commit 4462849 into Mahmud0808:master Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants