Skip to content

feat(mobile): add Polish localization and native language support - #2054

Draft
Dragonk wants to merge 70 commits into
CodeWithCJ:mainfrom
Dragonk:feat/mobile-i18n-language-settings
Draft

feat(mobile): add Polish localization and native language support#2054
Dragonk wants to merge 70 commits into
CodeWithCJ:mainfrom
Dragonk:feat/mobile-i18n-language-settings

Conversation

@Dragonk

@Dragonk Dragonk commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Tip

Draft — automated QA and Android device testing are complete; iOS native validation is still in progress. A few isolated untranslated strings (e.g. "Save", "End workout") are known and will be addressed in follow-up PRs after architecture approval.

Description

What problem does this PR solve?
Adds full Polish (PL) localization and native language support to the mobile app, alongside mobile compatibility fixes for custom measurement entries and custom meal types in the Diary. The branch is synchronized with the current upstream main.

How did you implement the solution?

  • Built a complete client-side i18n infrastructure (EN/PL) with splash-safe bootstrap (no translation-key flash), language preference (System / English / Polski), native Android App Language synchronization and iOS native locale prep.
  • Localized native surfaces: Android App Languages, Android Glance widgets, iOS WidgetKit (EN/PL), Workout Live Activity, with language refresh where the platform allows.
  • Fixed mobile compatibility for existing backend contracts: custom measurement entry support (Daily / Hourly / Unlimited/All, numeric/text/boolean), custom meal types as separate Diary categories, ID-first meal type flow, literal custom names (never passed through t()).
  • Integrated the latest upstream main (food search / ownership filters, workout telemetry, exercise images) without regressing the i18n work.

How to Test

  1. Check out this branch and run pnpm install --frozen-lockfile in the repo root.
  2. Run pnpm run typecheck && pnpm run lint && pnpm run i18n:audit in SparkyFitnessMobile/.
  3. Build the app (npx expo prebuild --clean --platform android, then gradlew assembleRelease).
  4. Launch, log in, switch language Settings → App language (System / English / Polski), restart and verify no translation keys are shown.
  5. Verify Diary (system + custom meal types), custom measurements (numeric/boolean, 0, false, PL decimal 1,5, Daily/Hourly/Unlimited, delete), workout, and widgets in both languages.

PR Type

  • Issue (bug fix)
  • New Feature
  • Refactor
  • Documentation

Checklist

All PRs:

  • [MANDATORY - ALL] Integrity & License: I certify this is my own work, free of malicious code, and I agree to the License terms.

New features only:

  • [MANDATORY for new feature] Alignment: I have raised a GitHub issue and it was reviewed/approved by maintainers or it was approved on Discord.

Frontend changes (SparkyFitnessFrontend/):

  • [MANDATORY for Frontend changes] Quality: I have run pnpm run validate and it passes.
  • [MANDATORY for Frontend changes] Translations: I have only updated the English (en) translation file.

Backend changes (SparkyFitnessServer/):

  • [MANDATORY for Backend changes] Code Quality: I have run typecheck, lint, and tests. New files use TypeScript, new endpoints have Zod schemas, and new endpoints include tests.
  • [MANDATORY for Backend changes] Database Security: I have updated rls_policies.sql for any new user-specific tables.

UI changes (components, screens, pages):

  • [MANDATORY for UI changes] Screenshots: I have attached Before/After screenshots below.

Mobile changes (SparkyFitnessMobile/):

  • [MANDATORY for Mobile changes] Tested on device or emulator: I have verified the changes work on iOS or Android.

Testing status (verified)

  • Jest: 327/327 suites passed, 5470/5470 tests passed
  • TypeScript typecheck: passed
  • ESLint: passed
  • i18n audit: missing 0, structural 0, placeholder 0, plural 0, dynamic 0, new baseline findings 0, stale baseline findings 0
  • Android clean prebuild: passed
  • Android release APK build: passed
  • Android physical-device testing: completed — verified on a real Android device against a current-main server. App starts, no translation keys are shown, language switching works (System / English / Polski), Diary (system + custom meal types), custom measurements, workouts, and widgets all work correctly.
  • iOS Xcode/device validation: pending (requires Mac/Xcode)

