feat: setup localization (l10n) and language switcher, add sidebar and navbar locale

This commit is contained in:
Kingkor Roy Tirtho 2023-04-29 00:13:37 +06:00
parent 8432dc6286
commit f12d81259f
14 changed files with 161 additions and 58 deletions

3
l10n.yaml Normal file
View File

@ -0,0 +1,3 @@
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class SideBarTiles {
final IconData icon;
@ -7,16 +8,16 @@ class SideBarTiles {
SideBarTiles({required this.icon, required this.title});
}
List<SideBarTiles> sidebarTileList = [
SideBarTiles(icon: SpotubeIcons.home, title: "Browse"),
SideBarTiles(icon: SpotubeIcons.search, title: "Search"),
SideBarTiles(icon: SpotubeIcons.library, title: "Library"),
SideBarTiles(icon: SpotubeIcons.music, title: "Lyrics")
List<SideBarTiles> getSidebarTileList(AppLocalizations l10n) => [
SideBarTiles(icon: SpotubeIcons.home, title: l10n.browse),
SideBarTiles(icon: SpotubeIcons.search, title: l10n.search),
SideBarTiles(icon: SpotubeIcons.library, title: l10n.library),
SideBarTiles(icon: SpotubeIcons.music, title: l10n.lyrics),
];
List<SideBarTiles> navbarTileList = [
SideBarTiles(icon: SpotubeIcons.home, title: "Browse"),
SideBarTiles(icon: SpotubeIcons.search, title: "Search"),
SideBarTiles(icon: SpotubeIcons.library, title: "Library"),
SideBarTiles(icon: SpotubeIcons.settings, title: "Settings")
List<SideBarTiles> getNavbarTileList(AppLocalizations l10n) => [
SideBarTiles(icon: SpotubeIcons.home, title: l10n.browse),
SideBarTiles(icon: SpotubeIcons.search, title: l10n.search),
SideBarTiles(icon: SpotubeIcons.library, title: l10n.library),
SideBarTiles(icon: SpotubeIcons.settings, title: l10n.settings)
];

View File

@ -77,4 +77,5 @@ abstract class SpotubeIcons {
static const dragHandle = Icons.drag_indicator;
static const lightning = Icons.flash_on_rounded;
static const colorSync = FeatherIcons.activity;
static const language = FeatherIcons.globe;
}

View File

@ -9,6 +9,7 @@ import 'package:spotube/collections/assets.gen.dart';
import 'package:spotube/collections/side_bar_tiles.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/use_breakpoints.dart';
import 'package:spotube/hooks/use_brightness_value.dart';
import 'package:spotube/hooks/use_sidebarx_controller.dart';
@ -70,6 +71,9 @@ class Sidebar extends HookConsumerWidget {
Color.lerp(bg, Colors.black, 0.45)!,
);
final sidebarTileList =
useMemoized(() => getSidebarTileList(context.l10n), [context.l10n]);
useEffect(() {
controller.addListener(() {
onSelectedIndexChanged(controller.selectedIndex);
@ -263,7 +267,7 @@ class SidebarFooter extends HookConsumerWidget {
const SizedBox(width: 10),
Flexible(
child: Text(
data.displayName ?? "Guest",
data.displayName ?? context.l10n.guest,
maxLines: 1,
softWrap: false,
overflow: TextOverflow.fade,

View File

@ -7,6 +7,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/collections/side_bar_tiles.dart';
import 'package:spotube/components/root/sidebar.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/use_breakpoints.dart';
import 'package:spotube/hooks/use_brightness_value.dart';
import 'package:spotube/provider/downloader_provider.dart';
@ -39,6 +40,9 @@ class SpotubeNavigationBar extends HookConsumerWidget {
theme.colorScheme.primary.withOpacity(0.2),
);
final navbarTileList =
useMemoized(() => getNavbarTileList(context.l10n), [context.l10n]);
useEffect(() {
insideSelectedIndex.value = selectedIndex;
return null;

View File

@ -0,0 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
extension AppLocale on BuildContext {
AppLocalizations get l10n => AppLocalizations.of(this)!;
}

8
lib/l10n/app_bn.arb Normal file
View File

@ -0,0 +1,8 @@
{
"guest": "অতিথি",
"browse": "ব্রাউজ করুন",
"search": "অনুসন্ধান করুন",
"library": "লাইব্রেরী",
"lyrics": "গানের কথা",
"settings": "সেটিংস"
}

8
lib/l10n/app_en.arb Normal file
View File

@ -0,0 +1,8 @@
{
"guest": "Guest",
"browse": "Browse",
"search": "Search",
"library": "Library",
"lyrics": "Lyrics",
"settings": "Settings"
}

8
lib/l10n/l10n.dart Normal file
View File

@ -0,0 +1,8 @@
import 'package:flutter/material.dart';
class L10n {
static final all = [
const Locale('en'),
const Locale('bn', 'BD'),
];
}

View File

@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:metadata_god/metadata_god.dart';
@ -17,6 +18,7 @@ import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart
import 'package:spotube/entities/cache_track.dart';
import 'package:spotube/collections/routes.dart';
import 'package:spotube/collections/intents.dart';
import 'package:spotube/l10n/l10n.dart';
import 'package:spotube/models/logger.dart';
import 'package:spotube/provider/downloader_provider.dart';
import 'package:spotube/provider/palette_provider.dart';
@ -29,6 +31,7 @@ import 'package:spotube/utils/persisted_state_notifier.dart';
import 'package:system_theme/system_theme.dart';
import 'package:path_provider/path_provider.dart';
import 'package:spotube/hooks/use_init_sys_tray.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
Future<void> main(List<String> rawArgs) async {
final parser = ArgParser();
@ -189,6 +192,7 @@ class SpotubeState extends ConsumerState<Spotube> {
ref.watch(userPreferencesProvider.select((s) => s.themeMode));
final accentMaterialColor =
ref.watch(userPreferencesProvider.select((s) => s.accentColorScheme));
final locale = ref.watch(userPreferencesProvider.select((s) => s.locale));
final paletteColor =
ref.watch(paletteProvider.select((s) => s?.dominantColor?.color));
@ -203,6 +207,14 @@ class SpotubeState extends ConsumerState<Spotube> {
}, []);
return MaterialApp.router(
supportedLocales: L10n.all,
locale: locale.languageCode == "system" ? null : locale,
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
routeInformationParser: router.routeInformationParser,
routerDelegate: router.routerDelegate,
routeInformationProvider: router.routeInformationProvider,

View File

@ -12,6 +12,7 @@ import 'package:spotube/components/settings/color_scheme_picker_dialog.dart';
import 'package:spotube/components/shared/adaptive/adaptive_list_tile.dart';
import 'package:spotube/components/shared/page_window_title_bar.dart';
import 'package:spotube/collections/spotify_markets.dart';
import 'package:spotube/l10n/l10n.dart';
import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/provider/downloader_provider.dart';
import 'package:spotube/provider/user_preferences_provider.dart';
@ -127,6 +128,60 @@ class SettingsPage extends HookConsumerWidget {
),
);
}),
Text(
" Language & Region",
style: theme.textTheme.headlineSmall
?.copyWith(fontWeight: FontWeight.bold),
),
ListTile(
leading: const Icon(SpotubeIcons.language),
title: const Text("Language"),
trailing: DropdownButton<Locale>(
value: preferences.locale,
items: [
const DropdownMenuItem(
value: Locale("system"),
child: Text("System Default"),
),
for (final locale in L10n.all)
DropdownMenuItem(
value: locale,
child: Text(locale.languageCode),
),
],
onChanged: (value) {
if (value != null) {
preferences.setLocale(value);
}
},
),
),
AdaptiveListTile(
leading: const Icon(SpotubeIcons.shoppingBag),
title: const Text("Market Place Region"),
subtitle: const Text("Recommendation Country"),
trailing: (context, update) => ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 350),
child: DropdownMenu(
initialSelection: preferences.recommendationMarket,
dropdownMenuEntries: spotifyMarkets
.map(
(country) => DropdownMenuEntry(
value: country.first,
label: country.last,
),
)
.toList(),
onSelected: (value) {
if (value == null) return;
preferences.setRecommendationMarket(
value as String,
);
update?.call(() {});
},
),
),
),
Text(
" Appearance",
style: theme.textTheme.headlineSmall
@ -273,37 +328,6 @@ class SettingsPage extends HookConsumerWidget {
},
trailing: const Icon(SpotubeIcons.angleRight),
),
Text(
" Search",
style: theme.textTheme.headlineSmall
?.copyWith(fontWeight: FontWeight.bold),
),
AdaptiveListTile(
leading: const Icon(SpotubeIcons.shoppingBag),
title: const Text("Market Place"),
subtitle: const Text("Recommendation Country"),
trailing: (context, update) => ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 350),
child: DropdownMenu(
initialSelection: preferences.recommendationMarket,
dropdownMenuEntries: spotifyMarkets
.map(
(country) => DropdownMenuEntry(
value: country.first,
label: country.last,
),
)
.toList(),
onSelected: (value) {
if (value == null) return;
preferences.setRecommendationMarket(
value as String,
);
update?.call(() {});
},
),
),
),
Text(
" Downloads",
style: theme.textTheme.headlineSmall

View File

@ -48,6 +48,8 @@ class UserPreferences extends PersistedChangeNotifier {
bool showSystemTrayIcon;
Locale locale;
final Ref ref;
UserPreferences(
@ -65,6 +67,7 @@ class UserPreferences extends PersistedChangeNotifier {
this.downloadLocation = "",
this.closeBehavior = CloseBehavior.minimizeToTray,
this.showSystemTrayIcon = true,
this.locale = const Locale("system"),
}) : super() {
if (downloadLocation.isEmpty) {
_getDefaultDownloadDirectory().then(
@ -159,6 +162,12 @@ class UserPreferences extends PersistedChangeNotifier {
updatePersistence();
}
void setLocale(Locale locale) {
this.locale = locale;
notifyListeners();
updatePersistence();
}
Future<String> _getDefaultDownloadDirectory() async {
if (kIsAndroid) return "/storage/emulated/0/Download/Spotube";
@ -201,6 +210,11 @@ class UserPreferences extends PersistedChangeNotifier {
: closeBehavior;
showSystemTrayIcon = map["showSystemTrayIcon"] ?? showSystemTrayIcon;
locale = Locale(
map["locale"]?["lc"] ?? locale.languageCode,
map["locale"]?["cc"] ?? locale.countryCode,
);
}
@override
@ -219,6 +233,7 @@ class UserPreferences extends PersistedChangeNotifier {
"predownload": predownload,
"closeBehavior": closeBehavior.index,
"showSystemTrayIcon": showSystemTrayIcon,
"locale": {"lc": locale.languageCode, "cc": locale.countryCode},
};
}
}

View File

@ -467,7 +467,7 @@ packages:
source: hosted
version: "1.1.0"
dbus:
dependency: "direct main"
dependency: transitive
description:
name: dbus
sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263"
@ -701,6 +701,11 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
flutter_localizations:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_mailer:
dependency: transitive
description:
@ -946,7 +951,7 @@ packages:
source: sdk
version: "0.0.0"
intl:
dependency: transitive
dependency: "direct main"
description:
name: intl
sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"

View File

@ -32,9 +32,15 @@ dependencies:
flutter:
sdk: flutter
flutter_cache_manager: ^3.3.0
flutter_desktop_tools:
git:
url: https://github.com/KRTirtho/flutter_desktop_tools.git
ref: 1f0bec3283626dcbd8ee2f54e238d096d8dea50e
flutter_feather_icons: ^2.0.0+1
flutter_hooks: ^0.18.2+1
flutter_inappwebview: ^5.7.2+3
flutter_localizations:
sdk: flutter
flutter_riverpod: ^2.1.1
flutter_secure_storage: ^8.0.0
flutter_svg: ^1.1.6
@ -45,12 +51,16 @@ dependencies:
hooks_riverpod: ^2.1.1
html: ^0.15.1
http: ^0.13.5
intl: ^0.17.0
introduction_screen: ^3.0.2
json_annotation: ^4.8.0
json_serializable: ^6.6.0
logger: ^1.1.0
metadata_god: ^0.4.1
mime: ^1.0.2
mpris_service:
git:
url: https://github.com/alexmercerind/mpris_service
package_info_plus: ^3.0.2
palette_generator: ^0.3.3
path: ^1.8.0
@ -64,6 +74,11 @@ dependencies:
sidebarx: ^0.15.0
simple_circular_progress_bar: ^1.0.2
skeleton_text: ^3.0.0
smtc_windows:
git:
url: https://github.com/KRTirtho/smtc_windows.git
ref: 6cc93624b8fab8d7727c8693e91577a7413ccd13
path: packages/smtc_windows
spotify: ^0.11.0
system_theme: ^2.1.0
titlebar_buttons: ^1.0.0
@ -79,18 +94,6 @@ dependencies:
ref: a738913c8ce2c9f47515382d40827e794a334274
path: plugins/window_size
youtube_explode_dart: ^1.12.1
flutter_desktop_tools:
git:
url: https://github.com/KRTirtho/flutter_desktop_tools.git
ref: 1f0bec3283626dcbd8ee2f54e238d096d8dea50e
smtc_windows:
git:
url: https://github.com/KRTirtho/smtc_windows.git
ref: 6cc93624b8fab8d7727c8693e91577a7413ccd13
path: packages/smtc_windows
mpris_service:
git:
url: https://github.com/alexmercerind/mpris_service
dev_dependencies:
build_runner: ^2.3.2
@ -111,6 +114,7 @@ dependency_overrides:
package_info_plus: ^3.0.2
flutter:
generate: true
uses-material-design: true
assets:
- assets/