feat(locale): player, playlist view, track tile bengali and english translations

This commit is contained in:
Kingkor Roy Tirtho 2023-04-29 11:01:16 +06:00
parent 11fe9ec744
commit c55133dc8b
9 changed files with 173 additions and 59 deletions

View File

@ -8,6 +8,7 @@ import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/player/player_queue.dart'; import 'package:spotube/components/player/player_queue.dart';
import 'package:spotube/components/player/sibling_tracks_sheet.dart'; import 'package:spotube/components/player/sibling_tracks_sheet.dart';
import 'package:spotube/components/shared/heart_button.dart'; import 'package:spotube/components/shared/heart_button.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/models/local_track.dart'; import 'package:spotube/models/local_track.dart';
import 'package:spotube/models/logger.dart'; import 'package:spotube/models/logger.dart';
import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/provider/authentication_provider.dart';
@ -55,7 +56,7 @@ class PlayerActions extends HookConsumerWidget {
children: [ children: [
IconButton( IconButton(
icon: const Icon(SpotubeIcons.queue), icon: const Icon(SpotubeIcons.queue),
tooltip: 'Queue', tooltip: context.l10n.queue,
onPressed: playlist != null onPressed: playlist != null
? () { ? () {
showModalBottomSheet( showModalBottomSheet(
@ -81,7 +82,7 @@ class PlayerActions extends HookConsumerWidget {
if (!isLocalTrack) if (!isLocalTrack)
IconButton( IconButton(
icon: const Icon(SpotubeIcons.alternativeRoute), icon: const Icon(SpotubeIcons.alternativeRoute),
tooltip: "Alternative Track Sources", tooltip: context.l10n.alternative_track_sources,
onPressed: playlist?.activeTrack != null onPressed: playlist?.activeTrack != null
? () { ? () {
showModalBottomSheet( showModalBottomSheet(
@ -115,7 +116,7 @@ class PlayerActions extends HookConsumerWidget {
) )
else else
IconButton( IconButton(
tooltip: 'Download track', tooltip: context.l10n.download_track,
icon: Icon( icon: Icon(
isDownloaded ? SpotubeIcons.done : SpotubeIcons.download, isDownloaded ? SpotubeIcons.done : SpotubeIcons.download,
), ),

View File

@ -6,6 +6,7 @@ import 'package:palette_generator/palette_generator.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/collections/intents.dart'; import 'package:spotube/collections/intents.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/use_progress.dart'; import 'package:spotube/hooks/use_progress.dart';
import 'package:spotube/models/logger.dart'; import 'package:spotube/models/logger.dart';
import 'package:spotube/provider/playlist_queue_provider.dart'; import 'package:spotube/provider/playlist_queue_provider.dart';
@ -133,7 +134,7 @@ class PlayerControls extends HookConsumerWidget {
return Column( return Column(
children: [ children: [
Tooltip( Tooltip(
message: "Slide to seek forward or backward", message: context.l10n.slide_to_seek,
child: Slider( child: Slider(
// cannot divide by zero // cannot divide by zero
// there's an edge case for value being bigger // there's an edge case for value being bigger
@ -181,8 +182,8 @@ class PlayerControls extends HookConsumerWidget {
children: [ children: [
IconButton( IconButton(
tooltip: playlist?.isShuffled == true tooltip: playlist?.isShuffled == true
? "Unshuffle playlist" ? context.l10n.unshuffle_playlist
: "Shuffle playlist", : context.l10n.shuffle_playlist,
icon: const Icon(SpotubeIcons.shuffle), icon: const Icon(SpotubeIcons.shuffle),
style: playlist?.isShuffled == true style: playlist?.isShuffled == true
? activeButtonStyle ? activeButtonStyle
@ -198,13 +199,15 @@ class PlayerControls extends HookConsumerWidget {
}, },
), ),
IconButton( IconButton(
tooltip: "Previous track", tooltip: context.l10n.previous_track,
icon: const Icon(SpotubeIcons.skipBack), icon: const Icon(SpotubeIcons.skipBack),
style: buttonStyle, style: buttonStyle,
onPressed: playlistNotifier.previous, onPressed: playlistNotifier.previous,
), ),
IconButton( IconButton(
tooltip: playing ? "Pause playback" : "Resume playback", tooltip: playing
? context.l10n.pause_playback
: context.l10n.resume_playback,
icon: playlist?.isLoading == true icon: playlist?.isLoading == true
? SizedBox( ? SizedBox(
height: 20, height: 20,
@ -224,15 +227,15 @@ class PlayerControls extends HookConsumerWidget {
), ),
), ),
IconButton( IconButton(
tooltip: "Next track", tooltip: context.l10n.next_track,
icon: const Icon(SpotubeIcons.skipForward), icon: const Icon(SpotubeIcons.skipForward),
style: buttonStyle, style: buttonStyle,
onPressed: playlistNotifier.next, onPressed: playlistNotifier.next,
), ),
IconButton( IconButton(
tooltip: playlist?.isLooping != true tooltip: playlist?.isLooping != true
? "Loop Track" ? context.l10n.loop_track
: "Repeat playlist", : context.l10n.repeat_playlist,
icon: Icon( icon: Icon(
playlist?.isLooping == true playlist?.isLooping == true
? SpotubeIcons.repeatOne ? SpotubeIcons.repeatOne

View File

@ -12,6 +12,7 @@ import 'package:spotube/components/player/player_actions.dart';
import 'package:spotube/components/player/player_overlay.dart'; import 'package:spotube/components/player/player_overlay.dart';
import 'package:spotube/components/player/player_track_details.dart'; import 'package:spotube/components/player/player_track_details.dart';
import 'package:spotube/components/player/player_controls.dart'; import 'package:spotube/components/player/player_controls.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/use_breakpoints.dart'; import 'package:spotube/hooks/use_breakpoints.dart';
import 'package:spotube/hooks/use_brightness_value.dart'; import 'package:spotube/hooks/use_brightness_value.dart';
import 'package:spotube/models/logger.dart'; import 'package:spotube/models/logger.dart';
@ -130,7 +131,7 @@ class BottomPlayer extends HookConsumerWidget {
PlayerActions( PlayerActions(
extraActions: [ extraActions: [
IconButton( IconButton(
tooltip: 'Mini Player', tooltip: context.l10n.mini_player,
icon: const Icon(SpotubeIcons.miniPlayer), icon: const Icon(SpotubeIcons.miniPlayer),
onPressed: () async { onPressed: () async {
await DesktopTools.window.setMinimumSize( await DesktopTools.window.setMinimumSize(

View File

@ -4,6 +4,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/use_palette_color.dart'; import 'package:spotube/hooks/use_palette_color.dart';
import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/services/mutations/mutations.dart'; import 'package:spotube/services/mutations/mutations.dart';
@ -120,7 +121,9 @@ class TrackHeartButton extends HookConsumerWidget {
} }
return HeartButton( return HeartButton(
tooltip: toggler.item1 ? "Remove from Favorite" : "Add to Favorite", tooltip: toggler.item1
? context.l10n.remove_from_favorites
: context.l10n.save_as_favorite,
isLiked: toggler.item1, isLiked: toggler.item1,
onPressed: savedTracks.hasData onPressed: savedTracks.hasData
? () { ? () {
@ -174,8 +177,8 @@ class PlaylistHeartButton extends HookConsumerWidget {
return HeartButton( return HeartButton(
isLiked: isLikedQuery.data ?? false, isLiked: isLikedQuery.data ?? false,
tooltip: isLikedQuery.data ?? false tooltip: isLikedQuery.data ?? false
? "Remove from Favorite" ? context.l10n.remove_from_favorites
: "Add to Favorite", : context.l10n.save_as_favorite,
color: color?.titleTextColor, color: color?.titleTextColor,
onPressed: isLikedQuery.hasData onPressed: isLikedQuery.hasData
? () { ? () {
@ -216,7 +219,9 @@ class AlbumHeartButton extends HookConsumerWidget {
return HeartButton( return HeartButton(
isLiked: isLiked, isLiked: isLiked,
tooltip: isLiked ? "Remove from Favorite" : "Add to Favorite", tooltip: isLiked
? context.l10n.remove_from_favorites
: context.l10n.save_as_favorite,
onPressed: albumIsSaved.hasData onPressed: albumIsSaved.hasData
? () { ? () {
toggleAlbumLike.mutate(isLiked); toggleAlbumLike.mutate(isLiked);

View File

@ -13,6 +13,7 @@ import 'package:spotube/components/shared/shimmers/shimmer_track_tile.dart';
import 'package:spotube/components/shared/page_window_title_bar.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/image/universal_image.dart';
import 'package:spotube/components/shared/track_table/tracks_table_view.dart'; import 'package:spotube/components/shared/track_table/tracks_table_view.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/use_custom_status_bar_color.dart'; import 'package:spotube/hooks/use_custom_status_bar_color.dart';
import 'package:spotube/hooks/use_palette_color.dart'; import 'package:spotube/hooks/use_palette_color.dart';
import 'package:spotube/models/logger.dart'; import 'package:spotube/models/logger.dart';
@ -80,7 +81,7 @@ class TrackCollectionView<T> extends HookConsumerWidget {
), ),
if (heartBtn != null && auth != null) heartBtn!, if (heartBtn != null && auth != null) heartBtn!,
IconButton( IconButton(
tooltip: "Shuffle", tooltip: context.l10n.shuffle,
icon: Icon( icon: Icon(
SpotubeIcons.shuffle, SpotubeIcons.shuffle,
color: color?.titleTextColor, color: color?.titleTextColor,
@ -166,7 +167,7 @@ class TrackCollectionView<T> extends HookConsumerWidget {
onChanged: (value) => searchText.value = value, onChanged: (value) => searchText.value = value,
style: TextStyle(color: color?.titleTextColor), style: TextStyle(color: color?.titleTextColor),
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search tracks...", hintText: context.l10n.search_tracks,
hintStyle: TextStyle(color: color?.titleTextColor), hintStyle: TextStyle(color: color?.titleTextColor),
border: theme.inputDecorationTheme.border?.copyWith( border: theme.inputDecorationTheme.border?.copyWith(
borderSide: BorderSide( borderSide: BorderSide(
@ -211,7 +212,7 @@ class TrackCollectionView<T> extends HookConsumerWidget {
if (kIsMobile) if (kIsMobile)
CompactSearch( CompactSearch(
onChanged: (value) => searchText.value = value, onChanged: (value) => searchText.value = value,
placeholder: "Search tracks...", placeholder: context.l10n.search_tracks,
iconColor: color?.titleTextColor, iconColor: color?.titleTextColor,
), ),
if (collapsed.value) ...buttons, if (collapsed.value) ...buttons,
@ -287,7 +288,7 @@ class TrackCollectionView<T> extends HookConsumerWidget {
), ),
if (album != null) if (album != null)
Text( Text(
"${AlbumType.from(album?.albumType).formatted}Released${DateTime.tryParse( "${AlbumType.from(album?.albumType).formatted}${context.l10n.released}${DateTime.tryParse(
album?.releaseDate ?? "", album?.releaseDate ?? "",
)?.year}", )?.year}",
style: style:
@ -325,7 +326,10 @@ class TrackCollectionView<T> extends HookConsumerWidget {
return const ShimmerTrackTile(); return const ShimmerTrackTile();
} else if (tracksSnapshot.hasError) { } else if (tracksSnapshot.hasError) {
return SliverToBoxAdapter( return SliverToBoxAdapter(
child: Text("Error ${tracksSnapshot.error}")); child: Text(
context.l10n.error(tracksSnapshot.error ?? ""),
),
);
} }
return TracksTableView( return TracksTableView(

View File

@ -10,6 +10,7 @@ import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/heart_button.dart'; import 'package:spotube/components/shared/heart_button.dart';
import 'package:spotube/components/shared/links/link_text.dart'; import 'package:spotube/components/shared/links/link_text.dart';
import 'package:spotube/components/shared/image/universal_image.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_breakpoints.dart';
import 'package:spotube/models/logger.dart'; import 'package:spotube/models/logger.dart';
import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/provider/authentication_provider.dart';
@ -90,7 +91,7 @@ class TrackTile extends HookConsumerWidget {
width: 300, width: 300,
behavior: SnackBarBehavior.floating, behavior: SnackBarBehavior.floating,
content: Text( content: Text(
"Copied $data to clipboard", context.l10n.copied_to_clipboard(data),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
), ),
@ -114,7 +115,8 @@ class TrackTile extends HookConsumerWidget {
final playlistsCheck = useState(<String, bool>{}); final playlistsCheck = useState(<String, bool>{});
return AlertDialog( return AlertDialog(
title: Text( title: Text(
"Add `${track.value.name}` to following Playlists", context.l10n
.add_to_following_playlists(track.value.name!),
style: const TextStyle( style: const TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -122,11 +124,11 @@ class TrackTile extends HookConsumerWidget {
), ),
actions: [ actions: [
OutlinedButton( OutlinedButton(
child: const Text("Cancel"), child: Text(context.l10n.cancel),
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
), ),
FilledButton( FilledButton(
child: const Text("Add"), child: Text(context.l10n.add),
onPressed: () async { onPressed: () async {
final selectedPlaylists = playlistsCheck final selectedPlaylists = playlistsCheck
.value.entries .value.entries
@ -263,7 +265,7 @@ class TrackTile extends HookConsumerWidget {
if (isBlackListed) ...[ if (isBlackListed) ...[
const SizedBox(width: 5), const SizedBox(width: 5),
Text( Text(
"Blacklisted", context.l10n.blacklisted,
style: TextStyle( style: TextStyle(
color: Colors.red[400], color: Colors.red[400],
fontSize: 12, fontSize: 12,
@ -307,7 +309,7 @@ class TrackTile extends HookConsumerWidget {
PopupMenuButton( PopupMenuButton(
icon: const Icon(SpotubeIcons.moreHorizontal), icon: const Icon(SpotubeIcons.moreHorizontal),
position: PopupMenuPosition.under, position: PopupMenuPosition.under,
tooltip: "More options", tooltip: context.l10n.more_actions,
itemBuilder: (context) { itemBuilder: (context) {
return [ return [
if (!playlistQueueNotifier.isTrackOnQueue(track.value)) ...[ if (!playlistQueueNotifier.isTrackOnQueue(track.value)) ...[
@ -318,14 +320,15 @@ class TrackTile extends HookConsumerWidget {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text( content: Text(
"Added ${track.value.name} to queue", context.l10n
.added_track_to_queue(track.value.name!),
), ),
), ),
); );
}, },
child: const ListTile( child: ListTile(
leading: Icon(SpotubeIcons.queueAdd), leading: const Icon(SpotubeIcons.queueAdd),
title: Text("Add to Queue"), title: Text(context.l10n.add_to_queue),
), ),
), ),
PopupMenuItem( PopupMenuItem(
@ -334,14 +337,16 @@ class TrackTile extends HookConsumerWidget {
playlistQueueNotifier.playNext([track.value]); playlistQueueNotifier.playNext([track.value]);
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: content: Text(
Text("${track.value.name} will play next"), context.l10n
.track_will_play_next(track.value.name!),
),
), ),
); );
}, },
child: const ListTile( child: ListTile(
leading: Icon(SpotubeIcons.lightning), leading: const Icon(SpotubeIcons.lightning),
title: Text("Play next"), title: Text(context.l10n.play_next),
), ),
), ),
] else ] else
@ -354,14 +359,17 @@ class TrackTile extends HookConsumerWidget {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text( content: Text(
"Removed ${track.value.name} from queue"), context.l10n.removed_track_from_queue(
track.value.name!,
),
),
), ),
); );
}, },
enabled: playlist?.activeTrack.id != track.value.id, enabled: playlist?.activeTrack.id != track.value.id,
child: const ListTile( child: ListTile(
leading: Icon(SpotubeIcons.queueRemove), leading: const Icon(SpotubeIcons.queueRemove),
title: Text("Remove from queue"), title: Text(context.l10n.remove_from_queue),
), ),
), ),
if (toggler.item3.hasData) if (toggler.item3.hasData)
@ -378,7 +386,9 @@ class TrackTile extends HookConsumerWidget {
) )
: const Icon(SpotubeIcons.heart), : const Icon(SpotubeIcons.heart),
title: Text( title: Text(
"${toggler.item1 ? "Remove from" : "Save as "} favorite", toggler.item1
? context.l10n.remove_from_favorites
: context.l10n.save_as_favorite,
), ),
), ),
), ),
@ -386,9 +396,9 @@ class TrackTile extends HookConsumerWidget {
PopupMenuItem( PopupMenuItem(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onTap: actionAddToPlaylist, onTap: actionAddToPlaylist,
child: const ListTile( child: ListTile(
leading: Icon(SpotubeIcons.playlistAdd), leading: const Icon(SpotubeIcons.playlistAdd),
title: Text("Add To playlist"), title: Text(context.l10n.add_to_playlist),
), ),
), ),
if (userPlaylist && auth != null) if (userPlaylist && auth != null)
@ -406,7 +416,7 @@ class TrackTile extends HookConsumerWidget {
child: CircularProgressIndicator(), child: CircularProgressIndicator(),
) )
: const Icon(SpotubeIcons.removeFilled), : const Icon(SpotubeIcons.removeFilled),
title: const Text("Remove from playlist"), title: Text(context.l10n.remove_from_playlist),
), ),
), ),
PopupMenuItem( PopupMenuItem(
@ -429,7 +439,9 @@ class TrackTile extends HookConsumerWidget {
iconColor: !isBlackListed ? Colors.red[400] : null, iconColor: !isBlackListed ? Colors.red[400] : null,
textColor: !isBlackListed ? Colors.red[400] : null, textColor: !isBlackListed ? Colors.red[400] : null,
title: Text( title: Text(
"${isBlackListed ? "Remove from" : "Add to"} blacklist", isBlackListed
? context.l10n.remove_from_blacklist
: context.l10n.add_to_blacklist,
), ),
), ),
), ),
@ -438,9 +450,9 @@ class TrackTile extends HookConsumerWidget {
onTap: () { onTap: () {
actionShare(track.value); actionShare(track.value);
}, },
child: const ListTile( child: ListTile(
leading: Icon(SpotubeIcons.share), leading: const Icon(SpotubeIcons.share),
title: Text("Share"), title: Text(context.l10n.share),
), ),
) )
]; ];

View File

@ -10,6 +10,7 @@ import 'package:spotube/components/shared/fallbacks/not_found.dart';
import 'package:spotube/components/shared/sort_tracks_dropdown.dart'; import 'package:spotube/components/shared/sort_tracks_dropdown.dart';
import 'package:spotube/components/shared/track_table/track_tile.dart'; import 'package:spotube/components/shared/track_table/track_tile.dart';
import 'package:spotube/components/library/user_local_tracks.dart'; import 'package:spotube/components/library/user_local_tracks.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/use_breakpoints.dart'; import 'package:spotube/hooks/use_breakpoints.dart';
import 'package:spotube/provider/blacklist_provider.dart'; import 'package:spotube/provider/blacklist_provider.dart';
import 'package:spotube/provider/downloader_provider.dart'; import 'package:spotube/provider/downloader_provider.dart';
@ -96,7 +97,7 @@ class TracksTableView extends HookConsumerWidget {
child: Row( child: Row(
children: [ children: [
Text( Text(
"Title", context.l10n.title,
style: tableHeadStyle, style: tableHeadStyle,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -110,7 +111,7 @@ class TracksTableView extends HookConsumerWidget {
child: Row( child: Row(
children: [ children: [
Text( Text(
"Album", context.l10n.album,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: tableHeadStyle, style: tableHeadStyle,
), ),
@ -120,7 +121,7 @@ class TracksTableView extends HookConsumerWidget {
], ],
if (!breakpoint.isSm) ...[ if (!breakpoint.isSm) ...[
const SizedBox(width: 10), const SizedBox(width: 10),
Text("Time", style: tableHeadStyle), Text(context.l10n.time, style: tableHeadStyle),
const SizedBox(width: 10), const SizedBox(width: 10),
], ],
SortTracksDropdown( SortTracksDropdown(
@ -133,7 +134,7 @@ class TracksTableView extends HookConsumerWidget {
}, },
), ),
PopupMenuButton( PopupMenuButton(
tooltip: "More Actions", tooltip: context.l10n.more_actions,
itemBuilder: (context) { itemBuilder: (context) {
return [ return [
PopupMenuItem( PopupMenuItem(
@ -144,7 +145,8 @@ class TracksTableView extends HookConsumerWidget {
const Icon(SpotubeIcons.download), const Icon(SpotubeIcons.download),
const SizedBox(width: 5), const SizedBox(width: 5),
Text( Text(
"Download ${selectedTracks.isNotEmpty ? "(${selectedTracks.length})" : ""}", context.l10n
.download_count(selectedTracks.length),
), ),
], ],
), ),
@ -158,7 +160,9 @@ class TracksTableView extends HookConsumerWidget {
const Icon(SpotubeIcons.playlistAdd), const Icon(SpotubeIcons.playlistAdd),
const SizedBox(width: 5), const SizedBox(width: 5),
Text( Text(
"Add (${selectedTracks.length}) to Playlist", context.l10n.add_count_to_playlist(
selectedTracks.length,
),
), ),
], ],
), ),
@ -171,7 +175,8 @@ class TracksTableView extends HookConsumerWidget {
const Icon(SpotubeIcons.queueAdd), const Icon(SpotubeIcons.queueAdd),
const SizedBox(width: 5), const SizedBox(width: 5),
Text( Text(
"Add (${selectedTracks.length}) to Queue", context.l10n
.add_count_to_queue(selectedTracks.length),
), ),
], ],
), ),
@ -184,7 +189,8 @@ class TracksTableView extends HookConsumerWidget {
const Icon(SpotubeIcons.lightning), const Icon(SpotubeIcons.lightning),
const SizedBox(width: 5), const SizedBox(width: 5),
Text( Text(
"Play (${selectedTracks.length}) Next", context.l10n
.play_count_next(selectedTracks.length),
), ),
], ],
), ),

View File

@ -57,5 +57,46 @@
"added_to_queue": "{tracks}টি গানের ট্র্যাক কিউতে যোগ করা হয়েছে", "added_to_queue": "{tracks}টি গানের ট্র্যাক কিউতে যোগ করা হয়েছে",
"filter_albums": "অ্যালবাম অনুসন্ধান করুন...", "filter_albums": "অ্যালবাম অনুসন্ধান করুন...",
"synced": "সময়ের সাথে সুসংগত", "synced": "সময়ের সাথে সুসংগত",
"plain": "অসুসংগত" "plain": "অসুসংগত",
"shuffle": "অদলবদল",
"search_tracks": "গান অনুসন্ধান করুন...",
"released": "প্রকাশিত হয়েছে",
"error": "ত্রুটি {error}",
"title": "শিরোনাম",
"time": "সময়",
"more_actions": "আরও অপশন",
"download_count": "ডাউনলোড ({count}টি)",
"add_count_to_playlist": "প্লেলিস্টে যোগ করুন ({count}টি)",
"add_count_to_queue": "কিউতে যোগ করুন ({count}টি)",
"play_count_next": "পরবর্তীতে চালান ({count}টি)",
"album": "অ্যালবাম",
"copied_to_clipboard": "{data} ক্লিপবোর্ডে কপি করা হয়েছে",
"add_to_following_playlists": "নিম্নলিখিত প্লেলিস্টে {track} যোগ করুন",
"add": "যোগ করুন",
"added_track_to_queue": "কিউতে {track} যোগ করা হয়েছে",
"add_to_queue": "কিউতে যোগ করুন",
"track_will_play_next": "{track} পরবর্তীতে চালানো হবে",
"play_next": "পরবর্তীতে চালান",
"removed_track_from_queue": "কিউ থেকে {track} সরিয়ে নেওয়া হয়েছে",
"remove_from_queue": "কিউ থেকে সরান",
"remove_from_favorites": "পছন্দের তালিকা থেকে অপসারণ করুন",
"save_as_favorite": "পছন্দের তালিকায় সংরক্ষণ করুন",
"add_to_playlist": "প্লেলিস্টে যোগ করুন",
"remove_from_playlist": "প্লেলিস্ট থেকে সরান",
"add_to_blacklist": "ব্ল্যাকলিস্টে যোগ করুন",
"remove_from_blacklist": "ব্ল্যাকলিস্ট থেকে সরান",
"share": "শেয়ার করুন",
"mini_player": "মিনি প্লেয়ার",
"slide_to_seek": "গান সামনে বা পিছনে নিতে স্লাইড করুন",
"shuffle_playlist": "প্লেলিস্ট এলোমেলো করুন",
"unshuffle_playlist": "প্লেলিস্ট আগের মতো করুন",
"previous_track": "আগের গানের ট্র্যাক",
"next_track": "পরের গানের ট্র্যাক",
"pause_playback": "গান বন্ধ করুন",
"resume_playback": "গান চালু করুন",
"loop_track": "গান শেষে পুনরায় চালান",
"repeat_playlist": "প্লেলিস্ট শেষে পুনরায় চালান",
"queue": "গানের কিউ",
"alternative_track_sources": "বিকল্প গানের উৎস",
"download_track": "গান ডাউনলোড করুন"
} }

View File

@ -57,5 +57,46 @@
"added_to_queue": "Added {tracks} tracks to queue", "added_to_queue": "Added {tracks} tracks to queue",
"filter_albums": "Filter albums...", "filter_albums": "Filter albums...",
"synced": "Synced", "synced": "Synced",
"plain": "Plain" "plain": "Plain",
"shuffle": "Shuffle",
"search_tracks": "Search tracks...",
"released": "Released",
"error": "Error {error}",
"title": "Title",
"time": "Time",
"more_actions": "More actions",
"download_count": "Download ({count})",
"add_count_to_playlist": "Add ({count}) to Playlist",
"add_count_to_queue": "Add ({count}) to Queue",
"play_count_next": "Play ({count}) next",
"album": "Album",
"copied_to_clipboard": "Copied {data} to clipboard",
"add_to_following_playlists": "Add {track} to following Playlists",
"add": "Add",
"added_track_to_queue": "Added {track} to queue",
"add_to_queue": "Add to queue",
"track_will_play_next": "{track} will play next",
"play_next": "Play next",
"removed_track_from_queue": "Removed {track} from queue",
"remove_from_queue": "Remove from queue",
"remove_from_favorites": "Remove from favorites",
"save_as_favorite": "Save as favorite",
"add_to_playlist": "Add to playlist",
"remove_from_playlist": "Remove from playlist",
"add_to_blacklist": "Add to blacklist",
"remove_from_blacklist": "Remove from blacklist",
"share": "Share",
"mini_player": "Mini Player",
"slide_to_seek": "Slide to seek forward or backward",
"shuffle_playlist": "Shuffle playlist",
"unshuffle_playlist": "Unshuffle playlist",
"previous_track": "Previous track",
"next_track": "Next track",
"pause_playback": "Pause Playback",
"resume_playback": "Resume Playback",
"loop_track": "Loop track",
"repeat_playlist": "Repeat playlist",
"queue": "Queue",
"alternative_track_sources": "Alternative track sources",
"download_track": "Download track"
} }