Known follow-ups (not blocking this draft)

  • A few isolated UI strings still render in English (e.g. "Save", "End workout"). These are individual cases to be resolved in follow-up PRs after architecture approval; they do not affect the overall i18n flow.
  • The Android system-level "App language" entry in Settings is not exposed on every device/ROM; the in-app language setting is the supported path.

Related issues

Resolved by this implementation

Related / partially addressed

Screenshots

Click to expand

Before

Screenshot_2026-08-07-10-31-10-021_com SparkyApps SparkyFitnessMobile Screenshot_2026-08-07-10-31-01-444_com SparkyApps SparkyFitnessMobile Screenshot_2026-08-07-10-30-54-264_com SparkyApps SparkyFitnessMobile

After

Screenshot_2026-08-07-08-18-36-945_org SparkyApps SparkyFitnessMobile1 dev Screenshot_2026-08-07-08-18-46-475_org SparkyApps SparkyFitnessMobile1 dev Screenshot_2026-08-07-08-18-29-804_org SparkyApps SparkyFitnessMobile1 dev Screenshot_2026-08-07-08-19-03-877_org SparkyApps SparkyFitnessMobile1 dev

Screenshots will be added after final manual validation.

Notes for Reviewers

This is a Draft PR. Automated QA and real-device Android testing are complete; iOS native validation (Xcode/device) is still pending. The remaining mandatory checkboxes (screenshots, feature alignment issue) will be completed before this is marked ready. The project's CI may flag the unchecked alignment/screenshot checkboxes — that is expected for this draft stage.

Kamil Maciag added 30 commits July 29, 2026 21:32
Add mobile i18n support, automatic device language detection, and manual language selection.

Refs CodeWithCJ#1774

Refs CodeWithCJ#1490
Add data layer and UI for custom (user-defined) measurements.

Stage 7 — Data layer:
- Types for CustomCategory and CustomMeasurementEntry
- API client functions (fetchCustomCategories,
  fetchCustomMeasurementsByDate, save, delete)
- TanStack Query hooks with automatic cache invalidation
- Query keys and barrel exports

Stage 8 — UI integration:
- MeasurementsAddScreen: dynamic custom measurement fields
  rendered per category, with numeric/text/boolean input,
  prefilled existing values, clear-on-empty, and save/delete
- MeasurementsSummary: tiles for custom entries alongside
  built-in measurements
- DiaryScreen: hasAnyMeasurement includes custom entries
- Convert async i18n tests to jest.isolateModulesAsync
- Block built-in saves when custom form fails validation
- Add confirmation Alert for custom deletes with affected category names
- Gate save button on custom-data loading/error state
- Add dynamic-content protection tests (MeasurementsSummary, FoodLibraryRow,
  MealLibraryRow, ExerciseHistoryList, MeasurementsAddScreen t-spy)
Kamil Maciag and others added 16 commits August 5, 2026 21:51
…nguage-settings

