From a5c36bbb20cc69d609bfb5ab973c7e288c1ea9de Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Sat, 29 Apr 2023 13:46:42 +0600 Subject: [PATCH] feat: localize settings, about, login, player queue with Bengali and English translations --- lib/components/desktop_login/login_form.dart | 19 +-- lib/components/player/player_queue.dart | 11 +- .../player/sibling_tracks_sheet.dart | 3 +- lib/l10n/app_bn.arb | 87 ++++++++++- lib/l10n/app_en.arb | 85 ++++++++++- lib/pages/desktop_login/desktop_login.dart | 11 +- lib/pages/desktop_login/login_tutorial.dart | 49 +++---- lib/pages/lyrics/mini_lyrics.dart | 16 ++- lib/pages/settings/about.dart | 35 ++--- lib/pages/settings/settings.dart | 136 +++++++++--------- 10 files changed, 307 insertions(+), 145 deletions(-) diff --git a/lib/components/desktop_login/login_form.dart b/lib/components/desktop_login/login_form.dart index fe7c222ff..0d2662867 100644 --- a/lib/components/desktop_login/login_form.dart +++ b/lib/components/desktop_login/login_form.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:spotube/extensions/context.dart'; import 'package:spotube/provider/authentication_provider.dart'; @@ -27,18 +28,18 @@ class TokenLoginForm extends HookConsumerWidget { children: [ TextField( controller: directCodeController, - decoration: const InputDecoration( - hintText: "Spotify \"sp_dc\" Cookie", - labelText: "sp_dc Cookie", + decoration: InputDecoration( + hintText: context.l10n.spotify_cookie("\"sp_dc\""), + labelText: context.l10n.cookie_name_cookie("sp_dc"), ), keyboardType: TextInputType.visiblePassword, ), const SizedBox(height: 10), TextField( controller: keyCodeController, - decoration: const InputDecoration( - hintText: "Spotify \"sp_key\" Cookie", - labelText: "sp_key Cookie", + decoration: InputDecoration( + hintText: context.l10n.spotify_cookie("\"sp_key\""), + labelText: context.l10n.cookie_name_cookie("sp_key"), ), keyboardType: TextInputType.visiblePassword, ), @@ -48,8 +49,8 @@ class TokenLoginForm extends HookConsumerWidget { if (keyCodeController.text.isEmpty || directCodeController.text.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text("Please fill in all fields"), + SnackBar( + content: Text(context.l10n.fill_in_all_fields), behavior: SnackBarBehavior.floating, ), ); @@ -65,7 +66,7 @@ class TokenLoginForm extends HookConsumerWidget { onDone?.call(); } }, - child: const Text("Submit"), + child: Text(context.l10n.submit), ) ], ), diff --git a/lib/components/player/player_queue.dart b/lib/components/player/player_queue.dart index f66075a7d..7a2dd39ef 100644 --- a/lib/components/player/player_queue.dart +++ b/lib/components/player/player_queue.dart @@ -8,6 +8,7 @@ import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/components/shared/fallbacks/not_found.dart'; import 'package:spotube/components/shared/track_table/track_tile.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/use_auto_scroll_controller.dart'; import 'package:spotube/provider/playlist_queue_provider.dart'; import 'package:spotube/utils/primitive_utils.dart'; @@ -79,7 +80,7 @@ class PlayerQueue extends HookConsumerWidget { children: [ const SizedBox(width: 10), Text( - "${tracks.length} tracks in Queue", + context.l10n.tracks_in_queue(tracks.length), style: TextStyle( color: headlineColor, fontWeight: FontWeight.bold, @@ -94,10 +95,10 @@ class PlayerQueue extends HookConsumerWidget { foregroundColor: theme.textTheme.headlineSmall?.color, ), child: Row( - children: const [ - Icon(SpotubeIcons.playlistRemove), - SizedBox(width: 5), - Text("Clear All"), + children: [ + const Icon(SpotubeIcons.playlistRemove), + const SizedBox(width: 5), + Text(context.l10n.clear_all), ], ), onPressed: () { diff --git a/lib/components/player/sibling_tracks_sheet.dart b/lib/components/player/sibling_tracks_sheet.dart index 528b8a159..0a34e13ec 100644 --- a/lib/components/player/sibling_tracks_sheet.dart +++ b/lib/components/player/sibling_tracks_sheet.dart @@ -5,6 +5,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/components/shared/image/universal_image.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/models/spotube_track.dart'; import 'package:spotube/provider/playlist_queue_provider.dart'; import 'package:spotube/utils/primitive_utils.dart'; @@ -58,7 +59,7 @@ class SiblingTracksSheet extends HookConsumerWidget { appBar: AppBar( centerTitle: true, title: Text( - 'Alternative Tracks Sources', + context.l10n.alternative_track_sources, style: theme.textTheme.headlineSmall, ), automaticallyImplyLeading: false, diff --git a/lib/l10n/app_bn.arb b/lib/l10n/app_bn.arb index a3d676903..9af0c4a06 100644 --- a/lib/l10n/app_bn.arb +++ b/lib/l10n/app_bn.arb @@ -56,7 +56,7 @@ "artist_url_copied": "শিল্পীর URL কপি করা হয়েছে", "added_to_queue": "{tracks}টি গানের ট্র্যাক কিউতে যোগ করা হয়েছে", "filter_albums": "অ্যালবাম অনুসন্ধান করুন...", - "synced": "সময়ের সাথে সুসংগত", + "synced": "সময় সুসংগত", "plain": "অসুসংগত", "shuffle": "অদলবদল", "search_tracks": "গান অনুসন্ধান করুন...", @@ -98,5 +98,88 @@ "repeat_playlist": "প্লেলিস্ট শেষে পুনরায় চালান", "queue": "গানের কিউ", "alternative_track_sources": "বিকল্প গানের উৎস", - "download_track": "গান ডাউনলোড করুন" + "download_track": "গান ডাউনলোড করুন", + "tracks_in_queue": "{tracks}টি গান কিউতে রয়েছে", + "clear_all": "সব মুছে ফেলুন", + "show_hide_ui_on_hover": "হভার করলে UI দেখান/লুকান", + "always_on_top": "সর্বদা উপরে", + "exit_mini_player": "মিনি প্লেয়ার থেকে বের হয়ে যান", + "download_location": "ডাউনলোড স্থান", + "account": "অ্যাকাউন্ট", + "login_with_spotify": "আপনার Spotify account দিয়ে লগইন করুন", + "connect_with_spotify": "Spotify লগইন", + "logout": "লগআউট করুন", + "logout_of_this_account": "অ্যাকাউন্ট থেকে লগআউট করুন", + "language_region": "ভাষা ও অঞ্চল", + "language": "ভাষা", + "system_default": "সিস্টেম ডিফল্ট", + "market_place_region": "মার্কেটপ্লেস অঞ্চল", + "recommendation_country": "দেশভিত্তিক সঙ্গীত পরামর্শের জন্য দেশ", + "appearance": "রুপ", + "layout_mode": "UI বিন্যাস রূপ", + "override_layout_settings": "প্রতিক্রিয়াশীল UI বিন্যাস রূপের সেটিংস পরিবর্তন করুন", + "adaptive": "অভিযোজিত", + "compact": "আঁটসাঁট UI", + "extended": "বিস্তৃত UI", + "theme": "থিম", + "dark": "অন্ধকার", + "light": "উজ্জল", + "system": "সিস্টেম থিম", + "accent_color": "প্রভাবশালী রং", + "sync_album_color": "অ্যালবাম সুসংগত UI এর রং", + "sync_album_color_description": "অ্যালবাম কভারের প্রভাবশালী রঙ UI অ্যাকসেন্ট রঙ হিসাবে ব্যবহার করে", + "playback": "সংগীতের প্লেব্যাক", + "audio_quality": "শব্দের গুণমান", + "high": "উচ্চ", + "low": "নিম্ন", + "pre_download_play": "আগে গান ডাউনলোড করে পরে চালান ", + "pre_download_play_description": "গান স্ট্রিম করার পরিবর্তে, ডাউনলোড করুন এবং প্লে করুন (উচ্চ ব্যান্ডউইথ ব্যবহারকারীদের জন্য প্রস্তাবিত)", + "skip_non_music": "গানের নন-মিউজিক সেগমেন্ট এড়িয়ে যান (SponsorBlock)", + "blacklist_description": "কালো তালিকাভুক্ত গানের ট্র্যাক এবং শিল্পী", + "wait_for_download_to_finish": "ডাউনলোড শেষ হওয়ার জন্য অপেক্ষা করুন", + "download_lyrics": "গানের সাথে লিরিক্স ডাউনলোড করুন", + "desktop": "ডেস্কটপ", + "close_behavior": "বন্ধ করার প্রক্রিয়া", + "close": "বন্ধ করুন", + "minimize_to_tray": "সিস্টেম ট্রেতে রাখুন", + "show_tray_icon": "সিস্টেম ট্রে আইকন দেখান", + "about": "বিস্তারিত", + "u_love_spotube": "আমরা জানি আপনি Spotube কে ভালবাসেন", + "check_for_updates": "আপডেট চেক করুন", + "about_spotube": "Spotube সম্পর্কে বিস্তারিত", + "blacklist": "কালো তালিকা", + "please_sponsor": "স্পনসর/সহায়তা করুন", + "spotube_description": "Spotube, একটি কর্মদক্ষ, ক্রস-প্ল্যাটফর্ম, বিনামূল্যের জন্য Spotify ক্লায়েন্ট", + "version": "সংস্করণ", + "build_number": "বিল্ড নম্বর", + "founder": "প্রতিষ্ঠাতা", + "repository": "সংগ্রহস্থল", + "bug_issues": "বাগ/সমস্যা", + "made_with": "❤️ দিয়ে বাংলাদেশে🇧🇩 তৈরি", + "kingkor_roy_tirtho": "কিংকর রায় তীর্থ", + "copyright": "© 2021-{current_year} কিংকর রায় তীর্থ", + "license": "লাইসেন্স", + "add_spotify_credentials": "আপনার Spotify লগইন তথ্য যোগ করুন", + "credentials_will_not_be_shared_disclaimer": "চিন্তা করবেন না, আপনার কোনো লগইন তথ্য সংগ্রহ করা হবে না বা কারো সাথে শেয়ার করা হবে না", + "know_how_to_login": "আপনি কিভাবে লগইন করবেন তা জানেন না?", + "follow_step_by_step_guide": "ধাপে ধাপে নির্দেশিকা অনুসরণ করুন", + "spotify_cookie": "Spotify {name} কুকি", + "cookie_name_cookie": "{name} কুকি", + "fill_in_all_fields": "সমস্ত ফর্ম ক্ষেত্র পূরণ করুন", + "submit": "জমা দিন", + "exit": "প্রস্থান", + "previous": "পূর্ববর্তী", + "next": "পরবর্তী", + "done": "সম্পন্ন", + "step_1": "ধাপ 1", + "first_go_to": "প্রথমে যান", + "login_if_not_logged_in": "এবং যদি আপনি লগইন/সাইন-আপ না থাকেন তবে লগইন/সাইন-আপ করুন", + "step_2": "ধাপ 2", + "step_2_steps": "১. একবার আপনি লগ ইন করলে, ব্রাউজার ডেভটুল খুলতে F12 বা মাউসের রাইট ক্লিক > \"Inspect to open Browser DevTools\" টিপুন।\n২. তারপর \"Application\" ট্যাবে যান (Chrome, Edge, Brave etc..) অথবা \"Storage\" Tab (Firefox, Palemoon etc..)\n৩. \"Cookies \" বিভাগে যান তারপর \"https://accounts.spotify.com\" উপবিভাগে যান", + "step_3": "ধাপ 3", + "step_3_steps": "\"sp_dc\" এবং \"sp_key\" কুকিজের মান কপি করুন", + "success_emoji": "আমরা সফল🥳", + "success_message": "এখন আপনি সফলভাবে আপনার Spotify অ্যাকাউন্ট দিয়ে লগ ইন করেছেন। সাধুভাত আপনাকে", + "step_4": "ধাপ 4", + "step_4_steps": "কপি করা \"sp_dc\" এবং \"sp_key\" এর মান সংশ্লিষ্ট ফিল্ডে পেস্ট করুন" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 66adc2912..ed5552cec 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -98,5 +98,88 @@ "repeat_playlist": "Repeat playlist", "queue": "Queue", "alternative_track_sources": "Alternative track sources", - "download_track": "Download track" + "download_track": "Download track", + "tracks_in_queue": "{tracks} tracks in queue", + "clear_all": "Clear all", + "show_hide_ui_on_hover": "Show/Hide UI on hover", + "always_on_top": "Always on top", + "exit_mini_player": "Exit Mini player", + "download_location": "Download location", + "account": "Account", + "login_with_spotify": "Login with your Spotify account", + "connect_with_spotify": "Connect with Spotify", + "logout": "Logout", + "logout_of_this_account": "Logout of this account", + "language_region": "Language & Region", + "language": "Language", + "system_default": "System Default", + "market_place_region": "Marketplace Region", + "recommendation_country": "Recommendation Country", + "appearance": "Appearance", + "layout_mode": "Layout Mode", + "override_layout_settings": "Override responsive layout mode settings", + "adaptive": "Adaptive", + "compact": "Compact", + "extended": "Extended", + "theme": "Theme", + "dark": "Dark", + "light": "Light", + "system": "System", + "accent_color": "Accent Color", + "sync_album_color": "Sync album color", + "sync_album_color_description": "Uses the dominant color of the album art as the accent color", + "playback": "Playback", + "audio_quality": "Audio Quality", + "high": "High", + "low": "Low", + "pre_download_play": "Pre-download and play", + "pre_download_play_description": "Instead of streaming audio, download bytes and play instead (Recommended for higher bandwidth users)", + "skip_non_music": "Skip non-music segments (SponsorBlock)", + "blacklist_description": "Blacklisted tracks and artists", + "wait_for_download_to_finish": "Please wait for the current download to finish", + "download_lyrics": "Download lyrics along with tracks", + "desktop": "Desktop", + "close_behavior": "Close Behavior", + "close": "Close", + "minimize_to_tray": "Minimize to tray", + "show_tray_icon": "Show System tray icon", + "about": "About", + "u_love_spotube": "We know you love Spotube", + "check_for_updates": "Check for updates", + "about_spotube": "About Spotube", + "blacklist": "Blacklist", + "please_sponsor": "Please Sponsor/Donate", + "spotube_description": "Spotube, a light-weight, cross-platform, free-for-all spotify client", + "version": "Version", + "build_number": "Build Number", + "founder": "Founder", + "repository": "Repository", + "bug_issues": "Bug+Issues", + "made_with": "Made with ❤️ in Bangladesh🇧🇩", + "kingkor_roy_tirtho": "Kingkor Roy Tirtho", + "copyright": "© 2021-{current_year} Kingkor Roy Tirtho", + "license": "License", + "add_spotify_credentials": "Add your spotify credentials to get started", + "credentials_will_not_be_shared_disclaimer": "Don't worry, any of your credentials won't be collected or shared with anyone", + "know_how_to_login": "Don't know how to do this?", + "follow_step_by_step_guide": "Follow along the Step by Step guide", + "spotify_cookie": "Spotify {name} Cookie", + "cookie_name_cookie": "{name} Cookie", + "fill_in_all_fields": "Please fill in all the fields", + "submit": "Submit", + "exit": "Exit", + "previous": "Previous", + "next": "Next", + "done": "Done", + "step_1": "Step 1", + "first_go_to": "First, Go to", + "login_if_not_logged_in": "and Login/Signup if you are not logged in", + "step_2": "Step 2", + "step_2_steps": "1. Once you're logged in, press F12 or Mouse Right Click > Inspect to Open the Browser devtools.\n2. Then go the \"Application\" Tab (Chrome, Edge, Brave etc..) or \"Storage\" Tab (Firefox, Palemoon etc..)\n3. Go to the \"Cookies\" section then the \"https://accounts.spotify.com\" subsection", + "step_3": "Step 3", + "step_3_steps": "Copy the values of \"sp_dc\" and \"sp_key\" Cookies", + "success_emoji": "Success🥳", + "success_message": "Now you're successfully Logged In with your Spotify account. Good Job, mate!", + "step_4": "Step 4", + "step_4_steps": "Paste the copied \"sp_dc\" and \"sp_key\" values in the respective fields" } \ No newline at end of file diff --git a/lib/pages/desktop_login/desktop_login.dart b/lib/pages/desktop_login/desktop_login.dart index 51b384366..bb9fed346 100644 --- a/lib/pages/desktop_login/desktop_login.dart +++ b/lib/pages/desktop_login/desktop_login.dart @@ -5,6 +5,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/collections/assets.gen.dart'; import 'package:spotube/components/desktop_login/login_form.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/use_breakpoints.dart'; class DesktopLoginPage extends HookConsumerWidget { @@ -37,11 +38,11 @@ class DesktopLoginPage extends HookConsumerWidget { (breakpoint <= Breakpoints.md ? .5 : .3), ), Text( - "Add your spotify credentials to get started", + context.l10n.add_spotify_credentials, style: theme.textTheme.titleMedium, ), Text( - "Don't worry, any of your credentials won't be collected or shared with anyone", + context.l10n.credentials_will_not_be_shared_disclaimer, style: theme.textTheme.labelMedium, ), const SizedBox(height: 10), @@ -53,10 +54,10 @@ class DesktopLoginPage extends HookConsumerWidget { alignment: WrapAlignment.center, crossAxisAlignment: WrapCrossAlignment.center, children: [ - const Text("Don't know how to do this?"), + Text(context.l10n.know_how_to_login), TextButton( - child: const Text( - "Follow along the Step by Step guide", + child: Text( + context.l10n.follow_step_by_step_guide, ), onPressed: () => GoRouter.of(context).push( "/login-tutorial", diff --git a/lib/pages/desktop_login/login_tutorial.dart b/lib/pages/desktop_login/login_tutorial.dart index d8e5a05c0..355df838d 100644 --- a/lib/pages/desktop_login/login_tutorial.dart +++ b/lib/pages/desktop_login/login_tutorial.dart @@ -7,6 +7,7 @@ import 'package:spotube/collections/assets.gen.dart'; import 'package:spotube/components/desktop_login/login_form.dart'; import 'package:spotube/components/shared/links/hyper_link.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/utils/service_utils.dart'; @@ -28,7 +29,7 @@ class LoginTutorial extends ConsumerWidget { return Scaffold( appBar: PageWindowTitleBar( leading: TextButton( - child: const Text("Exit"), + child: Text(context.l10n.exit), onPressed: () { Navigator.of(context).pop(); }, @@ -38,13 +39,13 @@ class LoginTutorial extends ConsumerWidget { key: key, globalBackgroundColor: theme.scaffoldBackgroundColor, overrideBack: OutlinedButton( - child: const Center(child: Text("Previous")), + child: Center(child: Text(context.l10n.previous)), onPressed: () { (key.currentState as IntroductionScreenState).previous(); }, ), overrideNext: FilledButton( - child: const Center(child: Text("Next")), + child: Center(child: Text(context.l10n.next)), onPressed: () { (key.currentState as IntroductionScreenState).next(); }, @@ -56,64 +57,56 @@ class LoginTutorial extends ConsumerWidget { ServiceUtils.navigate(context, "/"); } : null, - child: const Center(child: Text("Done")), + child: Center(child: Text(context.l10n.done)), ), pages: [ PageViewModel( decoration: pageDecoration, - title: "Step 1", + title: context.l10n.step_1, image: Assets.tutorial.step1.image(), bodyWidget: Wrap( - children: const [ - Text( - "First, Go to ", - ), - Hyperlink( + children: [ + Text(context.l10n.first_go_to), + const SizedBox(width: 5), + const Hyperlink( "accounts.spotify.com ", "https://accounts.spotify.com", ), - Text( - "and Login/Sign up if you're not logged in", - ), + Text(context.l10n.login_if_not_logged_in), ], ), ), PageViewModel( decoration: pageDecoration, - title: "Step 2", + title: context.l10n.step_2, image: Assets.tutorial.step2.image(), - bodyWidget: const Text( - "1. Once you're logged in, press F12 or Mouse Right Click > Inspect to Open the Browser devtools.\n2. Then go the \"Application\" Tab (Chrome, Edge, Brave etc..) or \"Storage\" Tab (Firefox, Palemoon etc..)\n3. Go to the \"Cookies\" section then the \"https://accounts.spotify.com\" subsection", - textAlign: TextAlign.left, - ), + bodyWidget: + Text(context.l10n.step_2_steps, textAlign: TextAlign.left), ), PageViewModel( decoration: pageDecoration, - title: "Step 3", + title: context.l10n.step_3, image: Assets.tutorial.step3.image(), - bodyWidget: const Text( - "Copy the values of \"sp_dc\" and \"sp_key\" Cookies", - textAlign: TextAlign.left, - ), + bodyWidget: + Text(context.l10n.step_3_steps, textAlign: TextAlign.left), ), if (authenticationNotifier.isLoggedIn) PageViewModel( decoration: pageDecoration.copyWith( bodyAlignment: Alignment.center, ), - title: "Success🥳", + title: context.l10n.success_emoji, image: Assets.success.image(), - body: - "Now you're successfully Logged In with your Spotify account. Good Job, mate!", + body: context.l10n.success_message, ) else PageViewModel( decoration: pageDecoration, - title: "Step 5", + title: context.l10n.step_4, bodyWidget: Column( children: [ Text( - "Paste the copied \"sp_dc\" and \"sp_key\" values in the respective fields", + context.l10n.step_4_steps, style: theme.textTheme.labelMedium, ), const SizedBox(height: 10), diff --git a/lib/pages/lyrics/mini_lyrics.dart b/lib/pages/lyrics/mini_lyrics.dart index d481deb07..d83030b6a 100644 --- a/lib/pages/lyrics/mini_lyrics.dart +++ b/lib/pages/lyrics/mini_lyrics.dart @@ -10,6 +10,7 @@ import 'package:spotube/components/player/player_queue.dart'; import 'package:spotube/components/root/sidebar.dart'; import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/use_force_update.dart'; import 'package:spotube/pages/lyrics/plain_lyrics.dart'; import 'package:spotube/pages/lyrics/synced_lyrics.dart'; @@ -82,16 +83,19 @@ class MiniLyricsPage extends HookConsumerWidget { child: Sidebar.brandLogo(), ), const Spacer(), - const SizedBox( + SizedBox( height: 30, child: TabBar( - tabs: [Tab(text: 'Synced'), Tab(text: 'Plain')], + tabs: [ + Tab(text: context.l10n.synced), + Tab(text: context.l10n.plain), + ], isScrollable: true, ), ), const Spacer(), IconButton( - tooltip: 'Show/Hide UI on hover', + tooltip: context.l10n.show_hide_ui_on_hover, icon: hoverMode.value ? const Icon(SpotubeIcons.hoverOn) : const Icon(SpotubeIcons.hoverOff), @@ -112,7 +116,7 @@ class MiniLyricsPage extends HookConsumerWidget { future: DesktopTools.window.isAlwaysOnTop(), builder: (context, snapshot) { return IconButton( - tooltip: 'Always on top', + tooltip: context.l10n.always_on_top, icon: Icon( snapshot.data == true ? SpotubeIcons.pinOn @@ -173,7 +177,7 @@ class MiniLyricsPage extends HookConsumerWidget { children: [ IconButton( icon: const Icon(SpotubeIcons.queue), - tooltip: 'Queue', + tooltip: context.l10n.queue, onPressed: playlistQueue != null ? () { showModalBottomSheet( @@ -199,7 +203,7 @@ class MiniLyricsPage extends HookConsumerWidget { ), Flexible(child: PlayerControls(compact: true)), IconButton( - tooltip: 'Exit Mini Player', + tooltip: context.l10n.exit_mini_player, icon: const Icon(SpotubeIcons.maximize), onPressed: () async { try { diff --git a/lib/pages/settings/about.dart b/lib/pages/settings/about.dart index 069eb1f50..67daef453 100644 --- a/lib/pages/settings/about.dart +++ b/lib/pages/settings/about.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import 'package:spotube/collections/assets.gen.dart'; import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/use_package_info.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -24,9 +25,9 @@ class AboutSpotube extends HookConsumerWidget { final theme = Theme.of(context); return Scaffold( - appBar: const PageWindowTitleBar( - leading: BackButton(), - title: Text("About Spotube"), + appBar: PageWindowTitleBar( + leading: const BackButton(), + title: Text(context.l10n.about_spotube), ), body: SingleChildScrollView( child: Padding( @@ -42,16 +43,16 @@ class AboutSpotube extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Spotube, a light-weight, cross-platform, free-for-all spotify client", + context.l10n.spotube_description, style: theme.textTheme.titleLarge, ), const SizedBox(height: 20), Row( mainAxisSize: MainAxisSize.min, children: [ - const Text( - "Founder: Kingkor Roy Tirtho", - style: TextStyle( + Text( + "${context.l10n.founder}: ${context.l10n.kingkor_roy_tirtho}", + style: const TextStyle( fontWeight: FontWeight.bold, ), ), @@ -68,11 +69,11 @@ class AboutSpotube extends HookConsumerWidget { ), const SizedBox(height: 5), Text( - "Version: v${packageInfo.version}", + "${context.l10n.version}: v${packageInfo.version}", ), const SizedBox(height: 5), Text( - "Build Number: ${packageInfo.buildNumber.replaceAll(".", " ")}", + "${context.l10n.build_number}: ${packageInfo.buildNumber.replaceAll(".", " ")}", ), const SizedBox(height: 5), InkWell( @@ -82,8 +83,8 @@ class AboutSpotube extends HookConsumerWidget { mode: LaunchMode.externalApplication, ); }, - child: const Text( - "Repository: https://github.com/KRTirtho/spotube", + child: Text( + "${context.l10n.repository}: https://github.com/KRTirtho/spotube", ), ), const SizedBox(height: 5), @@ -94,8 +95,8 @@ class AboutSpotube extends HookConsumerWidget { mode: LaunchMode.externalApplication, ); }, - child: const Text( - "License: BSD-4-Clause", + child: Text( + "${context.l10n.license}: BSD-4-Clause", ), ), const SizedBox(height: 5), @@ -106,8 +107,8 @@ class AboutSpotube extends HookConsumerWidget { mode: LaunchMode.externalApplication, ); }, - child: const Text( - "Bugs+Issues: https://github.com/KRTirtho/spotube/issues", + child: Text( + "${context.l10n.bug_issues}: https://github.com/KRTirtho/spotube/issues", ), ), ], @@ -186,12 +187,12 @@ class AboutSpotube extends HookConsumerWidget { ), const SizedBox(height: 20), Text( - "Made with ❤️ in Bangladesh🇧🇩", + context.l10n.made_with, textAlign: TextAlign.center, style: theme.textTheme.bodySmall, ), Text( - "© 2021-${DateTime.now().year} Kingkor Roy Tirtho", + context.l10n.copyright(DateTime.now().year), textAlign: TextAlign.center, style: theme.textTheme.bodySmall, ), diff --git a/lib/pages/settings/settings.dart b/lib/pages/settings/settings.dart index c32467ddc..764988bc4 100644 --- a/lib/pages/settings/settings.dart +++ b/lib/pages/settings/settings.dart @@ -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/extensions/context.dart'; import 'package:spotube/l10n/l10n.dart'; import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/provider/downloader_provider.dart'; @@ -39,7 +40,7 @@ class SettingsPage extends HookConsumerWidget { final pickDownloadLocation = useCallback(() async { final dirStr = await FilePicker.platform.getDirectoryPath( - dialogTitle: "Download Location", + dialogTitle: context.l10n.download_location, ); if (dirStr == null) return; preferences.setDownloadLocation(dirStr); @@ -48,8 +49,8 @@ class SettingsPage extends HookConsumerWidget { return SafeArea( bottom: false, child: Scaffold( - appBar: const PageWindowTitleBar( - title: Text("Settings"), + appBar: PageWindowTitleBar( + title: Text(context.l10n.settings), centerTitle: true, ), body: Row( @@ -61,7 +62,7 @@ class SettingsPage extends HookConsumerWidget { child: ListView( children: [ Text( - " Account", + " ${context.l10n.account}", style: theme.textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.bold), ), @@ -74,7 +75,7 @@ class SettingsPage extends HookConsumerWidget { title: Align( alignment: Alignment.centerLeft, child: AutoSizeText( - "Login with your Spotify account", + context.l10n.login_with_spotify, maxLines: 1, style: TextStyle( color: theme.colorScheme.primary, @@ -92,20 +93,22 @@ class SettingsPage extends HookConsumerWidget { ), ), ), - child: Text("Connect with Spotify".toUpperCase()), + child: Text( + context.l10n.connect_with_spotify.toUpperCase(), + ), ), ) else Builder(builder: (context) { return ListTile( leading: const Icon(SpotubeIcons.logout), - title: const SizedBox( + title: SizedBox( height: 50, width: 180, child: Align( alignment: Alignment.centerLeft, child: AutoSizeText( - "Log out of this account", + context.l10n.logout_of_this_account, maxLines: 1, ), ), @@ -124,24 +127,24 @@ class SettingsPage extends HookConsumerWidget { .logout(); GoRouter.of(context).pop(); }, - child: const Text("Logout"), + child: Text(context.l10n.logout), ), ); }), Text( - " Language & Region", + " ${context.l10n.language_region}", style: theme.textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.bold), ), ListTile( leading: const Icon(SpotubeIcons.language), - title: const Text("Language"), + title: Text(context.l10n.language), trailing: DropdownButton( value: preferences.locale, items: [ - const DropdownMenuItem( - value: Locale("system"), - child: Text("System Default"), + DropdownMenuItem( + value: const Locale("system"), + child: Text(context.l10n.system_default), ), for (final locale in L10n.all) DropdownMenuItem( @@ -158,8 +161,8 @@ class SettingsPage extends HookConsumerWidget { ), AdaptiveListTile( leading: const Icon(SpotubeIcons.shoppingBag), - title: const Text("Market Place Region"), - subtitle: const Text("Recommendation Country"), + title: Text(context.l10n.market_place_region), + subtitle: Text(context.l10n.recommendation_country), trailing: (context, update) => ConstrainedBox( constraints: const BoxConstraints(maxWidth: 350), child: DropdownMenu( @@ -183,29 +186,27 @@ class SettingsPage extends HookConsumerWidget { ), ), Text( - " Appearance", + " ${context.l10n.appearance}", style: theme.textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.bold), ), AdaptiveListTile( leading: const Icon(SpotubeIcons.dashboard), - title: const Text("Layout Mode"), - subtitle: const Text( - "Override responsive layout mode settings", - ), + title: Text(context.l10n.layout_mode), + subtitle: Text(context.l10n.override_layout_settings), trailing: (context, update) => DropdownButton( - items: const [ + items: [ DropdownMenuItem( value: LayoutMode.adaptive, - child: Text("Adaptive"), + child: Text(context.l10n.adaptive), ), DropdownMenuItem( value: LayoutMode.compact, - child: Text("Compact"), + child: Text(context.l10n.compact), ), DropdownMenuItem( value: LayoutMode.extended, - child: Text("Extended"), + child: Text(context.l10n.extended), ), ], value: preferences.layoutMode, @@ -219,21 +220,21 @@ class SettingsPage extends HookConsumerWidget { ), AdaptiveListTile( leading: const Icon(SpotubeIcons.darkMode), - title: const Text("Theme"), + title: Text(context.l10n.theme), trailing: (context, update) => DropdownButton( value: preferences.themeMode, - items: const [ + items: [ DropdownMenuItem( value: ThemeMode.dark, - child: Text("Dark"), + child: Text(context.l10n.dark), ), DropdownMenuItem( value: ThemeMode.light, - child: Text("Light"), + child: Text(context.l10n.light), ), DropdownMenuItem( value: ThemeMode.system, - child: Text("System"), + child: Text(context.l10n.system), ), ], onChanged: (value) { @@ -246,7 +247,7 @@ class SettingsPage extends HookConsumerWidget { ), ListTile( leading: const Icon(SpotubeIcons.palette), - title: const Text("Accent Color"), + title: Text(context.l10n.accent_color), contentPadding: const EdgeInsets.symmetric( horizontal: 15, vertical: 5, @@ -260,32 +261,30 @@ class SettingsPage extends HookConsumerWidget { ), SwitchListTile( secondary: const Icon(SpotubeIcons.colorSync), - title: const Text("Sync Album Color"), - subtitle: const Text( - "Uses the dominant color of the album art as the accent color", - ), + title: Text(context.l10n.sync_album_color), + subtitle: Text(context.l10n.sync_album_color_description), value: preferences.albumColorSync, onChanged: preferences.setAlbumColorSync, ), Text( - " Playback", + " ${context.l10n.playback}", style: theme.textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.bold), ), AdaptiveListTile( leading: const Icon(SpotubeIcons.audioQuality), - title: const Text("Audio Quality"), + title: Text(context.l10n.audio_quality), trailing: (context, update) => DropdownButton( value: preferences.audioQuality, - items: const [ + items: [ DropdownMenuItem( value: AudioQuality.high, - child: Text("High"), + child: Text(context.l10n.high), ), DropdownMenuItem( value: AudioQuality.low, - child: Text("Low"), + child: Text(context.l10n.low), ), ], onChanged: (value) { @@ -298,10 +297,9 @@ class SettingsPage extends HookConsumerWidget { ), SwitchListTile( secondary: const Icon(SpotubeIcons.download), - title: const Text("Pre download and play"), - subtitle: const Text( - "Instead of streaming audio, download bytes and play instead (Recommended for higher bandwidth users)", - ), + title: Text(context.l10n.pre_download_play), + subtitle: + Text(context.l10n.pre_download_play_description), value: preferences.predownload, onChanged: (state) { preferences.setPredownload(state); @@ -309,9 +307,7 @@ class SettingsPage extends HookConsumerWidget { ), SwitchListTile( secondary: const Icon(SpotubeIcons.fastForward), - title: const Text( - "Skip non-music segments (SponsorBlock)", - ), + title: Text(context.l10n.skip_non_music), value: preferences.skipSponsorSegments, onChanged: (state) { preferences.setSkipSponsorSegments(state); @@ -319,27 +315,25 @@ class SettingsPage extends HookConsumerWidget { ), ListTile( leading: const Icon(SpotubeIcons.playlistRemove), - title: const Text("Blacklist"), - subtitle: const Text( - "Blacklisted tracks and artists", - ), + title: Text(context.l10n.blacklist), + subtitle: Text(context.l10n.blacklist_description), onTap: () { GoRouter.of(context).push("/settings/blacklist"); }, trailing: const Icon(SpotubeIcons.angleRight), ), Text( - " Downloads", + " ${context.l10n.downloads}", style: theme.textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.bold), ), Tooltip( message: isDownloading - ? "Please wait for the current download to finish" + ? context.l10n.wait_for_download_to_finish : "", child: ListTile( leading: const Icon(SpotubeIcons.download), - title: const Text("Download Location"), + title: Text(context.l10n.download_location), subtitle: Text(preferences.downloadLocation), trailing: FilledButton( onPressed: @@ -351,7 +345,7 @@ class SettingsPage extends HookConsumerWidget { ), SwitchListTile( secondary: const Icon(SpotubeIcons.lyrics), - title: const Text("Download lyrics along with the Track"), + title: Text(context.l10n.download_lyrics), value: preferences.saveTrackLyrics, onChanged: (state) { preferences.setSaveTrackLyrics(state); @@ -359,24 +353,24 @@ class SettingsPage extends HookConsumerWidget { ), if (DesktopTools.platform.isDesktop) ...[ Text( - " Desktop", + " ${context.l10n.desktop}", style: theme.textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.bold), ), AdaptiveListTile( leading: const Icon(SpotubeIcons.close), - title: const Text("Close Behavior"), + title: Text(context.l10n.close_behavior), trailing: (context, update) => DropdownButton( value: preferences.closeBehavior, - items: const [ + items: [ DropdownMenuItem( value: CloseBehavior.close, - child: Text("Close"), + child: Text(context.l10n.close), ), DropdownMenuItem( value: CloseBehavior.minimizeToTray, - child: Text("Minimize to Tray"), + child: Text(context.l10n.minimize_to_tray), ), ], onChanged: (value) { @@ -389,13 +383,13 @@ class SettingsPage extends HookConsumerWidget { ), SwitchListTile( secondary: const Icon(SpotubeIcons.tray), - title: const Text("Show System Tray Icon"), + title: Text(context.l10n.show_tray_icon), value: preferences.showSystemTrayIcon, onChanged: preferences.setShowSystemTrayIcon, ), ], Text( - " About", + " ${context.l10n.about}", style: theme.textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.bold), ), @@ -404,15 +398,15 @@ class SettingsPage extends HookConsumerWidget { SpotubeIcons.heart, color: Colors.pink, ), - title: const SizedBox( + title: SizedBox( height: 50, width: 200, child: Align( alignment: Alignment.centerLeft, child: AutoSizeText( - "We know you Love Spotube", + context.l10n.u_love_spotube, maxLines: 1, - style: TextStyle( + style: const TextStyle( color: Colors.pink, fontWeight: FontWeight.bold, ), @@ -436,10 +430,10 @@ class SettingsPage extends HookConsumerWidget { }, child: Row( mainAxisSize: MainAxisSize.min, - children: const [ - Icon(SpotubeIcons.heart), - SizedBox(width: 5), - Text("Please Sponsor/Donate"), + children: [ + const Icon(SpotubeIcons.heart), + const SizedBox(width: 5), + Text(context.l10n.please_sponsor), ], ), ), @@ -447,14 +441,14 @@ class SettingsPage extends HookConsumerWidget { if (Env.enableUpdateChecker) SwitchListTile( secondary: const Icon(SpotubeIcons.update), - title: const Text("Check for Update"), + title: Text(context.l10n.check_for_updates), value: preferences.checkUpdate, onChanged: (checked) => preferences.setCheckUpdate(checked), ), ListTile( leading: const Icon(SpotubeIcons.info), - title: const Text("About Spotube"), + title: Text(context.l10n.about_spotube), trailing: const Icon(SpotubeIcons.angleRight), onTap: () { GoRouter.of(context).push("/settings/about");