diff --git a/assets/css/default.css b/assets/css/default.css index 2cedcf0c5..ccf108d61 100644 --- a/assets/css/default.css +++ b/assets/css/default.css @@ -9,6 +9,36 @@ body { Arial, sans-serif; } +.length-watch-page{ + position: relative; + background-color: rgba(35, 35, 35, 0.75); + color: #fff; + border-radius: 2px; + padding: 4px; + font-size: 20px; + right: 0.25em; + bottom: 0.25em; + margin-left: 10px; + margin-right: 10px; +} + +.dark-theme .length-watch-page{ + background-color: #fff; + color: rgba(35, 35, 35, 1); +} + +@media (prefers-color-scheme: dark) { + .length-watch-page{ + background-color: #fff; + color: rgba(35, 35, 35, 1); + } + + .light-theme .length-watch-page { + background-color: rgba(35, 35, 35, 0.75); + color: #fff; + } +} + #contents { display: flex; flex-direction: column; diff --git a/locales/en-US.json b/locales/en-US.json index 3987f796e..ba584c102 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -1,500 +1,503 @@ { - "Add to playlist": "Add to playlist", - "Add to playlist: ": "Add to playlist: ", - "Answer": "Answer", - "Search for videos": "Search for videos", - "The Popular feed has been disabled by the administrator.": "The Popular feed has been disabled by the administrator.", - "generic_channels_count": "{{count}} channel", - "generic_channels_count_plural": "{{count}} channels", - "generic_views_count": "{{count}} view", - "generic_views_count_plural": "{{count}} views", - "generic_videos_count": "{{count}} video", - "generic_videos_count_plural": "{{count}} videos", - "generic_playlists_count": "{{count}} playlist", - "generic_playlists_count_plural": "{{count}} playlists", - "generic_subscribers_count": "{{count}} subscriber", - "generic_subscribers_count_plural": "{{count}} subscribers", - "generic_subscriptions_count": "{{count}} subscription", - "generic_subscriptions_count_plural": "{{count}} subscriptions", - "generic_button_delete": "Delete", - "generic_button_edit": "Edit", - "generic_button_save": "Save", - "generic_button_cancel": "Cancel", - "generic_button_rss": "RSS", - "LIVE": "LIVE", - "Shared `x` ago": "Shared `x` ago", - "Unsubscribe": "Unsubscribe", - "Subscribe": "Subscribe", - "View channel on YouTube": "View channel on YouTube", - "View playlist on YouTube": "View playlist on YouTube", - "newest": "newest", - "oldest": "oldest", - "popular": "popular", - "last": "last", - "Next page": "Next page", - "Previous page": "Previous page", - "Clear watch history?": "Clear watch history?", - "New password": "New password", - "New passwords must match": "New passwords must match", - "Authorize token?": "Authorize token?", - "Authorize token for `x`?": "Authorize token for `x`?", - "Yes": "Yes", - "No": "No", - "Import and Export Data": "Import and Export Data", - "Import": "Import", - "Import Invidious data": "Import Invidious JSON data", - "Import YouTube subscriptions": "Import YouTube CSV or OPML subscriptions", - "Import YouTube playlist (.csv)": "Import YouTube playlist (.csv)", - "Import YouTube watch history (.json)": "Import YouTube watch history (.json)", - "Import FreeTube subscriptions (.db)": "Import FreeTube subscriptions (.db)", - "Import NewPipe subscriptions (.json)": "Import NewPipe subscriptions (.json)", - "Import NewPipe data (.zip)": "Import NewPipe data (.zip)", - "Export": "Export", - "Export subscriptions as OPML": "Export subscriptions as OPML", - "Export subscriptions as OPML (for NewPipe & FreeTube)": "Export subscriptions as OPML (for NewPipe & FreeTube)", - "Export data as JSON": "Export Invidious data as JSON", - "Delete account?": "Delete account?", - "History": "History", - "An alternative front-end to YouTube": "An alternative front-end to YouTube", - "JavaScript license information": "JavaScript license information", - "source": "source", - "Log in": "Log in", - "Log in/register": "Log in/register", - "User ID": "User ID", - "Password": "Password", - "Time (h:mm:ss):": "Time (h:mm:ss):", - "Text CAPTCHA": "Text CAPTCHA", - "Image CAPTCHA": "Image CAPTCHA", - "Sign In": "Sign In", - "Register": "Register", - "E-mail": "E-mail", - "Preferences": "Preferences", - "preferences_category_player": "Player preferences", - "preferences_video_loop_label": "Always loop: ", - "preferences_autoplay_label": "Autoplay: ", - "preferences_continue_label": "Play next by default: ", - "preferences_continue_autoplay_label": "Autoplay next video: ", - "preferences_listen_label": "Listen by default: ", - "preferences_local_label": "Proxy videos: ", - "preferences_watch_history_label": "Enable watch history: ", - "preferences_speed_label": "Default speed: ", - "preferences_quality_label": "Preferred video quality: ", - "preferences_quality_option_dash": "DASH (adaptive quality)", - "preferences_quality_option_hd720": "HD720", - "preferences_quality_option_medium": "Medium", - "preferences_quality_option_small": "Small", - "preferences_quality_dash_label": "Preferred DASH video quality: ", - "preferences_quality_dash_option_auto": "Auto", - "preferences_quality_dash_option_best": "Best", - "preferences_quality_dash_option_worst": "Worst", - "preferences_quality_dash_option_4320p": "4320p", - "preferences_quality_dash_option_2160p": "2160p", - "preferences_quality_dash_option_1440p": "1440p", - "preferences_quality_dash_option_1080p": "1080p", - "preferences_quality_dash_option_720p": "720p", - "preferences_quality_dash_option_480p": "480p", - "preferences_quality_dash_option_360p": "360p", - "preferences_quality_dash_option_240p": "240p", - "preferences_quality_dash_option_144p": "144p", - "preferences_volume_label": "Player volume: ", - "preferences_comments_label": "Default comments: ", - "youtube": "YouTube", - "reddit": "Reddit", - "invidious": "Invidious", - "preferences_captions_label": "Default captions: ", - "Fallback captions: ": "Fallback captions: ", - "preferences_related_videos_label": "Show related videos: ", - "preferences_annotations_label": "Show annotations by default: ", - "preferences_extend_desc_label": "Automatically extend video description: ", - "preferences_vr_mode_label": "Interactive 360 degree videos (requires WebGL): ", - "preferences_category_visual": "Visual preferences", - "preferences_region_label": "Content country: ", - "preferences_player_style_label": "Player style: ", - "Dark mode: ": "Dark mode: ", - "preferences_dark_mode_label": "Theme: ", - "dark": "dark", - "light": "light", - "preferences_thin_mode_label": "Thin mode: ", - "preferences_category_misc": "Miscellaneous preferences", - "preferences_automatic_instance_redirect_label": "Automatic instance redirection (fallback to redirect.invidious.io): ", - "preferences_category_subscription": "Subscription preferences", - "preferences_annotations_subscribed_label": "Show annotations by default for subscribed channels? ", - "Redirect homepage to feed: ": "Redirect homepage to feed: ", - "preferences_max_results_label": "Number of videos shown in feed: ", - "preferences_sort_label": "Sort videos by: ", - "published": "published", - "published - reverse": "published - reverse", - "alphabetically": "alphabetically", - "alphabetically - reverse": "alphabetically - reverse", - "channel name": "channel name", - "channel name - reverse": "channel name - reverse", - "Only show latest video from channel: ": "Only show latest video from channel: ", - "Only show latest unwatched video from channel: ": "Only show latest unwatched video from channel: ", - "preferences_unseen_only_label": "Only show unwatched: ", - "preferences_notifications_only_label": "Only show notifications (if there are any): ", - "Enable web notifications": "Enable web notifications", - "`x` uploaded a video": "`x` uploaded a video", - "`x` is live": "`x` is live", - "preferences_category_data": "Data preferences", - "Clear watch history": "Clear watch history", - "Import/export data": "Import/export data", - "Change password": "Change password", - "Manage subscriptions": "Manage subscriptions", - "Manage tokens": "Manage tokens", - "Watch history": "Watch history", - "Delete account": "Delete account", - "preferences_category_admin": "Administrator preferences", - "preferences_default_home_label": "Default homepage: ", - "preferences_feed_menu_label": "Feed menu: ", - "preferences_show_nick_label": "Show nickname on top: ", - "Popular enabled: ": "Popular enabled: ", - "Top enabled: ": "Top enabled: ", - "CAPTCHA enabled: ": "CAPTCHA enabled: ", - "Login enabled: ": "Login enabled: ", - "Registration enabled: ": "Registration enabled: ", - "Report statistics: ": "Report statistics: ", - "Save preferences": "Save preferences", - "Subscription manager": "Subscription manager", - "Token manager": "Token manager", - "Token": "Token", - "tokens_count": "{{count}} token", - "tokens_count_plural": "{{count}} tokens", - "Import/export": "Import/export", - "unsubscribe": "unsubscribe", - "revoke": "revoke", - "Subscriptions": "Subscriptions", - "subscriptions_unseen_notifs_count": "{{count}} unseen notification", - "subscriptions_unseen_notifs_count_plural": "{{count}} unseen notifications", - "search": "search", - "Log out": "Log out", - "Released under the AGPLv3 on Github.": "Released under the AGPLv3 on GitHub.", - "Source available here.": "Source available here.", - "View JavaScript license information.": "View JavaScript license information.", - "View privacy policy.": "View privacy policy.", - "Trending": "Trending", - "Public": "Public", - "Unlisted": "Unlisted", - "Private": "Private", - "View all playlists": "View all playlists", - "Updated `x` ago": "Updated `x` ago", - "Delete playlist `x`?": "Delete playlist `x`?", - "Delete playlist": "Delete playlist", - "Create playlist": "Create playlist", - "Title": "Title", - "Playlist privacy": "Playlist privacy", - "Editing playlist `x`": "Editing playlist `x`", - "playlist_button_add_items": "Add videos", - "Show more": "Show more", - "Show less": "Show less", - "Watch on YouTube": "Watch on YouTube", - "Switch Invidious Instance": "Switch Invidious Instance", - "search_message_no_results": "No results found.", - "search_message_change_filters_or_query": "Try widening your search query and/or changing the filters.", - "search_message_use_another_instance": " You can also search on another instance.", - "Hide annotations": "Hide annotations", - "Show annotations": "Show annotations", - "Genre: ": "Genre: ", - "License: ": "License: ", - "Standard YouTube license": "Standard YouTube license", - "Family friendly? ": "Family friendly? ", - "Wilson score: ": "Wilson score: ", - "Engagement: ": "Engagement: ", - "Whitelisted regions: ": "Whitelisted regions: ", - "Blacklisted regions: ": "Blacklisted regions: ", - "Music in this video": "Music in this video", - "Artist: ": "Artist: ", - "Song: ": "Song: ", - "Album: ": "Album: ", - "Shared `x`": "Shared `x`", - "Premieres in `x`": "Premieres in `x`", - "Premieres `x`": "Premieres `x`", - "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.", - "View YouTube comments": "View YouTube comments", - "View more comments on Reddit": "View more comments on Reddit", - "View `x` comments": { - "([^.,0-9]|^)1([^.,0-9]|$)": "View `x` comment", - "": "View `x` comments" - }, - "View Reddit comments": "View Reddit comments", - "Hide replies": "Hide replies", - "Show replies": "Show replies", - "Incorrect password": "Incorrect password", - "Wrong answer": "Wrong answer", - "Erroneous CAPTCHA": "Erroneous CAPTCHA", - "CAPTCHA is a required field": "CAPTCHA is a required field", - "User ID is a required field": "User ID is a required field", - "Password is a required field": "Password is a required field", - "Wrong username or password": "Wrong username or password", - "Password cannot be empty": "Password cannot be empty", - "Password cannot be longer than 55 characters": "Password cannot be longer than 55 characters", - "Please log in": "Please log in", - "Invidious Private Feed for `x`": "Invidious Private Feed for `x`", - "channel:`x`": "channel:`x`", - "Deleted or invalid channel": "Deleted or invalid channel", - "This channel does not exist.": "This channel does not exist.", - "Could not get channel info.": "Could not get channel info.", - "Could not fetch comments": "Could not fetch comments", - "comments_view_x_replies": "View {{count}} reply", - "comments_view_x_replies_plural": "View {{count}} replies", - "`x` ago": "`x` ago", - "Load more": "Load more", - "comments_points_count": "{{count}} point", - "comments_points_count_plural": "{{count}} points", - "Could not create mix.": "Could not create mix.", - "Empty playlist": "Empty playlist", - "Not a playlist.": "Not a playlist.", - "Playlist does not exist.": "Playlist does not exist.", - "Could not pull trending pages.": "Could not pull trending pages.", - "Hidden field \"challenge\" is a required field": "Hidden field \"challenge\" is a required field", - "Hidden field \"token\" is a required field": "Hidden field \"token\" is a required field", - "Erroneous challenge": "Erroneous challenge", - "Erroneous token": "Erroneous token", - "No such user": "No such user", - "Token is expired, please try again": "Token is expired, please try again", - "English": "English", - "English (United Kingdom)": "English (United Kingdom)", - "English (United States)": "English (United States)", - "English (auto-generated)": "English (auto-generated)", - "Afrikaans": "Afrikaans", - "Albanian": "Albanian", - "Amharic": "Amharic", - "Arabic": "Arabic", - "Armenian": "Armenian", - "Azerbaijani": "Azerbaijani", - "Bangla": "Bangla", - "Basque": "Basque", - "Belarusian": "Belarusian", - "Bosnian": "Bosnian", - "Bulgarian": "Bulgarian", - "Burmese": "Burmese", - "Cantonese (Hong Kong)": "Cantonese (Hong Kong)", - "Catalan": "Catalan", - "Cebuano": "Cebuano", - "Chinese": "Chinese", - "Chinese (China)": "Chinese (China)", - "Chinese (Hong Kong)": "Chinese (Hong Kong)", - "Chinese (Simplified)": "Chinese (Simplified)", - "Chinese (Taiwan)": "Chinese (Taiwan)", - "Chinese (Traditional)": "Chinese (Traditional)", - "Corsican": "Corsican", - "Croatian": "Croatian", - "Czech": "Czech", - "Danish": "Danish", - "Dutch": "Dutch", - "Dutch (auto-generated)": "Dutch (auto-generated)", - "Esperanto": "Esperanto", - "Estonian": "Estonian", - "Filipino": "Filipino", - "Finnish": "Finnish", - "French": "French", - "French (auto-generated)": "French (auto-generated)", - "Galician": "Galician", - "Georgian": "Georgian", - "German": "German", - "German (auto-generated)": "German (auto-generated)", - "Greek": "Greek", - "Gujarati": "Gujarati", - "Haitian Creole": "Haitian Creole", - "Hausa": "Hausa", - "Hawaiian": "Hawaiian", - "Hebrew": "Hebrew", - "Hindi": "Hindi", - "Hmong": "Hmong", - "Hungarian": "Hungarian", - "Icelandic": "Icelandic", - "Igbo": "Igbo", - "Indonesian": "Indonesian", - "Indonesian (auto-generated)": "Indonesian (auto-generated)", - "Interlingue": "Interlingue", - "Irish": "Irish", - "Italian": "Italian", - "Italian (auto-generated)": "Italian (auto-generated)", - "Japanese": "Japanese", - "Japanese (auto-generated)": "Japanese (auto-generated)", - "Javanese": "Javanese", - "Kannada": "Kannada", - "Kazakh": "Kazakh", - "Khmer": "Khmer", - "Korean": "Korean", - "Korean (auto-generated)": "Korean (auto-generated)", - "Kurdish": "Kurdish", - "Kyrgyz": "Kyrgyz", - "Lao": "Lao", - "Latin": "Latin", - "Latvian": "Latvian", - "Lithuanian": "Lithuanian", - "Luxembourgish": "Luxembourgish", - "Macedonian": "Macedonian", - "Malagasy": "Malagasy", - "Malay": "Malay", - "Malayalam": "Malayalam", - "Maltese": "Maltese", - "Maori": "Maori", - "Marathi": "Marathi", - "Mongolian": "Mongolian", - "Nepali": "Nepali", - "Norwegian Bokmål": "Norwegian Bokmål", - "Nyanja": "Nyanja", - "Pashto": "Pashto", - "Persian": "Persian", - "Polish": "Polish", - "Portuguese": "Portuguese", - "Portuguese (auto-generated)": "Portuguese (auto-generated)", - "Portuguese (Brazil)": "Portuguese (Brazil)", - "Punjabi": "Punjabi", - "Romanian": "Romanian", - "Russian": "Russian", - "Russian (auto-generated)": "Russian (auto-generated)", - "Samoan": "Samoan", - "Scottish Gaelic": "Scottish Gaelic", - "Serbian": "Serbian", - "Shona": "Shona", - "Sindhi": "Sindhi", - "Sinhala": "Sinhala", - "Slovak": "Slovak", - "Slovenian": "Slovenian", - "Somali": "Somali", - "Southern Sotho": "Southern Sotho", - "Spanish": "Spanish", - "Spanish (auto-generated)": "Spanish (auto-generated)", - "Spanish (Latin America)": "Spanish (Latin America)", - "Spanish (Mexico)": "Spanish (Mexico)", - "Spanish (Spain)": "Spanish (Spain)", - "Sundanese": "Sundanese", - "Swahili": "Swahili", - "Swedish": "Swedish", - "Tajik": "Tajik", - "Tamil": "Tamil", - "Telugu": "Telugu", - "Thai": "Thai", - "Turkish": "Turkish", - "Turkish (auto-generated)": "Turkish (auto-generated)", - "Ukrainian": "Ukrainian", - "Urdu": "Urdu", - "Uzbek": "Uzbek", - "Vietnamese": "Vietnamese", - "Vietnamese (auto-generated)": "Vietnamese (auto-generated)", - "Welsh": "Welsh", - "Western Frisian": "Western Frisian", - "Xhosa": "Xhosa", - "Yiddish": "Yiddish", - "Yoruba": "Yoruba", - "Zulu": "Zulu", - "generic_count_years": "{{count}} year", - "generic_count_years_plural": "{{count}} years", - "generic_count_months": "{{count}} month", - "generic_count_months_plural": "{{count}} months", - "generic_count_weeks": "{{count}} week", - "generic_count_weeks_plural": "{{count}} weeks", - "generic_count_days": "{{count}} day", - "generic_count_days_plural": "{{count}} days", - "generic_count_hours": "{{count}} hour", - "generic_count_hours_plural": "{{count}} hours", - "generic_count_minutes": "{{count}} minute", - "generic_count_minutes_plural": "{{count}} minutes", - "generic_count_seconds": "{{count}} second", - "generic_count_seconds_plural": "{{count}} seconds", - "Fallback comments: ": "Fallback comments: ", - "Popular": "Popular", - "Search": "Search", - "Top": "Top", - "About": "About", - "Rating: ": "Rating: ", - "preferences_locale_label": "Language: ", - "View as playlist": "View as playlist", - "Default": "Default", - "Music": "Music", - "Gaming": "Gaming", - "News": "News", - "Movies": "Movies", - "Download": "Download", - "Download as: ": "Download as: ", - "Download is disabled": "Download is disabled", - "%A %B %-d, %Y": "%A %B %-d, %Y", - "(edited)": "(edited)", - "YouTube comment permalink": "YouTube comment permalink", - "permalink": "permalink", - "`x` marked it with a ❤": "`x` marked it with a ❤", - "Channel Sponsor": "Channel Sponsor", - "Audio mode": "Audio mode", - "Video mode": "Video mode", - "Playlists": "Playlists", - "search_filters_title": "Filters", - "search_filters_date_label": "Upload date", - "search_filters_date_option_none": "Any date", - "search_filters_date_option_hour": "Last Hour", - "search_filters_date_option_today": "Today", - "search_filters_date_option_week": "This week", - "search_filters_date_option_month": "This month", - "search_filters_date_option_year": "This year", - "search_filters_type_label": "Type", - "search_filters_type_option_all": "Any type", - "search_filters_type_option_video": "Video", - "search_filters_type_option_channel": "Channel", - "search_filters_type_option_playlist": "Playlist", - "search_filters_type_option_movie": "Movie", - "search_filters_type_option_show": "Show", - "search_filters_duration_label": "Duration", - "search_filters_duration_option_none": "Any duration", - "search_filters_duration_option_short": "Short (< 4 minutes)", - "search_filters_duration_option_medium": "Medium (4 - 20 minutes)", - "search_filters_duration_option_long": "Long (> 20 minutes)", - "search_filters_features_label": "Features", - "search_filters_features_option_live": "Live", - "search_filters_features_option_four_k": "4K", - "search_filters_features_option_hd": "HD", - "search_filters_features_option_subtitles": "Subtitles/CC", - "search_filters_features_option_c_commons": "Creative Commons", - "search_filters_features_option_three_sixty": "360°", - "search_filters_features_option_vr180": "VR180", - "search_filters_features_option_three_d": "3D", - "search_filters_features_option_hdr": "HDR", - "search_filters_features_option_location": "Location", - "search_filters_features_option_purchased": "Purchased", - "search_filters_sort_label": "Sort By", - "search_filters_sort_option_relevance": "Relevance", - "search_filters_sort_option_rating": "Rating", - "search_filters_sort_option_date": "Upload Date", - "search_filters_sort_option_views": "View count", - "search_filters_apply_button": "Apply selected filters", - "Current version: ": "Current version: ", - "next_steps_error_message": "After which you should try to: ", - "next_steps_error_message_refresh": "Refresh", - "next_steps_error_message_go_to_youtube": "Go to YouTube", - "footer_donate_page": "Donate", - "footer_documentation": "Documentation", - "footer_source_code": "Source code", - "footer_original_source_code": "Original source code", - "footer_modfied_source_code": "Modified source code", - "adminprefs_modified_source_code_url_label": "URL to modified source code repository", - "none": "none", - "videoinfo_started_streaming_x_ago": "Started streaming `x` ago", - "videoinfo_watch_on_youTube": "Watch on YouTube", - "videoinfo_youTube_embed_link": "Embed", - "videoinfo_invidious_embed_link": "Embed Link", - "download_subtitles": "Subtitles - `x` (.vtt)", - "user_created_playlists": "`x` created playlists", - "user_saved_playlists": "`x` saved playlists", - "Video unavailable": "Video unavailable", - "preferences_save_player_pos_label": "Save playback position: ", - "crash_page_you_found_a_bug": "It looks like you found a bug in Invidious!", - "crash_page_before_reporting": "Before reporting a bug, make sure that you have:", - "crash_page_refresh": "tried to refresh the page", - "crash_page_switch_instance": "tried to use another instance", - "crash_page_read_the_faq": "read the Frequently Asked Questions (FAQ)", - "crash_page_search_issue": "searched for existing issues on GitHub", - "crash_page_report_issue": "If none of the above helped, please open a new issue on GitHub (preferably in English) and include the following text in your message (do NOT translate that text):", - "error_video_not_in_playlist": "The requested video doesn't exist in this playlist. Click here for the playlist home page.", - "channel_tab_videos_label": "Videos", - "channel_tab_shorts_label": "Shorts", - "channel_tab_streams_label": "Livestreams", - "channel_tab_podcasts_label": "Podcasts", - "channel_tab_releases_label": "Releases", - "channel_tab_playlists_label": "Playlists", - "channel_tab_community_label": "Community", - "channel_tab_channels_label": "Channels", - "toggle_theme": "Toggle Theme", - "carousel_slide": "Slide {{current}} of {{total}}", - "carousel_skip": "Skip the Carousel", - "carousel_go_to": "Go to slide `x`" + "Add to playlist": "Add to playlist", + "Add to playlist: ": "Add to playlist: ", + "Answer": "Answer", + "Search for videos": "Search for videos", + "The Popular feed has been disabled by the administrator.": "The Popular feed has been disabled by the administrator.", + "generic_channels_count": "{{count}} channel", + "generic_channels_count_plural": "{{count}} channels", + "generic_views_count": "{{count}} view", + "generic_views_count_plural": "{{count}} views", + "generic_videos_count": "{{count}} video", + "generic_videos_count_plural": "{{count}} videos", + "generic_playlists_count": "{{count}} playlist", + "generic_playlists_count_plural": "{{count}} playlists", + "generic_subscribers_count": "{{count}} subscriber", + "generic_subscribers_count_plural": "{{count}} subscribers", + "generic_subscriptions_count": "{{count}} subscription", + "generic_subscriptions_count_plural": "{{count}} subscriptions", + "generic_button_delete": "Delete", + "generic_button_edit": "Edit", + "generic_button_save": "Save", + "generic_button_cancel": "Cancel", + "generic_button_rss": "RSS", + "LIVE": "LIVE", + "Shared `x` ago": "Shared `x` ago", + "Unsubscribe": "Unsubscribe", + "Subscribe": "Subscribe", + "View channel on YouTube": "View channel on YouTube", + "View playlist on YouTube": "View playlist on YouTube", + "newest": "newest", + "oldest": "oldest", + "popular": "popular", + "last": "last", + "Next page": "Next page", + "Previous page": "Previous page", + "Clear watch history?": "Clear watch history?", + "New password": "New password", + "New passwords must match": "New passwords must match", + "Authorize token?": "Authorize token?", + "Authorize token for `x`?": "Authorize token for `x`?", + "Yes": "Yes", + "No": "No", + "Import and Export Data": "Import and Export Data", + "Import": "Import", + "Import Invidious data": "Import Invidious JSON data", + "Import YouTube subscriptions": "Import YouTube CSV or OPML subscriptions", + "Import YouTube playlist (.csv)": "Import YouTube playlist (.csv)", + "Import YouTube watch history (.json)": "Import YouTube watch history (.json)", + "Import FreeTube subscriptions (.db)": "Import FreeTube subscriptions (.db)", + "Import NewPipe subscriptions (.json)": "Import NewPipe subscriptions (.json)", + "Import NewPipe data (.zip)": "Import NewPipe data (.zip)", + "Export": "Export", + "Export subscriptions as OPML": "Export subscriptions as OPML", + "Export subscriptions as OPML (for NewPipe & FreeTube)": "Export subscriptions as OPML (for NewPipe & FreeTube)", + "Export data as JSON": "Export Invidious data as JSON", + "Delete account?": "Delete account?", + "History": "History", + "An alternative front-end to YouTube": "An alternative front-end to YouTube", + "JavaScript license information": "JavaScript license information", + "source": "source", + "Log in": "Log in", + "Log in/register": "Log in/register", + "User ID": "User ID", + "Password": "Password", + "Time (h:mm:ss):": "Time (h:mm:ss):", + "Text CAPTCHA": "Text CAPTCHA", + "Image CAPTCHA": "Image CAPTCHA", + "Sign In": "Sign In", + "Register": "Register", + "E-mail": "E-mail", + "Preferences": "Preferences", + "preferences_category_player": "Player preferences", + "preferences_video_loop_label": "Always loop: ", + "preferences_autoplay_label": "Autoplay: ", + "preferences_continue_label": "Play next by default: ", + "preferences_continue_autoplay_label": "Autoplay next video: ", + "preferences_listen_label": "Listen by default: ", + "preferences_local_label": "Proxy videos: ", + "preferences_watch_history_label": "Enable watch history: ", + "preferences_speed_label": "Default speed: ", + "preferences_quality_label": "Preferred video quality: ", + "preferences_quality_option_dash": "DASH (adaptive quality)", + "preferences_quality_option_hd720": "HD720", + "preferences_quality_option_medium": "Medium", + "preferences_quality_option_small": "Small", + "preferences_quality_dash_label": "Preferred DASH video quality: ", + "preferences_quality_dash_option_auto": "Auto", + "preferences_quality_dash_option_best": "Best", + "preferences_quality_dash_option_worst": "Worst", + "preferences_quality_dash_option_4320p": "4320p", + "preferences_quality_dash_option_2160p": "2160p", + "preferences_quality_dash_option_1440p": "1440p", + "preferences_quality_dash_option_1080p": "1080p", + "preferences_quality_dash_option_720p": "720p", + "preferences_quality_dash_option_480p": "480p", + "preferences_quality_dash_option_360p": "360p", + "preferences_quality_dash_option_240p": "240p", + "preferences_quality_dash_option_144p": "144p", + "preferences_volume_label": "Player volume: ", + "preferences_comments_label": "Default comments: ", + "youtube": "YouTube", + "reddit": "Reddit", + "invidious": "Invidious", + "preferences_captions_label": "Default captions: ", + "Fallback captions: ": "Fallback captions: ", + "preferences_related_videos_label": "Show related videos: ", + "preferences_annotations_label": "Show annotations by default: ", + "preferences_extend_desc_label": "Automatically extend video description: ", + "preferences_vr_mode_label": "Interactive 360 degree videos (requires WebGL): ", + "preferences_category_visual": "Visual preferences", + "preferences_region_label": "Content country: ", + "preferences_player_style_label": "Player style: ", + "Dark mode: ": "Dark mode: ", + "preferences_dark_mode_label": "Theme: ", + "dark": "dark", + "light": "light", + "preferences_thin_mode_label": "Thin mode: ", + "preferences_category_misc": "Miscellaneous preferences", + "preferences_automatic_instance_redirect_label": "Automatic instance redirection (fallback to redirect.invidious.io): ", + "preferences_category_subscription": "Subscription preferences", + "preferences_annotations_subscribed_label": "Show annotations by default for subscribed channels? ", + "Redirect homepage to feed: ": "Redirect homepage to feed: ", + "preferences_max_results_label": "Number of videos shown in feed: ", + "preferences_sort_label": "Sort videos by: ", + "published": "published", + "published - reverse": "published - reverse", + "alphabetically": "alphabetically", + "alphabetically - reverse": "alphabetically - reverse", + "channel name": "channel name", + "channel name - reverse": "channel name - reverse", + "Only show latest video from channel: ": "Only show latest video from channel: ", + "Only show latest unwatched video from channel: ": "Only show latest unwatched video from channel: ", + "preferences_unseen_only_label": "Only show unwatched: ", + "preferences_notifications_only_label": "Only show notifications (if there are any): ", + "Enable web notifications": "Enable web notifications", + "`x` uploaded a video": "`x` uploaded a video", + "`x` is live": "`x` is live", + "preferences_category_data": "Data preferences", + "Clear watch history": "Clear watch history", + "Import/export data": "Import/export data", + "Change password": "Change password", + "Manage subscriptions": "Manage subscriptions", + "Manage tokens": "Manage tokens", + "Watch history": "Watch history", + "Delete account": "Delete account", + "preferences_category_admin": "Administrator preferences", + "preferences_default_home_label": "Default homepage: ", + "preferences_feed_menu_label": "Feed menu: ", + "preferences_show_nick_label": "Show nickname on top: ", + "Popular enabled: ": "Popular enabled: ", + "Top enabled: ": "Top enabled: ", + "CAPTCHA enabled: ": "CAPTCHA enabled: ", + "Login enabled: ": "Login enabled: ", + "Registration enabled: ": "Registration enabled: ", + "Report statistics: ": "Report statistics: ", + "Save preferences": "Save preferences", + "Subscription manager": "Subscription manager", + "Token manager": "Token manager", + "Token": "Token", + "tokens_count": "{{count}} token", + "tokens_count_plural": "{{count}} tokens", + "Import/export": "Import/export", + "unsubscribe": "unsubscribe", + "revoke": "revoke", + "Subscriptions": "Subscriptions", + "subscriptions_unseen_notifs_count": "{{count}} unseen notification", + "subscriptions_unseen_notifs_count_plural": "{{count}} unseen notifications", + "search": "search", + "Log out": "Log out", + "Released under the AGPLv3 on Github.": "Released under the AGPLv3 on GitHub.", + "Source available here.": "Source available here.", + "View JavaScript license information.": "View JavaScript license information.", + "View privacy policy.": "View privacy policy.", + "Trending": "Trending", + "Public": "Public", + "Unlisted": "Unlisted", + "Private": "Private", + "View all playlists": "View all playlists", + "Updated `x` ago": "Updated `x` ago", + "Delete playlist `x`?": "Delete playlist `x`?", + "Delete playlist": "Delete playlist", + "Create playlist": "Create playlist", + "Title": "Title", + "Playlist privacy": "Playlist privacy", + "Editing playlist `x`": "Editing playlist `x`", + "playlist_button_add_items": "Add videos", + "Show more": "Show more", + "Show less": "Show less", + "Watch on YouTube": "Watch on YouTube", + "Switch Invidious Instance": "Switch Invidious Instance", + "search_message_no_results": "No results found.", + "search_message_change_filters_or_query": "Try widening your search query and/or changing the filters.", + "search_message_use_another_instance": " You can also search on another instance.", + "Hide annotations": "Hide annotations", + "Show annotations": "Show annotations", + "Genre: ": "Genre: ", + "License: ": "License: ", + "Standard YouTube license": "Standard YouTube license", + "Family friendly? ": "Family friendly? ", + "Wilson score: ": "Wilson score: ", + "Engagement: ": "Engagement: ", + "Whitelisted regions: ": "Whitelisted regions: ", + "Blacklisted regions: ": "Blacklisted regions: ", + "Music in this video": "Music in this video", + "Artist: ": "Artist: ", + "Song: ": "Song: ", + "Album: ": "Album: ", + "Shared `x`": "Shared `x`", + "Premieres in `x`": "Premieres in `x`", + "Premieres `x`": "Premieres `x`", + "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.", + "View YouTube comments": "View YouTube comments", + "View more comments on Reddit": "View more comments on Reddit", + "View `x` comments": { + "([^.,0-9]|^)1([^.,0-9]|$)": "View `x` comment", + "": "View `x` comments" + }, + "View Reddit comments": "View Reddit comments", + "Hide replies": "Hide replies", + "Show replies": "Show replies", + "Incorrect password": "Incorrect password", + "Wrong answer": "Wrong answer", + "Erroneous CAPTCHA": "Erroneous CAPTCHA", + "CAPTCHA is a required field": "CAPTCHA is a required field", + "User ID is a required field": "User ID is a required field", + "Password is a required field": "Password is a required field", + "Wrong username or password": "Wrong username or password", + "Password cannot be empty": "Password cannot be empty", + "Password cannot be longer than 55 characters": "Password cannot be longer than 55 characters", + "Please log in": "Please log in", + "Invidious Private Feed for `x`": "Invidious Private Feed for `x`", + "channel:`x`": "channel:`x`", + "Deleted or invalid channel": "Deleted or invalid channel", + "This channel does not exist.": "This channel does not exist.", + "Could not get channel info.": "Could not get channel info.", + "Could not fetch comments": "Could not fetch comments", + "comments_view_x_replies": "View {{count}} reply", + "comments_view_x_replies_plural": "View {{count}} replies", + "`x` ago": "`x` ago", + "Load more": "Load more", + "comments_points_count": "{{count}} point", + "comments_points_count_plural": "{{count}} points", + "Could not create mix.": "Could not create mix.", + "Empty playlist": "Empty playlist", + "Not a playlist.": "Not a playlist.", + "Playlist does not exist.": "Playlist does not exist.", + "Could not pull trending pages.": "Could not pull trending pages.", + "Hidden field \"challenge\" is a required field": "Hidden field \"challenge\" is a required field", + "Hidden field \"token\" is a required field": "Hidden field \"token\" is a required field", + "Erroneous challenge": "Erroneous challenge", + "Erroneous token": "Erroneous token", + "No such user": "No such user", + "Token is expired, please try again": "Token is expired, please try again", + "English": "English", + "English (United Kingdom)": "English (United Kingdom)", + "English (United States)": "English (United States)", + "English (auto-generated)": "English (auto-generated)", + "Afrikaans": "Afrikaans", + "Albanian": "Albanian", + "Amharic": "Amharic", + "Arabic": "Arabic", + "Armenian": "Armenian", + "Azerbaijani": "Azerbaijani", + "Bangla": "Bangla", + "Basque": "Basque", + "Belarusian": "Belarusian", + "Bosnian": "Bosnian", + "Bulgarian": "Bulgarian", + "Burmese": "Burmese", + "Cantonese (Hong Kong)": "Cantonese (Hong Kong)", + "Catalan": "Catalan", + "Cebuano": "Cebuano", + "Chinese": "Chinese", + "Chinese (China)": "Chinese (China)", + "Chinese (Hong Kong)": "Chinese (Hong Kong)", + "Chinese (Simplified)": "Chinese (Simplified)", + "Chinese (Taiwan)": "Chinese (Taiwan)", + "Chinese (Traditional)": "Chinese (Traditional)", + "Corsican": "Corsican", + "Croatian": "Croatian", + "Czech": "Czech", + "Danish": "Danish", + "Dutch": "Dutch", + "Dutch (auto-generated)": "Dutch (auto-generated)", + "Esperanto": "Esperanto", + "Estonian": "Estonian", + "Filipino": "Filipino", + "Finnish": "Finnish", + "French": "French", + "French (auto-generated)": "French (auto-generated)", + "Galician": "Galician", + "Georgian": "Georgian", + "German": "German", + "German (auto-generated)": "German (auto-generated)", + "Greek": "Greek", + "Gujarati": "Gujarati", + "Haitian Creole": "Haitian Creole", + "Hausa": "Hausa", + "Hawaiian": "Hawaiian", + "Hebrew": "Hebrew", + "Hindi": "Hindi", + "Hmong": "Hmong", + "Hungarian": "Hungarian", + "Icelandic": "Icelandic", + "Igbo": "Igbo", + "Indonesian": "Indonesian", + "Indonesian (auto-generated)": "Indonesian (auto-generated)", + "Interlingue": "Interlingue", + "Irish": "Irish", + "Italian": "Italian", + "Italian (auto-generated)": "Italian (auto-generated)", + "Japanese": "Japanese", + "Japanese (auto-generated)": "Japanese (auto-generated)", + "Javanese": "Javanese", + "Kannada": "Kannada", + "Kazakh": "Kazakh", + "Khmer": "Khmer", + "Korean": "Korean", + "Korean (auto-generated)": "Korean (auto-generated)", + "Kurdish": "Kurdish", + "Kyrgyz": "Kyrgyz", + "Lao": "Lao", + "Latin": "Latin", + "Latvian": "Latvian", + "Lithuanian": "Lithuanian", + "Luxembourgish": "Luxembourgish", + "Macedonian": "Macedonian", + "Malagasy": "Malagasy", + "Malay": "Malay", + "Malayalam": "Malayalam", + "Maltese": "Maltese", + "Maori": "Maori", + "Marathi": "Marathi", + "Mongolian": "Mongolian", + "Nepali": "Nepali", + "Norwegian Bokmål": "Norwegian Bokmål", + "Nyanja": "Nyanja", + "Pashto": "Pashto", + "Persian": "Persian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Portuguese (auto-generated)": "Portuguese (auto-generated)", + "Portuguese (Brazil)": "Portuguese (Brazil)", + "Punjabi": "Punjabi", + "Romanian": "Romanian", + "Russian": "Russian", + "Russian (auto-generated)": "Russian (auto-generated)", + "Samoan": "Samoan", + "Scottish Gaelic": "Scottish Gaelic", + "Serbian": "Serbian", + "Shona": "Shona", + "Sindhi": "Sindhi", + "Sinhala": "Sinhala", + "Slovak": "Slovak", + "Slovenian": "Slovenian", + "Somali": "Somali", + "Southern Sotho": "Southern Sotho", + "Spanish": "Spanish", + "Spanish (auto-generated)": "Spanish (auto-generated)", + "Spanish (Latin America)": "Spanish (Latin America)", + "Spanish (Mexico)": "Spanish (Mexico)", + "Spanish (Spain)": "Spanish (Spain)", + "Sundanese": "Sundanese", + "Swahili": "Swahili", + "Swedish": "Swedish", + "Tajik": "Tajik", + "Tamil": "Tamil", + "Telugu": "Telugu", + "Thai": "Thai", + "Turkish": "Turkish", + "Turkish (auto-generated)": "Turkish (auto-generated)", + "Ukrainian": "Ukrainian", + "Urdu": "Urdu", + "Uzbek": "Uzbek", + "Vietnamese": "Vietnamese", + "Vietnamese (auto-generated)": "Vietnamese (auto-generated)", + "Welsh": "Welsh", + "Western Frisian": "Western Frisian", + "Xhosa": "Xhosa", + "Yiddish": "Yiddish", + "Yoruba": "Yoruba", + "Zulu": "Zulu", + "generic_count_years": "{{count}} year", + "generic_count_years_plural": "{{count}} years", + "generic_count_months": "{{count}} month", + "generic_count_months_plural": "{{count}} months", + "generic_count_weeks": "{{count}} week", + "generic_count_weeks_plural": "{{count}} weeks", + "generic_count_days": "{{count}} day", + "generic_count_days_plural": "{{count}} days", + "generic_count_days_short": "{{count}} d", + "generic_count_hours": "{{count}} hour", + "generic_count_hours_plural": "{{count}} hours", + "generic_count_hours_short": "{{count}} hr", + "generic_count_minutes": "{{count}} minute", + "generic_count_minutes_plural": "{{count}} minutes", + "generic_count_minutes_short": "{{count}} min", + "generic_count_seconds": "{{count}} second", + "generic_count_seconds_plural": "{{count}} seconds", + "Fallback comments: ": "Fallback comments: ", + "Popular": "Popular", + "Search": "Search", + "Top": "Top", + "About": "About", + "Rating: ": "Rating: ", + "preferences_locale_label": "Language: ", + "View as playlist": "View as playlist", + "Default": "Default", + "Music": "Music", + "Gaming": "Gaming", + "News": "News", + "Movies": "Movies", + "Download": "Download", + "Download as: ": "Download as: ", + "Download is disabled": "Download is disabled", + "%A %B %-d, %Y": "%A %B %-d, %Y", + "(edited)": "(edited)", + "YouTube comment permalink": "YouTube comment permalink", + "permalink": "permalink", + "`x` marked it with a ❤": "`x` marked it with a ❤", + "Channel Sponsor": "Channel Sponsor", + "Audio mode": "Audio mode", + "Video mode": "Video mode", + "Playlists": "Playlists", + "search_filters_title": "Filters", + "search_filters_date_label": "Upload date", + "search_filters_date_option_none": "Any date", + "search_filters_date_option_hour": "Last Hour", + "search_filters_date_option_today": "Today", + "search_filters_date_option_week": "This week", + "search_filters_date_option_month": "This month", + "search_filters_date_option_year": "This year", + "search_filters_type_label": "Type", + "search_filters_type_option_all": "Any type", + "search_filters_type_option_video": "Video", + "search_filters_type_option_channel": "Channel", + "search_filters_type_option_playlist": "Playlist", + "search_filters_type_option_movie": "Movie", + "search_filters_type_option_show": "Show", + "search_filters_duration_label": "Duration", + "search_filters_duration_option_none": "Any duration", + "search_filters_duration_option_short": "Short (< 4 minutes)", + "search_filters_duration_option_medium": "Medium (4 - 20 minutes)", + "search_filters_duration_option_long": "Long (> 20 minutes)", + "search_filters_features_label": "Features", + "search_filters_features_option_live": "Live", + "search_filters_features_option_four_k": "4K", + "search_filters_features_option_hd": "HD", + "search_filters_features_option_subtitles": "Subtitles/CC", + "search_filters_features_option_c_commons": "Creative Commons", + "search_filters_features_option_three_sixty": "360°", + "search_filters_features_option_vr180": "VR180", + "search_filters_features_option_three_d": "3D", + "search_filters_features_option_hdr": "HDR", + "search_filters_features_option_location": "Location", + "search_filters_features_option_purchased": "Purchased", + "search_filters_sort_label": "Sort By", + "search_filters_sort_option_relevance": "Relevance", + "search_filters_sort_option_rating": "Rating", + "search_filters_sort_option_date": "Upload Date", + "search_filters_sort_option_views": "View count", + "search_filters_apply_button": "Apply selected filters", + "Current version: ": "Current version: ", + "next_steps_error_message": "After which you should try to: ", + "next_steps_error_message_refresh": "Refresh", + "next_steps_error_message_go_to_youtube": "Go to YouTube", + "footer_donate_page": "Donate", + "footer_documentation": "Documentation", + "footer_source_code": "Source code", + "footer_original_source_code": "Original source code", + "footer_modfied_source_code": "Modified source code", + "adminprefs_modified_source_code_url_label": "URL to modified source code repository", + "none": "none", + "videoinfo_started_streaming_x_ago": "Started streaming `x` ago", + "videoinfo_watch_on_youTube": "Watch on YouTube", + "videoinfo_youTube_embed_link": "Embed", + "videoinfo_invidious_embed_link": "Embed Link", + "download_subtitles": "Subtitles - `x` (.vtt)", + "user_created_playlists": "`x` created playlists", + "user_saved_playlists": "`x` saved playlists", + "Video unavailable": "Video unavailable", + "preferences_save_player_pos_label": "Save playback position: ", + "crash_page_you_found_a_bug": "It looks like you found a bug in Invidious!", + "crash_page_before_reporting": "Before reporting a bug, make sure that you have:", + "crash_page_refresh": "tried to refresh the page", + "crash_page_switch_instance": "tried to use another instance", + "crash_page_read_the_faq": "read the Frequently Asked Questions (FAQ)", + "crash_page_search_issue": "searched for existing issues on GitHub", + "crash_page_report_issue": "If none of the above helped, please open a new issue on GitHub (preferably in English) and include the following text in your message (do NOT translate that text):", + "error_video_not_in_playlist": "The requested video doesn't exist in this playlist. Click here for the playlist home page.", + "channel_tab_videos_label": "Videos", + "channel_tab_shorts_label": "Shorts", + "channel_tab_streams_label": "Livestreams", + "channel_tab_podcasts_label": "Podcasts", + "channel_tab_releases_label": "Releases", + "channel_tab_playlists_label": "Playlists", + "channel_tab_community_label": "Community", + "channel_tab_channels_label": "Channels", + "toggle_theme": "Toggle Theme", + "carousel_slide": "Slide {{current}} of {{total}}", + "carousel_skip": "Skip the Carousel", + "carousel_go_to": "Go to slide `x`" } diff --git a/src/invidious/helpers/utils.cr b/src/invidious/helpers/utils.cr index 8e9e9a6a3..d1cf9896b 100644 --- a/src/invidious/helpers/utils.cr +++ b/src/invidious/helpers/utils.cr @@ -11,6 +11,21 @@ def ci_lower_bound(pos, n) return (phat + z*z/(2*n) - z * Math.sqrt((phat*(1 - phat) + z*z/(4*n))/n))/(1 + z*z/n) end +def video_length_abbreviated(locale, length) + length_abbreviated = "" + if length.days > 0 + length_abbreviated = "#{translate_count(locale, "generic_count_days_short", length.days)} #{translate_count(locale, "generic_count_hours_short", length.hours)} #{translate_count(locale, "generic_count_minutes_short", length.minutes)}" + elsif length.hours > 0 + length_abbreviated = "#{translate_count(locale, "generic_count_hours_short", length.hours)} #{translate_count(locale, "generic_count_minutes_short", length.minutes)}" + elsif length.minutes > 0 + length_abbreviated = translate_count(locale, "generic_count_minutes_short", length.minutes) + else + length_abbreviated = translate_count(locale, "generic_count_seconds", length.seconds) + end + + return length_abbreviated +end + def elapsed_text(elapsed) millis = elapsed.total_milliseconds return "#{millis.round(2)}ms" if millis >= 1 diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index 45c58a162..e924d4e55 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -77,6 +77,9 @@ we're going to need to do it here in order to allow for translations.

<%= title %> + + <%= video_length_abbreviated(locale, video.length_seconds.seconds)%> + <% if params.listen %> " href="/watch?<%= env.params.query %>&listen=0"> @@ -88,6 +91,7 @@ we're going to need to do it here in order to allow for translations. <% end %>

+ <% if !video.is_listed %>

<%= translate(locale, "Unlisted") %>