# Conflicts:
#	SparkyFitnessMobile/App.tsx
#	SparkyFitnessMobile/__tests__/screens/MeasurementsAddScreen.test.tsx
#	SparkyFitnessMobile/src/components/ActionSheet.tsx
#	SparkyFitnessMobile/src/components/AddSheet.tsx
#	SparkyFitnessMobile/src/components/BottomSheetPicker.tsx
#	SparkyFitnessMobile/src/components/ConnectionStatus.tsx
#	SparkyFitnessMobile/src/components/CopyMealSheet.tsx
#	SparkyFitnessMobile/src/components/DateRangeSheet.tsx
#	SparkyFitnessMobile/src/components/DevTools.tsx
#	SparkyFitnessMobile/src/components/EndFastSheet.tsx
#	SparkyFitnessMobile/src/components/FastingEditSheet.tsx
#	SparkyFitnessMobile/src/components/FastingHistorySheet.tsx
#	SparkyFitnessMobile/src/components/FoodForm.tsx
#	SparkyFitnessMobile/src/components/HydrationGauge.tsx
#	SparkyFitnessMobile/src/components/MacroSummaryCard.tsx
#	SparkyFitnessMobile/src/components/NutrientBarChart.tsx
#	SparkyFitnessMobile/src/components/RestPeriodSheet.tsx
#	SparkyFitnessMobile/src/components/ServingAdjustSheet.tsx
#	SparkyFitnessMobile/src/components/StepsBarChart.tsx
#	SparkyFitnessMobile/src/components/SwipeableDeleteRow.tsx
#	SparkyFitnessMobile/src/components/SwipeableExerciseRow.tsx
#	SparkyFitnessMobile/src/components/SwipeableFoodRow.tsx
#	SparkyFitnessMobile/src/components/SwipeableIngredientRow.tsx
#	SparkyFitnessMobile/src/components/SyncFrequency.tsx
#	SparkyFitnessMobile/src/components/SyncOnOpen.tsx
#	SparkyFitnessMobile/src/components/WeightLineChart.tsx
#	SparkyFitnessMobile/src/components/medications/WeekdaySheet.tsx
#	SparkyFitnessMobile/src/components/wellness/BBTLineChart.tsx
#	SparkyFitnessMobile/src/screens/ActivityAddScreen.tsx
#	SparkyFitnessMobile/src/screens/ActivityDetailScreen.tsx
#	SparkyFitnessMobile/src/screens/AppSettingsScreen.tsx
#	SparkyFitnessMobile/src/screens/CalorieSettingsScreen.tsx
#	SparkyFitnessMobile/src/screens/CycleHubScreen.tsx
#	SparkyFitnessMobile/src/screens/CycleLogModalScreen.tsx
#	SparkyFitnessMobile/src/screens/CycleOnboardingScreen.tsx
#	SparkyFitnessMobile/src/screens/CycleSettingsScreen.tsx
#	SparkyFitnessMobile/src/screens/DailyNutritionDetailsScreen.tsx
#	SparkyFitnessMobile/src/screens/DashboardScreen.tsx
#	SparkyFitnessMobile/src/screens/DashboardSettingsScreen.tsx
#	SparkyFitnessMobile/src/screens/DiaryScreen.tsx
#	SparkyFitnessMobile/src/screens/DiarySettingsScreen.tsx
#	SparkyFitnessMobile/src/screens/ExercisesLibraryScreen.tsx
#	SparkyFitnessMobile/src/screens/FastingDetailScreen.tsx
#	SparkyFitnessMobile/src/screens/FoodEntryAddScreen.tsx
#	SparkyFitnessMobile/src/screens/FoodFormScreen.tsx
#	SparkyFitnessMobile/src/screens/FoodPhotoLogEntryScreen.tsx
#	SparkyFitnessMobile/src/screens/FoodSearchScreen.tsx
#	SparkyFitnessMobile/src/screens/FoodsLibraryScreen.tsx
#	SparkyFitnessMobile/src/screens/MealAddScreen.tsx
#	SparkyFitnessMobile/src/screens/MealTypeDetailScreen.tsx
#	SparkyFitnessMobile/src/screens/MealsLibraryScreen.tsx
#	SparkyFitnessMobile/src/screens/MeasurementsAddScreen.tsx
#	SparkyFitnessMobile/src/screens/MedicationFormScreen.tsx
#	SparkyFitnessMobile/src/screens/MedicationScheduleFormScreen.tsx
#	SparkyFitnessMobile/src/screens/NotificationSettingsScreen.tsx
#	SparkyFitnessMobile/src/screens/NutrientTrendsScreen.tsx
#	SparkyFitnessMobile/src/screens/SyncScreen.tsx
#	SparkyFitnessMobile/src/screens/WorkoutAddScreen.tsx
#	SparkyFitnessMobile/src/screens/WorkoutPresetsLibraryScreen.tsx
#	SparkyFitnessMobile/src/screens/WorkoutSettingsScreen.tsx
#	SparkyFitnessMobile/src/utils/dateUtils.ts
Localize the new exercise image crossfade accessibility labels introduced by upstream PR CodeWithCJ#2047.

Assisted-by: Open WebUI
Localize ownership filter UI, remove duplicated favorite stars, drop removed popover DevTools tests, and localize the new exercise image crossfade accessibility labels.

