Compare commits

...

32 Commits

Author SHA1 Message Date
PikachuEXE
6ea2b7afc6
Merge branch 'development' into feature/playlist-2023-05
* development:
  Translated using Weblate (Italian)
  Translated using Weblate (Polish)
  Translated using Weblate (Kurdish (Central))
  Translated using Weblate (Spanish)
  Translated using Weblate (Kurdish (Central))
  Translated using Weblate (Kurdish)
  A new way to subscribe (#4238)
  Display more profiles on the profile drop-down list, v2 (fixed for low res, fixed linter)  (#4359)
  Translated using Weblate (Estonian)
  Translated using Weblate (Serbian)
  Translated using Weblate (Arabic)
  Translated using Weblate (Chinese (Simplified))
  Display currently watching viewer count on live streams (#4206)
  Translated using Weblate (Spanish)
  Translated using Weblate (Czech)
  Translated using Weblate (Chinese (Traditional))
  Translated using Weblate (Italian)
  Fix block channel channel ID validation (#4366)
2023-11-23 15:15:57 +08:00
PikachuEXE
dbe57a4caa
Merge pull request #62 from PikachuEXE/feature/playlist-2023-05-w-old-ft-consumable-playlist-export
Add toggle to export playlist for older FT
2023-11-23 15:12:21 +08:00
PikachuEXE
8b1fe4268a
Merge pull request #63 from jasonhenriquez/feat/change-tooltip-styling
Feat/change tooltip styling
2023-11-23 14:11:42 +08:00
Jason Henriquez
a968655d4a Adjust tooltip styling 2023-11-22 22:28:34 -06:00
Jason Henriquez
8c73360e41 Revert "* Make tooltip auto-wrap"
This reverts commit 7d932b936c.
2023-11-22 22:16:02 -06:00
PikachuEXE
7d932b936c
* Make tooltip auto-wrap 2023-11-23 11:41:58 +08:00
PikachuEXE
73626f66cd
Update default filename 2023-11-23 09:32:33 +08:00
PikachuEXE
fd74dc97e6
Fix tootip in lower width view 2023-11-23 09:29:28 +08:00
PikachuEXE
1a96092d6f
Backtick > quote 2023-11-23 08:38:19 +08:00
PikachuEXE
fe8440de24
* Remove the extra surrounding spaces 2023-11-23 08:35:02 +08:00
PikachuEXE
f1225cfc97
* Update text align 2023-11-23 08:27:17 +08:00
Massimo Pissarello
19c7a247c5
Translated using Weblate (Italian)
Currently translated at 100.0% (733 of 733 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/it/
2023-11-23 01:07:37 +01:00
WaldiS
07e2775098
Translated using Weblate (Polish)
Currently translated at 100.0% (733 of 733 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/pl/
2023-11-22 23:09:57 +01:00
ڕاستی
7981b05223
Translated using Weblate (Kurdish (Central))
Currently translated at 40.6% (298 of 733 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/ckb/
2023-11-22 21:04:26 +01:00
gallegonovato
3ea5b1465d
Translated using Weblate (Spanish)
Currently translated at 100.0% (733 of 733 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/es/
2023-11-22 21:04:25 +01:00
Hosted Weblate
22fed89c3f
Merge branch 'origin/development' into Weblate. 2023-11-22 18:19:19 +01:00
ڕاستی
1ff0682c3c
Translated using Weblate (Kurdish (Central))
Currently translated at 16.6% (122 of 731 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/ckb/
2023-11-22 18:19:19 +01:00
ڕاستی
14dc80e007
Translated using Weblate (Kurdish)
Currently translated at 17.2% (126 of 731 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/ku/
2023-11-22 18:19:19 +01:00
Jason
e68c534e6c
A new way to subscribe (#4238)
* Implement styling for new subscribe button

* Implement dropdown element and styling

* Implements remaining styling and logic

* Correct use of aria-selected in FT

Note: was able to add aria-controls to ft-profile-selector because it keeps the hidden dropdown in the DOM. The same is not true of the ft-icon-button or ft-subscribe-button. Main point: aria-expanded should go on the button opening the dropdown, not the dropdown itself.

* Resolve subscribe button staying upon bug

* Remove unneeded vendor-specific transition prefixes

See discussion here: https://www.web-plus-plus.com/Articles/css-transition-moz-and-webkit-vs-css3
2023-11-22 17:19:11 +00:00
CelularBat
62e7b439db
Display more profiles on the profile drop-down list, v2 (fixed for low res, fixed linter) (#4359)
* Update ft-profile-selector.css

Fixed for low res, fixed linter complains

* Update comment to max-block-size

* comment to max-block-size

fixed typo

* Update ft-profile-selector.css

adjust for screen with horizontal navbar (mobile)

* Update src/renderer/components/ft-profile-selector/ft-profile-selector.css

Co-authored-by: PikachuEXE <pikachuexe@gmail.com>

* Update src/renderer/components/ft-profile-selector/ft-profile-selector.css

Co-authored-by: PikachuEXE <pikachuexe@gmail.com>

* Update src/renderer/components/ft-profile-selector/ft-profile-selector.css

Co-authored-by: PikachuEXE <pikachuexe@gmail.com>

---------

Co-authored-by: PikachuEXE <pikachuexe@gmail.com>
2023-11-22 11:14:54 -05:00
Priit Jõerüüt
7b8d36023e
Translated using Weblate (Estonian)
Currently translated at 100.0% (731 of 731 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/et/
2023-11-22 14:15:55 +01:00
PikachuEXE
94f0463c4d
* Update tooltip text 2023-11-22 14:12:22 +08:00
NEXI
91ceacd89d
Translated using Weblate (Serbian)
Currently translated at 100.0% (731 of 731 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/sr/
2023-11-21 21:03:38 +00:00
Rex_sa
cc87017290
Translated using Weblate (Arabic)
Currently translated at 100.0% (731 of 731 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/ar/
2023-11-21 15:03:31 +00:00
Eric
a3d375ba8e
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (731 of 731 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/zh_Hans/
2023-11-21 14:02:26 +01:00
absidue
d1a7b84bf3
Display currently watching viewer count on live streams (#4206)
* Display currently watching viewer count on live streams

* Improve watching count styling

Co-authored-by: Jason <84899178+jasonhenriquez@users.noreply.github.com>

---------

Co-authored-by: Jason <84899178+jasonhenriquez@users.noreply.github.com>
2023-11-21 06:05:21 -05:00
gallegonovato
a9fd50227e
Translated using Weblate (Spanish)
Currently translated at 100.0% (731 of 731 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/es/
2023-11-21 12:02:32 +01:00
Fjuro
9d9a769139
Translated using Weblate (Czech)
Currently translated at 100.0% (731 of 731 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/cs/
2023-11-21 09:17:59 +01:00
Jeff Huang
55261487f9
Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (731 of 731 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/zh_Hant/
2023-11-21 09:17:58 +01:00
Massimo Pissarello
ae4dedaeed
Translated using Weblate (Italian)
Currently translated at 100.0% (731 of 731 strings)

Translation: FreeTube/Translations
Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/it/
2023-11-21 06:06:00 +01:00
absidue
c219926c5e
Fix block channel channel ID validation (#4366) 2023-11-21 02:22:29 +00:00
PikachuEXE
d8b149c24d
+ Add toggle to export playlist for older FT 2023-11-21 10:16:26 +08:00
40 changed files with 759 additions and 313 deletions

View File

@ -4,6 +4,7 @@ import { mapActions, mapMutations } from 'vuex'
import FtButton from '../ft-button/ft-button.vue'
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
import FtPrompt from '../ft-prompt/ft-prompt.vue'
import FtToggleSwitch from '../ft-toggle-switch/ft-toggle-switch.vue'
import { MAIN_PROFILE_ID } from '../../../constants'
import { calculateColorLuminance, getRandomColor } from '../../helpers/colors'
@ -27,7 +28,8 @@ export default defineComponent({
'ft-settings-section': FtSettingsSection,
'ft-button': FtButton,
'ft-flex-box': FtFlexBox,
'ft-prompt': FtPrompt
'ft-prompt': FtPrompt,
'ft-toggle-switch': FtToggleSwitch,
},
data: function () {
return {
@ -38,7 +40,9 @@ export default defineComponent({
'youtube',
'youtubeold',
'newpipe'
]
],
shouldExportPlaylistForOlderVersions: false,
}
},
computed: {
@ -1015,6 +1019,55 @@ export default defineComponent({
await this.promptAndWriteToFile(options, JSON.stringify(this.allPlaylists), 'All playlists has been successfully exported')
},
exportPlaylistsForOlderVersionsSometimes: function () {
if (this.shouldExportPlaylistForOlderVersions) {
this.exportPlaylistsForOlderVersions()
} else {
this.exportPlaylists()
}
},
exportPlaylistsForOlderVersions: async function () {
const dateStr = getTodayDateStrLocalTimezone()
const exportFileName = 'freetube-playlists-as-single-favorites-playlist-' + dateStr + '.db'
const options = {
defaultPath: exportFileName,
filters: [
{
name: 'Database File',
extensions: ['db']
}
]
}
const favoritesPlaylistData = {
playlistName: 'Favorites',
protected: true,
videos: [],
}
this.allPlaylists.forEach((playlist) => {
playlist.videos.forEach((video) => {
const videoAlreadyAdded = favoritesPlaylistData.videos.some((v) => {
return v.videoId === video.videoId
})
if (videoAlreadyAdded) { return }
favoritesPlaylistData.videos.push(
Object.assign({
// The "required" keys during import (but actually unused) in older versions
isLive: false,
paid: false,
published: '',
}, video)
)
})
})
await this.promptAndWriteToFile(options, JSON.stringify([favoritesPlaylistData]), 'All playlists has been successfully exported')
},
convertOldFreeTubeFormatToNew(oldData) {
const convertedData = []
for (const channel of oldData) {

View File

@ -42,7 +42,17 @@
/>
<ft-button
:label="$t('Settings.Data Settings.Export Playlists')"
@click="exportPlaylists"
@click="exportPlaylistsForOlderVersionsSometimes"
/>
</ft-flex-box>
<ft-flex-box>
<ft-toggle-switch
:label="$t('Settings.Data Settings.Export Playlists For Older FreeTube Versions.Label')"
:compact="true"
:default-value="shouldExportPlaylistForOlderVersions"
:tooltip="$t('Settings.Data Settings.Export Playlists For Older FreeTube Versions.Tooltip')"
:tooltip-allow-newlines="true"
@change="shouldExportPlaylistForOlderVersions = !shouldExportPlaylistForOlderVersions"
/>
</ft-flex-box>
<ft-prompt

View File

@ -5,7 +5,7 @@ import FtToggleSwitch from '../ft-toggle-switch/ft-toggle-switch.vue'
import FtInputTags from '../../components/ft-input-tags/ft-input-tags.vue'
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
import { showToast } from '../../helpers/utils'
import { checkYoutubeId, findChannelTagInfo } from '../../helpers/channels'
import { checkYoutubeChannelId, findChannelTagInfo } from '../../helpers/channels'
export default defineComponent({
name: 'PlayerSettings',
@ -152,7 +152,7 @@ export default defineComponent({
showToast(this.$t('Settings.Distraction Free Settings.Hide Channels Already Exists'))
},
validateChannelId: function (text) {
return checkYoutubeId(text)
return checkYoutubeChannelId(text)
},
findChannelTagInfo: async function (text) {
return await findChannelTagInfo(text, this.backendOptions)
@ -167,7 +167,7 @@ export default defineComponent({
if (tag.invalid) continue
// process if no preferred name and is possibly a YouTube ID
if (tag.preferredName === '' && checkYoutubeId(tag.name)) {
if (tag.preferredName === '' && checkYoutubeChannelId(tag.name)) {
this.channelHiderDisabled = true
const { preferredName, icon, iconHref, invalidId } = await this.findChannelTagInfo(tag.name)

View File

@ -11,17 +11,12 @@
overflow: hidden;
color: inherit;
text-decoration: none;
-webkit-transition: background 0.2s ease-out;
-moz-transition: background 0.2s ease-out;
-o-transition: background 0.2s ease-out;
transition: background 0.2s ease-out;
}
.bubblePadding:hover {
background-color: var(--side-nav-hover-color);
color: var(--side-nav-hover-text-color);
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}

View File

@ -14,6 +14,7 @@
}"
tabindex="0"
role="button"
:aria-expanded="dropdownShown"
@click="handleIconClick"
@mousedown="handleIconMouseDown"
@keydown.enter.prevent="handleIconClick"
@ -33,7 +34,6 @@
v-if="dropdownOptions.length > 0"
class="list"
role="listbox"
:aria-expanded="dropdownShown"
>
<li
v-for="(option, index) in dropdownOptions"
@ -71,7 +71,6 @@
v-if="dropdownOptions.length > 0"
class="list"
role="listbox"
:aria-expanded="dropdownShown"
>
<li
v-for="(option, index) in dropdownOptions"

View File

@ -57,8 +57,6 @@
border-radius: 100%;
color: var(--primary-text-color);
opacity: 0;
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}
@ -74,8 +72,6 @@
.clearInputTextButton.visible:active {
background-color: var(--tertiary-text-color);
color: var(--side-nav-active-text-color);
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}
@ -172,8 +168,6 @@
.inputAction.enabled:hover {
background-color: var(--side-nav-hover-color);
color: var(--side-nav-hover-text-color);
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}
@ -184,8 +178,6 @@
.inputAction.enabled:active {
background-color: var(--tertiary-text-color);
color: var(--side-nav-active-text-color);
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}

View File

@ -4,17 +4,12 @@
padding-block: 10px 30px;
padding-inline: 10px;
cursor: pointer;
-webkit-transition: background 0.2s ease-out;
-moz-transition: background 0.2s ease-out;
-o-transition: background 0.2s ease-out;
transition: background 0.2s ease-out;
}
.bubblePadding:hover {
background-color: var(--side-nav-hover-color);
color: var(--side-nav-hover-text-color);
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}

View File

@ -27,7 +27,7 @@
inset-block-start: 60px;
inset-inline-end: 10px;
min-inline-size: 250px;
block-size: 400px;
block-size: auto;
padding: 5px;
background-color: var(--card-bg-color);
box-shadow: 0 0 4px var(--scrollbar-color-hover);
@ -35,24 +35,33 @@
.profileWrapper {
margin-block-start: 60px;
block-size: 340px;
block-size: auto;
overflow-y: auto;
/*
profile list max height: 90% of window size - 100 px. It's scaled to be 340px on 800x600 resolution.
Offset of 100px is to compensate for the fixed size of elements above the list, which takes more screen space on lower resolutions
*/
max-block-size: calc(90vh - 100px);
min-block-size: 340px;
}
/* Navbar changes position to horizontal with this media rule.
Height adjust for profile list so it won't cover navbar. */
@media only screen and (max-width: 680px){
.profileWrapper {
max-block-size: calc(95vh - 180px);
}
}
.profile {
cursor: pointer;
block-size: 50px;
-webkit-transition: background 0.2s ease-out;
-moz-transition: background 0.2s ease-out;
-o-transition: background 0.2s ease-out;
transition: background 0.2s ease-out;
}
.profile:hover {
background-color: var(--side-nav-hover-color);
color: var(--side-nav-hover-text-color);
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}

View File

@ -35,6 +35,10 @@ export default defineComponent({
}
},
methods: {
isActiveProfile: function (profile) {
return profile._id === this.activeProfile._id
},
toggleProfileList: function () {
this.profileListShown = !this.profileListShown

View File

@ -6,6 +6,8 @@
:style="{ background: activeProfile.bgColor, color: activeProfile.textColor }"
tabindex="0"
role="button"
:aria-expanded="profileListShown"
aria-controls="profileSelectorList"
@click="toggleProfileList"
@mousedown="handleIconMouseDown"
@keydown.space.prevent="toggleProfileList"
@ -19,6 +21,7 @@
</div>
<ft-card
v-show="profileListShown"
id="profileSelectorList"
ref="profileList"
class="profileList"
tabindex="-1"
@ -46,7 +49,7 @@
:key="index"
class="profile"
:aria-labelledby="'profile-' + index + '-name'"
aria-selected="false"
:aria-selected="isActiveProfile(profile)"
tabindex="0"
role="option"
@click="setActiveProfile(profile)"

View File

@ -1,8 +0,0 @@
/* Ensures style here overrides style of .btn */
.subscribeButton.btn {
align-self: center;
block-size: 50%;
margin-block-end: 10px;
min-inline-size: 150px;
white-space: initial;
}

View File

@ -25,29 +25,54 @@ export default defineComponent({
type: String,
required: true
},
hideProfileDropdownToggle: {
type: Boolean,
default: false
},
subscriptionCountText: {
default: '',
type: String,
required: false
}
},
data: function () {
return {
isProfileDropdownOpen: false
}
},
computed: {
profileInitials: function () {
return this.profileDisplayList.map((profile) => {
return profile?.name?.length > 0 ? Array.from(profile.name)[0].toUpperCase() : ''
})
},
profileList: function () {
return this.$store.getters.getProfileList
},
/* sort by 'All Channels' -> active profile -> unsubscribed channels -> subscribed channels */
profileDisplayList: function () {
const mainProfileAndActiveProfile = [this.profileList[0]]
if (this.activeProfile._id !== MAIN_PROFILE_ID) {
mainProfileAndActiveProfile.push(this.activeProfile)
}
return [
...mainProfileAndActiveProfile,
...this.profileList.filter((profile, i) =>
i !== 0 && !this.isActiveProfile(profile) && !this.isProfileSubscribed(profile)),
...this.profileList.filter((profile, i) =>
i !== 0 && !this.isActiveProfile(profile) && this.isProfileSubscribed(profile))
]
},
activeProfile: function () {
return this.$store.getters.getActiveProfile
},
subscriptionInfo: function () {
return this.activeProfile.subscriptions.find((channel) => {
return channel.id === this.channelId
}) ?? null
},
isSubscribed: function () {
return this.subscriptionInfo !== null
return this.subscriptionInfoForProfile(this.activeProfile)
},
hideChannelSubscriptions: function () {
@ -55,23 +80,27 @@ export default defineComponent({
},
subscribedText: function () {
let subscribedValue = (this.isSubscribed ? this.$t('Channel.Unsubscribe') : this.$t('Channel.Subscribe')).toUpperCase()
let subscribedValue = (this.isProfileSubscribed(this.activeProfile) ? this.$t('Channel.Unsubscribe') : this.$t('Channel.Subscribe')).toUpperCase()
if (this.subscriptionCountText !== '' && !this.hideChannelSubscriptions) {
subscribedValue += ' ' + this.subscriptionCountText
}
return subscribedValue
},
isProfileDropdownEnabled: function () {
return !this.hideProfileDropdownToggle && this.profileList.length > 1
}
},
methods: {
handleSubscription: function () {
handleSubscription: function (profile = this.activeProfile) {
if (this.channelId === '') {
return
}
const currentProfile = deepCopy(this.activeProfile)
const currentProfile = deepCopy(profile)
if (this.isSubscribed) {
if (this.isProfileSubscribed(profile)) {
currentProfile.subscriptions = currentProfile.subscriptions.filter((channel) => {
return channel.id !== this.channelId
})
@ -79,16 +108,16 @@ export default defineComponent({
this.updateProfile(currentProfile)
showToast(this.$t('Channel.Channel has been removed from your subscriptions'))
if (this.activeProfile._id === MAIN_PROFILE_ID) {
if (profile._id === MAIN_PROFILE_ID) {
// Check if a subscription exists in a different profile.
// Remove from there as well.
let duplicateSubscriptions = 0
this.profileList.forEach((profile) => {
if (profile._id === MAIN_PROFILE_ID) {
this.profileList.forEach((profileInList) => {
if (profileInList._id === MAIN_PROFILE_ID) {
return
}
duplicateSubscriptions += this.unsubscribe(profile, this.channelId)
duplicateSubscriptions += this.unsubscribe(profileInList, this.channelId)
})
if (duplicateSubscriptions > 0) {
@ -107,7 +136,7 @@ export default defineComponent({
this.updateProfile(currentProfile)
showToast(this.$t('Channel.Added channel to your subscriptions'))
if (this.activeProfile._id !== MAIN_PROFILE_ID) {
if (profile._id !== MAIN_PROFILE_ID) {
const primaryProfile = deepCopy(this.profileList.find(prof => {
return prof._id === MAIN_PROFILE_ID
}))
@ -122,6 +151,34 @@ export default defineComponent({
}
}
}
if (this.isProfileDropdownEnabled && !this.isProfileDropdownOpen) {
this.toggleProfileDropdown()
}
},
handleProfileDropdownFocusOut: function () {
if (!this.$refs.subscribeButton.matches(':focus-within')) {
this.isProfileDropdownOpen = false
}
},
toggleProfileDropdown: function() {
this.isProfileDropdownOpen = !this.isProfileDropdownOpen
},
isActiveProfile: function (profile) {
return profile._id === this.activeProfile._id
},
subscriptionInfoForProfile: function (profile) {
return profile.subscriptions.find((channel) => {
return channel.id === this.channelId
}) ?? null
},
isProfileSubscribed: function (profile) {
return this.subscriptionInfoForProfile(profile) !== null
},
unsubscribe: function(profile, channelId) {

View File

@ -0,0 +1,141 @@
.buttonList {
margin: 5px;
margin-block-end: 10px;
border-radius: 4px;
block-size: fit-content;
box-shadow: 0px 1px 2px rgb(0 0 0 / 50%);
display: flex;
flex-wrap: nowrap;
/* addresses odd clipping behavior when adjusting window size */
background-color: var(--primary-color);
}
.ftSubscribeButton {
position: relative;
text-align: start;
}
/* Ensures style here overrides style of .btn */
.subscribeButton.btn {
min-inline-size: 150px;
white-space: initial;
}
.subscribeButton.btn, .profileDropdownToggle.btn {
align-self: center;
margin-block: 0;
margin-inline: 0;
}
.dropdownOpened {
.subscribeButton, .profileDropdownToggle {
border-end-start-radius: 0;
border-end-end-radius: 0;
}
}
.profileDropdownToggle.btn {
border-inline-start: none !important;
border-start-start-radius: 0;
border-end-start-radius: 0;
display: inline-block;
min-inline-size: 1em;
padding-inline: 10px;
box-sizing: content-box;
}
.hasProfileDropdownToggle {
.subscribeButton.btn {
min-inline-size: 100px;
padding-inline: 5px;
border-inline-end: 2px solid var(--primary-color-active) !important;
border-start-end-radius: 0;
border-end-end-radius: 0;
box-sizing: content-box;
}
}
.hasProfileDropdownToggle > .subscribeButton.btn, .profileDropdownToggle.btn {
padding-block: 5px;
padding-inline: 6px;
box-shadow: none;
flex: auto;
block-size: 2em;
}
.profileDropdown {
background-color: var(--side-nav-color);
box-shadow: 0 1px 2px rgb(0 0 0 / 50%);
color: var(--secondary-text-color);
display: inline;
font-size: 12px;
max-block-size: 200px;
margin-block: -10px 0;
margin-inline: 5px 0;
overflow-y: scroll;
position: absolute;
text-align: center;
-webkit-user-select: none;
user-select: none;
z-index: 3;
// accounts for parent's left and right margins
inline-size: calc(100% - 10px);
.profileList {
list-style-type: none;
margin: 0;
padding-inline: 0;
}
.profile {
cursor: pointer;
display: flex;
gap: 0.5em;
padding-inline-start: 0.5em;
block-size: 50px;
align-items: center;
transition: background 0.2s ease-out;
&:hover {
background-color: var(--side-nav-hover-color);
color: var(--side-nav-hover-text-color);
transition: background 0.2s ease-in;
}
.colorOption {
inline-size: 40px;
block-size: 40px;
cursor: pointer;
align-items: center;
display: flex;
justify-content: center;
flex-shrink: 0;
border-radius: 50%;
-webkit-border-radius: 50%;
}
.initial {
font-size: 20px;
line-height: 1em;
text-align: center;
user-select: none;
-webkit-user-select: none;
}
.profileName {
padding-inline-end: 1em;
text-align: start;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&.subscribed {
background-color: var(--primary-color);
.profileName {
color: var(--text-with-main-color);
}
}
}
}

View File

@ -1,12 +1,83 @@
<template>
<ft-button
:label="subscribedText"
class="subscribeButton"
background-color="var(--primary-color)"
text-color="var(--text-with-main-color)"
@click="handleSubscription"
/>
<div
ref="subscribeButton"
class="ftSubscribeButton"
:class="{ dropdownOpened: isProfileDropdownOpen}"
@focusout="handleProfileDropdownFocusOut"
>
<div
class="buttonList"
:class="{ hasProfileDropdownToggle: isProfileDropdownEnabled}"
>
<ft-button
:label="subscribedText"
:no-border="true"
class="subscribeButton"
background-color="var(--primary-color)"
text-color="var(--text-with-main-color)"
@click="handleSubscription"
/>
<ft-button
v-if="isProfileDropdownEnabled"
:no-border="true"
:title="isProfileDropdownOpen ? $t('Profile.Close Profile Dropdown') : $t('Profile.Open Profile Dropdown')"
class="profileDropdownToggle"
background-color="var(--primary-color)"
text-color="var(--text-with-main-color)"
:aria-expanded="isProfileDropdownOpen"
@click="toggleProfileDropdown"
>
<font-awesome-icon
:icon="isProfileDropdownOpen ? ['fas', 'angle-up'] : ['fas', 'angle-down']"
/>
</ft-button>
</div>
<template v-if="isProfileDropdownOpen">
<div
tabindex="-1"
class="profileDropdown"
>
<ul
class="profileList"
>
<li
v-for="(profile, index) in profileDisplayList"
:id="'subscription-profile-' + index"
:key="index"
class="profile"
:class="{
subscribed: isProfileSubscribed(profile)
}"
:aria-labelledby="'subscription-profile-' + index + '-name'"
:aria-selected="isActiveProfile(profile)"
:aria-checked="isProfileSubscribed(profile)"
tabindex="0"
role="checkbox"
@click.stop.prevent="handleSubscription(profile)"
@keydown.space.stop.prevent="handleSubscription(profile)"
>
<div
class="colorOption"
:style="{ background: profile.bgColor, color: profile.textColor }"
>
<div
class="initial"
>
{{ isProfileSubscribed(profile) ? '✓' : profileInitials[index] }}
</div>
</div>
<p
:id="'subscription-profile-' + index + '-name'"
class="profileName"
>
{{ profile.name }}
</p>
</li>
</ul>
</div>
</template>
</div>
</template>
<script src="./ft-subscribe-button.js" />
<style src="./ft-subscribe-button.css" />
<style lang="scss" src="./ft-subscribe-button.scss" />

View File

@ -30,7 +30,11 @@ export default defineComponent({
tooltipPosition: {
type: String,
default: 'bottom-left'
}
},
tooltipAllowNewlines: {
type: Boolean,
default: false,
},
},
data: function () {
return {

View File

@ -29,6 +29,7 @@
class="selectTooltip"
:position="tooltipPosition"
:tooltip="tooltip"
:allow-newlines="tooltipAllowNewlines"
/>
</label>
</div>

View File

@ -92,6 +92,16 @@
transform: translate(calc(-50% * var(--horizontal-directionality-coefficient)), 1em);
}
.text.allowNewlines {
white-space: pre-wrap;
text-align: start;
inline-size: 55vw;
}
@media only screen and (max-width: 1100px) {
inline-size: 40vw;
}
.tooltip {
display: inline-block;
position: relative;

View File

@ -13,7 +13,11 @@ export default defineComponent({
tooltip: {
type: String,
required: true
}
},
allowNewlines: {
type: Boolean,
default: false,
},
},
data() {
const id = `ft-tooltip-${++idCounter}`

View File

@ -10,11 +10,13 @@
<p
:id="id"
class="text"
:class="position"
:class="{
[position]: true,
allowNewlines,
}"
role="tooltip"
>
{{ tooltip }}
</p>
v-text="tooltip"
/>
</div>
</template>

View File

@ -14,16 +14,12 @@
.navOption:hover {
background-color: var(--side-nav-hover-color);
color: var(--side-nav-hover-text-color);
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}
.navOption:active {
background-color: var(--side-nav-active-color);
color: var(--side-nav-active-text-color);
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}

View File

@ -53,16 +53,12 @@
.navOption:hover, .navChannel:hover {
background-color: var(--side-nav-hover-color);
color: var(--side-nav-hover-text-color);
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}
.navOption:active, .navChannel:active {
background-color: var(--side-nav-active-color);
color: var(--side-nav-active-text-color);
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}

View File

@ -22,6 +22,13 @@
row-gap: 16px;
}
.watchingCount {
font-weight: normal;
margin-inline-start: 5px;
font-size: 15px;
color: var(--tertiary-text-color);
}
.message {
font-size: 18px;
color: var(--tertiary-text-color);

View File

@ -6,6 +6,7 @@ import FtButton from '../ft-button/ft-button.vue'
import autolinker from 'autolinker'
import { getRandomColorClass } from '../../helpers/colors'
import { getLocalVideoInfo, parseLocalTextRuns } from '../../helpers/api/local'
import { formatNumber } from '../../helpers/utils'
export default defineComponent({
name: 'WatchVideoLiveChat',
@ -30,6 +31,7 @@ export default defineComponent({
},
data: function () {
return {
/** @type {import('youtubei.js').YT.LiveChat|null} */
liveChatInstance: null,
isLoading: true,
hasError: false,
@ -52,7 +54,9 @@ export default defineComponent({
amount: '',
colorClass: ''
}
}
},
/** @type {number|null} */
watchingCount: null,
}
},
computed: {
@ -74,6 +78,14 @@ export default defineComponent({
scrollingBehaviour: function () {
return this.$store.getters.getDisableSmoothScrolling ? 'auto' : 'smooth'
},
hideVideoViews: function () {
return this.$store.getters.getHideVideoViews
},
formattedWatchingCount: function () {
return this.watchingCount !== null ? formatNumber(this.watchingCount) : '0'
}
},
beforeDestroy: function () {
@ -181,6 +193,12 @@ export default defineComponent({
}
})
this.liveChatInstance.on('metadata-update', metadata => {
if (!this.hideVideoViews && metadata.views && !isNaN(metadata.views.original_view_count)) {
this.watchingCount = metadata.views.original_view_count
}
})
this.liveChatInstance.once('end', () => {
this.hasEnded = true
this.liveChatInstance = null

View File

@ -42,7 +42,15 @@
v-else
class="relative"
>
<h4>{{ $t("Video.Live Chat") }}</h4>
<h4>
{{ $t("Video.Live Chat") }}
<span
v-if="!hideVideoViews && watchingCount !== null"
class="watchingCount"
>
{{ $tc('Global.Counts.Watching Count', watchingCount, { count: formattedWatchingCount }) }}
</span>
</h4>
<div
v-if="superChatComments.length > 0"
class="superChatComments"

View File

@ -43,7 +43,7 @@ async function findChannelById(id, backendOptions) {
* @returns {Promise<{icon: string, iconHref: string, preferredName: string} | { invalidId: boolean }>}
*/
export async function findChannelTagInfo(id, backendOptions) {
if (!/UC\S{22}/.test(id)) return { invalidId: true }
if (!checkYoutubeChannelId(id)) return { invalidId: true }
try {
const channel = await findChannelById(id, backendOptions)
if (!process.env.IS_ELECTRON || backendOptions.preference === 'invidious') {
@ -71,6 +71,6 @@ export async function findChannelTagInfo(id, backendOptions) {
* @param {string} id
* @returns {boolean}
*/
export function checkYoutubeId(id) {
return /UC\S{22}/.test(id)
export function checkYoutubeChannelId(id) {
return /^UC[\w-]{22}$/.test(id)
}

View File

@ -9,6 +9,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'
// to avoid code conflict and duplicate entries
import {
faAngleDown,
faAngleUp,
faArrowDown,
faArrowLeft,
faArrowRight,
@ -86,6 +87,7 @@ Vue.config.productionTip = process.env.NODE_ENV === 'development'
library.add(
// solid icons
faAngleDown,
faAngleUp,
faArrowDown,
faArrowLeft,
faArrowRight,

View File

@ -69,6 +69,7 @@
display: flex;
gap: 30px;
justify-content: space-between;
align-items: center;
}
.subscribeButton {

View File

@ -26,7 +26,7 @@
<ft-flex-box class="channels">
<div
v-for="channel in channelList"
:key="channel.key"
:key="channel.id"
class="channel"
>
<router-link
@ -53,7 +53,6 @@
class="unsubscribeContainer"
>
<ft-subscribe-button
class="btn"
:channel-id="channel.id"
:channel-name="channel.name"
:channel-thumbnail="channel.thumbnail"

View File

@ -811,6 +811,8 @@ Video:
'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': الدردشة
المباشرة غير متاحة لهذا البث. ربما تم تعطيلها من قبل القائم بالتحميل.
Pause on Current Video: توقف مؤقتًا على الفيديو الحالي
Unhide Channel: عرض القناة
Hide Channel: إخفاء القناة
Videos:
#& Sort By
Sort By:
@ -1037,3 +1039,6 @@ Playlist will pause when current video is finished: ستتوقف قائمة ال
انتهاء الفيديو الحالي
Playlist will not pause when current video is finished: لن تتوقف قائمة التشغيل مؤقتًا
عند انتهاء الفيديو الحالي
Channel Hidden: تم إضافة {channel} إلى مرشح القناة
Go to page: إذهب إلى {page}
Channel Unhidden: تمت إزالة {channel} من مرشح القناة

View File

@ -3,7 +3,7 @@ Locale Name: 'ئیگلیزی (وڵاتە یەکگرتووەکانی ئەمریک
FreeTube: 'فریتیوب'
# Currently on Subscriptions, Playlists, and History
'This part of the app is not ready yet. Come back later when progress has been made.': >-
بەشێک لە بەرنامۆچکە هێشتا ئامادە نییە. کە ڕەوتەکە درووست کرا دووبارە وەرەوە.
بەشێک لە نەرمەواڵەکە هێشتا ئامادە نییە. کە ڕەوتەکە درووست کرا دووبارە وەرەوە.
# Webkit Menu Bar
File: 'پەڕگە'
@ -32,10 +32,11 @@ Back: 'دواوە'
Forward: 'پێشەوە'
Open New Window: 'کردنەوەی پەنجەرەیەکی نوێ'
Version {versionNumber} is now available! Click for more details: 'وەشانی {versionNumber}
ئێستا بەردەستە! بۆ زانیاری زۆرتر کرتە بکە'
Download From Site: 'داگرتن لە وێبگە'
A new blog is now available, {blogTitle}. Click to view more: ''
Version {versionNumber} is now available! Click for more details: 'ئێستا وەشانی {versionNumber}
بەردەستە..بۆ زانیاری زۆرتر کرتە بکە'
Download From Site: 'لە وێبگەوە دایگرە'
A new blog is now available, {blogTitle}. Click to view more: 'بلۆگێکی نوێ بەردەستە،
{blogTitle}. کرتە بکە بۆ بینینی'
Are you sure you want to open this link?: 'دڵنیایت دەتەوێت ئەم بەستەرە بکەیتەوە؟'
# Global
@ -44,27 +45,27 @@ Global:
Videos: 'ڤیدیۆکان'
Shorts: ''
Live: 'ڕاستەوخۆ'
Community: ''
Community: 'کۆمەڵگە'
Counts:
Video Count: '١ ڤیدیۆ | {count} ڤیدیۆ'
Channel Count: '١ کەناڵ | {count} کەناڵ'
Subscriber Count: '١ بەشداربوو | {count} بەشداربوو'
View Count: 'بینینەک | {count} بینین'
Watching Count: ''
Watching Count: '١ تەمەشاکردن | {count} تەمەشاکردن'
# Search Bar
Search / Go to URL: ''
Search / Go to URL: 'گەڕان/ بڕۆ بۆ ئرڵ'
Search Bar:
Clear Input: ''
# In Filter Button
Search Filters:
Search Filters: ''
Search Filters: 'پاڵفتەکردنی گەڕان'
Sort By:
Sort By: 'ڕیزکردن بە'
Most Relevant: ''
Rating: 'هەڵسەنگاندن'
Upload Date: 'ڕێکەوتی بارکردن'
View Count: ''
View Count: 'ژمارەی بینین'
Time:
Time: 'کات'
Any Time: 'هەر کاتێک'
@ -87,10 +88,10 @@ Search Filters:
Medium (4 - 20 minutes): 'ناوەند (٤ - ٢٠ خولەک)'
Long (> 20 minutes): 'درێژ (> ٢٠ خولەک)'
# On Search Page
Search Results: ''
Search Results: 'ئەنجامەکانی گەڕان'
Fetching results. Please wait: ''
Fetch more results: ''
There are no more results for this search: ''
There are no more results for this search: 'ئەنجامەکی تر نییە بۆ ئەم گەڕانە'
# Sidebar
Subscriptions:
# On Subscriptions Page
@ -121,26 +122,27 @@ Channels:
Unsubscribe Prompt: ''
Trending:
Trending: ''
Default: ''
Default: 'بنەڕەت'
Music: 'مۆسیقا'
Gaming: 'یاری'
Movies: 'فیلم'
Trending Tabs: ''
Most Popular: 'باوترین'
Playlists: ''
Playlists: 'پێڕستی لێدانەکان'
User Playlists:
Your Playlists: ''
Your Playlists: 'پێڕستی لێدانەکانت'
Playlist Message: ''
Your saved videos are empty. Click on the save button on the corner of a video to have it listed here: ''
Empty Search Message: ''
Search bar placeholder: ''
Search bar placeholder: 'لەناو پێڕستی لێدان بگەڕێ'
History:
# On History Page
History: 'مێژوو'
Watch History: 'مێژووی تەمەشاکردن'
Your history list is currently empty.: ''
Empty Search Message: ''
Search bar placeholder: ""
Your history list is currently empty.: 'ئێستا لیستەی مێژووت بەتاڵە.'
Empty Search Message: 'هیچ ڤیدیۆیەک لە مێژووت نەدۆزرایەوە کە بەرانبەری گەڕانەکەت
بێت'
Search bar placeholder: "لەناو مێژوو بگەڕێ"
Settings:
# On Settings Page
Settings: 'ڕێکخستنەکان'
@ -150,22 +152,22 @@ Settings:
Check for Updates: ''
Check for Latest Blog Posts: ''
Fallback to Non-Preferred Backend on Failure: ''
Enable Search Suggestions: ''
Enable Search Suggestions: 'کاراکردنی پێشنیارەکانی گەڕان'
Default Landing Page: ''
Locale Preference: ''
System Default: ''
System Default: 'بنەڕەتی سیستەم'
Preferred API Backend:
Preferred API Backend: ''
Local API: ''
Invidious API: ''
Video View Type:
Video View Type: ''
Grid: ''
List: 'پێڕست'
Grid: 'خانەخانە'
List: 'لیستە'
Thumbnail Preference:
Thumbnail Preference: ''
Default: ''
Beginning: ''
Default: 'بنەڕەت'
Beginning: 'سەرەتا'
Middle: 'ناوەڕاست'
End: 'کۆتایی'
Hidden: 'شاراوە'
@ -193,10 +195,10 @@ Settings:
Hide Side Bar Labels: ''
Hide FreeTube Header Logo: ''
Base Theme:
Base Theme: ''
Base Theme: 'ڕووکاری بنچینە'
Black: 'ڕەش'
Dark: 'تاریک'
System Default: ''
System Default: 'بنەڕەتی سیستەم'
Light: 'ڕووناک'
Dracula: ''
Catppuccin Mocha: ''
@ -208,11 +210,11 @@ Settings:
Pink: 'پەمبە'
Purple: 'وەنەوشەیی'
Deep Purple: 'وەنەوشەیی تۆخ'
Indigo: ''
Indigo: 'نیلی'
Blue: 'شین'
Light Blue: 'شینی ئاڵ'
Cyan: ''
Teal: ''
Cyan: 'شینی تۆخ'
Teal: 'شەدری'
Green: 'کەسک'
Light Green: 'کەسکی ئاڵ'
Lime: ''
@ -247,11 +249,11 @@ Settings:
Player Settings: 'ڕێکخستنەکانی لێدەر'
Force Local Backend for Legacy Formats: ''
Play Next Video: 'لێدانی ڤیدیۆی دواتر'
Turn on Subtitles by Default: ''
Turn on Subtitles by Default: 'هەڵکردنی بنەڕەتی ژێرنووس'
Autoplay Videos: 'خۆلێدانی ڤیدیۆ'
Proxy Videos Through Invidious: ''
Autoplay Playlists: ''
Enable Theatre Mode by Default: ''
Autoplay Playlists: 'خۆلێدانی پێڕستی لێدان'
Enable Theatre Mode by Default: 'کاراکردنی بنەڕەتیی شێوازی شانۆیی'
Scroll Volume Over Video Player: ''
Scroll Playback Rate Over Video Player: ''
Skip by Scrolling Over Video Player: ''
@ -269,23 +271,23 @@ Settings:
Legacy Formats: ''
Audio Formats: ''
Default Quality:
Default Quality: ''
Default Quality: 'جۆرایەتی بنەڕەت'
Auto: 'خۆکار'
144p: ''
240p: ''
360p: ''
480p: ''
720p: ''
1080p: ''
1440p: ''
4k: ''
8k: ''
144p: '١٤٤p'
240p: '٢٤٠p'
360p: '٣٦٠p'
480p: '٤٨٠p'
720p: '٧٢٠p'
1080p: '١٠٨٠p'
1440p: '١٤٤٠p'
4k: '٤k'
8k: '٨k'
Allow DASH AV1 formats: ''
Screenshot:
Enable: ''
Format Label: ''
Quality Label: ''
Ask Path: ''
Ask Path: 'بۆ بوخچەی پاشەکەوت بپرسە'
Folder Label: ''
Folder Button: 'دیاریکردنی بوخچە'
File Name Label: ''
@ -313,9 +315,10 @@ Settings:
Clear Search Cache: ''
Are you sure you want to clear out your search cache?: ''
Search cache has been cleared: ''
Remove Watch History: ''
Are you sure you want to remove your entire watch history?: ''
Watch history has been cleared: ''
Remove Watch History: 'سڕینەوەی مێژووی تەمەشاکردن'
Are you sure you want to remove your entire watch history?: 'دڵنیایت دەتەوێت تەواوی
مێژووی تەمەشاکردنت بسڕیەوە؟'
Watch history has been cleared: 'مێژووی تەمەشاکردن لابرا'
Remove All Subscriptions / Profiles: ''
Are you sure you want to remove all subscriptions and profiles? This cannot be undone.: ''
Subscription Settings:
@ -329,17 +332,17 @@ Settings:
Sections:
Side Bar: ''
Subscriptions Page: ''
Channel Page: ''
Watch Page: ''
General: ''
Hide Video Views: ''
Channel Page: 'پەڕەی کەناڵ'
Watch Page: 'پەڕەی تەمەشاکردن'
General: 'گشتی'
Hide Video Views: 'شاردنەوەی ژمارەی بینراوەکانی ڤیدیۆ'
Hide Video Likes And Dislikes: ''
Hide Channel Subscribers: ''
Hide Comment Likes: ''
Hide Recommended Videos: ''
Hide Recommended Videos: 'شاردنەوەی ڤیدیۆ پێشنیازکراوەکان'
Hide Trending Videos: ''
Hide Popular Videos: ''
Hide Playlists: ''
Hide Playlists: 'شاردنەوەی پێڕستی لێدان'
Hide Live Chat: ''
Hide Active Subscriptions: ''
Hide Video Description: ''
@ -367,29 +370,30 @@ Settings:
Hide Subscriptions Live: ''
Hide Subscriptions Community: ''
Data Settings:
Data Settings: ''
Select Import Type: ''
Select Export Type: ''
Data Settings: 'ڕێکخستنەکانی دراوە'
Select Import Type: 'دیاریکردنی جۆری هاوردە'
Select Export Type: 'دیاریکردنی جۆری هەناردە'
Import Subscriptions: ''
Subscription File: ''
History File: ''
Playlist File: ''
History File: 'پەڕگەی مێژوو'
Playlist File: 'پەڕگەی پێڕستی لێدان'
Check for Legacy Subscriptions: ''
Export Subscriptions: ''
Export FreeTube: ''
Export YouTube: ''
Export NewPipe: ''
Import History: ''
Export History: ''
Import Playlists: ''
Export Playlists: ''
Export FreeTube: 'هەناردەکردنی فریتیوب'
Export YouTube: 'هەناردەکردنی یوتیوب'
Export NewPipe: 'هەناردەکردنی نیوپایپ'
Import History: 'هاوردەکردنی مێژوو'
Export History: 'هەناردەکردنی مێژوو'
Import Playlists: 'هاوردەکردنی پێڕستی لێدان'
Export Playlists: 'هەناردەکردنی پێڕستی لێدان'
Profile object has insufficient data, skipping item: ''
All subscriptions and profiles have been successfully imported: ''
All subscriptions have been successfully imported: ''
One or more subscriptions were unable to be imported: ''
Invalid subscriptions file: ''
This might take a while, please wait: ''
Invalid history file: ''
This might take a while, please wait: 'تکایە چاوەڕوانبە لەوانەیە هەندێک کاتی پێ
بچێت'
Invalid history file: 'پەڕگەی نادرووستی مێژوو'
Subscriptions have been successfully exported: ''
History object has insufficient data, skipping item: ''
All watched history has been successfully imported: ''
@ -403,18 +407,19 @@ Settings:
How do I import my subscriptions?: ''
Manage Subscriptions: ''
Proxy Settings:
Proxy Settings: ''
Enable Tor / Proxy: ''
Proxy Protocol: ''
Proxy Host: ''
Proxy Port Number: ''
Clicking on Test Proxy will send a request to: ''
Test Proxy: ''
Your Info: ''
Ip: ''
Country: ''
Region: ''
City: ''
Proxy Settings: 'ڕێکخستنەکانی پێشکار'
Enable Tor / Proxy: 'کاراکردنی تۆر / پێشکار'
Proxy Protocol: 'پرۆتۆکۆلی پێشکار'
Proxy Host: 'خانەخوێی پێشکار'
Proxy Port Number: 'ژمارەی دەرچەی پێشکار'
Clicking on Test Proxy will send a request to: 'کرتە کردن لە تاقیکردنەوەی پێشکار،
داخوازییەک دەنێرێت بۆ'
Test Proxy: 'تاقیکردنەوەی پێشکار'
Your Info: 'زانیارییەکانت'
Ip: 'ئای پی'
Country: 'وڵات'
Region: 'هەرێم'
City: 'شار'
Error getting network information. Is your proxy configured properly?: ''
SponsorBlock Settings:
SponsorBlock Settings: ''
@ -427,15 +432,15 @@ Settings:
Auto Skip: ''
Show In Seek Bar: ''
Prompt To Skip: ''
Do Nothing: ''
Do Nothing: 'هیچ مەکە'
Category Color: ''
Parental Control Settings:
Parental Control Settings: ''
Hide Unsubscribe Button: ''
Show Family Friendly Only: ''
Hide Search Bar: ''
Hide Search Bar: 'شاردنەوەی میلی گەڕان'
Download Settings:
Download Settings: ''
Download Settings: 'ڕێکخستنەکانی داگرتن'
Ask Download Path: ''
Choose Path: ''
Download Behavior: ''
@ -446,50 +451,50 @@ Settings:
Warning: ''
Replace HTTP Cache: ''
Password Dialog:
Password: ''
Enter Password To Unlock: ''
Password Incorrect: ''
Unlock: ''
Password: 'تێپەڕەوشە'
Enter Password To Unlock: 'تێپەڕەوشە بنووسە بۆ کردنەوەی کڵۆمی ڕێکخستنەکان'
Password Incorrect: 'تێپەڕەوشەی نادرووست'
Unlock: 'کردنەوەی کڵۆم'
Password Settings:
Password Settings: ''
Password Settings: 'ڕێکخستنەکانی تێپەڕەوشە'
Set Password To Prevent Access: ''
Set Password: ''
Remove Password: ''
Set Password: 'دانانی تێپەڕەوشە'
Remove Password: 'لادانی تێپەڕەوشە'
About:
#On About page
About: ''
About: 'دەربارە'
Beta: ''
Source code: ''
Licensed under the AGPLv3: ''
View License: ''
Source code: 'کۆدی سەرچاوە'
Licensed under the AGPLv3: 'مۆڵەتی وەشانی سێیەمی AGPL هەیە'
View License: 'بینینی مۆڵەت'
Downloads / Changelog: ''
GitHub releases: ''
Help: ''
FreeTube Wiki: ''
FAQ: ''
Help: 'یارمەتی'
FreeTube Wiki: 'ویکی فریتیوب'
FAQ: 'پرسیارە دووبارەکان'
Discussions: ''
Report a problem: ''
Report a problem: 'سکاڵا لە کێشەیەک بکە'
GitHub issues: ''
Please check for duplicates before posting: ''
Website: ''
Blog: ''
Email: ''
Mastodon: ''
Website: 'وێبگە'
Blog: 'بلۆگ'
Email: 'ئیمێڵ'
Mastodon: 'ماستادۆن'
Chat on Matrix: ''
Please read the: ''
room rules: ''
Translate: ''
Translate: 'وەرگێڕان'
Credits: ''
FreeTube is made possible by: ''
these people and projects: ''
Donate: ''
Donate: 'بەخشین'
Profile:
Profile Settings: ''
Toggle Profile List: ''
Profile Select: ''
Profile Filter: ''
All Channels: ''
All Channels: 'هەموو کەناڵەکان'
Profile Manager: ''
Create New Profile: ''
Edit Profile: ''
@ -512,12 +517,12 @@ Profile:
'{profile} is now the active profile': ''
Subscription List: ''
Other Channels: ''
'{number} selected': ''
Select All: ''
Select None: ''
Delete Selected: ''
'{number} selected': '{number} دیاریکراوە'
Select All: 'دیاریکردنی هەموویان'
Select None: 'دیاری نەکردنی هیچیان'
Delete Selected: 'سڕینەوەی دیاریکراوەکان'
Add Selected To Profile: ''
No channel(s) have been selected: ''
No channel(s) have been selected: 'هیچ کەناڵێک دیاری نەکراوە'
? This is your primary profile. Are you sure you want to delete the selected channels? The
same channels will be deleted in any profile they are found in.
: ''
@ -531,78 +536,82 @@ Channel:
Added channel to your subscriptions: ''
Search Channel: ''
Your search results have returned 0 results: ''
Sort By: ''
This channel does not exist: ''
This channel does not allow searching: ''
Sort By: 'ڕیزکردن بە'
This channel does not exist: 'ئەم کەناڵە بوونی نییە'
This channel does not allow searching: 'ئەم کەناڵە ڕێ بە گەڕان نادات'
This channel is age-restricted and currently cannot be viewed in FreeTube.: ''
Channel Tabs: ''
Videos:
Videos: ''
This channel does not currently have any videos: ''
Videos: 'ڤیدیۆکان'
This channel does not currently have any videos: 'ئەم کەناڵە ئێستا هیچ ڤیدیۆیەکی
نییە'
Sort Types:
Newest: ''
Oldest: ''
Newest: 'نوێترین'
Oldest: 'کۆنترین'
Most Popular: ''
Shorts:
This channel does not currently have any shorts: ''
Live:
Live: ''
Live: 'ڕاستەوخۆ'
This channel does not currently have any live streams: ''
Playlists:
Playlists: ''
This channel does not currently have any playlists: ''
Playlists: 'پێڕستی لێدان'
This channel does not currently have any playlists: 'ئەم کەناڵە ئێستا هیچ پێڕستێکی
لێدانی نییە'
Sort Types:
Last Video Added: ''
Newest: ''
Oldest: ''
Last Video Added: 'دوایین ڤیدیۆ زیادکراوەکان'
Newest: 'نوێترین'
Oldest: 'کۆنترین'
Podcasts:
Podcasts: ''
This channel does not currently have any podcasts: ''
Podcasts: 'پۆدکاستەکان'
This channel does not currently have any podcasts: 'ئەم کەناڵە ئێستا هیچ پۆدکاستێکی
نییە'
Releases:
Releases: ''
This channel does not currently have any releases: ''
About:
About: ''
Channel Description: ''
About: 'دەربارە'
Channel Description: 'پێناسی کەناڵ'
Tags:
Tags: ''
Search for: ''
Details: ''
Details: 'وردەکاری'
Joined: ''
Location: ''
Featured Channels: ''
Community:
This channel currently does not have any posts: ''
votes: ''
votes: '{votes} دەنگ'
Reveal Answers: ''
Hide Answers: ''
Hide Answers: 'شاردنەوەی وەڵامەکان'
Video:
Mark As Watched: ''
Remove From History: ''
Video has been marked as watched: ''
Video has been removed from your history: ''
Save Video: ''
Video has been saved: ''
Video has been removed from your saved list: ''
Open in YouTube: ''
Copy YouTube Link: ''
Mark As Watched: 'وەکو تەمەشاکراو نیشانی بکە'
Remove From History: 'لە مێژوو لای ببە'
Video has been marked as watched: 'ڤیدیۆکە وەکو تەمەشاکراو نیشان کراوە'
Video has been removed from your history: 'ڤیدیۆکە لە مێژووەکەت لابرا'
Save Video: 'پاشەکەوتکردنی ڤیدیۆ'
Video has been saved: 'ڤیدیۆکە پاشەکەوت کرا'
Video has been removed from your saved list: 'ڤیدیۆکە لە لیستەی پاشەکەوت کراوەکان
لابرا'
Open in YouTube: 'کردنەوە لە یوتیوب'
Copy YouTube Link: 'بەستەری یوتیوب لەبەر بگرەوە'
Open YouTube Embedded Player: ''
Copy YouTube Embedded Player Link: ''
Open in Invidious: ''
Copy Invidious Link: ''
Open Channel in YouTube: ''
Copy YouTube Channel Link: ''
Open Channel in YouTube: 'کردنەوەی کەناڵ لە یوتیوب'
Copy YouTube Channel Link: 'لەبەرگرتنەوەی بەستەری کەناڵی یوتیوب'
Open Channel in Invidious: ''
Copy Invidious Channel Link: ''
Views: ''
Views: 'بینراو'
Loop Playlist: ''
Shuffle Playlist: ''
Reverse Playlist: ''
Play Next Video: ''
Play Previous Video: ''
Play Next Video: 'لێدانی ڤیدیۆی دواتر'
Play Previous Video: 'لێدانی ڤیدیۆی پێشوو'
Pause on Current Video: ''
Watched: ''
Autoplay: ''
Watched: 'تەمەشاکراو'
Autoplay: 'خۆلێدان'
Starting soon, please refresh the page to check again: ''
# As in a Live Video
Premieres on: ''
@ -619,14 +628,14 @@ Video:
'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': ''
Show Super Chat Comment: ''
Scroll to Bottom: ''
Download Video: ''
video only: ''
audio only: ''
Download Video: 'داگرتنی ڤیدیۆ'
video only: 'تەنیا ڤیدیۆ'
audio only: 'تەنیا دەنگ'
Audio:
Low: ''
Medium: ''
High: ''
Best: ''
Low: 'نزم'
Medium: 'مامناوەند'
High: 'بەرز'
Best: 'باشترین'
Published:
Jan: ''
Feb: ''
@ -640,24 +649,24 @@ Video:
Oct: ''
Nov: ''
Dec: ''
Second: ''
Seconds: ''
Minute: ''
Minutes: ''
Hour: ''
Hours: ''
Day: ''
Days: ''
Week: ''
Weeks: ''
Month: ''
Months: ''
Year: ''
Years: ''
Second: 'چرکە'
Seconds: 'چرکە'
Minute: 'خولەک'
Minutes: 'خولەک'
Hour: 'کاتژمێر'
Hours: 'کاتژمێر'
Day: 'ڕۆژ'
Days: 'ڕۆژ'
Week: 'هەفتە'
Weeks: 'هەفتە'
Month: 'مانگ'
Months: 'مانگ'
Year: 'ساڵ'
Years: 'ساڵ'
Ago: ''
Upcoming: ''
In less than a minute: ''
Published on: ''
Published on: 'بڵاوکرایەوە لە'
Streamed on: ''
Started streaming on: ''
translated from English: ''
@ -674,8 +683,8 @@ Video:
filler: ''
External Player:
OpenInTemplate: ''
video: ''
playlist: ''
video: 'ڤیدیۆ'
playlist: 'پێڕستی لێدان'
OpeningTemplate: ''
UnsupportedActionTemplate: ''
Unsupported Actions:
@ -698,20 +707,22 @@ Video:
Dropped / Total Frames: ''
Mimetype: ''
#& Videos
Unhide Channel: پیشاندانی کەناڵ
Hide Channel: شاردنەوەی کەناڵ
Videos:
#& Sort By
Sort By:
Newest: ''
Oldest: ''
Newest: 'نوێترین'
Oldest: 'کۆنترین'
#& Most Popular
#& Playlists
Playlist:
#& About
Playlist: ''
Playlist: 'پێڕستی لێدان'
View Full Playlist: ''
Videos: ''
View: ''
Views: ''
Videos: 'ڤیدیۆکان'
View: 'بینراو'
Views: 'بینراو'
Last Updated On: ''
# On Video Watch Page
@ -726,12 +737,12 @@ Change Format:
Dash formats are not available for this video: ''
Audio formats are not available for this video: ''
Share:
Share Video: ''
Share Channel: ''
Share Playlist: ''
Share Video: 'هاوبەشکردنی ڤیدیۆ'
Share Channel: 'هاوبەشکردنی کەناڵ'
Share Playlist: 'هاوبەشکردنی پێڕستی لێدان'
Include Timestamp: ''
Copy Link: ''
Open Link: ''
Copy Link: 'لەبەرگرتنەوەی بەستەر'
Open Link: 'کردنەوەی بەستەر'
Copy Embed: ''
Open Embed: ''
# On Click
@ -750,7 +761,7 @@ Chapters:
'Chapters list visible, current chapter: {chapterName}': ''
'Chapters list hidden, current chapter: {chapterName}': ''
Mini Player: ''
Mini Player: 'لێدەری گچکە'
Comments:
Comments: ''
Click to View Comments: ''
@ -758,23 +769,23 @@ Comments:
There are no more comments for this video: ''
Show Comments: ''
Hide Comments: ''
Sort by: ''
Sort by: 'ڕیزکردن بە'
Top comments: ''
Newest first: ''
Newest first: 'سەرەتا نوێترینەکان'
View {replyCount} replies: ''
# Context: View 10 Replies, View 1 Reply, View 1 Reply from Owner, View 2 Replies from Owner and others
View: ''
Hide: ''
Replies: ''
Show More Replies: ''
Reply: ''
From {channelName}: ''
And others: ''
View: 'بینین'
Hide: 'شاردنەوە'
Replies: 'وەڵامدانەوەکان'
Show More Replies: 'پیشاندانی وەڵامدانەوەی زۆرتر'
Reply: 'وەڵامدانەوە'
From {channelName}: 'لە {channelName}ەوە'
And others: 'هی تر'
There are no comments available for this video: ''
Load More Comments: ''
No more comments available: ''
Pinned by: ''
Member: ''
Member: 'ئەندام'
Subscribed: ''
Hearted: ''
Up Next: ''
@ -800,7 +811,7 @@ Tooltips:
Custom External Player Executable: ''
Ignore Warnings: ''
Custom External Player Arguments: ''
DefaultCustomArgumentsTemplate: ""
DefaultCustomArgumentsTemplate: "(بنەڕەت: '{defaultCustomArguments}')"
Distraction Free Settings:
Hide Channels: ''
Hide Subscriptions Live: ''
@ -828,8 +839,8 @@ Loop is now enabled: ''
Shuffle is now disabled: ''
Shuffle is now enabled: ''
The playlist has been reversed: ''
Playing Next Video: ''
Playing Previous Video: ''
Playing Next Video: 'لێدانی ڤیدیۆی دواتر'
Playing Previous Video: 'لێدانی ڤیدیۆی پێشوو'
Playlist will not pause when current video is finished: ''
Playlist will pause when current video is finished: ''
Playing Next Video Interval: ''
@ -841,8 +852,8 @@ Default Invidious instance has been cleared: ''
Age Restricted:
This {videoOrPlaylist} is age restricted: ''
Type:
Channel: ''
Video: ''
Channel: 'کەناڵ'
Video: 'ڤیدیۆ'
External link opening has been disabled in the general settings: ''
Downloading has completed: ''
Starting download: ''
@ -853,6 +864,7 @@ Screenshot Error: ''
Hashtag:
Hashtag: ''
This hashtag does not currently have any videos: ''
Yes: ''
No: ''
Ok: ''
Yes: 'بەڵێ'
No: 'نەخێر'
Ok: 'باشە'
Go to page: بڕۆ بۆ {page}

View File

@ -806,6 +806,8 @@ Video:
'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': Živý
chat není pro tento stream k dispozici. Je možné, že byl vypnut nahrávajícím.
Pause on Current Video: Pozastavit na současném videu
Unhide Channel: Zobrazit kanál
Hide Channel: Skrýt kanál
Videos:
#& Sort By
Sort By:
@ -1036,3 +1038,6 @@ Playlist will pause when current video is finished: Po přehrání aktuálního
playlist pozastaven
Playlist will not pause when current video is finished: Po přehrání aktuálního videa
nebude playlist pozastaven
Channel Hidden: Kanál {channel} přidán do filtru kanálů
Go to page: Přejít na {page}
Channel Unhidden: Kanál {channel} odebrán z filtrů kanálů

View File

@ -470,6 +470,15 @@ Settings:
Export History: Export History
Import Playlists: Import Playlists
Export Playlists: Export Playlists
Export Playlists For Older FreeTube Versions:
Label: Export Playlists For Older FreeTube Versions
# |- = Keep newlines, No newline at end
Tooltip: |-
This option exports videos from all playlists into one playlist named 'Favorites'.
How to export & import videos in playlists for an older version of FreeTube:
1. Export your playlists with this option enabled.
2. Delete all of your existing playlists using the Remove All Playlists option under Privacy Settings.
3. Launch the older version of FreeTube and import the exported playlists."
Profile object has insufficient data, skipping item: Profile object has insufficient
data, skipping item
All subscriptions and profiles have been successfully imported: All subscriptions
@ -624,6 +633,8 @@ Profile:
Are you sure you want to delete the selected channels? This will not delete the channel from any other profile.: Are
you sure you want to delete the selected channels? This will not delete the channel
from any other profile.
Close Profile Dropdown: Close Profile Dropdown
Open Profile Dropdown: Open Profile Dropdown
#On Channel Page
Channel:
Subscribe: Subscribe

View File

@ -620,6 +620,8 @@ Profile:
Profile Filter: Filtro de perfil
Profile Settings: Ajustes del perfil
Toggle Profile List: Alternar la lista de los perfiles
Open Profile Dropdown: Abrir el desplegable del Perfil
Close Profile Dropdown: Cerrar el desplegable del Perfil
Channel:
Subscribe: 'Suscribirse'
Unsubscribe: 'Anular suscripción'
@ -827,6 +829,8 @@ Video:
chat en vivo no está disponible para esta transmisión. Tal vez estaba deshabilitado
antes de la retransmisión.
Pause on Current Video: Pausa en el vídeo actual
Unhide Channel: Mostrar el canal
Hide Channel: Ocultar el canal
Videos:
#& Sort By
Sort By:
@ -1073,3 +1077,5 @@ Playlist will pause when current video is finished: La lista de reproducción se
Playlist will not pause when current video is finished: La lista de reproducción no
se detendrá cuando termine el vídeo actual
Go to page: Ir a la {page}
Channel Hidden: '{channel} añadido al filtro de canales'
Channel Unhidden: '{channel} eliminado del filtro de canales'

View File

@ -764,6 +764,8 @@ Video:
'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': Otsevestlus
pole selle videovoo puhul saadaval. Võib-olla on üleslaadija vestluse keelanud.
Pause on Current Video: Peata hetkel esitatav video
Unhide Channel: Näita kanalit
Hide Channel: Peida kanal
Videos:
#& Sort By
Sort By:
@ -991,3 +993,6 @@ Playlist will pause when current video is finished: Hetkel mängiva video lõppe
esitusloendi esitamine peatub
Playlist will not pause when current video is finished: Hetkel mängiva video lõppemisel
esitusloendi esitamine jätkub
Channel Hidden: '{channel} on lisatud kanalite filtrisse'
Go to page: 'Ava leht: {page}'
Channel Unhidden: '{channel} on eemaldatud kanalite filtrist'

View File

@ -794,6 +794,8 @@ Video:
chat dal vivo non è disponibile per questo video. Potrebbe essere stata disattivata
dall'autore del caricamento.
Pause on Current Video: Pausa sul video attuale
Unhide Channel: Mostra canale
Hide Channel: Nascondi canale
Videos:
#& Sort By
Sort By:
@ -942,6 +944,8 @@ Profile:
Profile Filter: Filtro del profilo
Profile Settings: Impostazioni dei profili
Toggle Profile List: Attiva/disattiva elenco profili
Open Profile Dropdown: Apri il menu a discesa del profilo
Close Profile Dropdown: Chiudi il menu a discesa del profilo
This video is unavailable because of missing formats. This can happen due to country unavailability.: Questo
video non è disponibile a causa di alcuni formati mancanti. Questo può succedere
in caso di mancata disponibilità della nazione.
@ -1082,3 +1086,6 @@ Playlist will pause when current video is finished: La playlist verrà messa in
al termine del video attuale
Playlist will not pause when current video is finished: La playlist non verrà messa
in pausa al termine del video attuale
Channel Hidden: '{channel} aggiunto al filtro canali'
Go to page: Vai a {page}
Channel Unhidden: '{channel} rimosso dal filtro canali'

View File

@ -1,5 +1,5 @@
# Put the name of your locale in the same language
Locale Name: 'kur-ckb'
Locale Name: 'کوردی ناوەڕاست'
FreeTube: 'فریتیوب'
# Currently on Subscriptions, Playlists, and History
'This part of the app is not ready yet. Come back later when progress has been made.': >-
@ -7,20 +7,20 @@ FreeTube: 'فریتیوب'
رویداوە.
# Webkit Menu Bar
File: 'فایل'
Quit: 'چونەدەرەوە'
Edit: 'دەستکاریکردن'
Undo: 'گەڕانەوە'
File: 'پەڕگە'
Quit: 'دەرچوون'
Edit: 'دەستکاری'
Undo: 'پووچکردنەوە'
Redo: 'هێنانەوە'
Cut: 'بڕین'
Copy: 'کۆپی'
Paste: 'پەیست'
Copy: 'لەبەرگرتنەوە'
Paste: 'لکاندن'
Delete: 'سڕینەوە'
Select all: 'دیاریکردنی هەمووی'
Reload: 'دوبارە دابەزاندن'
Force Reload: 'دوباری دابەزاندی بەهێز'
Toggle Developer Tools: 'ئەدەواتەکانی دیڤیڵۆپەر بەردەست بخە'
Actual size: 'گەورەیی راستی'
Reload: 'بارکردنەوە'
Force Reload: 'بارکردنەوەی بەزۆر'
Toggle Developer Tools: 'زامنی ئامرازەکانی گەشەپێدەر'
Actual size: 'قەبارەی ڕاستەقینە'
Zoom in: 'زووم کردنە ناوەوە'
Zoom out: 'زووم کردنە دەرەوە'
Toggle fullscreen: 'شاشەکەت پرکەرەوە'
@ -30,9 +30,9 @@ Close: 'داخستن'
Back: 'گەڕانەوە'
Forward: 'چونەپێشەوە'
Version {versionNumber} is now available! Click for more details: 'ڤێرژنی {versionNumber}
ئێستا بەردەستە! کلیک بکە بۆ زانیاری زیاتر'
Download From Site: 'دایبەزێنە لە سایتەکەوە'
Version {versionNumber} is now available! Click for more details: 'ئێستا وەشانی {versionNumber}
بەردەستە..بۆ زانیاری زۆرتر کرتە بکە'
Download From Site: 'لە وێبگەوە دایگرە'
A new blog is now available, {blogTitle}. Click to view more: 'بڵۆگێکی نوێ بەردەستە،
{blogTitle}. کلیک بکە بۆ بینینی زیاتر'
@ -190,3 +190,8 @@ Profile:
Removed {profile} from your profiles: 'سڕاوەتەوە لە پرۆفایلەکانت {profile}'
Channel:
Playlists: {}
New Window: پەنجەرەی نوێ
Go to page: بڕۆ بۆ {page}
Preferences: هەڵبژاردەکان
Are you sure you want to open this link?: دڵنیایت دەتەوێت ئەم بەستەرە بکەیتەوە؟
Open New Window: کردنەوەی پەنجەرەیەکی نوێ

View File

@ -798,6 +798,8 @@ Video:
na żywo jest nie dostępny dla tej transmisji. Być może został on wyłączony przez
osobę wstawiającą.
Pause on Current Video: Zatrzymaj po tym filmie
Unhide Channel: Pokaż kanał
Hide Channel: Ukryj kanał
Videos:
#& Sort By
Sort By:
@ -939,6 +941,8 @@ Profile:
Profile Filter: Filtr profilu
Profile Settings: Ustawienia profilu
Toggle Profile List: Włącz/wyłącz listę profili
Open Profile Dropdown: Otwórz rozwijane menu profilu
Close Profile Dropdown: Zamknij rozwijane menu profilu
The playlist has been reversed: Playlista została odwrócona
A new blog is now available, {blogTitle}. Click to view more: 'Nowy wpis na blogu
jest dostępny, {blogTitle}. Kliknij, aby zobaczyć więcej'
@ -1086,3 +1090,6 @@ Playlist will pause when current video is finished: Playlista zatrzyma się, gdy
film się zakończy
Playlist will not pause when current video is finished: Playlista nie zatrzyma się,
gdy obecny film się zakończy
Channel Hidden: '{channel} dodany do filtra kanałów'
Go to page: Idź do {page}
Channel Unhidden: '{channel} usunięty z filtra kanału'

View File

@ -761,6 +761,8 @@ Video:
YouTube-ом.
'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': Ћаскање
уживо није доступно за овај стрим. Можда га је онемогућио аутор.
Unhide Channel: Прикажи канал
Hide Channel: Сакриј канал
Tooltips:
Subscription Settings:
Fetch Feeds from RSS: 'Када је омогућено, FreeTube ће користити RSS уместо свог
@ -982,3 +984,6 @@ Screenshot Error: Снимак екрана није успео. {error}
Downloading has completed: „{videoTitle}“ је завршио преузимање
Loop is now enabled: Понављање је сада омогућено
Downloading failed: Дошло је до проблема при преузимању „{videoTitle}“
Channel Hidden: '{channel} је додат на филтер канала'
Go to page: Иди на {page}
Channel Unhidden: '{channel} је уклоњен из филтера канала'

View File

@ -713,6 +713,8 @@ Video:
Upcoming: 即将到来
'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': 实时聊天对此音视频流不可用。上传者可能禁用了它。
Pause on Current Video: 当前视频播完后不自动播放列表中下一视频
Unhide Channel: 显示频道
Hide Channel: 隐藏频道
Videos:
#& Sort By
Sort By:
@ -936,3 +938,5 @@ Hashtag:
Playlist will pause when current video is finished: 当前视频播完后播放列表会暂停
Playlist will not pause when current video is finished: 当前视频播完后播放列表不会暂停
Go to page: 转到页{page}
Channel Hidden: '{channel} 频道已添加到频道过滤器'
Channel Unhidden: 从频道过滤器删除了{channel} 频道

View File

@ -131,7 +131,7 @@ Settings:
Preferred API Backend:
Preferred API Backend: '偏好API伺服器'
Local API: '本機 API'
Invidious API: 'Invidious API(應用程式介面)'
Invidious API: 'Invidious API'
Video View Type:
Video View Type: '影片觀看類別'
Grid: '網格'
@ -141,7 +141,7 @@ Settings:
Default: '預設'
Beginning: '片頭'
Middle: '中間'
End: '尾'
End: '尾'
Hidden: 隱藏
Blur: 模糊
'Invidious Instance (Default is https://invidious.snopyta.org)': 'Invidious實例(預設為
@ -410,7 +410,7 @@ Settings:
Hide Channels Disabled Message: 某些頻道被使用 ID 封鎖且無法處理。當這些 ID 更新時,功能將會被封鎖
Hide Channels Already Exists: 頻道 ID 已存在
Hide Channels API Error: 使用提供的 ID 擷取使用者時發生錯誤。請再次檢查 ID 是否正確。
The app needs to restart for changes to take effect. Restart and apply change?: 此變更需要重啟讓修改生效。重啟並且套用變更?
The app needs to restart for changes to take effect. Restart and apply change?: 必須重新啟動應用程式以生效。重新啟動並套用變更嗎?
Proxy Settings:
Error getting network information. Is your proxy configured properly?: 取得網路資訊時發生錯誤。您的代理伺服器設定正確嗎?
City: 城市
@ -590,12 +590,12 @@ Channel:
Releases: 發布
This channel does not currently have any releases: 此頻道目前沒有任何發布
Video:
Open in YouTube: '在YouTube中開啟'
Copy YouTube Link: '複製YouTube連結'
Open YouTube Embedded Player: '開啟YouTube內嵌播放器'
Copy YouTube Embedded Player Link: '複製YouTube內嵌播放器連結'
Open in Invidious: '在Invidious中開啟'
Copy Invidious Link: '複製Invidious連結'
Open in YouTube: '在 YouTube 中開啟'
Copy YouTube Link: '複製 YouTube 連結'
Open YouTube Embedded Player: '開啟 YouTube 內嵌播放器'
Copy YouTube Embedded Player Link: '複製 YouTube 內嵌播放器連結'
Open in Invidious: '在 Invidious 中開啟'
Copy Invidious Link: '複製 Invidious 連結'
Views: '觀看'
Watched: '已觀看'
# As in a Live Video
@ -661,10 +661,10 @@ Video:
audio only: 僅音訊
video only: 僅影片
Download Video: 下載影片
Copy Invidious Channel Link: 複製Invidious頻道連結
Open Channel in Invidious: Invidious開啟頻道
Copy YouTube Channel Link: 複製YouTube頻道連結
Open Channel in YouTube: YouTube開啟頻道
Copy Invidious Channel Link: 複製 Invidious 頻道連結
Open Channel in Invidious: Invidious 開啟頻道
Copy YouTube Channel Link: 複製 YouTube 頻道連結
Open Channel in YouTube: YouTube 開啟頻道
Started streaming on: '開始直播時間'
Streamed on: 直播於
Video has been removed from your saved list: 影片已從您的播放清單移除
@ -722,6 +722,8 @@ Video:
Upcoming: 即將到來
'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': 即時聊天在此串流不可用。其可能被上傳者停用了。
Pause on Current Video: 暫停目前影片
Unhide Channel: 顯示頻道
Hide Channel: 隱藏頻道
Videos:
#& Sort By
Sort By:
@ -944,3 +946,6 @@ Hashtag:
This hashtag does not currently have any videos: 此標籤目前沒有任何影片
Playlist will pause when current video is finished: 當目前影片結束時,播放清單將會暫停
Playlist will not pause when current video is finished: 當目前影片結束時,播放清單將不會暫停
Channel Hidden: '{channel} 已新增至頻道過濾條件'
Go to page: 到 {page}
Channel Unhidden: '{channel} 已從頻道過濾條件移除'