diff --git a/README.md b/README.md index 0a7849c67..a6d8433bd 100644 --- a/README.md +++ b/README.md @@ -203,13 +203,20 @@ If you are concerned, you can [read the reason of choosing this license](https:/ 1. [collection](https://pub.dev/packages/collection) - Collections and utilities functions and classes related to collections. 1. [cupertino_icons](https://pub.dev/packages/cupertino_icons) - Default icons asset for Cupertino widgets based on Apple styled icons 1. [curved_navigation_bar](https://github.com/rafalbednarczuk/curved_navigation_bar) - Stunning Animating Curved Shape Navigation Bar. Adjustable color, background color, animation curve, animation duration. +1. [dbus](https://github.com/canonical/dbus.dart) - A native Dart implementation of the D-Bus message bus client. This package allows Dart applications to directly access services on the Linux desktop. +1. [device_info_plus](https://plus.fluttercommunity.dev/) - Flutter plugin providing detailed information about the device (make, model, etc.), and Android or iOS version the app is running on. +1. [device_preview](https://github.com/aloisdeniel/flutter_device_preview) - Approximate how your Flutter app looks and performs on another device. +1. [dio](https://github.com/cfug/dio) - A powerful HTTP networking package,supports Interceptors,Aborting and canceling a request,Custom adapters, Transformers, etc. +1. [disable_battery_optimization](https://github.com/pvsvamsi/Disable-Battery-Optimizations) - Flutter plugin to check and disable battery optimizations. Also shows custom steps to disable the optimizations in devices like mi, xiaomi, samsung, oppo, huawei, oneplus etc +1. [duration](https://github.com/desktop-dart/duration) - Utilities to make working with 'Duration's easier. Formats duration in human readable form and also parses duration in human readable form to Dart's Duration. 1. [envied](https://github.com/petercinibulk/envied) - Explicitly reads environment variables into a dart file from a .env file for more security and faster start up times. 1. [file_picker](https://github.com/miguelpruivo/plugins_flutter_file_picker) - A package that allows you to use a native file explorer to pick single or multiple absolute file paths, with extension filtering support. 1. [fl_query](https://fl-query.vercel.app) - Asynchronous data caching, refetching & invalidation library for Flutter 1. [fl_query_hooks](https://fl-query.vercel.app) - Elite flutter_hooks compatible library for fl_query, the Asynchronous data caching, refetching & invalidation library for Flutter 1. [fl_query_connectivity_plus_adapter](https://fl-query.vercel.app) - Connectivity Plus adapter for FlQuery Connectivity 1. [fluentui_system_icons](https://github.com/microsoft/fluentui-system-icons/tree/main) - Fluent UI System Icons are a collection of familiar, friendly and modern icons from Microsoft. -1. [flutter_cache_manager](https://github.com/Baseflow/flutter_cache_manager/tree/master/flutter_cache_manager) - Generic cache manager for flutter. Saves web files on the storages of the device and saves the cache info using sqflite. +1. [flutter_cache_manager](https://github.com/Baseflow/flutter_cache_manager/tree/develop/flutter_cache_manager) - Generic cache manager for flutter. Saves web files on the storages of the device and saves the cache info using sqflite. +1. [flutter_displaymode](https://github.com/ajinasokan/flutter_displaymode) - A Flutter plugin to set display mode (resolution, refresh rate) on Android platform. Allows to enable high refresh rate on supported devices. 1. [flutter_feather_icons](https://github.com/muj-programmer/flutter_feather_icons) - Feather is a collection of simply beautiful open source icons. Each icon is designed on a 24x24 grid with an emphasis on simplicity, consistency and usability. 1. [flutter_hooks](https://github.com/rrousselGit/flutter_hooks) - A flutter implementation of React hooks. It adds a new kind of widget with enhanced code reuse. 1. [flutter_inappwebview](https://inappwebview.dev/) - A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window. @@ -218,6 +225,7 @@ If you are concerned, you can [read the reason of choosing this license](https:/ 1. [flutter_secure_storage](https://pub.dev/packages/flutter_secure_storage) - Flutter Secure Storage provides API to store data in secure storage. Keychain is used in iOS, KeyStore based solution is used in Android. 1. [flutter_svg](https://pub.dev/packages/flutter_svg) - An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. 1. [fuzzywuzzy](https://github.com/sphericalkat/dart-fuzzywuzzy) - An implementation of the popular fuzzywuzzy package in Dart, to suit all your fuzzy string matching/searching needs! +1. [google_fonts](https://pub.dev/packages/google_fonts) - A Flutter package to use fonts from fonts.google.com. Supports HTTP fetching, caching, and asset bundling. 1. [go_router](https://pub.dev/packages/go_router) - A declarative router for Flutter based on Navigation 2 supporting deep linking, data-driven routes and more 1. [hive](https://github.com/hivedb/hive/tree/master/hive) - Lightweight and blazing fast key-value database written in pure Dart. Strongly encrypted using AES-256. 1. [hive_flutter](https://github.com/hivedb/hive/tree/master/hive_flutter) - Extension for Hive. Makes it easier to use Hive in Flutter apps. @@ -228,12 +236,13 @@ If you are concerned, you can [read the reason of choosing this license](https:/ 1. [introduction_screen](https://github.com/pyozer/introduction_screen) - Introduction/Onboarding package for flutter app with some customizations possibilities 1. [json_annotation](https://pub.dev/packages/json_annotation) - Classes and helper functions that support JSON code generation via the `json_serializable` package. 1. [logger](https://pub.dev/packages/logger) - Small, easy to use and extensible logger which prints beautiful logs. -1. [media_kit](https://github.com/alexmercerind/media_kit) - A complete video & audio playback library for Flutter & Dart. Performant, stable, feature-proof & modular. -1. [media_kit_libs_android_audio](https://github.com/alexmercerind/media_kit.git) - Android package providing audio (only) native libraries for package:media_kit. -1. [media_kit_libs_ios_audio](https://github.com/alexmercerind/media_kit.git) - iOS package providing audio native libraries for package:media_kit. -1. [media_kit_libs_linux](https://github.com/alexmercerind/media_kit.git) - GNU/Linux dependency package for package:media_kit. Necessary for initialization. -1. [media_kit_libs_macos_audio](https://github.com/alexmercerind/media_kit.git) - macOS package providing audio native libraries for package:media_kit. -1. [media_kit_libs_windows_audio](https://github.com/alexmercerind/media_kit.git) - Windows package providing audio (only) native libraries for package:media_kit. +1. [media_kit](https://github.com/media-kit/media-kit) - A cross-platform video player & audio player for Flutter & Dart. Performant, stable, feature-proof & modular. +1. [media_kit_native_event_loop](https://github.com/media-kit/media-kit) - Platform specific threaded event handling for media_kit. Enables support for higher number of concurrent instances. +1. [media_kit_libs_android_audio](https://github.com/media-kit/media-kit.git) - Android package providing audio (only) native libraries for package:media_kit. +1. [media_kit_libs_ios_audio](https://github.com/media-kit/media-kit.git) - iOS package providing audio native libraries for package:media_kit. +1. [media_kit_libs_macos_audio](https://github.com/media-kit/media-kit.git) - macOS package providing audio native libraries for package:media_kit. +1. [media_kit_libs_windows_audio](https://github.com/media-kit/media-kit.git) - Windows package providing audio (only) native libraries for package:media_kit. +1. [media_kit_libs_linux](https://github.com/media-kit/media-kit.git) - GNU/Linux dependency package for package:media_kit. Necessary for initialization. 1. [metadata_god](https://github.com/KRTirtho/metadata_god) - Plugin for retrieving and writing audio tags/metadata from audio files 1. [mime](https://pub.dev/packages/mime) - Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. 1. [package_info_plus](https://plus.fluttercommunity.dev/) - Flutter plugin for querying information about the application package, such as CFBundleVersion on iOS or versionCode on Android. @@ -241,6 +250,7 @@ If you are concerned, you can [read the reason of choosing this license](https:/ 1. [path](https://pub.dev/packages/path) - A string-based path manipulation library. All of the path operations you know and love, with solid support for Windows, POSIX (Linux and Mac OS X), and the web. 1. [path_provider](https://pub.dev/packages/path_provider) - Flutter plugin for getting commonly used locations on host platform file systems, such as the temp and app data directories. 1. [permission_handler](https://pub.dev/packages/permission_handler) - Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions. +1. [piped_client](https://github.com/KRTirtho/piped_client) - API Client for piped.video 1. [popover](https://github.com/minikin/popover) - A popover is a transient view that appears above other content onscreen when you tap a control or in an area. 1. [scroll_to_index](https://github.com/quire-io/scroll-to-index) - Scroll to a specific child of any scrollable widget in Flutter 1. [shared_preferences](https://pub.dev/packages/shared_preferences) - Flutter plugin for reading and writing simple key-value pairs. Wraps NSUserDefaults on iOS and SharedPreferences on Android. @@ -248,6 +258,7 @@ If you are concerned, you can [read the reason of choosing this license](https:/ 1. [skeleton_text](https://github.com/101Loop/Skeleton-Text) - A package that provides an easy way to add skeleton text loading animation in Flutter project. This project is a part of 101Loop community. 1. [smtc_windows](https://github.com/KRTirtho/smtc_windows) - Windows `SystemMediaTransportControls` implementation for Flutter giving access to Windows OS Media Control applet. 1. [spotify](https://github.com/rinukkusu/spotify-dart) - An incomplete dart library for interfacing with the Spotify Web API. +1. [supabase](https://supabase.com) - A dart client for Supabase. This client makes it simple for developers to build secure and scalable products. 1. [system_theme](https://pub.dev/packages/system_theme) - A plugin to get the current system theme info. Supports Android, Web, Windows, Linux and macOS 1. [titlebar_buttons](https://github.com/gtk-flutter/titlebar_buttons) - A package which provides most of the titlebar buttons from windows, linux and macos. 1. [url_launcher](https://pub.dev/packages/url_launcher) - Flutter plugin for launching a URL. Supports web, phone, SMS, and email schemes. @@ -255,14 +266,6 @@ If you are concerned, you can [read the reason of choosing this license](https:/ 1. [version](https://github.com/dartninja/version) - Provides a simple class for parsing and comparing semantic versions as defined by http://semver.org/ 1. [visibility_detector](https://pub.dev/packages/visibility_detector) - A widget that detects the visibility of its child and notifies a callback. 1. [window_manager](https://github.com/leanflutter/window_manager) - This plugin allows Flutter desktop apps to resizing and repositioning the window. -1. [piped_client](https://github.com/KRTirtho/piped_client) - API Client for piped.video -1. [supabase_flutter](https://supabase.com) - Flutter integration for Supabase. This package makes it simple for developers to build secure and scalable products. -1. [device_preview](https://github.com/aloisdeniel/flutter_device_preview) - Approximate how your Flutter app looks and performs on another device. -1. [media_kit_native_event_loop](https://github.com/alexmercerind/media_kit) - Platform specific threaded event handling for media_kit. Enables support for higher number of concurrent instances. -1. [dbus](https://github.com/canonical/dbus.dart) - A native Dart implementation of the D-Bus message bus client. This package allows Dart applications to directly access services on the Linux desktop. -1. [background_downloader](https://pub.dev/packages/background_downloader) - A multi-platform background file downloader and uploader. Define the task, enqueue and monitor progress -1. [duration](https://github.com/desktop-dart/duration) - Utilities to make working with 'Duration's easier. Formats duration in human readable form and also parses duration in human readable form to Dart's Duration. -1. [disable_battery_optimization](https://github.com/pvsvamsi/Disable-Battery-Optimizations) - Flutter plugin to check and disable battery optimizations. Also shows custom steps to disable the optimizations in devices like mi, xiaomi, samsung, oppo, huawei, oneplus etc 1. [youtube_explode_dart](https://github.com/Hexer10/youtube_explode_dart) - A port in dart of the youtube explode library. Supports several API functions without the need of Youtube API Key. 1. [build_runner](https://pub.dev/packages/build_runner) - A build system for Dart code generation and modular compilation. 1. [envied_generator](https://github.com/petercinibulk/envied) - Generator for the Envied package. See https://pub.dev/packages/envied. @@ -277,7 +280,6 @@ If you are concerned, you can [read the reason of choosing this license](https:/ 1. [catcher](https://github.com/jhomlala/catcher) - Plugin for error catching which provides multiple handlers for dealing with errors when they are not caught by the developer. 1. [flutter_desktop_tools](https://github.com/KRTirtho/flutter_desktop_tools) - Essential collection of tools for flutter desktop app development 1. [window_size](https://github.com/google/flutter-desktop-embedding.git) - Allows resizing and repositioning the window containing Flutter. -

© Copyright Spotube 2023

diff --git a/bin/gen-credits.dart b/bin/gen-credits.dart index 74f4a9354..6f3e1b511 100644 --- a/bin/gen-credits.dart +++ b/bin/gen-credits.dart @@ -72,7 +72,7 @@ void main() async { packageInfo .map( (package) => - '- [${package.name}](${package.latestPubspec.homepage ?? package.url}) - ${package.description.replaceAll('\n', '')}', + '1. [${package.name}](${package.latestPubspec.homepage ?? package.url}) - ${package.description.replaceAll('\n', '')}', ) .join('\n'), ); @@ -85,7 +85,7 @@ void main() async { ?.value .url .toString(); - return '- [${package.name}]($packageUrl) - ${package.description?.replaceAll('\n', '')}'; + return '1. [${package.name}]($packageUrl) - ${package.description?.replaceAll('\n', '')}'; }, ).join('\n'), ); diff --git a/lib/collections/language_codes.dart b/lib/collections/language_codes.dart index 8209f33d8..cdb6a76dd 100644 --- a/lib/collections/language_codes.dart +++ b/lib/collections/language_codes.dart @@ -520,10 +520,10 @@ abstract class LanguageLocals { // name: "Pashto, Pushto", // nativeName: "پښتو", // ), - // "pt": const ISOLanguageName( - // name: "Portuguese", - // nativeName: "Português", - // ), + "pt": const ISOLanguageName( + name: "Portuguese", + nativeName: "Português", + ), // "qu": const ISOLanguageName( // name: "Quechua", // nativeName: "Runa Simi, Kichwa", diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb new file mode 100644 index 000000000..af26c335e --- /dev/null +++ b/lib/l10n/app_pt.arb @@ -0,0 +1,260 @@ +{ + "guest": "Visitante", + "browse": "Explorar", + "search": "Buscar", + "library": "Biblioteca", + "lyrics": "Letras", + "settings": "Configurações", + "genre_categories_filter": "Filtrar categorias ou gêneros...", + "genre": "Gênero", + "personalized": "Personalizado", + "featured": "Destaque", + "new_releases": "Novos Lançamentos", + "songs": "Músicas", + "playing_track": "Tocando {track}", + "queue_clear_alert": "Isso irá limpar a fila atual. {track_length} músicas serão removidas.\nDeseja continuar?", + "load_more": "Carregar mais", + "playlists": "Playlists", + "artists": "Artistas", + "albums": "Álbuns", + "tracks": "Faixas", + "downloads": "Downloads", + "filter_playlists": "Filtrar suas playlists...", + "liked_tracks": "Músicas Curtidas", + "liked_tracks_description": "Todas as suas músicas curtidas", + "create_playlist": "Criar Playlist", + "create_a_playlist": "Criar uma playlist", + "create": "Criar", + "cancel": "Cancelar", + "playlist_name": "Nome da Playlist", + "name_of_playlist": "Nome da playlist", + "description": "Descrição", + "public": "Pública", + "collaborative": "Colaborativa", + "search_local_tracks": "Buscar músicas locais...", + "play": "Reproduzir", + "delete": "Excluir", + "none": "Nenhum", + "sort_a_z": "Ordenar de A-Z", + "sort_z_a": "Ordenar de Z-A", + "sort_artist": "Ordenar por Artista", + "sort_album": "Ordenar por Álbum", + "sort_tracks": "Ordenar Faixas", + "currently_downloading": "Baixando no momento ({tracks_length})", + "cancel_all": "Cancelar Tudo", + "filter_artist": "Filtrar artistas...", + "followers": "{followers} Seguidores", + "add_artist_to_blacklist": "Adicionar artista à lista negra", + "top_tracks": "Principais Músicas", + "fans_also_like": "Fãs também curtiram", + "loading": "Carregando...", + "artist": "Artista", + "blacklisted": "Na Lista Negra", + "following": "Seguindo", + "follow": "Seguir", + "artist_url_copied": "URL do artista copiada para a área de transferência", + "added_to_queue": "Adicionadas {tracks} músicas à fila", + "filter_albums": "Filtrar álbuns...", + "synced": "Sincronizado", + "plain": "Simples", + "shuffle": "Aleatório", + "search_tracks": "Buscar músicas...", + "released": "Lançado", + "error": "Erro {error}", + "title": "Título", + "time": "Tempo", + "more_actions": "Mais ações", + "download_count": "Baixar ({count})", + "add_count_to_playlist": "Adicionar ({count}) à Playlist", + "add_count_to_queue": "Adicionar ({count}) à Fila", + "play_count_next": "Reproduzir ({count}) em seguida", + "album": "Álbum", + "copied_to_clipboard": "{data} copiado para a área de transferência", + "add_to_following_playlists": "Adicionar {track} às Playlists Seguintes", + "add": "Adicionar", + "added_track_to_queue": "Adicionada {track} à fila", + "add_to_queue": "Adicionar à fila", + "track_will_play_next": "{track} será reproduzida em seguida", + "play_next": "Reproduzir em seguida", + "removed_track_from_queue": "{track} removida da fila", + "remove_from_queue": "Remover da fila", + "remove_from_favorites": "Remover dos favoritos", + "save_as_favorite": "Salvar como favorita", + "add_to_playlist": "Adicionar à playlist", + "remove_from_playlist": "Remover da playlist", + "add_to_blacklist": "Adicionar à lista negra", + "remove_from_blacklist": "Remover da lista negra", + "share": "Compartilhar", + "mini_player": "Mini Player", + "slide_to_seek": "Arraste para avançar ou retroceder", + "shuffle_playlist": "Embaralhar playlist", + "unshuffle_playlist": "Desembaralhar playlist", + "previous_track": "Faixa anterior", + "next_track": "Próxima faixa", + "pause_playback": "Pausar Reprodução", + "resume_playback": "Continuar Reprodução", + "loop_track": "Repetir faixa", + "repeat_playlist": "Repetir playlist", + "queue": "Fila", + "alternative_track_sources": "Fontes alternativas de faixas", + "download_track": "Baixar faixa", + "tracks_in_queue": "{tracks} músicas na fila", + "clear_all": "Limpar tudo", + "show_hide_ui_on_hover": "Mostrar/Ocultar UI ao passar o mouse", + "always_on_top": "Sempre no topo", + "exit_mini_player": "Sair do Mini player", + "download_location": "Local de download", + "account": "Conta", + "login_with_spotify": "Fazer login com sua conta do Spotify", + "connect_with_spotify": "Conectar ao Spotify", + "logout": "Sair", + "logout_of_this_account": "Sair desta conta", + "language_region": "Idioma e Região", + "language": "Idioma", + "system_default": "Padrão do Sistema", + "market_place_region": "Região da Loja", + "recommendation_country": "País de Recomendação", + "appearance": "Aparência", + "layout_mode": "Modo de Layout", + "override_layout_settings": "Substituir configurações do modo de layout responsivo", + "adaptive": "Adaptável", + "compact": "Compacto", + "extended": "Estendido", + "theme": "Tema", + "dark": "Escuro", + "light": "Claro", + "system": "Sistema", + "accent_color": "Cor de Destaque", + "sync_album_color": "Sincronizar cor do álbum", + "sync_album_color_description": "Usa a cor predominante da capa do álbum como cor de destaque", + "playback": "Reprodução", + "audio_quality": "Qualidade do Áudio", + "high": "Alta", + "low": "Baixa", + "pre_download_play": "Pré-download e reprodução", + "pre_download_play_description": "Em vez de transmitir áudio, baixar bytes e reproduzir (recomendado para usuários com maior largura de banda)", + "skip_non_music": "Pular segmentos não musicais (SponsorBlock)", + "blacklist_description": "Faixas e artistas na lista negra", + "wait_for_download_to_finish": "Aguarde o download atual ser concluído", + "download_lyrics": "Baixar letras junto com as faixas", + "desktop": "Desktop", + "close_behavior": "Comportamento de Fechamento", + "close": "Fechar", + "minimize_to_tray": "Minimizar para a bandeja", + "show_tray_icon": "Mostrar ícone na bandeja do sistema", + "about": "Sobre", + "u_love_spotube": "Sabemos que você adora o Spotube", + "check_for_updates": "Verificar atualizações", + "about_spotube": "Sobre o Spotube", + "blacklist": "Lista Negra", + "please_sponsor": "Por favor, patrocine/doe", + "spotube_description": "Spotube, um cliente leve, multiplataforma e gratuito para o Spotify", + "version": "Versão", + "build_number": "Número de Build", + "founder": "Fundador", + "repository": "Repositório", + "bug_issues": "Bugs/Problemas", + "made_with": "Feito com ❤️ em Bangladesh🇧🇩", + "kingkor_roy_tirtho": "Kingkor Roy Tirtho", + "copyright": "© 2021-{current_year} Kingkor Roy Tirtho", + "license": "Licença", + "add_spotify_credentials": "Adicione suas credenciais do Spotify para começar", + "credentials_will_not_be_shared_disclaimer": "Não se preocupe, suas credenciais não serão coletadas nem compartilhadas com ninguém", + "know_how_to_login": "Não sabe como fazer isso?", + "follow_step_by_step_guide": "Siga o guia passo a passo", + "spotify_cookie": "Cookie do Spotify {name}", + "cookie_name_cookie": "Cookie {name}", + "fill_in_all_fields": "Preencha todos os campos, por favor", + "submit": "Enviar", + "exit": "Sair", + "previous": "Anterior", + "next": "Próximo", + "done": "Concluído", + "step_1": "Passo 1", + "first_go_to": "Primeiro, vá para", + "login_if_not_logged_in": "e faça login/cadastro se ainda não estiver logado", + "step_2": "Passo 2", + "step_2_steps": "1. Uma vez logado, pressione F12 ou clique com o botão direito do mouse > Inspecionar para abrir as ferramentas de desenvolvimento do navegador.\n2. Em seguida, vá para a guia \"Aplicativo\" (Chrome, Edge, Brave, etc.) ou \"Armazenamento\" (Firefox, Palemoon, etc.)\n3. Acesse a seção \"Cookies\" e depois a subseção \"https://accounts.spotify.com\"", + "step_3": "Passo 3", + "step_3_steps": "Copie os valores dos Cookies \"sp_dc\" e \"sp_key\" (ou sp_gaid)", + "success_emoji": "Sucesso🥳", + "success_message": "Agora você está logado com sucesso em sua conta do Spotify. Bom trabalho!", + "step_4": "Passo 4", + "step_4_steps": "Cole os valores copiados \"sp_dc\" e \"sp_key\" (ou sp_gaid) nos campos correspondentes", + "something_went_wrong": "Algo deu errado", + "piped_instance": "Instância do Servidor Piped", + "piped_description": "A instância do servidor Piped a ser usada para correspondência de faixas", + "piped_warning": "Algumas delas podem não funcionar bem. Use por sua conta e risco", + "generate_playlist": "Gerar Playlist", + "track_exists": "A faixa {track} já existe", + "replace_downloaded_tracks": "Substituir todas as faixas baixadas", + "skip_download_tracks": "Pular o download de todas as faixas baixadas", + "do_you_want_to_replace": "Deseja substituir a faixa existente?", + "replace": "Substituir", + "skip": "Pular", + "select_up_to_count_type": "Selecione até {count} {type}", + "select_genres": "Selecionar Gêneros", + "add_genres": "Adicionar Gêneros", + "country": "País", + "number_of_tracks_generate": "Número de faixas a gerar", + "acousticness": "Acústica", + "danceability": "Dançabilidade", + "energy": "Energia", + "instrumentalness": "Instrumentalidade", + "liveness": "Vivacidade", + "loudness": "Volume", + "speechiness": "Discurso", + "valence": "Valência", + "popularity": "Popularidade", + "key": "Tonalidade", + "duration": "Duração (s)", + "tempo": "Tempo (BPM)", + "mode": "Modo", + "time_signature": "Assinatura de tempo", + "short": "Curto", + "medium": "Médio", + "long": "Longo", + "min": "Min", + "max": "Máx", + "target": "Alvo", + "moderate": "Moderado", + "deselect_all": "Desmarcar Todos", + "select_all": "Selecionar Todos", + "are_you_sure": "Tem certeza?", + "generating_playlist": "Gerando sua playlist personalizada...", + "selected_count_tracks": "{count} faixas selecionadas", + "download_warning": "Se você baixar todas as faixas em massa, estará claramente pirateando música e causando danos à sociedade criativa da música. Espero que você esteja ciente disso. Sempre tente respeitar e apoiar o trabalho árduo dos artistas", + "download_ip_ban_warning": "Além disso, seu IP pode ser bloqueado no YouTube devido a solicitações de download excessivas. O bloqueio de IP significa que você não poderá usar o YouTube (mesmo se estiver conectado) por pelo menos 2-3 meses a partir do dispositivo IP. E o Spotube não se responsabiliza se isso acontecer", + "by_clicking_accept_terms": "Ao clicar em 'aceitar', você concorda com os seguintes termos:", + "download_agreement_1": "Eu sei que estou pirateando música. Sou mau", + "download_agreement_2": "Vou apoiar o artista onde puder e estou fazendo isso porque não tenho dinheiro para comprar sua arte", + "download_agreement_3": "Estou completamente ciente de que meu IP pode ser bloqueado no YouTube e não responsabilizo o Spotube ou seus proprietários/colaboradores por quaisquer acidentes causados pela minha ação atual", + "decline": "Recusar", + "accept": "Aceitar", + "details": "Detalhes", + "youtube": "YouTube", + "channel": "Canal", + "likes": "Curtidas", + "dislikes": "Descurtidas", + "views": "Visualizações", + "streamUrl": "URL do Stream", + "stop": "Parar", + "sort_newest": "Ordenar por mais recente adicionado", + "sort_oldest": "Ordenar por mais antigo adicionado", + "sleep_timer": "Temporizador de Sono", + "mins": "{minutes} Minutos", + "hours": "{hours} Horas", + "hour": "{hours} Hora", + "custom_hours": "Horas Personalizadas", + "logs": "Registros", + "developers": "Desenvolvedores", + "not_logged_in": "Você não está logado", + "search_mode": "Modo de Busca", + "youtube_api_type": "Tipo de API", + "ok": "Ok", + "failed_to_encrypt": "Falha ao criptografar", + "encryption_failed_warning": "O Spotube usa criptografia para armazenar seus dados com segurança, mas falhou em fazê-lo. Portanto, ele voltará para o armazenamento não seguro.\nSe você estiver usando o Linux, certifique-se de ter algum serviço secreto (gnome-keyring, kde-wallet, keepassxc, etc.) instalado", + "querying_info": "Consultando informações...", + "piped_api_down": "A API do Piped está fora do ar", + "piped_down_error_instructions": "A instância do Piped {pipedInstance} está fora do ar no momento\n\nMude a instância ou altere o 'Tipo de API' para a API oficial do YouTube\n\nCertifique-se de reiniciar o aplicativo após a alteração" +} diff --git a/lib/l10n/l10n.dart b/lib/l10n/l10n.dart index 449cf5fb9..f1efdb753 100644 --- a/lib/l10n/l10n.dart +++ b/lib/l10n/l10n.dart @@ -19,5 +19,6 @@ class L10n { const Locale('ja', 'JP'), const Locale('zh', 'CN'), const Locale('pl', 'PL'), + const Locale('pt', 'PT'), ]; } diff --git a/lib/models/spotube_track.dart b/lib/models/spotube_track.dart index 6b5e9b64c..268a273ec 100644 --- a/lib/models/spotube_track.dart +++ b/lib/models/spotube_track.dart @@ -10,7 +10,7 @@ import 'package:spotube/utils/service_utils.dart'; import 'package:collection/collection.dart'; final officialMusicRegex = RegExp( - r"official\s(video|audio|music\svideo)", + r"official\s(video|audio|music\svideo|lyric\svideo|visualizer)", caseSensitive: false, ); @@ -68,54 +68,64 @@ class SpotubeTrack extends Track { onlyCleanArtist: true, ).trim(); - final List siblings = - await client.search("$title - ${artists.join(", ")}").then( + final query = "$title - ${artists.join(", ")}"; + final List siblings = await client.search(query).then( (res) { final isYoutubeApi = client.preferences.youtubeApiType == YoutubeApiType.youtube; final siblings = isYoutubeApi || client.preferences.searchMode == SearchMode.youtube - ? res - .sorted((a, b) => b.views.compareTo(a.views)) - .map((sibling) { - int score = 0; - - for (final artist in artists) { - final isSameChannelArtist = - sibling.channelName.toLowerCase() == - artist.toLowerCase(); - final channelContainsArtist = sibling.channelName - .toLowerCase() - .contains(artist.toLowerCase()); - - if (isSameChannelArtist || channelContainsArtist) { - score += 1; - } - - final titleContainsArtist = sibling.title - .toLowerCase() - .contains(artist.toLowerCase()); - - if (titleContainsArtist) { - score += 1; - } - } - - if (sibling.title - .toLowerCase() - .contains(track.name!.toLowerCase())) { - score += 2; - } - - if (officialMusicRegex - .hasMatch(sibling.title.toLowerCase())) { - score += 1; - } - - return (sibling: sibling, score: score); - }) - .sorted((a, b) => b.score.compareTo(a.score)) - .map((e) => e.sibling) + ? ServiceUtils.onlyContainsEnglish(query) + ? res + : res + .sorted((a, b) => b.views.compareTo(a.views)) + .map((sibling) { + int score = 0; + + for (final artist in artists) { + final isSameChannelArtist = + sibling.channelName.toLowerCase() == + artist.toLowerCase(); + final channelContainsArtist = sibling.channelName + .toLowerCase() + .contains(artist.toLowerCase()); + + if (isSameChannelArtist || channelContainsArtist) { + score += 1; + } + + final titleContainsArtist = sibling.title + .toLowerCase() + .contains(artist.toLowerCase()); + + if (titleContainsArtist) { + score += 1; + } + } + + final titleContainsTrackName = sibling.title + .toLowerCase() + .contains(track.name!.toLowerCase()); + + final hasOfficialFlag = officialMusicRegex + .hasMatch(sibling.title.toLowerCase()); + + if (titleContainsTrackName) { + score += 3; + } + + if (hasOfficialFlag) { + score += 1; + } + + if (hasOfficialFlag && titleContainsTrackName) { + score += 2; + } + + return (sibling: sibling, score: score); + }) + .sorted((a, b) => b.score.compareTo(a.score)) + .map((e) => e.sibling) : res.sorted((a, b) => b.views.compareTo(a.views)).where((item) { return artists.any( (artist) => diff --git a/lib/utils/service_utils.dart b/lib/utils/service_utils.dart index 64aa45b6e..2d44b9841 100644 --- a/lib/utils/service_utils.dart +++ b/lib/utils/service_utils.dart @@ -17,6 +17,13 @@ import 'package:html/parser.dart' as parser; abstract class ServiceUtils { static final logger = getLogger("ServiceUtils"); + static final _englishMatcherRegex = RegExp( + "^[a-zA-Z0-9\\s!\"#\$%&\\'()*+,-.\\/:;<=>?@\\[\\]^_`{|}~]*\$", + ); + static bool onlyContainsEnglish(String text) { + return _englishMatcherRegex.hasMatch(text); + } + static String clearArtistsOfTitle(String title, List artists) { return title .replaceAll(RegExp(artists.join("|"), caseSensitive: false), "")