Assisted-by: Open WebUI
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1c72d968-8f16-4feb-a7bf-aa9c8b25102e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@apedley

apedley commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Wow that's a lot, thanks again for taking this on. I know this is a draft but would you be able to split this up into a sequence of PRs? 30k lines added and most of them are replacing strings with t() is going to be very hard to review. Something like:

  1. Unrelated feature work - I see some new things like a MealTypeSettingsScreen which is a different topic/PR. The mobile compatibility fixes would go here
  2. Infrastructure PR - the one I can review in depth for localization. Include some strings here so I can test it
  3. Rest of the strings - having this separate will keep the merge conflicts together (everything updated on main is going to conflict). Then when the other two PRs get merged we can fix the conflicts and merge it next.

I know splitting after the fact is a pain. If you want help pulling it apart or have other concerns let me know

@Dragonk

Dragonk commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

Wow that's a lot, thanks again for taking this on. I know this is a draft but would you be able to split this up into a sequence of PRs? 30k lines added and most of them are replacing strings with t() is going to be very hard to review. Something like:

  1. Unrelated feature work - I see some new things like a MealTypeSettingsScreen which is a different topic/PR. The mobile compatibility fixes would go here
  2. Infrastructure PR - the one I can review in depth for localization. Include some strings here so I can test it
  3. Rest of the strings - having this separate will keep the merge conflicts together (everything updated on main is going to conflict). Then when the other two PRs get merged we can fix the conflicts and merge it next.

I know splitting after the fact is a pain. If you want help pulling it apart or have other concerns let me know

That makes sense. I’ll first finish building the app with everything together so I can do a full round of device testing on the integrated version.

After that I’ll try to split this draft into a sequence of smaller PRs so each part is easier to review:

  1. Custom measurements
  2. Custom meal types
  3. i18n infrastructure and native language handling
  4. Widgets + Live Activity localization
  5. The remaining string localization

I’ll keep the current branch as the integrated reference while I split the work out. That should also make it easier to verify that the smaller PRs still behave the same as the fully integrated build.

Thanks for the suggestion — I agree this should make the review much more manageable.

@CodeWithCJ

Copy link
Copy Markdown
Owner

Always include english wording as fallback. This way even if the translation files are not available, the app will continue to work.

t('some.key', 'Default English Text')

Also, Translation files are maintained in another repository. Are we not re-using the existing translation @apedley any suggestion on this? I know there were some discussion earlier around this.

@github-actions github-actions Bot added enhancement New feature or request mobile labels Aug 7, 2026
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

PR Validation Results

Change Detection

  • 📱 Mobile changes detected

⚠️ Recommendations (1)

  • Please link a related GitHub issue (Linked Issue: Closes #123).

✅ All required checks passed.

@Dragonk

Dragonk commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Android device testing — completed ✅

Verified on a real Android device against a current-main server (release APK with embedded JS bundle, no Metro required):

  • App starts, no translation keys are shown
  • Language switching works: System / English / Polski (in-app; the system-level "App language" entry is not exposed on every Android ROM)
  • Diary: system + custom meal types work, custom names stay literal
  • Custom measurements: numeric/PL decimal/0/false/Daily/Hourly/Unlimited/delete work
  • Workout: start, sets, rest, finish, exercise images work
  • Widgets: Calorie + Macro, EN/PL, language refresh works

Known follow-ups (not blocking this draft): a few isolated UI strings still render in English (e.g. "Save", "End workout") — individual cases to resolve in follow-up PRs after architecture approval. iOS Xcode/device validation remains pending.

@apedley

apedley commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Also, Translation files are maintained in another repository. Are we not re-using the existing translation @apedley any suggestion on this? I know there were some discussion earlier around this.

You'll have to copy the translation files to the translations repo (mobile/en/translation.json and one for pl), create a component in weblate, then update sync-translations.yml for github action to handle mobile paths. By creating the weblate component in the same project, we get shared translation memory. So strings like "save" or "cancel" that were already translated for web will affect mobile.

Since the translation is bundled for mobile I wouldn't do anything until we are close to merging the final step. Otherwise youll have to copy the files again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request mobile refactor

Projects

None yet

3 participants