Skip to content

Conversation

@rainxchzed
Copy link
Owner

@rainxchzed rainxchzed commented Dec 27, 2025

This commit introduces a TextUi sealed interface to abstract string resource handling, allowing for the use of both static String values and dynamic StringResource references.

This refactoring enables more flexible and centralized text management within the UI layer.

Key changes:

  • Created a TextUi sealed interface with two data classes: Static for raw strings and Dynamic for resource IDs.
  • Added a composable function asString() to resolve the TextUi instance into a displayable string.

Summary by CodeRabbit

  • New Features

    • App-wide localization added (ES, FR, JA, RU, ZH) plus consolidated default strings and localized theme names.
    • Install logs and status messages now use structured, localized labels for clearer, translated readouts.
  • Bug Fixes

    • App name corrected to "GitHub Store".
  • UX Improvements

    • Numerous UI strings, accessibility descriptions, progress indicators and error/snackbar messages replaced with localized resources for a more consistent, translated experience.

✏️ Tip: You can customize this high-level summary in your review settings.

This commit introduces a `TextUi` sealed interface to abstract string resource handling, allowing for the use of both static `String` values and dynamic `StringResource` references.

This refactoring enables more flexible and centralized text management within the UI layer.

Key changes:
- Created a `TextUi` sealed interface with two data classes: `Static` for raw strings and `Dynamic` for resource IDs.
- Added a composable function `asString()` to resolve the `TextUi` instance into a displayable string.
This commit introduces internationalization (i18n) to the application by replacing hardcoded strings with string resources. It also adds translations for Spanish, French, Russian, Japanese, and Chinese (Simplified).

Key changes:
- All user-facing text in the "Installed Apps" feature is now sourced from `strings.xml` resources.
- Added translation files for Spanish (`es`), French (`fr`), Russian (`ru`), Japanese (`ja`), and Chinese (`zh-rCN`).
- Replaced hardcoded strings in `AppsRoot.kt` (UI) and `AppsViewModel.kt` (logic) with Compose resource accessors (`stringResource(Res.string.some_string)`).
- The `TextUi.kt` sealed interface has been removed as it's no longer needed with the new resource-based approach.
- Removed the `errorMessage` property from `AppsState`, as error messages are now handled directly via events with localized strings.
This commit refactors the authentication feature to use string resources, enabling localization and improving code maintainability.

All hardcoded text in the authentication UI and related view models has been replaced with string resources. This includes text for states like "Waiting for authorization", "Signed in", error messages, and button labels.

Additionally, translations for these new strings have been added for Spanish, French, Japanese, Russian, and Chinese.
This commit fully internationalizes the search screen by replacing hardcoded strings with Compose resources.

Key changes:
- Added new string resources for the search screen, including labels for filters, sorting, results count, and error messages.
- Provided translations for Japanese, French, Spanish, Russian, and Chinese.
- Refactored `ProgrammingLanguage` and `SortBy` enums to use `StringResource` for their display names, making them localizable.
- Updated `SearchRoot.kt`, `LanguageFilterBottomSheet.kt`, and `SortByBottomSheet.kt` to use the new `stringResource` APIs.
- The `SearchViewModel` now uses resource strings for error messages like "No repositories found" and "Search failed".
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 27, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds comprehensive i18n resource bundles (EN, ES, FR, JA, RU, ZH-CN) and replaces hardcoded UI strings with resource lookups across the app; refactors several enums to provide resource-backed labels; introduces a typed LogResult sealed type and updates install logging/state; minor README selection tweak and one composable removal.

Changes

