From ae9e3d8b7f09d040601aad9e9b5eba1668cc9d6f Mon Sep 17 00:00:00 2001 From: Josu Igoa Date: Tue, 16 Jul 2024 17:02:55 +0200 Subject: [PATCH] Make some hard coded strings translatable --- lib/collections/language_codes.dart | 6 +- .../dialogs/select_device_dialog.dart | 9 +-- lib/components/fallbacks/not_found.dart | 5 +- lib/components/playbutton_card.dart | 4 +- .../sections/header/header_actions.dart | 5 +- lib/l10n/app_en.arb | 61 ++++++++++++++- lib/l10n/app_eu.arb | 76 +++++++++++++++++-- lib/modules/home/sections/feed.dart | 5 +- lib/modules/home/sections/friends.dart | 3 +- lib/modules/home/sections/recent.dart | 3 +- .../playlist_generate/multi_select_field.dart | 2 +- lib/modules/player/player.dart | 3 +- lib/modules/playlist/playlist_card.dart | 5 +- .../playlist/playlist_create_dialog.dart | 2 +- lib/modules/root/update_dialog.dart | 13 ++-- .../settings/color_scheme_picker_dialog.dart | 7 +- lib/modules/stats/summary/summary.dart | 23 +++--- lib/modules/stats/top/albums.dart | 4 +- lib/modules/stats/top/artists.dart | 6 +- lib/modules/stats/top/top.dart | 29 +++---- lib/modules/stats/top/tracks.dart | 4 +- lib/pages/lyrics/lyrics.dart | 2 +- lib/pages/lyrics/synced_lyrics.dart | 2 +- lib/pages/profile/profile.dart | 22 +++--- lib/pages/settings/sections/accounts.dart | 2 +- lib/pages/stats/albums/albums.dart | 10 +-- lib/pages/stats/artists/artists.dart | 9 ++- lib/pages/stats/fees/fees.dart | 11 +-- lib/pages/stats/minutes/minutes.dart | 8 +- lib/pages/stats/playlists/playlists.dart | 9 ++- lib/pages/stats/streams/streams.dart | 8 +- 31 files changed, 251 insertions(+), 107 deletions(-) diff --git a/lib/collections/language_codes.dart b/lib/collections/language_codes.dart index f46e0efe..44da6ee6 100644 --- a/lib/collections/language_codes.dart +++ b/lib/collections/language_codes.dart @@ -83,7 +83,7 @@ abstract class LanguageLocals { // ), "eu": const ISOLanguageName( name: "Basque", - nativeName: "euskara", + nativeName: "Euskara", ), // "be": const ISOLanguageName( // name: "Belarusian", @@ -354,8 +354,8 @@ abstract class LanguageLocals { // nativeName: "KiKongo", // ), "ko": const ISOLanguageName( - name: "Korean", - nativeName: "한국어 (韓國語), 조선말 (朝鮮語)", + name: "Korean", + nativeName: "한국어 (韓國語), 조선말 (朝鮮語)", ), // "ku": const ISOLanguageName( // name: "Kurdish", diff --git a/lib/components/dialogs/select_device_dialog.dart b/lib/components/dialogs/select_device_dialog.dart index cd8dedb7..3a3bde60 100644 --- a/lib/components/dialogs/select_device_dialog.dart +++ b/lib/components/dialogs/select_device_dialog.dart @@ -15,15 +15,12 @@ class SelectDeviceDialog extends HookConsumerWidget { final remoteService = connectClients.asData!.value.resolvedService!; return AlertDialog( - title: const Text("Choose the device:"), + title: Text(context.l10n.choose_the_device), insetPadding: const EdgeInsets.all(16), content: Column( mainAxisSize: MainAxisSize.min, children: [ - const Text( - "There are multiple device connected.\n" - "Choose the device you want this action to take place", - ), + Text(context.l10n.multiple_device_connected), RadioListTile.adaptive( title: Text(remoteService.name), value: true, @@ -33,7 +30,7 @@ class SelectDeviceDialog extends HookConsumerWidget { }, ), RadioListTile.adaptive( - title: const Text("This Device"), + title: Text(context.l10n.this_device), value: false, groupValue: isRemoteService.value, onChanged: (value) { diff --git a/lib/components/fallbacks/not_found.dart b/lib/components/fallbacks/not_found.dart index 5a74f672..ce168f17 100644 --- a/lib/components/fallbacks/not_found.dart +++ b/lib/components/fallbacks/not_found.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:spotube/collections/assets.gen.dart'; +import 'package:spotube/extensions/context.dart'; class NotFound extends StatelessWidget { final bool vertical; @@ -18,9 +19,9 @@ class NotFound extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ - Text("Nothing found", style: theme.textTheme.titleLarge), + Text(context.l10n.nothing_found, style: theme.textTheme.titleLarge), Text( - "The box is empty", + context.l10n.the_box_is_empty, style: theme.textTheme.titleMedium, ), ], diff --git a/lib/components/playbutton_card.dart b/lib/components/playbutton_card.dart index a0b96ab8..a1a9bfb4 100644 --- a/lib/components/playbutton_card.dart +++ b/lib/components/playbutton_card.dart @@ -3,11 +3,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:gap/gap.dart'; import 'package:skeletonizer/skeletonizer.dart'; - import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/components/hover_builder.dart'; import 'package:spotube/components/image/universal_image.dart'; import 'package:spotube/extensions/constrains.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/string.dart'; import 'package:spotube/hooks/utils/use_breakpoint_value.dart'; import 'package:spotube/hooks/utils/use_brightness_value.dart'; @@ -128,7 +128,7 @@ class PlaybuttonCard extends HookWidget { ), if (isHovered) Text( - "Owned by you", + context.l10n.owned_by_you, style: theme.textTheme.bodySmall?.copyWith( color: Colors.white, ), diff --git a/lib/components/tracks_view/sections/header/header_actions.dart b/lib/components/tracks_view/sections/header/header_actions.dart index 94f0baa2..8e378f97 100644 --- a/lib/components/tracks_view/sections/header/header_actions.dart +++ b/lib/components/tracks_view/sections/header/header_actions.dart @@ -32,6 +32,9 @@ class TrackViewHeaderActions extends HookConsumerWidget { final auth = ref.watch(authenticationProvider); + final copiedText = + context.l10n.copied_shareurl_to_clipboard(props.shareUrl); + return Row( mainAxisSize: MainAxisSize.min, children: [ @@ -48,7 +51,7 @@ class TrackViewHeaderActions extends HookConsumerWidget { width: 300, behavior: SnackBarBehavior.floating, content: Text( - "Copied ${props.shareUrl} to clipboard", + copiedText, textAlign: TextAlign.center, ), ), diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ab615225..63c805f4 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -326,5 +326,64 @@ "this_device": "This Device", "remote": "Remote", "stats": "Stats", - "and_n_more": "and {count} more" + "and_n_more": "and {count} more", + "recently_played": "Recently Played", + "browse_more": "Browse More", + "no_title": "No Title", + "not_playing": "Not playing", + "epic_failure": "Epic failure!", + "added_num_tracks_to_queue": "Added {tracks_length} tracks to queue", + "spotube_has_an_update": "Spotube has an update", + "download_now": "Download Now", + "nightly_version": "Spotube Nightly {nightlyBuildNum} has been released", + "release_version": "Spotube v{version} has been released", + "read_the_latest": "Read the latest ", + "release_notes": "release notes", + "pick_color_scheme": "Pick color scheme", + "save": "Save", + "choose_the_device": "Choose the device:", + "multiple_device_connected": "There are multiple device connected.\nChoose the device you want this action to take place", + "nothing_found": "Nothing found", + "the_box_is_empty": "The box is empty", + "top_tracks": "Top Tracks", + "top_artists": "Top Artists", + "top_albums": "Top Albums", + "this_week": "This week", + "this_month": "This month", + "last_6_months": "Last 6 months", + "this_year": "This year", + "last_2_years": "Last 2 years", + "all_time": "All time", + "powered_by_provider": "Powered by {providerName}", + "email": "Email", + "profile_followers": "Followers", + "birthday": "Birthday", + "country": "Country", + "subscription": "Subscription", + "not_born": "Not born", + "hacker": "Hacker", + "profile": "Profile", + "no_name": "No Name", + "edit": "Edit", + "user_profile": "User Profile", + "count_plays": "{count} plays", + "streaming_fees_hypothetical": "Streaming fees (hypothetical)", + "minutes_listened": "Minutes listened", + "streamed_songs": "Streamed songs", + "count_streams": "{count} streams", + "owned_by_you": "Owned by you", + "copied_shareurl_to_clipboard": "Copied {shareUrl} to clipboard", + "spotify_hipotetical_calculation": "*This is calculated based on Spotify's per stream\npayout of $0.003 to $0.005. This is a hypothetical\ncalculation to give user insight about how much they\nwould have paid to the artists if they were to listen\ntheir song in Spotify.", + "count_mins": "{minutes} mins", + "summary_minutes": "minutes", + "summary_listened_to_music": "Listened to music", + "summary_songs": "songs", + "summary_streamed_overall": "Streamed overall", + "summary_owed_to_artists": "Owed to artists\nthis month", + "summary_artists": "artist's", + "summary_music_reached_you": "Music reached you", + "summary_full_albums": "full albums", + "summary_got_your_love": "Got your love", + "summary_playlists": "playlists", + "summary_were_on_repeat": "Were on repeat" } \ No newline at end of file diff --git a/lib/l10n/app_eu.arb b/lib/l10n/app_eu.arb index fb00a925..8f041581 100644 --- a/lib/l10n/app_eu.arb +++ b/lib/l10n/app_eu.arb @@ -107,6 +107,9 @@ "always_on_top": "Beti ikusgai", "exit_mini_player": "Irten mini erreproduzitzailetik", "download_location": "Deskargen kokapena", + "local_library": "Liburutegi lokala", + "add_library_location": "Gehitu liburutegira", + "remove_library_location": "Kendu liburutegitik", "account": "Kontua", "login_with_spotify": "Hasi saioa zure Spotify kontuarekin", "connect_with_spotify": "Spotify-rekin konektatu", @@ -118,8 +121,8 @@ "market_place_region": "Dendaren herrialdea", "recommendation_country": "Gomendio herrialdea", "appearance": "Itxura", - "layout_mode": "Diseinu modua", - "override_layout_settings": "Responsive diseinu moduaren ezarpenak ezeztatu", + "layout_mode": "Diseinua", + "override_layout_settings": "Responsive diseinuaren ezarpenak ezeztatu", "adaptive": "Moldagarria", "compact": "Trinkoa", "extended": "Hedatua", @@ -287,7 +290,7 @@ "genres": "Generoak", "explore_genres": "Esploratu generoak", "friends": "Lagunak", - "no_lyrics_available": "Sentitzen dut, ezin dira kanta honen hitzak aurkitu", + "no_lyrics_available": "Sentitzen dugu, ezin dira kanta honen hitzak aurkitu", "start_a_radio": "Hasi Irrati bat", "how_to_start_radio": "Nola hasi nahi duzu irratia?", "replace_queue_question": "Uneko zerrenda ordezkatu nahi duzu edo bertan gehitu?", @@ -295,6 +298,7 @@ "delete_playlist": "Ezabatu zerrenda", "delete_playlist_confirmation": "Ziur zaude zerrenda ezabatu nahi duzula?", "local_tracks": "Kanta lokalak", + "local_tab": "Lokalean", "song_link": "Kantaren lotura", "skip_this_nonsense": "Utzi txorakeria hau", "freedom_of_music": "“Musika Askatasuna”", @@ -321,9 +325,65 @@ "connect_client_alert": "{client} gailuak kontrolatzen zaitu", "this_device": "Gailu hau", "remote": "Urrunekoa", - "local_library": "Liburutegi lokala", - "add_library_location": "Gehitu liburutegira", - "remove_library_location": "Kendu liburutegitik", - "local_tab": "Tokiko", - "stats": "Estatistikak" + "stats": "Estatistikak", + "and_n_more": "eta {count} gehiago", + "recently_played": "Berriki entzunak", + "browse_more": "Gehiago Bilatu", + "no_title": "Titulurik ez", + "not_playing": "Erreprodukziorik ez", + "epic_failure": "Sekulako errorea!", + "added_num_tracks_to_queue": "{tracks_length} kanta gehitu dira zerrendara", + "spotube_has_an_update": "Spotube-ren eguneraketa bat dago", + "download_now": "Orain deskargatu", + "nightly_version": "Spotube {nightlyBuildNum} Nightly-a argitaratu da", + "release_version": "Spotube v{version} argitaratu da", + "read_the_latest": "Irakurri azken ", + "release_notes": "argitatratze oharrak", + "pick_color_scheme": "Aukeratu kolore eskema", + "save": "Gorde", + "choose_the_device": "Aukeratu gailua:", + "multiple_device_connected": "Hainbat gailu daude konektatuta.\nAukeratu zein gailutan aplikatu nahi duzun ekintza hau", + "nothing_found": "Ezer ez da aurkitu", + "the_box_is_empty": "Kaxa hutsik dago", + "top_tracks": "Top Kantak", + "top_artists": "Top Artistak", + "top_albums": "Top Albumak", + "this_week": "Aste honetan", + "this_month": "Hilabete honetan", + "last_6_months": "Azken 6 hilabeteetan", + "this_year": "Aurten", + "last_2_years": "Azken 2 urtetan", + "all_time": "Betidanik", + "powered_by_provider": "{providerName}-ren eskutik", + "email": "Email", + "profile_followers": "Jarraitzaileak", + "birthday": "Jaiotze-data", + "country": "Herrialdea", + "subscription": "Harpidetzak", + "not_born": "Jaio gabe", + "hacker": "Hacker", + "profile": "Profila", + "no_name": "Izenik Ez", + "edit": "Editatu", + "user_profile": "Erabiltzaile Profila", + "count_plays": "{count} erreprodukzio", + "streaming_fees_hypothetical": "Streaming ordainketa (hipotetikoa)", + "minutes_listened": "Entzundako minutuak", + "streamed_songs": "Stream-eatutako kantak", + "count_streams": "{count} stream", + "owned_by_you": "Zure jabetzakoa", + "copied_shareurl_to_clipboard": "{shareUrl} arbelera kopiatua", + "spotify_hipotetical_calculation": "*Sportify-k stream bakoitzeko duen $0.003 eta $0.005\nordainsarian oinarritua da. Kalkulu hipotetiko bat,\nkanta hauek Spotify-n entzun bazenitu,\nberaiek artistari zenbat ordaiduko lioketen jakin dezazun.", + "count_mins": "{minutes} minutu", + "summary_minutes": "minutu", + "summary_listened_to_music": "Musika entzuten", + "summary_songs": "kanta", + "summary_streamed_overall": "Stream-eatuta oro har", + "summary_owed_to_artists": "Hilabete honetan\nartistei zor zaiena", + "summary_artists": "artisten", + "summary_music_reached_you": "Musika ailegatu zaizu", + "summary_full_albums": "album osok", + "summary_got_your_love": "Izan dute zure maitasuna", + "summary_playlists": "zerrenda", + "summary_were_on_repeat": "Dituzu errepikatze moduan" } \ No newline at end of file diff --git a/lib/modules/home/sections/feed.dart b/lib/modules/home/sections/feed.dart index f66f01f2..8685fe19 100644 --- a/lib/modules/home/sections/feed.dart +++ b/lib/modules/home/sections/feed.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/components/horizontal_playbutton_card_view/horizontal_playbutton_card_view.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/pages/home/feed/feed_section.dart'; import 'package:spotube/provider/spotify/views/home.dart'; import 'package:spotube/utils/service_utils.dart'; @@ -33,14 +34,14 @@ class HomePageFeedSection extends HookConsumerWidget { else if (item.playlist != null) item.playlist!.asPlaylist ], - title: Text(section.title ?? "No Titel"), + title: Text(section.title ?? context.l10n.no_title), hasNextPage: false, isLoadingNextPage: false, onFetchMore: () {}, titleTrailing: Directionality( textDirection: TextDirection.rtl, child: TextButton.icon( - label: const Text("Browse More"), + label: Text(context.l10n.browse_more), icon: const Icon(SpotubeIcons.angleRight), onPressed: () => ServiceUtils.pushNamed( context, diff --git a/lib/modules/home/sections/friends.dart b/lib/modules/home/sections/friends.dart index d6bed6a8..6f59c209 100644 --- a/lib/modules/home/sections/friends.dart +++ b/lib/modules/home/sections/friends.dart @@ -6,6 +6,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotube/collections/fake.dart'; import 'package:spotube/modules/home/sections/friends/friend_item.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/utils/use_breakpoint_value.dart'; import 'package:spotube/models/spotify_friends.dart'; import 'package:spotube/provider/authentication/authentication.dart'; @@ -73,7 +74,7 @@ class HomePageFriendsSection extends HookConsumerWidget { child: Padding( padding: const EdgeInsets.all(8.0), child: Text( - 'Friends', + context.l10n.friends, style: Theme.of(context).textTheme.titleMedium, ), ), diff --git a/lib/modules/home/sections/recent.dart b/lib/modules/home/sections/recent.dart index b26c0e16..43c0459d 100644 --- a/lib/modules/home/sections/recent.dart +++ b/lib/modules/home/sections/recent.dart @@ -3,6 +3,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotube/collections/fake.dart'; import 'package:spotube/components/horizontal_playbutton_card_view/horizontal_playbutton_card_view.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/models/database/database.dart'; import 'package:spotube/provider/history/recent.dart'; @@ -22,7 +23,7 @@ class HomeRecentlyPlayedSection extends HookConsumerWidget { return Skeletonizer( enabled: history.isLoading, child: HorizontalPlaybuttonCardView( - title: const Text('Recently Played'), + title: Text(context.l10n.recently_played), items: [ for (final item in historyData) if (item.playlist != null) diff --git a/lib/modules/library/playlist_generate/multi_select_field.dart b/lib/modules/library/playlist_generate/multi_select_field.dart index e54fc2ba..8cafe02f 100644 --- a/lib/modules/library/playlist_generate/multi_select_field.dart +++ b/lib/modules/library/playlist_generate/multi_select_field.dart @@ -187,7 +187,7 @@ class _MultiSelectDialog extends HookWidget { return AlertDialog( scrollable: true, - title: dialogTitle ?? const Text('Select'), + title: dialogTitle ?? Text(context.l10n.select), contentPadding: mediaQuery.mdAndUp ? null : const EdgeInsets.all(16), insetPadding: const EdgeInsets.all(16), actions: [ diff --git a/lib/modules/player/player.dart b/lib/modules/player/player.dart index 6db84692..538af685 100644 --- a/lib/modules/player/player.dart +++ b/lib/modules/player/player.dart @@ -233,7 +233,8 @@ class PlayerView extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ AutoSizeText( - currentTrack?.name ?? "Not playing", + currentTrack?.name ?? + context.l10n.not_playing, style: TextStyle( color: titleTextColor, fontSize: 22, diff --git a/lib/modules/playlist/playlist_card.dart b/lib/modules/playlist/playlist_card.dart index d6ea2a46..df683a80 100644 --- a/lib/modules/playlist/playlist_card.dart +++ b/lib/modules/playlist/playlist_card.dart @@ -4,6 +4,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/dialogs/select_device_dialog.dart'; import 'package:spotube/components/playbutton_card.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/image.dart'; import 'package:spotube/models/connect/connect.dart'; import 'package:spotube/pages/playlist/playlist.dart'; @@ -133,8 +134,8 @@ class PlaylistCard extends HookConsumerWidget { historyNotifier.addPlaylists([playlist]); if (context.mounted) { final snackbar = SnackBar( - content: - Text("Added ${fetchedInitialTracks.length} tracks to queue"), + content: Text(context.l10n + .added_num_tracks_to_queue(fetchedInitialTracks.length)), action: SnackBarAction( label: "Undo", onPressed: () { diff --git a/lib/modules/playlist/playlist_create_dialog.dart b/lib/modules/playlist/playlist_create_dialog.dart index b9e4be8f..78680a1c 100644 --- a/lib/modules/playlist/playlist_create_dialog.dart +++ b/lib/modules/playlist/playlist_create_dialog.dart @@ -76,7 +76,7 @@ class PlaylistCreateDialog extends HookConsumerWidget { scaffold.showSnackBar( SnackBar( content: Text( - l10n.error(error.message ?? "Epic failure!"), + l10n.error(error.message ?? context.l10n.epic_failure), style: theme.textTheme.bodyMedium!.copyWith( color: theme.colorScheme.onError, ), diff --git a/lib/modules/root/update_dialog.dart b/lib/modules/root/update_dialog.dart index 4a313096..27b857df 100644 --- a/lib/modules/root/update_dialog.dart +++ b/lib/modules/root/update_dialog.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:spotube/components/links/anchor_button.dart'; import 'package:url_launcher/url_launcher_string.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:version/version.dart'; class RootAppUpdateDialog extends StatelessWidget { @@ -16,10 +17,10 @@ class RootAppUpdateDialog extends StatelessWidget { const url = "https://spotube.krtirtho.dev/downloads"; const nightlyUrl = "https://spotube.krtirtho.dev/downloads/nightly"; return AlertDialog( - title: const Text("Spotube has an update"), + title: Text(context.l10n.spotube_has_an_update), actions: [ FilledButton( - child: const Text("Download Now"), + child: Text(context.l10n.download_now), onPressed: () => launchUrlString( nightlyBuildNum != null ? nightlyUrl : url, mode: LaunchMode.externalApplication, @@ -31,16 +32,16 @@ class RootAppUpdateDialog extends StatelessWidget { children: [ Text( nightlyBuildNum != null - ? "Spotube Nightly $nightlyBuildNum has been released" - : "Spotube v$version has been released", + ? context.l10n.nightly_version(nightlyBuildNum!) + : context.l10n.release_version(version!), ), if (nightlyBuildNum == null) Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Text("Read the latest "), + Text(context.l10n.read_the_latest), AnchorButton( - "release notes", + context.l10n.release_notes, style: const TextStyle(color: Colors.blue), onTap: () => launchUrlString( url, diff --git a/lib/modules/settings/color_scheme_picker_dialog.dart b/lib/modules/settings/color_scheme_picker_dialog.dart index 8d098375..550446bc 100644 --- a/lib/modules/settings/color_scheme_picker_dialog.dart +++ b/lib/modules/settings/color_scheme_picker_dialog.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/user_preferences/user_preferences_provider.dart'; import 'package:system_theme/system_theme.dart'; @@ -69,17 +70,17 @@ class ColorSchemePickerDialog extends HookConsumerWidget { } return AlertDialog( - title: const Text("Pick color scheme"), + title: Text(context.l10n.pick_color_scheme), actions: [ OutlinedButton( - child: const Text("Cancel"), + child: Text(context.l10n.cancel), onPressed: () { Navigator.pop(context); }, ), FilledButton( onPressed: onOk, - child: const Text("Save"), + child: Text(context.l10n.save), ), ], content: SizedBox( diff --git a/lib/modules/stats/summary/summary.dart b/lib/modules/stats/summary/summary.dart index ef8aa1b0..46068fec 100644 --- a/lib/modules/stats/summary/summary.dart +++ b/lib/modules/stats/summary/summary.dart @@ -5,6 +5,7 @@ import 'package:spotube/collections/fake.dart'; import 'package:spotube/collections/formatters.dart'; import 'package:spotube/modules/stats/summary/summary_card.dart'; import 'package:spotube/extensions/constrains.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/pages/stats/albums/albums.dart'; import 'package:spotube/pages/stats/artists/artists.dart'; import 'package:spotube/pages/stats/fees/fees.dart'; @@ -45,8 +46,8 @@ class StatsPageSummarySection extends HookConsumerWidget { delegate: SliverChildListDelegate([ SummaryCard( title: summaryData.duration.inMinutes.toDouble(), - unit: "minutes", - description: 'Listened to music', + unit: context.l10n.summary_minutes, + description: context.l10n.summary_listened_to_music, color: Colors.purple, onTap: () { ServiceUtils.pushNamed(context, StatsMinutesPage.name); @@ -54,8 +55,8 @@ class StatsPageSummarySection extends HookConsumerWidget { ), SummaryCard( title: summaryData.tracks.toDouble(), - unit: "songs", - description: 'Streamed overall', + unit: context.l10n.summary_songs, + description: context.l10n.summary_streamed_overall, color: Colors.lightBlue, onTap: () { ServiceUtils.pushNamed(context, StatsStreamsPage.name); @@ -64,7 +65,7 @@ class StatsPageSummarySection extends HookConsumerWidget { SummaryCard.unformatted( title: usdFormatter.format(summaryData.fees.toDouble()), unit: "", - description: 'Owed to artists\nthis month', + description: context.l10n.summary_owed_to_artists, color: Colors.green, onTap: () { ServiceUtils.pushNamed(context, StatsStreamFeesPage.name); @@ -72,8 +73,8 @@ class StatsPageSummarySection extends HookConsumerWidget { ), SummaryCard( title: summaryData.artists.toDouble(), - unit: "artist's", - description: 'Music reached you', + unit: context.l10n.summary_artists, + description: context.l10n.summary_music_reached_you, color: Colors.yellow, onTap: () { ServiceUtils.pushNamed(context, StatsArtistsPage.name); @@ -81,8 +82,8 @@ class StatsPageSummarySection extends HookConsumerWidget { ), SummaryCard( title: summaryData.albums.toDouble(), - unit: "full albums", - description: 'Got your love', + unit: context.l10n.summary_full_albums, + description: context.l10n.summary_got_your_love, color: Colors.pink, onTap: () { ServiceUtils.pushNamed(context, StatsAlbumsPage.name); @@ -90,8 +91,8 @@ class StatsPageSummarySection extends HookConsumerWidget { ), SummaryCard( title: summaryData.playlists.toDouble(), - unit: "playlists", - description: 'Were on repeat', + unit: context.l10n.summary_playlists, + description: context.l10n.summary_were_on_repeat, color: Colors.teal, onTap: () { ServiceUtils.pushNamed(context, StatsPlaylistsPage.name); diff --git a/lib/modules/stats/top/albums.dart b/lib/modules/stats/top/albums.dart index 4329b871..e401340e 100644 --- a/lib/modules/stats/top/albums.dart +++ b/lib/modules/stats/top/albums.dart @@ -3,6 +3,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotube/collections/formatters.dart'; import 'package:spotube/modules/stats/common/album_item.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/history/top.dart'; import 'package:spotube/provider/history/top/albums.dart'; import 'package:spotube/provider/spotify/spotify.dart'; @@ -35,7 +36,8 @@ class TopAlbums extends HookConsumerWidget { return StatsAlbumItem( album: album.album, info: Text( - "${compactNumberFormatter.format(album.count)} plays", + context.l10n + .count_plays(compactNumberFormatter.format(album.count)), ), ); }, diff --git a/lib/modules/stats/top/artists.dart b/lib/modules/stats/top/artists.dart index d5eb2d0e..3e4e098d 100644 --- a/lib/modules/stats/top/artists.dart +++ b/lib/modules/stats/top/artists.dart @@ -4,6 +4,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotube/collections/formatters.dart'; import 'package:spotube/modules/stats/common/artist_item.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/history/top.dart'; import 'package:spotube/provider/history/top/tracks.dart'; import 'package:spotube/provider/spotify/spotify.dart'; @@ -38,7 +39,10 @@ class TopArtists extends HookConsumerWidget { final artist = artistsData[index]; return StatsArtistItem( artist: artist.artist, - info: Text("${compactNumberFormatter.format(artist.count)} plays"), + info: Text( + context.l10n + .count_plays(compactNumberFormatter.format(artist.count)), + ), ); }, ), diff --git a/lib/modules/stats/top/top.dart b/lib/modules/stats/top/top.dart index ea52c517..643064aa 100644 --- a/lib/modules/stats/top/top.dart +++ b/lib/modules/stats/top/top.dart @@ -5,6 +5,7 @@ import 'package:spotube/components/themed_button_tab_bar.dart'; import 'package:spotube/modules/stats/top/albums.dart'; import 'package:spotube/modules/stats/top/artists.dart'; import 'package:spotube/modules/stats/top/tracks.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/history/top.dart'; @@ -24,23 +25,23 @@ class StatsPageTopSection extends HookConsumerWidget { floating: true, flexibleSpace: ThemedButtonsTabBar( controller: tabController, - tabs: const [ + tabs: [ Tab( child: Padding( - padding: EdgeInsets.all(5), - child: Text("Top Tracks"), + padding: const EdgeInsets.all(5), + child: Text(context.l10n.top_tracks), ), ), Tab( child: Padding( - padding: EdgeInsets.all(5), - child: Text("Top Artists"), + padding: const EdgeInsets.all(5), + child: Text(context.l10n.top_artists), ), ), Tab( child: Padding( - padding: EdgeInsets.all(5), - child: Text("Top Albums"), + padding: const EdgeInsets.all(5), + child: Text(context.l10n.top_albums), ), ), ], @@ -61,30 +62,30 @@ class StatsPageTopSection extends HookConsumerWidget { historyDurationNotifier.update((_) => value); }, icon: const Icon(Icons.arrow_drop_down), - items: const [ + items: [ DropdownMenuItem( value: HistoryDuration.days7, - child: Text("This week"), + child: Text(context.l10n.this_week), ), DropdownMenuItem( value: HistoryDuration.days30, - child: Text("This month"), + child: Text(context.l10n.this_month), ), DropdownMenuItem( value: HistoryDuration.months6, - child: Text("Last 6 months"), + child: Text(context.l10n.last_6_months), ), DropdownMenuItem( value: HistoryDuration.year, - child: Text("This year"), + child: Text(context.l10n.this_year), ), DropdownMenuItem( value: HistoryDuration.years2, - child: Text("Last 2 years"), + child: Text(context.l10n.last_2_years), ), DropdownMenuItem( value: HistoryDuration.allTime, - child: Text("All time"), + child: Text(context.l10n.all_time), ), ], ), diff --git a/lib/modules/stats/top/tracks.dart b/lib/modules/stats/top/tracks.dart index be457b2e..7fba220d 100644 --- a/lib/modules/stats/top/tracks.dart +++ b/lib/modules/stats/top/tracks.dart @@ -3,6 +3,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotube/collections/formatters.dart'; import 'package:spotube/modules/stats/common/track_item.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/history/top.dart'; import 'package:spotube/provider/history/top/tracks.dart'; import 'package:spotube/provider/spotify/spotify.dart'; @@ -37,7 +38,8 @@ class TopTracks extends HookConsumerWidget { return StatsTrackItem( track: track.track, info: Text( - "${compactNumberFormatter.format(track.count)} plays", + context.l10n + .count_plays(compactNumberFormatter.format(track.count)), ), ); }, diff --git a/lib/pages/lyrics/lyrics.dart b/lib/pages/lyrics/lyrics.dart index 18ce6e28..810c18d6 100644 --- a/lib/pages/lyrics/lyrics.dart +++ b/lib/pages/lyrics/lyrics.dart @@ -73,7 +73,7 @@ class LyricsPage extends HookConsumerWidget { return Align( alignment: Alignment.bottomRight, - child: Text("Powered by $providerName"), + child: Text(context.l10n.powered_by_provider(providerName)), ); }, ), diff --git a/lib/pages/lyrics/synced_lyrics.dart b/lib/pages/lyrics/synced_lyrics.dart index c2bf7b81..643c1064 100644 --- a/lib/pages/lyrics/synced_lyrics.dart +++ b/lib/pages/lyrics/synced_lyrics.dart @@ -103,7 +103,7 @@ class SyncedLyrics extends HookConsumerWidget { backgroundColor: Colors.transparent, centerTitle: true, title: Text( - playlist.activeTrack?.name ?? "Not Playing", + playlist.activeTrack?.name ?? context.l10n.not_playing, style: headlineTextStyle, ), bottom: PreferredSize( diff --git a/lib/pages/profile/profile.dart b/lib/pages/profile/profile.dart index e6546960..67bd8f57 100644 --- a/lib/pages/profile/profile.dart +++ b/lib/pages/profile/profile.dart @@ -9,6 +9,7 @@ import 'package:spotube/collections/spotify_markets.dart'; import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/components/image/universal_image.dart'; import 'package:spotube/components/titlebar/titlebar.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/image.dart'; import 'package:spotube/provider/spotify/spotify.dart'; import 'package:url_launcher/url_launcher_string.dart'; @@ -27,21 +28,22 @@ class ProfilePage extends HookConsumerWidget { final userProperties = useMemoized( () => { - "Email": meData.email ?? "N/A", - "Followers": meData.followers?.total.toString() ?? "N/A", - "Birthday": meData.birthdate ?? "Not born", - "Country": spotifyMarkets + context.l10n.email: meData.email ?? "N/A", + context.l10n.profile_followers: + meData.followers?.total.toString() ?? "N/A", + context.l10n.birthday: meData.birthdate ?? context.l10n.not_born, + context.l10n.country: spotifyMarkets .firstWhere((market) => market.$1 == meData.country) .$2, - "Subscription": meData.product ?? "Hacker", + context.l10n.subscription: meData.product ?? context.l10n.hacker, }, [meData], ); return SafeArea( child: Scaffold( - appBar: const PageWindowTitleBar( - title: Text("Profile"), + appBar: PageWindowTitleBar( + title: Text(context.l10n.profile), titleSpacing: 0, automaticallyImplyLeading: true, centerTitle: false, @@ -72,7 +74,7 @@ class ProfilePage extends HookConsumerWidget { const SliverGap(10), SliverToBoxAdapter( child: Text( - meData.displayName ?? "No Name", + meData.displayName ?? context.l10n.no_name, style: textTheme.titleLarge, textAlign: TextAlign.center, ), @@ -85,7 +87,7 @@ class ProfilePage extends HookConsumerWidget { mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton.icon( - label: const Text("Edit"), + label: Text(context.l10n.edit), icon: const Icon(SpotubeIcons.edit), onPressed: () { launchUrlString( @@ -118,7 +120,7 @@ class ProfilePage extends HookConsumerWidget { child: Padding( padding: const EdgeInsets.all(6), child: Text( - key, + '$key', style: textTheme.titleSmall, ), ), diff --git a/lib/pages/settings/sections/accounts.dart b/lib/pages/settings/sections/accounts.dart index 7e37b68b..1b5b7e39 100644 --- a/lib/pages/settings/sections/accounts.dart +++ b/lib/pages/settings/sections/accounts.dart @@ -92,7 +92,7 @@ class SettingsAccountSection extends HookConsumerWidget { if (auth.asData?.value != null) ListTile( leading: const Icon(SpotubeIcons.user), - title: const Text("User Profile"), + title: Text(context.l10n.user_profile), trailing: Padding( padding: const EdgeInsets.all(8.0), child: CircleAvatar( diff --git a/lib/pages/stats/albums/albums.dart b/lib/pages/stats/albums/albums.dart index db0eedf6..e14a2f32 100644 --- a/lib/pages/stats/albums/albums.dart +++ b/lib/pages/stats/albums/albums.dart @@ -4,6 +4,7 @@ import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotube/collections/formatters.dart'; import 'package:spotube/components/titlebar/titlebar.dart'; import 'package:spotube/modules/stats/common/album_item.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/history/top.dart'; import 'package:spotube/provider/history/top/albums.dart'; @@ -24,10 +25,10 @@ class StatsAlbumsPage extends HookConsumerWidget { final albumsData = topAlbums.asData?.value.items ?? []; return Scaffold( - appBar: const PageWindowTitleBar( + appBar: PageWindowTitleBar( automaticallyImplyLeading: true, centerTitle: false, - title: Text("Albums"), + title: Text(context.l10n.albums), ), body: Skeletonizer( enabled: topAlbums.isLoading && !topAlbums.isLoadingNextPage, @@ -43,9 +44,8 @@ class StatsAlbumsPage extends HookConsumerWidget { final album = albumsData[index]; return StatsAlbumItem( album: album.album, - info: Text( - "${compactNumberFormatter.format(album.count)} plays", - ), + info: Text(context.l10n + .count_plays(compactNumberFormatter.format(album.count))), ); }, ), diff --git a/lib/pages/stats/artists/artists.dart b/lib/pages/stats/artists/artists.dart index 80ff5f23..436bbb57 100644 --- a/lib/pages/stats/artists/artists.dart +++ b/lib/pages/stats/artists/artists.dart @@ -5,6 +5,7 @@ import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotube/collections/formatters.dart'; import 'package:spotube/components/titlebar/titlebar.dart'; import 'package:spotube/modules/stats/common/artist_item.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/history/top.dart'; import 'package:spotube/provider/history/top/tracks.dart'; @@ -27,10 +28,10 @@ class StatsArtistsPage extends HookConsumerWidget { () => topTracks.asData?.value.artists ?? [], [topTracks.asData?.value]); return Scaffold( - appBar: const PageWindowTitleBar( + appBar: PageWindowTitleBar( automaticallyImplyLeading: true, centerTitle: false, - title: Text("Artists"), + title: Text(context.l10n.artists), ), body: Skeletonizer( enabled: topTracks.isLoading && !topTracks.isLoadingNextPage, @@ -46,8 +47,8 @@ class StatsArtistsPage extends HookConsumerWidget { final artist = artistsData[index]; return StatsArtistItem( artist: artist.artist, - info: - Text("${compactNumberFormatter.format(artist.count)} plays"), + info: Text(context.l10n + .count_plays(compactNumberFormatter.format(artist.count))), ); }, ), diff --git a/lib/pages/stats/fees/fees.dart b/lib/pages/stats/fees/fees.dart index 33d223ae..5f9aa779 100644 --- a/lib/pages/stats/fees/fees.dart +++ b/lib/pages/stats/fees/fees.dart @@ -6,6 +6,7 @@ import 'package:sliver_tools/sliver_tools.dart'; import 'package:spotube/collections/formatters.dart'; import 'package:spotube/components/titlebar/titlebar.dart'; import 'package:spotube/modules/stats/common/artist_item.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/history/top.dart'; import 'package:spotube/provider/history/top/tracks.dart'; @@ -40,10 +41,10 @@ class StatsStreamFeesPage extends HookConsumerWidget { ); return Scaffold( - appBar: const PageWindowTitleBar( + appBar: PageWindowTitleBar( automaticallyImplyLeading: true, centerTitle: false, - title: Text("Streaming fees (hypothetical)"), + title: Text(context.l10n.streaming_fees_hypothetical), ), body: CustomScrollView( slivers: [ @@ -54,11 +55,7 @@ class StatsStreamFeesPage extends HookConsumerWidget { padding: const EdgeInsets.all(16.0), sliver: SliverToBoxAdapter( child: Text( - "*This is calculated based on Spotify's per stream " - "payout of \$0.003 to \$0.005. This is a hypothetical " - "calculation to give user insight about how much they " - "would have paid to the artists if they were to listen " - "their song in Spotify.", + context.l10n.spotify_hipotetical_calculation, style: textTheme.bodySmall?.copyWith( color: hintColor, ), diff --git a/lib/pages/stats/minutes/minutes.dart b/lib/pages/stats/minutes/minutes.dart index ea3048ef..35bea3ab 100644 --- a/lib/pages/stats/minutes/minutes.dart +++ b/lib/pages/stats/minutes/minutes.dart @@ -5,6 +5,7 @@ import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotube/collections/formatters.dart'; import 'package:spotube/components/titlebar/titlebar.dart'; import 'package:spotube/modules/stats/common/track_item.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/history/top.dart'; import 'package:spotube/provider/history/top/tracks.dart'; @@ -27,8 +28,8 @@ class StatsMinutesPage extends HookConsumerWidget { final tracksData = topTracks.asData?.value.items ?? []; return Scaffold( - appBar: const PageWindowTitleBar( - title: Text("Minutes listened"), + appBar: PageWindowTitleBar( + title: Text(context.l10n.minutes_listened), centerTitle: false, automaticallyImplyLeading: true, ), @@ -48,7 +49,8 @@ class StatsMinutesPage extends HookConsumerWidget { return StatsTrackItem( track: track.track, info: Text( - "${compactNumberFormatter.format(track.count)} plays", + context.l10n + .count_plays(compactNumberFormatter.format(track.count)), ), ); }, diff --git a/lib/pages/stats/playlists/playlists.dart b/lib/pages/stats/playlists/playlists.dart index a6db3e1c..4e83b0a2 100644 --- a/lib/pages/stats/playlists/playlists.dart +++ b/lib/pages/stats/playlists/playlists.dart @@ -4,6 +4,7 @@ import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotube/collections/formatters.dart'; import 'package:spotube/components/titlebar/titlebar.dart'; import 'package:spotube/modules/stats/common/playlist_item.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/history/top.dart'; import 'package:spotube/provider/history/top/playlists.dart'; @@ -25,10 +26,10 @@ class StatsPlaylistsPage extends HookConsumerWidget { final playlistsData = topPlaylists.asData?.value.items ?? []; return Scaffold( - appBar: const PageWindowTitleBar( + appBar: PageWindowTitleBar( automaticallyImplyLeading: true, centerTitle: false, - title: Text("Playlists"), + title: Text(context.l10n.playlists), ), body: Skeletonizer( enabled: topPlaylists.isLoading && !topPlaylists.isLoadingNextPage, @@ -45,7 +46,9 @@ class StatsPlaylistsPage extends HookConsumerWidget { return StatsPlaylistItem( playlist: playlist.playlist, info: Text( - "${compactNumberFormatter.format(playlist.count)} plays"), + context.l10n + .count_plays(compactNumberFormatter.format(playlist.count)), + ), ); }, ), diff --git a/lib/pages/stats/streams/streams.dart b/lib/pages/stats/streams/streams.dart index dd5856d0..5c90e879 100644 --- a/lib/pages/stats/streams/streams.dart +++ b/lib/pages/stats/streams/streams.dart @@ -5,6 +5,7 @@ import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotube/collections/formatters.dart'; import 'package:spotube/components/titlebar/titlebar.dart'; import 'package:spotube/modules/stats/common/track_item.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/history/top.dart'; import 'package:spotube/provider/history/top/tracks.dart'; @@ -27,8 +28,8 @@ class StatsStreamsPage extends HookConsumerWidget { final tracksData = topTracks.asData?.value.items ?? []; return Scaffold( - appBar: const PageWindowTitleBar( - title: Text("Streamed songs"), + appBar: PageWindowTitleBar( + title: Text(context.l10n.streamed_songs), centerTitle: false, automaticallyImplyLeading: true, ), @@ -48,7 +49,8 @@ class StatsStreamsPage extends HookConsumerWidget { return StatsTrackItem( track: track.track, info: Text( - "${compactNumberFormatter.format(track.count * track.track.duration!.inMinutes)} mins", + context.l10n.count_mins(compactNumberFormatter + .format(track.count * track.track.duration!.inMinutes)), ), ); },