diff --git a/mobile/lib/constants/locales.dart b/mobile/lib/constants/locales.dart index d92ae7660e..5c928c124e 100644 --- a/mobile/lib/constants/locales.dart +++ b/mobile/lib/constants/locales.dart @@ -48,3 +48,8 @@ const Map locales = { }; const String translationsPath = 'assets/i18n'; + +const List localesNotSupportedByOverpass = [ + Locale('el', 'GR'), + Locale('sr', 'Cyrl'), +]; diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 3b582e336c..e9ca8ceb6a 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -10,6 +10,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/providers/locale_provider.dart'; import 'package:immich_mobile/utils/download.dart'; import 'package:intl/date_symbol_data_local.dart'; import 'package:timezone/data/latest.dart'; @@ -212,20 +213,31 @@ class ImmichAppState extends ConsumerState final router = ref.watch(appRouterProvider); final immichTheme = ref.watch(immichThemeProvider); - return MaterialApp( - localizationsDelegates: context.localizationDelegates, - supportedLocales: context.supportedLocales, - locale: context.locale, - debugShowCheckedModeBanner: true, - home: MaterialApp.router( - title: 'Immich', - debugShowCheckedModeBanner: false, - themeMode: ref.watch(immichThemeModeProvider), - darkTheme: getThemeData(colorScheme: immichTheme.dark), - theme: getThemeData(colorScheme: immichTheme.light), - routeInformationParser: router.defaultRouteParser(), - routerDelegate: router.delegate( - navigatorObservers: () => [TabNavigationObserver(ref: ref)], + return ProviderScope( + overrides: [ + localeProvider.overrideWithValue(context.locale), + ], + child: MaterialApp( + localizationsDelegates: context.localizationDelegates, + supportedLocales: context.supportedLocales, + locale: context.locale, + debugShowCheckedModeBanner: true, + home: MaterialApp.router( + title: 'Immich', + debugShowCheckedModeBanner: false, + themeMode: ref.watch(immichThemeModeProvider), + darkTheme: getThemeData( + colorScheme: immichTheme.dark, + locale: context.locale, + ), + theme: getThemeData( + colorScheme: immichTheme.light, + locale: context.locale, + ), + routeInformationParser: router.defaultRouteParser(), + routerDelegate: router.delegate( + navigatorObservers: () => [TabNavigationObserver(ref: ref)], + ), ), ), ); diff --git a/mobile/lib/providers/locale_provider.dart b/mobile/lib/providers/locale_provider.dart new file mode 100644 index 0000000000..5de3fa009a --- /dev/null +++ b/mobile/lib/providers/locale_provider.dart @@ -0,0 +1,4 @@ +import 'package:flutter/widgets.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +final localeProvider = Provider((_) => throw UnimplementedError()); diff --git a/mobile/lib/utils/immich_app_theme.dart b/mobile/lib/utils/immich_app_theme.dart index 42d338956f..da47490651 100644 --- a/mobile/lib/utils/immich_app_theme.dart +++ b/mobile/lib/utils/immich_app_theme.dart @@ -2,6 +2,7 @@ import 'package:dynamic_color/dynamic_color.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/immich_colors.dart'; +import 'package:immich_mobile/constants/locales.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; @@ -145,7 +146,18 @@ ImmichTheme _decolorizeSurfaces({ ); } -ThemeData getThemeData({required ColorScheme colorScheme}) { +String? getFontFamilyFromLocale(Locale locale) { + if (localesNotSupportedByOverpass.contains(locale)) { + // Let Flutter use the default font + return null; + } + return 'Overpass'; +} + +ThemeData getThemeData({ + required ColorScheme colorScheme, + required Locale locale, +}) { var isDark = colorScheme.brightness == Brightness.dark; var primaryColor = colorScheme.primary; @@ -163,10 +175,10 @@ ThemeData getThemeData({required ColorScheme colorScheme}) { bottomSheetTheme: BottomSheetThemeData( backgroundColor: colorScheme.surfaceContainer, ), - fontFamily: 'Overpass', + fontFamily: getFontFamilyFromLocale(locale), snackBarTheme: SnackBarThemeData( contentTextStyle: TextStyle( - fontFamily: 'Overpass', + fontFamily: getFontFamilyFromLocale(locale), color: primaryColor, fontWeight: FontWeight.bold, ), @@ -175,7 +187,7 @@ ThemeData getThemeData({required ColorScheme colorScheme}) { appBarTheme: AppBarTheme( titleTextStyle: TextStyle( color: primaryColor, - fontFamily: 'Overpass', + fontFamily: getFontFamilyFromLocale(locale), fontWeight: FontWeight.bold, fontSize: 18, ), diff --git a/mobile/lib/widgets/map/map_theme_override.dart b/mobile/lib/widgets/map/map_theme_override.dart index 3b66a1cc35..68a2146bfb 100644 --- a/mobile/lib/widgets/map/map_theme_override.dart +++ b/mobile/lib/widgets/map/map_theme_override.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/providers/locale_provider.dart'; import 'package:immich_mobile/providers/map/map_state.provider.dart'; import 'package:immich_mobile/utils/immich_app_theme.dart'; @@ -71,6 +72,7 @@ class _MapThemeOverideState extends ConsumerState _theme = widget.themeMode ?? ref.watch(mapStateNotifierProvider.select((v) => v.themeMode)); var appTheme = ref.watch(immichThemeProvider); + final locale = ref.watch(localeProvider); useValueChanged(_theme, (_, __) { if (_theme == ThemeMode.system) { @@ -85,8 +87,8 @@ class _MapThemeOverideState extends ConsumerState return Theme( data: _isDarkTheme - ? getThemeData(colorScheme: appTheme.dark) - : getThemeData(colorScheme: appTheme.light), + ? getThemeData(colorScheme: appTheme.dark, locale: locale) + : getThemeData(colorScheme: appTheme.light, locale: locale), child: widget.mapBuilder.call( ref.watch( mapStateNotifierProvider.select( diff --git a/mobile/test/modules/map/map_theme_override_test.dart b/mobile/test/modules/map/map_theme_override_test.dart index f399625ac2..b462ede4c5 100644 --- a/mobile/test/modules/map/map_theme_override_test.dart +++ b/mobile/test/modules/map/map_theme_override_test.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/models/map/map_state.model.dart'; +import 'package:immich_mobile/providers/locale_provider.dart'; import 'package:immich_mobile/providers/map/map_state.provider.dart'; import 'package:immich_mobile/widgets/map/map_theme_override.dart'; @@ -24,7 +25,10 @@ void main() { setUp(() { mapState = MapState(themeMode: ThemeMode.dark); mapStateNotifier = MockMapStateNotifier(mapState); - overrides = [mapStateNotifierProvider.overrideWith(() => mapStateNotifier)]; + overrides = [ + mapStateNotifierProvider.overrideWith(() => mapStateNotifier), + localeProvider.overrideWithValue(Locale("en")), + ]; }); testWidgets("Return dark theme style when theme mode is dark",