Cohort / File(s) Summary
Android & Common Resources
composeApp/src/androidMain/res/values/strings.xml, composeApp/src/commonMain/composeResources/values/strings.xml, composeApp/src/commonMain/composeResources/values-es/strings-es.xml, composeApp/src/commonMain/composeResources/values-fr/strings-fr.xml, composeApp/src/commonMain/composeResources/values-ja/values-ja.xml, composeApp/src/commonMain/composeResources/values-ru/strings-ru.xml, composeApp/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml
Added/updated comprehensive resource bundles and localized files; changed Android app_name to "GitHub Store".
Presentation — localization replacements
composeApp/src/commonMain/.../feature/*/presentation/*.kt (AppsRoot, AuthenticationRoot, SearchRoot, SettingsRoot, HomeRoot, Details components, etc.)
Replaced hardcoded texts and accessibility labels with stringResource() / getString(Res.string.*) and added generated resource imports across many screens and components.
Enums → resource labels
composeApp/src/commonMain/kotlin/.../core/presentation/model/AppTheme.kt, .../feature/search/domain/model/ProgrammingLanguage.kt, .../feature/search/domain/model/SortBy.kt, .../feature/home/presentation/model/HomeCategory.kt
Removed literal displayName fields; added composable label/displayText methods returning resource-backed strings; updated enum entries and imports.
ViewModels & State (message localization & small state change)
composeApp/src/commonMain/kotlin/.../feature/apps/presentation/AppsState.kt, .../AppsViewModel.kt, .../AuthenticationViewModel.kt, .../SearchViewModel.kt, .../HomeViewModel.kt
ViewModels now use getString(Res.string.*) for user messages/events; AppsState had errorMessage property removed. No public method signatures changed aside from state property removal.
Details: typed logs & API changes
composeApp/src/commonMain/kotlin/.../feature/details/presentation/model/LogResult.kt, .../DetailsViewModel.kt, .../DetailsState.kt, .../components/sections/Logs.kt, .../components/SmartInstallButton.kt, .../components/AppHeader.kt, ...
Introduced exported sealed LogResult + @Composable LogResult.asText(); changed internal logging API and state to use LogResult instead of raw strings; updated log rendering and error coloring to use typed variants.
Details: behavior tweak
composeApp/src/commonMain/kotlin/.../feature/details/data/repository/DetailsRepositoryImpl.kt
Broadened README selection logic: when primaryLang == "en", the presence of any non-null detectedLang now causes continuing the search.
UI component removal
composeApp/src/commonMain/kotlin/.../feature/details/presentation/components/Badge.kt
Deleted Badge composable and its file.
Misc small presentation components & utils
composeApp/src/commonMain/kotlin/.../core/presentation/*, .../feature/*/presentation/components/* (UpdatedAtFormatter, RepositoryCard, RateLimitDialog, About, Header, Owner, Stats, WhatsNew, ErrorState, LanguageFilterBottomSheet, SortByBottomSheet, LogoutDialog, Account/Appearance, etc.)
Many small components switched to resource strings; some helpers annotated @Composable (e.g., UpdatedAtFormatter). Mostly presentation/localization-only changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰
I hopped through literals, nibbling each line,
Planted tiny locales so text can shine,
Logs now sing typed tales, tidy and bright,
Themes ask for strings before they take flight,
Hooray — translations danced into the night!

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'refactor: Introduce TextUi sealed interface for string handling' refers to a real component (TextUi sealed interface) mentioned in objectives, but the actual changeset is dominated by broad localization/internationalization work across 30+ files with translations in 5 new languages, enum refactoring, and removal of unused code. The title focuses on one abstraction mechanism rather than the main i18n effort. Update the title to reflect the primary change: e.g., 'refactor: Add internationalization support with multiple languages and TextUi abstraction' or 'feat: Implement app localization for Spanish, French, Japanese, Russian, and Chinese'.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fbf3e37 and 4bed525.

📒 Files selected for processing (5)
  • composeApp/src/commonMain/composeResources/values-es/strings-es.xml
  • composeApp/src/commonMain/composeResources/values-fr/strings-fr.xml
  • composeApp/src/commonMain/composeResources/values-ja/values-ja.xml
  • composeApp/src/commonMain/composeResources/values-ru/strings-ru.xml
  • composeApp/src/commonMain/composeResources/values/strings.xml

Comment @coderabbitai help to get the list of available commands and usage tips.

This commit replaces hardcoded strings on the settings screen and its related components with string resources from `composeResources` to support internationalization.

Key changes:
- All static text in the `SettingsRoot`, `Appearance`, `About`, `Account`, and `LogoutDialog` composables now uses the `stringResource()` function.
- The `AppTheme` enum was refactored to provide theme display names via a composable `displayName()` function, which fetches the appropriate localized string.
- Added new string resources for all text related to the settings screen, including section headers, item titles, dialog text, and theme names.
- Provided translations for the new strings in Chinese (`zh-rCN`), Russian (`ru`), Spanish (`es`), French (`fr`), and Japanese (`ja`).
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/presentation/components/SortByBottomSheet.kt (2)

29-29: Replace hardcoded string with resource.

The "Close" text should use stringResource for localization. The resource key close is available in strings.xml.

🔎 Proposed fix

Add the required import at the top if not already present:

import githubstore.composeapp.generated.resources.close

Then update the text:

             TextButton(onClick = onDismissRequest) {
-                Text(text = "Close")
+                Text(text = stringResource(Res.string.close))
             }

34-34: Replace hardcoded string with resource.

The "Sort by" text should use stringResource for localization. The resource key sort_by is available in strings.xml.

🔎 Proposed fix

Add the required import at the top if not already present:

import githubstore.composeapp.generated.resources.sort_by

Then update the text:

             Text(
-                text = "Sort by",
+                text = stringResource(Res.string.sort_by),
                 style = MaterialTheme.typography.titleMedium
             )
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/auth/presentation/AuthenticationViewModel.kt (1)

127-139: Inconsistent localization: hardcoded clipboard label.

Line 136 still uses a hardcoded clipboard label "GitHub Code", while line 98 correctly uses getString(Res.string.enter_code_on_github) for the same purpose. This inconsistency should be addressed for complete localization coverage.

🔎 Suggested fix
     private fun copyCode(start: DeviceStart) {
         _state.update {
             it.copy(
                 loginState = AuthLoginState.DevicePrompt(start),
                 copied = true
             )
         }
 
         clipboardHelper.copy(
-            label = "GitHub Code",
+            label = getString(Res.string.enter_code_on_github),
             text = start.userCode
         )
     }
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/domain/model/SortBy.kt (1)

15-25: Remove only the unused getString import from this file.

The getString import on line 8 is not used in SortBy.kt. However, displayText() is actively used in SearchRoot.kt and should be kept. Both displayText() and label() serve different purposes and are not redundant.

🧹 Nitpick comments (4)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/core/presentation/model/AppTheme.kt (1)

7-7: Remove unused import.

The logout resource is imported but never used in this file. Only theme-related resources are referenced in the displayName() function.

🔎 Proposed fix
-import githubstore.composeapp.generated.resources.logout
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/settings/presentation/components/LogoutDialog.kt (1)

22-28: Unused import can be removed.

The navigate_back resource is imported on line 26 but doesn't appear to be used in this file.

🔎 Suggested cleanup
 import githubstore.composeapp.generated.resources.Res
 import githubstore.composeapp.generated.resources.close
 import githubstore.composeapp.generated.resources.logout
 import githubstore.composeapp.generated.resources.logout_confirmation
-import githubstore.composeapp.generated.resources.navigate_back
 import githubstore.composeapp.generated.resources.warning
 import org.jetbrains.compose.resources.stringResource
composeApp/src/commonMain/composeResources/values-es/strings-es.xml (1)

1-121: LGTM! Spanish localization resource file is well-structured.

The translations appear accurate, and placeholders are properly formatted for runtime substitution. The coverage is comprehensive across all UI elements.

One minor note: The filename strings-es.xml in values-es/ directory is slightly redundant since the directory suffix already indicates the locale. Consider using just strings.xml within locale-specific directories for consistency with Android resource conventions (e.g., values-es/strings.xml).

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/presentation/SearchRoot.kt (1)

271-303: Inconsistent string handling in disabled sorting feature.

While this code block is disabled (if (false)), line 282 mixes stringResource with the hardcoded displayText() method. When re-enabling this feature, update to use label() for consistency:

🔎 Suggested fix for when feature is enabled
                     Text(
-                        text = stringResource(Res.string.sort_by) + ": ${state.selectedSortBy.displayText()}",
+                        text = stringResource(Res.string.sort_by) + ": " + stringResource(state.selectedSortBy.label()),
                         style = MaterialTheme.typography.titleMedium,
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7489659 and de814fc.

📒 Files selected for processing (24)
  • composeApp/src/androidMain/res/values/strings.xml
  • composeApp/src/commonMain/composeResources/values-es/strings-es.xml
  • composeApp/src/commonMain/composeResources/values-fr/strings-fr.xml
  • composeApp/src/commonMain/composeResources/values-ja/values-ja.xml
  • composeApp/src/commonMain/composeResources/values-ru/strings-ru.xml
  • composeApp/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml
  • composeApp/src/commonMain/composeResources/values/strings.xml
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/core/presentation/model/AppTheme.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/apps/presentation/AppsRoot.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/apps/presentation/AppsState.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/apps/presentation/AppsViewModel.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/auth/presentation/AuthenticationRoot.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/auth/presentation/AuthenticationViewModel.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/domain/model/ProgrammingLanguage.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/domain/model/SortBy.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/presentation/SearchRoot.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/presentation/SearchViewModel.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/presentation/components/LanguageFilterBottomSheet.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/presentation/components/SortByBottomSheet.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/settings/presentation/SettingsRoot.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/settings/presentation/components/LogoutDialog.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/settings/presentation/components/sections/About.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/settings/presentation/components/sections/Account.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/settings/presentation/components/sections/Appearance.kt
💤 Files with no reviewable changes (1)
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/apps/presentation/AppsState.kt
🧰 Additional context used
🧬 Code graph analysis (2)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/auth/presentation/AuthenticationRoot.kt (1)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/core/presentation/components/GithubStoreButton.kt (1)
  • GithubStoreButton (17-52)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/apps/presentation/AppsRoot.kt (1)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/apps/presentation/AppsViewModel.kt (1)
  • onAction (107-146)
🪛 detekt (1.23.8)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/apps/presentation/AppsViewModel.kt

[warning] 338-338: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

🔇 Additional comments (26)
composeApp/src/androidMain/res/values/strings.xml (1)

2-2: LGTM! Branding correction applied.

The capitalization change from "Github Store" to "GitHub Store" correctly reflects GitHub's official branding.

composeApp/src/commonMain/composeResources/values-fr/strings-fr.xml (1)

1-121: LGTM! Comprehensive French localization added.

The French resource file is well-structured with proper placeholder formatting (%1$s, %2$d) and covers all UI features including apps, authentication, search, settings, and themes.

composeApp/src/commonMain/composeResources/values-ja/values-ja.xml (1)

1-121: LGTM! Comprehensive Japanese localization added.

The Japanese resource file follows the same well-structured pattern as other locale files with proper placeholder formatting.

composeApp/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml (1)

1-121: LGTM! Comprehensive Simplified Chinese localization added.

The Simplified Chinese resource file is properly structured and consistent with other localization files.

composeApp/src/commonMain/composeResources/values-ru/strings-ru.xml (1)

1-121: LGTM! Comprehensive Russian localization added.

The Russian resource file follows the established pattern with proper formatting and placeholder usage.

composeApp/src/commonMain/composeResources/values/strings.xml (1)

1-148: LGTM! Well-organized base English resource file.

The base resource file is comprehensive and well-structured with clear section comments, proper placeholder formatting, and correct HTML entity escaping (&). This serves as an excellent foundation for all locale-specific translations.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/core/presentation/model/AppTheme.kt (1)

38-48: LGTM! Excellent localization refactor.

The new displayName() composable function properly uses stringResource to provide localized theme names. This approach correctly separates display logic from data and enables runtime locale switching.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/presentation/components/SortByBottomSheet.kt (1)

53-53: Good localization implementation for sort options.

The sort option labels correctly use stringResource(option.label()) to enable localized text.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/settings/presentation/components/sections/Account.kt (1)

29-31: LGTM! Clean localization implementation.

The logout string has been correctly migrated to use stringResource, maintaining consistency with the broader localization effort across the codebase.

Also applies to: 53-53

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/presentation/components/LanguageFilterBottomSheet.kt (1)

22-24: LGTM! Proper resource-based localization.

Both the bottom sheet title and language labels have been correctly migrated to use stringResource. The language.label() pattern effectively delegates display name resolution to the resource system.

Also applies to: 48-48, 70-70

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/settings/presentation/components/LogoutDialog.kt (1)

48-48: LGTM! Comprehensive dialog localization.

All user-facing strings in the logout dialog have been properly migrated to use stringResource, ensuring the dialog can be displayed in multiple languages.

Also applies to: 54-54, 70-70, 84-84

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/auth/presentation/AuthenticationViewModel.kt (1)

98-100: LGTM! Proper error message localization.

Error messages and the primary clipboard label have been correctly migrated to use resource-based strings via getString.

Also applies to: 108-108, 113-113

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/settings/presentation/components/sections/About.kt (1)

31-35: LGTM! Complete section localization.

All user-facing strings in the About section have been correctly migrated to stringResource, maintaining consistency with the settings UI localization pattern.

Also applies to: 45-45, 63-63, 77-77

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/settings/presentation/SettingsRoot.kt (1)

29-36: LGTM! Correct context-aware resource usage.

The implementation properly uses getString in the coroutine context (line 59) and stringResource in composable contexts (lines 123, 130), following the correct pattern for Compose resource handling.

Also applies to: 59-59, 123-123, 130-130

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/presentation/SearchViewModel.kt (1)

6-8: LGTM! Proper ViewModel localization.

Error messages have been correctly migrated to use getString (appropriate for non-composable ViewModel context), with smart fallback to localized strings when specific error messages aren't available.

Also applies to: 21-21, 146-146, 163-163

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/settings/presentation/components/sections/Appearance.kt (1)

36-42: LGTM! Comprehensive appearance section localization.

All user-facing strings have been properly migrated to stringResource. The refactoring of theme.displayName (property) to theme.displayName() (composable function) is a good architectural choice that enables resource-based theme names. The formatted string usage in the content description (lines 128-131) correctly combines the localized template with the dynamic theme name.

Also applies to: 55-55, 75-75, 128-131, 139-139, 172-172, 180-180

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/domain/model/ProgrammingLanguage.kt (1)

21-54: LGTM! Clean refactor to resource-based labels.

The enum properly separates the API query values from UI display concerns. The exhaustive when expression ensures all enum values are mapped, and adding a new language will produce a compile-time error if the mapping is forgotten.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/apps/presentation/AppsViewModel.kt (2)

68-105: LGTM! Error handling updated for resource-based messaging.

The load failure path correctly sets isLoading = false and logs the error. The removal of errorMessage from state aligns with the event-driven messaging pattern used elsewhere.


148-166: LGTM! Resource-based error messages for app operations.

The openApp function correctly uses getString with formatted resources for error messages. The nullable handling with arrayOf(app.appName) is appropriate here since appName is non-null.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/auth/presentation/AuthenticationRoot.kt (2)

127-148: LGTM! Authentication states properly localized.

The pending, logged-in, and error states now use resource-based strings. The parameterized error message correctly passes authState.message to the format string.


259-326: LGTM! Logged-out state UI fully localized.

The StateLoggedOut composable properly uses stringResource for all user-facing text including the marketing copy and button labels.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/search/presentation/SearchRoot.kt (2)

202-253: LGTM! Language filter UI properly localized.

The language label, selected language display via label(), and filter chip interactions correctly use resource-based strings. Setting contentDescription = null for the decorative close icon is appropriate.


381-462: LGTM! Search topbar and input field localized.

Navigation back button, title, and search placeholder all properly use stringResource for localization.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/apps/presentation/AppsRoot.kt (3)

65-84: LGTM! Comprehensive resource imports for localization.

All required string resources are imported for the various UI states and actions in this screen.


419-509: LGTM! Update state displays properly localized.

All update states (Downloading, Installing, Checking, Success, Error) use resource-based strings with appropriate parameterization for progress percentages and error messages.


295-348: LGTM! Update progress card properly localized.

The UpdateAllProgressCard correctly uses parameterized resources for displaying progress counts and current app name.

Comment on lines 338 to +342
} catch (e: CancellationException) {
Logger.d { "Update all cancelled" }
} catch (e: Exception) {
Logger.e { "Update all failed: ${e.message}" }
_events.send(AppsEvent.ShowError("Update all failed: ${e.message}"))
_events.send(AppsEvent.ShowError(getString(Res.string.update_all_failed, arrayOf(e.message))))
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential null value in string format argument.

The static analysis hint about the swallowed CancellationException is a false positive—logging and returning early is the correct pattern for coroutine cancellation.

However, on line 342, e.message can be null, and passing it directly to arrayOf() may result in displaying "null" in the UI if the exception has no message. Consider providing a fallback:

🔎 Proposed fix
-                _events.send(AppsEvent.ShowError(getString(Res.string.update_all_failed, arrayOf(e.message))))
+                _events.send(AppsEvent.ShowError(getString(Res.string.update_all_failed, arrayOf(e.message ?: ""))))
🧰 Tools
🪛 detekt (1.23.8)

[warning] 338-338: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

🤖 Prompt for AI Agents
In
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/apps/presentation/AppsViewModel.kt
around lines 338 to 342, the exception message e.message can be null and passing
it directly to arrayOf(...) may display "null" in the UI; change the code to
provide a safe fallback (e.g., use e.message ?:
getString(Res.string.unknown_error) or e.message ?: "") when building the format
arguments and use that fallback both in the log and in the _events.send call so
the UI shows a sensible message instead of "null".

This commit refactors the Details screen and related components to use Compose multiplatform string resources instead of hardcoded strings. This enhances internationalization (i18n) by providing translations for Chinese (zh-rCN), Russian (ru), Spanish (es), French (fr), and Japanese (ja).

Additionally, the logic for installation and download logs has been improved by introducing a `LogResult` sealed class. This makes log messages type-safe and also ties them into the new resource string system for easier translation.

Key changes:
- Replaced hardcoded text in the Details screen UI (`Header`, `About`, `Stats`, `Owner`, `WhatsNew`, `SmartInstallButton`, `ErrorState`, etc.) with `stringResource()` calls.
- Added extensive new string resources for the details screen, including install states, download progress, error messages, and section titles.
- Created `values-zh-rCN`, `values-ru`, `values-es`, `values-fr`, and `values-ja` resource directories with corresponding translations.
- Introduced `LogResult` sealed class to represent different installation outcomes (e.g., `Downloaded`, `Installed`, `Error`), replacing simple `String` results.
- Updated `DetailsViewModel` to use the new `LogResult` types when appending logs.
- Created a `LogResult.asText()` composable function to provide localized string representations of log statuses.
- Removed the now-unused `Badge.kt` composable.
- Minor fix in `DetailsRepositoryImpl` to always search for an English README if the detected one isn't English, regardless of the primary language.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/AppHeader.kt (1)

43-43: Unused import.

The verifying resource is imported but not used in this file.

🔎 Proposed fix
 import githubstore.composeapp.generated.resources.no_description
 import githubstore.composeapp.generated.resources.update_available
-import githubstore.composeapp.generated.resources.verifying
 import org.jetbrains.compose.resources.stringResource
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/Owner.kt (1)

33-33: Unused import.

error_loading_details is imported but not used in this file.

🔎 Proposed fix
 import githubstore.composeapp.generated.resources.author
-import githubstore.composeapp.generated.resources.error_loading_details
 import githubstore.composeapp.generated.resources.ic_github
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/WhatsNew.kt (1)

24-24: Unused import.

error_loading_details is imported but not used in this file.

🔎 Proposed fix
 import githubstore.composeapp.generated.resources.Res
-import githubstore.composeapp.generated.resources.error_loading_details
 import githubstore.composeapp.generated.resources.no_release_notes
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/Logs.kt (1)

14-14: Unused import.

error_loading_details is imported but not used in this file.

🔎 Proposed fix
 import githubstore.composeapp.generated.resources.Res
-import githubstore.composeapp.generated.resources.error_loading_details
 import githubstore.composeapp.generated.resources.install_logs
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de814fc and 3c3bba6.

📒 Files selected for processing (21)
  • composeApp/src/commonMain/composeResources/values-es/strings-es.xml
  • composeApp/src/commonMain/composeResources/values-fr/strings-fr.xml
  • composeApp/src/commonMain/composeResources/values-ja/values-ja.xml
  • composeApp/src/commonMain/composeResources/values-ru/strings-ru.xml
  • composeApp/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml
  • composeApp/src/commonMain/composeResources/values/strings.xml
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/data/repository/DetailsRepositoryImpl.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/DetailsRoot.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/DetailsState.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/DetailsViewModel.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/AppHeader.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/Badge.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/SmartInstallButton.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/About.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/Header.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/Logs.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/Owner.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/Stats.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/WhatsNew.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/states/ErrorState.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/model/LogResult.kt
💤 Files with no reviewable changes (1)
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/Badge.kt
✅ Files skipped from review due to trivial changes (1)
  • composeApp/src/commonMain/composeResources/values-fr/strings-fr.xml
🚧 Files skipped from review as they are similar to previous changes (4)
  • composeApp/src/commonMain/composeResources/values-ru/strings-ru.xml
  • composeApp/src/commonMain/composeResources/values-es/strings-es.xml
  • composeApp/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml
  • composeApp/src/commonMain/composeResources/values-ja/values-ja.xml
🧰 Additional context used
🧬 Code graph analysis (1)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/Stats.kt (1)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/StatItem.kt (1)
  • StatItem (14-45)
🔇 Additional comments (20)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/Header.kt (2)

21-29: LGTM! Clean resource imports for localization.

The imports correctly bring in the generated resource object and string resolution function following Compose Multiplatform conventions. This properly supports the i18n refactor described in the PR objectives.


82-82: LGTM! Proper string resource integration.

The hardcoded strings have been correctly replaced with stringResource() calls referencing appropriate resource keys. The implementation is clean and consistent across both dropdown menu items.

Also applies to: 87-87, 112-112, 117-117

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/data/repository/DetailsRepositoryImpl.kt (1)

187-190: LGTM - Removed redundant condition.

The && detectedLang != "en" check was redundant since the prior condition at lines 182-185 already returns early when detectedLang == primaryLang. If execution reaches line 187 with primaryLang == "en", we know detectedLang cannot be "en". This simplification improves readability.

composeApp/src/commonMain/composeResources/values/strings.xml (1)

1-221: LGTM - Comprehensive localization resource file.

The string resources are well-organized with clear categories, properly typed format specifiers (%1$d for integers, %1$s for strings), and correctly escaped HTML entities (&). This establishes a solid foundation for internationalization.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/SmartInstallButton.kt (1)

35-50: LGTM - Consistent localization implementation.

All hardcoded strings have been properly replaced with stringResource lookups, including button text, download stage messages, and accessibility descriptions. Format specifiers are used correctly for dynamic values.

Also applies to: 93-105, 157-185, 273-273, 319-319, 344-344

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/DetailsRoot.kt (1)

36-43: LGTM - Accessibility strings localized.

Icon contentDescription attributes now use localized strings, improving accessibility for international users.

Also applies to: 132-132, 147-147

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/Stats.kt (1)

11-17: LGTM - Stat labels localized.

Repository statistics labels (Forks, Stars, Issues) now pull from string resources, enabling translation across all supported languages.

Also applies to: 35-35, 43-43, 51-51

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/DetailsState.kt (1)

10-18: LGTM - Type-safe result representation.

Changing result from String to LogResult improves type safety and enables compile-time verification of log result states. This pairs well with the resource-based localization strategy.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/About.kt (1)

21-23: LGTM - Section heading localized.

The "About this app" heading now uses a localized string resource, consistent with the broader i18n effort.

Also applies to: 51-51

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/states/ErrorState.kt (1)

12-16: LGTM - Error state localized.

Error messages and action buttons now display in the user's preferred language, improving the error handling experience for international users.

Also applies to: 31-31, 44-44

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/AppHeader.kt (1)

167-173: LGTM!

Good improvements: the null-safe let wrapper for tagName display and the resource-based strings for install status badges are correctly implemented.

Also applies to: 219-223

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/Owner.kt (1)

56-56: LGTM!

The localization changes for the "Author" title and "Profile" link text are correctly implemented.

Also applies to: 137-137

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/WhatsNew.kt (1)

44-44: LGTM!

The localization for the "What's New" section title and "No release notes" fallback is correctly implemented.

Also applies to: 93-93

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/Logs.kt (1)

40-52: LGTM!

Good improvements: using the typed LogResult with is LogResult.Error check is cleaner and type-safe compared to string prefix matching. The asText() composable extension is correctly invoked within the composition context.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/model/LogResult.kt (2)

18-35: LGTM!

Well-designed sealed class with clear separation of log result types. Using data object for singleton states and data class for those carrying payloads is idiomatic Kotlin.


38-71: LGTM!

The asText() extension correctly maps each variant to its localized string. The nullable message handling for Error (lines 62-65) is well implemented. Note that Info returns the raw message directly, which is appropriate for dynamic/programmatic messages that don't need localization.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/DetailsViewModel.kt (4)

873-878: LGTM!

The signature change from result: String to result: LogResult is clean. The function correctly stores the typed result in the state, allowing the UI layer to render it with proper localization via asText().


631-638: LGTM!

Good use of conditional LogResult assignment for distinguishing between fresh installs and updates. The ternary-style expression is clear and correctly applies UpdateStarted/DownloadStarted and Updated/Installed variants.

Also applies to: 693-700


526-531: LGTM!

All appendLog call sites have been consistently updated to use LogResult variants with named arguments for clarity. The variant choices are semantically appropriate for each scenario.

Also applies to: 552-557, 573-578, 590-595, 660-665, 710-715, 830-835, 849-854, 862-867


684-686: getString is correctly imported from Compose Resources.

The import on line 24 confirms getString comes from org.jetbrains.compose.resources. Using this suspend function within viewModelScope.launch is appropriate and correct.


Text(
text = "by ${author?.login}",
text = stringResource(Res.string.by_author, author?.login.toString()),
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid displaying literal "null" when author is missing.

Using author?.login.toString() will produce the string "null" when author or login is null. Consider using the Elvis operator to provide a meaningful fallback:

🔎 Proposed fix
-                    text = stringResource(Res.string.by_author, author?.login.toString()),
+                    text = stringResource(Res.string.by_author, author?.login ?: ""),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
text = stringResource(Res.string.by_author, author?.login.toString()),
text = stringResource(Res.string.by_author, author?.login ?: ""),
🤖 Prompt for AI Agents
In
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/AppHeader.kt
at line 148, the code uses author?.login.toString() which will render the
literal "null" when author or login is null; replace that expression with a safe
non-null fallback (e.g., use the Elvis operator like author?.login ?:
"<unknown>" or an empty string) so the stringResource call receives a meaningful
value and does not display "null".

Comment on lines 157 to 161
Icon(
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
contentDescription = "Navigate Back",
contentDescription = stringResource(Res.string.navigate_back),
modifier = Modifier.size(24.dp)
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Semantic mismatch: forward arrow with "navigate back" description.

The icon uses Icons.AutoMirrored.Filled.KeyboardArrowRight (a forward arrow) but the content description references navigate_back. This is misleading for accessibility users. Consider using a more appropriate resource key like navigate_forward or open_author.

🤖 Prompt for AI Agents
In
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/details/presentation/components/sections/Owner.kt
around lines 157 to 161, the icon shown is a forward arrow (KeyboardArrowRight)
but its contentDescription uses the string resource Res.string.navigate_back;
update the contentDescription to a semantically correct string (e.g.,
Res.string.navigate_forward or Res.string.open_author) that matches the visual
arrow, or change the icon to a back arrow if the action is “navigate back,”
ensuring the contentDescription and icon match.

This commit replaces hardcoded UI strings with internationalized string resources (`Res.string.*`). This is a significant refactoring to support localization and improve code maintainability.

Key changes:
- Added new string resources for the home screen, rate limit dialog, and date formatting.
- Created translations for Chinese (Simplified), Russian, Spanish, French, and Japanese.
- Updated composables (`HomeRoot`, `RateLimitDialog`, `RepositoryCard`, etc.) to use `stringResource()` instead of hardcoded text.
- Refactored `HomeCategory` enum to provide a composable `displayText()` function for retrieving localized category names.
- Updated `formatUpdatedAt` to be a `@Composable` function that uses string resources for relative time formatting (e.g., "updated yesterday").
- Removed the unused `TrendingPeriod` enum as it was no longer needed.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/core/presentation/utils/UpdatedAtFormmater.kt (1)

32-35: Hardcoded string breaks localization.

The else branch uses a hardcoded English string "updated on $date" while the rest of the function correctly uses localized resources. The updated_on_date resource key exists in strings.xml and should be used here.

🔎 Proposed fix
         else -> {
             val date = updated.toLocalDateTime(TimeZone.currentSystemDefault()).date
-            "updated on $date"
+            stringResource(Res.string.updated_on_date, date.toString())
         }

You'll also need to add the import:

import githubstore.composeapp.generated.resources.updated_on_date
🧹 Nitpick comments (3)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/app_state/components/RateLimitDialog.kt (1)

137-138: Consider adding mock data to the preview.

The preview function passes null for rateLimitInfo, which will cause the dialog to display "0" for limit and reset time values. Consider using mock RateLimitInfo data to make the preview more visually representative.

Example mock data for preview
rateLimitInfo = RateLimitInfo(
    limit = 60,
    remaining = 0,
    reset = System.currentTimeMillis() + 15 * 60 * 1000 // 15 minutes from now
),
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/core/presentation/components/RepositoryCard.kt (1)

36-36: Unused import.

updated_yesterday is imported but not used in this file. Consider removing it.

🔎 Proposed fix
 import githubstore.composeapp.generated.resources.installed
 import githubstore.composeapp.generated.resources.update_available
-import githubstore.composeapp.generated.resources.updated_yesterday
 import org.jetbrains.compose.resources.stringResource
composeApp/src/commonMain/composeResources/values/strings.xml (1)

232-234: Consider using plural resources for better localization.

The hour(s) and day(s) patterns don't translate well to languages with complex plural rules (e.g., Russian has three plural forms). Android/Compose resources support <plurals> for proper pluralization. This is acceptable for now but consider improving in a follow-up.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c3bba6 and fbf3e37.

📒 Files selected for processing (16)
  • composeApp/src/commonMain/composeResources/values-es/strings-es.xml
  • composeApp/src/commonMain/composeResources/values-fr/strings-fr.xml
  • composeApp/src/commonMain/composeResources/values-ja/values-ja.xml
  • composeApp/src/commonMain/composeResources/values-ru/strings-ru.xml
  • composeApp/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml
  • composeApp/src/commonMain/composeResources/values/strings.xml
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/app_state/components/RateLimitDialog.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/core/presentation/components/RepositoryCard.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/core/presentation/utils/UpdatedAtFormmater.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/data/repository/HomeRepositoryImpl.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/domain/model/TrendingPeriod.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/domain/repository/HomeRepository.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/presentation/HomeRoot.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/presentation/HomeViewModel.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/presentation/components/HomeFilterChips.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/presentation/model/HomeCategory.kt
💤 Files with no reviewable changes (3)
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/data/repository/HomeRepositoryImpl.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/domain/repository/HomeRepository.kt
  • composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/domain/model/TrendingPeriod.kt
🚧 Files skipped from review as they are similar to previous changes (4)
  • composeApp/src/commonMain/composeResources/values-fr/strings-fr.xml
  • composeApp/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml
  • composeApp/src/commonMain/composeResources/values-ja/values-ja.xml
  • composeApp/src/commonMain/composeResources/values-es/strings-es.xml
🔇 Additional comments (7)
composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/app_state/components/RateLimitDialog.kt (2)

20-29: Localization imports look good.

All necessary resource imports and the stringResource function are correctly added to support the localization refactor.


56-124: String resource replacements are correctly implemented.

The hardcoded strings have been properly replaced with stringResource() calls throughout the dialog. Format parameters for rate_limit_used_all, rate_limit_used_all_free, and rate_limit_resets_in_minutes are correctly passed with safe null fallbacks.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/presentation/components/HomeFilterChips.kt (1)

26-26: LGTM!

The change from property access to function call correctly aligns with the refactored HomeCategory.displayText() composable function for localized text.

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/core/presentation/components/RepositoryCard.kt (1)

163-167: Localization changes look good.

The button label and status badge texts are correctly migrated to use stringResource for localization support.

Also applies to: 195-199

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/presentation/HomeViewModel.kt (1)

147-149: LGTM!

The error messages are correctly migrated to use getString() (the suspend variant for non-composable contexts) within the coroutine scope. The fallback pattern on line 171 appropriately uses the localized string when the exception message is null.

Also applies to: 170-172

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/presentation/HomeRoot.kt (1)

51-62: LGTM!

Comprehensive localization migration for all UI text elements including the app bar title, loading states, retry button, end-of-list message, and accessibility content descriptions. The changes are consistent and well-structured.

Also applies to: 153-153, 209-209, 235-235, 288-288, 300-300, 338-338, 359-359, 388-388

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/feature/home/presentation/model/HomeCategory.kt (1)

10-22: LGTM!

Clean refactor from a value-bearing enum to a composable function approach for localized display text. The when expression is exhaustive, ensuring all enum values are handled. This pattern is consistent with the broader localization strategy in this PR.

This commit corrects a formatting issue in internationalization string resources across multiple languages (English, Russian, Spanish, French, and Japanese). The `percent` string resource was missing a second percentage sign, which is required to properly escape it in Android XML format strings.

Additionally, new strings for the app details screen have been added to the Russian localization file (`strings-ru.xml`):
- `no_release_notes`
- `open_in_browser`
- `show_install_options`
@rainxchzed rainxchzed merged commit 3e13227 into main Dec 28, 2025
1 of 2 checks passed
@rainxchzed rainxchzed changed the title refactor: Introduce TextUi sealed interface for string handling feat: Localization for english, french, chinese, japanese, spanish and russian Dec 28, 2025
@coderabbitai coderabbitai bot mentioned this pull request Dec 28, 2025
@rainxchzed rainxchzed deleted the app-localization-support branch January 1, 2026 16:58
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.

2 participants