feat: localize settings, about, login, player queue with Bengali and English translations

This commit is contained in:
Kingkor Roy Tirtho 2023-04-29 13:46:42 +06:00
parent c55133dc8b
commit a5c36bbb20
10 changed files with 307 additions and 145 deletions

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/provider/authentication_provider.dart';
@ -27,18 +28,18 @@ class TokenLoginForm extends HookConsumerWidget {
children: [ children: [
TextField( TextField(
controller: directCodeController, controller: directCodeController,
decoration: const InputDecoration( decoration: InputDecoration(
hintText: "Spotify \"sp_dc\" Cookie", hintText: context.l10n.spotify_cookie("\"sp_dc\""),
labelText: "sp_dc Cookie", labelText: context.l10n.cookie_name_cookie("sp_dc"),
), ),
keyboardType: TextInputType.visiblePassword, keyboardType: TextInputType.visiblePassword,
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
TextField( TextField(
controller: keyCodeController, controller: keyCodeController,
decoration: const InputDecoration( decoration: InputDecoration(
hintText: "Spotify \"sp_key\" Cookie", hintText: context.l10n.spotify_cookie("\"sp_key\""),
labelText: "sp_key Cookie", labelText: context.l10n.cookie_name_cookie("sp_key"),
), ),
keyboardType: TextInputType.visiblePassword, keyboardType: TextInputType.visiblePassword,
), ),
@ -48,8 +49,8 @@ class TokenLoginForm extends HookConsumerWidget {
if (keyCodeController.text.isEmpty || if (keyCodeController.text.isEmpty ||
directCodeController.text.isEmpty) { directCodeController.text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( SnackBar(
content: Text("Please fill in all fields"), content: Text(context.l10n.fill_in_all_fields),
behavior: SnackBarBehavior.floating, behavior: SnackBarBehavior.floating,
), ),
); );
@ -65,7 +66,7 @@ class TokenLoginForm extends HookConsumerWidget {
onDone?.call(); onDone?.call();
} }
}, },
child: const Text("Submit"), child: Text(context.l10n.submit),
) )
], ],
), ),

View File

