Skip to content

feat(mobile): Add internationalization (i18n) support#1957

Open
bvisible wants to merge 12 commits intoThe-Commit-Company:developfrom
bvisible:feat/mobile-i18n
Open

feat(mobile): Add internationalization (i18n) support#1957
bvisible wants to merge 12 commits intoThe-Commit-Company:developfrom
bvisible:feat/mobile-i18n

Conversation

@bvisible
Copy link
Copy Markdown

@bvisible bvisible commented Jan 4, 2026

Summary

  • Add i18next and react-i18next for translation management in the mobile app
  • Create English (en.json) and French (fr.json) locale files with all user-facing strings
  • Replace all hardcoded user-facing strings with translation keys across the entire mobile app
  • Add language selector in profile settings allowing users to switch between languages
  • Configure i18n with automatic language detection and persistence

Changes

This PR introduces full internationalization support for the Raven mobile app, allowing users to use the app in their preferred language. All user-facing text (buttons, labels, messages, error texts, menu items, etc.) has been wrapped with the translation function and corresponding translation keys have been added to the locale files.

Test plan

  • Verify all text displays correctly in English (default)
  • Switch language to French in settings and verify all text is translated
  • Check that language preference persists after app restart
  • Verify interpolated strings (with variables) display correctly
  • Test error messages and toast notifications are translated

- Add i18next and react-i18next for translation management
- Create English (en.json) and French (fr.json) locale files
- Replace all hardcoded user-facing strings with translation keys
- Add language selector in profile settings
- Configure i18n with language detection and persistence
- Create dedicated language selection page
- Update LanguageSetting to navigate to the new page
- Show current language with chevron indicator
- Add ai_thread_created event handler in useChatStream for auto-navigation
- Update is_thread flag on parent message when AI thread is created
- Fix ViewThreadButton to properly revalidate reply count on mount/focus
- Remove duplicate reply count display in thread button
@nikkothari22
Copy link
Copy Markdown
Member

@bvisible The translation strings here make it much more harder to manage. We would add translations similar to how Frappe offers them on the web. That would also remove duplicate translation files (one for mobile, the other for web).

Example: t('media.cameraPermissionDenied') this is very hard to maintain over such a large codebase - and introduces a new paradigm for mobile - hence duplicating work. We would use the way Frappe does it - _("Camera permission not granted")) will get translated based on the user's language selection. Will also find a way to auto-migrate the .po files into the mobile app.

@nikkothari22
Copy link
Copy Markdown
Member

@barredterra Thoughts?

@barredterra
Copy link
Copy Markdown
Contributor

Having JSON in addition to .po files seems wasteful/duplicative. Can't i18next handle .po files?

- Replace t('key.subkey') pattern with __("English text") Frappe style
- Use raven/locale/fr.po as single source of truth for translations
- Add po-to-json.js script to convert .po to JSON at build time
- Add sync-po-with-code.js to extract strings from components
- Force app re-render on language change via Providers.tsx
- Add react-native-worklets dependency (required by NativeWind)

This addresses the concerns raised in PR review:
- No more duplicate translation files (web + mobile share .po)
- Frappe-compatible format using __() function
- 335 French translations preserved from original PR
@bvisible
Copy link
Copy Markdown
Author

Refactored i18n to Frappe-style with single .po source

Based on the feedback, I've refactored the i18n implementation to:

Changes Made

  1. Frappe-style translation syntax

    • Replaced t('key.subkey') with __("English text")
    • Same pattern as Frappe web: _("String to translate")
  2. Single source of truth

    • All translations now live in raven/locale/fr.po
    • No duplicate JSON files - .po is converted to JSON at build time
    • Can be used with bench compile-po-to-mo for Frappe integration
  3. Build pipeline

    • yarn start automatically runs po-to-json.js
    • Converts .po → JSON for i18next consumption
    • sync-po-with-code.js extracts all strings from components

Architecture

raven/locale/fr.po           ← Single source (edit here)
       ↓ (prestart script)
apps/mobile/locales/*.json   ← Auto-generated (don't edit)

Stats

  • 335 French translations preserved
  • 123 component files migrated
  • Full app re-render on language change

This should address the concerns about:

  • ✅ Duplicate translation files
  • ✅ Hard-to-maintain t('key.subkey') pattern
  • ✅ Frappe compatibility

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants