diff --git a/lib/components/artist/artist_card.dart b/lib/components/artist/artist_card.dart index 9f1036375..77e22c226 100644 --- a/lib/components/artist/artist_card.dart +++ b/lib/components/artist/artist_card.dart @@ -4,6 +4,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/shared/image/universal_image.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/use_breakpoint_value.dart'; import 'package:spotube/hooks/use_brightness_value.dart'; import 'package:spotube/provider/blacklist_provider.dart'; @@ -89,9 +90,9 @@ class ArtistCard extends HookConsumerWidget { decoration: BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.circular(50)), - child: const Text( - "Artist", - style: TextStyle( + child: Text( + context.l10n.artist, + style: const TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold, diff --git a/lib/components/library/user_albums.dart b/lib/components/library/user_albums.dart index c67f5eafa..fb722cc54 100644 --- a/lib/components/library/user_albums.dart +++ b/lib/components/library/user_albums.dart @@ -8,6 +8,7 @@ import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/components/album/album_card.dart'; import 'package:spotube/components/shared/shimmers/shimmer_playbutton_card.dart'; import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/use_breakpoint_value.dart'; import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/services/queries/queries.dart'; @@ -71,9 +72,9 @@ class UserAlbums extends HookConsumerWidget { children: [ TextField( onChanged: (value) => searchText.value = value, - decoration: const InputDecoration( - prefixIcon: Icon(SpotubeIcons.filter), - hintText: 'Filter albums...', + decoration: InputDecoration( + prefixIcon: const Icon(SpotubeIcons.filter), + hintText: context.l10n.filter_albums, ), ), const SizedBox(height: 20), diff --git a/lib/components/library/user_artists.dart b/lib/components/library/user_artists.dart index dd5dc6878..e22c4d50b 100644 --- a/lib/components/library/user_artists.dart +++ b/lib/components/library/user_artists.dart @@ -9,6 +9,7 @@ import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart'; import 'package:spotube/components/shared/waypoint.dart'; import 'package:spotube/components/artist/artist_card.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/services/queries/queries.dart'; import 'package:tuple/tuple.dart'; @@ -62,9 +63,9 @@ class UserArtists extends HookConsumerWidget { color: theme.scaffoldBackgroundColor, child: TextField( onChanged: (value) => searchText.value = value, - decoration: const InputDecoration( - prefixIcon: Icon(SpotubeIcons.filter), - hintText: 'Filter artists...', + decoration: InputDecoration( + prefixIcon: const Icon(SpotubeIcons.filter), + hintText: context.l10n.filter_artist, ), ), ), @@ -76,10 +77,10 @@ class UserArtists extends HookConsumerWidget { padding: const EdgeInsets.all(20), child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: const [ - CircularProgressIndicator(), - SizedBox(width: 10), - Text("Loading..."), + children: [ + const CircularProgressIndicator(), + const SizedBox(width: 10), + Text(context.l10n.loading), ], ), ) diff --git a/lib/components/library/user_downloads.dart b/lib/components/library/user_downloads.dart index a5af4c2a9..f8ad1d70e 100644 --- a/lib/components/library/user_downloads.dart +++ b/lib/components/library/user_downloads.dart @@ -4,6 +4,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/shared/image/universal_image.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/downloader_provider.dart'; import 'package:spotube/utils/type_conversion_utils.dart'; @@ -24,7 +25,8 @@ class UserDownloads extends HookConsumerWidget { children: [ Expanded( child: AutoSizeText( - "Currently downloading (${downloader.currentlyRunning})", + context.l10n + .currently_downloading(downloader.currentlyRunning), maxLines: 1, style: Theme.of(context).textTheme.headlineMedium, ), @@ -38,7 +40,7 @@ class UserDownloads extends HookConsumerWidget { onPressed: downloader.currentlyRunning > 0 ? downloader.cancelAll : null, - child: const Text("Cancel All"), + child: Text(context.l10n.cancel_all), ), ], ), diff --git a/lib/components/library/user_local_tracks.dart b/lib/components/library/user_local_tracks.dart index 0df439b27..020764350 100644 --- a/lib/components/library/user_local_tracks.dart +++ b/lib/components/library/user_local_tracks.dart @@ -19,6 +19,7 @@ import 'package:spotube/components/shared/compact_search.dart'; import 'package:spotube/components/shared/shimmers/shimmer_track_tile.dart'; import 'package:spotube/components/shared/sort_tracks_dropdown.dart'; import 'package:spotube/components/shared/track_table/track_tile.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/use_async_effect.dart'; import 'package:spotube/models/local_track.dart'; import 'package:spotube/provider/playlist_queue_provider.dart'; @@ -175,9 +176,9 @@ class UserLocalTracks extends HookConsumerWidget { [], ); - var searchbar = CompactSearch( + final searchbar = CompactSearch( onChanged: (value) => searchText.value = value, - placeholder: "Search local tracks...", + placeholder: context.l10n.search_local_tracks, ); return Column( @@ -202,7 +203,7 @@ class UserLocalTracks extends HookConsumerWidget { : null, child: Row( children: [ - const Text("Play"), + Text(context.l10n.play), Icon( isPlaylistPlaying ? SpotubeIcons.stop : SpotubeIcons.play, ) @@ -294,9 +295,9 @@ class UserLocalTracks extends HookConsumerWidget { ref.refresh(localTracksProvider); }, padding: EdgeInsets.zero, - child: const ListTile( - leading: Icon(SpotubeIcons.trash), - title: Text("Delete"), + child: ListTile( + leading: const Icon(SpotubeIcons.trash), + title: Text(context.l10n.delete), ), ), ]; diff --git a/lib/components/library/user_playlists.dart b/lib/components/library/user_playlists.dart index 6d1c18c49..4e6e551c6 100644 --- a/lib/components/library/user_playlists.dart +++ b/lib/components/library/user_playlists.dart @@ -10,6 +10,7 @@ import 'package:spotube/components/playlist/playlist_create_dialog.dart'; import 'package:spotube/components/shared/shimmers/shimmer_playbutton_card.dart'; import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart'; import 'package:spotube/components/playlist/playlist_card.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/use_breakpoint_value.dart'; import 'package:spotube/hooks/use_breakpoints.dart'; import 'package:spotube/provider/authentication_provider.dart'; @@ -33,8 +34,8 @@ class UserPlaylists extends HookConsumerWidget { final likedTracksPlaylist = useMemoized( () => PlaylistSimple() - ..name = "Liked Tracks" - ..description = "All your liked tracks" + ..name = context.l10n.liked_tracks + ..description = context.l10n.liked_tracks_description ..type = "playlist" ..collaborative = false ..public = false @@ -46,7 +47,7 @@ class UserPlaylists extends HookConsumerWidget { ..url = "https://t.scdn.co/images/3099b3803ad9496896c43f22fe9be8c4.png" ], - []); + [context.l10n]); final playlists = useMemoized( () { @@ -87,9 +88,9 @@ class UserPlaylists extends HookConsumerWidget { padding: const EdgeInsets.all(10), child: TextField( onChanged: (value) => searchText.value = value, - decoration: const InputDecoration( - hintText: "Filter your playlists...", - prefixIcon: Icon(SpotubeIcons.filter), + decoration: InputDecoration( + hintText: context.l10n.filter_playlists, + prefixIcon: const Icon(SpotubeIcons.filter), ), ), ), diff --git a/lib/components/playlist/playlist_create_dialog.dart b/lib/components/playlist/playlist_create_dialog.dart index eb5af8f0a..f61a662fa 100644 --- a/lib/components/playlist/playlist_create_dialog.dart +++ b/lib/components/playlist/playlist_create_dialog.dart @@ -4,6 +4,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/collections/spotube_icons.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/spotify_provider.dart'; class PlaylistCreateDialog extends HookConsumerWidget { @@ -18,7 +19,7 @@ class PlaylistCreateDialog extends HookConsumerWidget { foregroundColor: Theme.of(context).colorScheme.primary, ), icon: const Icon(SpotubeIcons.addFilled), - label: const Text("Create Playlist"), + label: Text(context.l10n.create_playlist), onPressed: () { showDialog( context: context, @@ -50,17 +51,17 @@ class PlaylistCreateDialog extends HookConsumerWidget { } return AlertDialog( - title: const Text("Create a Playlist"), + title: Text(context.l10n.create_a_playlist), actions: [ OutlinedButton( - child: const Text("Cancel"), + child: Text(context.l10n.cancel), onPressed: () { Navigator.pop(context); }, ), FilledButton( onPressed: onCreate, - child: const Text("Create"), + child: Text(context.l10n.create), ), ], content: Container( @@ -71,29 +72,29 @@ class PlaylistCreateDialog extends HookConsumerWidget { children: [ TextField( controller: playlistName, - decoration: const InputDecoration( - hintText: "Name of the playlist", - labelText: "Playlist Name", + decoration: InputDecoration( + hintText: context.l10n.name_of_playlist, + labelText: context.l10n.name_of_playlist, ), ), const SizedBox(height: 10), TextField( controller: description, - decoration: const InputDecoration( - hintText: "Description...", + decoration: InputDecoration( + hintText: context.l10n.description, ), keyboardType: TextInputType.multiline, maxLines: 5, ), const SizedBox(height: 10), CheckboxListTile( - title: const Text("Public"), + title: Text(context.l10n.public), value: public.value, onChanged: (val) => public.value = val ?? false, ), const SizedBox(height: 10), CheckboxListTile( - title: const Text("Collaborative"), + title: Text(context.l10n.collaborative), value: collaborative.value, onChanged: (val) => collaborative.value = val ?? false, ), diff --git a/lib/components/shared/sort_tracks_dropdown.dart b/lib/components/shared/sort_tracks_dropdown.dart index a5c5eccfd..a73bf8ed3 100644 --- a/lib/components/shared/sort_tracks_dropdown.dart +++ b/lib/components/shared/sort_tracks_dropdown.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/components/library/user_local_tracks.dart'; +import 'package:spotube/extensions/context.dart'; class SortTracksDropdown extends StatelessWidget { final SortBy? value; @@ -20,37 +21,37 @@ class SortTracksDropdown extends StatelessWidget { PopupMenuItem( value: SortBy.none, enabled: value != SortBy.none, - child: const Text("None"), + child: Text(context.l10n.none), ), PopupMenuItem( value: SortBy.ascending, enabled: value != SortBy.ascending, - child: const Text("Sort by A-Z"), + child: Text(context.l10n.sort_a_z), ), PopupMenuItem( value: SortBy.descending, enabled: value != SortBy.descending, - child: const Text("Sort by Z-A"), + child: Text(context.l10n.sort_z_a), ), PopupMenuItem( value: SortBy.dateAdded, enabled: value != SortBy.dateAdded, - child: const Text("Sort by Date"), + child: Text(context.l10n.sort_date), ), PopupMenuItem( value: SortBy.artist, enabled: value != SortBy.artist, - child: const Text("Sort by Artist"), + child: Text(context.l10n.sort_artist), ), PopupMenuItem( value: SortBy.album, enabled: value != SortBy.album, - child: const Text("Sort by Album"), + child: Text(context.l10n.sort_album), ), ]; }, onSelected: onChanged, - tooltip: "Sort tracks", + tooltip: context.l10n.sort_tracks, icon: const Icon(SpotubeIcons.sort), ); } diff --git a/lib/l10n/app_bn.arb b/lib/l10n/app_bn.arb index 338f6c754..5c9265795 100644 --- a/lib/l10n/app_bn.arb +++ b/lib/l10n/app_bn.arb @@ -16,5 +16,46 @@ "load_more": "আরো লোড করুন", "playlists": "প্লেলিস্ট", "artists": "শিল্পী", - "albums": "অ্যালবাম" + "albums": "অ্যালবাম", + "tracks": "গানের ট্র্যাক", + "downloads": "ডাউনলোড", + "filter_playlists": "প্লেলিস্ট অনুসন্ধান করুন...", + "liked_tracks": "পছন্দের গান", + "liked_tracks_description": "আপনার পছন্দের গান সমূহ", + "create_playlist": "প্লেলিস্ট তৈরি করুন", + "create_a_playlist": "একটি প্লেলিস্ট তৈরি করুন", + "create": "তৈরি করুন", + "cancel": "বাতিল করুন", + "playlist_name": "প্লেলিস্টের নাম", + "name_of_playlist": "প্লেলিস্টের নাম", + "description": "বিবরণ", + "public": "পাবলিক", + "collaborative": "সহযোগিতামূলক", + "search_local_tracks": "ডাউনলোডকৃত গান অনুসন্ধান করুন...", + "play": "চালান", + "delete": "মুছে ফেলুন", + "none": "কোনটিই না", + "sort_a_z": "A-Z ক্রমে সাজান", + "sort_z_a": "Z-A ক্রমে সাজান", + "sort_date": "তারিখের ক্রমে সাজান", + "sort_artist": "শিল্পীর ক্রমে সাজান", + "sort_album": "অ্যালবামের ক্রমে সাজান", + "sort_tracks": "গানের ক্রম", + "currently_downloading": "ডাউনলোড করা হচ্ছে ({tracks_length})", + "cancel_all": "সব বাতিল করুন", + "filter_artist": "শিল্পীর অনুসন্ধান করুন...", + "followers": "{followers} অনুসরণকারী", + "add_artist_to_blacklist": "শিল্পীকে ব্ল্যাকলিস্টে যোগ করুন", + "top_tracks": "শীর্ষ গানের ট্র্যাক", + "fans_also_like": "অনুসরণকারীদের পছন্দ", + "loading": "লোড হচ্ছে...", + "artist": "শিল্পী", + "blacklisted": "ব্ল্যাকলিস্টে আছে", + "following": "অনুসরণ করছেন", + "follow": "অনুসরণ করুন", + "artist_url_copied": "শিল্পীর URL কপি করা হয়েছে", + "added_to_queue": "{tracks}টি গানের ট্র্যাক কিউতে যোগ করা হয়েছে", + "filter_albums": "অ্যালবাম অনুসন্ধান করুন...", + "synced": "সময়ের সাথে সুসংগত", + "plain": "অসুসংগত" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ec6b7aa32..01b8b4474 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -16,5 +16,46 @@ "load_more": "Load more", "playlists": "Playlists", "artists": "Artists", - "albums": "Albums" + "albums": "Albums", + "tracks": "Tracks", + "downloads": "Downloads", + "filter_playlists": "Filter your playlists...", + "liked_tracks": "Liked Tracks", + "liked_tracks_description": "All your liked tracks", + "create_playlist": "Create Playlist", + "create_a_playlist": "Create a playlist", + "create": "Create", + "cancel": "Cancel", + "playlist_name": "Playlist Name", + "name_of_playlist": "Name of the playlist", + "description": "Description", + "public": "Public", + "collaborative": "Collaborative", + "search_local_tracks": "Search local tracks...", + "play": "Play", + "delete": "Delete", + "none": "None", + "sort_a_z": "Sort by A-Z", + "sort_z_a": "Sort by Z-A", + "sort_date": "Sort by date", + "sort_artist": "Sort by Artist", + "sort_album": "Sort by Album", + "sort_tracks": "Sort Tracks", + "currently_downloading": "Currently Downloading ({tracks_length})", + "cancel_all": "Cancel All", + "filter_artist": "Filter artists...", + "followers": "{followers} Followers", + "add_artist_to_blacklist": "Add artist to blacklist", + "top_tracks": "Top Tracks", + "fans_also_like": "Fans also like", + "loading": "Loading...", + "artist": "Artist", + "blacklisted": "Blacklisted", + "following": "Following", + "follow": "Follow", + "artist_url_copied": "Artist URL copied to clipboard", + "added_to_queue": "Added {tracks} tracks to queue", + "filter_albums": "Filter albums...", + "synced": "Synced", + "plain": "Plain" } \ No newline at end of file diff --git a/lib/pages/artist/artist.dart b/lib/pages/artist/artist.dart index 5853808f4..1584cb159 100644 --- a/lib/pages/artist/artist.dart +++ b/lib/pages/artist/artist.dart @@ -12,6 +12,7 @@ import 'package:spotube/components/shared/track_table/track_tile.dart'; import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/artist/artist_album_list.dart'; import 'package:spotube/components/artist/artist_card.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/use_breakpoint_value.dart'; import 'package:spotube/hooks/use_breakpoints.dart'; import 'package:spotube/models/logger.dart'; @@ -142,7 +143,7 @@ class ArtistPage extends HookConsumerWidget { borderRadius: BorderRadius.circular(50)), child: Text( - "Blacklisted", + context.l10n.blacklisted, style: chipTextVariant.copyWith( color: Colors.white, ), @@ -158,7 +159,11 @@ class ArtistPage extends HookConsumerWidget { : textTheme.headlineMedium, ), Text( - "${PrimitiveUtils.toReadableNumber(data.followers!.total!.toDouble())} followers", + context.l10n.followers( + PrimitiveUtils.toReadableNumber( + data.followers!.total!.toDouble(), + ), + ), style: textTheme.bodyMedium?.copyWith( fontWeight: breakpoint.isSm ? null : FontWeight.bold, @@ -211,19 +216,20 @@ class ArtistPage extends HookConsumerWidget { if (isFollowingQuery.data!) { return OutlinedButton( onPressed: followUnfollow, - child: const Text("Following"), + child: Text(context.l10n.following), ); } return FilledButton( onPressed: followUnfollow, - child: const Text("Follow"), + child: Text(context.l10n.follow), ); }, ), const SizedBox(width: 5), IconButton( - tooltip: "Add to blacklisted artists", + tooltip: + context.l10n.add_artist_to_blacklist, icon: Icon( SpotubeIcons.userRemove, color: !isBlackListed @@ -263,12 +269,14 @@ class ArtistPage extends HookConsumerWidget { text: data.externalUrls?.spotify), ); + if (!context.mounted) return; + scaffoldMessenger.showSnackBar( - const SnackBar( + SnackBar( width: 300, behavior: SnackBarBehavior.floating, content: Text( - "Artist URL copied to clipboard", + context.l10n.artist_url_copied, textAlign: TextAlign.center, ), ), @@ -324,7 +332,7 @@ class ArtistPage extends HookConsumerWidget { Row( children: [ Text( - "Top Tracks", + context.l10n.top_tracks, style: theme.textTheme.headlineSmall, ), if (!isPlaylistPlaying) @@ -339,7 +347,9 @@ class ArtistPage extends HookConsumerWidget { width: 300, behavior: SnackBarBehavior.floating, content: Text( - "Added ${topTracks.length} tracks to queue", + context.l10n.added_to_queue( + topTracks.length, + ), textAlign: TextAlign.center, ), ), @@ -383,14 +393,14 @@ class ArtistPage extends HookConsumerWidget { ), const SizedBox(height: 50), Text( - "Albums", + context.l10n.albums, style: theme.textTheme.headlineSmall, ), const SizedBox(height: 10), ArtistAlbumList(artistId), const SizedBox(height: 20), Text( - "Fans also likes", + context.l10n.fans_also_like, style: theme.textTheme.headlineSmall, ), const SizedBox(height: 10), diff --git a/lib/pages/library/library.dart b/lib/pages/library/library.dart index 4bc04b660..2fbcef0fc 100644 --- a/lib/pages/library/library.dart +++ b/lib/pages/library/library.dart @@ -8,12 +8,13 @@ import 'package:spotube/components/library/user_artists.dart'; import 'package:spotube/components/library/user_downloads.dart'; import 'package:spotube/components/library/user_playlists.dart'; import 'package:spotube/components/shared/themed_button_tab_bar.dart'; +import 'package:spotube/extensions/context.dart'; class LibraryPage extends HookConsumerWidget { const LibraryPage({Key? key}) : super(key: key); @override Widget build(BuildContext context, ref) { - return const DefaultTabController( + return DefaultTabController( length: 5, child: SafeArea( bottom: false, @@ -22,16 +23,16 @@ class LibraryPage extends HookConsumerWidget { centerTitle: true, leading: ThemedButtonsTabBar( tabs: [ - 'Playlists', - 'Tracks', - 'Downloads', - 'Artists', - 'Albums', + context.l10n.playlists, + context.l10n.tracks, + context.l10n.downloads, + context.l10n.artists, + context.l10n.albums, ], ), leadingWidth: double.infinity, ), - body: TabBarView( + body: const TabBarView( children: [ UserPlaylists(), UserLocalTracks(), diff --git a/lib/pages/lyrics/lyrics.dart b/lib/pages/lyrics/lyrics.dart index c69cecb6f..ac5a78628 100644 --- a/lib/pages/lyrics/lyrics.dart +++ b/lib/pages/lyrics/lyrics.dart @@ -9,6 +9,7 @@ import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart'; import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/themed_button_tab_bar.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/use_breakpoints.dart'; import 'package:spotube/hooks/use_custom_status_bar_color.dart'; import 'package:spotube/hooks/use_palette_color.dart'; @@ -43,10 +44,10 @@ class LyricsPage extends HookConsumerWidget { noSetBGColor: true, ); - const tabbar = ThemedButtonsTabBar( + final tabbar = ThemedButtonsTabBar( tabs: [ - "Synced", - "Plain", + context.l10n.synced, + context.l10n.plain, ], ); @@ -120,7 +121,7 @@ class LyricsPage extends HookConsumerWidget { child: Scaffold( extendBodyBehindAppBar: true, appBar: !kIsMacOS - ? const PageWindowTitleBar( + ? PageWindowTitleBar( backgroundColor: Colors.transparent, title: tabbar, )