diff --git a/assets/lang/en.json b/assets/lang/en.json index 6bb1e6a..4e4131c 100644 --- a/assets/lang/en.json +++ b/assets/lang/en.json @@ -7,6 +7,7 @@ "btn.capture": "Capture", "btn.gallery": "Gallery", "btn.camera": "Camera", + "capture.prompt": "Take a photo of the issue", "btn.next": "Next", "btn.submit": "Submit", "btn.save": "Save", diff --git a/assets/lang/ms.json b/assets/lang/ms.json index f7e63da..83f537f 100644 --- a/assets/lang/ms.json +++ b/assets/lang/ms.json @@ -7,6 +7,7 @@ "btn.capture": "Tangkap", "btn.gallery": "Galeri", "btn.camera": "Kamera", + "capture.prompt": "Ambil gambar isu", "btn.next": "Seterusnya", "btn.submit": "Hantar", "btn.save": "Simpan", diff --git a/lib/app.dart b/lib/app.dart index bf9e859..611ad3a 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; import 'l10n/i18n.dart'; import 'l10n/locale_provider.dart'; import 'screens/report_flow/capture_screen.dart'; @@ -22,10 +23,29 @@ class FixMateApp extends StatelessWidget { darkTheme: AppThemes.dark(), themeMode: ThemeMode.system, locale: localeProvider.locale, - supportedLocales: const [ - Locale('en', 'US'), - Locale('ms', 'MY'), + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, ], + supportedLocales: const [ + Locale('en'), + Locale('ms'), + ], + localeResolutionCallback: (locale, supported) { + debugPrint('[i18n] localeResolution: device=$locale, supported=$supported'); + if (locale == null) return supported.first; + for (final s in supported) { + if (s.languageCode == locale.languageCode) { + return s; + } + } + return supported.first; + }, + builder: (context, child) { + debugPrint('[i18n] Building MaterialApp; locale=${localeProvider.locale}'); + return child!; + }, home: const StartRouter(), ); }, @@ -153,6 +173,7 @@ class _StartRouterState extends State { @override Widget build(BuildContext context) { + debugPrint('[i18n] StartRouter: hasMaterial=${Localizations.of(context, MaterialLocalizations) != null} locale=${Localizations.localeOf(context)}'); if (_loading) { return const Scaffold(body: Center(child: CircularProgressIndicator())); } diff --git a/lib/l10n/locale_provider.dart b/lib/l10n/locale_provider.dart index 09888a9..5ceeef2 100644 --- a/lib/l10n/locale_provider.dart +++ b/lib/l10n/locale_provider.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'i18n.dart'; /// Provider for managing app locale and language switching class LocaleProvider extends ChangeNotifier { @@ -20,6 +21,7 @@ class LocaleProvider extends ChangeNotifier { _prefs = await SharedPreferences.getInstance(); final savedLanguage = _prefs.getString(_languageKey) ?? _defaultLanguage; _locale = Locale(savedLanguage); + await I18n.init(_locale); notifyListeners(); } @@ -29,6 +31,7 @@ class LocaleProvider extends ChangeNotifier { _locale = locale; await _prefs.setString(_languageKey, locale.languageCode); + await I18n.init(locale); notifyListeners(); } diff --git a/lib/screens/map/map_screen.dart b/lib/screens/map/map_screen.dart index 622873c..d06ccd5 100644 --- a/lib/screens/map/map_screen.dart +++ b/lib/screens/map/map_screen.dart @@ -64,9 +64,11 @@ class _MapScreenState extends State { _applyFilters(); // If we have filtered reports, fit; otherwise try device location if (_filteredReports.isNotEmpty) { + debugPrint('[map] _refresh: filtered=${_filteredReports.length}; scheduling fitBounds postFrame'); WidgetsBinding.instance.addPostFrameCallback((_) => _fitToBounds()); } else { - await _centerOnDeviceOrDefault(); + debugPrint('[map] _refresh: filtered=0; scheduling centerOnDeviceOrDefault postFrame'); + WidgetsBinding.instance.addPostFrameCallback((_) => _centerOnDeviceOrDefault()); } } @@ -74,11 +76,12 @@ class _MapScreenState extends State { try { final pos = await LocationService.getBestAvailablePosition(); if (pos != null) { + debugPrint('[map] _centerOnDeviceOrDefault: moving to device location (${pos.latitude}, ${pos.longitude})'); _mapController.move(LatLng(pos.latitude, pos.longitude), _defaultZoom); return; } } catch (_) {} - // fallback + debugPrint('[map] _centerOnDeviceOrDefault: moving to default center ($_defaultCenter) zoom=$_defaultZoom'); _mapController.move(_defaultCenter, _defaultZoom); } diff --git a/lib/screens/report_flow/capture_screen.dart b/lib/screens/report_flow/capture_screen.dart index d3d2714..b70b3ca 100644 --- a/lib/screens/report_flow/capture_screen.dart +++ b/lib/screens/report_flow/capture_screen.dart @@ -116,6 +116,7 @@ class _CaptureScreenState extends State { @override Widget build(BuildContext context) { + debugPrint('[i18n] CaptureScreen: locale=${I18n.currentLocale} prompt=${I18n.t('capture.prompt')}'); return Scaffold( appBar: AppBar( title: Text(I18n.t('nav.report')), @@ -126,7 +127,7 @@ class _CaptureScreenState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - 'Take a photo of the issue', + I18n.t('capture.prompt'), style: Theme.of(context).textTheme.headlineSmall, textAlign: TextAlign.center, ), diff --git a/pubspec.lock b/pubspec.lock index 6d15889..ccc43cb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -166,6 +166,11 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.0" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" flutter_map: dependency: "direct main" description: @@ -340,10 +345,10 @@ packages: dependency: transitive description: name: intl - sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" url: "https://pub.dev" source: hosted - version: "0.19.0" + version: "0.20.2" latlong2: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index f5815b9..783b788 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,8 @@ environment: dependencies: flutter: sdk: flutter + flutter_localizations: + sdk: flutter cupertino_icons: ^1.0.8 flutter_map: ^8.2.2 flutter_map_marker_cluster: ^8.2.2