Add "Support GitHub Store" feature and SponsorScreen#309
Conversation
- Created a new `SponsorScreen` component providing options for financial support (GitHub Sponsors, Buy Me a Coffee) and community engagement (voting, starring, reporting bugs). - Integrated the sponsor section into the profile presentation layer by adding `SponsorCard` to the options list. - Added `OnSponsorClick` action to `ProfileAction` and updated `ProfileViewModel` and `ProfileRoot` to handle navigation. - Configured app navigation to include `SponsorScreen` in `AppNavigation` and `GithubStoreGraph`. - Added new string resources for the sponsor page, including specific messaging for the Golden Kodee Awards. - Cleaned up imports in `SortOrderMapper`.
WalkthroughAdds a Sponsor feature: new SponsorScreen composable, navigation route and graph entry, Profile integration (action + callback), a SponsorCard in profile options, and extensive sponsor localization strings across locales. Changes
Sequence DiagramsequenceDiagram
participant User as User
participant Profile as ProfileScreen
participant Root as ProfileRoot
participant Nav as Navigation
participant Sponsor as SponsorScreen
participant Uri as UriHandler
User->>Profile: taps SponsorCard
Profile->>Root: dispatch OnSponsorClick
Root->>Nav: invoke onNavigateToSponsor()
Nav->>Sponsor: navigate to SponsorScreen
Sponsor->>User: render sponsor options
User->>Sponsor: selects external link
Sponsor->>Uri: open URL (LocalUriHandler)
Uri->>User: launches browser/app
User->>Sponsor: taps back
Sponsor->>Nav: onNavigateBack (navigateUp)
Nav->>Profile: return to ProfileScreen
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (4)
core/presentation/src/commonMain/composeResources/values/strings.xml (1)
471-471: Hardcoded statistics may become outdated.The download/star counts ("130,000+ downloads and 7,700+ GitHub stars") are hardcoded and will become stale as the app grows.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@core/presentation/src/commonMain/composeResources/values/strings.xml` at line 471, The string resource sponsor_hero_subtitle embeds hardcoded download/star counts that will become stale; change it to remove fixed numbers or replace them with placeholders (e.g., "%1$s" and "%2$s") and update the code that consumes sponsor_hero_subtitle (wherever it's referenced) to inject live values (fetched or passed-in) or a generic message like "popular with millions of downloads and thousands of stars" so the text remains accurate without hardcoding numeric statistics.composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/AppNavigation.kt (1)
248-254: Consider importingSponsorScreeninstead of using fully qualified name.Other screen composables in this file are imported (e.g.,
ProfileRoot,SearchRoot,HomeRoot), butSponsorScreenuses a fully qualified name. For consistency, consider adding the import.♻️ Proposed fix
Add to imports at top of file:
import zed.rainxch.profile.presentation.SponsorScreenThen simplify the composable:
composable<GithubStoreGraph.SponsorScreen> { - zed.rainxch.profile.presentation.SponsorScreen( + SponsorScreen( onNavigateBack = { navController.navigateUp() } ) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/AppNavigation.kt` around lines 248 - 254, The composable uses a fully qualified name for SponsorScreen which is inconsistent with other screens; add an import for zed.rainxch.profile.presentation.SponsorScreen and replace the fully qualified usage in the composable block (the composable<GithubStoreGraph.SponsorScreen> { ... }) with the simple SponsorScreen reference, keeping the existing onNavigateBack lambda unchanged.feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/SponsorScreen.kt (2)
56-58: Screen composable lacks ViewModel injection.Per coding guidelines,
*Screen.ktfiles should inject ViewModels usingkoinViewModel(). While this screen is currently stateless, adding a ViewModel would:
- Provide a place for analytics tracking (sponsor link clicks)
- Allow centralized URL management
- Support potential future state (e.g., loading indicators for URL opening)
If the screen is intentionally stateless and won't evolve, this can be deferred.
As per coding guidelines: "Inject ViewModels in Compose screens using koinViewModel() helper"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/SponsorScreen.kt` around lines 56 - 58, The SponsorScreen composable should inject a ViewModel via koinViewModel() so analytics and URL handling are centralized; update SponsorScreen to obtain a SponsorViewModel (e.g., val viewModel: SponsorViewModel = koinViewModel()) and use its methods for sponsor link clicks and navigation events instead of handling them directly in the composable, and if SponsorViewModel does not exist create it (with functions like trackSponsorClick(url: String) and openSponsorUrl(url: String)) so future state/logic (loading, error handling) can live in the VM.
438-445: Share action opens URL instead of invoking system share.The "Share" option opens the GitHub URL directly in browser, same as "Star repo". Users typically expect "Share" to open the system share sheet, allowing them to share via messaging apps, social media, etc.
Consider using platform-specific share functionality or a multiplatform share library.
💡 Conceptual approach
// For Compose Multiplatform, you might need an expect/actual pattern: expect fun shareText(text: String) // Then in the click handler: OtherWayItem( icon = Icons.Filled.IosShare, title = stringResource(Res.string.sponsor_share), description = stringResource(Res.string.sponsor_share_desc), onClick = { shareText("Check out GitHub Store: https://github.com/OpenHub-Store/GitHub-Store") } )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/SponsorScreen.kt` around lines 438 - 445, The Share item in SponsorScreen.kt currently calls onOpenUrl (OtherWayItem -> onOpenUrl("https://github.com/...")) which opens a browser; change this to invoke a platform share API instead: add an expect fun shareText(text: String) in common code and provide actual implementations per platform (Android Intent.ACTION_SEND, iOS share sheet, desktop sharing APIs), then replace the OtherWayItem onClick to call shareText with a composed message (use the existing string resources like Res.string.sponsor_share_desc or a new Res.string.sponsor_share_message). Keep OtherWayItem, SponsorScreen.kt and the onOpenUrl usage intact for other items but swap only the Share item's handler to shareText.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@core/presentation/src/commonMain/composeResources/values/strings.xml`:
- Around line 474-477: The strings sponsor_kodee_subtitle,
sponsor_kodee_register, sponsor_kodee_vote and sponsor_kodee_deadline contain
time-sensitive event text (KotlinConf 2025 / "Voting closes March 22"); update
by either making these values configurable (move sponsor_kodee_subtitle and
sponsor_kodee_deadline to remote/feature config keys and read them at runtime)
or add a clear TODO comment next to these resource entries to remove or update
them after the event and open a follow-up PR; ensure the resource names
(sponsor_kodee_subtitle, sponsor_kodee_deadline) are the ones wired to remote
config so the hardcoded date/year can be overridden without code changes.
In
`@feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/SponsorScreen.kt`:
- Around line 60-62: The onOpenUrl lambda in SponsorScreen currently swallows
errors by discarding runCatching's result; update it to handle failures by
calling uriHandler.openUri(url) inside runCatching and in the onFailure branch
log the exception and/or show a user-facing snackbar via
snackbarHostState.showSnackbar, and ensure the Scaffold includes snackbarHost =
{ SnackbarHost(snackbarHostState) } so the snackbar is visible; reference the
onOpenUrl lambda, uriHandler.openUri, snackbarHostState, SnackbarHost, and the
Scaffold setup when making the change.
- Line 33: SponsorScreen.kt imports and uses ExperimentalMaterial3ExpressiveApi
and expressive typography variants (e.g., titleMediumEmphasized,
headlineSmallEmphasized) which were removed in Material 3 1.4.0; either remove
the ExperimentalMaterial3ExpressiveApi import and replace all emphasized
typography usages in SponsorScreen (and any other references at line ~54) with
their stable equivalents (e.g., titleMedium, headlineSmall, or custom TextStyle
overrides) or pin the Material 3 dependency to the Expressive-compatible release
(the 1.5.0-alpha line mentioned) in your build config; update references in
SponsorScreen.kt to the chosen stable styles or keep the expressive API only if
you add the explicit dependency pin so the code compiles.
---
Nitpick comments:
In
`@composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/AppNavigation.kt`:
- Around line 248-254: The composable uses a fully qualified name for
SponsorScreen which is inconsistent with other screens; add an import for
zed.rainxch.profile.presentation.SponsorScreen and replace the fully qualified
usage in the composable block (the composable<GithubStoreGraph.SponsorScreen> {
... }) with the simple SponsorScreen reference, keeping the existing
onNavigateBack lambda unchanged.
In `@core/presentation/src/commonMain/composeResources/values/strings.xml`:
- Line 471: The string resource sponsor_hero_subtitle embeds hardcoded
download/star counts that will become stale; change it to remove fixed numbers
or replace them with placeholders (e.g., "%1$s" and "%2$s") and update the code
that consumes sponsor_hero_subtitle (wherever it's referenced) to inject live
values (fetched or passed-in) or a generic message like "popular with millions
of downloads and thousands of stars" so the text remains accurate without
hardcoding numeric statistics.
In
`@feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/SponsorScreen.kt`:
- Around line 56-58: The SponsorScreen composable should inject a ViewModel via
koinViewModel() so analytics and URL handling are centralized; update
SponsorScreen to obtain a SponsorViewModel (e.g., val viewModel:
SponsorViewModel = koinViewModel()) and use its methods for sponsor link clicks
and navigation events instead of handling them directly in the composable, and
if SponsorViewModel does not exist create it (with functions like
trackSponsorClick(url: String) and openSponsorUrl(url: String)) so future
state/logic (loading, error handling) can live in the VM.
- Around line 438-445: The Share item in SponsorScreen.kt currently calls
onOpenUrl (OtherWayItem -> onOpenUrl("https://github.com/...")) which opens a
browser; change this to invoke a platform share API instead: add an expect fun
shareText(text: String) in common code and provide actual implementations per
platform (Android Intent.ACTION_SEND, iOS share sheet, desktop sharing APIs),
then replace the OtherWayItem onClick to call shareText with a composed message
(use the existing string resources like Res.string.sponsor_share_desc or a new
Res.string.sponsor_share_message). Keep OtherWayItem, SponsorScreen.kt and the
onOpenUrl usage intact for other items but swap only the Share item's handler to
shareText.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0612488b-bfdb-452a-9b06-b1e1868c0bab
📒 Files selected for processing (11)
composeApp/release/baselineProfiles/0/composeApp-release.dmcomposeApp/release/baselineProfiles/1/composeApp-release.dmcomposeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/AppNavigation.ktcomposeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/GithubStoreGraph.ktcore/presentation/src/commonMain/composeResources/values/strings.xmlfeature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileAction.ktfeature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileRoot.ktfeature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileViewModel.ktfeature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/SponsorScreen.ktfeature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Options.ktfeature/search/presentation/src/commonMain/kotlin/zed/rainxch/search/presentation/utils/SortOrderMapper.kt
| <string name="sponsor_kodee_subtitle">GitHub Store is nominated for the Golden Kodee Awards at KotlinConf 2025. Your vote takes just 2 minutes and means the world.</string> | ||
| <string name="sponsor_kodee_register">1. Register</string> | ||
| <string name="sponsor_kodee_vote">2. Vote</string> | ||
| <string name="sponsor_kodee_deadline">Voting closes March 22</string> |
There was a problem hiding this comment.
Time-sensitive content will become stale.
The Golden Kodee Awards voting deadline ("March 22") and KotlinConf 2025 references will become outdated after the event. Consider either:
- Adding a TODO/reminder to remove this section post-event
- Making these strings configurable via remote config
- Planning a follow-up PR to clean up after March 22
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@core/presentation/src/commonMain/composeResources/values/strings.xml` around
lines 474 - 477, The strings sponsor_kodee_subtitle, sponsor_kodee_register,
sponsor_kodee_vote and sponsor_kodee_deadline contain time-sensitive event text
(KotlinConf 2025 / "Voting closes March 22"); update by either making these
values configurable (move sponsor_kodee_subtitle and sponsor_kodee_deadline to
remote/feature config keys and read them at runtime) or add a clear TODO comment
next to these resource entries to remove or update them after the event and open
a follow-up PR; ensure the resource names (sponsor_kodee_subtitle,
sponsor_kodee_deadline) are the ones wired to remote config so the hardcoded
date/year can be overridden without code changes.
| import androidx.compose.material3.ElevatedButton | ||
| import androidx.compose.material3.ElevatedCard | ||
| import androidx.compose.material3.ExperimentalMaterial3Api | ||
| import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Material3 ExperimentalMaterial3ExpressiveApi stability status 2026
💡 Result:
As of March 8, 2026, @ExperimentalMaterial3ExpressiveApi is not stable: APIs marked with it are treated as experimental and may change or be removed.
In fact, Jetpack Compose Material3 1.4.0-beta01 (July 30, 2025) explicitly removed all public APIs tagged with ExperimentalMaterial3ExpressiveApi (and ExperimentalMaterial3ComponentOverrideApi), instructing developers to use the 1.5.0-alpha line to keep using those Expressive features. So these Expressive APIs did not progress into the 1.4 beta/stable track. [1]
The annotation itself still exists (e.g., in Compose Multiplatform’s Material3 API surface), reinforcing that it remains an opt-in experimental marker, not a stability guarantee. [2]
Sources: [1], [2]
Replace ExperimentalMaterial3ExpressiveApi usage or pin Material 3 version.
The ExperimentalMaterial3ExpressiveApi used for emphasized typography variants (titleMediumEmphasized, headlineSmallEmphasized, etc.) was removed from Material 3 1.4.0-beta01 (July 30, 2025). Code relying on these APIs will break when updating to Material 3 1.4.0 or later. Either migrate to stable typography variants or explicitly pin Material 3 to the 1.5.0-alpha line to retain Expressive features.
Also applies to: 54-54
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/SponsorScreen.kt`
at line 33, SponsorScreen.kt imports and uses ExperimentalMaterial3ExpressiveApi
and expressive typography variants (e.g., titleMediumEmphasized,
headlineSmallEmphasized) which were removed in Material 3 1.4.0; either remove
the ExperimentalMaterial3ExpressiveApi import and replace all emphasized
typography usages in SponsorScreen (and any other references at line ~54) with
their stable equivalents (e.g., titleMedium, headlineSmall, or custom TextStyle
overrides) or pin the Material 3 dependency to the Expressive-compatible release
(the 1.5.0-alpha line mentioned) in your build config; update references in
SponsorScreen.kt to the chosen stable styles or keep the expressive API only if
you add the explicit dependency pin so the code compiles.
| val onOpenUrl: (String) -> Unit = { url -> | ||
| runCatching { uriHandler.openUri(url) } | ||
| } |
There was a problem hiding this comment.
Silent error handling may leave users without feedback.
The runCatching result is discarded. If openUri fails (e.g., no browser installed, malformed URL), users receive no indication.
Consider logging the failure or showing a snackbar/toast.
💡 Suggested improvement
- val onOpenUrl: (String) -> Unit = { url ->
- runCatching { uriHandler.openUri(url) }
- }
+ val snackbarHostState = remember { SnackbarHostState() }
+ val scope = rememberCoroutineScope()
+ val errorMessage = stringResource(Res.string.error_opening_url)
+
+ val onOpenUrl: (String) -> Unit = { url ->
+ runCatching { uriHandler.openUri(url) }
+ .onFailure {
+ scope.launch { snackbarHostState.showSnackbar(errorMessage) }
+ }
+ }Then add snackbarHost = { SnackbarHost(snackbarHostState) } to the Scaffold.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/SponsorScreen.kt`
around lines 60 - 62, The onOpenUrl lambda in SponsorScreen currently swallows
errors by discarding runCatching's result; update it to handle failures by
calling uriHandler.openUri(url) inside runCatching and in the onFailure branch
log the exception and/or show a user-facing snackbar via
snackbarHostState.showSnackbar, and ensure the Scaffold includes snackbarHost =
{ SnackbarHost(snackbarHostState) } so the snackbar is visible; reference the
onOpenUrl lambda, uriHandler.openUri, snackbarHostState, SnackbarHost, and the
Scaffold setup when making the change.
…calizations - Added comprehensive string resources for a new sponsorship and "Golden Kodee Awards" voting feature. - Included localized strings for various languages: Korean, Polish, Italian, Japanese, French, Hindi, Bengali, Spanish, Arabic, Chinese (Simplified), Russian, and Turkish. - Defined strings for hero titles, personal notes, GitHub Sponsors/Buy Me a Coffee links, and alternative support methods (starring repo, reporting bugs, sharing). - Added step-by-step instructions for the KotlinConf 2025 voting process. - Updated the base `strings.xml` with organized sections and consistent keys.
- Updated the `sponsor_kodee_subtitle` string to change the KotlinConf Golden Kodee Awards year from 2025 to 2026 across all supported languages (ko, pl, it, ja, fr, hi, bn, es, ar, en, zh-rCN, ru, tr).
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (7)
core/presentation/src/commonMain/composeResources/values-ru/strings-ru.xml (1)
430-467: Russian sponsor strings are well-structured and grammatically correct.The translations are accurate and follow proper Russian conventions. A few observations:
- Hardcoded time-sensitive values may require future updates:
- Line 434: Statistics "130 000 загрузок и 7 700 звёзд" will become outdated
- Line 439: "KotlinConf 2026" is year-specific
- Line 443: "Голосование до 22 марта" — deadline will pass
Consider extracting frequently changing values (like download counts) to a separate mechanism or documenting that these strings need periodic updates.
For the voting deadline, you could use a placeholder to make it more maintainable:
<!-- Alternative approach for deadline --> <string name="sponsor_kodee_deadline">Голосование до %1$s</string>This would allow the date to be passed programmatically and updated without string changes, though the current static approach is acceptable for a one-time campaign.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@core/presentation/src/commonMain/composeResources/values-ru/strings-ru.xml` around lines 430 - 467, Several strings contain hard-coded, time-sensitive values; update sponsor_hero_subtitle (counts), sponsor_kodee_subtitle (event year), and sponsor_kodee_deadline (deadline) to use placeholders or reference injected values so they can be updated programmatically (e.g., change sponsor_kodee_deadline to "Голосование до %1$s"); ensure callers provide the date/year/counts at runtime or document these keys for periodic updates and adjust any code that formats/getString for these names (sponsor_hero_subtitle, sponsor_kodee_subtitle, sponsor_kodee_deadline).core/presentation/src/commonMain/composeResources/values-ja/strings-ja.xml (1)
433-446: Parameterize the campaign metadata instead of freezing it in each locale.This block hardcodes volatile facts like the download/star counts,
2026, the March 22 deadline, and the nominee name. Every refresh now requires editing all locale files, which is easy to miss and will drift over time.Possible direction
- <string name="sponsor_hero_subtitle">GitHub Store は 13万以上のダウンロードと 7700 以上の GitHub スターを達成しました。完全無料、広告なし、追跡なし。</string> + <string name="sponsor_hero_subtitle">GitHub Store は %1$s 以上のダウンロードと %2$s 以上の GitHub スターを達成しました。完全無料、広告なし、追跡なし。</string> - <string name="sponsor_kodee_subtitle">KotlinConf 2026 の Golden Kodee Awards にノミネートされています。投票は2分で完了します。</string> + <string name="sponsor_kodee_subtitle">KotlinConf %1$s の Golden Kodee Awards にノミネートされています。投票は2分で完了します。</string> - <string name="sponsor_kodee_deadline">投票締切:3月22日</string> + <string name="sponsor_kodee_deadline">投票締切:%1$s</string> - <string name="sponsor_kodee_step3">3. Usmon Narzullayev を見つけて投票</string> + <string name="sponsor_kodee_step3">3. %1$s を見つけて投票</string>Then feed those values from one shared source instead of duplicating them across every
values-*file.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@core/presentation/src/commonMain/composeResources/values-ja/strings-ja.xml` around lines 433 - 446, The locale file hardcodes volatile campaign metadata (strings sponsor_hero_subtitle, sponsor_kodee_subtitle, sponsor_kodee_deadline, sponsor_kodee_step3), so change these to formatted/resource-backed strings and move the variable pieces to shared resource keys (e.g., download_count, star_count, campaign_year, campaign_deadline, nominee_name). Replace the hardcoded lines with format strings that reference those shared keys (use Android string formatting/placeholders like %1$s) and ensure the shared keys are populated from a single source (build-time config or central values/strings.xml) so updates occur in one place rather than editing every values-* file. Ensure translations keep the format placeholders intact.core/presentation/src/commonMain/composeResources/values-ko/strings-ko.xml (1)
471-480: Consider parameterizing the event year and deadline.These strings hardcode
2026and3월 22일, so the next rollover will require another locale-wide sweep. Passing the year/deadline as formatted args would keep the copy reusable and lower the chance of one locale drifting behind.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@core/presentation/src/commonMain/composeResources/values-ko/strings-ko.xml` around lines 471 - 480, Replace hardcoded year and deadline text with format arguments in the Korean resource strings: change sponsor_kodee_subtitle to include a %1$s placeholder for the event year, sponsor_kodee_deadline to include a %1$s placeholder for the deadline date, and any other related strings (e.g., sponsor_kodee_title if needed) so the year/deadline are injected at runtime; update callers to pass the formatted year (e.g., "2026") and deadline (e.g., "3월 22일") when fetching getString for sponsor_kodee_subtitle and sponsor_kodee_deadline so the locale strings remain reusable across years.core/presentation/src/commonMain/composeResources/values-hi/strings-hi.xml (1)
475-480: Parameterize the campaign year and deadline.These strings already need periodic sweeps (
2025→2026), so hard-coding the year and cutoff date in every locale will keep creating translation churn and stale copy risk. It would be safer to keep the sentence translated here and pass the year/deadline in as placeholders.♻️ Suggested direction
- <string name="sponsor_kodee_subtitle">GitHub Store KotlinConf 2026 Golden Kodee Awards के लिए नामांकित है।</string> + <string name="sponsor_kodee_subtitle">GitHub Store KotlinConf %1$s Golden Kodee Awards के लिए नामांकित है।</string> - <string name="sponsor_kodee_deadline">वोटिंग 22 मार्च को बंद होगी</string> + <string name="sponsor_kodee_deadline">वोटिंग %1$s को बंद होगी</string>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@core/presentation/src/commonMain/composeResources/values-hi/strings-hi.xml` around lines 475 - 480, The hard-coded year and deadline in the Hindi strings cause churn; change sponsor_kodee_subtitle and sponsor_kodee_deadline to use placeholders (e.g., "%1$s" for the campaign year and "%2$s" for the deadline) instead of literal "2026" and "22 मार्च", and update the calling site(s) that reference these resource IDs to pass the year and deadline strings as format arguments (look for usages of sponsor_kodee_subtitle and sponsor_kodee_deadline in the compose/resources code and pass the two arguments in the correct order). Ensure placeholder positions match usage and keep sponsor_kodee_register/sponsor_kodee_vote unchanged.core/presentation/src/commonMain/composeResources/values-fr/strings-fr.xml (1)
434-442: Make the volatile stats and event dates data-driven.These translations hardcode download/star counts, the KotlinConf year, and the voting deadline. That copy will stale quickly and force another full locale sweep for each update. Prefer placeholders or runtime-provided values for the changing pieces.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@core/presentation/src/commonMain/composeResources/values-fr/strings-fr.xml` around lines 434 - 442, Several strings hardcode volatile data; update sponsor_hero_subtitle, sponsor_kodee_subtitle and sponsor_kodee_deadline to use format placeholders (e.g., %1$d/%1$s) instead of fixed counts/year/date and supply those values at runtime (via getString(..., args) or platform-specific resource formatting) so stars/downloads, KotlinConf year, and vote deadline come from the app state or remote config; leave static labels (sponsor_personal_note, sponsor_kodee_register, sponsor_kodee_vote, sponsor_kodee_title) unchanged.core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml (2)
465-465: Let the UI handle wrapping for the hero title.Embedding
\nin a localized string locks Turkish to one layout and can wrap awkwardly with different widths or font scales. Keep this as a single line in resources and let the composable break it naturally.Suggested change
- <string name="sponsor_hero_title">Sevgiyle yapıldı,\nkahveyle sürdürüldü</string> + <string name="sponsor_hero_title">Sevgiyle yapıldı, kahveyle sürdürüldü</string>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml` at line 465, The localized string sponsor_hero_title contains an explicit '\n' which forces a hard line break; remove the newline escape and make the value a single line (e.g., "Sevgiyle yapıldı, kahveyle sürdürüldü") so the composable can handle wrapping and line breaks responsively; update the resource string value for sponsor_hero_title accordingly.
467-467: Avoid hardcoding fast-changing metrics and dates in localized copy.
130.000+,7.700+, and22 Martwill all drift and force another locale-wide edit. Prefer placeholders or timeless wording so only one source of truth needs updating.Suggested change
- <string name="sponsor_hero_subtitle">GitHub Store 130.000+ indirme ve 7.700+ GitHub yıldızına ulaştı — %100 ücretsiz, reklamsız ve izleme yok.</string> + <string name="sponsor_hero_subtitle">GitHub Store %1$s+ indirme ve %2$s+ GitHub yıldızına ulaştı — %100 ücretsiz, reklamsız ve izleme yok.</string> … - <string name="sponsor_kodee_deadline">Oylama 22 Mart'ta kapanıyor</string> + <string name="sponsor_kodee_deadline">Oylama %1$s tarihinde kapanıyor</string>Also applies to: 477-477
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml` at line 467, The string resource sponsor_hero_subtitle (and the similar entry around line 477) hardcodes fast-changing metrics and a date; change these to use placeholders or timeless phrasing instead (e.g., "%1$s indirme, %2$s GitHub yıldızı" or "milyonlarca indirme ve onbinlerce yıldız") so the localized XML only contains the format and callers supply the live numbers/dates from a single source of truth; update any code that reads sponsor_hero_subtitle to pass the dynamic values (or switch the text to non-numeric wording) and add corresponding placeholder variants for pluralization if needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@core/presentation/src/commonMain/composeResources/values-es/strings-es.xml`:
- Around line 434-435: Update the two Spanish strings: in sponsor_hero_subtitle
replace English-style digit separators with Spanish ones (e.g., "130.000" and
"7.700") and keep the percent styling consistent with locale (e.g., "100%" or
"100 %" per project convention) in the string name sponsor_hero_subtitle; in
sponsor_personal_note fix the trailing incomplete clause by making it a complete
verb phrase (for example, "...ayuda a mantener la app sin errores, pagar la
infraestructura y lanzar las funciones que solicitan" or "...y a lanzar las
funciones que nos piden") so the sentence reads naturally. Ensure you edit
sponsor_hero_subtitle and sponsor_personal_note accordingly and preserve
punctuation/HTML entity encoding used in the XML file.
In `@core/presentation/src/commonMain/composeResources/values-fr/strings-fr.xml`:
- Around line 462-463: The two French strings are inconsistent: string
"sponsor_share" says "amis" while "sponsor_share_desc" says "développeurs"; pick
one audience and make both strings match. Edit either "sponsor_share" to target
developers (e.g., use "Partager avec des développeurs") or change
"sponsor_share_desc" to target friends (e.g., "Parlez-en à vos amis"), and
ensure both string entries ("sponsor_share" and "sponsor_share_desc") use the
same audience phrasing and tone.
In `@core/presentation/src/commonMain/composeResources/values-hi/strings-hi.xml`:
- Line 470: The Hindi string resource sponsor_hero_subtitle currently hard-codes
Western-formatted stats ("130,000+"), which is both non‑localized and will go
stale; replace the literal numbers with placeholders (e.g., %1$s/%2$s or named
placeholders) in sponsor_hero_subtitle and update the caller that sets this
string to inject values from a single canonical source, formatting counts with
the runtime locale (use NumberFormat.getInstance(locale) or equivalent) and
passing localized strings into the resource so the Hindi variant reads naturally
(e.g., "1,30,000+" or localized wording) rather than embedding fixed
Western-formatted numbers.
In `@core/presentation/src/commonMain/composeResources/values-ja/strings-ja.xml`:
- Line 435: Change the Japanese string value for the resource named
"sponsor_personal_note" to use a natural expression for “while still in high
school” (e.g., replace 「高校を卒業しながら」 with 「高校に通いながら」 or 「高校生活を送りながら」) so the
sentence reads naturally; update the text between the quotes for
sponsor_personal_note accordingly while preserving the rest of the message.
In `@core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml`:
- Line 472: The string resource sponsor_kodee_subtitle uses an unnatural
phrasing; update its value so the award name takes the Turkish dative suffix
rather than "için aday gösterildi" (e.g., use a form like "KotlinConf 2026
Golden Kodee Ödülleri'ne aday gösterildi."); locate the string named
sponsor_kodee_subtitle and replace the existing text with the corrected Turkish
phrasing that applies the dative suffix to the award name.
In `@core/presentation/src/commonMain/composeResources/values/strings.xml`:
- Line 471: The string resource sponsor_hero_subtitle currently hardcodes
"130,000+ downloads and 7,700+ GitHub stars" which will become stale; update the
resource named sponsor_hero_subtitle to use a non-numeric, evergreen phrase
(e.g., "thousands of downloads and GitHub stars") or change it to a placeholder
(e.g., "%1$s downloads, %2$s stars") and implement a runtime solution that
fetches live counts from the GitHub API (or a release-time script that updates
the resource) and injects formatted values into the placeholder; ensure the code
that displays sponsor_hero_subtitle uses the new placeholder pattern or the new
generic text consistently.
---
Nitpick comments:
In `@core/presentation/src/commonMain/composeResources/values-fr/strings-fr.xml`:
- Around line 434-442: Several strings hardcode volatile data; update
sponsor_hero_subtitle, sponsor_kodee_subtitle and sponsor_kodee_deadline to use
format placeholders (e.g., %1$d/%1$s) instead of fixed counts/year/date and
supply those values at runtime (via getString(..., args) or platform-specific
resource formatting) so stars/downloads, KotlinConf year, and vote deadline come
from the app state or remote config; leave static labels (sponsor_personal_note,
sponsor_kodee_register, sponsor_kodee_vote, sponsor_kodee_title) unchanged.
In `@core/presentation/src/commonMain/composeResources/values-hi/strings-hi.xml`:
- Around line 475-480: The hard-coded year and deadline in the Hindi strings
cause churn; change sponsor_kodee_subtitle and sponsor_kodee_deadline to use
placeholders (e.g., "%1$s" for the campaign year and "%2$s" for the deadline)
instead of literal "2026" and "22 मार्च", and update the calling site(s) that
reference these resource IDs to pass the year and deadline strings as format
arguments (look for usages of sponsor_kodee_subtitle and sponsor_kodee_deadline
in the compose/resources code and pass the two arguments in the correct order).
Ensure placeholder positions match usage and keep
sponsor_kodee_register/sponsor_kodee_vote unchanged.
In `@core/presentation/src/commonMain/composeResources/values-ja/strings-ja.xml`:
- Around line 433-446: The locale file hardcodes volatile campaign metadata
(strings sponsor_hero_subtitle, sponsor_kodee_subtitle, sponsor_kodee_deadline,
sponsor_kodee_step3), so change these to formatted/resource-backed strings and
move the variable pieces to shared resource keys (e.g., download_count,
star_count, campaign_year, campaign_deadline, nominee_name). Replace the
hardcoded lines with format strings that reference those shared keys (use
Android string formatting/placeholders like %1$s) and ensure the shared keys are
populated from a single source (build-time config or central values/strings.xml)
so updates occur in one place rather than editing every values-* file. Ensure
translations keep the format placeholders intact.
In `@core/presentation/src/commonMain/composeResources/values-ko/strings-ko.xml`:
- Around line 471-480: Replace hardcoded year and deadline text with format
arguments in the Korean resource strings: change sponsor_kodee_subtitle to
include a %1$s placeholder for the event year, sponsor_kodee_deadline to include
a %1$s placeholder for the deadline date, and any other related strings (e.g.,
sponsor_kodee_title if needed) so the year/deadline are injected at runtime;
update callers to pass the formatted year (e.g., "2026") and deadline (e.g., "3월
22일") when fetching getString for sponsor_kodee_subtitle and
sponsor_kodee_deadline so the locale strings remain reusable across years.
In `@core/presentation/src/commonMain/composeResources/values-ru/strings-ru.xml`:
- Around line 430-467: Several strings contain hard-coded, time-sensitive
values; update sponsor_hero_subtitle (counts), sponsor_kodee_subtitle (event
year), and sponsor_kodee_deadline (deadline) to use placeholders or reference
injected values so they can be updated programmatically (e.g., change
sponsor_kodee_deadline to "Голосование до %1$s"); ensure callers provide the
date/year/counts at runtime or document these keys for periodic updates and
adjust any code that formats/getString for these names (sponsor_hero_subtitle,
sponsor_kodee_subtitle, sponsor_kodee_deadline).
In `@core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml`:
- Line 465: The localized string sponsor_hero_title contains an explicit '\n'
which forces a hard line break; remove the newline escape and make the value a
single line (e.g., "Sevgiyle yapıldı, kahveyle sürdürüldü") so the composable
can handle wrapping and line breaks responsively; update the resource string
value for sponsor_hero_title accordingly.
- Line 467: The string resource sponsor_hero_subtitle (and the similar entry
around line 477) hardcodes fast-changing metrics and a date; change these to use
placeholders or timeless phrasing instead (e.g., "%1$s indirme, %2$s GitHub
yıldızı" or "milyonlarca indirme ve onbinlerce yıldız") so the localized XML
only contains the format and callers supply the live numbers/dates from a single
source of truth; update any code that reads sponsor_hero_subtitle to pass the
dynamic values (or switch the text to non-numeric wording) and add corresponding
placeholder variants for pluralization if needed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f60ecf7c-d906-4af8-be39-b08b0d3fa7b3
📒 Files selected for processing (13)
core/presentation/src/commonMain/composeResources/values-ar/strings-ar.xmlcore/presentation/src/commonMain/composeResources/values-bn/strings-bn.xmlcore/presentation/src/commonMain/composeResources/values-es/strings-es.xmlcore/presentation/src/commonMain/composeResources/values-fr/strings-fr.xmlcore/presentation/src/commonMain/composeResources/values-hi/strings-hi.xmlcore/presentation/src/commonMain/composeResources/values-it/strings-it.xmlcore/presentation/src/commonMain/composeResources/values-ja/strings-ja.xmlcore/presentation/src/commonMain/composeResources/values-ko/strings-ko.xmlcore/presentation/src/commonMain/composeResources/values-pl/strings-pl.xmlcore/presentation/src/commonMain/composeResources/values-ru/strings-ru.xmlcore/presentation/src/commonMain/composeResources/values-tr/strings-tr.xmlcore/presentation/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xmlcore/presentation/src/commonMain/composeResources/values/strings.xml
✅ Files skipped from review due to trivial changes (2)
- core/presentation/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml
- core/presentation/src/commonMain/composeResources/values-ar/strings-ar.xml
| <string name="sponsor_hero_subtitle">GitHub Store ha alcanzado más de 130,000 descargas y 7,700 estrellas en GitHub — 100% gratis, sin anuncios ni rastreo.</string> | ||
| <string name="sponsor_personal_note">Construí y mantengo esto completamente por mi cuenta mientras termino la secundaria. Tu apoyo — incluso una pequeña cantidad — ayuda a mantener la app sin errores, pagar la infraestructura y lanzar las funciones que solicitan.</string> |
There was a problem hiding this comment.
Polish the Spanish sponsor copy before shipping.
Line 434 still uses English numeric formatting (130,000, 7,700, 100%), and Line 435 ends with an incomplete clause (las funciones que solicitan). Both will read unpolished in the ES locale.
💬 Suggested copy update
- <string name="sponsor_hero_subtitle">GitHub Store ha alcanzado más de 130,000 descargas y 7,700 estrellas en GitHub — 100% gratis, sin anuncios ni rastreo.</string>
- <string name="sponsor_personal_note">Construí y mantengo esto completamente por mi cuenta mientras termino la secundaria. Tu apoyo — incluso una pequeña cantidad — ayuda a mantener la app sin errores, pagar la infraestructura y lanzar las funciones que solicitan.</string>
+ <string name="sponsor_hero_subtitle">GitHub Store ha alcanzado más de 130.000 descargas y 7.700 estrellas en GitHub: 100 % gratis, sin anuncios ni rastreo.</string>
+ <string name="sponsor_personal_note">Construí y mantengo esto completamente por mi cuenta mientras termino la secundaria. Tu apoyo — incluso una pequeña cantidad — ayuda a mantener la app sin errores, pagar la infraestructura y lanzar las funciones más solicitadas.</string>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@core/presentation/src/commonMain/composeResources/values-es/strings-es.xml`
around lines 434 - 435, Update the two Spanish strings: in sponsor_hero_subtitle
replace English-style digit separators with Spanish ones (e.g., "130.000" and
"7.700") and keep the percent styling consistent with locale (e.g., "100%" or
"100 %" per project convention) in the string name sponsor_hero_subtitle; in
sponsor_personal_note fix the trailing incomplete clause by making it a complete
verb phrase (for example, "...ayuda a mantener la app sin errores, pagar la
infraestructura y lanzar las funciones que solicitan" or "...y a lanzar las
funciones que nos piden") so the sentence reads naturally. Ensure you edit
sponsor_hero_subtitle and sponsor_personal_note accordingly and preserve
punctuation/HTML entity encoding used in the XML file.
| <string name="sponsor_share">Partager avec des amis</string> | ||
| <string name="sponsor_share_desc">Parlez-en aux développeurs</string> |
There was a problem hiding this comment.
Align the share CTA and its description.
sponsor_share targets “friends”, while sponsor_share_desc narrows the audience to “developers”. That reads like a translation mismatch in the UI. Keep both strings aimed at the same audience.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@core/presentation/src/commonMain/composeResources/values-fr/strings-fr.xml`
around lines 462 - 463, The two French strings are inconsistent: string
"sponsor_share" says "amis" while "sponsor_share_desc" says "développeurs"; pick
one audience and make both strings match. Edit either "sponsor_share" to target
developers (e.g., use "Partager avec des développeurs") or change
"sponsor_share_desc" to target friends (e.g., "Parlez-en à vos amis"), and
ensure both string entries ("sponsor_share" and "sponsor_share_desc") use the
same audience phrasing and tone.
| <string name="sponsor_button">प्रोजेक्ट को समर्थन दें</string> | ||
| <string name="sponsor_hero_title">प्यार से बनाया,\nकॉफी से चलाया</string> | ||
|
|
||
| <string name="sponsor_hero_subtitle">GitHub Store ने 130,000+ डाउनलोड और 7,700+ GitHub स्टार प्राप्त किए हैं — 100% मुफ्त, बिना विज्ञापन और बिना ट्रैकिंग।</string> |
There was a problem hiding this comment.
Avoid hard-coded, Western-formatted stats in this Hindi string.
Line 470 uses 130,000+, which looks off in values-hi (1,30,000+ or a localized phrasing would read more naturally), and baking live download/star counts into every locale will go stale quickly. Prefer injecting locale-formatted values from a single source instead of freezing them in the translation.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@core/presentation/src/commonMain/composeResources/values-hi/strings-hi.xml`
at line 470, The Hindi string resource sponsor_hero_subtitle currently
hard-codes Western-formatted stats ("130,000+"), which is both non‑localized and
will go stale; replace the literal numbers with placeholders (e.g., %1$s/%2$s or
named placeholders) in sponsor_hero_subtitle and update the caller that sets
this string to inject values from a single canonical source, formatting counts
with the runtime locale (use NumberFormat.getInstance(locale) or equivalent) and
passing localized strings into the resource so the Hindi variant reads naturally
(e.g., "1,30,000+" or localized wording) rather than embedding fixed
Western-formatted numbers.
| <string name="sponsor_hero_title">愛を込めて作り、\nコーヒーで維持</string> | ||
| <string name="sponsor_hero_subtitle">GitHub Store は 13万以上のダウンロードと 7700 以上の GitHub スターを達成しました。完全無料、広告なし、追跡なし。</string> | ||
|
|
||
| <string name="sponsor_personal_note">私は高校を卒業しながら、このプロジェクトを一人で開発・維持しています。小さな支援でも、バグ修正やインフラ費用、機能開発に役立ちます。</string> |
There was a problem hiding this comment.
Line 435 reads awkwardly in Japanese.
高校を卒業しながら sounds unnatural for an ongoing situation. If the intent is “while still in high school,” 高校に通いながら or 高校生活を送りながら reads much more naturally.
Suggested wording
- <string name="sponsor_personal_note">私は高校を卒業しながら、このプロジェクトを一人で開発・維持しています。小さな支援でも、バグ修正やインフラ費用、機能開発に役立ちます。</string>
+ <string name="sponsor_personal_note">私は高校に通いながら、このプロジェクトを一人で開発・維持しています。小さな支援でも、バグ修正やインフラ費用、機能開発に役立ちます。</string>📝 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.
| <string name="sponsor_personal_note">私は高校を卒業しながら、このプロジェクトを一人で開発・維持しています。小さな支援でも、バグ修正やインフラ費用、機能開発に役立ちます。</string> | |
| <string name="sponsor_personal_note">私は高校に通いながら、このプロジェクトを一人で開発・維持しています。小さな支援でも、バグ修正やインフラ費用、機能開発に役立ちます。</string> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@core/presentation/src/commonMain/composeResources/values-ja/strings-ja.xml`
at line 435, Change the Japanese string value for the resource named
"sponsor_personal_note" to use a natural expression for “while still in high
school” (e.g., replace 「高校を卒業しながら」 with 「高校に通いながら」 or 「高校生活を送りながら」) so the
sentence reads naturally; update the text between the quotes for
sponsor_personal_note accordingly while preserving the rest of the message.
| <string name="sponsor_personal_note">Bu projeyi liseyi bitirirken tamamen tek başıma geliştiriyorum ve sürdürüyorum.</string> | ||
|
|
||
| <string name="sponsor_kodee_title">GitHub Store için oy ver!</string> | ||
| <string name="sponsor_kodee_subtitle">GitHub Store KotlinConf 2026 Golden Kodee Awards için aday gösterildi.</string> |
There was a problem hiding this comment.
Fix the Turkish phrasing in the award subtitle.
KotlinConf 2026 Golden Kodee Awards için aday gösterildi reads unnatural here. The award name should take the dative suffix.
Suggested change
- <string name="sponsor_kodee_subtitle">GitHub Store KotlinConf 2026 Golden Kodee Awards için aday gösterildi.</string>
+ <string name="sponsor_kodee_subtitle">GitHub Store, KotlinConf 2026 Golden Kodee Awards'a aday gösterildi.</string>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml`
at line 472, The string resource sponsor_kodee_subtitle uses an unnatural
phrasing; update its value so the award name takes the Turkish dative suffix
rather than "için aday gösterildi" (e.g., use a form like "KotlinConf 2026
Golden Kodee Ödülleri'ne aday gösterildi."); locate the string named
sponsor_kodee_subtitle and replace the existing text with the corrected Turkish
phrasing that applies the dative suffix to the award name.
| <string name="sponsor_title">Support GitHub Store</string> | ||
| <string name="sponsor_button">Support the Project</string> | ||
| <string name="sponsor_hero_title">Built with love,\nmaintained with coffee</string> | ||
| <string name="sponsor_hero_subtitle">GitHub Store has reached 130,000+ downloads and 7,700+ GitHub stars — 100% free, no ads, no tracking.</string> |
There was a problem hiding this comment.
Hardcoded statistics will become outdated.
The values "130,000+ downloads and 7,700+ GitHub stars" are hardcoded and will become stale. Consider either:
- Updating these periodically via release process
- Using a more general phrasing like "thousands of downloads"
- Fetching live stats from the GitHub API (if feasible)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@core/presentation/src/commonMain/composeResources/values/strings.xml` at line
471, The string resource sponsor_hero_subtitle currently hardcodes "130,000+
downloads and 7,700+ GitHub stars" which will become stale; update the resource
named sponsor_hero_subtitle to use a non-numeric, evergreen phrase (e.g.,
"thousands of downloads and GitHub stars") or change it to a placeholder (e.g.,
"%1$s downloads, %2$s stars") and implement a runtime solution that fetches live
counts from the GitHub API (or a release-time script that updates the resource)
and injects formatted values into the placeholder; ensure the code that displays
sponsor_hero_subtitle uses the new placeholder pattern or the new generic text
consistently.
SponsorScreencomponent providing options for financial support (GitHub Sponsors, Buy Me a Coffee) and community engagement (voting, starring, reporting bugs).SponsorCardto the options list.OnSponsorClickaction toProfileActionand updatedProfileViewModelandProfileRootto handle navigation.SponsorScreeninAppNavigationandGithubStoreGraph.SortOrderMapper.Summary by CodeRabbit
New Features
Localization