Flutter localization - #426
Conversation
📝 WalkthroughWalkthroughThis PR introduces comprehensive localization support to the Flutter app. It adds Flutter localization infrastructure (configuration, translation strings, abstract contract, and English implementation), migrates 20+ feature pages and widgets to use localized strings instead of hardcoded text, wires localization into the main app, and updates Android build configuration and tests accordingly. ChangesLocalization Feature Implementation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (6)
android/gradle.properties (1)
4-5: ⚡ Quick winAvoid committing an environment-specific workaround to shared build config.
kotlin.incremental=falseapplies globally, so it disables incremental Kotlin compilation for every developer and CI, even though the comment ties the problem to one contributor's specific Windows drive layout (project onD:, Pub cache onC:). This trades a build-speed regression for everyone to work around a local environment quirk.Prefer keeping this in the affected user's
~/.gradle/gradle.properties(orGRADLE_USER_HOME) instead of the repo. If it must stay in-repo, consider scoping it so the slowdown isn't imposed unconditionally.♻️ Option: keep repo default fast, override locally
-# Project on D: with Pub cache on C: breaks Kotlin incremental compilation on Windows. -kotlin.incremental=falseThen, on the affected machine only, add to
%USERPROFILE%\.gradle\gradle.properties:# Local-only: project on D: with Pub cache on C: breaks Kotlin incremental compilation on Windows. kotlin.incremental=false🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@android/gradle.properties` around lines 4 - 5, Remove the repository-wide kotlin.incremental=false entry (the global property key `kotlin.incremental`) from the committed gradle.properties so you don't disable incremental Kotlin compilation for all developers/CI; instead instruct the contributor to place that setting in their local Gradle user properties (`%USERPROFILE%\.gradle\gradle.properties` or `GRADLE_USER_HOME`) or implement a conditional mechanism (e.g., environment-variable gated check) so the slowdown is only applied on the affected Windows machine rather than in-repo.pubspec.yaml (1)
13-13: ⚡ Quick winConsider constraining the
intlversion.Using
intl: anyis permissive and could lead to version conflicts. While the generated code suggests using the pinned version fromflutter_localizations, specifyinganydoesn't enforce this. Consider using a version constraint like^0.18.0or relying onflutter_localizationsto transitively bring in the appropriate version without explicitly declaring it here.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pubspec.yaml` at line 13, The pubspec currently uses an unconstrained dependency "intl: any", which can cause version conflicts; change the constraint in pubspec.yaml to a specific compatible range (for example ^0.18.0) or remove the explicit "intl" entry and rely on flutter_localizations to transitively provide the correct intl version; update the dependency declaration for "intl" accordingly so tools resolve a stable, compatible version.lib/features/auth/username_setup_page.dart (1)
74-94: 💤 Low valueConsider creating a single
l10nvariable in_saveUsernameto avoid repeated lookups.Lines 74, 82, and 94 each call
AppLocalizations.of(context)!separately. While functionally correct, creatingfinal l10n = AppLocalizations.of(context)!;once at the start of the_saveUsernamemethod would be more efficient and consistent with the pattern used inbuild.♻️ Suggested refactor
Future<void> _saveUsername() async { + final l10n = AppLocalizations.of(context)!; final validationError = _validateUsername(); if (validationError != null) { setState(() => _errorText = validationError); return; } // ... rest of method ... if (!isTakenResult.isSuccess) { setState(() { _isSubmitting = false; - _errorText = isTakenResult.error ?? AppLocalizations.of(context)!.authUsernameSaveFailed; + _errorText = isTakenResult.error ?? l10n.authUsernameSaveFailed; }); return; } if (isTakenResult.value == true) { setState(() { _isSubmitting = false; - _errorText = AppLocalizations.of(context)!.authUsernameTakenError; + _errorText = l10n.authUsernameTakenError; }); return; } // ... more code ... if (!saveResult.isSuccess) { setState(() { _isSubmitting = false; - _errorText = saveResult.error ?? AppLocalizations.of(context)!.authUsernameSaveFailed; + _errorText = saveResult.error ?? l10n.authUsernameSaveFailed; }); return; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/features/auth/username_setup_page.dart` around lines 74 - 94, In _saveUsername, avoid repeated AppLocalizations.of(context)! calls by creating a single local variable (e.g., final l10n = AppLocalizations.of(context)!) at the top of the method, then replace the three occurrences where you use AppLocalizations.of(context)! (used to assign _errorText for authUsernameSaveFailed and authUsernameTakenError and any other localized strings) with l10n to improve consistency and slight performance.lib/features/checkout/widgets/share_location_dialog.dart (1)
13-36: ⚡ Quick winConsider localizing the dialog content for consistency.
The dialog's Cancel and Ok buttons are now localized (lines 31, 36), but the main dialog message at line 20 still uses
AppStrings.wantToShareLocation. For a consistent user experience, the dialog content should also be localized when the action buttons are.💬 Suggested fix
Text( - AppStrings.wantToShareLocation, + l10n.checkoutShareLocationMessage, style: Theme.of(context).textTheme.titleSmall, ),Note: This assumes
checkoutShareLocationMessageis added to the ARB file.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/features/checkout/widgets/share_location_dialog.dart` around lines 13 - 36, Replace the hardcoded string reference AppStrings.wantToShareLocation in the AlertDialog body with the localized resource from the l10n instance (e.g., l10n.checkoutShareLocationMessage), ensuring the ARB/localization files include checkoutShareLocationMessage; keep the existing usage of l10n for the action buttons and leave the Confirm handler (context.read<CheckoutViewModel>().onConfirmLocation) unchanged.lib/features/checkout/checkout_page.dart (1)
50-58: ⚡ Quick winReuse the
l10nvariable instead of callingAppLocalizations.of(context)!again.Line 50 creates
l10n, but line 58 callsAppLocalizations.of(context)!directly instead of reusing it. This is inconsistent and performs an unnecessary lookup.♻️ Suggested fix
if (status == StatusType.success) { - Fluttertoast.showToast(msg: AppLocalizations.of(context)!.checkoutPaymentSuccessfulToast); + Fluttertoast.showToast(msg: l10n.checkoutPaymentSuccessfulToast); vm.resetCreateOrderStatus(); vm.gotoCheckoutComplete(); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/features/checkout/checkout_page.dart` around lines 50 - 58, The success branch is calling AppLocalizations.of(context)! directly instead of reusing the already-created l10n variable; replace the direct lookup with the existing l10n instance (use l10n.checkoutPaymentSuccessfulToast) so the code consistently reuses l10n (ensure l10n is in scope where the StatusType.success branch runs).lib/features/discover/discover_page.dart (1)
25-25: 💤 Low valueConsider caching the localization instance for consistency.
While functionally correct, this file calls
AppLocalizations.of(context)!inline, whereas all other files in this PR cache it asfinal l10n = AppLocalizations.of(context)!;at the start ofbuild(). For consistency and to avoid repeated lookups if more localized strings are added later, consider adopting the same pattern:♻️ Proposed refactor for consistency
`@override` Widget build(BuildContext context) { + final l10n = AppLocalizations.of(context)!; return Scaffold( body: Consumer<DiscoverViewModel>( builder: (context, viewModel, _) { final charities = viewModel.fetchCharities(); final products = viewModel.fetchProducts(); return SafeArea( bottom: false, child: CustomScrollView( slivers: [ SliverAppBar( - title: Text(AppLocalizations.of(context)!.navDiscoverTitle), + title: Text(l10n.navDiscoverTitle), floating: true,🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/features/discover/discover_page.dart` at line 25, The code calls AppLocalizations.of(context)! inline in the widget tree (title: Text(AppLocalizations.of(context)!.navDiscoverTitle)) rather than caching it; update the build() method to declare final l10n = AppLocalizations.of(context)! at the top and replace the inline call with l10n.navDiscoverTitle to match other files and avoid repeated lookups.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/features/password_flow/not_you_page/not_you_page.dart`:
- Line 67: The TextField in not_you_page.dart is using l10n.authEmailLabel as
its hintText which should be the placeholder string; update the hint to use
l10n.authEmailHint instead. Locate the TextField instance in the NotYouPage
widget (or the build method) and replace the hintText reference from
authEmailLabel to authEmailHint so the placeholder matches login_form.dart and
the rest of the auth flow.
In `@lib/l10n/app_en.arb`:
- Line 34: The string value for the localization key authUsernameSetupSubtitle
contains a grammatical mistake ("you will like"); update the localized text to
proper grammar by changing the value to "Enter the name you would like to go
by." so the user-facing message reads correctly.
---
Nitpick comments:
In `@android/gradle.properties`:
- Around line 4-5: Remove the repository-wide kotlin.incremental=false entry
(the global property key `kotlin.incremental`) from the committed
gradle.properties so you don't disable incremental Kotlin compilation for all
developers/CI; instead instruct the contributor to place that setting in their
local Gradle user properties (`%USERPROFILE%\.gradle\gradle.properties` or
`GRADLE_USER_HOME`) or implement a conditional mechanism (e.g.,
environment-variable gated check) so the slowdown is only applied on the
affected Windows machine rather than in-repo.
In `@lib/features/auth/username_setup_page.dart`:
- Around line 74-94: In _saveUsername, avoid repeated
AppLocalizations.of(context)! calls by creating a single local variable (e.g.,
final l10n = AppLocalizations.of(context)!) at the top of the method, then
replace the three occurrences where you use AppLocalizations.of(context)! (used
to assign _errorText for authUsernameSaveFailed and authUsernameTakenError and
any other localized strings) with l10n to improve consistency and slight
performance.
In `@lib/features/checkout/checkout_page.dart`:
- Around line 50-58: The success branch is calling AppLocalizations.of(context)!
directly instead of reusing the already-created l10n variable; replace the
direct lookup with the existing l10n instance (use
l10n.checkoutPaymentSuccessfulToast) so the code consistently reuses l10n
(ensure l10n is in scope where the StatusType.success branch runs).
In `@lib/features/checkout/widgets/share_location_dialog.dart`:
- Around line 13-36: Replace the hardcoded string reference
AppStrings.wantToShareLocation in the AlertDialog body with the localized
resource from the l10n instance (e.g., l10n.checkoutShareLocationMessage),
ensuring the ARB/localization files include checkoutShareLocationMessage; keep
the existing usage of l10n for the action buttons and leave the Confirm handler
(context.read<CheckoutViewModel>().onConfirmLocation) unchanged.
In `@lib/features/discover/discover_page.dart`:
- Line 25: The code calls AppLocalizations.of(context)! inline in the widget
tree (title: Text(AppLocalizations.of(context)!.navDiscoverTitle)) rather than
caching it; update the build() method to declare final l10n =
AppLocalizations.of(context)! at the top and replace the inline call with
l10n.navDiscoverTitle to match other files and avoid repeated lookups.
In `@pubspec.yaml`:
- Line 13: The pubspec currently uses an unconstrained dependency "intl: any",
which can cause version conflicts; change the constraint in pubspec.yaml to a
specific compatible range (for example ^0.18.0) or remove the explicit "intl"
entry and rely on flutter_localizations to transitively provide the correct intl
version; update the dependency declaration for "intl" accordingly so tools
resolve a stable, compatible version.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: a3ee7e88-43bc-4180-b090-dbe413ebdb76
⛔ Files ignored due to path filters (1)
pubspec.lockis excluded by!**/*.lock
📒 Files selected for processing (30)
android/app/build.gradle.ktsandroid/gradle.propertiesl10n.yamllib/features/auth/username_setup_page.dartlib/features/checkout/checkout_page.dartlib/features/checkout/widgets/delivery_options.dartlib/features/checkout/widgets/share_location_dialog.dartlib/features/discover/discover_page.dartlib/features/discover/widgets/discover_selection_bar.dartlib/features/home/widgets/bottom_nav_bar.dartlib/features/login/login_page.dartlib/features/login/widgets/login_form.dartlib/features/password_flow/not_you_page/not_you_page.dartlib/features/products/product_page.dartlib/features/products/widgets/seller_information.dartlib/features/register/register_page.dartlib/features/register/verify_email_page.dartlib/features/register/widgets/register_form.dartlib/features/settings/widgets/settings_category_group.dartlib/features/welcome/welcome_page.dartlib/features/welcome/widgets/signup_card.dartlib/l10n/app_en.arblib/l10n/app_localizations.dartlib/l10n/app_localizations_en.dartlib/main.dartpubspec.yamltest/auth_ui_test.darttest/auth_ui_test.mocks.darttest/checkout_view_model_test.mocks.darttest/widget_test.dart
| TextField( | ||
| decoration: InputDecoration( | ||
| hintText: AppStrings.email, | ||
| hintText: l10n.authEmailLabel, |
There was a problem hiding this comment.
Use authEmailHint for the field hint, not authEmailLabel.
This TextField uses l10n.authEmailLabel as its hintText, whereas login_form.dart (Line 83) uses l10n.authEmailHint for the equivalent hint. The label string (e.g. "Email") reads incorrectly as placeholder text; this is inconsistent with the rest of the auth flow.
Proposed fix
- hintText: l10n.authEmailLabel,
+ hintText: l10n.authEmailHint,📝 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.
| hintText: l10n.authEmailLabel, | |
| hintText: l10n.authEmailHint, |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/features/password_flow/not_you_page/not_you_page.dart` at line 67, The
TextField in not_you_page.dart is using l10n.authEmailLabel as its hintText
which should be the placeholder string; update the hint to use
l10n.authEmailHint instead. Locate the TextField instance in the NotYouPage
widget (or the build method) and replace the hintText reference from
authEmailLabel to authEmailHint so the placeholder matches login_form.dart and
the rest of the auth flow.
| "authSendEmailButton": "Send email", | ||
| "authNotYouLink": "Not you", | ||
| "authUsernameSetupTitle": "Who is this?", | ||
| "authUsernameSetupSubtitle": "Enter the name you will like to go by.", |
There was a problem hiding this comment.
Grammatical error in user-facing text.
The phrase "you will like" should be "you would like" for proper grammar.
📝 Suggested correction
- "authUsernameSetupSubtitle": "Enter the name you will like to go by.",
+ "authUsernameSetupSubtitle": "Enter the name you would like to go by.",📝 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.
| "authUsernameSetupSubtitle": "Enter the name you will like to go by.", | |
| "authUsernameSetupSubtitle": "Enter the name you would like to go by.", |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/l10n/app_en.arb` at line 34, The string value for the localization key
authUsernameSetupSubtitle contains a grammatical mistake ("you will like");
update the localized text to proper grammar by changing the value to "Enter the
name you would like to go by." so the user-facing message reads correctly.
|
Hey @AsadAli93916 thank you for this. However, due to the structure of cherry and how logistics processes work with it, we can't have an 'add to cart' option available. |
|
@AsadAli93916 which issue does this aim to fix? 🫶 |
|
Hey @AsadAli93916 is this aiming to do: #381 (comment) Before I can merge, we need to clarify the scope and fix the merge conflicts. Other than that, coderabbit came back positive and I see no immediately pressing issues. Thank you for this work, it is not an overstatement to say you are supporting us in our mission to help charities through this difficult and increasingly digital time. I appreciate your efforts. |
Implemented Flutter localisation setup using gen-l10n.
Added:
Converted:
Remaining hardcoded strings:
Verified app builds and runs successfully.
Summary by CodeRabbit
New Features
Chores