@ -8,6 +8,7 @@ import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/fallbacks/not_found.dart'; import 'package:spotube/components/shared/fallbacks/not_found.dart';
import 'package:spotube/components/shared/track_table/track_tile.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/hooks/use_auto_scroll_controller.dart';
import 'package:spotube/provider/playlist_queue_provider.dart'; import 'package:spotube/provider/playlist_queue_provider.dart';
import 'package:spotube/utils/primitive_utils.dart'; import 'package:spotube/utils/primitive_utils.dart';
@ -79,7 +80,7 @@ class PlayerQueue extends HookConsumerWidget {
children: [ children: [
const SizedBox(width: 10), const SizedBox(width: 10),
Text( Text(
"${tracks.length} tracks in Queue", context.l10n.tracks_in_queue(tracks.length),
style: TextStyle( style: TextStyle(
color: headlineColor, color: headlineColor,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -94,10 +95,10 @@ class PlayerQueue extends HookConsumerWidget {
foregroundColor: theme.textTheme.headlineSmall?.color, foregroundColor: theme.textTheme.headlineSmall?.color,
), ),
child: Row( child: Row(
children: const [ children: [
Icon(SpotubeIcons.playlistRemove), const Icon(SpotubeIcons.playlistRemove),
SizedBox(width: 5), const SizedBox(width: 5),
Text("Clear All"), Text(context.l10n.clear_all),
], ],
), ),
onPressed: () { onPressed: () {

View File

@ -5,6 +5,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.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/models/spotube_track.dart'; import 'package:spotube/models/spotube_track.dart';
import 'package:spotube/provider/playlist_queue_provider.dart'; import 'package:spotube/provider/playlist_queue_provider.dart';
import 'package:spotube/utils/primitive_utils.dart'; import 'package:spotube/utils/primitive_utils.dart';
@ -58,7 +59,7 @@ class SiblingTracksSheet extends HookConsumerWidget {
appBar: AppBar( appBar: AppBar(
centerTitle: true, centerTitle: true,
title: Text( title: Text(
'Alternative Tracks Sources', context.l10n.alternative_track_sources,
style: theme.textTheme.headlineSmall, style: theme.textTheme.headlineSmall,
), ),
automaticallyImplyLeading: false, automaticallyImplyLeading: false,

View File

@ -56,7 +56,7 @@
"artist_url_copied": "শিল্পীর URL কপি করা হয়েছে", "artist_url_copied": "শিল্পীর URL কপি করা হয়েছে",
"added_to_queue": "{tracks}টি গানের ট্র্যাক কিউতে যোগ করা হয়েছে", "added_to_queue": "{tracks}টি গানের ট্র্যাক কিউতে যোগ করা হয়েছে",
"filter_albums": "অ্যালবাম অনুসন্ধান করুন...", "filter_albums": "অ্যালবাম অনুসন্ধান করুন...",
"synced": "সময়ের সাথে সুসংগত", "synced": "সময় সুসংগত",
"plain": "অসুসংগত", "plain": "অসুসংগত",
"shuffle": "অদলবদল", "shuffle": "অদলবদল",
"search_tracks": "গান অনুসন্ধান করুন...", "search_tracks": "গান অনুসন্ধান করুন...",
@ -98,5 +98,88 @@
"repeat_playlist": "প্লেলিস্ট শেষে পুনরায় চালান", "repeat_playlist": "প্লেলিস্ট শেষে পুনরায় চালান",
"queue": "গানের কিউ", "queue": "গানের কিউ",
"alternative_track_sources": "বিকল্প গানের উৎস", "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\" এর মান সংশ্লিষ্ট ফিল্ডে পেস্ট করুন"
} }

View File

@ -98,5 +98,88 @@
"repeat_playlist": "Repeat playlist", "repeat_playlist": "Repeat playlist",
"queue": "Queue", "queue": "Queue",
"alternative_track_sources": "Alternative track sources", "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"
} }

View File

@ -5,6 +5,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/collections/assets.gen.dart'; import 'package:spotube/collections/assets.gen.dart';
import 'package:spotube/components/desktop_login/login_form.dart'; import 'package:spotube/components/desktop_login/login_form.dart';
import 'package:spotube/components/shared/page_window_title_bar.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/use_breakpoints.dart'; import 'package:spotube/hooks/use_breakpoints.dart';
class DesktopLoginPage extends HookConsumerWidget { class DesktopLoginPage extends HookConsumerWidget {
@ -37,11 +38,11 @@ class DesktopLoginPage extends HookConsumerWidget {
(breakpoint <= Breakpoints.md ? .5 : .3), (breakpoint <= Breakpoints.md ? .5 : .3),
), ),
Text( Text(
"Add your spotify credentials to get started", context.l10n.add_spotify_credentials,
style: theme.textTheme.titleMedium, style: theme.textTheme.titleMedium,
), ),
Text( 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, style: theme.textTheme.labelMedium,
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
@ -53,10 +54,10 @@ class DesktopLoginPage extends HookConsumerWidget {
alignment: WrapAlignment.center, alignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center, crossAxisAlignment: WrapCrossAlignment.center,
children: [ children: [
const Text("Don't know how to do this?"), Text(context.l10n.know_how_to_login),
TextButton( TextButton(
child: const Text( child: Text(
"Follow along the Step by Step guide", context.l10n.follow_step_by_step_guide,
), ),
onPressed: () => GoRouter.of(context).push( onPressed: () => GoRouter.of(context).push(
"/login-tutorial", "/login-tutorial",

View File

@ -7,6 +7,7 @@ import 'package:spotube/collections/assets.gen.dart';
import 'package:spotube/components/desktop_login/login_form.dart'; import 'package:spotube/components/desktop_login/login_form.dart';
import 'package:spotube/components/shared/links/hyper_link.dart'; import 'package:spotube/components/shared/links/hyper_link.dart';
import 'package:spotube/components/shared/page_window_title_bar.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/provider/authentication_provider.dart';
import 'package:spotube/utils/service_utils.dart'; import 'package:spotube/utils/service_utils.dart';
@ -28,7 +29,7 @@ class LoginTutorial extends ConsumerWidget {
return Scaffold( return Scaffold(
appBar: PageWindowTitleBar( appBar: PageWindowTitleBar(
leading: TextButton( leading: TextButton(
child: const Text("Exit"), child: Text(context.l10n.exit),
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
@ -38,13 +39,13 @@ class LoginTutorial extends ConsumerWidget {
key: key, key: key,
globalBackgroundColor: theme.scaffoldBackgroundColor, globalBackgroundColor: theme.scaffoldBackgroundColor,
overrideBack: OutlinedButton( overrideBack: OutlinedButton(
child: const Center(child: Text("Previous")), child: Center(child: Text(context.l10n.previous)),
onPressed: () { onPressed: () {
(key.currentState as IntroductionScreenState).previous(); (key.currentState as IntroductionScreenState).previous();
}, },
), ),
overrideNext: FilledButton( overrideNext: FilledButton(
child: const Center(child: Text("Next")), child: Center(child: Text(context.l10n.next)),
onPressed: () { onPressed: () {
(key.currentState as IntroductionScreenState).next(); (key.currentState as IntroductionScreenState).next();
}, },
@ -56,64 +57,56 @@ class LoginTutorial extends ConsumerWidget {
ServiceUtils.navigate(context, "/"); ServiceUtils.navigate(context, "/");
} }
: null, : null,
child: const Center(child: Text("Done")), child: Center(child: Text(context.l10n.done)),
), ),
pages: [ pages: [
PageViewModel( PageViewModel(
decoration: pageDecoration, decoration: pageDecoration,
title: "Step 1", title: context.l10n.step_1,
image: Assets.tutorial.step1.image(), image: Assets.tutorial.step1.image(),
bodyWidget: Wrap( bodyWidget: Wrap(
children: const [ children: [
Text( Text(context.l10n.first_go_to),
"First, Go to ", const SizedBox(width: 5),
), const Hyperlink(
Hyperlink(
"accounts.spotify.com ", "accounts.spotify.com ",
"https://accounts.spotify.com", "https://accounts.spotify.com",
), ),
Text( Text(context.l10n.login_if_not_logged_in),
"and Login/Sign up if you're not logged in",
),
], ],
), ),
), ),
PageViewModel( PageViewModel(
decoration: pageDecoration, decoration: pageDecoration,
title: "Step 2", title: context.l10n.step_2,
image: Assets.tutorial.step2.image(), image: Assets.tutorial.step2.image(),
bodyWidget: const Text( bodyWidget:
"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", Text(context.l10n.step_2_steps, textAlign: TextAlign.left),
textAlign: TextAlign.left,
),
), ),
PageViewModel( PageViewModel(
decoration: pageDecoration, decoration: pageDecoration,
title: "Step 3", title: context.l10n.step_3,
image: Assets.tutorial.step3.image(), image: Assets.tutorial.step3.image(),
bodyWidget: const Text( bodyWidget:
"Copy the values of \"sp_dc\" and \"sp_key\" Cookies", Text(context.l10n.step_3_steps, textAlign: TextAlign.left),
textAlign: TextAlign.left,
),
), ),
if (authenticationNotifier.isLoggedIn) if (authenticationNotifier.isLoggedIn)
PageViewModel( PageViewModel(
decoration: pageDecoration.copyWith( decoration: pageDecoration.copyWith(
bodyAlignment: Alignment.center, bodyAlignment: Alignment.center,
), ),
title: "Success🥳", title: context.l10n.success_emoji,
image: Assets.success.image(), image: Assets.success.image(),
body: body: context.l10n.success_message,
"Now you're successfully Logged In with your Spotify account. Good Job, mate!",
) )
else else
PageViewModel( PageViewModel(
decoration: pageDecoration, decoration: pageDecoration,
title: "Step 5", title: context.l10n.step_4,
bodyWidget: Column( bodyWidget: Column(
children: [ children: [
Text( Text(
"Paste the copied \"sp_dc\" and \"sp_key\" values in the respective fields", context.l10n.step_4_steps,
style: theme.textTheme.labelMedium, style: theme.textTheme.labelMedium,
), ),
const SizedBox(height: 10), const SizedBox(height: 10),

View File

@ -10,6 +10,7 @@ import 'package:spotube/components/player/player_queue.dart';
import 'package:spotube/components/root/sidebar.dart'; import 'package:spotube/components/root/sidebar.dart';
import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart'; import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart';
import 'package:spotube/components/shared/page_window_title_bar.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/hooks/use_force_update.dart';
import 'package:spotube/pages/lyrics/plain_lyrics.dart'; import 'package:spotube/pages/lyrics/plain_lyrics.dart';
import 'package:spotube/pages/lyrics/synced_lyrics.dart'; import 'package:spotube/pages/lyrics/synced_lyrics.dart';
@ -82,16 +83,19 @@ class MiniLyricsPage extends HookConsumerWidget {
child: Sidebar.brandLogo(), child: Sidebar.brandLogo(),
), ),
const Spacer(), const Spacer(),
const SizedBox( SizedBox(
height: 30, height: 30,
child: TabBar( child: TabBar(
tabs: [Tab(text: 'Synced'), Tab(text: 'Plain')], tabs: [
Tab(text: context.l10n.synced),
Tab(text: context.l10n.plain),
],
isScrollable: true, isScrollable: true,
), ),
), ),
const Spacer(), const Spacer(),
IconButton( IconButton(
tooltip: 'Show/Hide UI on hover', tooltip: context.l10n.show_hide_ui_on_hover,
icon: hoverMode.value icon: hoverMode.value
? const Icon(SpotubeIcons.hoverOn) ? const Icon(SpotubeIcons.hoverOn)
: const Icon(SpotubeIcons.hoverOff), : const Icon(SpotubeIcons.hoverOff),
@ -112,7 +116,7 @@ class MiniLyricsPage extends HookConsumerWidget {
future: DesktopTools.window.isAlwaysOnTop(), future: DesktopTools.window.isAlwaysOnTop(),
builder: (context, snapshot) { builder: (context, snapshot) {
return IconButton( return IconButton(
tooltip: 'Always on top', tooltip: context.l10n.always_on_top,
icon: Icon( icon: Icon(
snapshot.data == true snapshot.data == true
? SpotubeIcons.pinOn ? SpotubeIcons.pinOn
@ -173,7 +177,7 @@ class MiniLyricsPage extends HookConsumerWidget {
children: [ children: [
IconButton( IconButton(
icon: const Icon(SpotubeIcons.queue), icon: const Icon(SpotubeIcons.queue),
tooltip: 'Queue', tooltip: context.l10n.queue,
onPressed: playlistQueue != null onPressed: playlistQueue != null
? () { ? () {
showModalBottomSheet( showModalBottomSheet(
@ -199,7 +203,7 @@ class MiniLyricsPage extends HookConsumerWidget {
), ),
Flexible(child: PlayerControls(compact: true)), Flexible(child: PlayerControls(compact: true)),
IconButton( IconButton(
tooltip: 'Exit Mini Player', tooltip: context.l10n.exit_mini_player,
icon: const Icon(SpotubeIcons.maximize), icon: const Icon(SpotubeIcons.maximize),
onPressed: () async { onPressed: () async {
try { try {

View File

@ -3,6 +3,7 @@ import 'package:flutter/services.dart';
import 'package:spotube/collections/assets.gen.dart'; import 'package:spotube/collections/assets.gen.dart';
import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/components/shared/page_window_title_bar.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:spotube/hooks/use_package_info.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
@ -24,9 +25,9 @@ class AboutSpotube extends HookConsumerWidget {
final theme = Theme.of(context); final theme = Theme.of(context);
return Scaffold( return Scaffold(
appBar: const PageWindowTitleBar( appBar: PageWindowTitleBar(
leading: BackButton(), leading: const BackButton(),
title: Text("About Spotube"), title: Text(context.l10n.about_spotube),
), ),
body: SingleChildScrollView( body: SingleChildScrollView(
child: Padding( child: Padding(
@ -42,16 +43,16 @@ class AboutSpotube extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"Spotube, a light-weight, cross-platform, free-for-all spotify client", context.l10n.spotube_description,
style: theme.textTheme.titleLarge, style: theme.textTheme.titleLarge,
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Text( Text(
"Founder: Kingkor Roy Tirtho", "${context.l10n.founder}: ${context.l10n.kingkor_roy_tirtho}",
style: TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
@ -68,11 +69,11 @@ class AboutSpotube extends HookConsumerWidget {
), ),
const SizedBox(height: 5), const SizedBox(height: 5),
Text( Text(
"Version: v${packageInfo.version}", "${context.l10n.version}: v${packageInfo.version}",
), ),
const SizedBox(height: 5), const SizedBox(height: 5),
Text( Text(
"Build Number: ${packageInfo.buildNumber.replaceAll(".", " ")}", "${context.l10n.build_number}: ${packageInfo.buildNumber.replaceAll(".", " ")}",
), ),
const SizedBox(height: 5), const SizedBox(height: 5),
InkWell( InkWell(
@ -82,8 +83,8 @@ class AboutSpotube extends HookConsumerWidget {
mode: LaunchMode.externalApplication, mode: LaunchMode.externalApplication,
); );
}, },
child: const Text( child: Text(
"Repository: https://github.com/KRTirtho/spotube", "${context.l10n.repository}: https://github.com/KRTirtho/spotube",
), ),
), ),
const SizedBox(height: 5), const SizedBox(height: 5),
@ -94,8 +95,8 @@ class AboutSpotube extends HookConsumerWidget {
mode: LaunchMode.externalApplication, mode: LaunchMode.externalApplication,
); );
}, },
child: const Text( child: Text(
"License: BSD-4-Clause", "${context.l10n.license}: BSD-4-Clause",
), ),
), ),
const SizedBox(height: 5), const SizedBox(height: 5),
@ -106,8 +107,8 @@ class AboutSpotube extends HookConsumerWidget {
mode: LaunchMode.externalApplication, mode: LaunchMode.externalApplication,
); );
}, },
child: const Text( child: Text(
"Bugs+Issues: https://github.com/KRTirtho/spotube/issues", "${context.l10n.bug_issues}: https://github.com/KRTirtho/spotube/issues",
), ),
), ),
], ],
@ -186,12 +187,12 @@ class AboutSpotube extends HookConsumerWidget {
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
Text( Text(
"Made with ❤️ in Bangladesh🇧🇩", context.l10n.made_with,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: theme.textTheme.bodySmall, style: theme.textTheme.bodySmall,
), ),
Text( Text(
"© 2021-${DateTime.now().year} Kingkor Roy Tirtho", context.l10n.copyright(DateTime.now().year),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: theme.textTheme.bodySmall, style: theme.textTheme.bodySmall,
), ),

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/adaptive/adaptive_list_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/collections/spotify_markets.dart'; import 'package:spotube/collections/spotify_markets.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/l10n/l10n.dart'; import 'package:spotube/l10n/l10n.dart';
import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/provider/downloader_provider.dart'; import 'package:spotube/provider/downloader_provider.dart';
@ -39,7 +40,7 @@ class SettingsPage extends HookConsumerWidget {
final pickDownloadLocation = useCallback(() async { final pickDownloadLocation = useCallback(() async {
final dirStr = await FilePicker.platform.getDirectoryPath( final dirStr = await FilePicker.platform.getDirectoryPath(
dialogTitle: "Download Location", dialogTitle: context.l10n.download_location,
); );
if (dirStr == null) return; if (dirStr == null) return;
preferences.setDownloadLocation(dirStr); preferences.setDownloadLocation(dirStr);
@ -48,8 +49,8 @@ class SettingsPage extends HookConsumerWidget {
return SafeArea( return SafeArea(
bottom: false, bottom: false,
child: Scaffold( child: Scaffold(
appBar: const PageWindowTitleBar( appBar: PageWindowTitleBar(
title: Text("Settings"), title: Text(context.l10n.settings),
centerTitle: true, centerTitle: true,
), ),
body: Row( body: Row(
@ -61,7 +62,7 @@ class SettingsPage extends HookConsumerWidget {
child: ListView( child: ListView(
children: [ children: [
Text( Text(
" Account", " ${context.l10n.account}",
style: theme.textTheme.headlineSmall style: theme.textTheme.headlineSmall
?.copyWith(fontWeight: FontWeight.bold), ?.copyWith(fontWeight: FontWeight.bold),
), ),
@ -74,7 +75,7 @@ class SettingsPage extends HookConsumerWidget {
title: Align( title: Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: AutoSizeText( child: AutoSizeText(
"Login with your Spotify account", context.l10n.login_with_spotify,
maxLines: 1, maxLines: 1,
style: TextStyle( style: TextStyle(
color: theme.colorScheme.primary, 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 else
Builder(builder: (context) { Builder(builder: (context) {
return ListTile( return ListTile(
leading: const Icon(SpotubeIcons.logout), leading: const Icon(SpotubeIcons.logout),
title: const SizedBox( title: SizedBox(
height: 50, height: 50,
width: 180, width: 180,
child: Align( child: Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: AutoSizeText( child: AutoSizeText(
"Log out of this account", context.l10n.logout_of_this_account,
maxLines: 1, maxLines: 1,
), ),
), ),
@ -124,24 +127,24 @@ class SettingsPage extends HookConsumerWidget {
.logout(); .logout();
GoRouter.of(context).pop(); GoRouter.of(context).pop();
}, },
child: const Text("Logout"), child: Text(context.l10n.logout),
), ),
); );
}), }),
Text( Text(
" Language & Region", " ${context.l10n.language_region}",
style: theme.textTheme.headlineSmall style: theme.textTheme.headlineSmall
?.copyWith(fontWeight: FontWeight.bold), ?.copyWith(fontWeight: FontWeight.bold),
), ),
ListTile( ListTile(
leading: const Icon(SpotubeIcons.language), leading: const Icon(SpotubeIcons.language),
title: const Text("Language"), title: Text(context.l10n.language),
trailing: DropdownButton<Locale>( trailing: DropdownButton<Locale>(
value: preferences.locale, value: preferences.locale,
items: [ items: [
const DropdownMenuItem( DropdownMenuItem(
value: Locale("system"), value: const Locale("system"),
child: Text("System Default"), child: Text(context.l10n.system_default),
), ),
for (final locale in L10n.all) for (final locale in L10n.all)
DropdownMenuItem( DropdownMenuItem(
@ -158,8 +161,8 @@ class SettingsPage extends HookConsumerWidget {
), ),
AdaptiveListTile( AdaptiveListTile(
leading: const Icon(SpotubeIcons.shoppingBag), leading: const Icon(SpotubeIcons.shoppingBag),
title: const Text("Market Place Region"), title: Text(context.l10n.market_place_region),
subtitle: const Text("Recommendation Country"), subtitle: Text(context.l10n.recommendation_country),
trailing: (context, update) => ConstrainedBox( trailing: (context, update) => ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 350), constraints: const BoxConstraints(maxWidth: 350),
child: DropdownMenu( child: DropdownMenu(
@ -183,29 +186,27 @@ class SettingsPage extends HookConsumerWidget {
), ),
), ),
Text( Text(
" Appearance", " ${context.l10n.appearance}",
style: theme.textTheme.headlineSmall style: theme.textTheme.headlineSmall
?.copyWith(fontWeight: FontWeight.bold), ?.copyWith(fontWeight: FontWeight.bold),
), ),
AdaptiveListTile( AdaptiveListTile(
leading: const Icon(SpotubeIcons.dashboard), leading: const Icon(SpotubeIcons.dashboard),
title: const Text("Layout Mode"), title: Text(context.l10n.layout_mode),
subtitle: const Text( subtitle: Text(context.l10n.override_layout_settings),
"Override responsive layout mode settings",
),
trailing: (context, update) => DropdownButton<LayoutMode>( trailing: (context, update) => DropdownButton<LayoutMode>(
items: const [ items: [
DropdownMenuItem( DropdownMenuItem(
value: LayoutMode.adaptive, value: LayoutMode.adaptive,
child: Text("Adaptive"), child: Text(context.l10n.adaptive),
), ),
DropdownMenuItem( DropdownMenuItem(
value: LayoutMode.compact, value: LayoutMode.compact,
child: Text("Compact"), child: Text(context.l10n.compact),
), ),
DropdownMenuItem( DropdownMenuItem(
value: LayoutMode.extended, value: LayoutMode.extended,
child: Text("Extended"), child: Text(context.l10n.extended),
), ),
], ],
value: preferences.layoutMode, value: preferences.layoutMode,
@ -219,21 +220,21 @@ class SettingsPage extends HookConsumerWidget {
), ),
AdaptiveListTile( AdaptiveListTile(
leading: const Icon(SpotubeIcons.darkMode), leading: const Icon(SpotubeIcons.darkMode),
title: const Text("Theme"), title: Text(context.l10n.theme),
trailing: (context, update) => DropdownButton<ThemeMode>( trailing: (context, update) => DropdownButton<ThemeMode>(
value: preferences.themeMode, value: preferences.themeMode,
items: const [ items: [
DropdownMenuItem( DropdownMenuItem(
value: ThemeMode.dark, value: ThemeMode.dark,
child: Text("Dark"), child: Text(context.l10n.dark),
), ),
DropdownMenuItem( DropdownMenuItem(
value: ThemeMode.light, value: ThemeMode.light,
child: Text("Light"), child: Text(context.l10n.light),
), ),
DropdownMenuItem( DropdownMenuItem(
value: ThemeMode.system, value: ThemeMode.system,
child: Text("System"), child: Text(context.l10n.system),
), ),
], ],
onChanged: (value) { onChanged: (value) {
@ -246,7 +247,7 @@ class SettingsPage extends HookConsumerWidget {
), ),
ListTile( ListTile(
leading: const Icon(SpotubeIcons.palette), leading: const Icon(SpotubeIcons.palette),
title: const Text("Accent Color"), title: Text(context.l10n.accent_color),
contentPadding: const EdgeInsets.symmetric( contentPadding: const EdgeInsets.symmetric(
horizontal: 15, horizontal: 15,
vertical: 5, vertical: 5,
@ -260,32 +261,30 @@ class SettingsPage extends HookConsumerWidget {
), ),
SwitchListTile( SwitchListTile(
secondary: const Icon(SpotubeIcons.colorSync), secondary: const Icon(SpotubeIcons.colorSync),
title: const Text("Sync Album Color"), title: Text(context.l10n.sync_album_color),
subtitle: const Text( subtitle: Text(context.l10n.sync_album_color_description),
"Uses the dominant color of the album art as the accent color",
),
value: preferences.albumColorSync, value: preferences.albumColorSync,
onChanged: preferences.setAlbumColorSync, onChanged: preferences.setAlbumColorSync,
), ),
Text( Text(
" Playback", " ${context.l10n.playback}",
style: theme.textTheme.headlineSmall style: theme.textTheme.headlineSmall
?.copyWith(fontWeight: FontWeight.bold), ?.copyWith(fontWeight: FontWeight.bold),
), ),
AdaptiveListTile( AdaptiveListTile(
leading: const Icon(SpotubeIcons.audioQuality), leading: const Icon(SpotubeIcons.audioQuality),
title: const Text("Audio Quality"), title: Text(context.l10n.audio_quality),
trailing: (context, update) => trailing: (context, update) =>
DropdownButton<AudioQuality>( DropdownButton<AudioQuality>(
value: preferences.audioQuality, value: preferences.audioQuality,
items: const [ items: [
DropdownMenuItem( DropdownMenuItem(
value: AudioQuality.high, value: AudioQuality.high,
child: Text("High"), child: Text(context.l10n.high),
), ),
DropdownMenuItem( DropdownMenuItem(
value: AudioQuality.low, value: AudioQuality.low,
child: Text("Low"), child: Text(context.l10n.low),
), ),
], ],
onChanged: (value) { onChanged: (value) {
@ -298,10 +297,9 @@ class SettingsPage extends HookConsumerWidget {
), ),
SwitchListTile( SwitchListTile(
secondary: const Icon(SpotubeIcons.download), secondary: const Icon(SpotubeIcons.download),
title: const Text("Pre download and play"), title: Text(context.l10n.pre_download_play),
subtitle: const Text( subtitle:
"Instead of streaming audio, download bytes and play instead (Recommended for higher bandwidth users)", Text(context.l10n.pre_download_play_description),
),
value: preferences.predownload, value: preferences.predownload,
onChanged: (state) { onChanged: (state) {
preferences.setPredownload(state); preferences.setPredownload(state);
@ -309,9 +307,7 @@ class SettingsPage extends HookConsumerWidget {
), ),
SwitchListTile( SwitchListTile(
secondary: const Icon(SpotubeIcons.fastForward), secondary: const Icon(SpotubeIcons.fastForward),
title: const Text( title: Text(context.l10n.skip_non_music),
"Skip non-music segments (SponsorBlock)",
),
value: preferences.skipSponsorSegments, value: preferences.skipSponsorSegments,
onChanged: (state) { onChanged: (state) {
preferences.setSkipSponsorSegments(state); preferences.setSkipSponsorSegments(state);
@ -319,27 +315,25 @@ class SettingsPage extends HookConsumerWidget {
), ),
ListTile( ListTile(
leading: const Icon(SpotubeIcons.playlistRemove), leading: const Icon(SpotubeIcons.playlistRemove),
title: const Text("Blacklist"), title: Text(context.l10n.blacklist),
subtitle: const Text( subtitle: Text(context.l10n.blacklist_description),
"Blacklisted tracks and artists",
),
onTap: () { onTap: () {
GoRouter.of(context).push("/settings/blacklist"); GoRouter.of(context).push("/settings/blacklist");
}, },
trailing: const Icon(SpotubeIcons.angleRight), trailing: const Icon(SpotubeIcons.angleRight),
), ),
Text( Text(
" Downloads", " ${context.l10n.downloads}",
style: theme.textTheme.headlineSmall style: theme.textTheme.headlineSmall
?.copyWith(fontWeight: FontWeight.bold), ?.copyWith(fontWeight: FontWeight.bold),
), ),
Tooltip( Tooltip(
message: isDownloading message: isDownloading
? "Please wait for the current download to finish" ? context.l10n.wait_for_download_to_finish
: "", : "",
child: ListTile( child: ListTile(
leading: const Icon(SpotubeIcons.download), leading: const Icon(SpotubeIcons.download),
title: const Text("Download Location"), title: Text(context.l10n.download_location),
subtitle: Text(preferences.downloadLocation), subtitle: Text(preferences.downloadLocation),
trailing: FilledButton( trailing: FilledButton(
onPressed: onPressed:
@ -351,7 +345,7 @@ class SettingsPage extends HookConsumerWidget {
), ),
SwitchListTile( SwitchListTile(
secondary: const Icon(SpotubeIcons.lyrics), secondary: const Icon(SpotubeIcons.lyrics),
title: const Text("Download lyrics along with the Track"), title: Text(context.l10n.download_lyrics),
value: preferences.saveTrackLyrics, value: preferences.saveTrackLyrics,
onChanged: (state) { onChanged: (state) {
preferences.setSaveTrackLyrics(state); preferences.setSaveTrackLyrics(state);
@ -359,24 +353,24 @@ class SettingsPage extends HookConsumerWidget {
), ),
if (DesktopTools.platform.isDesktop) ...[ if (DesktopTools.platform.isDesktop) ...[
Text( Text(
" Desktop", " ${context.l10n.desktop}",
style: theme.textTheme.headlineSmall style: theme.textTheme.headlineSmall
?.copyWith(fontWeight: FontWeight.bold), ?.copyWith(fontWeight: FontWeight.bold),
), ),
AdaptiveListTile( AdaptiveListTile(
leading: const Icon(SpotubeIcons.close), leading: const Icon(SpotubeIcons.close),
title: const Text("Close Behavior"), title: Text(context.l10n.close_behavior),
trailing: (context, update) => trailing: (context, update) =>
DropdownButton<CloseBehavior>( DropdownButton<CloseBehavior>(
value: preferences.closeBehavior, value: preferences.closeBehavior,
items: const [ items: [
DropdownMenuItem( DropdownMenuItem(
value: CloseBehavior.close, value: CloseBehavior.close,
child: Text("Close"), child: Text(context.l10n.close),
), ),
DropdownMenuItem( DropdownMenuItem(
value: CloseBehavior.minimizeToTray, value: CloseBehavior.minimizeToTray,
child: Text("Minimize to Tray"), child: Text(context.l10n.minimize_to_tray),
), ),
], ],
onChanged: (value) { onChanged: (value) {
@ -389,13 +383,13 @@ class SettingsPage extends HookConsumerWidget {
), ),
SwitchListTile( SwitchListTile(
secondary: const Icon(SpotubeIcons.tray), secondary: const Icon(SpotubeIcons.tray),
title: const Text("Show System Tray Icon"), title: Text(context.l10n.show_tray_icon),
value: preferences.showSystemTrayIcon, value: preferences.showSystemTrayIcon,
onChanged: preferences.setShowSystemTrayIcon, onChanged: preferences.setShowSystemTrayIcon,
), ),
], ],
Text( Text(
" About", " ${context.l10n.about}",
style: theme.textTheme.headlineSmall style: theme.textTheme.headlineSmall
?.copyWith(fontWeight: FontWeight.bold), ?.copyWith(fontWeight: FontWeight.bold),
), ),
@ -404,15 +398,15 @@ class SettingsPage extends HookConsumerWidget {
SpotubeIcons.heart, SpotubeIcons.heart,
color: Colors.pink, color: Colors.pink,
), ),
title: const SizedBox( title: SizedBox(
height: 50, height: 50,
width: 200, width: 200,
child: Align( child: Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: AutoSizeText( child: AutoSizeText(
"We know you Love Spotube", context.l10n.u_love_spotube,
maxLines: 1, maxLines: 1,
style: TextStyle( style: const TextStyle(
color: Colors.pink, color: Colors.pink,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@ -436,10 +430,10 @@ class SettingsPage extends HookConsumerWidget {
}, },
child: Row( child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: const [ children: [
Icon(SpotubeIcons.heart), const Icon(SpotubeIcons.heart),
SizedBox(width: 5), const SizedBox(width: 5),
Text("Please Sponsor/Donate"), Text(context.l10n.please_sponsor),
], ],
), ),
), ),
@ -447,14 +441,14 @@ class SettingsPage extends HookConsumerWidget {
if (Env.enableUpdateChecker) if (Env.enableUpdateChecker)
SwitchListTile( SwitchListTile(
secondary: const Icon(SpotubeIcons.update), secondary: const Icon(SpotubeIcons.update),
title: const Text("Check for Update"), title: Text(context.l10n.check_for_updates),
value: preferences.checkUpdate, value: preferences.checkUpdate,
onChanged: (checked) => onChanged: (checked) =>
preferences.setCheckUpdate(checked), preferences.setCheckUpdate(checked),
), ),
ListTile( ListTile(
leading: const Icon(SpotubeIcons.info), leading: const Icon(SpotubeIcons.info),
title: const Text("About Spotube"), title: Text(context.l10n.about_spotube),
trailing: const Icon(SpotubeIcons.angleRight), trailing: const Icon(SpotubeIcons.angleRight),
onTap: () { onTap: () {
GoRouter.of(context).push("/settings/about"); GoRouter.of(context).push("/settings/about");